{- -----------------------------------------------------------------------------
Copyright 2019-2023 Kevin P. Barry

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
----------------------------------------------------------------------------- -}

-- Author: Kevin P. Barry [ta0kira@gmail.com]

{-# LANGUAGE Safe #-}

module Types.Procedure (
  ArgValues(..),
  Assignable(..),
  AssignmentType(..),
  ExecutableProcedure(..),
  Expression(..),
  ExpressionStart(..),
  ExpressionType,
  FunctionCall(..),
  FunctionQualifier(..),
  FunctionSpec(..),
  IfElifElse(..),
  InputValue(..),
  InstanceOrInferred(..),
  IteratedLoop(..),
  MacroExpression(..),
  MacroName(..),
  Operator(..),
  OutputValue(..),
  PragmaProcedure(..),
  Procedure(..),
  ReturnValues(..),
  ScopedBlock(..),
  Statement(..),
  TestProcedure(..),
  TraceType(..),
  ValueCallType(..),
  ValueLiteral(..),
  ValueOperation(..),
  VariableName(..),
  VoidExpression(..),
  assignableName,
  getExpressionContext,
  getOperatorContext,
  getOperatorName,
  getStatementContext,
  inputValueName,
  isAssignableDiscard,
  isDiscardedInput,
  isFunctionOperator,
  isNoTrace,
  isTraceCreation,
  isRawCodeLine,
  isUnnamedReturns,
) where

import Data.List (intercalate)

import Base.Positional
import Types.Builtin
import Types.TypeCategory
import Types.TypeInstance


-- NOTE: Requires FunctionType and SymbolScope to compile, but those might not
-- be available when this needs to be parsed.
data ExecutableProcedure c =
  ExecutableProcedure {
    forall c. ExecutableProcedure c -> [c]
epContext :: [c],
    forall c. ExecutableProcedure c -> [PragmaProcedure c]
epPragmas :: [PragmaProcedure c],
    forall c. ExecutableProcedure c -> [c]
epEnd :: [c],
    forall c. ExecutableProcedure c -> FunctionName
epName :: FunctionName,
    forall c. ExecutableProcedure c -> ArgValues c
epArgs :: ArgValues c,
    forall c. ExecutableProcedure c -> ReturnValues c
epReturns :: ReturnValues c,
    forall c. ExecutableProcedure c -> Procedure c
epProcedure :: Procedure c
  }
  deriving (Int -> ExecutableProcedure c -> ShowS
forall c. Show c => Int -> ExecutableProcedure c -> ShowS
forall c. Show c => [ExecutableProcedure c] -> ShowS
forall c. Show c => ExecutableProcedure c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExecutableProcedure c] -> ShowS
$cshowList :: forall c. Show c => [ExecutableProcedure c] -> ShowS
show :: ExecutableProcedure c -> String
$cshow :: forall c. Show c => ExecutableProcedure c -> String
showsPrec :: Int -> ExecutableProcedure c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> ExecutableProcedure c -> ShowS
Show) -- TODO: Remove Show? Or add proper formatting.

data ArgValues c =
  ArgValues {
    forall c. ArgValues c -> [c]
avContext :: [c],
    forall c. ArgValues c -> Positional (InputValue c)
avNames :: Positional (InputValue c)
  }

instance Show c => Show (ArgValues c) where
  show :: ArgValues c -> String
show (ArgValues [c]
c Positional (InputValue c)
v) =
    String
"(" forall a. [a] -> [a] -> [a]
++ forall a. [a] -> [[a]] -> [a]
intercalate String
",\n" (forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ forall a. Positional a -> [a]
pValues Positional (InputValue c)
v) forall a. [a] -> [a] -> [a]
++ String
")" forall a. [a] -> [a] -> [a]
++
    String
" /*" forall a. [a] -> [a] -> [a]
++ forall a. Show a => [a] -> String
formatFullContext [c]
c forall a. [a] -> [a] -> [a]
++ String
"*/"

