Parse call statements
This commit is contained in:
		
							
								
								
									
										10
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								TODO
									
									
									
									
									
								
							@@ -1,15 +1,17 @@
 | 
				
			|||||||
# Intermediate code generation
 | 
					# Intermediate code generation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Put symbol table in the reader monad and it to the stack
 | 
					- Traverse the AST and generate IR.
 | 
				
			||||||
  or use the state monad for everything.
 | 
					 | 
				
			||||||
- Add errors handling to the monad stack.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ELF generation
 | 
					# ELF generation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Don't ignore relocations where the symbol is not defined in the symbol table.
 | 
					- Don't ignore relocations where the symbol is not defined in the symbol table.
 | 
				
			||||||
  Report an error about an undefined symbol.
 | 
					  Report an error about an undefined symbol.
 | 
				
			||||||
- Don't hardcode symbols in symbolEntry.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Name analysis
 | 
					# Name analysis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Format error messages.
 | 
					- Format error messages.
 | 
				
			||||||
 | 
					- Return non-zero error code on errors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Built-in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Printi should be able to print numbers with multiple digits.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,11 +7,12 @@ module Language.Elna.AST
 | 
				
			|||||||
    , TypeExpression(..)
 | 
					    , TypeExpression(..)
 | 
				
			||||||
    , VariableDeclaration(..)
 | 
					    , VariableDeclaration(..)
 | 
				
			||||||
    {-, VariableAccess(..)
 | 
					    {-, VariableAccess(..)
 | 
				
			||||||
    , Condition(..)
 | 
					    , Condition(..)-}
 | 
				
			||||||
    , Expression(..)
 | 
					    , Expression(..)
 | 
				
			||||||
    , Literal(..)-}
 | 
					    , Literal(..)
 | 
				
			||||||
    ) where
 | 
					    ) where
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Data.Int (Int32)
 | 
				
			||||||
import Data.List (intercalate)
 | 
					import Data.List (intercalate)
 | 
				
			||||||
import Data.Word ({-Word16, -}Word32)
 | 
					import Data.Word ({-Word16, -}Word32)
 | 
				
			||||||
import Language.Elna.Location (Identifier(..), showArrayType)
 | 
					import Language.Elna.Location (Identifier(..), showArrayType)
 | 
				
			||||||
@@ -67,8 +68,8 @@ data Statement
 | 
				
			|||||||
    {-| AssignmentStatement VariableAccess Expression
 | 
					    {-| AssignmentStatement VariableAccess Expression
 | 
				
			||||||
    | IfStatement Condition Statement (Maybe Statement)
 | 
					    | IfStatement Condition Statement (Maybe Statement)
 | 
				
			||||||
    | WhileStatement Condition Statement
 | 
					    | WhileStatement Condition Statement
 | 
				
			||||||
    | CompoundStatement [Statement]
 | 
					    | CompoundStatement [Statement]-}
 | 
				
			||||||
    | CallStatement Identifier [Expression]-}
 | 
					    | CallStatement Identifier [Expression]
 | 
				
			||||||
    deriving Eq
 | 
					    deriving Eq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
instance Show Statement
 | 
					instance Show Statement
 | 
				
			||||||
@@ -84,39 +85,58 @@ instance Show Statement
 | 
				
			|||||||
    show (WhileStatement expression statement) =
 | 
					    show (WhileStatement expression statement) =
 | 
				
			||||||
        concat ["while (", show expression, ") ", show statement, ";"]
 | 
					        concat ["while (", show expression, ") ", show statement, ";"]
 | 
				
			||||||
    show (CompoundStatement statements) =
 | 
					    show (CompoundStatement statements) =
 | 
				
			||||||
        concat ["{\n", unlines (show <$> statements), " }"]
 | 
					        concat ["{\n", unlines (show <$> statements), " }"]-}
 | 
				
			||||||
    show (CallStatement name parameters) = show name <> "("
 | 
					    show (CallStatement name parameters) = show name <> "("
 | 
				
			||||||
        <> intercalate ", " (show <$> parameters) <> ")"-}
 | 
					        <> intercalate ", " (show <$> parameters) <> ")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data VariableDeclaration =
 | 
					data VariableDeclaration =
 | 
				
			||||||
    VariableDeclaration Identifier TypeExpression
 | 
					    VariableDeclaration Identifier TypeExpression
 | 
				
			||||||
    deriving Eq
 | 
					    deriving Eq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
