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()
23 TypeCheckerVisitor::check(T
*& node
)
29 node
= reinterpret_cast<T
*> (replacement_
);
35 TypeCheckerVisitor::visit(File
& node
)
42 TypeCheckerVisitor::visit(Function
& node
)
44 /// @todo check that the last statement is a branch or a return
45 currentFunction_
= &node
;
50 TypeCheckerVisitor::visit(Block
& node
)
53 // We must respect this order
54 BOOST_FOREACH (VarDecl
*& varDecl
, (*node
.varDecls
))
56 BOOST_FOREACH (Node
*& statement
, (*node
.statements
))
61 TypeCheckerVisitor::visit(Return
& node
)
64 if (!isSameType(node
.exp
->type
, currentFunction_
->returnType
))
66 CastExp
* castExp
= new CastExp
;
67 castExp
->exp
= node
.exp
;
68 castExp
->type
= currentFunction_
->returnType
;
74 TypeCheckerVisitor::visit(AssignExp
& node
)
78 CastExp
* castExp
= new CastExp();
79 castExp
->type
= node
.dest
->type
;
80 castExp
->exp
= node
.value
;
81 assert(node
.dest
->type
);
83 node
.type
= node
.dest
->type
;
87 TypeCheckerVisitor::visit(IdExp
& node
)
89 if (node
.symbol
&& node
.symbol
->address
&&
90 node
.symbol
->address
->nodeType
== RegisterAddress::nodeTypeId())
94 Symbol
* s
= scope_
->findSymbol(node
.symbol
->name
);
102 TypeCheckerVisitor::visit(DereferenceExp
& node
)
105 Type
* unrefType
= unreferencedType(node
.exp
->type
);
106 assert_msg(unrefType
->nodeType
== PointerType::nodeTypeId(),
107 "You can't dereference a non pointer type");
108 PointerType
* type
= reinterpret_cast<PointerType
*> (unrefType
);
109 node
.type
= type
->type
;
113 TypeCheckerVisitor::visit(DereferenceByIndexExp
& node
)
117 Type
* unrefType
= unreferencedType(node
.exp
->type
);
118 assert_msg(unrefType
->nodeType
== PointerType::nodeTypeId(),
119 "You can't dereference a non pointer type");
120 PointerType
* type
= reinterpret_cast<PointerType
*> (unrefType
);
121 node
.type
= type
->type
;
123 // @todo select the itype depending on the platforme pointer size
124 IntegerType
* itype
= new IntegerType
;
125 itype
->isSigned
= true;
127 node
.index
= castToType(itype
, node
.index
);
131 TypeCheckerVisitor::visit(Symbol
& node
)
134 const Symbol
* s
= scope_
->findSymbol(node
.name
);
141 TypeCheckerVisitor::visit(CastExp
& node
)
148 TypeCheckerVisitor::visit(CallExp
& node
)
150 super_t::visit(node
);
151 /// @todo generate the function's signature depending on parameters type
152 const Symbol
* s
= scope_
->findSymbol(node
.id
);
153 assert_msg(s
, "function not found in symbol table");
156 assert(s
->type
->nodeType
== FunctionType::nodeTypeId());
157 node
.ftype
= reinterpret_cast<FunctionType
*> (s
->type
);
158 node
.type
= node
.ftype
->returnType
;
160 assert(node
.ftype
->argsType
->size() >= node
.args
->size());
161 for (unsigned i
= 0; i
< node
.args
->size(); i
++)
162 (*node
.args
)[i
] = castToType((*node
.ftype
->argsType
)[i
], (*node
.args
)[i
]);
166 TypeCheckerVisitor::homogenizeTypes(BinaryExp
& node
)
168 CastExp
* castExp
= castToBestType(node
.left
->type
,
172 node
.type
= node
.left
->type
;
176 if (castExp
->type
== node
.left
->type
)
178 castExp
->exp
= node
.right
;
179 node
.right
= castExp
;
183 castExp
->exp
= node
.left
;
186 node
.type
= castExp
->type
;
191 * - compute the new address:
192 * - addrui = ptrtoui addr
193 * - offset = index * sizeof(*addr)
194 * - newaddrui = ptrtoui + offset
195 * - newaddr = cast(*, newaddrui)
198 TypeCheckerVisitor::pointerArith(Exp
* pointer
, Exp
* offset
)
200 assert(unreferencedType(offset
->type
)->nodeType
!= PointerType::nodeTypeId());
201 PointerType
* pointerType
=
202 reinterpret_cast<PointerType
*> (unreferencedType(pointer
->type
));
204 /* cast node.exp to uint */
205 CastExp
* cast1
= NodeFactory::createCastPtrToUInt(pointer
);
207 /* compute the offset */
208 MulExp
* mul
= new MulExp
;
210 mul
->right
= NodeFactory::createSizeofValue(pointerType
->type
);
212 /* add the offset to the uint addr */
213 AddExp
* add
= new AddExp
;
217 /* cast uint addr to ptr */
218 CastExp
* cast2
= NodeFactory::createCastUIntToPtr(add
, unreferencedType(pointerType
));
221 replacement_
= cast2
;
224 #define VISIT_ADD_EXP(Type) \
226 TypeCheckerVisitor::visit(Type & node) \
230 if (unreferencedType(node.left->type)->nodeType == \
231 PointerType::nodeTypeId()) \
232 pointerArith(node.left, node.right); \
233 else if (unreferencedType(node.right->type)->nodeType == \
234 PointerType::nodeTypeId()) \
235 pointerArith(node.right, node.left); \
237 homogenizeTypes(node); \
240 #define VISIT_BINARY_ARITH(Type) \
242 TypeCheckerVisitor::visit(Type & node) \
246 homogenizeTypes(node); \
249 VISIT_ADD_EXP(AddExp
)
250 VISIT_ADD_EXP(SubExp
)
251 VISIT_BINARY_ARITH(MulExp
)
252 VISIT_BINARY_ARITH(DivExp
)
253 VISIT_BINARY_ARITH(ModExp
)
255 #define VISIT_BITWISE_EXP(Type) \
257 TypeCheckerVisitor::visit(Type & node) \
262 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node.left->type) && \
263 !AST_IS_FLOATING_POINT_TYPE(node.right->type), \
264 "throw and error here, can't do bitwise operation on float."); \
265 homogenizeTypes(node); \
268 VISIT_BITWISE_EXP(AndExp
)
269 VISIT_BITWISE_EXP(OrExp
)
270 VISIT_BITWISE_EXP(XorExp
)
272 VISIT_BITWISE_EXP(ShlExp
)
273 VISIT_BITWISE_EXP(AShrExp
)
274 VISIT_BITWISE_EXP(LShrExp
)
276 #define VISIT_BINARY_CMP_EXP(Type) \
278 TypeCheckerVisitor::visit(Type & node) \
283 * @todo check if type match \
284 * @todo look for an overloaded operator '+' \
285 * @todo the cast can be applied on both nodes \
287 homogenizeTypes(node); \
288 node.type = NodeFactory::createBoolType(); \
291 VISIT_BINARY_CMP_EXP(EqExp
)
292 VISIT_BINARY_CMP_EXP(NeqExp
)
293 VISIT_BINARY_CMP_EXP(LtExp
)
294 VISIT_BINARY_CMP_EXP(LtEqExp
)
295 VISIT_BINARY_CMP_EXP(GtExp
)
296 VISIT_BINARY_CMP_EXP(GtEqExp
)
298 #define VISIT_BINARY_BOOL_EXP(Type) \
300 TypeCheckerVisitor::visit(Type & node) \
302 node.type = NodeFactory::createBoolType(); \
307 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node.left->type) && \
308 !AST_IS_FLOATING_POINT_TYPE(node.right->type), \
309 "throw and error here, can't do bitwise operation on float."); \
311 node.left = castToType(node.type, node.left); \
312 node.right = castToType(node.type, node.right); \
315 VISIT_BINARY_BOOL_EXP(OrOrExp
)
316 VISIT_BINARY_BOOL_EXP(AndAndExp
)
319 TypeCheckerVisitor::visit(NegExp
& node
)
322 node
.type
= node
.exp
->type
;
326 TypeCheckerVisitor::visit(NotExp
& node
)
329 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node
.exp
->type
),
330 "throw and error here, can't do bitwise operation on float.");
331 node
.type
= node
.exp
->type
;
335 TypeCheckerVisitor::visit(BangExp
& node
)
338 assert_msg(!AST_IS_FLOATING_POINT_TYPE(node
.exp
->type
),
339 "throw and error here, can't do bitwise operation on float.");
340 node
.type
= NodeFactory::createBoolType();
341 node
.exp
= castToType(node
.type
, node
.exp
);
345 TypeCheckerVisitor::visit(ConditionalBranch
& node
)
348 node
.cond
= castToType(NodeFactory::createBoolType(), node
.cond
);