data ReturnValues c =
  NamedReturns {
    forall c. ReturnValues c -> [c]
nrContext :: [c],
    forall c. ReturnValues c -> Positional (OutputValue c)
nrNames :: Positional (OutputValue c)
  } |
  UnnamedReturns {
    forall c. ReturnValues c -> [c]
urContext :: [c]
  }

isUnnamedReturns :: ReturnValues c -> Bool
isUnnamedReturns :: forall c. ReturnValues c -> Bool
isUnnamedReturns (UnnamedReturns [c]
_) = Bool
True
isUnnamedReturns ReturnValues c
_                  = Bool
False

instance Show c => Show (ReturnValues c) where
  show :: ReturnValues c -> String
show (NamedReturns [c]
c Positional (OutputValue c)
v) =
    String
"(" forall a. [a] -> [a] -> [a]
++ forall a. [a] -> [[a]] -> [a]
intercalate String
",\n" (forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ forall a. Positional a -> [a]
pValues Positional (OutputValue c)
v) forall a. [a] -> [a] -> [a]
++ String
")" forall a. [a] -> [a] -> [a]
++
    String
" /*" forall a. [a] -> [a] -> [a]
++ forall a. Show a => [a] -> String
formatFullContext [c]
c forall a. [a] -> [a] -> [a]
++ String
"*/"
  show (UnnamedReturns [c]
c) = String
"/*unnamed returns: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => [a] -> String
formatFullContext [c]
c forall a. [a] -> [a] -> [a]
++ String
"*/"

data VariableName =
  VariableName {
    VariableName -> String
vnName :: String
  } |
  VariableSelf
  deriving (VariableName -> VariableName -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: VariableName -> VariableName -> Bool
$c/= :: VariableName -> VariableName -> Bool
== :: VariableName -> VariableName -> Bool
$c== :: VariableName -> VariableName -> Bool
Eq,Eq VariableName
VariableName -> VariableName -> Bool
VariableName -> VariableName -> Ordering
VariableName -> VariableName -> VariableName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: VariableName -> VariableName -> VariableName
$cmin :: VariableName -> VariableName -> VariableName
max :: VariableName -> VariableName -> VariableName
$cmax :: VariableName -> VariableName -> VariableName
>= :: VariableName -> VariableName -> Bool
$c>= :: VariableName -> VariableName -> Bool
> :: VariableName -> VariableName -> Bool
$c> :: VariableName -> VariableName -> Bool
<= :: VariableName -> VariableName -> Bool
$c<= :: VariableName -> VariableName -> Bool
< :: VariableName -> VariableName -> Bool
$c< :: VariableName -> VariableName -> Bool
compare :: VariableName -> VariableName -> Ordering
$ccompare :: VariableName -> VariableName -> Ordering
Ord)

instance Show VariableName where
  show :: VariableName -> String
show (VariableName String
n) = String
n
  show VariableName
VariableSelf     = String
"self"

data InputValue c =
  InputValue {
    forall c. InputValue c -> [c]
ivContext :: [c],
    forall c. InputValue c -> VariableName
ivName :: VariableName
  } |
  DiscardInput {
    forall c. InputValue c -> [c]
iiContext :: [c]
  }

inputValueName :: InputValue c -> VariableName
inputValueName :: forall c. InputValue c -> VariableName
inputValueName (DiscardInput [c]
_) = VariableName
discardInputName
inputValueName (InputValue [c]
_ VariableName
n) = VariableName
n

isDiscardedInput :: InputValue c -> Bool
isDiscardedInput :: forall c. InputValue c -> Bool
isDiscardedInput (DiscardInput [c]
_) = Bool
True
isDiscardedInput InputValue c
_                = Bool
False

discardInputName :: VariableName
discardInputName :: VariableName
discardInputName = String -> VariableName
VariableName String
"_"

instance Show c => Show (InputValue c) where
  show :: InputValue c -> String
show (InputValue [c]
c VariableName
v) = forall a. Show a => a -> String
show VariableName
v forall a. [a] -> [a] -> [a]
++ String
" /*" forall a. [a] -> [a] -> [a]
++ forall a. Show a => [a] -> String
formatFullContext [c]
c forall a. [a] -> [a] -> [a]
++ String
"*/"
  show (DiscardInput [c]
c) = String
"_" forall a. [a] -> [a] -> [a]
++ String
" /*" forall a. [a] -> [a] -> [a]
++ forall a. Show a => [a] -> String
formatFullContext [c]
c forall a. [a] -> [a] -> [a]
++ String
"*/"

