-
Notifications
You must be signed in to change notification settings - Fork 1
/
SymbolTable.hs
166 lines (143 loc) · 3.82 KB
/
SymbolTable.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
module SymbolTable
( Variable(..)
, ScopeType(..)
, SymbolTable(..)
, varType
, empty
, insert
, delete
, deepUpdate
, update
, SymbolTable.elem
, deepLookup
, lookup
) where
import Data.List (intercalate)
import qualified Data.Set as Set (Set(..), toAscList)
import qualified Data.Map as Map (
Map(..)
, delete
, empty
, insert
, lookup
, member
, null
, toList
)
import Control.Monad (mplus)
import Prelude hiding (lookup)
import AST (Inst(..), Type(..), tabs)
data ScopeType
= ProgramScope
| WhileScope
| IfScope
| BlockScope
| ForScope
deriving (Eq)
instance Show ScopeType where
show x = case x of
ProgramScope -> "Program"
WhileScope -> "While"
IfScope -> "If"
BlockScope -> "Block"
ForScope -> "For"
varType :: Variable -> Type
varType (IntVar _) = IntType
varType (BoolVar _) = BoolType
varType (SetVar _) = SetType
varType (StrVar _) = StrType
data Variable
= BoolVar { getBool :: Bool }
| IntVar { getInt :: Int }
| SetVar { getSet :: (Set.Set Int) }
| StrVar { getStr :: String }
deriving (Eq, Ord)
instance Show Variable where
show (BoolVar True) = "true"
show (BoolVar False) = "false"
show (IntVar i) = show i
show (SetVar elems) =
"{" ++ (intercalate ", " $ map show (Set.toAscList elems)) ++ "}"
show (StrVar s) = s
data SymbolTable
= SymbolTable
{ scopeType :: ScopeType
, variables :: Map.Map String Variable
, daughters :: [SymbolTable]
, instructions :: [Inst]
}
instance Show SymbolTable where
show = show' 0
show' :: Int -> SymbolTable -> String
show' n (SymbolTable scopeType variables daughters instructions) =
tabs n ++ "SCOPE (" ++ show scopeType ++ ")\n" ++ (
if Map.null variables
then ""
else
tabs (n+1) ++ (
intercalate
("\n" ++ (tabs (n+1)))
(map show'' (Map.toList variables))
) ++ "\n"
) ++ (
concat $ map (show' (n+1)) daughters
)
show'' :: (String, Variable) -> String
show'' (name, var) =
name ++ " :: " ++ (
case var of
(BoolVar x) -> "bool"
(IntVar x) -> "int"
(SetVar x) -> "set"
(StrVar x) -> "str"
) ++ ", value = " ++ show var
empty :: SymbolTable
empty =
SymbolTable
{ scopeType = ProgramScope
, variables = Map.empty
, daughters = []
, instructions = []
}
insert' :: String -> Variable -> SymbolTable -> SymbolTable
insert' name var (SymbolTable scopeType variables daughters instructions) =
SymbolTable
scopeType
(Map.insert name var (variables))
daughters
instructions
insert :: String -> Variable -> SymbolTable -> SymbolTable
insert name var st =
if name `Map.member` (variables st)
then error ("Variable " ++ name ++ " already declared in this scope.")
else insert' name var st
delete :: String -> SymbolTable -> SymbolTable
delete name (SymbolTable scopeType variables daughters instructions) =
SymbolTable
scopeType
(Map.delete name (variables))
daughters
instructions
deepUpdate :: String -> Variable -> [SymbolTable] -> [SymbolTable]
deepUpdate name var [] =
[]
deepUpdate name var (st:sts) =
if name `Map.member` (variables st)
then (insert' name var st):sts
else st:(deepUpdate name var sts)
update :: String -> Variable -> SymbolTable -> SymbolTable
update name var st =
if name `Map.member` (variables st)
then insert' name var st
else error ("Variable " ++ name ++ " not declared in this scope.")
elem :: String -> SymbolTable -> Bool
elem name st =
name `Map.member` (variables st)
deepLookup :: String -> [SymbolTable] -> Maybe (Variable, ScopeType)
deepLookup s sts =
foldr mplus Nothing $ map (lookup s) sts
lookup :: String -> SymbolTable -> Maybe (Variable, ScopeType)
lookup name st =
case name `Map.lookup` (variables st) of
Just x -> Just (x, scopeType st)
Nothing -> Nothing