elna/lib/Language/Elna/Frontend/SymbolTable.hs

110 lines
3.3 KiB
Haskell
Raw Normal View History

2024-12-11 21:44:32 +01:00
{- This Source Code Form is subject to the terms of the Mozilla Public License,
v. 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at https://mozilla.org/MPL/2.0/. -}
2024-10-02 22:56:15 +02:00
module Language.Elna.Frontend.SymbolTable
2024-09-08 02:08:13 +02:00
( SymbolTable
2024-09-20 13:32:24 +02:00
, Info(..)
2024-07-26 12:22:07 +02:00
, ParameterInfo(..)
2024-08-05 22:56:35 +02:00
, builtInSymbolTable
2024-09-20 13:32:24 +02:00
, empty
2024-07-29 07:26:47 +02:00
, enter
2024-08-04 12:23:19 +02:00
, fromList
2024-07-29 07:26:47 +02:00
, lookup
2024-09-20 13:32:24 +02:00
, member
, scope
2024-12-04 16:11:06 +01:00
, size
2024-09-20 13:32:24 +02:00
, toMap
, update
2024-07-26 12:22:07 +02:00
) where
import Data.HashMap.Strict (HashMap)
2024-07-29 07:26:47 +02:00
import qualified Data.HashMap.Strict as HashMap
2024-08-05 22:56:35 +02:00
import Data.List (sort)
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NonEmpty
2024-09-20 13:32:24 +02:00
import Data.Maybe (isJust)
2024-07-26 12:22:07 +02:00
import Data.Vector (Vector)
2024-09-24 22:20:57 +02:00
import qualified Data.Vector as Vector
2024-07-29 07:26:47 +02:00
import Language.Elna.Location (Identifier(..))
2024-10-02 22:56:15 +02:00
import Language.Elna.Frontend.Types (Type(..), intType)
2024-07-29 07:26:47 +02:00
import Prelude hiding (lookup)
2024-07-26 12:22:07 +02:00
2024-09-20 13:32:24 +02:00
data SymbolTable = SymbolTable (Maybe SymbolTable) (HashMap Identifier Info)
deriving (Eq, Show)
2024-07-26 12:22:07 +02:00
2024-09-20 13:32:24 +02:00
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
2024-07-26 12:22:07 +02:00
2024-08-04 12:23:19 +02:00
builtInSymbolTable :: SymbolTable
2024-09-20 13:32:24 +02:00
builtInSymbolTable = SymbolTable Nothing $ HashMap.fromList
2024-10-04 18:26:10 +02:00
[ ("printi", ProcedureInfo empty (Vector.singleton printiX))
, ("printc", ProcedureInfo empty (Vector.singleton printcI))
, ("exit", ProcedureInfo empty Vector.empty)
2024-07-29 07:26:47 +02:00
, ("int", TypeInfo intType)
]
2024-10-04 18:26:10 +02:00
where
printiX = ParameterInfo
{ name = "x"
, type' = intType
, isReferenceParameter = False
}
printcI = ParameterInfo
{ name = "i"
, type' = intType
, isReferenceParameter = False
}
2024-07-26 12:22:07 +02:00
2024-09-20 13:32:24 +02:00
toMap :: SymbolTable -> HashMap Identifier Info
toMap (SymbolTable _ map') = map'
2024-08-05 22:56:35 +02:00
enter :: Identifier -> Info -> SymbolTable -> Maybe SymbolTable
2024-09-20 13:32:24 +02:00
enter identifier info table@(SymbolTable parent hashTable)
2024-08-05 22:56:35 +02:00
| member identifier table = Nothing
| otherwise = Just
2024-09-20 13:32:24 +02:00
$ SymbolTable parent (HashMap.insert identifier info hashTable)
2024-07-26 12:22:07 +02:00
2024-07-29 07:26:47 +02:00
lookup :: Identifier -> SymbolTable -> Maybe Info
2024-09-20 13:32:24 +02:00
lookup identifier (SymbolTable parent table)
| Just found <- HashMap.lookup identifier table = Just found
| Just parent' <- parent = lookup identifier parent'
| otherwise = Nothing
2024-07-26 12:22:07 +02:00
2024-08-05 22:56:35 +02:00
member :: Identifier -> SymbolTable -> Bool
2024-09-20 13:32:24 +02:00
member identifier table =
isJust $ lookup identifier table
2024-08-05 22:56:35 +02:00
2024-12-04 16:11:06 +01:00
size :: SymbolTable -> Int
size (SymbolTable _ map') = HashMap.size map'
2024-08-05 22:56:35 +02:00
fromList :: [(Identifier, Info)] -> Either (NonEmpty Identifier) SymbolTable
fromList elements
| Just identifierDuplicates' <- identifierDuplicates =
Left identifierDuplicates'
2024-09-20 13:32:24 +02:00
| otherwise = Right $ SymbolTable Nothing $ HashMap.fromList elements
2024-08-05 22:56:35 +02:00
where
identifierDuplicates = NonEmpty.nonEmpty
$ fmap NonEmpty.head
$ filter ((> 1) . NonEmpty.length)
$ NonEmpty.group . sort
$ fst <$> elements
2024-08-04 12:23:19 +02:00
2024-07-26 12:22:07 +02:00
data ParameterInfo = ParameterInfo
{ name :: Identifier
, type' :: Type
, isReferenceParameter :: Bool
} deriving (Eq, Show)
data Info
= TypeInfo Type
| VariableInfo Bool Type
2024-07-26 12:22:07 +02:00
| ProcedureInfo SymbolTable (Vector ParameterInfo)
deriving (Eq, Show)