data OutputValue c =
  OutputValue {
    forall c. OutputValue c -> [c]
ovContext :: [c],
    forall c. OutputValue c -> VariableName
ovName :: VariableName
  }

instance Show c => Show (OutputValue c) where
  show :: OutputValue c -> String
show (OutputValue [c]
c VariableName
v) = forall a. Show a => a -> String
show VariableName
v forall a. [a] -> [a] -> [a]
++ String
" /*" forall a. [a] -> [a] -> [a]
++ forall a. Show a => [a] -> String
formatFullContext [c]
c forall a. [a] -> [a] -> [a]
++ String
"*/"

data TestProcedure c =
  TestProcedure {
    forall c. TestProcedure c -> [c]
tpContext :: [c],
    forall c. TestProcedure c -> FunctionName
tpName :: FunctionName,
    forall c. TestProcedure c -> Bool
tpDisableCoverage :: Bool,
    forall c. TestProcedure c -> Procedure c
tpProcedure :: Procedure c
  }
  deriving (Int -> TestProcedure c -> ShowS
forall c. Show c => Int -> TestProcedure c -> ShowS
forall c. Show c => [TestProcedure c] -> ShowS
forall c. Show c => TestProcedure c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TestProcedure c] -> ShowS
$cshowList :: forall c. Show c => [TestProcedure c] -> ShowS
show :: TestProcedure c -> String
$cshow :: forall c. Show c => TestProcedure c -> String
showsPrec :: Int -> TestProcedure c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> TestProcedure c -> ShowS
Show)

data Procedure c =
  Procedure [c] [Statement c]
  deriving (Int -> Procedure c -> ShowS
forall c. Show c => Int -> Procedure c -> ShowS
forall c. Show c => [Procedure c] -> ShowS
forall c. Show c => Procedure c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Procedure c] -> ShowS
$cshowList :: forall c. Show c => [Procedure c] -> ShowS
show :: Procedure c -> String
$cshow :: forall c. Show c => Procedure c -> String
showsPrec :: Int -> Procedure c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> Procedure c -> ShowS
Show)

data Statement c =
  EmptyReturn [c] |
  ExplicitReturn [c] (Positional (Expression c)) |
  LoopBreak [c] |
  LoopContinue [c] |
  FailCall [c] (Expression c) |
  ExitCall [c] (Expression c) |
  RawFailCall String |
  IgnoreValues [c] (Expression c) |
  Assignment [c] (Positional (Assignable c)) (Expression c) |
  AssignmentEmpty [c] VariableName (Expression c) |
  VariableSwap [c] (OutputValue c) (OutputValue c) |
  DeferredVariables [c] [Assignable c] |
  NoValueExpression [c] (VoidExpression c) |
  MarkReadOnly [c] [VariableName] |
  MarkHidden [c] [VariableName] |
  ValidateRefs [c] [VariableName] |
  ShowVariable [c] ValueType VariableName |
  RawCodeLine String
  deriving (Int -> Statement c -> ShowS
forall c. Show c => Int -> Statement c -> ShowS
forall c. Show c => [Statement c] -> ShowS
forall c. Show c => Statement c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Statement c] -> ShowS
$cshowList :: forall c. Show c => [Statement c] -> ShowS
show :: Statement c -> String
$cshow :: forall c. Show c => Statement c -> String
showsPrec :: Int -> Statement c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> Statement c -> ShowS
Show)

isRawCodeLine :: Statement c -> Bool
isRawCodeLine :: forall c. Statement c -> Bool
isRawCodeLine (RawCodeLine String
_) = Bool
True
isRawCodeLine Statement c
_               = Bool
False

