{-# LANGUAGE GADTs #-}
-- | Defines an AST for defining Modules.
module Language.Drasil.Mod (Class(..), StateVariable(..), Func(..), 
  FuncData(..), FuncDef(..), FuncStmt(..), Initializer, Mod(..), Name, 
  Version, Description, Import, ($:=), pubStateVar, privStateVar, classDef, 
  classImplements, ctorDef, ffor, fforRange, fDecDef, fname, fstdecl, funcData, funcDef, 
  funcDefParams, packmod, packmodRequires
) where

import Language.Drasil (Space, MayHaveUnit, Quantity)
import Database.Drasil (ChunkDB)
import GOOL.Drasil (ScopeTag(..))

import Language.Drasil.Chunk.Code (CodeVarChunk, CodeFuncChunk, codevars, 
  codevars', quantvar)
import Language.Drasil.Chunk.Parameter (ParameterChunk, pcAuto)
import Language.Drasil.Code.DataDesc (DataDesc)
import Language.Drasil.CodeExpr (CodeExpr)
import qualified Language.Drasil.CodeExpr as CE

import Utils.Drasil (toPlainName)

import Data.List ((\\), nub)

-- | Type synonym for clarity.
type Name = String
-- | Type synonym for clarity.
type Description = String
-- | Type synonym for clarity.
type Import = String
-- | Type synonym for clarity.
type Version = String

-- | Holds module information.
data Mod = Mod Name Description [Import] [Class] [Func]

-- | Define a 'Mod' with the given 'Name', 'Description', 'Classes', and 'Functions'.
packmod :: Name -> Description -> [Class] -> [Func] -> Mod
packmod :: Name -> Name -> [Class] -> [Func] -> Mod
packmod n :: Name
n d :: Name
d = Name -> Name -> [Name] -> [Class] -> [Func] -> Mod
packmodRequires Name
n Name
d []

-- | Define a 'Mod' that requires some library imports, with the given Name, 
-- Description, Classes, and Functions.
packmodRequires :: Name -> Description -> [Import] -> [Class] -> [Func] -> Mod
packmodRequires :: Name -> Name -> [Name] -> [Class] -> [Func] -> Mod
packmodRequires n :: Name
n = Name -> Name -> [Name] -> [Class] -> [Func] -> Mod
Mod (Name -> Name
toPlainName Name
n)

-- | Holds information needed to define a class.
data Class = ClassDef {
  Class -> Name
className :: Name, 
  Class -> Maybe Name
implements :: Maybe Name,
  Class -> Name
classDesc :: Description,
  Class -> [StateVariable]
stateVars :: [StateVariable],
  Class -> [Func]
methods :: [Func]}

-- | State variables hold attach a 'ScopeTag' to a 'CodeVarChunk'.
data StateVariable = SV {
  StateVariable -> ScopeTag
svScope :: ScopeTag,
  StateVariable -> CodeVarChunk
stVar :: CodeVarChunk}

-- | Define a public state variable based on the given 'CodeVarChunk'.
pubStateVar :: CodeVarChunk -> StateVariable
pubStateVar :: CodeVarChunk -> StateVariable
pubStateVar = ScopeTag -> CodeVarChunk -> StateVariable
SV ScopeTag
Pub

-- | Define a private state variable based on the given 'CodeVarChunk'.
privStateVar :: CodeVarChunk -> StateVariable
privStateVar :: CodeVarChunk -> StateVariable
privStateVar = ScopeTag -> CodeVarChunk -> StateVariable
SV ScopeTag
Priv

-- | Define a class with the given 'Name', 'Description', state variables, and 
-- methods.
classDef :: Name -> Description -> [StateVariable] -> [Func] -> Class
classDef :: Name -> Name -> [StateVariable] -> [Func] -> Class
classDef n :: Name
n = Name -> Maybe Name -> Name -> [StateVariable] -> [Func] -> Class
ClassDef Name
n Maybe Name
forall a. Maybe a
Nothing

-- | Define a class that implements an interface. 1st 'Name' is class name, 2nd is
-- interface name. 
classImplements :: Name -> Name -> Description -> [StateVariable] -> [Func] -> 
  Class
classImplements :: Name -> Name -> Name -> [StateVariable] -> [Func] -> Class
classImplements n :: Name
n i :: Name
i = Name -> Maybe Name -> Name -> [StateVariable] -> [Func] -> Class
ClassDef Name
n (Name -> Maybe Name
forall a. a -> Maybe a
Just Name
i)

-- | Holds a function definition or function data.
data Func = FDef FuncDef
          | FData FuncData

-- | Define a function that reads data from a file, according to the given
-- 'DataDesc'.
funcData :: Name -> Description -> DataDesc -> Func
funcData :: Name -> Name -> DataDesc -> Func
funcData n :: Name
n desc :: Name
desc d :: DataDesc
d = FuncData -> Func
FData (FuncData -> Func) -> FuncData -> Func
forall a b. (a -> b) -> a -> b
$ Name -> Name -> DataDesc -> FuncData
FuncData (Name -> Name
toPlainName Name
n) Name
desc DataDesc
d

-- | Define a function by providing the 'FuncStmt's for its body. Other 
-- parameters are function name, description, list of parameters, space of the 
-- returned value, and description of the returned value.
funcDef :: (Quantity c, MayHaveUnit c) => Name -> Description -> [c] -> 
  Space -> Maybe Description -> [FuncStmt] -> Func
funcDef :: Name -> Name -> [c] -> Space -> Maybe Name -> [FuncStmt] -> Func
funcDef s :: Name
s desc :: Name
desc i :: [c]
i t :: Space
t returnDesc :: Maybe Name
returnDesc fs :: [FuncStmt]
fs = FuncDef -> Func
FDef (FuncDef -> Func) -> FuncDef -> Func
forall a b. (a -> b) -> a -> b
$ Name
-> Name
-> [ParameterChunk]
-> Space
-> Maybe Name
-> [FuncStmt]
-> FuncDef
FuncDef (Name -> Name
toPlainName Name
s) Name
desc 
  ((c -> ParameterChunk) -> [c] -> [ParameterChunk]
forall a b. (a -> b) -> [a] -> [b]
map (CodeVarChunk -> ParameterChunk
forall c. CodeIdea c => c -> ParameterChunk
pcAuto (CodeVarChunk -> ParameterChunk)
-> (c -> CodeVarChunk) -> c -> ParameterChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. c -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar) [c]
i) Space
t Maybe Name
returnDesc [FuncStmt]
fs 

-- | Like 'funcDef' but uses 'ParameterChunk's to represent the parameters.
funcDefParams :: Name -> Description -> [ParameterChunk] -> Space -> 
  Maybe Description -> [FuncStmt] -> Func
funcDefParams :: Name
-> Name
-> [ParameterChunk]
-> Space
-> Maybe Name
-> [FuncStmt]
-> Func
funcDefParams s :: Name
s desc :: Name
desc ps :: [ParameterChunk]
ps t :: Space
t returnDesc :: Maybe Name
returnDesc fs :: [FuncStmt]
fs = FuncDef -> Func
FDef (FuncDef -> Func) -> FuncDef -> Func
forall a b. (a -> b) -> a -> b
$ Name
-> Name
-> [ParameterChunk]
-> Space
-> Maybe Name
-> [FuncStmt]
-> FuncDef
FuncDef (Name -> Name
toPlainName Name
s) Name
desc 
  [ParameterChunk]
ps Space
t Maybe Name
returnDesc [FuncStmt]
fs

-- | Define a constructor, with the given name, description, parameters, 
-- initializers (variable-value pairs), and 'FuncStmt's for the body. 
ctorDef :: Name -> Description -> [ParameterChunk] -> [Initializer] -> 
  [FuncStmt] -> Func
ctorDef :: Name
-> Name -> [ParameterChunk] -> [Initializer] -> [FuncStmt] -> Func
ctorDef n :: Name
n desc :: Name
desc ps :: [ParameterChunk]
ps is :: [Initializer]
is fs :: [FuncStmt]
fs = FuncDef -> Func
FDef (FuncDef -> Func) -> FuncDef -> Func
forall a b. (a -> b) -> a -> b
$ Name
-> Name
-> [ParameterChunk]
-> [Initializer]
-> [FuncStmt]
-> FuncDef
CtorDef Name
n Name
desc [ParameterChunk]
ps [Initializer]
is [FuncStmt]
fs

-- | Function data. Holds a name, description, and pieces of data with its own description.
data FuncData where
  FuncData :: Name -> Description -> DataDesc -> FuncData

-- | Defines a function.
data FuncDef where
  -- | Parameters are: Name, description, parameters, return type, return description, statements.
  FuncDef :: Name -> Description -> [ParameterChunk] -> Space -> 
    Maybe Description -> [FuncStmt] -> FuncDef
  CtorDef :: Name -> Description -> [ParameterChunk] -> [Initializer] -> 
    [FuncStmt] -> FuncDef

-- | Variable-value pair.
type Initializer = (CodeVarChunk, CodeExpr)
 
data FuncStmt where
  FAsg      :: CodeVarChunk -> CodeExpr -> FuncStmt
  FAsgIndex :: CodeVarChunk -> Integer -> CodeExpr -> FuncStmt
  -- | For-loop; Variable, Start, Stop, Step, Body.
  FFor      :: CodeVarChunk -> CodeExpr -> CodeExpr -> CodeExpr
                -> [FuncStmt] -> FuncStmt
  FForEach  :: CodeVarChunk -> CodeExpr -> [FuncStmt] -> FuncStmt
  FWhile    :: CodeExpr -> [FuncStmt] -> FuncStmt
  FCond     :: CodeExpr -> [FuncStmt] -> [FuncStmt] -> FuncStmt
  FRet      :: CodeExpr -> FuncStmt
  FThrow    :: String -> FuncStmt
  FTry      :: [FuncStmt] -> [FuncStmt] -> FuncStmt
  FContinue :: FuncStmt
  FDecDef   :: CodeVarChunk -> CodeExpr -> FuncStmt
  FFuncDef  :: CodeFuncChunk -> [ParameterChunk] -> [FuncStmt] -> FuncStmt
  FVal      :: CodeExpr -> FuncStmt
  FMulti    :: [FuncStmt] -> FuncStmt
  -- slight hack, for now
  FAppend   :: CodeExpr -> CodeExpr -> FuncStmt
  
-- | Define an assignment statement.
($:=) :: (Quantity c, MayHaveUnit c) => c -> CodeExpr -> FuncStmt
v :: c
v $:= :: c -> CodeExpr -> FuncStmt
$:= e :: CodeExpr
e = CodeVarChunk -> CodeExpr -> FuncStmt
FAsg (c -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar c
v) CodeExpr
e

-- | Define a for-loop. 'Quantity' is for the iteration variable, 'CodeExpr' is the 
-- upper bound at that variable (the variable will start with a value of 0).
-- ['FuncStmt'] is for the loop body.
ffor :: (Quantity c, MayHaveUnit c) => c -> CodeExpr -> [FuncStmt] -> FuncStmt
ffor :: c -> CodeExpr -> [FuncStmt] -> FuncStmt
ffor v :: c
v end :: CodeExpr
end = c -> CodeExpr -> CodeExpr -> CodeExpr -> [FuncStmt] -> FuncStmt
forall c.
(Quantity c, MayHaveUnit c) =>
c -> CodeExpr -> CodeExpr -> CodeExpr -> [FuncStmt] -> FuncStmt
fforRange c
v (Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
CE.int 0) CodeExpr
end (Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
CE.int 1)

-- | Define a for-loop. 'Quantity' is for the iteration variable, and 3 'CodeExpr's
-- for the start, stop, step numbers.
-- ['FuncStmt'] is for the loop body.
fforRange :: (Quantity c, MayHaveUnit c) => c -> CodeExpr -> CodeExpr 
  -> CodeExpr -> [FuncStmt] -> FuncStmt
fforRange :: c -> CodeExpr -> CodeExpr -> CodeExpr -> [FuncStmt] -> FuncStmt
fforRange v :: c
v = CodeVarChunk
-> CodeExpr -> CodeExpr -> CodeExpr -> [FuncStmt] -> FuncStmt
FFor (c -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar c
v)

-- | Define a declare-define statement.
fDecDef :: (Quantity c, MayHaveUnit c) => c -> CodeExpr -> FuncStmt
fDecDef :: c -> CodeExpr -> FuncStmt
fDecDef v :: c
v  = CodeVarChunk -> CodeExpr -> FuncStmt
FDecDef (c -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar c
v)

-- | Returns the list of 'CodeVarChunk's that are used in the list of 'FuncStmt's 
-- but are not declared in any of the 'FuncStmt's.
fstdecl :: ChunkDB -> [FuncStmt] -> [CodeVarChunk]
fstdecl :: ChunkDB -> [FuncStmt] -> [CodeVarChunk]
fstdecl ctx :: ChunkDB
ctx fsts :: [FuncStmt]
fsts = [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a]
nub ((FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
ctx) [FuncStmt]
fsts) [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
\\ [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a]
nub ((FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
ctx) [FuncStmt]
fsts) 
  where
    fstvars :: ChunkDB -> FuncStmt -> [CodeVarChunk]
    fstvars :: ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars sm :: ChunkDB
sm (FDecDef cch :: CodeVarChunk
cch e :: CodeExpr
e) = CodeVarChunk
cchCodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
:CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
e ChunkDB
sm
    fstvars sm :: ChunkDB
sm (FFuncDef cch :: CodeFuncChunk
cch ps :: [ParameterChunk]
ps sts :: [FuncStmt]
sts) = CodeFuncChunk -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar CodeFuncChunk
cch CodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
: (ParameterChunk -> CodeVarChunk)
-> [ParameterChunk] -> [CodeVarChunk]
forall a b. (a -> b) -> [a] -> [b]
map ParameterChunk -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar [ParameterChunk]
ps 
      [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm) [FuncStmt]
sts
    fstvars sm :: ChunkDB
sm (FAsg cch :: CodeVarChunk
cch e :: CodeExpr
e) = CodeVarChunk
cchCodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
:CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
e ChunkDB
sm
    fstvars sm :: ChunkDB
sm (FAsgIndex cch :: CodeVarChunk
cch _ e :: CodeExpr
e) = CodeVarChunk
cchCodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
:CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
e ChunkDB
sm
    fstvars sm :: ChunkDB
sm (FFor cch :: CodeVarChunk
cch s :: CodeExpr
s e :: CodeExpr
e st :: CodeExpr
st fs :: [FuncStmt]
fs) = [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a]
nub ([CodeVarChunk] -> [CodeVarChunk])
-> [CodeVarChunk] -> [CodeVarChunk]
forall a b. (a -> b) -> a -> b
$ CodeVarChunk
cch CodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
: CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
e ChunkDB
sm [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
s ChunkDB
sm
       [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
st ChunkDB
sm [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm) [FuncStmt]
fs
    fstvars sm :: ChunkDB
sm (FForEach cch :: CodeVarChunk
cch e :: CodeExpr
e fs :: [FuncStmt]
fs) = [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a]
nub (CodeVarChunk
cch CodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
: CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
e ChunkDB
sm [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm) [FuncStmt]
fs)
    fstvars sm :: ChunkDB
sm (FWhile e :: CodeExpr
e fs :: [FuncStmt]
fs) = CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
e ChunkDB
sm [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm) [FuncStmt]
fs
    fstvars sm :: ChunkDB
sm (FCond e :: CodeExpr
e tfs :: [FuncStmt]
tfs efs :: [FuncStmt]
efs) = CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
e ChunkDB
sm [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm) [FuncStmt]
tfs [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm) [FuncStmt]
efs
    fstvars sm :: ChunkDB
sm (FRet e :: CodeExpr
e) = CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
e ChunkDB
sm
    fstvars sm :: ChunkDB
sm (FTry tfs :: [FuncStmt]
tfs cfs :: [FuncStmt]
cfs) = (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm) [FuncStmt]
tfs [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm ) [FuncStmt]
cfs
    fstvars _  (FThrow _) = [] -- is this right?
    fstvars _  FContinue = []
    fstvars sm :: ChunkDB
sm (FVal v :: CodeExpr
v) = CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars' CodeExpr
v ChunkDB
sm
    fstvars sm :: ChunkDB
sm (FMulti ss :: [FuncStmt]
ss) = (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
fstvars ChunkDB
sm) [FuncStmt]
ss
    fstvars sm :: ChunkDB
sm (FAppend a :: CodeExpr
a b :: CodeExpr
b) = [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a]
nub (CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars CodeExpr
a ChunkDB
sm [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ CodeExpr -> ChunkDB -> [CodeVarChunk]
codevars CodeExpr
b ChunkDB
sm)

    declared :: ChunkDB -> FuncStmt -> [CodeVarChunk]
    declared :: ChunkDB -> FuncStmt -> [CodeVarChunk]
declared _  (FDecDef cch :: CodeVarChunk
cch _) = [CodeVarChunk
cch]
    declared sm :: ChunkDB
sm (FFuncDef cch :: CodeFuncChunk
cch ps :: [ParameterChunk]
ps sts :: [FuncStmt]
sts) = CodeFuncChunk -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar CodeFuncChunk
cch CodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
: (ParameterChunk -> CodeVarChunk)
-> [ParameterChunk] -> [CodeVarChunk]
forall a b. (a -> b) -> [a] -> [b]
map ParameterChunk -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar [ParameterChunk]
ps 
      [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
sts
    declared _  (FAsg _ _) = []
    declared _  FAsgIndex {} = []
    declared sm :: ChunkDB
sm (FFor cch :: CodeVarChunk
cch _ _ _ fs :: [FuncStmt]
fs) = CodeVarChunk
cch CodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
: (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
fs
    declared sm :: ChunkDB
sm (FForEach cch :: CodeVarChunk
cch _ fs :: [FuncStmt]
fs) = CodeVarChunk
cch CodeVarChunk -> [CodeVarChunk] -> [CodeVarChunk]
forall a. a -> [a] -> [a]
: (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
fs
    declared sm :: ChunkDB
sm (FWhile _ fs :: [FuncStmt]
fs) = (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
fs
    declared sm :: ChunkDB
sm (FCond _ tfs :: [FuncStmt]
tfs efs :: [FuncStmt]
efs) = (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
tfs [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
efs
    declared _  (FRet _) = []
    declared sm :: ChunkDB
sm (FTry tfs :: [FuncStmt]
tfs cfs :: [FuncStmt]
cfs) = (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
tfs [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
cfs
    declared _  (FThrow _) = [] -- is this right?
    declared _  FContinue = []
    declared _  (FVal _) = []
    declared sm :: ChunkDB
sm (FMulti ss :: [FuncStmt]
ss) = (FuncStmt -> [CodeVarChunk]) -> [FuncStmt] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ChunkDB -> FuncStmt -> [CodeVarChunk]
declared ChunkDB
sm) [FuncStmt]
ss
    declared _  (FAppend _ _) = []

-- | Gets the name of a function. 
fname :: Func -> Name
fname :: Func -> Name
fname (FDef (FuncDef n :: Name
n _ _ _ _ _)) = Name
n
fname (FDef (CtorDef n :: Name
n _ _ _ _)) = Name
n
fname (FData (FuncData n :: Name
n _ _)) = Name
n