gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr); gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr) { u16 prev_state_flags = p->state_flags; defer (p->state_flags = prev_state_flags); if (expr->state_flags != 0) { u16 in = expr->state_flags; u16 out = p->state_flags; if (in & StateFlag_bounds_check) { out |= StateFlag_bounds_check; out &= ~StateFlag_no_bounds_check; } else if (in & StateFlag_no_bounds_check) { out |= StateFlag_no_bounds_check; out &= ~StateFlag_bounds_check; } if (in & StateFlag_type_assert) { out |= StateFlag_type_assert; out &= ~StateFlag_no_type_assert; } else if (in & StateFlag_no_type_assert) { out |= StateFlag_no_type_assert; out &= ~StateFlag_type_assert; } p->state_flags = out; } // IMPORTANT NOTE(bill): // Selector Call Expressions (foo->bar(...)) // must only evaluate `foo` once as it gets transformed into // `foo.bar(foo, ...)` // And if `foo` is a procedure call or something more complex, storing the value // once is a very good idea // If a stored value is found, it must be removed from the cache if (expr->state_flags & StateFlag_SelectorCallExpr) { // cgValue *pp = map_get(&p->selector_values, expr); // if (pp != nullptr) { // cgValue res = *pp; // map_remove(&p->selector_values, expr); // return res; // } // cgAddr *pa = map_get(&p->selector_addr, expr); // if (pa != nullptr) { // cgAddr res = *pa; // map_remove(&p->selector_addr, expr); // return cg_addr_load(p, res); // } } cgValue res = cg_build_expr_internal(p, expr); if (expr->state_flags & StateFlag_SelectorCallExpr) { // map_set(&p->selector_values, expr, res); } return res; } gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { return {}; } gb_internal cgAddr cg_build_addr(cgProcedure *p, Ast *expr) { return {}; }