getStatementContext :: Statement c -> [c]
getStatementContext :: forall c. Statement c -> [c]
getStatementContext (EmptyReturn [c]
c)         = [c]
c
getStatementContext (ExplicitReturn [c]
c Positional (Expression c)
_)    = [c]
c
getStatementContext (LoopBreak [c]
c)           = [c]
c
getStatementContext (LoopContinue [c]
c)        = [c]
c
getStatementContext (FailCall [c]
c Expression c
_)          = [c]
c
getStatementContext (ExitCall [c]
c Expression c
_)          = [c]
c
getStatementContext (RawFailCall String
_)         = []
getStatementContext (IgnoreValues [c]
c Expression c
_)      = [c]
c
getStatementContext (Assignment [c]
c Positional (Assignable c)
_ Expression c
_)      = [c]
c
getStatementContext (AssignmentEmpty [c]
c VariableName
_ Expression c
_) = [c]
c
getStatementContext (VariableSwap [c]
c OutputValue c
_ OutputValue c
_)    = [c]
c
getStatementContext (DeferredVariables [c]
c [Assignable c]
_) = [c]
c
getStatementContext (NoValueExpression [c]
c VoidExpression c
_) = [c]
c
getStatementContext (MarkReadOnly [c]
c [VariableName]
_)      = [c]
c
getStatementContext (MarkHidden [c]
c [VariableName]
_)        = [c]
c
getStatementContext (ValidateRefs [c]
c [VariableName]
_)      = [c]
c
getStatementContext (ShowVariable [c]
_ ValueType
_ VariableName
_)    = []
getStatementContext (RawCodeLine String
_)         = []

data Assignable c =
  CreateVariable [c] ValueType VariableName |
  ExistingVariable (InputValue c)
  deriving (Int -> Assignable c -> ShowS
forall c. Show c => Int -> Assignable c -> ShowS
forall c. Show c => [Assignable c] -> ShowS
forall c. Show c => Assignable c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Assignable c] -> ShowS
$cshowList :: forall c. Show c => [Assignable c] -> ShowS
show :: Assignable c -> String
$cshow :: forall c. Show c => Assignable c -> String
showsPrec :: Int -> Assignable c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> Assignable c -> ShowS
Show)

assignableName :: Assignable c -> VariableName
assignableName :: forall c. Assignable c -> VariableName
assignableName (CreateVariable [c]
_ ValueType
_ VariableName
n)              = VariableName
n
assignableName (ExistingVariable (InputValue [c]
_ VariableName
n)) = VariableName
n
assignableName Assignable c
_                                   = VariableName
discardInputName

isAssignableDiscard :: Assignable c -> Bool
isAssignableDiscard :: forall c. Assignable c -> Bool
isAssignableDiscard (CreateVariable [c]
_ ValueType
_ VariableName
_) = Bool
False
isAssignableDiscard (ExistingVariable InputValue c
v)   = forall c. InputValue c -> Bool
isDiscardedInput InputValue c
v

data VoidExpression c =
  Conditional (IfElifElse c) |
  Loop (IteratedLoop c) |
  WithScope (ScopedBlock c) |
  Unconditional (Procedure c) |
  LineComment String
  deriving (Int -> VoidExpression c -> ShowS
forall c. Show c => Int -> VoidExpression c -> ShowS
forall c. Show c => [VoidExpression c] -> ShowS
forall c. Show c => VoidExpression c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [VoidExpression c] -> ShowS
$cshowList :: forall c. Show c => [VoidExpression c] -> ShowS
show :: VoidExpression c -> String
$cshow :: forall c. Show c => VoidExpression c -> String
showsPrec :: Int -> VoidExpression c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> VoidExpression c -> ShowS
Show)

data IfElifElse c =
  IfStatement [c] (Expression c) (Procedure c) (IfElifElse c) |
  ElseStatement [c] (Procedure c) |
  TerminateConditional
  deriving (Int -> IfElifElse c -> ShowS
forall c. Show c => Int -> IfElifElse c -> ShowS
forall c. Show c => [IfElifElse c] -> ShowS
forall c. Show c => IfElifElse c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IfElifElse c] -> ShowS
$cshowList :: forall c. Show c => [IfElifElse c] -> ShowS
show :: IfElifElse c -> String
$cshow :: forall c. Show c => IfElifElse c -> String
showsPrec :: Int -> IfElifElse c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> IfElifElse c -> ShowS
Show)

