packages feed

dhscanner-bitcode 1.0.7 → 1.0.8

raw patch · 3 files changed

+131/−215 lines, 3 filesdep ~dhscanner-astPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: dhscanner-ast

API changes (from Hackage documentation)

- Bitcode: Arg :: ArgContent -> Variable
- Bitcode: ArgContent :: Fqn -> Word -> Location -> ArgContent
- Bitcode: BoolContent :: TmpVariable -> ConstBool -> BoolContent
- Bitcode: IntContent :: TmpVariable -> ConstInt -> IntContent
- Bitcode: LoadImmBool :: BoolContent -> InstructionContent
- Bitcode: LoadImmInt :: IntContent -> InstructionContent
- Bitcode: LoadImmNull :: NullContent -> InstructionContent
- Bitcode: LoadImmStr :: StrContent -> InstructionContent
- Bitcode: NullContent :: TmpVariable -> ConstNull -> NullContent
- Bitcode: SrcVariables :: Set SrcVariable -> SrcVariables
- Bitcode: StrContent :: TmpVariable -> ConstStr -> StrContent
- Bitcode: TmpVariables :: Set TmpVariable -> TmpVariables
- Bitcode: Variables :: Set Variable -> Variables
- Bitcode: [actualSrcVariables] :: SrcVariables -> Set SrcVariable
- Bitcode: [actualTmpVariables] :: TmpVariables -> Set TmpVariable
- Bitcode: [actualVariables] :: Variables -> Set Variable
- Bitcode: [argVariableFqn] :: ArgContent -> Fqn
- Bitcode: [argVariableMyAwesomeCallContext] :: ArgContent -> Location
- Bitcode: [argVariableSerialIdx] :: ArgContent -> Word
- Bitcode: [assumeVariable] :: AssumeContent -> Variable
- Bitcode: [assumedValue] :: AssumeContent -> Bool
- Bitcode: [loadImmBoolOutput] :: BoolContent -> TmpVariable
- Bitcode: [loadImmBoolValue] :: BoolContent -> ConstBool
- Bitcode: [loadImmIntOutput] :: IntContent -> TmpVariable
- Bitcode: [loadImmIntValue] :: IntContent -> ConstInt
- Bitcode: [loadImmNullOutput] :: NullContent -> TmpVariable
- Bitcode: [loadImmNullValue] :: NullContent -> ConstNull
- Bitcode: [loadImmStrOutput] :: StrContent -> TmpVariable
- Bitcode: [loadImmStrValue] :: StrContent -> ConstStr
- Bitcode: createEmptyCollectionOfGlobalVariables :: SrcVariables
- Bitcode: data ArgContent
- Bitcode: data BoolContent
- Bitcode: data IntContent
- Bitcode: data NullContent
- Bitcode: data SrcVariables
- Bitcode: data StrContent
- Bitcode: data TmpVariables
- Bitcode: data Variables
- Bitcode: inputs :: InstructionContent -> Set Variable
- Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.ArgContent
- Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.BoolContent
- Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.IntContent
- Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.NullContent
- Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.StrContent
- Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.ArgContent
- Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.BoolContent
- Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.IntContent
- Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.NullContent
- Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.StrContent
- Bitcode: instance GHC.Classes.Eq Bitcode.ArgContent
- Bitcode: instance GHC.Classes.Eq Bitcode.BoolContent
- Bitcode: instance GHC.Classes.Eq Bitcode.IntContent
- Bitcode: instance GHC.Classes.Eq Bitcode.NullContent
- Bitcode: instance GHC.Classes.Eq Bitcode.SrcVariables
- Bitcode: instance GHC.Classes.Eq Bitcode.StrContent
- Bitcode: instance GHC.Classes.Eq Bitcode.TmpVariables
- Bitcode: instance GHC.Classes.Eq Bitcode.Variables
- Bitcode: instance GHC.Classes.Ord Bitcode.ArgContent
- Bitcode: instance GHC.Classes.Ord Bitcode.BoolContent
- Bitcode: instance GHC.Classes.Ord Bitcode.IntContent
- Bitcode: instance GHC.Classes.Ord Bitcode.NullContent
- Bitcode: instance GHC.Classes.Ord Bitcode.SrcVariables
- Bitcode: instance GHC.Classes.Ord Bitcode.StrContent
- Bitcode: instance GHC.Classes.Ord Bitcode.TmpVariables
- Bitcode: instance GHC.Classes.Ord Bitcode.Variables
- Bitcode: instance GHC.Generics.Generic Bitcode.ArgContent
- Bitcode: instance GHC.Generics.Generic Bitcode.BoolContent
- Bitcode: instance GHC.Generics.Generic Bitcode.IntContent
- Bitcode: instance GHC.Generics.Generic Bitcode.NullContent
- Bitcode: instance GHC.Generics.Generic Bitcode.StrContent
- Bitcode: instance GHC.Show.Show Bitcode.ArgContent
- Bitcode: instance GHC.Show.Show Bitcode.BoolContent
- Bitcode: instance GHC.Show.Show Bitcode.IntContent
- Bitcode: instance GHC.Show.Show Bitcode.NullContent
- Bitcode: instance GHC.Show.Show Bitcode.SrcVariables
- Bitcode: instance GHC.Show.Show Bitcode.StrContent
- Bitcode: instance GHC.Show.Show Bitcode.TmpVariables
- Bitcode: instance GHC.Show.Show Bitcode.Variables
- Bitcode: output :: InstructionContent -> Maybe Variable
- Bitcode: variables :: InstructionContent -> Set Variable
- Cfg: Cfg :: Node -> Node -> Edges -> Cfg
- Cfg: empty :: Location -> Cfg
- Cfg: location :: Cfg -> Location
- Cfg: mkEmptyCollectionOfEdges :: Edges
- Cfg: parallel :: Cfg -> Cfg -> Cfg
- Cfg: preds :: Node -> Cfg -> Nodes
+ Bitcode: ConstBoolValue :: ConstBool -> ConstValue
+ Bitcode: ConstIntValue :: ConstInt -> ConstValue
+ Bitcode: ConstNullValue :: ConstNull -> ConstValue
+ Bitcode: ConstStrValue :: ConstStr -> ConstValue
+ Bitcode: ConstValueCtor :: ConstValue -> Value
+ Bitcode: KeywordArgCtor :: KeywordArgVariable -> Value
+ Bitcode: KeywordArgVariable :: String -> Value -> KeywordArgVariable
+ Bitcode: VariableCtor :: Variable -> Value
+ Bitcode: [assumeTruthy] :: AssumeContent -> Bool
+ Bitcode: [assumeValue] :: AssumeContent -> Value
+ Bitcode: [keywordArgName] :: KeywordArgVariable -> String
+ Bitcode: [keywordArgValue] :: KeywordArgVariable -> Value
+ Bitcode: data ConstValue
+ Bitcode: data KeywordArgVariable
+ Bitcode: data Value
+ Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.ConstValue
+ Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.KeywordArgVariable
+ Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.Value
+ Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.ConstValue
+ Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.KeywordArgVariable
+ Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.Value
+ Bitcode: instance GHC.Classes.Eq Bitcode.ConstValue
+ Bitcode: instance GHC.Classes.Eq Bitcode.KeywordArgVariable
+ Bitcode: instance GHC.Classes.Eq Bitcode.Value
+ Bitcode: instance GHC.Classes.Ord Bitcode.ConstValue
+ Bitcode: instance GHC.Classes.Ord Bitcode.KeywordArgVariable
+ Bitcode: instance GHC.Classes.Ord Bitcode.Value
+ Bitcode: instance GHC.Generics.Generic Bitcode.ConstValue
+ Bitcode: instance GHC.Generics.Generic Bitcode.KeywordArgVariable
+ Bitcode: instance GHC.Generics.Generic Bitcode.Value
+ Bitcode: instance GHC.Show.Show Bitcode.ConstValue
+ Bitcode: instance GHC.Show.Show Bitcode.KeywordArgVariable
+ Bitcode: instance GHC.Show.Show Bitcode.Value
+ Bitcode: locationConstValue :: ConstValue -> Location
+ Bitcode: locationValue :: Value -> Location
+ Cfg: Content :: Node -> Node -> Edges -> Content
+ Cfg: Empty :: Cfg
+ Cfg: Normal :: Content -> Cfg
+ Cfg: concatNormalContentFirst :: Content -> Cfg -> Content
+ Cfg: data Content
+ Cfg: emptySetOfEdges :: Edges
+ Cfg: emptySetOfNodes :: Nodes
+ Cfg: instance Data.Aeson.Types.FromJSON.FromJSON Cfg.Content
+ Cfg: instance Data.Aeson.Types.ToJSON.ToJSON Cfg.Content
+ Cfg: instance GHC.Classes.Eq Cfg.Content
+ Cfg: instance GHC.Classes.Ord Cfg.Content
+ Cfg: instance GHC.Generics.Generic Cfg.Content
+ Cfg: instance GHC.Show.Show Cfg.Content
+ Cfg: loopifyEmptyCondNormalBody :: Content -> Value -> Cfg
+ Cfg: loopifyNormalCondEmptyBody :: Content -> Value -> Cfg
+ Cfg: mkNewEntry :: Node -> Node
+ Cfg: mkNewExit :: Node -> Node
+ Cfg: mkNopNode :: Node -> Node
+ Cfg: nodes' :: Edges -> Nodes
+ Cfg: nodes'' :: Set Edge -> Nodes
+ Cfg: parallelNormalCfgs :: Content -> Content -> Cfg
- Bitcode: AssignContent :: Variable -> Variable -> AssignContent
+ Bitcode: AssignContent :: Variable -> Value -> AssignContent
- Bitcode: AssumeContent :: Variable -> Bool -> AssumeContent
+ Bitcode: AssumeContent :: Value -> Bool -> AssumeContent
- Bitcode: BinopContent :: Variable -> Variable -> Variable -> BinopContent
+ Bitcode: BinopContent :: Variable -> Value -> Value -> BinopContent
- Bitcode: CallContent :: Variable -> Variable -> [Variable] -> Location -> CallContent
+ Bitcode: CallContent :: Variable -> Variable -> [Value] -> Location -> CallContent
- Bitcode: FieldWriteContent :: Variable -> FieldName -> Variable -> FieldWriteContent
+ Bitcode: FieldWriteContent :: Variable -> FieldName -> Value -> FieldWriteContent
- Bitcode: ReturnContent :: Maybe Variable -> ReturnContent
+ Bitcode: ReturnContent :: Maybe Value -> ReturnContent
- Bitcode: SubscriptReadContent :: Variable -> Variable -> Variable -> SubscriptReadContent
+ Bitcode: SubscriptReadContent :: Variable -> Variable -> Value -> SubscriptReadContent
- Bitcode: SubscriptWriteContent :: Variable -> Variable -> Variable -> SubscriptWriteContent
+ Bitcode: SubscriptWriteContent :: Variable -> Value -> Value -> SubscriptWriteContent
- Bitcode: UnopContent :: Variable -> Variable -> UnopContent
+ Bitcode: UnopContent :: Variable -> Value -> UnopContent
- Bitcode: [args] :: CallContent -> [Variable]
+ Bitcode: [args] :: CallContent -> [Value]
- Bitcode: [assignInput] :: AssignContent -> Variable
+ Bitcode: [assignInput] :: AssignContent -> Value
- Bitcode: [binopLhs] :: BinopContent -> Variable
+ Bitcode: [binopLhs] :: BinopContent -> Value
- Bitcode: [binopRhs] :: BinopContent -> Variable
+ Bitcode: [binopRhs] :: BinopContent -> Value
- Bitcode: [fieldWriteInput] :: FieldWriteContent -> Variable
+ Bitcode: [fieldWriteInput] :: FieldWriteContent -> Value
- Bitcode: [returnValue] :: ReturnContent -> Maybe Variable
+ Bitcode: [returnValue] :: ReturnContent -> Maybe Value
- Bitcode: [subscriptReadIdx] :: SubscriptReadContent -> Variable
+ Bitcode: [subscriptReadIdx] :: SubscriptReadContent -> Value
- Bitcode: [subscriptWriteIdx] :: SubscriptWriteContent -> Variable
+ Bitcode: [subscriptWriteIdx] :: SubscriptWriteContent -> Value
- Bitcode: [subscriptWriteInput] :: SubscriptWriteContent -> Variable
+ Bitcode: [subscriptWriteInput] :: SubscriptWriteContent -> Value
- Bitcode: [unopLhs] :: UnopContent -> Variable
+ Bitcode: [unopLhs] :: UnopContent -> Value
- Bitcode: mkAssumeInstruction :: Variable -> Bool -> Instruction
+ Bitcode: mkAssumeInstruction :: Value -> Bool -> Instruction
- Cfg: [edges] :: Cfg -> Edges
+ Cfg: [edges] :: Content -> Edges
- Cfg: [entry] :: Cfg -> Node
+ Cfg: [entry] :: Content -> Node
- Cfg: [exit] :: Cfg -> Node
+ Cfg: [exit] :: Content -> Node
- Cfg: loopify :: Cfg -> Cfg -> Variable -> Cfg
+ Cfg: loopify :: Cfg -> Cfg -> Value -> Cfg

