packages feed

dhscanner-bitcode 2.3.0 → 2.4.0

raw patch · 3 files changed

+393/−390 lines, 3 filesdep ~dhscanner-astPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: dhscanner-ast

API changes (from Hackage documentation)

- Callable: Annotation :: Location -> Annotation
- Callable: data Annotation
- Callable: instance Data.Aeson.Types.FromJSON.FromJSON Callable.Annotation
- Callable: instance Data.Aeson.Types.ToJSON.ToJSON Callable.Annotation
- Callable: instance GHC.Internal.Classes.Eq Callable.Annotation
- Callable: instance GHC.Internal.Classes.Ord Callable.Annotation
- Callable: instance GHC.Internal.Generics.Generic Callable.Annotation
- Callable: instance GHC.Internal.Show.Show Callable.Annotation
+ Bitcode: Annotation :: Location -> Annotation
+ Bitcode: [paramAnnotations] :: ParamDeclContent -> [Annotation]
+ Bitcode: data Annotation
+ Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.Annotation
+ Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.Annotation
+ Bitcode: instance GHC.Internal.Classes.Eq Bitcode.Annotation
+ Bitcode: instance GHC.Internal.Classes.Ord Bitcode.Annotation
+ Bitcode: instance GHC.Internal.Generics.Generic Bitcode.Annotation
+ Bitcode: instance GHC.Internal.Show.Show Bitcode.Annotation
- Bitcode: ParamDeclContent :: ParamVariable -> ParamDeclContent
+ Bitcode: ParamDeclContent :: ParamVariable -> [Annotation] -> ParamDeclContent

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:            2.3.0
+version:            2.4.0
 license:            GPL-3.0-only
 license-file:       LICENSE
 author:             OrenGitHub
@@ -48,7 +48,7 @@         aeson >= 2.2 && < 2.4,
         base >= 4.22 && < 4.23,
         containers >= 0.8 && < 0.9,
-        dhscanner-ast >= 1.5.0 && < 1.6
+        dhscanner-ast >= 1.6.0
 
     hs-source-dirs:
         src