data IteratedLoop c =
  WhileLoop [c] (Expression c) (Procedure c) (Maybe (Procedure c)) |
  TraverseLoop [c] (Expression c) [c] (Assignable c) (Procedure c) (Maybe (Procedure c))
  deriving (Int -> IteratedLoop c -> ShowS
forall c. Show c => Int -> IteratedLoop c -> ShowS
forall c. Show c => [IteratedLoop c] -> ShowS
forall c. Show c => IteratedLoop c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IteratedLoop c] -> ShowS
$cshowList :: forall c. Show c => [IteratedLoop c] -> ShowS
show :: IteratedLoop c -> String
$cshow :: forall c. Show c => IteratedLoop c -> String
showsPrec :: Int -> IteratedLoop c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> IteratedLoop c -> ShowS
Show)

data ScopedBlock c =
  ScopedBlock [c] (Procedure c) (Maybe (Procedure c)) [c] (Statement c)
  deriving (Int -> ScopedBlock c -> ShowS
forall c. Show c => Int -> ScopedBlock c -> ShowS
forall c. Show c => [ScopedBlock c] -> ShowS
forall c. Show c => ScopedBlock c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ScopedBlock c] -> ShowS
$cshowList :: forall c. Show c => [ScopedBlock c] -> ShowS
show :: ScopedBlock c -> String
$cshow :: forall c. Show c => ScopedBlock c -> String
showsPrec :: Int -> ScopedBlock c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> ScopedBlock c -> ShowS
Show)

data Expression c =
  Expression [c] (ExpressionStart c) [ValueOperation c] |
  Literal (ValueLiteral c) |
  UnaryExpression [c] (Operator c) (Expression c) |
  InfixExpression [c] (Expression c) (Operator c) (Expression c) |
  RawExpression ExpressionType ExpressionValue |
  DelegatedFunctionCall [c] (FunctionSpec c) |
  DelegatedInitializeValue [c] (Maybe TypeInstance)
  deriving (Int -> Expression c -> ShowS
forall c. Show c => Int -> Expression c -> ShowS
forall c. Show c => [Expression c] -> ShowS
forall c. Show c => Expression c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Expression c] -> ShowS
$cshowList :: forall c. Show c => [Expression c] -> ShowS
show :: Expression c -> String
$cshow :: forall c. Show c => Expression c -> String
showsPrec :: Int -> Expression c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> Expression c -> ShowS
Show)

type ExpressionType = Positional ValueType

data FunctionQualifier c =
  CategoryFunction [c] CategoryName |
  TypeFunction [c] TypeInstanceOrParam |
  -- TODO: Does this need to allow conversion calls?
  ValueFunction [c] (Expression c) |
  UnqualifiedFunction
  deriving (Int -> FunctionQualifier c -> ShowS
forall c. Show c => Int -> FunctionQualifier c -> ShowS
forall c. Show c => [FunctionQualifier c] -> ShowS
forall c. Show c => FunctionQualifier c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FunctionQualifier c] -> ShowS
$cshowList :: forall c. Show c => [FunctionQualifier c] -> ShowS
show :: FunctionQualifier c -> String
$cshow :: forall c. Show c => FunctionQualifier c -> String
showsPrec :: Int -> FunctionQualifier c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> FunctionQualifier c -> ShowS
Show)

data InstanceOrInferred c =
  AssignedInstance [c] GeneralInstance |
  InferredInstance [c]

instance Show c => Show (InstanceOrInferred c) where
  show :: InstanceOrInferred c -> String
show (AssignedInstance [c]
_ GeneralInstance
t) = forall a. Show a => a -> String
show GeneralInstance
t
  show (InferredInstance [c]
_)   = String
"?"

