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) \
7 cast##Type1##Type2(Type * /*type1*/, \
13 #define TRIVIAL_CAST(Type1, Type2) \
15 cast##Type1##Type2(Type * type1, \
18 CastExp * castExp = new CastExp(); \
20 if (type1->nodeType == Type2##Type::nodeTypeId()) \
21 castExp->type = type1; \
23 castExp->type = type2; \
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());
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
)
58 castIntegerInteger(Type
* type1
,
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
)
67 castExp
= new CastExp();
68 if (itype1
->size
> itype2
->size
)
69 castExp
->type
= itype1
;
71 castExp
->type
= itype2
;
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());
90 castIntegerArray(Type
* type1
, Type
* type2
)
95 if (type1
->nodeType
== IntegerType::nodeTypeId())
97 itype
= ast_cast
<IntegerType
*>(type1
);
98 atype
= ast_cast
<ArrayType
*>(type2
);
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
;
115 castPointerArray(Type
* type1
, Type
* type2
)
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())
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
);
154 castToBestType(Type
* type1
, Type
* type2
)
156 static bool initTable
= true;
163 type1
= unreferencedType(type1
);
164 type2
= unreferencedType(type2
);
169 return table
.dispatch(type1
->nodeType
, type2
->nodeType
)(type1
, type2
);
173 isSameType(Type
* type1
, Type
* type2
)
175 return !castToBestType(type1
, type2
);
180 makeCast(Type
* type
, Exp
* exp
)
182 CastExp
* castExp
= new CastExp
;
183 castExp
->type
= type
;
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
);
207 #define UNREFERENCED_TYPE(Const) \
209 unreferencedType(Const Type * type) \
212 if (type->nodeType == ReferenceType::nodeTypeId()) \
213 return ast_cast<Const ReferenceType *> (type)->type; \
218 UNREFERENCED_TYPE(const)