{-# LANGUAGE DuplicateRecordFields #-}

module Analyzer.AnalyzedAst
  ( module Analyzer.AnalyzedAst,
    UnaryOp (..),
    BinaryOp (..),
    ForGoTo (..),
    IncDec (..),
  )
where

import Data.Text (Text)
import MaybeVoid (MaybeVoid)
import Parser.Ast (BinaryOp (..), ForGoTo (..), IncDec (..), UnaryOp (..))

--------------------------------------------------------Program---------------------------------------------------------

data Program = Program
  { Program -> [VarDecl]
topLevelVarDecls :: [VarDecl],
    Program -> [FunctionDef]
topLevelFunctionDefs :: [FunctionDef]
  }
  deriving (Int -> Program -> ShowS
[Program] -> ShowS
Program -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Program] -> ShowS
$cshowList :: [Program] -> ShowS
show :: Program -> String
$cshow :: Program -> String
showsPrec :: Int -> Program -> ShowS
$cshowsPrec :: Int -> Program -> ShowS
Show)

data FunctionDef = FunctionDef {FunctionDef -> Identifier
funcName :: Identifier, FunctionDef -> Function
func :: Function}
  deriving (Int -> FunctionDef -> ShowS
[FunctionDef] -> ShowS
FunctionDef -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FunctionDef] -> ShowS
$cshowList :: [FunctionDef] -> ShowS
show :: FunctionDef -> String
$cshow :: FunctionDef -> String
showsPrec :: Int -> FunctionDef -> ShowS
$cshowsPrec :: Int -> FunctionDef -> ShowS
Show)

------------------------------------------------------Expressions-------------------------------------------------------

data Expression
  = ExprValue Value
  | ExprIdentifier Identifier
  | ExprUnaryOp UnaryOp Expression
  | ExprBinaryOp BinaryOp Expression Expression
  | ExprArrayAccessByIndex Expression Expression
  | ExprFuncCall Expression [Expression]
  deriving (Int -> Expression -> ShowS
[Expression] -> ShowS
Expression -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Expression] -> ShowS
$cshowList :: [Expression] -> ShowS
show :: Expression -> String
$cshow :: Expression -> String
showsPrec :: Int -> Expression -> ShowS
$cshowsPrec :: Int -> Expression -> ShowS
Show)

-------------------------------------------------------Statements-------------------------------------------------------

data Statement
  = StmtReturn (MaybeVoid Expression)
  | StmtForGoTo ForGoTo
  | StmtFor For
  | StmtVarDecl VarDecl
  | StmtIfElse IfElse
  | StmtBlock Block
  | StmtSimple SimpleStmt
  deriving (Int -> Statement -> ShowS
[Statement] -> ShowS
Statement -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Statement] -> ShowS
$cshowList :: [Statement] -> ShowS
show :: Statement -> String
$cshow :: Statement -> String
showsPrec :: Int -> Statement -> ShowS
$cshowsPrec :: Int -> Statement -> ShowS
Show)

type Block = [Statement]

data For = For {For -> ForHead
forHead :: ForHead, For -> [Statement]
forBody :: Block}
  deriving (Int -> For -> ShowS
[For] -> ShowS
For -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [For] -> ShowS
$cshowList :: [For] -> ShowS
show :: For -> String
$cshow :: For -> String
showsPrec :: Int -> For -> ShowS
$cshowsPrec :: Int -> For -> ShowS
Show)

data ForHead = ForHead
  { ForHead -> Maybe SimpleStmt
forPreStmt :: Maybe SimpleStmt,
    ForHead -> Maybe Expression
forCondition :: Maybe Expression,
    ForHead -> Maybe SimpleStmt
forPostStmt :: Maybe SimpleStmt
  }
  deriving (Int -> ForHead -> ShowS
[ForHead] -> ShowS
ForHead -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ForHead] -> ShowS
$cshowList :: [ForHead] -> ShowS
show :: ForHead -> String
$cshow :: ForHead -> String
showsPrec :: Int -> ForHead -> ShowS
$cshowsPrec :: Int -> ForHead -> ShowS
Show)