data FunctionSpec c =
  FunctionSpec [c] (FunctionQualifier c) FunctionName (Positional (InstanceOrInferred c))
  deriving (Int -> FunctionSpec c -> ShowS
forall c. Show c => Int -> FunctionSpec c -> ShowS
forall c. Show c => [FunctionSpec c] -> ShowS
forall c. Show c => FunctionSpec c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FunctionSpec c] -> ShowS
$cshowList :: forall c. Show c => [FunctionSpec c] -> ShowS
show :: FunctionSpec c -> String
$cshow :: forall c. Show c => FunctionSpec c -> String
showsPrec :: Int -> FunctionSpec c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> FunctionSpec c -> ShowS
Show)

data Operator c =
  NamedOperator [c] String |
  FunctionOperator [c] (FunctionSpec c)
  deriving (Int -> Operator c -> ShowS
forall c. Show c => Int -> Operator c -> ShowS
forall c. Show c => [Operator c] -> ShowS
forall c. Show c => Operator c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Operator c] -> ShowS
$cshowList :: forall c. Show c => [Operator c] -> ShowS
show :: Operator c -> String
$cshow :: forall c. Show c => Operator c -> String
showsPrec :: Int -> Operator c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> Operator c -> ShowS
Show)

getOperatorContext :: Operator c -> [c]
getOperatorContext :: forall c. Operator c -> [c]
getOperatorContext (NamedOperator [c]
c String
_)    = [c]
c
getOperatorContext (FunctionOperator [c]
c FunctionSpec c
_) = [c]
c

isFunctionOperator :: Operator c -> Bool
isFunctionOperator :: forall c. Operator c -> Bool
isFunctionOperator (FunctionOperator [c]
_ FunctionSpec c
_) = Bool
True
isFunctionOperator Operator c
_                      = Bool
False

getOperatorName :: Operator c -> FunctionName
getOperatorName :: forall c. Operator c -> FunctionName
getOperatorName (NamedOperator [c]
_ String
n)                         = String -> FunctionName
FunctionName String
n
getOperatorName (FunctionOperator [c]
_ (FunctionSpec [c]
_ FunctionQualifier c
_ FunctionName
n Positional (InstanceOrInferred c)
_)) = FunctionName
n

getExpressionContext :: Expression c -> [c]
getExpressionContext :: forall c. Expression c -> [c]
getExpressionContext (Expression [c]
c ExpressionStart c
_ [ValueOperation c]
_)             = [c]
c
getExpressionContext (Literal ValueLiteral c
l)                    = forall c. ValueLiteral c -> [c]
getValueLiteralContext ValueLiteral c
l
getExpressionContext (UnaryExpression [c]
c Operator c
_ Expression c
_)        = [c]
c
getExpressionContext (InfixExpression [c]
c Expression c
_ Operator c
_ Expression c
_)      = [c]
c
getExpressionContext (RawExpression ExpressionType
_ ExpressionValue
_)            = []
getExpressionContext (DelegatedFunctionCall [c]
c FunctionSpec c
_)    = [c]
c
getExpressionContext (DelegatedInitializeValue [c]
c Maybe TypeInstance
_) = [c]
c

data FunctionCall c =
  FunctionCall [c] FunctionName (Positional (InstanceOrInferred c)) (Positional (Maybe (CallArgLabel c), Expression c))
  deriving (Int -> FunctionCall c -> ShowS
forall c. Show c => Int -> FunctionCall c -> ShowS
forall c. Show c => [FunctionCall c] -> ShowS
forall c. Show c => FunctionCall c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FunctionCall c] -> ShowS
$cshowList :: forall c. Show c => [FunctionCall c] -> ShowS
show :: FunctionCall c -> String
$cshow :: forall c. Show c => FunctionCall c -> String
showsPrec :: Int -> FunctionCall c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> FunctionCall c -> ShowS
Show)

data AssignmentType =
  AlwaysAssign |
  AssignIfEmpty
  deriving (AssignmentType -> AssignmentType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AssignmentType -> AssignmentType -> Bool
$c/= :: AssignmentType -> AssignmentType -> Bool
== :: AssignmentType -> AssignmentType -> Bool
$c== :: AssignmentType -> AssignmentType -> Bool
Eq,Int -> AssignmentType -> ShowS
[AssignmentType] -> ShowS
AssignmentType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AssignmentType] -> ShowS
$cshowList :: [AssignmentType] -> ShowS
show :: AssignmentType -> String
$cshow :: AssignmentType -> String
showsPrec :: Int -> AssignmentType -> ShowS
$cshowsPrec :: Int -> AssignmentType -> ShowS
Show)