src/Bitcode.hs view
@@ -1,274 +1,280 @@--- |
---
--- * The [intermediate language (IL) \/ intermediate representation (IR) \/ bitcode](https://en.wikipedia.org/wiki/Intermediate_representation#Intermediate_language)
--- are all synonyms for:
---
---     * a data structure able to represent code originating from /multiple/ programming languages.
---     * minimal instruction set, similar in spirit to [RISC](https://en.wikipedia.org/wiki/Reduced_instruction_set_computer) architectures
---     * unlike /actual/ assembly, it has an /infinite/ number of temporaries ( instead of registers )
---
--- * Its main purpose is to serve as the:
---
---     * second step for /static code analysis/ 
---     * part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework for
---       static analysis performing security checks 🔒 and
---       [PII](https://en.wikipedia.org/wiki/Personal_data) leaks detection 🪪
---
--- * As part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework:
---
---     * targets mostly languages used for /cloud native applications/ ☁️
---     * Python, Ruby 💎, Php, Javascript, Typescript, Java ☕️, C# and Golang.
---
--- * Typical flow:
---
---     * Abstract syntax trees (ASTs) are scanned
---
---         * 'Callable' entities are identified
---         * each 'Callable' is associated with its control flow graph ('Cfg')
---         * control flow graphs are directed, connecting bitcode instructions
---
--- * Non Haskell parogrammers note:
---
---     * Each 'Callable' object is /immutable/ ( like everything else in Haskell ... )
---
-
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DeriveAnyClass #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Bitcode
-
-where
-
--- project imports
-import Fqn
-import Location
-import qualified Token
-
--- general imports
-import GHC.Generics
-import Data.Aeson ( ToJSON, FromJSON )
-
--- |
--- * All instructions have an associated location
---
--- * That is also true for instrumented instructions (like `Nop` and `Assume`)
---
-data Instruction
-   = Instruction
-     {
-         location :: Location,
-         instructionContent :: InstructionContent
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
--- |
--- A minimal instruction set for translating common programming languages
-data InstructionContent
-   = Nop
-   | Call CallContent
-   | Unop UnopContent
-   | Binop BinopContent
-   | Assume AssumeContent
-   | Return ReturnContent
-   | Assign AssignContent
-   | ParamDecl ParamDeclContent
-   | FieldRead FieldReadContent
-   | FieldWrite FieldWriteContent
-   | UnresolvedRef UnresolvedRefContent -- ^ @since 1.0.5
-   | SubscriptRead SubscriptReadContent
-   | SubscriptWrite SubscriptWriteContent
-   deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-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
-     {
-         tmpVariableFqn :: Fqn,
-         tmpVariableLocation :: Location
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data SrcVariable
-   = SrcVariable
-     {
-         srcVariableFqn :: Fqn,
-         srcVariableToken :: Token.VarName
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data ParamVariable
-   = ParamVariable
-     {
-         paramVariableFqn :: Fqn,
-         paramVariableSerialIdx :: Word, -- ^ zero-based
-         paramVariableToken :: Token.ParamName
-     }
-     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
-
-locationVariable :: Variable -> Location
-locationVariable (TmpVariableCtor t) = tmpVariableLocation t
-locationVariable (SrcVariableCtor s) = Token.getVarNameLocation (srcVariableToken s)
-locationVariable (ParamVariableCtor p) = Token.getParamNameLocation (paramVariableToken p)
-
-locationValue :: Value -> Location
-locationValue (VariableCtor v) = locationVariable v
-locationValue (ConstValueCtor c) = locationConstValue c
-locationValue (KeywordArgCtor k) = locationValue (keywordArgValue k)
-
-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 :: [ Value ],
-         callLocation :: Location
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data UnresolvedRefContent
-   = UnresolvedRefContent
-     {
-         unresolvedRefOutput :: Variable,
-         unresolvedRef :: Variable,
-         unresolvedRefLocation :: Location
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
--- | Coarse operator classification for 'BinopContent'. Only equality
--- variants are distinguished; everything else collapses to 'OtherOp' so
--- downstream analyses ( e.g. @kb_comparison@ in @dhscanner-kbgen@ ) can
--- pick out gated-return-on-comparison patterns without carrying the full
--- 'Ast.Operator' surface into the bitcode layer.
-data BinopOp
-   = EqOp
-   | NeqOp
-   | OtherOp
-   deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data BinopContent
-   = BinopContent
-     {
-         binopOutput :: Variable,
-         binopLhs :: Value,
-         binopRhs :: Value,
-         binopOperator :: BinopOp
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data UnopContent
-   = UnopContent
-     {
-         unopOutput :: Variable,
-         unopLhs :: Value
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data AssumeContent
-   = AssumeContent
-     {
-         assumeValue :: Value,
-         assumeTruthy :: Bool
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-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 Value
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data AssignContent
-   = AssignContent
-     {
-         assignOutput :: Variable,
-         assignInput :: Value
-     }
-     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
-     {
-         fieldReadOutput :: Variable,
-         fieldReadInput :: Variable,
-         fieldReadName :: Token.FieldName
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data FieldWriteContent
-   = FieldWriteContent
-     {
-         fieldWriteOutput :: Variable,
-         fieldWriteName :: Token.FieldName,
-         fieldWriteInput :: Value
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data SubscriptReadContent
-   = SubscriptReadContent
-     {
-         subscriptReadOutput :: Variable,
-         subscriptReadInput :: Variable,
-         subscriptReadIdx :: Value
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data SubscriptWriteContent
-   = SubscriptWriteContent
-     {
-         subscriptWriteOutput :: Variable,
-         subscriptWriteIdx :: Value,
-         subscriptWriteInput :: Value
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
-
-data ParamDeclContent
-   = ParamDeclContent
-     {
-         paramVariable :: ParamVariable
-     }
-     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )
+-- |+--+-- * The [intermediate language (IL) \/ intermediate representation (IR) \/ bitcode](https://en.wikipedia.org/wiki/Intermediate_representation#Intermediate_language)+-- are all synonyms for:+--+--     * a data structure able to represent code originating from /multiple/ programming languages.+--     * minimal instruction set, similar in spirit to [RISC](https://en.wikipedia.org/wiki/Reduced_instruction_set_computer) architectures+--     * unlike /actual/ assembly, it has an /infinite/ number of temporaries ( instead of registers )+--+-- * Its main purpose is to serve as the:+--+--     * second step for /static code analysis/ +--     * part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework for+--       static analysis performing security checks 🔒 and+--       [PII](https://en.wikipedia.org/wiki/Personal_data) leaks detection 🪪+--+-- * As part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework:+--+--     * targets mostly languages used for /cloud native applications/ ☁️+--     * Python, Ruby 💎, Php, Javascript, Typescript, Java ☕️, C# and Golang.+--+-- * Typical flow:+--+--     * Abstract syntax trees (ASTs) are scanned+--+--         * 'Callable' entities are identified+--         * each 'Callable' is associated with its control flow graph ('Cfg')+--         * control flow graphs are directed, connecting bitcode instructions+--+-- * Non Haskell parogrammers note:+--+--     * Each 'Callable' object is /immutable/ ( like everything else in Haskell ... )+--++{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE OverloadedStrings #-}++module Bitcode++where++-- project imports+import Fqn+import Location+import qualified Token++-- general imports+import GHC.Generics+import Data.Aeson ( ToJSON, FromJSON )++-- |+-- * All instructions have an associated location+--+-- * That is also true for instrumented instructions (like `Nop` and `Assume`)+--+data Instruction+   = Instruction+     {+         location :: Location,+         instructionContent :: InstructionContent+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++-- |+-- A minimal instruction set for translating common programming languages+data InstructionContent+   = Nop+   | Call CallContent+   | Unop UnopContent+   | Binop BinopContent+   | Assume AssumeContent+   | Return ReturnContent+   | Assign AssignContent+   | ParamDecl ParamDeclContent+   | FieldRead FieldReadContent+   | FieldWrite FieldWriteContent+   | UnresolvedRef UnresolvedRefContent -- ^ @since 1.0.5+   | SubscriptRead SubscriptReadContent+   | SubscriptWrite SubscriptWriteContent+   deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++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+     {+         tmpVariableFqn :: Fqn,+         tmpVariableLocation :: Location+     }+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data SrcVariable+   = SrcVariable+     {+         srcVariableFqn :: Fqn,+         srcVariableToken :: Token.VarName+     }+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data ParamVariable+   = ParamVariable+     {+         paramVariableFqn :: Fqn,+         paramVariableSerialIdx :: Word, -- ^ zero-based+         paramVariableToken :: Token.ParamName+     }+     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++locationVariable :: Variable -> Location+locationVariable (TmpVariableCtor t) = tmpVariableLocation t+locationVariable (SrcVariableCtor s) = Token.getVarNameLocation (srcVariableToken s)+locationVariable (ParamVariableCtor p) = Token.getParamNameLocation (paramVariableToken p)++locationValue :: Value -> Location+locationValue (VariableCtor v) = locationVariable v+locationValue (ConstValueCtor c) = locationConstValue c+locationValue (KeywordArgCtor k) = locationValue (keywordArgValue k)++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 :: [ Value ],+         callLocation :: Location+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data UnresolvedRefContent+   = UnresolvedRefContent+     {+         unresolvedRefOutput :: Variable,+         unresolvedRef :: Variable,+         unresolvedRefLocation :: Location+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++-- | Coarse operator classification for 'BinopContent'. Only equality+-- variants are distinguished; everything else collapses to 'OtherOp' so+-- downstream analyses ( e.g. @kb_comparison@ in @dhscanner-kbgen@ ) can+-- pick out gated-return-on-comparison patterns without carrying the full+-- 'Ast.Operator' surface into the bitcode layer.+data BinopOp+   = EqOp+   | NeqOp+   | OtherOp+   deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data BinopContent+   = BinopContent+     {+         binopOutput :: Variable,+         binopLhs :: Value,+         binopRhs :: Value,+         binopOperator :: BinopOp+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data UnopContent+   = UnopContent+     {+         unopOutput :: Variable,+         unopLhs :: Value+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data AssumeContent+   = AssumeContent+     {+         assumeValue :: Value,+         assumeTruthy :: Bool+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++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 Value+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data AssignContent+   = AssignContent+     {+         assignOutput :: Variable,+         assignInput :: Value+     }+     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+     {+         fieldReadOutput :: Variable,+         fieldReadInput :: Variable,+         fieldReadName :: Token.FieldName+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data FieldWriteContent+   = FieldWriteContent+     {+         fieldWriteOutput :: Variable,+         fieldWriteName :: Token.FieldName,+         fieldWriteInput :: Value+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data SubscriptReadContent+   = SubscriptReadContent+     {+         subscriptReadOutput :: Variable,+         subscriptReadInput :: Variable,+         subscriptReadIdx :: Value+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data SubscriptWriteContent+   = SubscriptWriteContent+     {+         subscriptWriteOutput :: Variable,+         subscriptWriteIdx :: Value,+         subscriptWriteInput :: Value+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data ParamDeclContent+   = ParamDeclContent+     {+         paramVariable :: ParamVariable,+         paramAnnotations :: [ Annotation ] -- ^ ( for example, Java Spring: @\@RequestParam@ )+     }+     deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++-- | an annotation ( java @GetMapping, python decorator, ... ) is just its+-- location : it is lowered as a call at that same location, so its fqn+-- and args come from the call+data Annotation = Annotation Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
src/Callable.hs view
@@ -1,114 +1,111 @@--- |
---
--- * The [intermediate language (IL) \/ intermediate representation (IR) \/ bitcode](https://en.wikipedia.org/wiki/Intermediate_representation#Intermediate_language)
--- are all synonyms for a data structure able to represent code originating from /multiple/
--- programming languages.
---
--- * In our context, the main purpose is to enable an efficient and uniform /static code analysis/,
--- as part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework
--- for [CI/CD](https://en.wikipedia.org/wiki/CI/CD) container security checks.
---
--- * [dhscanner](https://github.com/OrenGitHub/dhscanner) targets mostly languages used for /cloud native applications/:
--- __Python__, __Ruby__, __Php__, __Javascript__, __Typescript__, __Java__, __C#__ and __Golang__.
---
--- * Typically, a collection of files are first parsed using relevant
--- [parsers](https://github.com/OrenGitHub/dhscanner.1.parsers), then,
--- the resulting abstract syntax trees are sent to code generation,
--- where they are translated into a collection of /callables/.
---
--- * A callable is a sequence of commands corresponding to either a function, a method,
--- a lambda or (in languages like python) a script.
---
-
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DeriveAnyClass #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Callable
-
-where
-
--- project imports
-import Cfg
-import Fqn
-import Token
-import Location
-
--- general imports
-import Data.Aeson
-import GHC.Generics
-
-data Callables
-   = Callables
-     {
-         actualCallables :: [ Callable ]
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
--- | Four kinds of callables.
-data Callable
-   = Method MethodContent
-   | Lambda LambdaContent
-   | Script ScriptContent
-   | Function FunctionContent
-   deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data HostingClassSuper
-   = HostingClassSuper
-     {
-         hostingClassSuperName :: Token.SuperName,
-         hostingClassSuperResolvedType :: Maybe Fqn
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data MethodContent
-   = MethodContent
-     {
-         methodName :: Token.MethodName,
-         hostingClassName :: Token.ClassName,
-         hostingClassSupers :: [ HostingClassSuper ],
-         hostingClassAnnotations :: [ Annotation ],
-         methodBody :: Cfg,
-         methodAnnotations :: [ Annotation ],
-         methodLocation :: Location,
-         methodSourceBodyLength :: Word -- ^ number of source-level statements ( see @stmtMethodBody@ in "Ast" )
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data LambdaContent
-   = LambdaContent
-     {
-         lambdaBody :: Cfg,
-         lambdaLocation :: Location,
-         lambdaSourceBodyLength :: Word -- ^ number of source-level statements ( see @expLambdaBody@ in "Ast" )
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data ScriptContent
-   = ScriptContent
-     {
-         filename :: String,
-         scriptBody :: Cfg
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data Annotation = Annotation Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
-data FunctionContent
-   = FunctionContent
-     {
-         funcName :: Token.FuncName,
-         funcBody :: Cfg,
-         funcAnnotations :: [ Annotation ],
-         funcLocation :: Location,
-         funcSourceBodyLength :: Word -- ^ number of source-level statements ( see @stmtFuncBody@ in "Ast" )
-     }
-     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
-
--- | Number of source-level statements in the callable's body ( see "Ast" ). Returns @0@ for 'Script'.
-numOriginalSourceInstructions :: Callable -> Word
-numOriginalSourceInstructions (Method   m) = methodSourceBodyLength m
-numOriginalSourceInstructions (Lambda   l) = lambdaSourceBodyLength l
-numOriginalSourceInstructions (Function f) = funcSourceBodyLength   f
-numOriginalSourceInstructions (Script   _) = 0
-
+-- |+--+-- * The [intermediate language (IL) \/ intermediate representation (IR) \/ bitcode](https://en.wikipedia.org/wiki/Intermediate_representation#Intermediate_language)+-- are all synonyms for a data structure able to represent code originating from /multiple/+-- programming languages.+--+-- * In our context, the main purpose is to enable an efficient and uniform /static code analysis/,+-- as part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework+-- for [CI/CD](https://en.wikipedia.org/wiki/CI/CD) container security checks.+--+-- * [dhscanner](https://github.com/OrenGitHub/dhscanner) targets mostly languages used for /cloud native applications/:+-- __Python__, __Ruby__, __Php__, __Javascript__, __Typescript__, __Java__, __C#__ and __Golang__.+--+-- * Typically, a collection of files are first parsed using relevant+-- [parsers](https://github.com/OrenGitHub/dhscanner.1.parsers), then,+-- the resulting abstract syntax trees are sent to code generation,+-- where they are translated into a collection of /callables/.+--+-- * A callable is a sequence of commands corresponding to either a function, a method,+-- a lambda or (in languages like python) a script.+--++{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE OverloadedStrings #-}++module Callable where++-- project imports+import Bitcode+import Cfg+import Fqn+import Token+import Location++-- general imports+import Data.Aeson+import GHC.Generics++data Callables+   = Callables+     {+         actualCallables :: [ Callable ]+     }+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++-- | Four kinds of callables.+data Callable+   = Method MethodContent+   | Lambda LambdaContent+   | Script ScriptContent+   | Function FunctionContent+   deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data HostingClassSuper+   = HostingClassSuper+     {+         hostingClassSuperName :: Token.SuperName,+         hostingClassSuperResolvedType :: Maybe Fqn+     }+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data MethodContent+   = MethodContent+     {+         methodName :: Token.MethodName,+         hostingClassName :: Token.ClassName,+         hostingClassSupers :: [ HostingClassSuper ],+         hostingClassAnnotations :: [ Annotation ],+         methodBody :: Cfg,+         methodAnnotations :: [ Annotation ],+         methodLocation :: Location,+         methodSourceBodyLength :: Word -- ^ number of source-level statements ( see @stmtMethodBody@ in "Ast" )+     }+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data LambdaContent+   = LambdaContent+     {+         lambdaBody :: Cfg,+         lambdaLocation :: Location,+         lambdaSourceBodyLength :: Word -- ^ number of source-level statements ( see @expLambdaBody@ in "Ast" )+     }+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data ScriptContent+   = ScriptContent+     {+         filename :: String,+         scriptBody :: Cfg+     }+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data FunctionContent+   = FunctionContent+     {+         funcName :: Token.FuncName,+         funcBody :: Cfg,+         funcAnnotations :: [ Annotation ],+         funcLocation :: Location,+         funcSourceBodyLength :: Word -- ^ number of source-level statements ( see @stmtFuncBody@ in "Ast" )+     }+     deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++-- | Number of source-level statements in the callable's body ( see "Ast" ). Returns @0@ for 'Script'.+numOriginalSourceInstructions :: Callable -> Word+numOriginalSourceInstructions (Method   m) = methodSourceBodyLength m+numOriginalSourceInstructions (Lambda   l) = lambdaSourceBodyLength l+numOriginalSourceInstructions (Function f) = funcSourceBodyLength   f+numOriginalSourceInstructions (Script   _) = 0+