]> Nishi Git Mirror - gwion.git/commitdiff
:art: Clear array/tuple access
authorfennecdjay <astor.jeremie@wanadoo.fr>
Fri, 9 Aug 2019 23:36:00 +0000 (01:36 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Fri, 9 Aug 2019 23:36:00 +0000 (01:36 +0200)
src/emit/emit.c

index 7d827856a42887fd71e1edff751bbc6d2dcf476a..1bf61461718da987a5b129efb5335a1676fb6859 100644 (file)
@@ -394,58 +394,7 @@ ANN static m_bool prim_array(const Emitter emit, const Exp_Primary * primary) {
   return GW_OK;
 }
 
-ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) {
-  const m_uint is_var = exp_self(array)->emit_var;
-  CHECK_BB(emit_exp(emit, array->base, 0))
-  const m_uint depth = get_depth(array->base->type) - get_depth(exp_self(array)->type);
-
-const Type t_base = array->base->type;
-Type type = array_base(t_base) ?: t_base;
-if(isa(type, t_tuple) > 0 && isa(exp_self(array)->type, t_tuple) < 0) {
-  Exp e = array->array->exp;
-  while(e->next && e->next->next)
-    e = e->next;
-  const Exp next = e->next;
-  if(!next) {
-      emit_add_instr(emit, GWOP_EXCEPT);
-      const Instr instr = emit_add_instr(emit, TupleMember);
-      instr->m_val = array->array->exp->d.exp_primary.d.num;
-      instr->m_val2 = is_var;
-      emit_add_instr(emit, DotMember); // just a place holder.
-      return GW_OK;
-    }
-    emit_add_instr(emit, GcAdd);
-    e->next = NULL;
-    CHECK_BB(emit_exp(emit, array->array->exp, 0))
-    e->next = next;
-    regpop(emit, (depth) * SZ_INT);
-    emit_add_instr(emit, GWOP_EXCEPT);
-assert(depth);
-    if(depth)
-    for(m_uint i = 0; i < depth-1; ++i) {
-      const Instr access = emit_add_instr(emit, ArrayAccess);
-      access->m_val = i;
-      const Instr get = emit_add_instr(emit, ArrayGet);
-      get->m_val = i;
-      get->m_val2 = -SZ_INT;
-      emit_add_instr(emit, GWOP_EXCEPT);
-    }
-    regpop(emit, SZ_INT);
-    const Instr access = emit_add_instr(emit, ArrayAccess);
-    access->m_val = depth;
-    const Instr get = emit_add_instr(emit, ArrayGet);
-    get->m_val = depth;
-    const Instr push = emit_add_instr(emit, ArrayValid);
-    push->m_val = SZ_INT;
-    emit_add_instr(emit, GWOP_EXCEPT);
-    const Instr instr = emit_add_instr(emit, TupleMember);
-    instr->m_val = next->d.exp_primary.d.num;
-    instr->m_val2 = is_var;
-    emit_add_instr(emit, DotMember); // just a place holder.
-    return GW_OK;
-  }
-  emit_add_instr(emit, GcAdd);
-  CHECK_BB(emit_exp(emit, array->array->exp, 0))
+ANN static void array_loop(const Emitter emit, const m_uint depth) {
   regpop(emit, depth * SZ_INT);
   emit_add_instr(emit, GWOP_EXCEPT);
   for(m_uint i = 0; i < depth - 1; ++i) {
@@ -459,10 +408,62 @@ assert(depth);
   regpop(emit, SZ_INT);
   const Instr access = emit_add_instr(emit, ArrayAccess);
   access->m_val = depth;
+}
+
+ANN static void array_finish(const Emitter emit, const m_uint depth,
+               const m_uint size, const m_bool is_var) {
   const Instr get = emit_add_instr(emit, is_var ? ArrayAddr : ArrayGet);
   get->m_val = depth;
   const Instr push = emit_add_instr(emit, ArrayValid);
-  push->m_val = is_var ? SZ_INT : exp_self(array)->type->size;
+  push->m_val = is_var ? SZ_INT : size;
+}
+
+ANN static inline void array_do(const  Emitter emit, const m_uint depth,
+                   const m_uint size, const m_bool is_var) {
+  array_loop(emit, depth);
+  array_finish(emit, depth, size, is_var);
+}
+
+ANN static inline void tuple_access(const  Emitter emit, const m_uint idx,
+        const m_bool is_var) {
+  emit_add_instr(emit, GWOP_EXCEPT);
+  const Instr instr = emit_add_instr(emit, TupleMember);
+  instr->m_val = idx;
+  instr->m_val2 = is_var;
+  emit_add_instr(emit, DotMember); // just a place holder.
+}
+
+ANN static inline Exp exp_antepenultimate(Exp e) {
+  while(e->next && e->next->next)
+    e = e->next;
+  return e;
+}
+
+ANN static m_bool emit_array_indexes(const Emitter emit, const Exp exp,
+      const m_bool is_tuple) {
+  const Exp e = exp_antepenultimate(exp), next = e->next;
+  emit_add_instr(emit, GcAdd);
+  if(is_tuple)
+    e->next = NULL;
+  CHECK_BB(emit_exp(emit, exp, 0))
+  if(is_tuple)
+    e->next = next;
+  return GW_OK;
+}
+
+ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) {
+  CHECK_BB(emit_exp(emit, array->base, 0))
+  const Type array_type = exp_self(array)->type, t_base = array->base->type,
+      type = array_base(t_base) ?: t_base;
+  const m_uint depth = get_depth(t_base) - get_depth(array_type);
+  const m_bool is_tuple = isa(type, t_tuple) > 0 && isa(array_type, t_tuple) < 0;
+  const m_uint is_var = exp_self(array)->emit_var;
+  if(depth) {
+    CHECK_BB(emit_array_indexes(emit, array->array->exp, is_tuple))
+    array_do(emit, depth, array_type->size, is_var);
+  }
+  if(is_tuple)
+    tuple_access(emit, array->array->exp->d.exp_primary.d.num, is_var);
   return GW_OK;
 }