data ExpressionStart c =
  NamedVariable (OutputValue c) |
  NamedMacro [c] MacroName |
  ExpressionMacro [c] MacroExpression |
  CategoryCall [c] CategoryName (FunctionCall c) |
  TypeCall [c] TypeInstanceOrParam (FunctionCall c) |
  UnqualifiedCall [c] (FunctionCall c) |
  BuiltinCall [c] (FunctionCall c) |
  ParensExpression [c] (Expression c) |
  InlineAssignment [c] VariableName AssignmentType (Expression c) |
  InitializeValue [c] (Maybe TypeInstance) (Positional (Expression c)) |
  UnambiguousLiteral (ValueLiteral c)
  deriving (Int -> ExpressionStart c -> ShowS
forall c. Show c => Int -> ExpressionStart c -> ShowS
forall c. Show c => [ExpressionStart c] -> ShowS
forall c. Show c => ExpressionStart c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExpressionStart c] -> ShowS
$cshowList :: forall c. Show c => [ExpressionStart c] -> ShowS
show :: ExpressionStart c -> String
$cshow :: forall c. Show c => ExpressionStart c -> String
showsPrec :: Int -> ExpressionStart c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> ExpressionStart c -> ShowS
Show)

data ValueLiteral c =
  StringLiteral [c] String |
  CharLiteral [c] Char |
  IntegerLiteral [c] Bool Integer |
  DecimalLiteral [c] Integer Integer Integer |
  BoolLiteral [c] Bool |
  EmptyLiteral [c]
  deriving (Int -> ValueLiteral c -> ShowS
forall c. Show c => Int -> ValueLiteral c -> ShowS
forall c. Show c => [ValueLiteral c] -> ShowS
forall c. Show c => ValueLiteral c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ValueLiteral c] -> ShowS
$cshowList :: forall c. Show c => [ValueLiteral c] -> ShowS
show :: ValueLiteral c -> String
$cshow :: forall c. Show c => ValueLiteral c -> String
showsPrec :: Int -> ValueLiteral c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> ValueLiteral c -> ShowS
Show)

getValueLiteralContext :: ValueLiteral c -> [c]
getValueLiteralContext :: forall c. ValueLiteral c -> [c]
getValueLiteralContext (StringLiteral [c]
c String
_)      = [c]
c
getValueLiteralContext (CharLiteral [c]
c Char
_)        = [c]
c
getValueLiteralContext (IntegerLiteral [c]
c Bool
_ Integer
_)   = [c]
c
getValueLiteralContext (DecimalLiteral [c]
c Integer
_ Integer
_ Integer
_) = [c]
c
getValueLiteralContext (BoolLiteral [c]
c Bool
_)        = [c]
c
getValueLiteralContext (EmptyLiteral [c]
c)         = [c]
c

data ValueCallType =
  AlwaysCall |
  CallUnlessEmpty
  deriving (ValueCallType -> ValueCallType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ValueCallType -> ValueCallType -> Bool
$c/= :: ValueCallType -> ValueCallType -> Bool
== :: ValueCallType -> ValueCallType -> Bool
$c== :: ValueCallType -> ValueCallType -> Bool
Eq,Int -> ValueCallType -> ShowS
[ValueCallType] -> ShowS
ValueCallType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ValueCallType] -> ShowS
$cshowList :: [ValueCallType] -> ShowS
show :: ValueCallType -> String
$cshow :: ValueCallType -> String
showsPrec :: Int -> ValueCallType -> ShowS
$cshowsPrec :: Int -> ValueCallType -> ShowS
Show)

