From 9a7fad4cea94aee90c3e07886d3d13a60fdbdc59 Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Thu, 10 Oct 2019 13:38:36 +0200 Subject: [PATCH] :art: Improve matching --- include/match.h | 9 +++++++-- src/emit/emit.c | 31 +++++++++++++++++++++++-------- src/parse/check.c | 10 +++------- tests/tree/parent_match_actual.gw | 6 ++++++ 4 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 tests/tree/parent_match_actual.gw diff --git a/include/match.h b/include/match.h index 9ab0bee2..fed283bc 100644 --- a/include/match.h +++ b/include/match.h @@ -18,8 +18,13 @@ ANN static inline void match_map(struct Match_ * const match, Exp e) { ANN static inline void match_unmap(struct Match_ * const match) { const Map map = &match->map; - for(m_uint i = 0; i < map_size(map) - 1; ++i) { - const Exp e = (Exp)VKEY(map, i), next = (Exp)VKEY(map, i + 1); + const vtype sz = map_size(map); + for(m_uint i = 0; i < sz; ++i) { + const Exp e = (Exp)VKEY(map, i), + next = (i < (sz-2)) ? (Exp)VKEY(map, i + 1) : NULL; + if(!e) + continue; + VKEY(map, i) = VKEY(map, i+1) = 0;// e->next = next; } map_release(map); diff --git a/src/emit/emit.c b/src/emit/emit.c index 8f2e33e3..5274fbad 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1445,14 +1445,20 @@ ANN static m_bool emit_stmt_exp(const Emitter emit, const struct Stmt_Exp_* exp) return exp->val ? emit_exp(emit, exp->val, 0) : 1; } -ANN static m_bool emit_case_head(const Emitter emit, const Exp base, const Exp e, const Symbol op) { +ANN static m_bool emit_case_head(const Emitter emit, const Exp base, + const Exp e, const Symbol op, const Vector v) { CHECK_BB(emit_exp(emit, base, 1)) - CHECK_BB(emit_exp(emit, e, 1)) + const Exp next = e->next; + e->next = NULL; + const m_bool ret = emit_exp(emit, e, 1); + e->next = next; + CHECK_BB(ret) const Exp_Binary bin = { .lhs=base, .rhs=e, .op=op }; struct Exp_ ebin = { .d={.exp_binary=bin}, .nspc=emit->env->curr}; struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type, .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos }; CHECK_BB(op_emit_bool(emit, &opi)) - regpop(emit, base->type->size); + const Instr instr = emit_add_instr(emit, BranchEqInt); + vector_add(v, (vtype)instr); return GW_OK; } @@ -1497,22 +1503,31 @@ ANN static Symbol case_op(const Emitter emit, const Exp base, const Exp e) { return insert_symbol("=="); } -ANN static m_bool _emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt) { +ANN static m_bool _emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt, + const Vector v) { Exp e = stmt->cond; const Map map = &emit->env->scope->match->map; - for(m_uint i = 0; i < map_size(map); e = e->next, ++i) { + for(m_uint i = 0; i < map_size(map) && e; e = e->next, ++i) { const Exp base = (Exp)VKEY(map, i); const Symbol op = case_op(emit, base, e); if(op != CASE_PASS) - CHECK_BB(emit_case_head(emit, base, e, op)) + CHECK_BB(emit_case_head(emit, base, e, op, v)) } - return emit_case_body(emit, stmt); + CHECK_BB(emit_case_body(emit, stmt)) + return GW_OK; } ANN static m_bool emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt) { emit_push_scope(emit); - const m_bool ret = _emit_stmt_match_case(emit, stmt); + struct Vector_ v; + vector_init(&v); + const m_bool ret = _emit_stmt_match_case(emit, stmt, &v); emit_pop_scope(emit); + for(m_uint i = 0; i < vector_size(&v); ++i) { + const Instr instr = (Instr)vector_at(&v, i); + instr->m_val = emit_code_size(emit); + } + vector_release(&v); return ret; } diff --git a/src/parse/check.c b/src/parse/check.c index 4059ca86..2d0e3ade 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -1192,7 +1192,7 @@ ANN static Symbol case_op(const Env env, const Exp e, const m_uint i) { } ANN static m_bool match_case_exp(const Env env, Exp e) { - for(m_uint i = 0; i < map_size(&env->scope->match->map); e = e->next, ++i) { + for(m_uint i = 0; i < map_size(&env->scope->match->map) && e; e = e->next, ++i) { const Symbol op = case_op(env, e, i); if(op) { const Exp base = (Exp)VKEY(&env->scope->match->map, i); @@ -1226,16 +1226,12 @@ ANN static m_bool case_loop(const Env env, const Stmt_Match stmt) { return GW_OK; } -ANN static m_bool check_match(const Env env, const Stmt_Match stmt) { - CHECK_OB(check_exp(env, stmt->cond)) - return case_loop(env, stmt); -} - ANN static m_bool _check_stmt_match(const Env env, const Stmt_Match stmt) { if(stmt->where) CHECK_BB(check_stmt(env, stmt->where)) + CHECK_OB(check_exp(env, stmt->cond)) MATCH_INI(env->scope) - const m_bool ret = check_match(env, stmt); + const m_bool ret = case_loop(env, stmt); MATCH_END(env->scope) return ret; } diff --git a/tests/tree/parent_match_actual.gw b/tests/tree/parent_match_actual.gw new file mode 100644 index 00000000..04cf6e90 --- /dev/null +++ b/tests/tree/parent_match_actual.gw @@ -0,0 +1,6 @@ +class C { + fun void test() {} +} +class D extends C { + fun void test() {} +} -- 2.43.0