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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
|
module Codegen(module Codegen, A.Module) where
import qualified Data.Map.Strict as Map
-- import qualified LLVM.General.AST.Type as A
-- import qualified LLVM.General.AST.Global as A
-- import qualified LLVM.General.AST.Constant as A.C
-- import qualified LLVM.General.AST.Operand as A
-- import qualified LLVM.General.AST.Name as A
-- import qualified LLVM.General.AST.Instruction as A
import qualified LLVM.General.AST as A
import AST
type Error a = Either String a
codegen :: Program -- Program to compile
-> String -- Module name
-> String -- File name of source
-> Error A.Module
codegen prog name fname = do
defs <- generateDefs (preprocess prog)
return $ A.defaultModule {
A.moduleName = name,
A.moduleSourceFileName = fname,
A.moduleDefinitions = defs
}
preprocess :: Program -> Program
preprocess prog@(Program decls) = mapProgram' filtered mapper
where
filtered = Program $ filter notTypedef decls
mapper = defaultPM' {typeHandler' = typeReplacer (findTypeRenames prog)}
notTypedef :: Declaration -> Bool
notTypedef (DecTypedef _ _) = False
notTypedef _ = True
typeReplacer :: Map.Map Name Type -> Type -> Type
typeReplacer m t@(TypeName n) = maybe t id $ Map.lookup n m
typeReplacer _ t = t
findTypeRenames :: Program -> Map.Map Name Type
findTypeRenames (Program d) = foldl go Map.empty d
where
go :: Map.Map Name Type -> Declaration -> Map.Map Name Type
go m (DecTypedef t n) = Map.insert n t m
go m _ = m
generateDefs :: Program -> Error [A.Definition]
generateDefs prog = do
checkUndefinedTypes prog
checkUndefinedVars prog
fail "TODO"
return []
checkUndefinedTypes :: Program -> Error ()
checkUndefinedTypes prog = fmap (const ()) $ mapProgram prog $ defaultPM {typeHandler = check}
where
check :: Type -> Error Type
check (TypeName n) = Left $ "Undefined type name '" ++ n ++ "'"
check t = Right t
-- checkUndefinedVars :: Program -> Error ()
-- checkUndefinedVars prog = do
-- mapTypes' :: Program -> (Type -> Type) -> Program
-- mapTypes' prog f = (\(Right res) -> res) $ mapTypes prog (return . f)
-- mapTypes :: Program -> (Type -> Error Type) -> Error Program
-- mapTypes (Program decls) f = Program <$> sequence (map goD decls)
-- where
-- handler :: Type -> Error Type
-- handler (TypePtr t) = f t >>= f . TypePtr
-- handler t = f t
-- goD :: Declaration -> Error Declaration
-- goD (DecFunction t n a b) = do
-- rt <- handler t
-- ra <- sequence $ map (\(at,an) -> (\art -> (art,an)) <$> handler at) a
-- rb <- goB b
-- return $ DecFunction rt n ra rb
-- goD (DecVariable t n v) = (\rt -> DecVariable rt n v) <$> handler t
-- goD (DecTypedef t n) = (\rt -> DecTypedef rt n) <$> handler t
-- goB :: Block -> Error Block
-- goB (Block stmts) = Block <$> sequence (map goS stmts)
-- goS :: Statement -> Error Statement
-- goS (StBlock bl) = StBlock <$> goB bl
-- goS (StVarDeclaration t n e) = (\rt -> StVarDeclaration rt n e) <$> handler t
-- goS (StIf c t e) = do
-- rt <- goS t
-- re <- goS e
-- return $ StIf c rt re
-- goS (StWhile c b) = StWhile c <$> goS b
-- goS s = return s
type MapperHandler a = a -> Error a
data ProgramMapper = ProgramMapper
{declarationHandler :: MapperHandler Declaration
,blockHandler :: MapperHandler Block
,typeHandler :: MapperHandler Type
,literalHandler :: MapperHandler Literal
,binOpHandler :: MapperHandler BinaryOperator
,unOpHandler :: MapperHandler UnaryOperator
,expressionHandler :: MapperHandler Expression
,statementHandler :: MapperHandler Statement
,nameHandler :: MapperHandler Name}
type MapperHandler' a = a -> a
data ProgramMapper' = ProgramMapper'
{declarationHandler' :: MapperHandler' Declaration
,blockHandler' :: MapperHandler' Block
,typeHandler' :: MapperHandler' Type
,literalHandler' :: MapperHandler' Literal
,binOpHandler' :: MapperHandler' BinaryOperator
,unOpHandler' :: MapperHandler' UnaryOperator
,expressionHandler' :: MapperHandler' Expression
,statementHandler' :: MapperHandler' Statement
,nameHandler' :: MapperHandler' Name}
defaultPM :: ProgramMapper
defaultPM = ProgramMapper return return return return return return return return return
defaultPM' :: ProgramMapper'
defaultPM' = ProgramMapper' id id id id id id id id id
mapProgram' :: Program -> ProgramMapper' -> Program
mapProgram' prog mapper = (\(Right r) -> r) $ mapProgram prog $ ProgramMapper
{declarationHandler = return . declarationHandler' mapper
,blockHandler = return . blockHandler' mapper
,typeHandler = return . typeHandler' mapper
,literalHandler = return . literalHandler' mapper
,binOpHandler = return . binOpHandler' mapper
,unOpHandler = return . unOpHandler' mapper
,expressionHandler = return . expressionHandler' mapper
,statementHandler = return . statementHandler' mapper
,nameHandler = return . nameHandler' mapper}
mapProgram :: Program -> ProgramMapper -> Error Program
mapProgram prog mapper = goP prog
where
h_d = declarationHandler mapper
h_b = blockHandler mapper
h_t = typeHandler mapper
h_l = literalHandler mapper
h_bo = binOpHandler mapper
h_uo = unOpHandler mapper
h_e = expressionHandler mapper
h_s = statementHandler mapper
h_n = nameHandler mapper
goP :: Program -> Error Program
goP (Program decls) = Program <$> sequence (map (\d -> goD d >>= h_d) decls)
goD :: Declaration -> Error Declaration
goD (DecFunction t n a b) = do
rt <- goT t
rn <- goN n
ra <- sequence $ map (\(at,an) -> (,) <$> goT at <*> goN an) a
rb <- goB b
h_d $ DecFunction rt rn ra rb
goD (DecVariable t n mv) = do
rt <- goT t
rn <- goN n
rmv <- sequence $ fmap goE mv
h_d $ DecVariable rt rn rmv
goD (DecTypedef t n) = do
rt <- goT t
rn <- goN n
h_d $ DecTypedef rt rn
goT :: Type -> Error Type
goT (TypePtr t) = goT t >>= (h_t . TypePtr)
goT (TypeName n) = goN n >>= (h_t . TypeName)
goT t = h_t t
goN :: Name -> Error Name
goN = h_n
goB :: Block -> Error Block
goB (Block sts) = (Block <$> sequence (map goS sts)) >>= h_b
goE :: Expression -> Error Expression
goE (ExLit l) = goL l >>= (h_e . ExLit)
goE (ExBinOp bo e1 e2) = do
rbo <- goBO bo
re1 <- goE e1
re2 <- goE e2
h_e $ ExBinOp rbo re1 re2
goE (ExUnOp uo e) = do
ruo <- goUO uo
re <- goE e
h_e $ ExUnOp ruo re
goS :: Statement -> Error Statement
goS StEmpty = h_s StEmpty
goS (StBlock b) = goB b >>= (h_s . StBlock)
goS (StExpr e) = goE e >>= (h_s . StExpr)
goS (StVarDeclaration t n me) = do
rt <- goT t
rn <- goN n
rme <- sequence $ fmap goE me
h_s $ StVarDeclaration rt rn rme
goS (StAssignment n e) = do
rn <- goN n
re <- goE e
h_s $ StAssignment rn re
goS (StIf e s1 s2) = do
re <- goE e
rs1 <- goS s1
rs2 <- goS s2
h_s $ StIf re rs1 rs2
goS (StWhile e s) = do
re <- goE e
rs <- goS s
h_s $ StWhile re rs
goS (StReturn e) = goE e >>= (h_s . StReturn)
goL :: Literal -> Error Literal
goL (LitVar n) = goN n >>= (h_l . LitVar)
goL (LitCall n a) = do
rn <- goN n
ra <- sequence $ map goE a
h_l $ LitCall rn ra
goBO :: BinaryOperator -> Error BinaryOperator
goBO = h_bo
goUO :: UnaryOperator -> Error UnaryOperator
goUO = h_uo
|