data ValueOperation c =
  TypeConversion [c] GeneralInstance |
  ValueCall [c] ValueCallType (FunctionCall c) |
  SelectReturn [c] Int
  deriving (Int -> ValueOperation c -> ShowS
forall c. Show c => Int -> ValueOperation c -> ShowS
forall c. Show c => [ValueOperation c] -> ShowS
forall c. Show c => ValueOperation c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ValueOperation c] -> ShowS
$cshowList :: forall c. Show c => [ValueOperation c] -> ShowS
show :: ValueOperation c -> String
$cshow :: forall c. Show c => ValueOperation c -> String
showsPrec :: Int -> ValueOperation c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> ValueOperation c -> ShowS
Show)

newtype MacroName =
  MacroName {
    MacroName -> String
mnName :: String
  }
  deriving (MacroName -> MacroName -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MacroName -> MacroName -> Bool
$c/= :: MacroName -> MacroName -> Bool
== :: MacroName -> MacroName -> Bool
$c== :: MacroName -> MacroName -> Bool
Eq,Eq MacroName
MacroName -> MacroName -> Bool
MacroName -> MacroName -> Ordering
MacroName -> MacroName -> MacroName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MacroName -> MacroName -> MacroName
$cmin :: MacroName -> MacroName -> MacroName
max :: MacroName -> MacroName -> MacroName
$cmax :: MacroName -> MacroName -> MacroName
>= :: MacroName -> MacroName -> Bool
$c>= :: MacroName -> MacroName -> Bool
> :: MacroName -> MacroName -> Bool
$c> :: MacroName -> MacroName -> Bool
<= :: MacroName -> MacroName -> Bool
$c<= :: MacroName -> MacroName -> Bool
< :: MacroName -> MacroName -> Bool
$c< :: MacroName -> MacroName -> Bool
compare :: MacroName -> MacroName -> Ordering
$ccompare :: MacroName -> MacroName -> Ordering
Ord)

instance Show MacroName where
  show :: MacroName -> String
show = MacroName -> String
mnName

data TraceType = NoTrace | TraceCreation deriving (Int -> TraceType -> ShowS
[TraceType] -> ShowS
TraceType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TraceType] -> ShowS
$cshowList :: [TraceType] -> ShowS
show :: TraceType -> String
$cshow :: TraceType -> String
showsPrec :: Int -> TraceType -> ShowS
$cshowsPrec :: Int -> TraceType -> ShowS
Show)

data MacroExpression =
  MacroCallTrace
  deriving (Int -> MacroExpression -> ShowS
[MacroExpression] -> ShowS
MacroExpression -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MacroExpression] -> ShowS
$cshowList :: [MacroExpression] -> ShowS
show :: MacroExpression -> String
$cshow :: MacroExpression -> String
showsPrec :: Int -> MacroExpression -> ShowS
$cshowsPrec :: Int -> MacroExpression -> ShowS
Show)

data PragmaProcedure c =
  PragmaTracing {
    forall c. PragmaProcedure c -> [c]
ptContext :: [c],
    forall c. PragmaProcedure c -> TraceType
ptType :: TraceType
  }
  deriving (Int -> PragmaProcedure c -> ShowS
forall c. Show c => Int -> PragmaProcedure c -> ShowS
forall c. Show c => [PragmaProcedure c] -> ShowS
forall c. Show c => PragmaProcedure c -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PragmaProcedure c] -> ShowS
$cshowList :: forall c. Show c => [PragmaProcedure c] -> ShowS
show :: PragmaProcedure c -> String
$cshow :: forall c. Show c => PragmaProcedure c -> String
showsPrec :: Int -> PragmaProcedure c -> ShowS
$cshowsPrec :: forall c. Show c => Int -> PragmaProcedure c -> ShowS
Show)

isNoTrace :: PragmaProcedure c -> Bool
isNoTrace :: forall c. PragmaProcedure c -> Bool
isNoTrace (PragmaTracing [c]
_ TraceType
NoTrace) = Bool
True
isNoTrace PragmaProcedure c
_                         = Bool
False

isTraceCreation :: PragmaProcedure c -> Bool
isTraceCreation :: forall c. PragmaProcedure c -> Bool
isTraceCreation (PragmaTracing [c]
_ TraceType
TraceCreation) = Bool
True
isTraceCreation PragmaProcedure c
_                               = Bool
False