summaryrefslogtreecommitdiff
path: root/lib/Language/Elna/Intermediate.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Language/Elna/Intermediate.hs')
-rw-r--r--lib/Language/Elna/Intermediate.hs57
1 files changed, 54 insertions, 3 deletions
diff --git a/lib/Language/Elna/Intermediate.hs b/lib/Language/Elna/Intermediate.hs
index 9245fb4..50d76c9 100644
--- a/lib/Language/Elna/Intermediate.hs
+++ b/lib/Language/Elna/Intermediate.hs
@@ -17,6 +17,7 @@ import qualified Language.Elna.AST as AST
import Language.Elna.Types (Type(..))
import Language.Elna.SymbolTable (SymbolTable, Info(..))
import qualified Language.Elna.SymbolTable as SymbolTable
+import Data.Maybe (fromMaybe)
data Operand
= VariableOperand Variable
@@ -34,7 +35,7 @@ data Quadruple
| GoToQuadruple Label
| AssignQuadruple Operand Variable
| ArrayQuadruple Variable Operand Variable
- | ArrayAssignQuadruple Operand Word32 Variable
+ | ArrayAssignQuadruple Operand Operand Variable
| AddQuadruple Operand Operand Variable
| SubtractionQuadruple Operand Operand Variable
| ProductQuadruple Operand Operand Variable
@@ -66,8 +67,58 @@ intermediate globalTable (AST.Program declarations) =
statement :: SymbolTable -> AST.Statement -> Vector Quadruple
statement _ AST.EmptyStatement = mempty
-statement globalTable (AST.CompoundStatement statements) =
- foldMap (statement globalTable) statements
+statement localTable (AST.AssignmentStatement variableAccess' assignee) =
+ let (rhsOperand, rhsStatements) = expression localTable assignee
+ variableType' = variableType variableAccess' localTable
+ lhsStatements = case variableAccess localTable variableAccess' Nothing variableType' mempty of
+ (AST.Identifier identifier, Just accumulatedIndex, accumulatedStatements) ->
+ Vector.snoc accumulatedStatements
+ $ ArrayAssignQuadruple rhsOperand accumulatedIndex
+ $ Variable identifier
+ (AST.Identifier identifier, Nothing, accumulatedStatements) ->
+ Vector.snoc accumulatedStatements
+ $ AssignQuadruple rhsOperand
+ $ Variable identifier
+ in rhsStatements <> lhsStatements
+statement localTable (AST.IfStatement ifCondition ifStatement elseStatement) =
+ let (conditionStatements, jumpConstructor) = condition localTable ifCondition
+ ifStatements = statement localTable ifStatement
+ ifLabel = Label "L1"
+ endLabel = Label "L2"
+ in conditionStatements <> case statement localTable <$> elseStatement of
+ Just elseStatements -> Vector.cons (jumpConstructor ifLabel) elseStatements
+ <> Vector.fromList [GoToQuadruple endLabel, LabelQuadruple ifLabel]
+ <> Vector.snoc ifStatements (LabelQuadruple endLabel)
+ Nothing -> Vector.fromList [jumpConstructor ifLabel, GoToQuadruple endLabel, LabelQuadruple ifLabel]
+ <> Vector.snoc ifStatements (LabelQuadruple endLabel)
+statement localTable (AST.CompoundStatement statements) =
+ foldMap (statement localTable) statements
+
+condition :: SymbolTable -> AST.Condition -> (Vector Quadruple, Label -> Quadruple)
+condition localTable (AST.EqualCondition lhs rhs) =
+ let (lhsOperand, lhsStatements) = expression localTable lhs
+ (rhsOperand, rhsStatements) = expression localTable rhs
+ in (lhsStatements <> rhsStatements, EqualQuadruple lhsOperand rhsOperand)
+condition localTable (AST.NonEqualCondition lhs rhs) =
+ let (lhsOperand, lhsStatements) = expression localTable lhs
+ (rhsOperand, rhsStatements) = expression localTable rhs
+ in (lhsStatements <> rhsStatements, NonEqualQuadruple lhsOperand rhsOperand)
+condition localTable (AST.LessCondition lhs rhs) =
+ let (lhsOperand, lhsStatements) = expression localTable lhs
+ (rhsOperand, rhsStatements) = expression localTable rhs
+ in (lhsStatements <> rhsStatements, LessQuadruple lhsOperand rhsOperand)
+condition localTable (AST.GreaterCondition lhs rhs) =
+ let (lhsOperand, lhsStatements) = expression localTable lhs
+ (rhsOperand, rhsStatements) = expression localTable rhs
+ in (lhsStatements <> rhsStatements, GreaterQuadruple lhsOperand rhsOperand)
+condition localTable (AST.LessOrEqualCondition lhs rhs) =
+ let (lhsOperand, lhsStatements) = expression localTable lhs
+ (rhsOperand, rhsStatements) = expression localTable rhs
+ in (lhsStatements <> rhsStatements, LessOrEqualQuadruple lhsOperand rhsOperand)
+condition localTable (AST.GreaterOrEqualCondition lhs rhs) =
+ let (lhsOperand, lhsStatements) = expression localTable lhs
+ (rhsOperand, rhsStatements) = expression localTable rhs
+ in (lhsStatements <> rhsStatements, GreaterOrEqualQuadruple lhsOperand rhsOperand)
variableAccess
:: SymbolTable