cast bool -> float
[ozulis.git] / src / ast / type-checker-visitor.cc
blobcd02a5292300adeedb739e64d7b2ebfe3e0b185b
1 #include <boost/foreach.hpp>
3 #include <core/assert.hh>
5 #include "type-checker-visitor.hh"
6 #include "scope.hh"
8 namespace ast
10 TypeCheckerVisitor::castTable_t TypeCheckerVisitor::castTable_;
12 TypeCheckerVisitor::TypeCheckerVisitor()
13 : BrowseVisitor(),
14 scope_()
16 #define ADD_CAST_TABLE_ENTRY(Type1, Type2, Method) \
17 do { \
18 const id_t id1 = Type1::nodeTypeId(); \
19 const id_t id2 = Type2::nodeTypeId(); \
20 castTableKey_t key; \
21 if (id1 < id2) \
22 key = std::make_pair(id1, id2); \
23 else \
24 key = std::make_pair(id2, id1); \
25 assert_msg(!castTable_.count(key), \
26 "the same key has been insterted two times"); \
27 castTable_[key] = TypeCheckerVisitor::Method; \
28 } while (0)
30 if (castTable_.empty())
32 ADD_CAST_TABLE_ENTRY(BoolType, BoolType, castBoolBool);
33 ADD_CAST_TABLE_ENTRY(BoolType, FloatType, castBoolFloat);
34 ADD_CAST_TABLE_ENTRY(BoolType, DoubleType, castBoolDouble);
35 ADD_CAST_TABLE_ENTRY(IntegerType, IntegerType, castIntegerInteger);
36 ADD_CAST_TABLE_ENTRY(IntegerType, FloatType, castIntegerFloat);
37 ADD_CAST_TABLE_ENTRY(IntegerType, DoubleType, castIntegerDouble);
38 ADD_CAST_TABLE_ENTRY(FloatType, FloatType, castFloatFloat);
39 ADD_CAST_TABLE_ENTRY(FloatType, DoubleType, castFloatDouble);
43 TypeCheckerVisitor::~TypeCheckerVisitor()
47 void
48 TypeCheckerVisitor::visit(File & node)
50 scope_ = node.scope;
51 super_t::visit(node);
54 void
55 TypeCheckerVisitor::visit(Block & node)
57 scope_ = node.scope;
58 // We must respect this order
59 BOOST_FOREACH (Node * varDecl, (*node.varDecls))
60 varDecl->accept(*this);
61 BOOST_FOREACH (Node * statement, (*node.statements))
62 statement->accept(*this);
65 void
66 TypeCheckerVisitor::visit(AssignExp & node)
68 node.dest->accept(*this);
69 node.value->accept(*this);
70 CastExp * castExp = new CastExp();
71 castExp->type = node.dest->type;
72 castExp->exp = node.value;
73 assert(node.dest->type);
74 node.value = castExp;
77 void
78 TypeCheckerVisitor::visit(IdExp & node)
80 assert(scope_);
81 const Symbol * s = scope_->findSymbol(node.name);
82 assert(s);
83 assert(s->type);
84 node.type = s->type;
87 void
88 TypeCheckerVisitor::visit(Symbol & node)
90 assert(scope_);
91 const Symbol * s = scope_->findSymbol(node.name);
92 assert(s);
93 assert(s->type);
94 node.type = s->type;
97 void
98 TypeCheckerVisitor::visit(CastExp & node)
100 assert(node.exp);
101 node.exp->accept(*this);
104 #define VISIT(Type) \
105 void \
106 TypeCheckerVisitor::visit(Type & node) \
108 node.left->accept(*this); \
109 node.right->accept(*this); \
110 /** \
111 * @todo check if type match \
112 * @todo look for an overloaded operator '+' \
113 * @todo the cast can be applied on both nodes \
114 */ \
115 CastExp * castExp = findCast(node.left->type, node.right->type); \
117 if (!castExp) \
119 node.type = node.left->type; \
120 return; \
123 if (castExp->type == node.left->type) \
125 castExp->exp = node.right; \
126 node.right = castExp; \
128 else \
130 castExp->exp = node.left; \
131 node.left = castExp; \
133 node.type = castExp->type; \
136 VISIT(AddExp)
137 VISIT(SubExp)
138 VISIT(MulExp)
139 VISIT(DivExp)
140 VISIT(ModExp)
142 VISIT(AndExp)
143 VISIT(OrExp)
144 VISIT(XorExp)
146 VISIT(ShlExp)
147 VISIT(AShrExp)
148 VISIT(LShrExp)
150 VISIT(EqExp)
151 VISIT(NeqExp)
152 VISIT(LtExp)
153 VISIT(LtEqExp)
154 VISIT(GtExp)
155 VISIT(GtEqExp)
157 CastExp *
158 TypeCheckerVisitor::findCast(Type * type1,
159 Type * type2)
161 assert(type1);
162 assert(type2);
164 castTableKey_t key;
165 if (type1->nodeType < type2->nodeType)
166 key = std::make_pair(type1->nodeType, type2->nodeType);
167 else
168 key = std::make_pair(type2->nodeType, type1->nodeType);
169 assert(castTable_.count(key) > 0);
171 CastExp * castExp = castTable_[key](type1, type2);
172 return castExp;
175 #define DUMMY_CAST(Type1, Type2) \
176 CastExp * \
177 TypeCheckerVisitor::cast##Type1##Type2(Type * /*type1*/, \
178 Type * /*type2*/) \
180 return 0; \
183 DUMMY_CAST(Bool, Bool)
184 DUMMY_CAST(Float, Float)
186 #define TRIVIAL_CAST(Type1, Type2) \
187 CastExp * \
188 TypeCheckerVisitor::cast##Type1##Type2(Type * type1, \
189 Type * type2) \
191 CastExp * castExp = new CastExp(); \
193 if (type1->nodeType == Type2##Type::nodeTypeId()) \
194 castExp->type = type1; \
195 else \
196 castExp->type = type2; \
197 return castExp; \
200 TRIVIAL_CAST(Bool, Integer)
201 TRIVIAL_CAST(Bool, Float)
202 TRIVIAL_CAST(Bool, Double)
203 TRIVIAL_CAST(Integer, Float)
204 TRIVIAL_CAST(Integer, Double)
205 TRIVIAL_CAST(Float, Double)
207 CastExp *
208 TypeCheckerVisitor::castIntegerInteger(Type * type1,
209 Type * type2)
211 CastExp * castExp = 0;
212 IntegerType * itype1 = reinterpret_cast<IntegerType *> (type1);
213 IntegerType * itype2 = reinterpret_cast<IntegerType *> (type2);
215 if (itype1->size == itype2->size && itype1->isSigned == itype2->isSigned)
216 return 0;
217 castExp = new CastExp();
218 if (itype1->size > itype2->size)
219 castExp->type = itype1;
220 else
221 castExp->type = itype2;
222 return castExp;