]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve matching
authorfennecdjay <astor.jeremie@wanadoo.fr>
Thu, 10 Oct 2019 11:38:36 +0000 (13:38 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Thu, 10 Oct 2019 11:38:36 +0000 (13:38 +0200)
include/match.h
src/emit/emit.c
src/parse/check.c

index 9ab0bee2415f00b7e046d8a7153304b5c8b4201d..fed283bc3a4f7fdd24725b61645c707ea8c980e5 100644 (file)
@@ -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);
index 8f2e33e3e53a93869886a5983573f24df45f208f..5274fbadf98e5b69eb2919bb536330a9690d2628 100644 (file)
@@ -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;
 }
 
index 4059ca86c0e70270ff37832240412efa90602cf7..2d0e3adeaa4ac0300690b09126d169f3c0c1ea95 100644 (file)
@@ -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;
 }