data VarDecl = VarDecl {VarDecl -> Identifier
varName :: Identifier, VarDecl -> Expression
varValue :: Expression}
  deriving (Int -> VarDecl -> ShowS
[VarDecl] -> ShowS
VarDecl -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [VarDecl] -> ShowS
$cshowList :: [VarDecl] -> ShowS
show :: VarDecl -> String
$cshow :: VarDecl -> String
showsPrec :: Int -> VarDecl -> ShowS
$cshowsPrec :: Int -> VarDecl -> ShowS
Show)

data IfElse = IfElse
  { IfElse -> Maybe SimpleStmt
ifPreStmt :: Maybe SimpleStmt,
    IfElse -> Expression
ifCondition :: Expression,
    IfElse -> [Statement]
ifBody :: Block,
    IfElse -> Else
elseStmt :: Else
  }
  deriving (Int -> IfElse -> ShowS
[IfElse] -> ShowS
IfElse -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IfElse] -> ShowS
$cshowList :: [IfElse] -> ShowS
show :: IfElse -> String
$cshow :: IfElse -> String
showsPrec :: Int -> IfElse -> ShowS
$cshowsPrec :: Int -> IfElse -> ShowS
Show)

data Else = NoElse | Else Block | Elif IfElse
  deriving (Int -> Else -> ShowS
[Else] -> ShowS
Else -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Else] -> ShowS
$cshowList :: [Else] -> ShowS
show :: Else -> String
$cshow :: Else -> String
showsPrec :: Int -> Else -> ShowS
$cshowsPrec :: Int -> Else -> ShowS
Show)

data SimpleStmt
  = StmtAssignment Lvalue Expression
  | StmtIncDec Lvalue IncDec
  | StmtShortVarDecl Identifier Expression
  | StmtExpression Expression
  deriving (Int -> SimpleStmt -> ShowS
[SimpleStmt] -> ShowS
SimpleStmt -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SimpleStmt] -> ShowS
$cshowList :: [SimpleStmt] -> ShowS
show :: SimpleStmt -> String
$cshow :: SimpleStmt -> String
showsPrec :: Int -> SimpleStmt -> ShowS
$cshowsPrec :: Int -> SimpleStmt -> ShowS
Show)

data Lvalue
  = LvalVar Identifier
  | LvalArrEl Identifier [Expression]
  deriving (Int -> Lvalue -> ShowS
[Lvalue] -> ShowS
Lvalue -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Lvalue] -> ShowS
$cshowList :: [Lvalue] -> ShowS
show :: Lvalue -> String
$cshow :: Lvalue -> String
showsPrec :: Int -> Lvalue -> ShowS
$cshowsPrec :: Int -> Lvalue -> ShowS
Show)

---------------------------------------------------------Values---------------------------------------------------------

data Value
  = ValInt Int
  | ValBool Bool
  | ValString Text
  | ValArray [Expression]
  | ValFunction FunctionValue
  deriving (Int -> Value -> ShowS
[Value] -> ShowS
Value -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Value] -> ShowS
$cshowList :: [Value] -> ShowS
show :: Value -> String
$cshow :: Value -> String
showsPrec :: Int -> Value -> ShowS
$cshowsPrec :: Int -> Value -> ShowS
Show)

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

data Function
  = FuncOrdinary OrdinaryFunction
  | FuncStdLib Identifier
  deriving (Int -> Function -> ShowS
[Function] -> ShowS
Function -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Function] -> ShowS
$cshowList :: [Function] -> ShowS
show :: Function -> String
$cshow :: Function -> String
showsPrec :: Int -> Function -> ShowS
$cshowsPrec :: Int -> Function -> ShowS
Show)

data OrdinaryFunction = OrdinaryFunction {OrdinaryFunction -> [Identifier]
funcParams :: [Identifier], OrdinaryFunction -> [Statement]
funcBody :: Block, OrdinaryFunction -> VoidMark
funcVoidMark :: VoidMark}
  deriving (Int -> OrdinaryFunction -> ShowS
[OrdinaryFunction] -> ShowS
OrdinaryFunction -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OrdinaryFunction] -> ShowS
$cshowList :: [OrdinaryFunction] -> ShowS
show :: OrdinaryFunction -> String
$cshow :: OrdinaryFunction -> String
showsPrec :: Int -> OrdinaryFunction -> ShowS
$cshowsPrec :: Int -> OrdinaryFunction -> ShowS
Show)

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

type Identifier = Text