summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2024-08-07 22:47:35 +0200
committerEugen Wissner <belka@caraus.de>2024-08-07 22:47:35 +0200
commit573990551cd19cba3959579910781637e0d9ecb4 (patch)
tree3cc487b5d15e41e12a07b5d08ad6d9cfbf6a086f
parent385322235ddabde3a2d5f33d8f258016a9170f83 (diff)
downloadelna-573990551cd19cba3959579910781637e0d9ecb4.tar.gz
Determine an expression type
-rw-r--r--TODO3
-rw-r--r--elna.cabal1
-rw-r--r--lib/Language/Elna/TypeAnalysis.hs77
3 files changed, 77 insertions, 4 deletions
diff --git a/TODO b/TODO
index 9862022..6a2f85b 100644
--- a/TODO
+++ b/TODO
@@ -1 +1,4 @@
# Type analysis
+
+- Iterate the tree and apply the expression function on procedure expressions.
+- Check statement types.
diff --git a/elna.cabal b/elna.cabal
index 6ca8912..564e108 100644
--- a/elna.cabal
+++ b/elna.cabal
@@ -22,6 +22,7 @@ common warnings
ghc-options: -Wall
default-extensions:
ExplicitForAll,
+ LambdaCase,
OverloadedStrings
default-language: GHC2021
diff --git a/lib/Language/Elna/TypeAnalysis.hs b/lib/Language/Elna/TypeAnalysis.hs
index 9804753..0cc60a2 100644
--- a/lib/Language/Elna/TypeAnalysis.hs
+++ b/lib/Language/Elna/TypeAnalysis.hs
@@ -3,12 +3,24 @@ module Language.Elna.TypeAnalysis
, typeAnalysis
) where
-import Control.Monad.Trans.Except (Except, runExcept)
-import Control.Monad.Trans.Reader (ReaderT, runReaderT)
+import Control.Applicative (Alternative(..))
+import Control.Monad.Trans.Except (Except, runExcept, throwE)
+import Control.Monad.Trans.Reader (ReaderT, asks, runReaderT)
import qualified Language.Elna.AST as AST
-import Language.Elna.SymbolTable (SymbolTable)
+import Language.Elna.Location (Identifier(..))
+import Language.Elna.SymbolTable (Info(..), SymbolTable)
+import qualified Language.Elna.SymbolTable as SymbolTable
+import Language.Elna.Types (Type(..), booleanType, intType)
+import Control.Monad.Trans.Class (MonadTrans(..))
+import Control.Monad (unless)
-data Error = Error
+data Error
+ = ArithmeticExpressionError Type
+ | ComparisonExpressionError Type Type
+ | UnexpectedVariableInfoError Info
+ | UndefinedSymbolError Identifier
+ | ArrayIndexError Type
+ | ArrayAccessError Type
deriving (Eq, Show)
newtype TypeAnalysis a = TypeAnalysis
@@ -37,3 +49,60 @@ typeAnalysis globalTable = either Just (const Nothing)
program :: AST.Program -> TypeAnalysis ()
program (AST.Program _declarations) = pure ()
+
+expression :: SymbolTable -> AST.Expression -> TypeAnalysis Type
+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 anotherInfo -> TypeAnalysis $ lift $ throwE
+ $ UnexpectedVariableInfoError anotherInfo
+ Nothing -> TypeAnalysis $ lift $ throwE
+ $ UndefinedSymbolError identifier
+ AST.LiteralExpression literal' -> literal literal'
+ AST.NegationExpression negation -> do
+ operandType <- expression globalTable negation
+ if operandType == intType
+ then pure intType
+ else TypeAnalysis $ lift $ throwE $ ArithmeticExpressionError operandType
+ AST.SumExpression lhs rhs -> arithmeticExpression lhs rhs
+ AST.SubtractionExpression lhs rhs -> arithmeticExpression lhs rhs
+ AST.ProductExpression lhs rhs -> arithmeticExpression lhs rhs
+ AST.DivisionExpression lhs rhs -> arithmeticExpression lhs rhs
+ AST.EqualExpression lhs rhs -> comparisonExpression lhs rhs
+ AST.NonEqualExpression lhs rhs -> comparisonExpression lhs rhs
+ AST.LessExpression lhs rhs -> comparisonExpression lhs rhs
+ AST.GreaterExpression lhs rhs -> comparisonExpression lhs rhs
+ AST.LessOrEqualExpression lhs rhs -> comparisonExpression lhs rhs
+ AST.GreaterOrEqualExpression lhs rhs -> comparisonExpression lhs rhs
+ AST.ArrayExpression arrayExpression indexExpression -> do
+ arrayType <- expression globalTable arrayExpression
+ indexType <- expression globalTable indexExpression
+ unless (indexType == intType)
+ $ TypeAnalysis $ lift $ throwE $ ArrayIndexError indexType
+ case arrayType of
+ ArrayType _ baseType -> pure baseType
+ nonArrayType -> TypeAnalysis $ lift $ throwE
+ $ ArrayAccessError nonArrayType
+ where
+ arithmeticExpression lhs rhs = do
+ lhsType <- expression globalTable lhs
+ unless (lhsType == intType)
+ $ TypeAnalysis $ lift $ throwE $ ArithmeticExpressionError lhsType
+ rhsType <- expression globalTable rhs
+ unless (rhsType == intType)
+ $ TypeAnalysis $ lift $ throwE $ ArithmeticExpressionError rhsType
+ pure intType
+ comparisonExpression lhs rhs = do
+ lhsType <- expression globalTable lhs
+ rhsType <- expression globalTable rhs
+ if lhsType == intType && rhsType ==intType
+ then pure booleanType
+ else TypeAnalysis $ lift $ throwE $ ComparisonExpressionError lhsType rhsType
+
+literal :: AST.Literal -> TypeAnalysis Type
+literal (AST.IntegerLiteral _) = pure intType
+literal (AST.HexadecimalLiteral _) = pure intType
+literal (AST.CharacterLiteral _) = pure intType
+literal (AST.BooleanLiteral _) = pure booleanType