diff options
Diffstat (limited to 'lib/Language/Elna/Frontend/SymbolTable.hs')
| -rw-r--r-- | lib/Language/Elna/Frontend/SymbolTable.hs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/lib/Language/Elna/Frontend/SymbolTable.hs b/lib/Language/Elna/Frontend/SymbolTable.hs new file mode 100644 index 0000000..9ace33f --- /dev/null +++ b/lib/Language/Elna/Frontend/SymbolTable.hs @@ -0,0 +1,88 @@ +module Language.Elna.Frontend.SymbolTable + ( SymbolTable + , Info(..) + , ParameterInfo(..) + , builtInSymbolTable + , empty + , enter + , fromList + , lookup + , member + , scope + , toMap + , update + ) where + +import Data.HashMap.Strict (HashMap) +import qualified Data.HashMap.Strict as HashMap +import Data.List (sort) +import Data.List.NonEmpty (NonEmpty) +import qualified Data.List.NonEmpty as NonEmpty +import Data.Maybe (isJust) +import Data.Vector (Vector) +import qualified Data.Vector as Vector +import Language.Elna.Location (Identifier(..)) +import Language.Elna.Frontend.Types (Type(..), intType) +import Prelude hiding (lookup) + +data SymbolTable = SymbolTable (Maybe SymbolTable) (HashMap Identifier Info) + deriving (Eq, Show) + +empty :: SymbolTable +empty = SymbolTable Nothing HashMap.empty + +update :: (Info -> Maybe Info) -> Identifier -> SymbolTable -> SymbolTable +update updater key (SymbolTable parent mappings) = SymbolTable parent + $ HashMap.update updater key mappings + +scope :: SymbolTable -> SymbolTable -> SymbolTable +scope parent (SymbolTable _ mappings) = SymbolTable (Just parent) mappings + +builtInSymbolTable :: SymbolTable +builtInSymbolTable = SymbolTable Nothing $ HashMap.fromList + [ ("printi", ProcedureInfo empty Vector.empty) + , ("int", TypeInfo intType) + ] + +toMap :: SymbolTable -> HashMap Identifier Info +toMap (SymbolTable _ map') = map' + +enter :: Identifier -> Info -> SymbolTable -> Maybe SymbolTable +enter identifier info table@(SymbolTable parent hashTable) + | member identifier table = Nothing + | otherwise = Just + $ SymbolTable parent (HashMap.insert identifier info hashTable) + +lookup :: Identifier -> SymbolTable -> Maybe Info +lookup identifier (SymbolTable parent table) + | Just found <- HashMap.lookup identifier table = Just found + | Just parent' <- parent = lookup identifier parent' + | otherwise = Nothing + +member :: Identifier -> SymbolTable -> Bool +member identifier table = + isJust $ lookup identifier table + +fromList :: [(Identifier, Info)] -> Either (NonEmpty Identifier) SymbolTable +fromList elements + | Just identifierDuplicates' <- identifierDuplicates = + Left identifierDuplicates' + | otherwise = Right $ SymbolTable Nothing $ HashMap.fromList elements + where + identifierDuplicates = NonEmpty.nonEmpty + $ fmap NonEmpty.head + $ filter ((> 1) . NonEmpty.length) + $ NonEmpty.group . sort + $ fst <$> elements + +data ParameterInfo = ParameterInfo + { name :: Identifier + , type' :: Type + , isReferenceParameter :: Bool + } deriving (Eq, Show) + +data Info + = TypeInfo Type + | VariableInfo Bool Type + | ProcedureInfo SymbolTable (Vector ParameterInfo) + deriving (Eq, Show) |