Files

dhscanner-bitcode.cabal view
@@ -20,7 +20,7 @@     in mind. The commands resemble an abstract RISC-style assembley, motivated by keeping
     later-phases analyses as simple as possible.
 
-version:            1.0.7
+version:            1.0.8
 license:            GPL-3.0-only
 license-file:       LICENSE
 author:             OrenGitHub
@@ -48,7 +48,7 @@         aeson,
         base >=4.17 && <=4.20,
         containers,
-        dhscanner-ast >= 1.1.0,
+        dhscanner-ast >= 1.1.1,
 
     hs-source-dirs:
         src
src/Bitcode.hs view
@@ -46,12 +46,8 @@ import qualified Token
 
 -- general imports
-import Data.Aeson
 import GHC.Generics
-import Data.Set ( Set )
-
--- general (qualified) imports
-import qualified Data.Set
+import Data.Aeson ( ToJSON, FromJSON )
 
 -- |
 -- * All instructions have an associated location
@@ -76,10 +72,6 @@    | Assume AssumeContent
    | Return ReturnContent
    | Assign AssignContent
-   | LoadImmStr StrContent
-   | LoadImmInt IntContent
-   | LoadImmBool BoolContent
-   | LoadImmNull NullContent
    | ParamDecl ParamDeclContent
    | FieldRead FieldReadContent
    | FieldWrite FieldWriteContent