instance Show VariableDeclaration
 | 
					newtype Literal
 | 
				
			||||||
  where
 | 
					 | 
				
			||||||
    show (VariableDeclaration identifier typeExpression) =
 | 
					 | 
				
			||||||
        concat ["var ", show identifier, ": " <> show typeExpression, ";"]
 | 
					 | 
				
			||||||
{-
 | 
					 | 
				
			||||||
import Data.Int (Int32)
 | 
					 | 
				
			||||||
import Data.Char (chr)
 | 
					 | 
				
			||||||
import Numeric (showHex)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
data Literal
 | 
					 | 
				
			||||||
    = IntegerLiteral Int32
 | 
					    = IntegerLiteral Int32
 | 
				
			||||||
    | HexadecimalLiteral Int32
 | 
					    {- | HexadecimalLiteral Int32
 | 
				
			||||||
    | CharacterLiteral Word16
 | 
					    | CharacterLiteral Word16
 | 
				
			||||||
    | BooleanLiteral Bool
 | 
					    | BooleanLiteral Bool -}
 | 
				
			||||||
    deriving Eq
 | 
					    deriving Eq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
instance Show Literal
 | 
					instance Show Literal
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
    show (IntegerLiteral integer) = show integer
 | 
					    show (IntegerLiteral integer) = show integer
 | 
				
			||||||
    show (HexadecimalLiteral integer) = '0' : 'x' : showHex integer ""
 | 
					    {- show (HexadecimalLiteral integer) = '0' : 'x' : showHex integer ""
 | 
				
			||||||
    show (CharacterLiteral character) =
 | 
					    show (CharacterLiteral character) =
 | 
				
			||||||
        '\'' : chr (fromEnum character) : ['\'']
 | 
					        '\'' : chr (fromEnum character) : ['\'']
 | 
				
			||||||
    show (BooleanLiteral boolean)
 | 
					    show (BooleanLiteral boolean)
 | 
				
			||||||
        | boolean = "true"
 | 
					        | boolean = "true"
 | 
				
			||||||
        | otherwise = "false"
 | 
					        | otherwise = "false" -}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					instance Show VariableDeclaration
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					    show (VariableDeclaration identifier typeExpression) =
 | 
				
			||||||
 | 
					        concat ["var ", show identifier, ": " <> show typeExpression, ";"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					newtype Expression
 | 
				
			||||||
 | 
					    = LiteralExpression Literal
 | 
				
			||||||
 | 
					{-    | VariableExpression VariableAccess
 | 
				
			||||||
 | 
					    | NegationExpression Expression
 | 
				
			||||||
 | 
					    | SumExpression Expression Expression
 | 
				
			||||||
 | 
					    | SubtractionExpression Expression Expression
 | 
				
			||||||
 | 
					    | ProductExpression Expression Expression
 | 
				
			||||||
 | 
					    | DivisionExpression Expression Expression -}
 | 
				
			||||||
 | 
					    deriving Eq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					instance Show Expression
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					    show (LiteralExpression literal) = show literal
 | 
				
			||||||
 | 
					    {- show (VariableExpression variable) = show variable
 | 
				
			||||||
 | 
					    show (NegationExpression negation) = '-' : show negation
 | 
				
			||||||
 | 
					    show (SumExpression lhs rhs) = concat [show lhs, " + ", show rhs]
 | 
				
			||||||
 | 
					    show (SubtractionExpression lhs rhs) = concat [show lhs, " - ", show rhs]
 | 
				
			||||||
 | 
					    show (ProductExpression lhs rhs) = concat [show lhs, " * ", show rhs]
 | 
				
			||||||
 | 
					    show (DivisionExpression lhs rhs) = concat [show lhs, " / ", show rhs] -}
 | 
				
			||||||
 | 
					{-
 | 
				
			||||||
 | 
					import Data.Char (chr)
 | 
				
			||||||
 | 
					import Numeric (showHex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data VariableAccess
 | 
					data VariableAccess
 | 
				
			||||||
    = VariableAccess Identifier
 | 
					    = VariableAccess Identifier
 | 
				
			||||||
@@ -129,26 +149,6 @@ instance Show VariableAccess
 | 
				
			|||||||
    show (ArrayAccess arrayAccess elementIndex) =
 | 
					    show (ArrayAccess arrayAccess elementIndex) =
 | 
				
			||||||
        concat [show arrayAccess, "[", show elementIndex, "]"]
 | 
					        concat [show arrayAccess, "[", show elementIndex, "]"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data Expression
 | 
					 | 
				
			||||||
    = VariableExpression VariableAccess
 | 
					 | 
				
			||||||
    | LiteralExpression Literal
 | 
					 | 
				
			||||||
    | NegationExpression Expression
 | 
					 | 
				
			||||||
    | SumExpression Expression Expression
 | 
					 | 
				
			||||||
    | SubtractionExpression Expression Expression
 | 
					 | 
				
			||||||
    | ProductExpression Expression Expression
 | 
					 | 
				
			||||||
    | DivisionExpression Expression Expression
 | 
					 | 
				
			||||||
    deriving Eq
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
instance Show Expression
 | 
					 | 
				
			||||||
  where
 | 
					 | 
				
			||||||
    show (VariableExpression variable) = show variable
 | 
					 | 
				
			||||||
    show (LiteralExpression literal) = show literal
 | 
					 | 
				
			||||||
    show (NegationExpression negation) = '-' : show negation
 | 
					 | 
				
			||||||
    show (SumExpression lhs rhs) = concat [show lhs, " + ", show rhs]
 | 
					 | 
				
			||||||
    show (SubtractionExpression lhs rhs) = concat [show lhs, " - ", show rhs]
 | 
					 | 
				
			||||||
    show (ProductExpression lhs rhs) = concat [show lhs, " * ", show rhs]
 | 
					 | 
				
			||||||
    show (DivisionExpression lhs rhs) = concat [show lhs, " / ", show rhs]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
data Condition
 | 
					data Condition
 | 
				
			||||||
    = EqualCondition Expression Expression
 | 
					    = EqualCondition Expression Expression
 | 
				
			||||||
    | NonEqualCondition Expression Expression
 | 
					    | NonEqualCondition Expression Expression
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
module Language.Elna.CodeGenerator
 | 
					module Language.Elna.CodeGenerator
 | 
				
			||||||
    ( Asm(..)
 | 
					    ( Statement(..)
 | 
				
			||||||
    , generateCode
 | 
					    , generateCode
 | 
				
			||||||
    ) where
 | 
					    ) where
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,12 +15,12 @@ data Directive
 | 
				
			|||||||
    | FunctionDirective
 | 
					    | FunctionDirective
 | 
				
			||||||
    deriving (Eq, Show)
 | 
					    deriving (Eq, Show)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data Asm
 | 
					data Statement
 | 
				
			||||||
    = Instruction RiscV.Instruction
 | 
					    = Instruction RiscV.Instruction
 | 
				
			||||||
    | JumpLabel ByteString [Directive]
 | 
					    | JumpLabel ByteString [Directive]
 | 
				
			||||||
    deriving Eq
 | 
					    deriving Eq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
generateCode :: SymbolTable -> Vector Quadruple -> Vector Asm
 | 
					generateCode :: SymbolTable -> Vector Quadruple -> Vector Statement
 | 
				
			||||||
generateCode _ _ = Vector.fromList
 | 
					generateCode _ _ = Vector.fromList
 | 
				
			||||||
    [ JumpLabel "main" [GlobalDirective, FunctionDirective]
 | 
					    [ JumpLabel "main" [GlobalDirective, FunctionDirective]
 | 
				
			||||||
    , Instruction (RiscV.CallInstruction "printi")
 | 
					    , Instruction (RiscV.CallInstruction "printi")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ import Data.Functor ((<&>))
 | 
				
			|||||||
import Language.Elna.Location (Identifier(..))
 | 
					import Language.Elna.Location (Identifier(..))
 | 
				
			||||||
import Language.Elna.Types (Type(..))
 | 
					import Language.Elna.Types (Type(..))
 | 
				
			||||||
import Data.Foldable (traverse_)
 | 
					import Data.Foldable (traverse_)
 | 
				
			||||||
import Control.Monad (foldM)
 | 
					import Control.Monad (foldM, unless)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data Error
 | 
					data Error
 | 
				
			||||||
    = UndefinedTypeError Identifier
 | 
					    = UndefinedTypeError Identifier
 | 
				
			||||||
@@ -128,38 +128,16 @@ dataType environmentSymbolTable (AST.NamedType baseType) = do
 | 
				
			|||||||
dataType environmentSymbolTable (AST.ArrayType arraySize baseType) =
 | 
					dataType environmentSymbolTable (AST.ArrayType arraySize baseType) =
 | 
				
			||||||
    dataType environmentSymbolTable baseType <&> ArrayType arraySize
 | 
					    dataType environmentSymbolTable baseType <&> ArrayType arraySize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
statement :: SymbolTable -> AST.Statement -> NameAnalysis ()
 | 
					 | 
				
			||||||
statement _ AST.EmptyStatement = pure ()
 | 
					 | 
				
			||||||
{- statement globalTable (AST.AssignmentStatement lvalue rvalue)
 | 
					 | 
				
			||||||
    = variableAccess globalTable lvalue
 | 
					 | 
				
			||||||
    >> expression globalTable rvalue
 | 
					 | 
				
			||||||
statement globalTable (AST.IfStatement ifCondition ifStatement elseStatement)
 | 
					 | 
				
			||||||
    = condition globalTable ifCondition
 | 
					 | 
				
			||||||
    >> statement globalTable ifStatement
 | 
					 | 
				
			||||||
    >> maybe (pure ()) (statement globalTable) elseStatement
 | 
					 | 
				
			||||||
statement globalTable (AST.WhileStatement whileCondition loop)
 | 
					 | 
				
			||||||
    = condition globalTable whileCondition
 | 
					 | 
				
			||||||
    >> statement globalTable loop
 | 
					 | 
				
			||||||
statement globalTable (AST.CompoundStatement statements) =
 | 
					 | 
				
			||||||
    traverse_ (statement globalTable) statements
 | 
					 | 
				
			||||||
statement globalTable (AST.CallStatement name arguments)
 | 
					 | 
				
			||||||
    = checkSymbol globalTable name
 | 
					 | 
				
			||||||
    >> traverse_ (expression globalTable) arguments
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
checkSymbol :: SymbolTable -> Identifier -> NameAnalysis ()
 | 
					checkSymbol :: SymbolTable -> Identifier -> NameAnalysis ()
 | 
				
			||||||
checkSymbol globalTable identifier =
 | 
					checkSymbol globalTable identifier
 | 
				
			||||||
    let undefinedSymbolError = NameAnalysis
 | 
					    = unless (SymbolTable.member identifier globalTable)
 | 
				
			||||||
            $ lift
 | 
					    $ NameAnalysis $ throwE
 | 
				
			||||||
            $ throwE
 | 
					    $ UndefinedSymbolError identifier
 | 
				
			||||||
            $ UndefinedSymbolError identifier
 | 
					 | 
				
			||||||
        isDefined = SymbolTable.member identifier globalTable
 | 
					 | 
				
			||||||
     in NameAnalysis (asks (SymbolTable.member identifier))
 | 
					 | 
				
			||||||
        >>= (flip unless undefinedSymbolError . (isDefined ||))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
expression :: SymbolTable -> AST.Expression -> NameAnalysis ()
 | 
					expression :: SymbolTable -> AST.Expression -> NameAnalysis ()
 | 
				
			||||||
expression globalTable (AST.VariableExpression variableExpression) =
 | 
					 | 
				
			||||||
    variableAccess globalTable variableExpression
 | 
					 | 
				
			||||||
expression _ (AST.LiteralExpression _) = pure ()
 | 
					expression _ (AST.LiteralExpression _) = pure ()
 | 
				
			||||||
 | 
					{- expression globalTable (AST.VariableExpression variableExpression) =
 | 
				
			||||||
 | 
					    variableAccess globalTable variableExpression
 | 
				
			||||||
expression globalTable (AST.NegationExpression negation) =
 | 
					expression globalTable (AST.NegationExpression negation) =
 | 
				
			||||||
    expression globalTable negation
 | 
					    expression globalTable negation
 | 
				
			||||||
expression globalTable (AST.SumExpression lhs rhs)
 | 
					expression globalTable (AST.SumExpression lhs rhs)
 | 
				
			||||||
@@ -174,6 +152,24 @@ expression globalTable (AST.ProductExpression lhs rhs)
 | 
				
			|||||||
expression globalTable (AST.DivisionExpression lhs rhs)
 | 
					expression globalTable (AST.DivisionExpression lhs rhs)
 | 
				
			||||||
    = expression globalTable lhs
 | 
					    = expression globalTable lhs
 | 
				
			||||||
    >> expression globalTable rhs
 | 
					    >> expression globalTable rhs
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					statement :: SymbolTable -> AST.Statement -> NameAnalysis ()
 | 
				
			||||||
 | 
					statement _ AST.EmptyStatement = pure ()
 | 
				
			||||||
 | 
					statement globalTable (AST.CallStatement name arguments)
 | 
				
			||||||
 | 
					    = checkSymbol globalTable name
 | 
				
			||||||
 | 
					    >> traverse_ (expression globalTable) arguments
 | 
				
			||||||
 | 
					{- statement globalTable (AST.AssignmentStatement lvalue rvalue)
 | 
				
			||||||
 | 
					    = variableAccess globalTable lvalue
 | 
				
			||||||
 | 
					    >> expression globalTable rvalue
 | 
				
			||||||
 | 
					statement globalTable (AST.IfStatement ifCondition ifStatement elseStatement)
 | 
				
			||||||
 | 
					    = condition globalTable ifCondition
 | 
				
			||||||
 | 
					    >> statement globalTable ifStatement
 | 
				
			||||||
 | 
					    >> maybe (pure ()) (statement globalTable) elseStatement
 | 
				
			||||||
 | 
					statement globalTable (AST.WhileStatement whileCondition loop)
 | 
				
			||||||
 | 
					    = condition globalTable whileCondition
 | 
				
			||||||
 | 
					    >> statement globalTable loop
 | 
				
			||||||
 | 
					statement globalTable (AST.CompoundStatement statements) =
 | 
				
			||||||
 | 
					    traverse_ (statement globalTable) statements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
variableAccess :: SymbolTable -> AST.VariableAccess -> NameAnalysis ()
 | 
					variableAccess :: SymbolTable -> AST.VariableAccess -> NameAnalysis ()
 | 
				
			||||||
variableAccess globalTable (AST.ArrayAccess arrayExpression indexExpression)
 | 
					variableAccess globalTable (AST.ArrayAccess arrayExpression indexExpression)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ module Language.Elna.Parser
 | 
				
			|||||||
    ) where
 | 
					    ) where
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Control.Monad (void)
 | 
					import Control.Monad (void)
 | 
				
			||||||
-- import Control.Monad.Combinators.Expr (Operator(..), makeExprParser)
 | 
					import Control.Monad.Combinators.Expr ({-Operator(..), -} makeExprParser)
 | 
				
			||||||
import Data.Text (Text)
 | 
					import Data.Text (Text)
 | 
				
			||||||
import qualified Data.Text as Text
 | 
					import qualified Data.Text as Text
 | 
				
			||||||
import Data.Void (Void)
 | 
					import Data.Void (Void)
 | 
				
			||||||
@@ -17,19 +17,19 @@ import Language.Elna.AST
 | 
				
			|||||||
    , TypeExpression(..)
 | 
					    , TypeExpression(..)
 | 
				
			||||||
    , VariableDeclaration(..)
 | 
					    , VariableDeclaration(..)
 | 
				
			||||||
    {-, VariableAccess(..)
 | 
					    {-, VariableAccess(..)
 | 
				
			||||||
    , Condition(..)
 | 
					    , Condition(..)-}
 | 
				
			||||||
    , Expression(..)
 | 
					    , Expression(..)
 | 
				
			||||||
    , Literal(..)-}
 | 
					    , Literal(..)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
import Text.Megaparsec
 | 
					import Text.Megaparsec
 | 
				
			||||||
    ( Parsec
 | 
					    ( Parsec
 | 
				
			||||||
    , (<?>)
 | 
					    , (<?>)
 | 
				
			||||||
    --, MonadParsec(..)
 | 
					    , MonadParsec(..)
 | 
				
			||||||
    , eof
 | 
					    , eof
 | 
				
			||||||
    , optional
 | 
					    , optional
 | 
				
			||||||
    , between
 | 
					    , between
 | 
				
			||||||
    , sepBy
 | 
					    , sepBy
 | 
				
			||||||
    --, choice
 | 
					    , choice
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
import qualified Text.Megaparsec.Char.Lexer as Lexer
 | 
					import qualified Text.Megaparsec.Char.Lexer as Lexer
 | 
				
			||||||
import Text.Megaparsec.Char
 | 
					import Text.Megaparsec.Char
 | 
				
			||||||
@@ -44,6 +44,17 @@ import Data.Maybe (isJust)
 | 
				
			|||||||
-- import Data.Functor (($>))
 | 
					-- import Data.Functor (($>))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Parser = Parsec Void Text
 | 
					type Parser = Parsec Void Text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					literalP :: Parser Literal
 | 
				
			||||||
 | 
					literalP
 | 
				
			||||||
 | 
					    = {- HexadecimalLiteral <$> (string "0x" *> lexeme Lexer.hexadecimal)
 | 
				
			||||||
 | 
					    <|> -} IntegerLiteral <$> lexeme Lexer.decimal
 | 
				
			||||||
 | 
					    {- <|> CharacterLiteral <$> lexeme charP
 | 
				
			||||||
 | 
					    <|> BooleanLiteral <$> (symbol "true" $> True)
 | 
				
			||||||
 | 
					    <|> BooleanLiteral <$> (symbol "false" $> False)
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					    charP = fromIntegral . fromEnum
 | 
				
			||||||
 | 
					        <$> between (char '\'') (char '\'') Lexer.charLiteral -}
 | 
				
			||||||
{-
 | 
					{-
 | 
				
			||||||
typeDefinitionP :: Parser Declaration
 | 
					typeDefinitionP :: Parser Declaration
 | 
				
			||||||
typeDefinitionP = TypeDefinition
 | 
					typeDefinitionP = TypeDefinition
 | 
				
			||||||
@@ -51,25 +62,14 @@ typeDefinitionP = TypeDefinition
 | 
				
			|||||||
    <*> (symbol "=" *> typeExpressionP)
 | 
					    <*> (symbol "=" *> typeExpressionP)
 | 
				
			||||||
    <* semicolonP
 | 
					    <* semicolonP
 | 
				
			||||||
    <?> "type definition"
 | 
					    <?> "type definition"
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
literalP :: Parser Literal
 | 
					 | 
				
			||||||
literalP
 | 
					 | 
				
			||||||
    = HexadecimalLiteral <$> (string "0x" *> lexeme Lexer.hexadecimal)
 | 
					 | 
				
			||||||
    <|> IntegerLiteral <$> lexeme Lexer.decimal
 | 
					 | 
				
			||||||
    <|> CharacterLiteral <$> lexeme charP
 | 
					 | 
				
			||||||
    <|> BooleanLiteral <$> (symbol "true" $> True)
 | 
					 | 
				
			||||||
    <|> BooleanLiteral <$> (symbol "false" $> False)
 | 
					 | 
				
			||||||
  where
 | 
					 | 
				
			||||||
    charP = fromIntegral . fromEnum
 | 
					 | 
				
			||||||
        <$> between (char '\'') (char '\'') Lexer.charLiteral
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
termP :: Parser Expression
 | 
					termP :: Parser Expression
 | 
				
			||||||
termP = choice
 | 
					termP = choice
 | 
				
			||||||
    [ parensP expressionP
 | 
					    [ parensP expressionP
 | 
				
			||||||
    , LiteralExpression <$> literalP
 | 
					    , LiteralExpression <$> literalP
 | 
				
			||||||
    , VariableExpression <$> variableAccessP
 | 
					    -- , VariableExpression <$> variableAccessP
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					{-
 | 
				
			||||||
variableAccessP :: Parser VariableAccess
 | 
					variableAccessP :: Parser VariableAccess
 | 
				
			||||||
variableAccessP = do
 | 
					variableAccessP = do
 | 
				
			||||||
    identifier <- identifierP
 | 
					    identifier <- identifierP
 | 
				
			||||||
@@ -97,10 +97,10 @@ operatorTable =
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
    prefix name f = Prefix (f <$ symbol name)
 | 
					    prefix name f = Prefix (f <$ symbol name)
 | 
				
			||||||
    binary name f = InfixL (f <$ symbol name)
 | 
					    binary name f = InfixL (f <$ symbol name)
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
expressionP :: Parser Expression
 | 
					expressionP :: Parser Expression
 | 
				
			||||||
expressionP = makeExprParser termP operatorTable
 | 
					expressionP = makeExprParser termP [] -- operatorTable
 | 
				
			||||||
 | 
					{-
 | 
				
			||||||
conditionP :: Parser Condition
 | 
					conditionP :: Parser Condition
 | 
				
			||||||
conditionP = do
 | 
					conditionP = do
 | 
				
			||||||
    lhs <- expressionP
 | 
					    lhs <- expressionP
 | 
				
			||||||
@@ -185,21 +185,21 @@ statementP
 | 
				
			|||||||
    {-<|> CompoundStatement <$> blockP (many statementP)
 | 
					    {-<|> CompoundStatement <$> blockP (many statementP)
 | 
				
			||||||
    <|> try assignmentP
 | 
					    <|> try assignmentP
 | 
				
			||||||
    <|> try ifElseP
 | 
					    <|> try ifElseP
 | 
				
			||||||
    <|> try whileP
 | 
					    <|> try whileP -}
 | 
				
			||||||
    <|> try callP -}
 | 
					    <|> try callP
 | 
				
			||||||
    <?> "statement"
 | 
					    <?> "statement"
 | 
				
			||||||
  {-where
 | 
					  where
 | 
				
			||||||
    ifElseP = IfStatement
 | 
					    callP = CallStatement
 | 
				
			||||||
 | 
					        <$> identifierP
 | 
				
			||||||
 | 
					        <*> parensP (sepBy expressionP commaP)
 | 
				
			||||||
 | 
					        <* semicolonP
 | 
				
			||||||
 | 
					    {-ifElseP = IfStatement
 | 
				
			||||||
        <$> (symbol "if" *> parensP conditionP)
 | 
					        <$> (symbol "if" *> parensP conditionP)
 | 
				
			||||||
        <*> statementP
 | 
					        <*> statementP
 | 
				
			||||||
        <*> optional (symbol "else" *> statementP)
 | 
					        <*> optional (symbol "else" *> statementP)
 | 
				
			||||||
    whileP = WhileStatement
 | 
					    whileP = WhileStatement
 | 
				
			||||||
        <$> (symbol "while" *> parensP conditionP)
 | 
					        <$> (symbol "while" *> parensP conditionP)
 | 
				
			||||||
        <*> statementP
 | 
					        <*> statementP
 | 
				
			||||||
    callP = CallStatement
 | 
					 | 
				
			||||||
        <$> identifierP
 | 
					 | 
				
			||||||
        <*> parensP (sepBy expressionP commaP)
 | 
					 | 
				
			||||||
        <* semicolonP
 | 
					 | 
				
			||||||
    assignmentP = AssignmentStatement
 | 
					    assignmentP = AssignmentStatement
 | 
				
			||||||
        <$> variableAccessP
 | 
					        <$> variableAccessP
 | 
				
			||||||
        <* symbol ":="
 | 
					        <* symbol ":="
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,12 +44,14 @@ import qualified Language.Elna.Architecture.RiscV as RiscV
 | 
				
			|||||||
import qualified Data.Text.Encoding as Text.Encoding
 | 
					import qualified Data.Text.Encoding as Text.Encoding
 | 
				
			||||||
import Control.Monad.IO.Class (MonadIO(..))
 | 
					import Control.Monad.IO.Class (MonadIO(..))
 | 
				
			||||||
import Control.Monad.Trans.State (get)
 | 
					import Control.Monad.Trans.State (get)
 | 
				
			||||||
import Language.Elna.CodeGenerator (Asm(..))
 | 
					import Language.Elna.CodeGenerator (Statement(..))
 | 
				
			||||||
 | 
					import qualified Data.HashSet as HashSet
 | 
				
			||||||
 | 
					import GHC.Records (HasField(..))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data UnresolvedRelocation = UnresolvedRelocation ByteString Elf32_Addr Word8
 | 
					data UnresolvedRelocation = UnresolvedRelocation ByteString Elf32_Addr Word8
 | 
				
			||||||
data UnresolvedRelocations = UnresolvedRelocations (Vector UnresolvedRelocation) Elf32_Word
 | 
					data UnresolvedRelocations = UnresolvedRelocations (Vector UnresolvedRelocation) Elf32_Word
 | 
				
			||||||
 | 
					
 | 
				
			||||||
riscv32Elf :: Vector Asm -> Handle -> ElfWriter Elf32_Ehdr
 | 
					riscv32Elf :: Vector Statement -> Handle -> ElfWriter Elf32_Ehdr
 | 
				
			||||||
riscv32Elf code objectHandle = text
 | 
					riscv32Elf code objectHandle = text
 | 
				
			||||||
    >>= uncurry symrel
 | 
					    >>= uncurry symrel
 | 
				
			||||||
    >>= strtab
 | 
					    >>= strtab
 | 
				
			||||||
@@ -180,9 +182,14 @@ riscv32Elf code objectHandle = text
 | 
				
			|||||||
                    , st_name = 0
 | 
					                    , st_name = 0
 | 
				
			||||||
                    , st_info = 0
 | 
					                    , st_info = 0
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
            (encoded, updatedRelocations, symbols) = 
 | 
					            (encoded, updatedRelocations, symbols, definitions) = 
 | 
				
			||||||
                encodeAsm textTabIndex (mempty, Vector.empty, initialHeaders) code
 | 
					                encodeAsm textTabIndex (mempty, Vector.empty, initialHeaders, HashSet.empty) code
 | 
				
			||||||
            symbolResult = encodeEmptyDefinitions symbols
 | 
					
 | 
				
			||||||
 | 
					            filterPredicate = not
 | 
				
			||||||
 | 
					                . (`ByteString.isInfixOf` getField @"sectionNames" symbols)
 | 
				
			||||||
 | 
					                . ("\0" <>) . (<> "\0")
 | 
				
			||||||
 | 
					            symbolResult = HashSet.foldl' encodeEmptyDefinitions symbols
 | 
				
			||||||
 | 
					                $ HashSet.filter filterPredicate definitions
 | 
				
			||||||
            size = fromIntegral $ LazyByteString.length encoded
 | 
					            size = fromIntegral $ LazyByteString.length encoded
 | 
				
			||||||
            newHeader = Elf32_Shdr
 | 
					            newHeader = Elf32_Shdr
 | 
				
			||||||
                { sh_type = SHT_PROGBITS
 | 
					                { sh_type = SHT_PROGBITS
 | 
				
			||||||
@@ -199,8 +206,8 @@ riscv32Elf code objectHandle = text
 | 
				
			|||||||
        liftIO $ ByteString.hPut objectHandle $ LazyByteString.toStrict encoded
 | 
					        liftIO $ ByteString.hPut objectHandle $ LazyByteString.toStrict encoded
 | 
				
			||||||
        addSectionHeader ".text" newHeader
 | 
					        addSectionHeader ".text" newHeader
 | 
				
			||||||
        pure (symbolResult, UnresolvedRelocations updatedRelocations $ fromIntegral $ Vector.length sectionHeaders)
 | 
					        pure (symbolResult, UnresolvedRelocations updatedRelocations $ fromIntegral $ Vector.length sectionHeaders)
 | 
				
			||||||
    encodeEmptyDefinitions (ElfHeaderResult names entries) =
 | 
					    encodeEmptyDefinitions (ElfHeaderResult names entries) definition =
 | 
				
			||||||
        let printEntry = Elf32_Sym
 | 
					        let nextEntry = Elf32_Sym
 | 
				
			||||||
                { st_value = 0
 | 
					                { st_value = 0
 | 
				
			||||||
                , st_size = 0
 | 
					                , st_size = 0
 | 
				
			||||||
                , st_shndx = 0
 | 
					                , st_shndx = 0
 | 
				
			||||||
@@ -208,18 +215,18 @@ riscv32Elf code objectHandle = text
 | 
				
			|||||||
                , st_name = fromIntegral (ByteString.length names)
 | 
					                , st_name = fromIntegral (ByteString.length names)
 | 
				
			||||||
                , st_info = stInfo STB_GLOBAL STT_FUNC
 | 
					                , st_info = stInfo STB_GLOBAL STT_FUNC
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
         in ElfHeaderResult (names <> "printi\0")
 | 
					         in ElfHeaderResult (names <> definition <> "\0")
 | 
				
			||||||
            $ Vector.snoc entries printEntry 
 | 
					            $ Vector.snoc entries nextEntry
 | 
				
			||||||
    encodeAsm shndx (encoded, relocations, ElfHeaderResult names symbols) instructions
 | 
					    encodeAsm shndx (encoded, relocations, ElfHeaderResult names symbols, definitions) instructions
 | 
				
			||||||
        | Just (instruction, rest) <- Vector.uncons instructions =
 | 
					        | Just (instruction, rest) <- Vector.uncons instructions =
 | 
				
			||||||
            case instruction of
 | 
					            case instruction of
 | 
				
			||||||
                Instruction _ ->
 | 
					                Instruction _ ->
 | 
				
			||||||
                    let (encoded', relocations', rest') =
 | 
					                    let (encoded', relocations', rest', definitions') =
 | 
				
			||||||
                            encodeInstructions (encoded, relocations, instructions)
 | 
					                            encodeInstructions (encoded, relocations, instructions, definitions)
 | 
				
			||||||
                     in encodeAsm shndx (encoded', relocations', ElfHeaderResult names symbols) rest'
 | 
					                     in encodeAsm shndx (encoded', relocations', ElfHeaderResult names symbols, definitions') rest'
 | 
				
			||||||
                JumpLabel labelName _ ->
 | 
					                JumpLabel labelName _ ->
 | 
				
			||||||
                    let (encoded', relocations', rest') =
 | 
					                    let (encoded', relocations', rest', definitions') =
 | 
				
			||||||
                            encodeInstructions (encoded, relocations, rest)
 | 
					                            encodeInstructions (encoded, relocations, rest, definitions)
 | 
				
			||||||
                        newEntry = Elf32_Sym
 | 
					                        newEntry = Elf32_Sym
 | 
				
			||||||
                            { st_value = fromIntegral $ LazyByteString.length encoded
 | 
					                            { st_value = fromIntegral $ LazyByteString.length encoded
 | 
				
			||||||
                            , st_size = fromIntegral $ LazyByteString.length encoded'
 | 
					                            , st_size = fromIntegral $ LazyByteString.length encoded'
 | 
				
			||||||
@@ -232,10 +239,11 @@ riscv32Elf code objectHandle = text
 | 
				
			|||||||
                            ( encoded <> encoded'
 | 
					                            ( encoded <> encoded'
 | 
				
			||||||
                            , relocations <> relocations'
 | 
					                            , relocations <> relocations'
 | 
				
			||||||
                            , ElfHeaderResult (names <> labelName <> "\0") (Vector.snoc symbols newEntry)
 | 
					                            , ElfHeaderResult (names <> labelName <> "\0") (Vector.snoc symbols newEntry)
 | 
				
			||||||
 | 
					                            , definitions'
 | 
				
			||||||
                            )
 | 
					                            )
 | 
				
			||||||
                     in encodeAsm shndx result rest'
 | 
					                     in encodeAsm shndx result rest'
 | 
				
			||||||
        | otherwise = (encoded, relocations, ElfHeaderResult names symbols)
 | 
					        | otherwise = (encoded, relocations, ElfHeaderResult names symbols, definitions)
 | 
				
			||||||
    encodeInstructions (encoded, relocations, instructions)
 | 
					    encodeInstructions (encoded, relocations, instructions, definitions)
 | 
				
			||||||
        | Just (Instruction instruction, rest) <- Vector.uncons instructions =
 | 
					        | Just (Instruction instruction, rest) <- Vector.uncons instructions =
 | 
				
			||||||
            let offset = fromIntegral $ LazyByteString.length encoded
 | 
					            let offset = fromIntegral $ LazyByteString.length encoded
 | 
				
			||||||
                unresolvedRelocation = case instruction of
 | 
					                unresolvedRelocation = case instruction of
 | 
				
			||||||
@@ -259,6 +267,10 @@ riscv32Elf code objectHandle = text
 | 
				
			|||||||
                    ( encoded <> chunk
 | 
					                    ( encoded <> chunk
 | 
				
			||||||
                    , maybe relocations (Vector.snoc relocations) unresolvedRelocation
 | 
					                    , maybe relocations (Vector.snoc relocations) unresolvedRelocation
 | 
				
			||||||
                    , rest
 | 
					                    , rest
 | 
				
			||||||
 | 
					                    , addDefinition unresolvedRelocation definitions
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
             in encodeInstructions result
 | 
					             in encodeInstructions result
 | 
				
			||||||
        | otherwise = (encoded, relocations, Vector.drop 1 instructions)
 | 
					        | otherwise = (encoded, relocations, Vector.drop 1 instructions, definitions)
 | 
				
			||||||
 | 
					    addDefinition (Just (UnresolvedRelocation symbolName _ _)) =
 | 
				
			||||||
 | 
					        HashSet.insert symbolName
 | 
				
			||||||
 | 
					    addDefinition Nothing = id
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,8 +20,9 @@ import Data.List.NonEmpty (NonEmpty)
 | 
				
			|||||||
import qualified Data.List.NonEmpty as NonEmpty
 | 
					import qualified Data.List.NonEmpty as NonEmpty
 | 
				
			||||||
import Data.Maybe (isJust)
 | 
					import Data.Maybe (isJust)
 | 
				
			||||||
import Data.Vector (Vector)
 | 
					import Data.Vector (Vector)
 | 
				
			||||||
 | 
					import qualified Data.Vector as Vector
 | 
				
			||||||
import Language.Elna.Location (Identifier(..))
 | 
					import Language.Elna.Location (Identifier(..))
 | 
				
			||||||
import Language.Elna.Types (Type(..), intType, booleanType)
 | 
					import Language.Elna.Types (Type(..), intType)
 | 
				
			||||||
import Prelude hiding (lookup)
 | 
					import Prelude hiding (lookup)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data SymbolTable = SymbolTable (Maybe SymbolTable) (HashMap Identifier Info)
 | 
					data SymbolTable = SymbolTable (Maybe SymbolTable) (HashMap Identifier Info)
 | 
				
			||||||
@@ -39,7 +40,7 @@ scope parent (SymbolTable _ mappings) = SymbolTable (Just parent) mappings
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
builtInSymbolTable :: SymbolTable
 | 
					builtInSymbolTable :: SymbolTable
 | 
				
			||||||
builtInSymbolTable = SymbolTable Nothing $ HashMap.fromList
 | 
					builtInSymbolTable = SymbolTable Nothing $ HashMap.fromList
 | 
				
			||||||
    [ ("boolean", TypeInfo booleanType)
 | 
					    [ ("printi", ProcedureInfo empty Vector.empty)
 | 
				
			||||||
    , ("int", TypeInfo intType)
 | 
					    , ("int", TypeInfo intType)
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,2 +1,3 @@
 | 
				
			|||||||
proc main() {
 | 
					proc main() {
 | 
				
			||||||
 | 
					  printi(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,6 +1,3 @@
 | 
				
			|||||||
.global main
 | 
					 | 
				
			||||||
.type main, @function
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.global printi
 | 
					.global printi
 | 
				
			||||||
.type printi, @function
 | 
					.type printi, @function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,7 +32,7 @@ printi:
 | 
				
			|||||||
    ret
 | 
					    ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_start:
 | 
					_start:
 | 
				
			||||||
    call "main"
 | 
					    call main
 | 
				
			||||||
    addi a0, zero, 0
 | 
					    addi a0, zero, 0
 | 
				
			||||||
    addi a7, zero, 93
 | 
					    addi a7, zero, 93
 | 
				
			||||||
    ecall
 | 
					    ecall
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user