]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve ArrayAccess
authorfennecdjay <astor.jeremie@wanadoo.fr>
Sat, 17 Aug 2019 10:32:20 +0000 (12:32 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Sat, 17 Aug 2019 10:32:20 +0000 (12:32 +0200)
src/emit/emit.c
src/parse/check.c

index 9a7bc160374fcac2c6baab5eb386551657b64ca4..f3a14efd46ea106546d1f89b95de632bf884e0e1 100644 (file)
@@ -398,6 +398,21 @@ ANN static m_bool prim_array(const Emitter emit, const Exp_Primary * primary) {
   return GW_OK;
 }
 
+//! emit only one index at the time
+ANN static inline m_bool emit_index(const Emitter emit, const Exp e) {
+  const Exp next = e->next;
+  e->next = NULL;
+  const m_bool ret = emit_exp(emit, e, 0);
+  e->next = next;
+  return ret;
+}
+
+static inline Exp take_exp(Exp e, m_uint n) {
+  for(m_uint i = 1; i < n; ++i)
+    CHECK_OO((e = e->next))
+  return e;
+}
+
 ANN static void array_loop(const Emitter emit, const m_uint depth) {
   regpop(emit, depth * SZ_INT);
   emit_add_instr(emit, GWOP_EXCEPT);
@@ -422,10 +437,12 @@ ANN static void array_finish(const Emitter emit, const m_uint depth,
   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 m_bool array_do(const  Emitter emit, const Array_Sub array, const m_bool is_var) {
+  emit_add_instr(emit, GcAdd);
+  CHECK_BB(emit_exp(emit, array->exp, 0))
+  array_loop(emit, array->depth);
+  array_finish(emit, array->depth, array->type->size, is_var);
+  return GW_OK;
 }
 
 ANN static inline void tuple_access(const  Emitter emit, const m_uint idx,
@@ -437,38 +454,61 @@ ANN static inline void tuple_access(const  Emitter emit, const m_uint idx,
   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;
-}
+struct ArrayAccessInfo {
+  struct Array_Sub_ array;
+  const Type type;
+  const m_bool is_var;
+};
 
-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 inline m_bool _emit_indexes(const Emitter emit, struct ArrayAccessInfo *const info);
+
+ANN static inline m_bool tuple_index(const Emitter emit, struct ArrayAccessInfo *const info) {
+  assert(isa(info->array.type, t_tuple) > 0);
+  const m_uint idx = info->array.exp->d.exp_primary.d.num;
+  tuple_access(emit, info->array.exp->d.exp_primary.d.num, info->array.depth ? 0 : info->is_var);
+  if(!info->array.exp->next)
+    return GW_OK;
+  const Type type = (Type)vector_at(&info->array.type->e->tuple->types, idx);
+  struct Array_Sub_ next = { info->array.exp->next, type, info->array.depth - 1 };
+  info->array = next;
+  return _emit_indexes(emit, info);
+}
+
+ANN static inline Exp emit_n_exp(const Emitter emit,  struct ArrayAccessInfo *const info) {
+  const Exp e = take_exp(info->array.exp, info->array.depth);
+  const Exp next = e->next;
+  e->next = NULL;
+  struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.depth };
+  const m_bool ret = array_do(emit, &partial, 0);
+  e->next = next;
+  return ret > 0 ? next : NULL;
+}
+
+ANN static inline m_bool _emit_indexes(const Emitter emit, struct ArrayAccessInfo *const info) {
+  if(GET_FLAG(info->array.type, typedef)) {
+    info->array.type = info->array.type->e->parent;
+    return _emit_indexes(emit, info);
+  }
+  if(!info->array.type->array_depth)
+    return tuple_index(emit, info);
+  if(info->array.type->array_depth >= info->array.depth) {
+    struct Array_Sub_ next = { info->array.exp, info->type, info->array.depth };
+    return array_do(emit, &next, info->is_var);
+  }
+  struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.depth - info->array.type->array_depth };
+  struct Array_Sub_ next = { info->array.exp, array_base(info->array.type), info->array.depth - info->array.type->array_depth };
+  info->array = partial;
+  DECL_OB(const Exp, exp, = emit_n_exp(emit, info))
+  next.exp = exp;
+  info->array = next;
+  return _emit_indexes(emit, info);
 }
 
 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;
+  const Exp e = exp_self(array);
+  struct ArrayAccessInfo info = { *array->array, e->type, e->emit_var };
+  return _emit_indexes(emit, &info);
 }
 
 ANN static m_bool prim_vec(const Emitter emit, const Exp_Primary * primary) {
index 9c2ef81d08744dfc98420623a414651b2ea04da8..4ba791520783babe6ce57d6b07bbd3b802ce5788 100644 (file)
@@ -358,13 +358,42 @@ ANN static Type check_exp_primary(const Env env, const Exp_Primary* primary) {
   return exp_self(primary)->type = prim_func[primary->primary_type](env, primary);
 }
 
-ANN Type at_depth(const Env env, const Type t, const m_uint depth) {
+static inline Exp take_exp(Exp e, m_uint n) {
+  for(m_uint i = 1; i < n; ++i)
+    CHECK_OO((e = e->next))
+  return e;
+}
+
+ANN static Type at_depth(const Env env, const Array_Sub array) {
+  const Type t = array->type;
+  const m_uint depth = array->depth;
+  const Exp e = array->exp;
   if(!depth)
     return t;
-  if(GET_FLAG(t, typedef))
-    return at_depth(env, t->e->parent, depth);
-  if(depth > t->array_depth)
-    return at_depth(env, t->e->d.base_type, depth - t->array_depth);
+  if(GET_FLAG(t, typedef)) {
+    struct Array_Sub_ next = { e, t->e->parent, depth };
+    return at_depth(env, &next);
+  }
+  if(depth > t->array_depth) {
+    const Exp curr = take_exp(e, t->array_depth);
+    const Type t_base = array_base(t) ?: t;
+    if(isa(t_base, t_tuple) > 0) {
+      if(curr->exp_type != ae_exp_primary ||
+          curr->d.exp_primary.primary_type != ae_primary_num)
+         ERR_O(e->pos, _("tuple subscripts must be litteral"))
+      const m_uint idx = curr->d.exp_primary.d.num;
+      const Type type = (Type)vector_at(&t_base->e->tuple->types, idx);
+      if(type == t_undefined)
+         ERR_O(e->pos, _("tuple subscripts is undefined"))
+      struct Array_Sub_ next = { curr->next, type, depth - t->array_depth - 1 };
+      return at_depth(env, &next);
+    }
+    if(!curr->next)
+      ERR_O(e->pos, _("array subscripts (%i) exceeds defined dimension (%i)"),
+          depth, get_depth(t))
+      struct Array_Sub_ next = { curr->next, t_base, depth - t->array_depth };
+      return at_depth(env, &next);
+  }
   return array_type(env, array_base(t), t->array_depth - depth);
 }
 
@@ -381,42 +410,14 @@ static m_bool array_access_valid(const Env env, const Exp_Array* array) {
   CHECK_BB(index_is_int(env, array->array->exp, &depth))
   if(depth != array->array->depth)
     ERR_B(exp_self(array)->pos, _("invalid array acces expression."))
-  DECL_OB(const Type, t_base,  = check_exp(env, array->base))
-  if(depth > get_depth(t_base)) {
-    const Type type = array_base(t_base) ?: t_base;
-    if(isa(type, t_tuple) > 0 && depth - get_depth(t_base) == 1) {
-      Exp e = array->array->exp;
-      while(e->next)
-        e = e->next;
-      if(e->exp_type != ae_exp_primary ||
-          e->d.exp_primary.primary_type != ae_primary_num)
-         ERR_B(exp_self(array)->pos, _("tuple subscripts must be litteral"))
-      if((Type)vector_at(&type->e->tuple->types, e->d.exp_primary.d.num) == t_undefined)
-         ERR_B(exp_self(array)->pos, _("tuple subscripts is undefined"))
-      return 0;
-    }
-    ERR_B(exp_self(array)->pos,
-      _("array subscripts (%i) exceeds defined dimension (%i)"),
-          array->array->depth, get_depth(t_base))
-  }
   return GW_OK;
 }
 
 static ANN Type check_exp_array(const Env env, const Exp_Array* array) {
+  CHECK_OO((array->array->type = check_exp(env, array->base)))
   CHECK_OO(check_exp(env, array->array->exp))
-  const m_bool ret = array_access_valid(env, array);
-  CHECK_BO(ret);
-  if(!ret) {
-    Exp e = array->array->exp;
-    while(e->next)
-      e = e->next;
-    // if we implement tuple with no type, err_msg
-    const Type type = array_base(array->base->type) ?: array->base->type;
-    if(e->d.exp_primary.d.num >= vector_size(&type->e->tuple->types))
-      ERR_O(exp_self(array)->pos, "Invalid tuple subscript")
-    return (Type)vector_at(&type->e->tuple->types, e->d.exp_primary.d.num);
-  }
-  return at_depth(env, array->base->type, array->array->depth);
+  CHECK_BO(array_access_valid(env, array))
+  return at_depth(env, array->array);
 }
 
 ANN static Type_List mk_type_list(const Env env, const Type type) {