vtype iter;
size_t default_case_index;
size_t depth;
+ struct SwInfo_ *info;
uint ok;
};
m_int value = 0;
const Value v = case_value(stmt->val);
if((!v && prim_value(stmt->val, &value)) || value_value(v, &value)) {
- CHECK_BB(switch_dup(emit->env, value, stmt->val->pos))
+ CHECK_BB(switch_dup(emit->env, value, stmt_self(stmt)->pos))
switch_dynpc(emit->env, value, emit_code_size(emit));
} else
switch_pc(emit->env, emit_code_size(emit));
(isa(exp_self(member)->type, t_function) > 0 && isa(exp_self(member)->type, t_fptr) < 0))
) {
CHECK_BB(emit_exp(emit, member->base, 0))
- emit_except(emit, member->t_base);
+// emit_except(emit, member->t_base);
+ emit_add_instr(emit, GWOP_EXCEPT);
}
if(isa(exp_self(member)->type, t_function) > 0 && isa(exp_self(member)->type, t_fptr) < 0)
return emit_member_func(emit, member, value->d.func_ref);
}
static DTOR(array_dtor) {
- const Type t = o->type_ref;
+ const Type t = !GET_FLAG(o->type_ref, nonnull) ?
+ o->type_ref : o->type_ref->e->parent;
const Type base = array_base(t);
struct M_Vector_* a = ARRAY(o);
if(t->array_depth > 1 || isa(base, t_object) > 0)
const Type type = bin->rhs->type;
const Instr pop = emit_add_instr(emit, RegPop);
pop->m_val = type->size;
- emit_add_instr(emit, GWOP_EXCEPT);
+ if(!GET_FLAG(bin->lhs->type, nonnull))
+ emit_add_instr(emit, GWOP_EXCEPT);
emit_add_instr(emit, ArrayAppend);
return GW_OK;
}
return sw;
}
+struct SwInfo_ {
+ Stmt_Switch s;
+ Type t;
+ Func f;
+};
+
ANN static void free_switch(MemPool p, const Switch sw) {
if(!sw->ok)
free_map(p, sw->cases);
free_vector(p, sw->vec); // only for dynamic
vector_release(&sw->exp);
+ mp_free(p, SwInfo, sw->info);
mp_free(p, Switch, sw);
}
-struct SwInfo_ {
- Stmt_Switch s;
- Type t;
- Func f;
-};
-
ANN static Switch new_swinfo(const Env env, const Stmt_Switch stmt) {
struct SwInfo_ *info = mp_calloc(env->gwion->mp, SwInfo);
info->s = stmt;
const Switch sw = new_switch(env->gwion->mp);
map_set(&env->scope->swi->map, (vtype)info, (vtype)sw);
sw->depth = env->scope->depth + 2;
+ sw->info = info;
return sw;
}
ANN Switch swinfo_get(const Env env, const struct SwInfo_ *info) {
for(m_uint i = 0; i < VLEN(&env->scope->swi->map); ++i) {
const struct SwInfo_ *key = (const struct SwInfo_*)VKEY(&env->scope->swi->map, i);
- if(swinfo_cmp(key, info))
+ if(swinfo_cmp(key, info)) {
return (Switch)VVAL(&env->scope->swi->map, i);
+ }
}
return NULL;
}
void switch_reset(const Env env) {
for(m_uint i = VLEN(&env->scope->swi->map) + 1; --i;) {
- struct SwInfo_ *info = (struct SwInfo_ *)VKEY(&env->scope->swi->map, i - 1);
- mp_free(env->gwion->mp, SwInfo, info);
- Switch sw = (Switch)VVAL(&env->scope->swi->map, i - 1);
+ const Switch sw = (Switch)VVAL(&env->scope->swi->map, i - 1);
free_switch(env->gwion->mp, sw);
}
_scope_clear(env->scope->swi);
ERR_B(pos, _("case found outside switch statement."))
return GW_OK;
}
+
ANN m_bool switch_dup(const Env env, const m_int value, const loc_t pos) {
const Switch sw = (Switch)_scope_back(env->scope->swi);
if(map_get(sw->cases, (vtype)value))
}
ANN m_bool switch_pop(const Env env) {
- const Switch sw = (Switch)_scope_back(env->scope->swi);
+ const Switch sw = (Switch)_scope_pop(env->scope->swi);
sw->ok = 1;
- _scope_pop(env->scope->swi);
return GW_OK;
}
ANN m_bool switch_end(const Env env, const loc_t pos) {
const Switch sw = (Switch)_scope_pop(env->scope->swi);
- const vtype index = VKEY(&env->scope->swi->map, VLEN(&env->scope->swi->map) - 1);
-// sw->ok = 1;
- if(!VLEN(sw->cases) && !VLEN(&sw->exp))
- ERR_B(pos, _("switch statement with no cases."))
- map_remove(&env->scope->swi->map, index);
+ map_remove(&env->scope->swi->map, sw->info);
+ const m_bool empty = !VLEN(sw->cases) && !VLEN(&sw->exp);
free_switch(env->gwion->mp, sw);
+ if(empty)
+ ERR_B(pos, _("switch statement with no cases."))
return GW_OK;
}
#define scan1_exp_lambda dummy_func
HANDLE_EXP_FUNC(scan1, m_bool, 1)
+ANN static inline m_bool scan1_stmt_switch(const restrict Env env, const Stmt_Switch stmt) {
+ CHECK_BB(scan1_exp(env, stmt->val))
+ CHECK_BB(scan1_stmt(env, stmt->stmt))
+ return GW_OK;
+}
+
#define describe_ret_nspc(name, type, prolog, exp) describe_stmt_func(scan1, name, type, prolog, exp)
describe_ret_nspc(flow, Stmt_Flow,, !(scan1_exp(env, stmt->cond) < 0 ||
scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
describe_ret_nspc(loop, Stmt_Loop,, !(scan1_exp(env, stmt->cond) < 0 ||
scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
-describe_ret_nspc(switch, Stmt_Switch,, !(scan1_exp(env, stmt->val) < 0 ||
- scan1_stmt(env, stmt->stmt) < 0) ? 1 : -1)
+//describe_ret_nspc(switch, Stmt_Switch,, !(scan1_exp(env, stmt->val) < 0 ||
+// scan1_stmt(env, stmt->stmt) < 0) ? 1 : -1)
describe_ret_nspc(if, Stmt_If,, !(scan1_exp(env, stmt->cond) < 0 ||
scan1_stmt(env, stmt->if_body) < 0 ||
(stmt->else_body && scan1_stmt(env, stmt->else_body) < 0)) ? 1 : -1)
CHECK_BB(scanx_parent(parent, scan1_cdef, env))
if(type_ref(parent))
ERR_B(pos, _("can't use ref type in class extend"))
+ if(GET_FLAG(parent, nonnull))
+ ERR_B(pos, _("can't use nonnull type in class extend"))
return GW_OK;
}
ANN m_bool traverse_func_def(const Env env, const Func_Def def) {
const Func former = env->func;
- if(scan1_func_def(env, def) > 0 &&
+ const m_bool ret = scan1_func_def(env, def) > 0 &&
scan2_func_def(env, def) > 0 &&
- check_func_def(env, def) > 0)
- return GW_OK;
+ check_func_def(env, def) > 0;
env->func = former;
- return GW_ERROR;
+ return ret ? GW_OK : GW_ERROR;
}
ANN m_bool traverse_union_def(const Env env, const Union_Def def) {