diff --git a/elna.cabal b/elna.cabal index 9f07012..136cd43 100644 --- a/elna.cabal +++ b/elna.cabal @@ -32,6 +32,7 @@ library elna-internal import: warnings exposed-modules: Language.Elna.AST + Language.Elna.CodeGenerator Language.Elna.Intermediate Language.Elna.Location Language.Elna.NameAnalysis diff --git a/lib/Language/Elna/CodeGenerator.hs b/lib/Language/Elna/CodeGenerator.hs new file mode 100644 index 0000000..cdbfc01 --- /dev/null +++ b/lib/Language/Elna/CodeGenerator.hs @@ -0,0 +1,3 @@ +module Language.Elna.CodeGenerator + ( + ) where diff --git a/lib/Language/Elna/Intermediate.hs b/lib/Language/Elna/Intermediate.hs index 0cda806..4e23fd9 100644 --- a/lib/Language/Elna/Intermediate.hs +++ b/lib/Language/Elna/Intermediate.hs @@ -21,6 +21,7 @@ import Language.Elna.SymbolTable (SymbolTable, Info(..)) import qualified Language.Elna.SymbolTable as SymbolTable import Data.Foldable (Foldable(..), foldrM) import GHC.Records (HasField(..)) +import qualified Data.Text as Text import qualified Data.Text.Lazy.Builder.Int as Text.Builder import qualified Data.Text.Lazy.Builder as Text.Builder import qualified Data.Text.Lazy as Text.Lazy @@ -31,25 +32,37 @@ data Operand deriving (Eq, Show) newtype Label = Label Text - deriving (Eq, Show) + deriving Eq -data Variable = Variable Text | TempVariable - deriving (Eq, Show) +instance Show Label + where + show (Label label) = '.' : Text.unpack label -newtype Generator = Generator +data Variable = Variable Text | TempVariable Int32 + deriving Eq + +instance Show Variable + where + show (Variable variable) = '$' : Text.unpack variable + show (TempVariable variable) = '$' : show variable + +data Generator = Generator { labelCounter :: Int32 + , temporaryCounter :: Int32 } deriving (Eq, Show) instance Semigroup Generator where lhs <> rhs = Generator { labelCounter = getField @"labelCounter" lhs + getField @"labelCounter" rhs + , temporaryCounter = getField @"temporaryCounter" lhs + getField @"temporaryCounter" rhs } instance Monoid Generator where mempty = Generator { labelCounter = 0 + , temporaryCounter = 0 } newtype Intermediate a = Intermediate @@ -106,6 +119,16 @@ createLabel = do { labelCounter = getField @"labelCounter" generator + 1 } +createTemporary :: Intermediate Variable +createTemporary = do + currentCounter <- Intermediate $ gets temporaryCounter + Intermediate $ modify' modifier + pure $ TempVariable currentCounter + where + modifier generator = generator + { temporaryCounter = getField @"temporaryCounter" generator + 1 + } + intermediate :: SymbolTable -> AST.Program -> HashMap AST.Identifier (Vector Quadruple) intermediate globalTable = fst @@ -237,8 +260,8 @@ variableAccess localTable (AST.ArrayAccess access1 index1) Nothing (ArrayType _ variableAccess localTable access1 (Just indexPlace) baseType statements variableAccess localTable (AST.ArrayAccess arrayAccess' arrayIndex) (Just baseIndex) (ArrayType arraySize baseType) statements = do (indexPlace, statements') <- expression localTable arrayIndex - let resultVariable = TempVariable - resultOperand = VariableOperand resultVariable + resultVariable <- createTemporary + let resultOperand = VariableOperand resultVariable indexCalculation = Vector.fromList [ ProductQuadruple (IntOperand $ fromIntegral arraySize) baseIndex resultVariable , AddQuadruple indexPlace resultOperand resultVariable @@ -262,19 +285,19 @@ expression localTable = \case case variableAccess' of (AST.Identifier identifier, Nothing, statements) -> pure (VariableOperand (Variable identifier), statements) - (AST.Identifier identifier, Just operand, statements) -> - let arrayAddress = TempVariable - arrayStatement = ArrayQuadruple (Variable identifier) operand arrayAddress - in pure + (AST.Identifier identifier, Just operand, statements) -> do + arrayAddress <- createTemporary + let arrayStatement = ArrayQuadruple (Variable identifier) operand arrayAddress + pure ( VariableOperand arrayAddress , Vector.snoc statements arrayStatement ) (AST.LiteralExpression literal') -> pure (literal literal', mempty) (AST.NegationExpression negation) -> do (operand, statements) <- expression localTable negation - let tempVariable = TempVariable - negationQuadruple = NegationQuadruple operand tempVariable - in pure + tempVariable <- createTemporary + let negationQuadruple = NegationQuadruple operand tempVariable + pure ( VariableOperand tempVariable , Vector.snoc statements negationQuadruple ) @@ -289,9 +312,9 @@ expression localTable = \case binaryExpression f lhs rhs = do (lhsOperand, lhsStatements) <- expression localTable lhs (rhsOperand, rhsStatements) <- expression localTable rhs - let tempVariable = TempVariable - newQuadruple = f lhsOperand rhsOperand tempVariable - in pure + tempVariable <- createTemporary + let newQuadruple = f lhsOperand rhsOperand tempVariable + pure ( VariableOperand tempVariable , Vector.snoc (lhsStatements <> rhsStatements) newQuadruple )