calc: boolean expressions
[m6w6/ext-psi] / src / calc.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27 #include <assert.h>
28
29 #include "token.h"
30 #include "calc.h"
31
32 #define PSI_CALC_CAST_SET(in_type, in_val, op, out_val, out_var) \
33 switch (in_type) { \
34 case PSI_T_INT8: (out_val)->out_var op (in_val)->i8; break; \
35 case PSI_T_UINT8: (out_val)->out_var op (in_val)->u8; break; \
36 case PSI_T_INT16: (out_val)->out_var op (in_val)->i16; break; \
37 case PSI_T_UINT16: (out_val)->out_var op (in_val)->u16; break; \
38 case PSI_T_INT32: (out_val)->out_var op (in_val)->i32; break; \
39 case PSI_T_UINT32: (out_val)->out_var op (in_val)->u32; break; \
40 case PSI_T_INT64: (out_val)->out_var op (in_val)->i64; break; \
41 case PSI_T_UINT64: (out_val)->out_var op (in_val)->u64; break; \
42 case PSI_T_FLOAT: (out_val)->out_var op (in_val)->fval; break; \
43 case PSI_T_DOUBLE: (out_val)->out_var op (in_val)->dval; break; \
44 case PSI_T_LONG_DOUBLE: (out_val)->out_var op (in_val)->ldval; break; \
45 default: \
46 assert(0); \
47 }
48
49 #define PSI_CALC_CAST(in_type, in_val, op, out_type, out_val) \
50 switch (out_type) { \
51 case PSI_T_INT8: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i8) break; \
52 case PSI_T_UINT8: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u8) break; \
53 case PSI_T_INT16: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i16) break; \
54 case PSI_T_UINT16: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u16) break; \
55 case PSI_T_INT32: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i32) break; \
56 case PSI_T_UINT32: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u32) break; \
57 case PSI_T_INT64: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i64) break; \
58 case PSI_T_UINT64: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u64) break; \
59 case PSI_T_FLOAT: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, fval) break; \
60 case PSI_T_DOUBLE: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, dval) break; \
61 case PSI_T_LONG_DOUBLE: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, ldval) break; \
62 default: \
63 assert(0); \
64 }
65
66 #define PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, out_var) \
67 switch (in_type) { \
68 case PSI_T_INT8: (out_val)->out_var op (in_val)->i8; break; \
69 case PSI_T_UINT8: (out_val)->out_var op (in_val)->u8; break; \
70 case PSI_T_INT16: (out_val)->out_var op (in_val)->i16; break; \
71 case PSI_T_UINT16: (out_val)->out_var op (in_val)->u16; break; \
72 case PSI_T_INT32: (out_val)->out_var op (in_val)->i32; break; \
73 case PSI_T_UINT32: (out_val)->out_var op (in_val)->u32; break; \
74 case PSI_T_INT64: (out_val)->out_var op (in_val)->i64; break; \
75 case PSI_T_UINT64: (out_val)->out_var op (in_val)->u64; break; \
76 default: \
77 assert(0); \
78 }
79 #define PSI_CALC_CAST_INT(in_type, in_val, op, out_type, out_val) \
80 switch (out_type) { \
81 case PSI_T_INT8: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i8) break; \
82 case PSI_T_UINT8: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u8) break; \
83 case PSI_T_INT16: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i16) break; \
84 case PSI_T_UINT16: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u16) break; \
85 case PSI_T_INT32: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i32) break; \
86 case PSI_T_UINT32: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u32) break; \
87 case PSI_T_INT64: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i64) break; \
88 case PSI_T_UINT64: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u64) break; \
89 default: \
90 assert(0); \
91 }
92
93 void psi_calc_cast(token_t in_type, impl_val *in_val, token_t out_type, impl_val *out_val)
94 {
95 PSI_CALC_CAST(in_type, in_val, =, out_type, out_val)
96 }
97
98 #if 0
99 #define PSI_CALC_OP(var) do { \
100 const char *fmt = "calc %" PRI##var ", %" PRI##var ": %" PRI##var "\n"; \
101 res->var = PSI_CALC(v1->var, v2->var); \
102 if (!res->var && (v1->var || v2->var)) fprintf(stderr, fmt, v1->var, v2->var, res->var); \
103 } while (0)
104 #define PSI_CALC_OP2(vres, var1, var2) do { \
105 const char *fmt = "calc %" PRI##var1 ", %" PRI##var2 ": %" PRI##vres "\n"; \
106 res->vres = PSI_CALC(v1->var1, v2->var2); \
107 if (!res->vres && (v1->var1 || v2->var2)) fprintf(stderr, fmt, v1->var1, v2->var2, res->vres); \
108 } while(0)
109 #else
110 #define PSI_CALC_OP(var) res->var = PSI_CALC(v1->var, v2->var)
111 #define PSI_CALC_OP2(vres, var1, var2) res->vres = PSI_CALC(v1->var1, v2->var2)
112 #endif
113
114 #ifdef HAVE_LONG_DOUBLE
115 # define PSI_CALC_NO_LD
116 # define PSI_CALC_OP_LD PSI_CALC_OP(ldval)
117 # define PSI_CALC_OP2_LD2(var1) PSI_CALC_OP2(ldval, var1, ldval)
118 # define PSI_CALC_OP2_LD1(var2) PSI_CALC_OP2(ldval, ldval, var2)
119 #else
120 # define PSI_CALC_NO_LD abort()
121 # define PSI_CALC_OP_LD PSI_CALC_NO_LD
122 # define PSI_CALC_OP2_LD2(var) PSI_CALC_NO_LD
123 # define PSI_CALC_OP2_LD1(var) PSI_CALC_NO_LD
124 #endif
125
126 #define PSI_CALC_FN(op) token_t psi_calc_##op(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) \
127 { \
128 if (t1 == t2) { \
129 switch (t1) { \
130 case PSI_T_FLOAT: PSI_CALC_OP(fval); break; \
131 case PSI_T_DOUBLE: PSI_CALC_OP(dval); break; \
132 case PSI_T_LONG_DOUBLE: PSI_CALC_OP_LD; break; \
133 case PSI_T_INT8: PSI_CALC_OP(i8); break; \
134 case PSI_T_UINT8: PSI_CALC_OP(u8); break; \
135 case PSI_T_INT16: PSI_CALC_OP(i16); break; \
136 case PSI_T_UINT16: PSI_CALC_OP(u16); break; \
137 case PSI_T_INT32: PSI_CALC_OP(i32); break; \
138 case PSI_T_UINT32: PSI_CALC_OP(u32); break; \
139 case PSI_T_INT64: PSI_CALC_OP(i64); break; \
140 case PSI_T_UINT64: PSI_CALC_OP(u64); break; \
141 EMPTY_SWITCH_DEFAULT_CASE(); \
142 } \
143 return t1; \
144 } else if (t1 == PSI_T_DOUBLE) { \
145 switch (t2) { \
146 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD2(dval); return t2; \
147 case PSI_T_FLOAT: PSI_CALC_OP2(dval, dval, fval); break; \
148 case PSI_T_INT8: PSI_CALC_OP2(dval, dval, i8); break; \
149 case PSI_T_UINT8: PSI_CALC_OP2(dval, dval, u8); break; \
150 case PSI_T_INT16: PSI_CALC_OP2(dval, dval, i16); break; \
151 case PSI_T_UINT16: PSI_CALC_OP2(dval, dval, u16); break; \
152 case PSI_T_INT32: PSI_CALC_OP2(dval, dval, i32); break; \
153 case PSI_T_UINT32: PSI_CALC_OP2(dval, dval, u32); break; \
154 case PSI_T_INT64: PSI_CALC_OP2(dval, dval, i64); break; \
155 case PSI_T_UINT64: PSI_CALC_OP2(dval, dval, u64); break; \
156 EMPTY_SWITCH_DEFAULT_CASE(); \
157 } \
158 return t1; \
159 } else if (t2 == PSI_T_DOUBLE) { \
160 switch (t1) { \
161 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD1(dval); return t1; \
162 case PSI_T_FLOAT: PSI_CALC_OP2(dval, fval, dval); break; \
163 case PSI_T_INT8: PSI_CALC_OP2(dval, i8, dval); break; \
164 case PSI_T_UINT8: PSI_CALC_OP2(dval, u8, dval); break; \
165 case PSI_T_INT16: PSI_CALC_OP2(dval, i16, dval); break; \
166 case PSI_T_UINT16: PSI_CALC_OP2(dval, u16, dval); break; \
167 case PSI_T_INT32: PSI_CALC_OP2(dval, i32, dval); break; \
168 case PSI_T_UINT32: PSI_CALC_OP2(dval, u32, dval); break; \
169 case PSI_T_INT64: PSI_CALC_OP2(dval, i64, dval); break; \
170 case PSI_T_UINT64: PSI_CALC_OP2(dval, u64, dval); break; \
171 EMPTY_SWITCH_DEFAULT_CASE(); \
172 } \
173 return t2; \
174 } else if (t1 == PSI_T_LONG_DOUBLE) { \
175 PSI_CALC_NO_LD; \
176 switch (t2) { \
177 case PSI_T_DOUBLE: PSI_CALC_OP2_LD1(dval); break; \
178 case PSI_T_FLOAT: PSI_CALC_OP2_LD1(fval); break; \
179 case PSI_T_INT8: PSI_CALC_OP2_LD1(i8); break; \
180 case PSI_T_UINT8: PSI_CALC_OP2_LD1(u8); break; \
181 case PSI_T_INT16: PSI_CALC_OP2_LD1(i16); break; \
182 case PSI_T_UINT16: PSI_CALC_OP2_LD1(u16); break; \
183 case PSI_T_INT32: PSI_CALC_OP2_LD1(i32); break; \
184 case PSI_T_UINT32: PSI_CALC_OP2_LD1(u32); break; \
185 case PSI_T_INT64: PSI_CALC_OP2_LD1(i64); break; \
186 case PSI_T_UINT64: PSI_CALC_OP2_LD1(u64); break; \
187 EMPTY_SWITCH_DEFAULT_CASE(); \
188 } \
189 return t1; \
190 } else if (t2 == PSI_T_LONG_DOUBLE) { \
191 PSI_CALC_NO_LD; \
192 switch (t1) { \
193 case PSI_T_DOUBLE: PSI_CALC_OP2_LD2(dval); break; \
194 case PSI_T_FLOAT: PSI_CALC_OP2_LD2(fval); break; \
195 case PSI_T_INT8: PSI_CALC_OP2_LD2(i8); break; \
196 case PSI_T_UINT8: PSI_CALC_OP2_LD2(u8); break; \
197 case PSI_T_INT16: PSI_CALC_OP2_LD2(i16); break; \
198 case PSI_T_UINT16: PSI_CALC_OP2_LD2(u16); break; \
199 case PSI_T_INT32: PSI_CALC_OP2_LD2(i32); break; \
200 case PSI_T_UINT32: PSI_CALC_OP2_LD2(u32); break; \
201 case PSI_T_INT64: PSI_CALC_OP2_LD2(i64); break; \
202 case PSI_T_UINT64: PSI_CALC_OP2_LD2(u64); break; \
203 EMPTY_SWITCH_DEFAULT_CASE(); \
204 } \
205 return t2; \
206 } else if (t1 == PSI_T_FLOAT) { \
207 switch (t2) { \
208 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD2(fval); return t2; \
209 case PSI_T_DOUBLE: PSI_CALC_OP2(dval, fval, dval); return t2; \
210 case PSI_T_INT8: PSI_CALC_OP2(fval, fval, i8); break; \
211 case PSI_T_UINT8: PSI_CALC_OP2(fval, fval, u8); break; \
212 case PSI_T_INT16: PSI_CALC_OP2(fval, fval, i16); break; \
213 case PSI_T_UINT16: PSI_CALC_OP2(fval, fval, u16); break; \
214 case PSI_T_INT32: PSI_CALC_OP2(fval, fval, i32); break; \
215 case PSI_T_UINT32: PSI_CALC_OP2(fval, fval, u32); break; \
216 case PSI_T_INT64: PSI_CALC_OP2(fval, fval, i64); break; \
217 case PSI_T_UINT64: PSI_CALC_OP2(fval, fval, u64); break; \
218 EMPTY_SWITCH_DEFAULT_CASE(); \
219 } \
220 return t1; \
221 } else if (t2 == PSI_T_FLOAT) { \
222 switch (t1) { \
223 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD1(fval); return t1; \
224 case PSI_T_DOUBLE: PSI_CALC_OP2(dval, dval, fval); return t1; \
225 case PSI_T_INT8: PSI_CALC_OP2(fval, i8, fval); break; \
226 case PSI_T_UINT8: PSI_CALC_OP2(fval, u8, fval); break; \
227 case PSI_T_INT16: PSI_CALC_OP2(fval, i16, fval); break; \
228 case PSI_T_UINT16: PSI_CALC_OP2(fval, u16, fval); break; \
229 case PSI_T_INT32: PSI_CALC_OP2(fval, i32, fval); break; \
230 case PSI_T_UINT32: PSI_CALC_OP2(fval, u32, fval); break; \
231 case PSI_T_INT64: PSI_CALC_OP2(fval, i64, fval); break; \
232 case PSI_T_UINT64: PSI_CALC_OP2(fval, u64, fval); break; \
233 EMPTY_SWITCH_DEFAULT_CASE(); \
234 } \
235 return t2; \
236 } else { \
237 switch (t1) { \
238 case PSI_T_INT8: \
239 switch (t2) { \
240 case PSI_T_INT8: PSI_CALC_OP2(i16, i8, i8); return PSI_T_INT16; \
241 case PSI_T_UINT8: PSI_CALC_OP2(i16, i8, u8); return PSI_T_INT16; \
242 case PSI_T_INT16: PSI_CALC_OP2(i32, i8, i16); return PSI_T_INT32; \
243 case PSI_T_UINT16: PSI_CALC_OP2(i32, i8, u16); return PSI_T_INT32; \
244 case PSI_T_INT32: PSI_CALC_OP2(i64, i8, i32); return PSI_T_INT64; \
245 case PSI_T_UINT32: PSI_CALC_OP2(i64, i8, u32); return PSI_T_INT64; \
246 case PSI_T_INT64: PSI_CALC_OP2(i64, i8, i64); return PSI_T_INT64; \
247 case PSI_T_UINT64: PSI_CALC_OP2(i64, i8, u64); return PSI_T_INT64; \
248 EMPTY_SWITCH_DEFAULT_CASE(); \
249 } \
250 break; \
251 case PSI_T_UINT8: \
252 switch (t2) { \
253 case PSI_T_INT8: PSI_CALC_OP2(i16, u8, i8); return PSI_T_INT16; \
254 case PSI_T_UINT8: PSI_CALC_OP2(u16, u8, u8); return PSI_T_UINT16; \
255 case PSI_T_INT16: PSI_CALC_OP2(i32, u8, i16); return PSI_T_INT32; \
256 case PSI_T_UINT16: PSI_CALC_OP2(u32, u8, u16); return PSI_T_UINT32; \
257 case PSI_T_INT32: PSI_CALC_OP2(i64, u8, i32); return PSI_T_INT64; \
258 case PSI_T_UINT32: PSI_CALC_OP2(u64, u8, u32); return PSI_T_UINT64; \
259 case PSI_T_INT64: PSI_CALC_OP2(i64, u8, i64); return PSI_T_INT64; \
260 case PSI_T_UINT64: PSI_CALC_OP2(u64, u8, u64); return PSI_T_UINT64; \
261 EMPTY_SWITCH_DEFAULT_CASE(); \
262 } \
263 break; \
264 case PSI_T_INT16: \
265 switch (t2) { \
266 case PSI_T_INT8: PSI_CALC_OP2(i32, i16, i8); return PSI_T_INT32; \
267 case PSI_T_UINT8: PSI_CALC_OP2(i32, i16, u8); return PSI_T_INT32; \
268 case PSI_T_INT16: PSI_CALC_OP2(i32, i16, i16); return PSI_T_INT32; \
269 case PSI_T_UINT16: PSI_CALC_OP2(i32, i16, u16); return PSI_T_INT32; \
270 case PSI_T_INT32: PSI_CALC_OP2(i64, i16, i32); return PSI_T_INT64; \
271 case PSI_T_UINT32: PSI_CALC_OP2(i64, i16, u32); return PSI_T_INT64; \
272 case PSI_T_INT64: PSI_CALC_OP2(i64, i16, i64); return PSI_T_INT64; \
273 case PSI_T_UINT64: PSI_CALC_OP2(i64, i16, u64); return PSI_T_INT64; \
274 EMPTY_SWITCH_DEFAULT_CASE(); \
275 } \
276 break; \
277 case PSI_T_UINT16: \
278 switch (t2) { \
279 case PSI_T_INT8: PSI_CALC_OP2(i32, u16, i8); return PSI_T_INT32; \
280 case PSI_T_UINT8: PSI_CALC_OP2(u32, u16, u8); return PSI_T_UINT32; \
281 case PSI_T_INT16: PSI_CALC_OP2(i32, u16, i16); return PSI_T_INT32; \
282 case PSI_T_UINT16: PSI_CALC_OP2(u32, u16, u16); return PSI_T_UINT32; \
283 case PSI_T_INT32: PSI_CALC_OP2(i64, u16, i32); return PSI_T_INT64; \
284 case PSI_T_UINT32: PSI_CALC_OP2(u64, u16, u32); return PSI_T_UINT64; \
285 case PSI_T_INT64: PSI_CALC_OP2(i64, u16, i64); return PSI_T_INT64; \
286 case PSI_T_UINT64: PSI_CALC_OP2(u64, u16, u64); return PSI_T_UINT64; \
287 EMPTY_SWITCH_DEFAULT_CASE(); \
288 } \
289 break; \
290 case PSI_T_INT32: \
291 switch (t2) { \
292 case PSI_T_INT8: PSI_CALC_OP2(i64, i32, i8); return PSI_T_INT64; \
293 case PSI_T_UINT8: PSI_CALC_OP2(i64, i32, u8); return PSI_T_INT64; \
294 case PSI_T_INT16: PSI_CALC_OP2(i64, i32, i16); return PSI_T_INT64; \
295 case PSI_T_UINT16: PSI_CALC_OP2(i64, i32, u16); return PSI_T_INT64; \
296 case PSI_T_INT32: PSI_CALC_OP2(i64, i32, i32); return PSI_T_INT64; \
297 case PSI_T_UINT32: PSI_CALC_OP2(i64, i32, u32); return PSI_T_INT64; \
298 case PSI_T_INT64: PSI_CALC_OP2(i64, i32, i64); return PSI_T_INT64; \
299 case PSI_T_UINT64: PSI_CALC_OP2(i64, i32, u64); return PSI_T_INT64; \
300 EMPTY_SWITCH_DEFAULT_CASE(); \
301 } \
302 break; \
303 case PSI_T_UINT32: \
304 switch (t2) { \
305 case PSI_T_INT8: PSI_CALC_OP2(i64, u32, i8); return PSI_T_INT64; \
306 case PSI_T_UINT8: PSI_CALC_OP2(u64, u32, u8); return PSI_T_UINT64; \
307 case PSI_T_INT16: PSI_CALC_OP2(i64, u32, i16); return PSI_T_INT64; \
308 case PSI_T_UINT16: PSI_CALC_OP2(u64, u32, u16); return PSI_T_UINT64; \
309 case PSI_T_INT32: PSI_CALC_OP2(i64, u32, i32); return PSI_T_INT64; \
310 case PSI_T_UINT32: PSI_CALC_OP2(u64, u32, u32); return PSI_T_UINT64; \
311 case PSI_T_INT64: PSI_CALC_OP2(i64, u32, i64); return PSI_T_INT64; \
312 case PSI_T_UINT64: PSI_CALC_OP2(u64, u32, u64); return PSI_T_UINT64; \
313 EMPTY_SWITCH_DEFAULT_CASE(); \
314 } \
315 break; \
316 case PSI_T_INT64: \
317 switch (t2) { \
318 case PSI_T_INT8: PSI_CALC_OP2(i64, i64, i8); return PSI_T_INT64; \
319 case PSI_T_UINT8: PSI_CALC_OP2(i64, i64, u8); return PSI_T_INT64; \
320 case PSI_T_INT16: PSI_CALC_OP2(i64, i64, i16); return PSI_T_INT64; \
321 case PSI_T_UINT16: PSI_CALC_OP2(i64, i64, u16); return PSI_T_INT64; \
322 case PSI_T_INT32: PSI_CALC_OP2(i64, i64, i32); return PSI_T_INT64; \
323 case PSI_T_UINT32: PSI_CALC_OP2(i64, i64, u32); return PSI_T_INT64; \
324 case PSI_T_INT64: PSI_CALC_OP2(i64, i64, i64); return PSI_T_INT64; \
325 case PSI_T_UINT64: PSI_CALC_OP2(i64, i64, u64); return PSI_T_INT64; \
326 EMPTY_SWITCH_DEFAULT_CASE(); \
327 } \
328 break; \
329 case PSI_T_UINT64: \
330 switch (t2) { \
331 case PSI_T_INT8: PSI_CALC_OP2(i64, u64, i8); return PSI_T_INT64; \
332 case PSI_T_UINT8: PSI_CALC_OP2(u64, u64, u8); return PSI_T_UINT64; \
333 case PSI_T_INT16: PSI_CALC_OP2(i64, u64, i16); return PSI_T_INT64; \
334 case PSI_T_UINT16: PSI_CALC_OP2(u64, u64, u16); return PSI_T_UINT64; \
335 case PSI_T_INT32: PSI_CALC_OP2(i64, u64, i32); return PSI_T_INT64; \
336 case PSI_T_UINT32: PSI_CALC_OP2(u64, u64, u32); return PSI_T_UINT64; \
337 case PSI_T_INT64: PSI_CALC_OP2(i64, u64, i64); return PSI_T_INT64; \
338 case PSI_T_UINT64: PSI_CALC_OP2(u64, u64, u64); return PSI_T_UINT64; \
339 EMPTY_SWITCH_DEFAULT_CASE(); \
340 } \
341 break; \
342 EMPTY_SWITCH_DEFAULT_CASE(); \
343 } \
344 } \
345 assert(0); \
346 return 0; \
347 }
348
349 #undef PSI_CALC
350 #define PSI_CALC(var1, var2) (var1) + (var2)
351 PSI_CALC_FN(add)
352 #undef PSI_CALC
353 #define PSI_CALC(var1, var2) (var1) * (var2)
354 PSI_CALC_FN(mul)
355 #undef PSI_CALC
356 #define PSI_CALC(var1, var2) (var1) - (var2)
357 PSI_CALC_FN(sub)
358 #undef PSI_CALC
359 #define PSI_CALC(var1, var2) (var1) / (var2)
360 PSI_CALC_FN(div)
361 #undef PSI_CALC
362
363 token_t psi_calc_mod(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
364 {
365 impl_val i1, i2;
366
367 PSI_CALC_CAST(t1, v1, =, PSI_T_INT64, &i1);
368 PSI_CALC_CAST(t2, v2, =, PSI_T_INT64, &i2);
369
370 res->i64 = i1.i64 % i2.i64;
371
372 return PSI_T_INT64;
373 }
374
375 #define PSI_CALC_BIT_FN(op) token_t psi_calc_##op(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) \
376 { \
377 impl_val i1, i2; \
378 PSI_CALC_CAST(t1, v1, =, PSI_T_UINT64, &i1); \
379 PSI_CALC_CAST(t2, v2, =, PSI_T_UINT64, &i2); \
380 res->u64 = PSI_CALC(i1.u64, i2.u64); \
381 return PSI_T_UINT64; \
382 }
383
384 #define PSI_CALC(var1, var2) (var1) << (var2)
385 PSI_CALC_BIT_FN(bin_lshift)
386 #undef PSI_CALC
387 #define PSI_CALC(var1, var2) (var1) >> (var2)
388 PSI_CALC_BIT_FN(bin_rshift)
389 #undef PSI_CALC
390 #define PSI_CALC(var1, var2) (var1) & (var2)
391 PSI_CALC_BIT_FN(bin_and)
392 #undef PSI_CALC
393 #define PSI_CALC(var1, var2) (var1) ^ (var2)
394 PSI_CALC_BIT_FN(bin_xor)
395 #undef PSI_CALC
396 #define PSI_CALC(var1, var2) (var1) | (var2)
397 PSI_CALC_BIT_FN(bin_or)
398 #undef PSI_CALC
399
400 #define PSI_CALC_CMP_FN(op) token_t psi_calc_##op(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) \
401 { \
402 switch (t1) { \
403 case PSI_T_FLOAT: \
404 switch (t2) { \
405 case PSI_T_FLOAT: PSI_CALC_OP2(u8, fval, fval); break; \
406 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, fval, dval); break; \
407 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, fval, ldval); break; \
408 case PSI_T_INT8: PSI_CALC_OP2(u8, fval, i8); break; \
409 case PSI_T_UINT8: PSI_CALC_OP2(u8, fval, u8); break; \
410 case PSI_T_INT16: PSI_CALC_OP2(u8, fval, i16); break; \
411 case PSI_T_UINT16: PSI_CALC_OP2(u8, fval, u16); break; \
412 case PSI_T_INT32: PSI_CALC_OP2(u8, fval, i32); break; \
413 case PSI_T_UINT32: PSI_CALC_OP2(u8, fval, u32); break; \
414 case PSI_T_INT64: PSI_CALC_OP2(u8, fval, i64); break; \
415 case PSI_T_UINT64: PSI_CALC_OP2(u8, fval, u64); break; \
416 EMPTY_SWITCH_DEFAULT_CASE(); \
417 } \
418 break; \
419 case PSI_T_DOUBLE: \
420 switch (t2) { \
421 case PSI_T_FLOAT: PSI_CALC_OP2(u8, dval, fval); break; \
422 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, dval, dval); break; \
423 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, dval, ldval); break; \
424 case PSI_T_INT8: PSI_CALC_OP2(u8, dval, i8); break; \
425 case PSI_T_UINT8: PSI_CALC_OP2(u8, dval, u8); break; \
426 case PSI_T_INT16: PSI_CALC_OP2(u8, dval, i16); break; \
427 case PSI_T_UINT16: PSI_CALC_OP2(u8, dval, u16); break; \
428 case PSI_T_INT32: PSI_CALC_OP2(u8, dval, i32); break; \
429 case PSI_T_UINT32: PSI_CALC_OP2(u8, dval, u32); break; \
430 case PSI_T_INT64: PSI_CALC_OP2(u8, dval, i64); break; \
431 case PSI_T_UINT64: PSI_CALC_OP2(u8, dval, u64); break; \
432 EMPTY_SWITCH_DEFAULT_CASE(); \
433 } \
434 break; \
435 case PSI_T_LONG_DOUBLE: \
436 switch (t2) { \
437 case PSI_T_FLOAT: PSI_CALC_OP2(u8, ldval, fval); break; \
438 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, ldval, dval); break; \
439 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, ldval, ldval); break; \
440 case PSI_T_INT8: PSI_CALC_OP2(u8, ldval, i8); break; \
441 case PSI_T_UINT8: PSI_CALC_OP2(u8, ldval, u8); break; \
442 case PSI_T_INT16: PSI_CALC_OP2(u8, ldval, i16); break; \
443 case PSI_T_UINT16: PSI_CALC_OP2(u8, ldval, u16); break; \
444 case PSI_T_INT32: PSI_CALC_OP2(u8, ldval, i32); break; \
445 case PSI_T_UINT32: PSI_CALC_OP2(u8, ldval, u32); break; \
446 case PSI_T_INT64: PSI_CALC_OP2(u8, ldval, i64); break; \
447 case PSI_T_UINT64: PSI_CALC_OP2(u8, ldval, u64); break; \
448 EMPTY_SWITCH_DEFAULT_CASE(); \
449 } \
450 break; \
451 case PSI_T_INT8: \
452 switch (t2) { \
453 case PSI_T_FLOAT: PSI_CALC_OP2(u8, i8, fval); break; \
454 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, i8, dval); break; \
455 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, i8, ldval); break; \
456 case PSI_T_INT8: PSI_CALC_OP2(u8, i8, i8); break; \
457 case PSI_T_UINT8: PSI_CALC_OP2(u8, i8, u8); break; \
458 case PSI_T_INT16: PSI_CALC_OP2(u8, i8, i16); break; \
459 case PSI_T_UINT16: PSI_CALC_OP2(u8, i8, u16); break; \
460 case PSI_T_INT32: PSI_CALC_OP2(u8, i8, i32); break; \
461 case PSI_T_UINT32: PSI_CALC_OP2(u8, i8, u32); break; \
462 case PSI_T_INT64: PSI_CALC_OP2(u8, i8, i64); break; \
463 case PSI_T_UINT64: PSI_CALC_OP2(u8, i8, u64); break; \
464 EMPTY_SWITCH_DEFAULT_CASE(); \
465 } \
466 break; \
467 case PSI_T_UINT8: \
468 switch (t2) { \
469 case PSI_T_FLOAT: PSI_CALC_OP2(u8, u8, fval); break; \
470 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, u8, dval); break; \
471 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, u8, ldval); break; \
472 case PSI_T_INT8: PSI_CALC_OP2(u8, u8, i8); break; \
473 case PSI_T_UINT8: PSI_CALC_OP2(u8, u8, u8); break; \
474 case PSI_T_INT16: PSI_CALC_OP2(u8, u8, i16); break; \
475 case PSI_T_UINT16: PSI_CALC_OP2(u8, u8, u16); break; \
476 case PSI_T_INT32: PSI_CALC_OP2(u8, u8, i32); break; \
477 case PSI_T_UINT32: PSI_CALC_OP2(u8, u8, u32); break; \
478 case PSI_T_INT64: PSI_CALC_OP2(u8, u8, i64); break; \
479 case PSI_T_UINT64: PSI_CALC_OP2(u8, u8, u64); break; \
480 EMPTY_SWITCH_DEFAULT_CASE(); \
481 } \
482 break; \
483 case PSI_T_INT16: \
484 switch (t2) { \
485 case PSI_T_FLOAT: PSI_CALC_OP2(u8, i16, fval); break; \
486 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, i16, dval); break; \
487 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, i16, ldval); break; \
488 case PSI_T_INT8: PSI_CALC_OP2(u8, i16, i8); break; \
489 case PSI_T_UINT8: PSI_CALC_OP2(u8, i16, u8); break; \
490 case PSI_T_INT16: PSI_CALC_OP2(u8, i16, i16); break; \
491 case PSI_T_UINT16: PSI_CALC_OP2(u8, i16, u16); break; \
492 case PSI_T_INT32: PSI_CALC_OP2(u8, i16, i32); break; \
493 case PSI_T_UINT32: PSI_CALC_OP2(u8, i16, u32); break; \
494 case PSI_T_INT64: PSI_CALC_OP2(u8, i16, i64); break; \
495 case PSI_T_UINT64: PSI_CALC_OP2(u8, i16, u64); break; \
496 EMPTY_SWITCH_DEFAULT_CASE(); \
497 } \
498 break; \
499 case PSI_T_UINT16: \
500 switch (t2) { \
501 case PSI_T_FLOAT: PSI_CALC_OP2(u8, u16, fval); break; \
502 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, u16, dval); break; \
503 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, u16, ldval); break; \
504 case PSI_T_INT8: PSI_CALC_OP2(u8, u16, i8); break; \
505 case PSI_T_UINT8: PSI_CALC_OP2(u8, u16, u8); break; \
506 case PSI_T_INT16: PSI_CALC_OP2(u8, u16, i16); break; \
507 case PSI_T_UINT16: PSI_CALC_OP2(u8, u16, u16); break; \
508 case PSI_T_INT32: PSI_CALC_OP2(u8, u16, i32); break; \
509 case PSI_T_UINT32: PSI_CALC_OP2(u8, u16, u32); break; \
510 case PSI_T_INT64: PSI_CALC_OP2(u8, u16, i64); break; \
511 case PSI_T_UINT64: PSI_CALC_OP2(u8, u16, u64); break; \
512 EMPTY_SWITCH_DEFAULT_CASE(); \
513 } \
514 break; \
515 case PSI_T_INT32: \
516 switch (t2) { \
517 case PSI_T_FLOAT: PSI_CALC_OP2(u8, i32, fval); break; \
518 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, i32, dval); break; \
519 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, i32, ldval); break; \
520 case PSI_T_INT8: PSI_CALC_OP2(u8, i32, i8); break; \
521 case PSI_T_UINT8: PSI_CALC_OP2(u8, i32, u8); break; \
522 case PSI_T_INT16: PSI_CALC_OP2(u8, i32, i16); break; \
523 case PSI_T_UINT16: PSI_CALC_OP2(u8, i32, u16); break; \
524 case PSI_T_INT32: PSI_CALC_OP2(u8, i32, i32); break; \
525 case PSI_T_UINT32: PSI_CALC_OP2(u8, i32, u32); break; \
526 case PSI_T_INT64: PSI_CALC_OP2(u8, i32, i64); break; \
527 case PSI_T_UINT64: PSI_CALC_OP2(u8, i32, u64); break; \
528 EMPTY_SWITCH_DEFAULT_CASE(); \
529 } \
530 break; \
531 case PSI_T_UINT32: \
532 switch (t2) { \
533 case PSI_T_FLOAT: PSI_CALC_OP2(u8, u32, fval); break; \
534 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, u32, dval); break; \
535 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, u32, ldval); break; \
536 case PSI_T_INT8: PSI_CALC_OP2(u8, u32, i8); break; \
537 case PSI_T_UINT8: PSI_CALC_OP2(u8, u32, u8); break; \
538 case PSI_T_INT16: PSI_CALC_OP2(u8, u32, i16); break; \
539 case PSI_T_UINT16: PSI_CALC_OP2(u8, u32, u16); break; \
540 case PSI_T_INT32: PSI_CALC_OP2(u8, u32, i32); break; \
541 case PSI_T_UINT32: PSI_CALC_OP2(u8, u32, u32); break; \
542 case PSI_T_INT64: PSI_CALC_OP2(u8, u32, i64); break; \
543 case PSI_T_UINT64: PSI_CALC_OP2(u8, u32, u64); break; \
544 EMPTY_SWITCH_DEFAULT_CASE(); \
545 } \
546 break; \
547 case PSI_T_INT64: \
548 switch (t2) { \
549 case PSI_T_FLOAT: PSI_CALC_OP2(u8, i64, fval); break; \
550 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, i64, dval); break; \
551 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, i64, ldval); break; \
552 case PSI_T_INT8: PSI_CALC_OP2(u8, i64, i8); break; \
553 case PSI_T_UINT8: PSI_CALC_OP2(u8, i64, u8); break; \
554 case PSI_T_INT16: PSI_CALC_OP2(u8, i64, i16); break; \
555 case PSI_T_UINT16: PSI_CALC_OP2(u8, i64, u16); break; \
556 case PSI_T_INT32: PSI_CALC_OP2(u8, i64, i32); break; \
557 case PSI_T_UINT32: PSI_CALC_OP2(u8, i64, u32); break; \
558 case PSI_T_INT64: PSI_CALC_OP2(u8, i64, i64); break; \
559 case PSI_T_UINT64: PSI_CALC_OP2(u8, i64, u64); break; \
560 EMPTY_SWITCH_DEFAULT_CASE(); \
561 } \
562 break; \
563 case PSI_T_UINT64: \
564 switch (t2) { \
565 case PSI_T_FLOAT: PSI_CALC_OP2(u8, u64, fval); break; \
566 case PSI_T_DOUBLE: PSI_CALC_OP2(u8, u64, dval); break; \
567 case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, u64, ldval); break; \
568 case PSI_T_INT8: PSI_CALC_OP2(u8, u64, i8); break; \
569 case PSI_T_UINT8: PSI_CALC_OP2(u8, u64, u8); break; \
570 case PSI_T_INT16: PSI_CALC_OP2(u8, u64, i16); break; \
571 case PSI_T_UINT16: PSI_CALC_OP2(u8, u64, u16); break; \
572 case PSI_T_INT32: PSI_CALC_OP2(u8, u64, i32); break; \
573 case PSI_T_UINT32: PSI_CALC_OP2(u8, u64, u32); break; \
574 case PSI_T_INT64: PSI_CALC_OP2(u8, u64, i64); break; \
575 case PSI_T_UINT64: PSI_CALC_OP2(u8, u64, u64); break; \
576 EMPTY_SWITCH_DEFAULT_CASE(); \
577 } \
578 break; \
579 EMPTY_SWITCH_DEFAULT_CASE(); \
580 } \
581 return PSI_T_UINT8; \
582 }
583
584 #define PSI_CALC(var1, var2) (var1) == (var2)
585 PSI_CALC_CMP_FN(cmp_eq)
586 #undef PSI_CALC
587 #define PSI_CALC(var1, var2) (var1) != (var2)
588 PSI_CALC_CMP_FN(cmp_ne)
589 #undef PSI_CALC
590 #define PSI_CALC(var1, var2) (var1) <= (var2)
591 PSI_CALC_CMP_FN(cmp_le)
592 #undef PSI_CALC
593 #define PSI_CALC(var1, var2) (var1) >= (var2)
594 PSI_CALC_CMP_FN(cmp_ge)
595 #undef PSI_CALC
596 #define PSI_CALC(var1, var2) (var1) < (var2)
597 PSI_CALC_CMP_FN(cmp_lt)
598 #undef PSI_CALC
599 #define PSI_CALC(var1, var2) (var1) > (var2)
600 PSI_CALC_CMP_FN(cmp_gt)
601 #undef PSI_CALC
602
603 #define PSI_CALC_BOOL_FN(op) token_t psi_calc_##op(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) \
604 { \
605 impl_val i1, i2; \
606 PSI_CALC_CAST(t1, v1, =!!, PSI_T_UINT8, &i1); \
607 PSI_CALC_CAST(t2, v2, =!!, PSI_T_UINT8, &i2); \
608 res->u8 = PSI_CALC(i1.u8, i2.u8); \
609 return PSI_T_UINT8; \
610 }
611
612 #define PSI_CALC(var1, var2) (var1) && (var2)
613 PSI_CALC_BOOL_FN(and)
614 #undef PSI_CALC
615 #define PSI_CALC(var1, var2) (var1) || (var2)
616 PSI_CALC_BOOL_FN(or)
617 #undef PSI_CALC
618
619 token_t psi_calc_not(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
620 {
621 (void) t2;
622 (void) v2;
623
624 PSI_CALC_CAST(t1, v1, =!, t1, res);
625 return t1;
626 }
627
628 token_t psi_calc_bin_not(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
629 {
630 impl_val i1;
631
632 (void) t2;
633 (void) v2;
634
635 PSI_CALC_CAST(t1, v1, =, PSI_T_UINT64, &i1);
636 PSI_CALC_CAST_INT(t1, &i1, =~, t1, res);
637 return t1;
638 }