[ozulis] fixed some memory leaks
[ozulis.git] / src / ozulis / ast / cast-tables.cc
blobe19a138671648ee7af68720f05d3f7e675725db0
1 #include <ozulis/core/multi-method.hh>
2 #include <ozulis/ast/ast-cast.hh>
3 #include "cast-tables.hh"
5 #define DUMMY_CAST(Type1, Type2) \
6 static CastExp * \
7 cast##Type1##Type2(Type * /*type1*/, \
8 Type * /*type2*/) \
9 { \
10 return 0; \
13 #define TRIVIAL_CAST(Type1, Type2) \
14 static CastExp * \
15 cast##Type1##Type2(Type * type1, \
16 Type * type2) \
17 { \
18 CastExp * castExp = new CastExp(); \
20 if (type1->nodeType == Type2##Type::nodeTypeId()) \
21 castExp->type = type1; \
22 else \
23 castExp->type = type2; \
24 return castExp; \
27 #define ADD_SYMETRIC_ENTRY(Type1, Type2) \
28 table.addEntry(cast##Type1##Type2, \
29 Type1##Type::nodeTypeId(), \
30 Type2##Type::nodeTypeId()); \
31 table.addEntry(cast##Type1##Type2, \
32 Type2##Type::nodeTypeId(), \
33 Type1##Type::nodeTypeId());
35 namespace ozulis
37 namespace ast
39 typedef CastExp * (*castFunc_t)(Type * type1, Type * type2);
40 typedef core::DispatchTable<castFunc_t, id_t, id_t> castTable_t;
42 static castTable_t table;
44 DUMMY_CAST(Void, Void)
45 DUMMY_CAST(Bool, Bool)
46 DUMMY_CAST(Float, Float)
47 DUMMY_CAST(Double, Double)
49 TRIVIAL_CAST(Bool, Integer)
50 TRIVIAL_CAST(Bool, Float)
51 TRIVIAL_CAST(Bool, Double)
52 TRIVIAL_CAST(Integer, Float)
53 TRIVIAL_CAST(Integer, Double)
54 TRIVIAL_CAST(Integer, Pointer)
55 TRIVIAL_CAST(Float, Double)
57 static CastExp *
58 castIntegerInteger(Type * type1,
59 Type * type2)
61 CastExp * castExp = 0;
62 IntegerType * itype1 = ast_cast<IntegerType *> (type1);
63 IntegerType * itype2 = ast_cast<IntegerType *> (type2);
65 if (itype1->size == itype2->size && itype1->isSigned == itype2->isSigned)
66 return 0;
67 castExp = new CastExp();
68 if (itype1->size > itype2->size)
69 castExp->type = itype1;
70 else
71 castExp->type = itype2;
72 return castExp;
75 static CastExp *
76 castPointerPointer(Type * type1, Type * type2)
78 PointerType * ptype1 = ast_cast<PointerType *>(type1);
79 PointerType * ptype2 = ast_cast<PointerType *>(type2);
81 printf("%s, %s\n", ptype1->type->nodeName().c_str(), ptype2->type->nodeName().c_str());
83 assert_msg(isSameType(ptype1->type, ptype2->type),
84 "error: cannot cast different pointers type, %s and %s.",
85 type1->nodeName().c_str(), type2->nodeName().c_str());
86 return 0;
89 static CastExp *
90 castIntegerArray(Type * type1, Type * type2)
92 IntegerType * itype;
93 ArrayType * atype;
95 if (type1->nodeType == IntegerType::nodeTypeId())
97 itype = ast_cast<IntegerType *>(type1);
98 atype = ast_cast<ArrayType *>(type2);
100 else
102 itype = ast_cast<IntegerType *>(type2);
103 atype = ast_cast<ArrayType *>(type1);
106 PointerType * ptype = new PointerType;
107 ptype->type = atype->type;
108 CastExp * cast = new CastExp;
109 cast->type = ptype;
111 return cast;
114 static CastExp *
115 castPointerArray(Type * type1, Type * type2)
117 UnaryType * utype1;
118 UnaryType * utype2;
120 utype1 = reinterpret_cast<UnaryType *>(type1);
121 utype2 = reinterpret_cast<UnaryType *>(type2);
123 assert(isSameType(utype1->type, utype2->type));
125 CastExp * cast = new CastExp;
126 if (type1->nodeType == PointerType::nodeTypeId())
127 cast->type = type1;
128 else
129 cast->type = type2;
130 return cast;
133 static void
134 init()
136 ADD_SYMETRIC_ENTRY(Void, Void);
137 ADD_SYMETRIC_ENTRY(Bool, Bool);
138 ADD_SYMETRIC_ENTRY(Bool, Integer);
139 ADD_SYMETRIC_ENTRY(Bool, Float);
140 ADD_SYMETRIC_ENTRY(Bool, Double);
141 ADD_SYMETRIC_ENTRY(Integer, Integer);
142 ADD_SYMETRIC_ENTRY(Integer, Float);
143 ADD_SYMETRIC_ENTRY(Integer, Double);
144 ADD_SYMETRIC_ENTRY(Integer, Pointer);
145 ADD_SYMETRIC_ENTRY(Integer, Array);
146 ADD_SYMETRIC_ENTRY(Float, Float);
147 ADD_SYMETRIC_ENTRY(Float, Double);
148 ADD_SYMETRIC_ENTRY(Double, Double);
149 ADD_SYMETRIC_ENTRY(Pointer, Pointer);
150 ADD_SYMETRIC_ENTRY(Pointer, Array);
153 CastExp *
154 castToBestType(Type * type1, Type * type2)
156 static bool initTable = true;
158 if (initTable) {
159 init();
160 initTable = false;
163 type1 = unreferencedType(type1);
164 type2 = unreferencedType(type2);
166 assert(type1);
167 assert(type2);
169 return table.dispatch(type1->nodeType, type2->nodeType)(type1, type2);
172 bool
173 isSameType(Type * type1, Type * type2)
175 return !castToBestType(type1, type2);
178 static inline
179 CastExp *
180 makeCast(Type * type, Exp * exp)
182 CastExp * castExp = new CastExp;
183 castExp->type = type;
184 castExp->exp = exp;
185 return castExp;
188 Exp *
189 castToType(Type * type, Exp * exp)
191 if (type->nodeType != exp->type->nodeType)
192 return makeCast(type, exp);
194 if (type->nodeType == IntegerType::nodeTypeId())
196 IntegerType * typeTo = ast_cast<IntegerType *> (type);
197 IntegerType * typeFrom = ast_cast<IntegerType *> (exp->type);
199 if (typeTo->size != typeFrom->size ||
200 typeTo->isSigned != typeFrom->isSigned)
201 return makeCast(type, exp);
204 return exp;
207 #define UNREFERENCED_TYPE(Const) \
208 Const Type * \
209 unreferencedType(Const Type * type) \
211 assert(type); \
212 if (type->nodeType == ReferenceType::nodeTypeId()) \
213 return ast_cast<Const ReferenceType *> (type)->type; \
214 return type; \
217 UNREFERENCED_TYPE()
218 UNREFERENCED_TYPE(const)