diff --git a/lib/Language/Elna/NameAnalysis.hs b/lib/Language/Elna/NameAnalysis.hs index 57c41b3..7078691 100644 --- a/lib/Language/Elna/NameAnalysis.hs +++ b/lib/Language/Elna/NameAnalysis.hs @@ -14,19 +14,26 @@ import Control.Monad.Trans.Reader import Data.Functor ((<&>)) import qualified Language.Elna.AST as AST import Language.Elna.Location (Identifier(..)) -import Language.Elna.SymbolTable (Info(..), SymbolTable, builtInSymbolTable) +import Language.Elna.SymbolTable + ( Info(..) + , ParameterInfo(..) + , SymbolTable + , builtInSymbolTable + ) import qualified Language.Elna.SymbolTable as SymbolTable import Language.Elna.Types (Type(..)) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad (foldM, unless) import qualified Data.List.NonEmpty as NonEmpty import Data.Foldable (traverse_) +import qualified Data.Vector as Vector data Error = UndefinedTypeError Identifier | UnexpectedTypeInfoError Info | IdentifierAlreadyDefinedError Identifier | UndefinedSymbolError Identifier + | UnexpectedArrayByValue Identifier deriving (Eq, Show) newtype NameAnalysis a = NameAnalysis @@ -66,9 +73,12 @@ declaration globalTable (AST.ProcedureDefinition identifier parameters variables variableInfo <- mapM variableDeclaration variables newTable <- either (identifierAlreadyDefinedError . NonEmpty.head) pure $ SymbolTable.fromList - $ parametersInfo <> variableInfo + $ fmap parameterToVariableInfo parametersInfo + <> variableInfo traverse_ (statement globalTable) body - enter identifier (ProcedureInfo newTable mempty) globalTable + let procedureInfo = ProcedureInfo newTable + $ Vector.fromList parametersInfo + enter identifier procedureInfo globalTable statement :: SymbolTable -> AST.Statement -> NameAnalysis () statement _ AST.EmptyStatement = pure () @@ -151,13 +161,29 @@ identifierAlreadyDefinedError = NameAnalysis variableDeclaration :: AST.VariableDeclaration -> NameAnalysis (Identifier, Info) variableDeclaration (AST.VariableDeclaration identifier typeExpression) - = (identifier,) . flip VariableInfo False + = (identifier,) . VariableInfo False <$> dataType typeExpression -parameter :: AST.Parameter -> NameAnalysis (Identifier, Info) -parameter (AST.Parameter identifier typeExpression isReferenceParameter') - = (identifier,) . flip VariableInfo isReferenceParameter' - <$> dataType typeExpression +parameter :: AST.Parameter -> NameAnalysis ParameterInfo +parameter (AST.Parameter identifier typeExpression isReferenceParameter') = do + parameterType <- dataType typeExpression + case parameterType of + ArrayType _ _ + | not isReferenceParameter' -> NameAnalysis + $ lift $ throwE $ UnexpectedArrayByValue identifier + _ -> + let parameterInfo = ParameterInfo + { name = identifier + , type' = parameterType + , isReferenceParameter = isReferenceParameter' + } + in pure parameterInfo + +parameterToVariableInfo :: ParameterInfo -> (Identifier, Info) +parameterToVariableInfo ParameterInfo{..} = + ( name + , VariableInfo isReferenceParameter type' + ) withSymbolTable :: forall a. SymbolTable -> NameAnalysis a -> NameAnalysis a withSymbolTable symbolTable' = NameAnalysis diff --git a/lib/Language/Elna/SymbolTable.hs b/lib/Language/Elna/SymbolTable.hs index eb82073..b56d0c7 100644 --- a/lib/Language/Elna/SymbolTable.hs +++ b/lib/Language/Elna/SymbolTable.hs @@ -73,6 +73,6 @@ data ParameterInfo = ParameterInfo data Info = TypeInfo Type - | VariableInfo Type Bool + | VariableInfo Bool Type | ProcedureInfo SymbolTable (Vector ParameterInfo) deriving (Eq, Show) diff --git a/lib/Language/Elna/TypeAnalysis.hs b/lib/Language/Elna/TypeAnalysis.hs index 040a022..c390196 100644 --- a/lib/Language/Elna/TypeAnalysis.hs +++ b/lib/Language/Elna/TypeAnalysis.hs @@ -125,7 +125,7 @@ expression globalTable = \case AST.VariableExpression identifier -> do localLookup <- TypeAnalysis $ asks $ SymbolTable.lookup identifier case localLookup <|> SymbolTable.lookup identifier globalTable of - Just (VariableInfo variableType _) -> pure variableType + Just (VariableInfo _ variableType) -> pure variableType Just anotherInfo -> TypeAnalysis $ lift $ throwE $ UnexpectedVariableInfoError anotherInfo Nothing -> TypeAnalysis $ lift $ throwE diff --git a/lib/Language/Elna/Types.hs b/lib/Language/Elna/Types.hs index 80a88c0..ee76ec8 100644 --- a/lib/Language/Elna/Types.hs +++ b/lib/Language/Elna/Types.hs @@ -1,5 +1,6 @@ module Language.Elna.Types ( Type(..) + , addressByteSize , booleanType , intType ) where @@ -8,18 +9,21 @@ import Data.Text (Text) import Data.Word (Word32) import Language.Elna.Location (showArrayType) +addressByteSize :: Int +addressByteSize = 4 + data Type - = PrimitiveType Text + = PrimitiveType Text Int | ArrayType Word32 Type deriving Eq instance Show Type where - show (PrimitiveType typeName) = show typeName + show (PrimitiveType typeName _) = show typeName show (ArrayType elementCount typeName) = showArrayType elementCount typeName intType :: Type -intType = PrimitiveType "int" +intType = PrimitiveType "int" 4 booleanType :: Type -booleanType = PrimitiveType "boolean" +booleanType = PrimitiveType "boolean" 1