1 #include <boost/foreach.hpp>
3 #include <core/assert.hh>
4 #include <ast/node-factory.hh>
5 #include <ast/cast-tables.hh>
6 #include <ast/scope.hh>
7 #include <ast/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
)
76 if (node
.symbol
&& node
.symbol
->address
&&
77 node
.symbol
->address
->nodeType
== RegisterAddress::nodeTypeId())
81 Symbol
* s
= scope_
->findSymbol(node
.symbol
->name
);
89 TypeCheckerVisitor::visit(DereferenceExp
& node
)
91 node
.exp
->accept(*this);
92 Type
* unrefType
= unreferencedType(node
.exp
->type
);
93 assert_msg(unrefType
->nodeType
== PointerType::nodeTypeId(),
94 "You can't dereference a non pointer type");
95 PointerType
* type
= reinterpret_cast<PointerType
*> (unrefType
);
96 node
.type
= type
->type
;
100 TypeCheckerVisitor::visit(DereferenceByIndexExp
& node
)
102 node
.exp
->accept(*this);
103 node
.index
->accept(*this);
104 Type
* unrefType
= unreferencedType(node
.exp
->type
);
105 assert_msg(unrefType
->nodeType
== PointerType::nodeTypeId(),
106 "You can't dereference a non pointer type");
107 PointerType
* type
= reinterpret_cast<PointerType
*> (unrefType
);
108 node
.type
= type
->type
;
110 // @todo select the itype depending on the platforme pointer size
111 IntegerType
* itype
= new IntegerType
;
112 itype
->isSigned
= true;
114 node
.index
= castToType(itype
, node
.index
);
118 TypeCheckerVisitor::visit(Symbol
& node
)
121 const Symbol
* s
= scope_
->findSymbol(node
.name
);
128 TypeCheckerVisitor::visit(CastExp
& node
)
131 node
.exp
->accept(*this);
135 TypeCheckerVisitor::visit(CallExp
& node
)
137 super_t::visit(node
);
138 /// @todo generate the function's signature depending on parameters type
139 const Symbol
* s
= scope_
->findSymbol(node
.id
);
140 assert_msg(s
, "function not found in symbol table");
143 assert(s
->type
->nodeType
== FunctionType::nodeTypeId());
144 node
.ftype
= reinterpret_cast<FunctionType
*> (s
->type
);
145 node
.type
= node
.ftype
->returnType
;
147 assert(node
.ftype
->argsType
->size() >= node
.args
->size());
148 for (unsigned i
= 0; i
< node
.args
->size(); i
++)
149 (*node
.args
)[i
] = castToType((*node
.ftype
->argsType
)[i
], (*node
.args
)[i
]);
153 TypeCheckerVisitor::homogenizeTypes(BinaryExp
& node
)
155 CastExp
* castExp
= castToBestType(node
.left
->type
,
159 node
.type
= node
.left
->type
;
163 if (castExp
->type
== node
.left
->type
)
165 castExp
->exp
= node
.right
;
166 node
.right
= castExp
;
170 castExp
->exp
= node
.left
;
173 node
.type
= castExp
->type
;
176 #define VISIT_BINARY_ARITH(Type) \
178 TypeCheckerVisitor::visit(Type & node) \
180 node.left->accept(*this); \
181 node.right->accept(*this); \
183 * @todo check if type match \
184 * @todo look for an overloaded operator '+' \
185 * @todo the cast can be applied on both nodes \
187 homogenizeTypes(node); \
190 VISIT_BINARY_ARITH(AddExp
)
191 VISIT_BINARY_ARITH(SubExp
)
192 VISIT_BINARY_ARITH(MulExp
)
193 VISIT_BINARY_ARITH(DivExp
)
194 VISIT_BINARY_ARITH(ModExp
)
196 #define VISIT_BITWISE_EXP(Type) \
198 TypeCheckerVisitor::visit(Type & node) \
200 node.left->accept(*this); \
201 node.right->accept(*this); \
203 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node.left->type) && \
204 !AST_IS_FLOATING_POINT_TYPE(node.right->type), \
205 "throw and error here, can't do bitwise operation on float."); \
206 homogenizeTypes(node); \
209 VISIT_BITWISE_EXP(AndExp
)
210 VISIT_BITWISE_EXP(OrExp
)
211 VISIT_BITWISE_EXP(XorExp
)
213 VISIT_BITWISE_EXP(ShlExp
)
214 VISIT_BITWISE_EXP(AShrExp
)
215 VISIT_BITWISE_EXP(LShrExp
)
217 #define VISIT_BINARY_CMP_EXP(Type) \
219 TypeCheckerVisitor::visit(Type & node) \
221 node.left->accept(*this); \
222 node.right->accept(*this); \
224 * @todo check if type match \
225 * @todo look for an overloaded operator '+' \
226 * @todo the cast can be applied on both nodes \
228 homogenizeTypes(node); \
229 node.type = NodeFactory::createBoolType(); \
232 VISIT_BINARY_CMP_EXP(EqExp
)
233 VISIT_BINARY_CMP_EXP(NeqExp
)
234 VISIT_BINARY_CMP_EXP(LtExp
)
235 VISIT_BINARY_CMP_EXP(LtEqExp
)
236 VISIT_BINARY_CMP_EXP(GtExp
)
237 VISIT_BINARY_CMP_EXP(GtEqExp
)
239 #define VISIT_BINARY_BOOL_EXP(Type) \
241 TypeCheckerVisitor::visit(Type & node) \
243 node.type = NodeFactory::createBoolType(); \
245 node.left->accept(*this); \
246 node.right->accept(*this); \
248 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node.left->type) && \
249 !AST_IS_FLOATING_POINT_TYPE(node.right->type), \
250 "throw and error here, can't do bitwise operation on float."); \
252 node.left = castToType(node.type, node.left); \
253 node.right = castToType(node.type, node.right); \
256 VISIT_BINARY_BOOL_EXP(OrOrExp
)
257 VISIT_BINARY_BOOL_EXP(AndAndExp
)
260 TypeCheckerVisitor::visit(NegExp
& node
)
262 node
.exp
->accept(*this);
263 node
.type
= node
.exp
->type
;
267 TypeCheckerVisitor::visit(NotExp
& node
)
269 node
.exp
->accept(*this);
270 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node
.exp
->type
),
271 "throw and error here, can't do bitwise operation on float.");
272 node
.type
= node
.exp
->type
;
276 TypeCheckerVisitor::visit(BangExp
& node
)
278 node
.exp
->accept(*this);
279 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node
.exp
->type
),
280 "throw and error here, can't do bitwise operation on float.");
281 node
.type
= NodeFactory::createBoolType();
282 node
.exp
= castToType(node
.type
, node
.exp
);
286 TypeCheckerVisitor::visit(ConditionalBranch
& node
)
288 node
.cond
->accept(*this);
289 node
.cond
= castToType(NodeFactory::createBoolType(), node
.cond
);