+
+static inline token_t psi_num_exp_eval_decl_var(struct psi_num_exp *exp,
+ impl_val *res, struct psi_call_frame *frame)
+{
+ impl_val *ref;
+ struct psi_call_frame_symbol *sym;
+ struct psi_decl_type *real;
+ size_t size;
+
+ real = psi_decl_type_get_real(exp->data.dvar->arg->type);
+ size = psi_decl_arg_get_size(exp->data.dvar->arg);
+ sym = psi_call_frame_fetch_symbol(frame, exp->data.dvar);
+ ref = deref_impl_val(sym->ptr, exp->data.dvar);
+
+ memcpy(res, ref, size);
+
+ switch (real->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:
+ case PSI_T_FLOAT:
+ case PSI_T_DOUBLE:
+ break;
+ default:
+ assert(0);
+ }
+
+ return real->type;
+}
+
+static inline token_t psi_num_exp_eval(struct psi_num_exp *exp, impl_val *res,
+ struct psi_call_frame *frame)
+{
+ switch (exp->type) {
+ case PSI_T_INT64:
+ case PSI_T_DOUBLE:
+ *res = exp->data.ival;
+ return exp->type;
+
+ case PSI_T_ENUM:
+ res->i64 = exp->data.enm->val;
+ return PSI_T_INT64;
+
+ case PSI_T_CONST:
+ return psi_num_exp_eval_constant(exp, res, frame);
+ break;
+
+ case PSI_T_NAME:
+ return psi_num_exp_eval_decl_var(exp, res, frame);
+ break;
+
+ default:
+ assert(0);
+ }
+ return 0;
+}
+
+token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
+ struct psi_call_frame *frame)
+{
+ impl_val num = {0};
+ token_t num_type = psi_num_exp_eval(exp, &num, frame);
+
+ /* FIXME operator precedence */
+ if (exp->operand) {
+ impl_val tmp = {0};
+ token_t tmp_type = psi_num_exp_exec(exp->operand, &tmp, frame);
+
+ return exp->calc(num_type, &num, tmp_type, &tmp, res);
+ }
+
+ *res = num;
+ return num_type;
+}