diff --git a/TODO b/TODO index 46877d5..e1bdc64 100644 --- a/TODO +++ b/TODO @@ -1 +1,4 @@ -# Register allocation +# Intermediate code generation + +Execute the generation in a state monad and generate unique labels and +temporary variable names. 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