1 #include <boost/foreach.hpp>
3 #include <core/assert.hh>
5 #include <ast/cast-tables.hh>
6 #include <ast/scope.hh>
7 #include "type-checker-visitor.hh"
11 TypeCheckerVisitor::TypeCheckerVisitor()
17 TypeCheckerVisitor::~TypeCheckerVisitor()
22 TypeCheckerVisitor::visit(File
& node
)
29 TypeCheckerVisitor::visit(Function
& node
)
31 /// @todo check that the last statement is a branch or a return
32 currentFunction_
= &node
;
37 TypeCheckerVisitor::visit(Block
& node
)
40 // We must respect this order
41 BOOST_FOREACH (Node
* varDecl
, (*node
.varDecls
))
42 varDecl
->accept(*this);
43 BOOST_FOREACH (Node
* statement
, (*node
.statements
))
44 statement
->accept(*this);
48 TypeCheckerVisitor::visit(Return
& node
)
50 node
.exp
->accept(*this);
51 if (!isSameType(node
.exp
->type
, currentFunction_
->returnType
))
53 CastExp
* castExp
= new CastExp
;
54 castExp
->exp
= node
.exp
;
55 castExp
->type
= currentFunction_
->returnType
;
61 TypeCheckerVisitor::visit(AssignExp
& node
)
63 node
.dest
->accept(*this);
64 node
.value
->accept(*this);
65 CastExp
* castExp
= new CastExp();
66 castExp
->type
= node
.dest
->type
;
67 castExp
->exp
= node
.value
;
68 assert(node
.dest
->type
);
70 node
.type
= node
.dest
->type
;
74 TypeCheckerVisitor::visit(IdExp
& node
)
77 Symbol
* s
= scope_
->findSymbol(node
.symbol
->name
);
85 TypeCheckerVisitor::visit(DereferenceExp
& node
)
87 node
.exp
->accept(*this);
88 Type
* unrefType
= unreferencedType(node
.exp
->type
);
89 assert_msg(unrefType
->nodeType
== PointerType::nodeTypeId(),
90 "You can't dereference a non pointer type");
91 PointerType
* type
= reinterpret_cast<PointerType
*> (unrefType
);
92 node
.type
= type
->type
;
96 TypeCheckerVisitor::visit(Symbol
& node
)
99 const Symbol
* s
= scope_
->findSymbol(node
.name
);
106 TypeCheckerVisitor::visit(CastExp
& node
)
109 node
.exp
->accept(*this);
113 TypeCheckerVisitor::visit(CallExp
& node
)
115 super_t::visit(node
);
116 /// @todo generate the function's signature depending on parameters type
117 const Symbol
* s
= scope_
->findSymbol(node
.id
);
118 assert_msg(s
, "function not found in symbol table");
121 assert(s
->type
->nodeType
== FunctionType::nodeTypeId());
122 node
.ftype
= reinterpret_cast<FunctionType
*> (s
->type
);
123 node
.type
= node
.ftype
->returnType
;
125 assert(node
.ftype
->argsType
->size() >= node
.args
->size());
126 for (unsigned i
= 0; i
< node
.args
->size(); i
++)
127 (*node
.args
)[i
] = castToType((*node
.ftype
->argsType
)[i
], (*node
.args
)[i
]);
130 #define VISIT(Type) \
132 TypeCheckerVisitor::visit(Type & node) \
134 node.left->accept(*this); \
135 node.right->accept(*this); \
137 * @todo check if type match \
138 * @todo look for an overloaded operator '+' \
139 * @todo the cast can be applied on both nodes \
141 CastExp * castExp = castToBestType(node.left->type, \
146 node.type = node.left->type; \
150 if (castExp->type == node.left->type) \
152 castExp->exp = node.right; \
153 node.right = castExp; \
157 castExp->exp = node.left; \
158 node.left = castExp; \
160 node.type = castExp->type; \
169 #define VISIT_BITWISE_EXP(Type) \
171 TypeCheckerVisitor::visit(Type & node) \
173 node.left->accept(*this); \
174 node.right->accept(*this); \
176 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node.left->type) && \
177 !AST_IS_FLOATING_POINT_TYPE(node.right->type), \
178 "throw and error here, can't do bitwise operation on float."); \
179 CastExp * castExp = castToBestType(node.left->type, \
184 node.type = node.left->type; \
188 if (castExp->type == node.left->type) \
190 castExp->exp = node.right; \
191 node.right = castExp; \
195 castExp->exp = node.left; \
196 node.left = castExp; \
198 node.type = castExp->type; \
201 VISIT_BITWISE_EXP(AndExp
)
202 VISIT_BITWISE_EXP(OrExp
)
203 VISIT_BITWISE_EXP(XorExp
)
205 VISIT_BITWISE_EXP(ShlExp
)
206 VISIT_BITWISE_EXP(AShrExp
)
207 VISIT_BITWISE_EXP(LShrExp
)
209 #define VISIT_BINARY_CMP_EXP(Type) \
211 TypeCheckerVisitor::visit(Type & node) \
213 node.left->accept(*this); \
214 node.right->accept(*this); \
215 node.type = new BoolType; \
217 * @todo check if type match \
218 * @todo look for an overloaded operator '+' \
219 * @todo the cast can be applied on both nodes \
221 CastExp * castExp = castToBestType(node.left->type, \
227 if (castExp->type == node.left->type) \
229 castExp->exp = node.right; \
230 node.right = castExp; \
234 castExp->exp = node.left; \
235 node.left = castExp; \
239 VISIT_BINARY_CMP_EXP(EqExp
)
240 VISIT_BINARY_CMP_EXP(NeqExp
)
241 VISIT_BINARY_CMP_EXP(LtExp
)
242 VISIT_BINARY_CMP_EXP(LtEqExp
)
243 VISIT_BINARY_CMP_EXP(GtExp
)
244 VISIT_BINARY_CMP_EXP(GtEqExp
)
246 #define VISIT_BINARY_BOOL_EXP(Type) \
248 TypeCheckerVisitor::visit(Type & node) \
250 node.type = new BoolType; \
252 node.left->accept(*this); \
253 node.right->accept(*this); \
255 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node.left->type) && \
256 !AST_IS_FLOATING_POINT_TYPE(node.right->type), \
257 "throw and error here, can't do bitwise operation on float."); \
259 if (node.left->type->nodeType != BoolType::nodeTypeId()) \
261 CastExp * castExp = new CastExp; \
262 castExp->type = node.type; \
263 castExp->exp = node.left; \
264 node.left = castExp; \
266 if (node.right->type->nodeType != BoolType::nodeTypeId()) \
268 CastExp * castExp = new CastExp; \
269 castExp->type = node.type; \
270 castExp->exp = node.right; \
271 node.right = castExp; \
275 VISIT_BINARY_BOOL_EXP(OrOrExp
)
276 VISIT_BINARY_BOOL_EXP(AndAndExp
)
279 TypeCheckerVisitor::visit(NegExp
& node
)
281 node
.exp
->accept(*this);
282 node
.type
= node
.exp
->type
;
286 TypeCheckerVisitor::visit(NotExp
& node
)
288 node
.exp
->accept(*this);
289 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node
.exp
->type
),
290 "throw and error here, can't do bitwise operation on float.");
291 node
.type
= node
.exp
->type
;
295 TypeCheckerVisitor::visit(BangExp
& node
)
297 node
.exp
->accept(*this);
298 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node
.exp
->type
),
299 "throw and error here, can't do bitwise operation on float.");
300 node
.type
= new BoolType
;
301 if (node
.exp
->type
->nodeType
!= BoolType::nodeTypeId())
303 CastExp
* castExp
= new CastExp
;
304 castExp
->exp
= node
.exp
;
305 castExp
->type
= node
.type
;
311 TypeCheckerVisitor::visit(ConditionalBranch
& node
)
313 node
.cond
->accept(*this);
314 if (node
.cond
->type
->nodeType
== BoolType::nodeTypeId())
317 CastExp
* castExp
= new CastExp
;
318 castExp
->exp
= node
.cond
;
319 castExp
->type
= new BoolType
;