@@ -88,9 +80,18 @@    | SubscriptWrite SubscriptWriteContent
    deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
-mkNopInstruction :: Location -> Instruction
-mkNopInstruction l = Instruction { location = l, instructionContent = Nop }
+data Value
+   = VariableCtor Variable
+   | ConstValueCtor ConstValue
+   | KeywordArgCtor KeywordArgVariable
+   deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
 
+data Variable
+   = TmpVariableCtor TmpVariable
+   | SrcVariableCtor SrcVariable
+   | ParamVariableCtor ParamVariable
+   deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
+
 data TmpVariable
    = TmpVariable
      {
@@ -107,17 +108,6 @@      }
      deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
 
-data ArgContent
-   = ArgContent
-     {
-         argVariableFqn :: Fqn,
-         argVariableSerialIdx :: Word, -- ^ zero-based
-         -- location is indicative to the call
-         -- this arg was generated for
-         argVariableMyAwesomeCallContext :: Location
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
 data ParamVariable
    = ParamVariable
      {
@@ -127,44 +117,41 @@      }
      deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
 
-data Variable
-   = TmpVariableCtor TmpVariable
-   | SrcVariableCtor SrcVariable
-   | ParamVariableCtor ParamVariable
-   | Arg ArgContent
-   deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
+data KeywordArgVariable
+   = KeywordArgVariable
+     {
+         keywordArgName :: String,
+         keywordArgValue :: Value
+     }
+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
 
 variableFqn :: Variable -> Fqn
 variableFqn (TmpVariableCtor   (TmpVariable   fqn _   )) = fqn
 variableFqn (SrcVariableCtor   (SrcVariable   fqn _   )) = fqn
 variableFqn (ParamVariableCtor (ParamVariable fqn _ _ )) = fqn
-variableFqn _ = Fqn "blah"
 
--- | Can /not/ be serialized to JSON
-data Variables = Variables { actualVariables :: Set Variable } deriving ( Show, Eq, Ord )
-
-data SrcVariables = SrcVariables { actualSrcVariables :: Set SrcVariable } deriving ( Show, Eq, Ord )
+locationVariable :: Variable -> Location
+locationVariable (TmpVariableCtor t) = tmpVariableLocation t
+locationVariable (SrcVariableCtor s) = Token.getVarNameLocation (srcVariableToken s)
+locationVariable (ParamVariableCtor p) = Token.getParamNameLocation (paramVariableToken p)
 
--- | Creating an empty collection of global variables
-createEmptyCollectionOfGlobalVariables :: SrcVariables
-createEmptyCollectionOfGlobalVariables = SrcVariables { actualSrcVariables = Data.Set.empty }
- 
--- | Can /not/ be serialized to JSON
-data TmpVariables = TmpVariables { actualTmpVariables :: Set TmpVariable } deriving ( Show, Eq, Ord )
+locationValue :: Value -> Location
+locationValue (VariableCtor v) = locationVariable v
+locationValue (ConstValueCtor c) = locationConstValue c
+locationValue (KeywordArgCtor k) = locationValue (keywordArgValue k)
 
-locationVariable :: Variable -> Location
-locationVariable v = case v of
-    (TmpVariableCtor tmpVariable) -> tmpVariableLocation tmpVariable
-    (SrcVariableCtor srcVariable) -> Token.getVarNameLocation $ srcVariableToken srcVariable
-    (ParamVariableCtor _paramVariable) -> Token.getParamNameLocation $ paramVariableToken _paramVariable
-    (Arg argContent) -> argVariableMyAwesomeCallContext argContent
+locationConstValue :: ConstValue -> Location
+locationConstValue (ConstIntValue  i) = Token.constIntLocation  i
+locationConstValue (ConstStrValue  s) = Token.constStrLocation  s
+locationConstValue (ConstBoolValue b) = Token.constBoolLocation b
+locationConstValue (ConstNullValue n) = Token.constNullLocation n
 
 data CallContent
    = CallContent
      {
          callOutput :: Variable,
          callee :: Variable,
-         args :: [ Variable ],
+         args :: [ Value ],
          callLocation :: Location
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
@@ -182,8 +169,8 @@    = BinopContent
      {
          binopOutput :: Variable,
-         binopLhs :: Variable,
-         binopRhs :: Variable
+         binopLhs :: Value,
+         binopRhs :: Value
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
@@ -191,25 +178,28 @@    = UnopContent
      {
          unopOutput :: Variable,
-         unopLhs :: Variable
+         unopLhs :: Value
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
 data AssumeContent
    = AssumeContent
      {
-         assumeVariable :: Variable,
-         assumedValue :: Bool
+         assumeValue :: Value,
+         assumeTruthy :: Bool
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
-mkAssumeInstruction :: Variable -> Bool -> Instruction
-mkAssumeInstruction v b = Instruction (locationVariable v) (Assume (AssumeContent v b))
+mkNopInstruction :: Location -> Instruction
+mkNopInstruction l = Instruction { location = l, instructionContent = Nop }
 
+mkAssumeInstruction :: Value -> Bool -> Instruction
+mkAssumeInstruction v b = Instruction (locationValue v) (Assume (AssumeContent v b))
+
 data ReturnContent
    = ReturnContent
      {
-         returnValue :: Maybe Variable
+         returnValue :: Maybe Value
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
@@ -217,41 +207,16 @@    = AssignContent
      {
          assignOutput :: Variable,
-         assignInput :: Variable
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data IntContent
-   = IntContent
-     {
-         loadImmIntOutput :: TmpVariable,
-         loadImmIntValue :: Token.ConstInt
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data StrContent
-   = StrContent
-     {
-         loadImmStrOutput :: TmpVariable,
-         loadImmStrValue :: Token.ConstStr
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data BoolContent
-   = BoolContent
-     {
-         loadImmBoolOutput :: TmpVariable,
-         loadImmBoolValue :: Token.ConstBool
+         assignInput :: Value
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
-data NullContent
-   = NullContent
-     {
-         loadImmNullOutput :: TmpVariable,
-         loadImmNullValue :: Token.ConstNull
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
+data ConstValue
+   = ConstIntValue Token.ConstInt
+   | ConstStrValue Token.ConstStr
+   | ConstBoolValue Token.ConstBool
+   | ConstNullValue Token.ConstNull
+   deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
 data FieldReadContent
    = FieldReadContent
@@ -267,7 +232,7 @@      {
          fieldWriteOutput :: Variable,
          fieldWriteName :: Token.FieldName,
-         fieldWriteInput :: Variable
+         fieldWriteInput :: Value
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
@@ -276,7 +241,7 @@      {
          subscriptReadOutput :: Variable,
          subscriptReadInput :: Variable,
-         subscriptReadIdx :: Variable
+         subscriptReadIdx :: Value
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
@@ -284,8 +249,8 @@    = SubscriptWriteContent
      {
          subscriptWriteOutput :: Variable,
-         subscriptWriteIdx :: Variable,
-         subscriptWriteInput :: Variable
+         subscriptWriteIdx :: Value,
+         subscriptWriteInput :: Value
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
 
@@ -295,37 +260,3 @@          paramVariable :: ParamVariable
      }
      deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-
--- |
---
--- * some instructions don't have an output variable
---
---     * 'Nop', 'Assume', 'Return' etc.
---
--- * other instructions have /exactly one/ output variable
---
-output :: InstructionContent -> Maybe Variable
-output (Unop          c) = Just $ unopOutput          c
-output (Call          c) = Just $ callOutput          c
-output (Binop         c) = Just $ binopOutput         c
-output (Assign        c) = Just $ assignOutput        c
-output (FieldRead     c) = Just $ fieldReadOutput     c
-output (SubscriptRead c) = Just $ subscriptReadOutput c
-output _              = Nothing
-
--- |
---
--- * some instructions don't have input variables /at all/
---
--- * other instructions have /multiple/ input variables
---
-inputs :: InstructionContent -> Set Variable
-inputs (Call       c) = Data.Set.fromList (args c)
-inputs              _ = Data.Set.empty
-
-variables :: InstructionContent -> Set Variable
-variables instruction = case output instruction of
-    Nothing -> inputs instruction
-    Just oneOutput -> (Data.Set.singleton oneOutput) `Data.Set.union` (inputs instruction)
-
src/Cfg.hs view
@@ -7,114 +7,99 @@ where
 
 -- project imports
-import Location
 import qualified Bitcode
 
 -- general imports
 import Data.Aeson
 import GHC.Generics hiding ( from, to )
 import Prelude hiding ( filter, map )
-import Data.Set ( Set, fromList, filter, map, union )
-
-data Node
-   = Node
-     {
-         theInstructionInside :: Bitcode.Instruction
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
+import Data.Set ( Set, fromList, map, union, empty, singleton )
 
-data Nodes
-   = Nodes
-     {
-         actualNodes :: Set Node
-     }
-     deriving ( Show, Eq, Ord )
+data Node = Node { theInstructionInside :: Bitcode.Instruction } deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
+data Nodes = Nodes { actualNodes :: Set Node } deriving ( Show, Eq, Ord )
 
-data Edge
-   = Edge
-     {
-         from :: Node,
-         to   :: Node
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
+data Edge = Edge { from :: Node, to :: Node } deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
+data Edges = Edges { actualEdges :: Set Edge } deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
 
-data Edges
-   = Edges
-     {
-         actualEdges :: Set Edge
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
+emptySetOfNodes :: Nodes
+emptySetOfNodes = Nodes { actualNodes = empty }
 
-mkEmptyCollectionOfEdges :: Edges
-mkEmptyCollectionOfEdges = Edges { actualEdges = fromList [] }
+emptySetOfEdges :: Edges
+emptySetOfEdges = Edges { actualEdges = empty }
 
-data Cfg
-   = Cfg
-     {
-         entry :: Node,
-         exit  :: Node,
-         edges :: Edges
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
+data Cfg = Empty | Normal Content deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
 
-location :: Cfg -> Location
-location = Bitcode.location . theInstructionInside . entry
+data Content = Content { entry :: Node, exit  :: Node, edges :: Edges } deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
 
 nodes :: Cfg -> Nodes
-nodes g = Nodes { actualNodes = nodes' `union` nodes'' }
-    where
-        nodes'  = map from (actualEdges (edges g))
-        nodes'' = map to   (actualEdges (edges g))
+nodes Empty = emptySetOfNodes
+nodes (Normal cfg) = nodes' (edges cfg)
 
-preds :: Node -> Cfg -> Nodes
-preds node g = Nodes { actualNodes = map from edges' }
-    where
-        edges' = filter (\e -> (to e) == node) (actualEdges (edges g))    
+nodes' :: Edges -> Nodes
+nodes' = nodes'' . actualEdges
 
-empty :: Location -> Cfg
-empty _location = atom (Node (Bitcode.Instruction _location Bitcode.Nop))
+nodes'' :: Set Edge -> Nodes
+nodes'' edges' = Nodes { actualNodes = (map from edges') `union` (map to edges') }
 
 atom :: Node -> Cfg
-atom node = Cfg { entry = node, exit = node, edges = mkEmptyCollectionOfEdges }
+atom node = Normal (Content { entry = node, exit = node, edges = emptySetOfEdges })
 
 concat :: Cfg -> Cfg -> Cfg
-concat g1 g2 = Cfg { entry = entry g1, exit = exit g2, edges = edges' }
-    where
-        edges' = Edges $ edges1 `union` edges2 `union` connector
-            where
-                edges1 = actualEdges $ edges g1
-                edges2 = actualEdges $ edges g2
-                connector = fromList [Edge { from = exit g1, to = entry g2 }]
+concat Empty cfg = cfg
+concat (Normal content) cfg = Normal (concatNormalContentFirst content cfg)
 
-parallel :: Cfg -> Cfg -> Cfg
-parallel g1 g2 = Cfg { entry = s, exit = t, edges = edges' }
-    where
-        s = Node $ Bitcode.mkNopInstruction (Bitcode.location (theInstructionInside (entry g1)))
-        t = Node $ Bitcode.mkNopInstruction (Bitcode.location (theInstructionInside (exit  g2)))
-        edges' = Edges $ edges1 `union` edges2 `union` connectors
-            where
-                edges1 = actualEdges $ edges g1
-                edges2 = actualEdges $ edges g2
-                connectors = fromList [ s_g1, s_g2, g1_t, g2_t ]
-                    where
-                        s_g1 = Edge { from = s, to = entry g1 }
-                        s_g2 = Edge { from = s, to = entry g2 }
-                        g1_t = Edge { from = entry g1, to = t }
-                        g2_t = Edge { from = entry g2, to = t }
+concatNormalContentFirst :: Content -> Cfg -> Content
+concatNormalContentFirst content Empty = content
+concatNormalContentFirst cfg1 (Normal cfg2) = let
+    edges1 = actualEdges (edges cfg1)
+    edges2 = actualEdges (edges cfg2)
+    connector = singleton (Edge { from = exit cfg1, to = entry cfg2 })
+    edges12 = Edges (edges1 `union` edges2 `union` connector)
+    in Content { entry = entry cfg1, exit = exit cfg2, edges = edges12 }
 
--- | create a loop from condition and body
-loopify :: Cfg -> Cfg -> Bitcode.Variable -> Cfg
-loopify cond body guardedValue = Cfg { entry = entry cond, exit = t, edges = edges' }
-    where
-        t = Node $ Bitcode.mkNopInstruction (Bitcode.locationVariable guardedValue)
-        edges' = Edges $ edges1 `union` edges2 `union` connectors
-            where
-                edges1 = actualEdges $ edges cond
-                edges2 = actualEdges $ edges body
-                connectors = fromList [ e1, e2, e3, e4, e5 ]
-                    where
-                        e1 = Edge { from = exit cond, to = Node $ Bitcode.mkAssumeInstruction guardedValue True }
-                        e2 = Edge { from = exit cond, to = Node $ Bitcode.mkAssumeInstruction guardedValue False }
-                        e3 = Edge { from = Node $ Bitcode.mkAssumeInstruction guardedValue True, to = entry body }
-                        e4 = Edge { from = Node $ Bitcode.mkAssumeInstruction guardedValue False, to = t }
-                        e5 = Edge { from = exit body, to = entry cond }
+mkNopNode :: Node -> Node
+mkNopNode = Node . Bitcode.mkNopInstruction . Bitcode.location . theInstructionInside
+
+mkNewEntry :: Node -> Node
+mkNewEntry = mkNopNode
+
+mkNewExit :: Node -> Node
+mkNewExit = mkNopNode
+
+parallelNormalCfgs :: Content -> Content -> Cfg
+parallelNormalCfgs cfg1 cfg2 = let
+    s = mkNewEntry (entry cfg1)
+    t = mkNewExit (exit cfg2)
+    c1 = Edge { from = s, to = entry cfg1 }
+    c2 = Edge { from = s, to = entry cfg2 }
+    c3 = Edge { from = exit cfg1, to = t }
+    c4 = Edge { from = exit cfg2, to = t }
+    edges1 = actualEdges (edges cfg1)
+    edges2 = actualEdges (edges cfg2)
+    connectors = fromList [ c1, c2, c3, c4 ]
+    edges12 = Edges (edges1 `union` edges2 `union` connectors)
+    in Normal (Content { entry = s, exit = t, edges = edges12 })
+
+loopifyEmptyCondNormalBody :: Content -> Bitcode.Value -> Cfg
+loopifyEmptyCondNormalBody _body _guardedValue = Empty
+
+loopifyNormalCondEmptyBody :: Content -> Bitcode.Value -> Cfg
+loopifyNormalCondEmptyBody _cond _guardedValue = Empty
+
+loopify :: Cfg -> Cfg -> Bitcode.Value -> Cfg
+loopify Empty Empty _ = Empty
+loopify Empty (Normal body) guardedValue = loopifyEmptyCondNormalBody body guardedValue
+loopify (Normal cond) Empty guardedValue = loopifyNormalCondEmptyBody cond guardedValue
+loopify (Normal cond) (Normal body) guardedValue = let
+    guardedValueIsTrue = Node (Bitcode.mkAssumeInstruction guardedValue True)
+    guardedValueIsFalse = Node (Bitcode.mkAssumeInstruction guardedValue False)
+    c1 = Edge { from = exit cond, to = guardedValueIsTrue }
+    c2 = Edge { from = exit cond, to = guardedValueIsFalse }
+    c3 = Edge { from = guardedValueIsTrue, to = entry body }
+    c4 = Edge { from = guardedValueIsFalse, to = exit body }
+    c5 = Edge { from = exit body, to = entry cond }
+    edgesCond = actualEdges (edges cond)
+    edgesBody = actualEdges (edges body)
+    connectors = fromList [ c1, c2, c3, c4, c5 ]
+    edges' = Edges (edgesCond `union` edgesBody `union` connectors)
+    in Normal (Content { entry = entry cond, exit = exit body, edges = edges' })