-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "php.h"
-#include "php_psi.h"
+/*******************************************************************************
+ Copyright (c) 2016, Michael Wallner <mike@php.net>.
+ All rights reserved.
-static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val *res) {
- impl_val *ref, *tmp = NULL;
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
- switch (exp->t) {
- case PSI_T_NUMBER:
- switch (is_numeric_string(exp->u.numb, strlen(exp->u.numb), (zend_long *) res, (double *) res, 0)) {
- case IS_LONG:
- return PSI_T_INT64;
- case IS_DOUBLE:
- return PSI_T_DOUBLE;
- }
- break;
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
- case PSI_T_NSNAME:
- switch (exp->u.cnst->type->type) {
- case PSI_T_INT:
- res->i64 = zend_get_constant_str(exp->u.cnst->name, strlen(exp->u.cnst->name))->value.lval;
- return PSI_T_INT64;
- case PSI_T_FLOAT:
- res->dval = zend_get_constant_str(exp->u.cnst->name, strlen(exp->u.cnst->name))->value.dval;
- return PSI_T_DOUBLE;
- default:
- return 0;
- }
- break;
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
- case PSI_T_NAME:
- if (strct) {
- ref = struct_member_ref(exp->u.dvar->arg, strct, &tmp);
- } else if (exp->u.dvar->arg->let) {
- ref = exp->u.dvar->arg->let->ptr;
- } else {
- ref = exp->u.dvar->arg->ptr;
- }
- switch (real_decl_type(exp->u.dvar->arg->type)->type) {
- case PSI_T_INT8:
- case PSI_T_UINT8:
- case PSI_T_INT16:
- case PSI_T_UINT16:
- case PSI_T_INT32:
- case PSI_T_UINT32:
- case PSI_T_INT64:
- case PSI_T_UINT64:
- memcpy(res, deref_impl_val(ref, exp->u.dvar), sizeof(*res));
- if (tmp) {
- free(tmp);
- }
- return real_decl_type(exp->u.dvar->arg->type)->type;
+#include "php_psi_stdinc.h"
+#include <assert.h>
- case PSI_T_FLOAT:
- case PSI_T_DOUBLE:
- memcpy(res, deref_impl_val(ref, exp->u.dvar), sizeof(*res));
- if (tmp) {
- free(tmp);
- }
- return real_decl_type(exp->u.dvar->arg->type)->type;
+#include "token.h"
+#include "calc.h"
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- break;
-
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- return 0;
+#define PSI_CALC_CAST_SET(in_type, in_val, op, out_val, out_var) \
+switch (in_type) { \
+case PSI_T_INT8: (out_val)->out_var op (in_val)->i8; break; \
+case PSI_T_UINT8: (out_val)->out_var op (in_val)->u8; break; \
+case PSI_T_INT16: (out_val)->out_var op (in_val)->i16; break; \
+case PSI_T_UINT16: (out_val)->out_var op (in_val)->u16; break; \
+case PSI_T_INT32: (out_val)->out_var op (in_val)->i32; break; \
+case PSI_T_UINT32: (out_val)->out_var op (in_val)->u32; break; \
+case PSI_T_INT64: (out_val)->out_var op (in_val)->i64; break; \
+case PSI_T_UINT64: (out_val)->out_var op (in_val)->u64; break; \
+case PSI_T_FLOAT: (out_val)->out_var op (in_val)->fval; break; \
+case PSI_T_DOUBLE: (out_val)->out_var op (in_val)->dval; break; \
+case PSI_T_LONG_DOUBLE: (out_val)->out_var op (in_val)->ldval; break; \
+default: \
+ assert(0); \
}
-int psi_calc_num_exp(num_exp *exp, impl_val *strct, impl_val *res) {
- impl_val num = {0};
- int num_type = psi_calc_num_exp_value(exp, strct, &num);
-
- if (exp->operand) {
- impl_val tmp = {0};
- int tmp_type = psi_calc_num_exp(exp->operand, strct, &tmp);
-
- return exp->calculator(num_type, &num, tmp_type, &tmp, res);
- }
+#define PSI_CALC_CAST(in_type, in_val, op, out_type, out_val) \
+switch (out_type) { \
+case PSI_T_INT8: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i8) break; \
+case PSI_T_UINT8: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u8) break; \
+case PSI_T_INT16: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i16) break; \
+case PSI_T_UINT16: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u16) break; \
+case PSI_T_INT32: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i32) break; \
+case PSI_T_UINT32: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u32) break; \
+case PSI_T_INT64: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i64) break; \
+case PSI_T_UINT64: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u64) break; \
+case PSI_T_FLOAT: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, fval) break; \
+case PSI_T_DOUBLE: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, dval) break; \
+case PSI_T_LONG_DOUBLE: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, ldval) break; \
+default: \
+ assert(0); \
+}
- memcpy(res, &num, sizeof(*res));
- return num_type;
+#define PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, out_var) \
+switch (in_type) { \
+case PSI_T_INT8: (out_val)->out_var op (in_val)->i8; break; \
+case PSI_T_UINT8: (out_val)->out_var op (in_val)->u8; break; \
+case PSI_T_INT16: (out_val)->out_var op (in_val)->i16; break; \
+case PSI_T_UINT16: (out_val)->out_var op (in_val)->u16; break; \
+case PSI_T_INT32: (out_val)->out_var op (in_val)->i32; break; \
+case PSI_T_UINT32: (out_val)->out_var op (in_val)->u32; break; \
+case PSI_T_INT64: (out_val)->out_var op (in_val)->i64; break; \
+case PSI_T_UINT64: (out_val)->out_var op (in_val)->u64; break; \
+default: \
+ assert(0); \
+}
+#define PSI_CALC_CAST_INT(in_type, in_val, op, out_type, out_val) \
+switch (out_type) { \
+case PSI_T_INT8: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i8) break; \
+case PSI_T_UINT8: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u8) break; \
+case PSI_T_INT16: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i16) break; \
+case PSI_T_UINT16: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u16) break; \
+case PSI_T_INT32: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i32) break; \
+case PSI_T_UINT32: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u32) break; \
+case PSI_T_INT64: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i64) break; \
+case PSI_T_UINT64: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u64) break; \
+default: \
+ assert(0); \
}
-#define PRIfval "f"
-#define PRIdval "lf"
-#define PRIldval "Lf"
+void psi_calc_cast(token_t in_type, impl_val *in_val, token_t out_type, impl_val *out_val)
+{
+ PSI_CALC_CAST(in_type, in_val, =, out_type, out_val)
+}
+#if 0
#define PSI_CALC_OP(var) do { \
const char *fmt = "calc %" PRI##var ", %" PRI##var ": %" PRI##var "\n"; \
res->var = PSI_CALC(v1->var, v2->var); \
- if (!res->var) fprintf(stderr, fmt, v1->var, v2->var, res->var); \
+ if (!res->var && (v1->var || v2->var)) fprintf(stderr, fmt, v1->var, v2->var, res->var); \
} while (0)
#define PSI_CALC_OP2(vres, var1, var2) do { \
const char *fmt = "calc %" PRI##var1 ", %" PRI##var2 ": %" PRI##vres "\n"; \
res->vres = PSI_CALC(v1->var1, v2->var2); \
- if (!res->vres) fprintf(stderr, fmt, v1->var1, v2->var2, res->vres); \
+ if (!res->vres && (v1->var1 || v2->var2)) fprintf(stderr, fmt, v1->var1, v2->var2, res->vres); \
} while(0)
+#else
+#define PSI_CALC_OP(var) res->var = PSI_CALC(v1->var, v2->var)
+#define PSI_CALC_OP2(vres, var1, var2) res->vres = PSI_CALC(v1->var1, v2->var2)
+#endif
#ifdef HAVE_LONG_DOUBLE
-#define PSI_CALC_NO_LD
-#define PSI_CALC_OP_LD PSI_CALC_OP(ldval)
-#define PSI_CALC_OP2_LD2(var1) PSI_CALC_OP2(ldval, var1, ldval)
-#define PSI_CALC_OP2_LD1(var2) PSI_CALC_OP2(ldval, ldval, var2)
+# define PSI_CALC_NO_LD
+# define PSI_CALC_OP_LD PSI_CALC_OP(ldval)
+# define PSI_CALC_OP2_LD2(var1) PSI_CALC_OP2(ldval, var1, ldval)
+# define PSI_CALC_OP2_LD1(var2) PSI_CALC_OP2(ldval, ldval, var2)
#else
-#define PSI_CALC_NO_LD abort()
-#define PSI_CALC_OP_LD PSI_CALC_NO_LD
-#define PSI_CALC_OP2_LD2(var) PSI_CALC_NO_LD
-#define PSI_CALC_OP2_LD1(var) PSI_CALC_NO_LD
+# define PSI_CALC_NO_LD abort()
+# define PSI_CALC_OP_LD PSI_CALC_NO_LD
+# define PSI_CALC_OP2_LD2(var) PSI_CALC_NO_LD
+# define PSI_CALC_OP2_LD1(var) PSI_CALC_NO_LD
#endif
-#define PSI_CALC_FN(op) int psi_calc_##op(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res) \
+#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) \
{ \
if (t1 == t2) { \
switch (t1) { \
} \
return t2; \
} else { \
- int64_t sval1 = v1->i64, sval2 = v2->i64; \
- uint64_t uval1 = v1->u64, uval2 = v2->u64; \
switch (t1) { \
- case PSI_T_INT8: sval1 >>= 8; \
- case PSI_T_INT16: sval1 >>= 8; \
- case PSI_T_INT32: sval1 >>= 8; \
+ case PSI_T_INT8: \
+ switch (t2) { \
+ case PSI_T_INT8: PSI_CALC_OP2(i16, i8, i8); return PSI_T_INT16; \
+ case PSI_T_UINT8: PSI_CALC_OP2(i16, i8, u8); return PSI_T_INT16; \
+ case PSI_T_INT16: PSI_CALC_OP2(i32, i8, i16); return PSI_T_INT32; \
+ case PSI_T_UINT16: PSI_CALC_OP2(i32, i8, u16); return PSI_T_INT32; \
+ case PSI_T_INT32: PSI_CALC_OP2(i64, i8, i32); return PSI_T_INT64; \
+ case PSI_T_UINT32: PSI_CALC_OP2(i64, i8, u32); return PSI_T_INT64; \
+ case PSI_T_INT64: PSI_CALC_OP2(i64, i8, i64); return PSI_T_INT64; \
+ case PSI_T_UINT64: PSI_CALC_OP2(i64, i8, u64); return PSI_T_INT64; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_UINT8: \
+ switch (t2) { \
+ case PSI_T_INT8: PSI_CALC_OP2(i16, u8, i8); return PSI_T_INT16; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u16, u8, u8); return PSI_T_UINT16; \
+ case PSI_T_INT16: PSI_CALC_OP2(i32, u8, i16); return PSI_T_INT32; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u32, u8, u16); return PSI_T_UINT32; \
+ case PSI_T_INT32: PSI_CALC_OP2(i64, u8, i32); return PSI_T_INT64; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u64, u8, u32); return PSI_T_UINT64; \
+ case PSI_T_INT64: PSI_CALC_OP2(i64, u8, i64); return PSI_T_INT64; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u64, u8, u64); return PSI_T_UINT64; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_INT16: \
+ switch (t2) { \
+ case PSI_T_INT8: PSI_CALC_OP2(i32, i16, i8); return PSI_T_INT32; \
+ case PSI_T_UINT8: PSI_CALC_OP2(i32, i16, u8); return PSI_T_INT32; \
+ case PSI_T_INT16: PSI_CALC_OP2(i32, i16, i16); return PSI_T_INT32; \
+ case PSI_T_UINT16: PSI_CALC_OP2(i32, i16, u16); return PSI_T_INT32; \
+ case PSI_T_INT32: PSI_CALC_OP2(i64, i16, i32); return PSI_T_INT64; \
+ case PSI_T_UINT32: PSI_CALC_OP2(i64, i16, u32); return PSI_T_INT64; \
+ case PSI_T_INT64: PSI_CALC_OP2(i64, i16, i64); return PSI_T_INT64; \
+ case PSI_T_UINT64: PSI_CALC_OP2(i64, i16, u64); return PSI_T_INT64; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_UINT16: \
+ switch (t2) { \
+ case PSI_T_INT8: PSI_CALC_OP2(i32, u16, i8); return PSI_T_INT32; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u32, u16, u8); return PSI_T_UINT32; \
+ case PSI_T_INT16: PSI_CALC_OP2(i32, u16, i16); return PSI_T_INT32; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u32, u16, u16); return PSI_T_UINT32; \
+ case PSI_T_INT32: PSI_CALC_OP2(i64, u16, i32); return PSI_T_INT64; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u64, u16, u32); return PSI_T_UINT64; \
+ case PSI_T_INT64: PSI_CALC_OP2(i64, u16, i64); return PSI_T_INT64; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u64, u16, u64); return PSI_T_UINT64; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_INT32: \
+ switch (t2) { \
+ case PSI_T_INT8: PSI_CALC_OP2(i64, i32, i8); return PSI_T_INT64; \
+ case PSI_T_UINT8: PSI_CALC_OP2(i64, i32, u8); return PSI_T_INT64; \
+ case PSI_T_INT16: PSI_CALC_OP2(i64, i32, i16); return PSI_T_INT64; \
+ case PSI_T_UINT16: PSI_CALC_OP2(i64, i32, u16); return PSI_T_INT64; \
+ case PSI_T_INT32: PSI_CALC_OP2(i64, i32, i32); return PSI_T_INT64; \
+ case PSI_T_UINT32: PSI_CALC_OP2(i64, i32, u32); return PSI_T_INT64; \
+ case PSI_T_INT64: PSI_CALC_OP2(i64, i32, i64); return PSI_T_INT64; \
+ case PSI_T_UINT64: PSI_CALC_OP2(i64, i32, u64); return PSI_T_INT64; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_UINT32: \
+ switch (t2) { \
+ case PSI_T_INT8: PSI_CALC_OP2(i64, u32, i8); return PSI_T_INT64; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u64, u32, u8); return PSI_T_UINT64; \
+ case PSI_T_INT16: PSI_CALC_OP2(i64, u32, i16); return PSI_T_INT64; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u64, u32, u16); return PSI_T_UINT64; \
+ case PSI_T_INT32: PSI_CALC_OP2(i64, u32, i32); return PSI_T_INT64; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u64, u32, u32); return PSI_T_UINT64; \
+ case PSI_T_INT64: PSI_CALC_OP2(i64, u32, i64); return PSI_T_INT64; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u64, u32, u64); return PSI_T_UINT64; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
case PSI_T_INT64: \
switch (t2) { \
- case PSI_T_INT8: sval2 >>= 8; \
- case PSI_T_INT16: sval2 >>= 8; \
- case PSI_T_INT32: sval2 >>= 8; \
- case PSI_T_INT64: \
- res->i64 = PSI_CALC(sval1 , sval2); \
- return PSI_T_INT64; \
- case PSI_T_UINT8: uval2 >>= 8; \
- case PSI_T_UINT16: uval2 >>= 8; \
- case PSI_T_UINT32: uval2 >>= 8; \
- case PSI_T_UINT64: \
- res->i64 = PSI_CALC(sval1, uval2); \
- return PSI_T_INT64; \
+ case PSI_T_INT8: PSI_CALC_OP2(i64, i64, i8); return PSI_T_INT64; \
+ case PSI_T_UINT8: PSI_CALC_OP2(i64, i64, u8); return PSI_T_INT64; \
+ case PSI_T_INT16: PSI_CALC_OP2(i64, i64, i16); return PSI_T_INT64; \
+ case PSI_T_UINT16: PSI_CALC_OP2(i64, i64, u16); return PSI_T_INT64; \
+ case PSI_T_INT32: PSI_CALC_OP2(i64, i64, i32); return PSI_T_INT64; \
+ case PSI_T_UINT32: PSI_CALC_OP2(i64, i64, u32); return PSI_T_INT64; \
+ case PSI_T_INT64: PSI_CALC_OP2(i64, i64, i64); return PSI_T_INT64; \
+ case PSI_T_UINT64: PSI_CALC_OP2(i64, i64, u64); return PSI_T_INT64; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
} \
break; \
- case PSI_T_UINT8: uval1 >>= 8; \
- case PSI_T_UINT16: uval1 >>= 8; \
- case PSI_T_UINT32: uval1 >>= 8; \
case PSI_T_UINT64: \
switch (t2) { \
- case PSI_T_INT8: sval2 >>= 8; \
- case PSI_T_INT16: sval2 >>= 8; \
- case PSI_T_INT32: sval2 >>= 8; \
- case PSI_T_INT64: \
- res->i64 = PSI_CALC(uval1, sval2); \
- return PSI_T_INT64; \
- case PSI_T_UINT8: uval2 >>= 8; \
- case PSI_T_UINT16: uval2 >>= 8; \
- case PSI_T_UINT32: uval2 >>= 8; \
- case PSI_T_UINT64: \
- res->u64 = PSI_CALC(uval1, uval2); \
- return PSI_T_UINT64; \
+ case PSI_T_INT8: PSI_CALC_OP2(i64, u64, i8); return PSI_T_INT64; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u64, u64, u8); return PSI_T_UINT64; \
+ case PSI_T_INT16: PSI_CALC_OP2(i64, u64, i16); return PSI_T_INT64; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u64, u64, u16); return PSI_T_UINT64; \
+ case PSI_T_INT32: PSI_CALC_OP2(i64, u64, i32); return PSI_T_INT64; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u64, u64, u32); return PSI_T_UINT64; \
+ case PSI_T_INT64: PSI_CALC_OP2(i64, u64, i64); return PSI_T_INT64; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u64, u64, u64); return PSI_T_UINT64; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
} \
break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
} \
} \
- ZEND_ASSERT(0); \
+ assert(0); \
return 0; \
}
#undef PSI_CALC
#define PSI_CALC(var1, var2) (var1) / (var2)
PSI_CALC_FN(div)
+#undef PSI_CALC
+
+token_t psi_calc_mod(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
+{
+ impl_val i1, i2;
+
+ PSI_CALC_CAST(t1, v1, =, PSI_T_INT64, &i1);
+ PSI_CALC_CAST(t2, v2, =, PSI_T_INT64, &i2);
+
+ res->i64 = i1.i64 % i2.i64;
+
+ return PSI_T_INT64;
+}
+
+#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) \
+{ \
+ impl_val i1, i2; \
+ PSI_CALC_CAST(t1, v1, =, PSI_T_UINT64, &i1); \
+ PSI_CALC_CAST(t2, v2, =, PSI_T_UINT64, &i2); \
+ res->u64 = PSI_CALC(i1.u64, i2.u64); \
+ return PSI_T_UINT64; \
+}
+
+#define PSI_CALC(var1, var2) (var1) << (var2)
+PSI_CALC_BIT_FN(bin_lshift)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) >> (var2)
+PSI_CALC_BIT_FN(bin_rshift)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) & (var2)
+PSI_CALC_BIT_FN(bin_and)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) ^ (var2)
+PSI_CALC_BIT_FN(bin_xor)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) | (var2)
+PSI_CALC_BIT_FN(bin_or)
+#undef PSI_CALC
+
+#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) \
+{ \
+ switch (t1) { \
+ case PSI_T_FLOAT: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, fval, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, fval, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, fval, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, fval, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, fval, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, fval, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, fval, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, fval, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, fval, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, fval, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, fval, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_DOUBLE: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, dval, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, dval, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, dval, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, dval, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, dval, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, dval, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, dval, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, dval, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, dval, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, dval, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, dval, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_LONG_DOUBLE: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, ldval, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, ldval, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, ldval, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, ldval, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, ldval, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, ldval, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, ldval, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, ldval, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, ldval, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, ldval, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, ldval, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_INT8: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, i8, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, i8, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, i8, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, i8, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, i8, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, i8, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, i8, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, i8, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, i8, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, i8, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, i8, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_UINT8: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, u8, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, u8, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, u8, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, u8, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, u8, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, u8, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, u8, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, u8, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, u8, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, u8, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, u8, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_INT16: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, i16, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, i16, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, i16, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, i16, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, i16, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, i16, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, i16, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, i16, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, i16, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, i16, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, i16, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_UINT16: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, u16, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, u16, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, u16, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, u16, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, u16, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, u16, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, u16, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, u16, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, u16, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, u16, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, u16, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_INT32: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, i32, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, i32, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, i32, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, i32, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, i32, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, i32, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, i32, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, i32, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, i32, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, i32, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, i32, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_UINT32: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, u32, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, u32, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, u32, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, u32, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, u32, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, u32, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, u32, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, u32, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, u32, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, u32, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, u32, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_INT64: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, i64, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, i64, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, i64, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, i64, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, i64, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, i64, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, i64, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, i64, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, i64, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, i64, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, i64, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ case PSI_T_UINT64: \
+ switch (t2) { \
+ case PSI_T_FLOAT: PSI_CALC_OP2(u8, u64, fval); break; \
+ case PSI_T_DOUBLE: PSI_CALC_OP2(u8, u64, dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2(u8, u64, ldval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2(u8, u64, i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2(u8, u64, u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2(u8, u64, i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2(u8, u64, u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2(u8, u64, i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2(u8, u64, u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2(u8, u64, i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2(u8, u64, u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ return PSI_T_UINT8; \
+}
+
+#define PSI_CALC(var1, var2) (var1) == (var2)
+PSI_CALC_CMP_FN(cmp_eq)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) != (var2)
+PSI_CALC_CMP_FN(cmp_ne)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) <= (var2)
+PSI_CALC_CMP_FN(cmp_le)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) >= (var2)
+PSI_CALC_CMP_FN(cmp_ge)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) < (var2)
+PSI_CALC_CMP_FN(cmp_lt)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) > (var2)
+PSI_CALC_CMP_FN(cmp_gt)
+#undef PSI_CALC
+
+#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) \
+{ \
+ impl_val i1, i2; \
+ PSI_CALC_CAST(t1, v1, =!!, PSI_T_UINT8, &i1); \
+ PSI_CALC_CAST(t2, v2, =!!, PSI_T_UINT8, &i2); \
+ res->u8 = PSI_CALC(i1.u8, i2.u8); \
+ return PSI_T_UINT8; \
+}
+
+#define PSI_CALC(var1, var2) (var1) && (var2)
+PSI_CALC_BOOL_FN(and)
+#undef PSI_CALC
+#define PSI_CALC(var1, var2) (var1) || (var2)
+PSI_CALC_BOOL_FN(or)
+#undef PSI_CALC
+
+token_t psi_calc_not(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
+{
+ (void) t2;
+ (void) v2;
+
+ PSI_CALC_CAST(t1, v1, =!, t1, res);
+ return t1;
+}
+
+token_t psi_calc_bin_not(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
+{
+ impl_val i1;
+
+ (void) t2;
+ (void) v2;
+
+ PSI_CALC_CAST(t1, v1, =, PSI_T_UINT64, &i1);
+ PSI_CALC_CAST_INT(t1, &i1, =~, t1, res);
+ return t1;
+}