+
+token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
+ struct psi_call_frame *frame, HashTable *defs)
+{
+ struct psi_plist *output, *input;
+ struct element {
+ token_t type;
+ union {
+ impl_val value;
+ psi_calc calc;
+ struct psi_decl_type *cast;
+ } data;
+ } entry, lhs, rhs;
+
+ output = psi_plist_init_ex(sizeof(entry), NULL);
+ input = psi_plist_init_ex(sizeof(entry), NULL);
+
+ psi_num_exp_reduce(exp, &output, &input, frame, defs);
+
+ while (psi_plist_pop(input, &entry)) {
+ if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
+ output = psi_plist_add(output, &entry);
+ }
+ if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
+
+ while (psi_plist_shift(output, &entry)) {
+ switch (entry.type) {
+ default:
+ input = psi_plist_add(input, &entry);
+ break;
+
+ case PSI_T_CAST:
+ psi_plist_pop(input, &rhs);
+ if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
+ psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
+
+ entry.type = psi_decl_type_get_real(entry.data.cast)->type;
+ psi_calc_cast(rhs.type, &rhs.data.value, entry.type, &entry.data.value);
+ input = psi_plist_add(input, &entry);
+ psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
+ break;
+
+ case PSI_T_NOT:
+ case PSI_T_TILDE:
+ psi_plist_pop(input, &rhs);
+ if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
+ psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
+
+ entry.type = entry.data.calc(rhs.type, &rhs.data.value, 0, NULL, &entry.data.value);
+ input = psi_plist_add(input, &entry);
+ psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
+ break;
+
+ case PSI_T_OR:
+ case PSI_T_AND:
+
+ case PSI_T_CMP_EQ:
+ case PSI_T_CMP_NE:
+ case PSI_T_CMP_LE:
+ case PSI_T_CMP_GE:
+ case PSI_T_RCHEVR:
+ case PSI_T_LCHEVR:
+
+ case PSI_T_PIPE:
+ case PSI_T_CARET:
+ case PSI_T_AMPERSAND:
+ case PSI_T_LSHIFT:
+ case PSI_T_RSHIFT:
+ case PSI_T_MINUS:
+ case PSI_T_PLUS:
+ case PSI_T_ASTERISK:
+ case PSI_T_SLASH:
+ case PSI_T_MODULO:
+ psi_plist_pop(input, &rhs);
+ psi_plist_pop(input, &lhs);
+
+ psi_impl_val_dump(lhs.type, &lhs.data.value, frame);
+ if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
+ psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
+
+ entry.type = entry.data.calc(
+ lhs.type, &lhs.data.value,
+ rhs.type, &rhs.data.value,
+ &entry.data.value);
+ input = psi_plist_add(input, &entry);
+ psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
+ break;
+ }
+
+ if (!psi_plist_count(output)) {
+ break;
+ }
+ }
+
+ psi_plist_free(output);
+ psi_plist_free(input);
+
+ *res = entry.data.value;
+ return entry.type;
+}
+