]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve foreach
authorJérémie Astor <fennecdjay@gmail.com>
Mon, 14 Dec 2020 23:27:24 +0000 (00:27 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Mon, 14 Dec 2020 23:27:24 +0000 (00:27 +0100)
ast
include/lang_private.h
include/tmpl_info.h
src/emit/emit.c
src/lib/engine.c
src/lib/foreach.c [new file with mode: 0644]
src/lib/object_op.c
src/parse/check.c
tests/tree/auto_array.gw
tests/tree/auto_fun.gw
tests/tree/auto_ptr.gw

diff --git a/ast b/ast
index 2183d0dd09928316960494532af8b57911341061..1f57eb48c6eb8b0379b3d232cb7f3fe1ccf90d67 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 2183d0dd09928316960494532af8b57911341061
+Subproject commit 1f57eb48c6eb8b0379b3d232cb7f3fe1ccf90d67
index caa2f380606a94f72ed24bbad632c73989a66d5c..7bd61e45e4c884a20178342764d994d4876dbf9f 100644 (file)
@@ -14,4 +14,5 @@ ANN m_bool import_modules(const Gwi gwi);
 ANN m_bool import_object_op(const Gwi gwi);
 ANN m_bool import_values(const Gwi gwi);
 ANN m_bool import_union(const Gwi gwi);
+ANN m_bool import_foreach(const Gwi gwi);
 #endif
index fd2b2b899b2efc4bd5cc050ccb086a53d43ee392..30acc1bf58e0f99517a91500d8cdd3410328b34f 100644 (file)
@@ -10,4 +10,6 @@ struct tmpl_info {
   struct Vector_   size;
   uint8_t index;
 };
+
+ANN Type tmpl_exists(const Env env, struct tmpl_info *const info);
 #endif
index 7cb55f3f6dbeeb02721214389958772c571a6920..af1d0e7a94a84f91b6413ef3e3602afc26d5a500 100644 (file)
@@ -416,6 +416,18 @@ ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) {
     return emit_symbol_owned(emit, data);
   if(vflag(v, vflag_builtin) || vflag(v, vflag_direct) || vflag(v, vflag_enum))
     return emit_symbol_builtin(emit, data);
+  if(!strncmp(v->type->name, "@Foreach:[", 10)) {
+    if(exp_getvar(exp_self(prim_self(data)))) {
+      const Instr instr = emit_add_instr(emit, RegPushMem);
+      instr->m_val = v->from->offset;
+      instr->m_val2 = SZ_INT;
+    } else {
+      const Instr instr = emit_add_instr(emit, RegPushMemDeref);
+      instr->m_val = v->from->offset;
+      instr->m_val2 = v->type->size;
+    }
+    return GW_OK;
+  }
   const m_uint size = v->type->size;
   const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), !vflag(v, vflag_fglobal) ? regpushmem : regpushbase);
   instr->m_val  = v->from->offset;
@@ -1619,20 +1631,18 @@ ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
 
 ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt, m_uint *end_pc) {
   const Instr s1 = emit_add_instr(emit, MemSetImm);
-  Instr cpy = stmt->is_ptr ? emit_add_instr(emit, MemSetImm) : NULL;
+  Instr cpy = emit_add_instr(emit, MemSetImm);
   emit_local(emit, emit->gwion->type[et_int]);
   const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
   emit_local(emit, emit->gwion->type[et_int]);
   stmt->v->from->offset = offset + SZ_INT;
   const m_uint ini_pc  = emit_code_size(emit);
-  const Instr loop = emit_add_instr(emit, stmt->is_ptr ? AutoLoopPtr : AutoLoop);
+  const Instr loop = emit_add_instr(emit, AutoLoopPtr);
   const Instr end = emit_add_instr(emit, BranchEqInt);
   const m_bool ret = scoped_stmt(emit, stmt->body, 1);
   *end_pc = emit_code_size(emit);
-  if(stmt->is_ptr) {
-    loop->m_val2 = (m_uint)stmt->v->type;
-    cpy->m_val = stmt->v->from->offset;
-  }
+  loop->m_val2 = (m_uint)stmt->v->type;
+  cpy->m_val = stmt->v->from->offset;
   const Instr tgt = emit_add_instr(emit, Goto);
   end->m_val = emit_code_size(emit);
   tgt->m_val = ini_pc;
index 14711919f0743e9c344aa4d43b4d955069f0c824..9dc2eaf6f503549db2288e55824731288fff21a4 100644 (file)
@@ -147,6 +147,7 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   GWI_BB(import_shred(gwi))
   GWI_BB(import_modules(gwi))
   GWI_BB(import_union(gwi))
+  GWI_BB(import_foreach(gwi))
 
   GWI_BB(gwi_oper_ini(gwi, "@Class", "@Class", "int"))
   GWI_BB(gwi_oper_end(gwi, "==", int_eq))
diff --git a/src/lib/foreach.c b/src/lib/foreach.c
new file mode 100644 (file)
index 0000000..37bac3d
--- /dev/null
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+#include <string.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "instr.h"
+#include "object.h"
+#include "operator.h"
+#include "import.h"
+#include "emit.h"
+#include "traverse.h"
+#include "template.h"
+#include "parse.h"
+#include "specialid.h"
+#include "gwi.h"
+#include "tmpl_info.h"
+
+OP_CHECK(opck_foreach_scan) {
+  struct TemplateScan *ts = (struct TemplateScan*)data;
+  struct tmpl_info info = { .base=ts->t, .td=ts->td, .list=ts->t->info->cdef->base.tmpl->list  };
+  const Type exists = tmpl_exists(env, &info);
+  if(exists)
+    return exists != env->gwion->type[et_error] ? exists : NULL;
+  const Type base = known_type(env, ts->td->types->td);
+  const Type t = new_type(env->gwion->mp, s_name(info.name), base);
+  return t;
+}
+
+GWION_IMPORT(foreach) {
+  const Type t_foreach = gwi_struct_ini(gwi, "@Foreach:[A]");
+  set_tflag(t_foreach, tflag_ntmpl);
+  GWI_BB(gwi_item_ini(gwi, "@internal", "val"))
+  GWI_BB(gwi_item_end(gwi, ae_flag_none, NULL))
+  GWI_BB(gwi_struct_end(gwi))
+  GWI_BB(gwi_oper_ini(gwi, "@Foreach", NULL, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_foreach_scan))
+  GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
+  return GW_OK;
+}
index 405313fa224c0f7bb19e514557c04c20fb5ce157..01c6e4c785bfa8d5a65c515f5892ee8346c147d6 100644 (file)
@@ -1,5 +1,3 @@
-#include <stdlib.h>
-#include <string.h>
 #include "gwion_util.h"
 #include "gwion_ast.h"
 #include "gwion_env.h"
@@ -13,7 +11,6 @@
 #include "traverse.h"
 #include "template.h"
 #include "parse.h"
-#include "specialid.h"
 #include "gwi.h"
 #include "tmpl_info.h"
 
@@ -241,41 +238,9 @@ ANN static m_bool scantmpl_union_def(const Env env, struct tmpl_info *info) {
     SET_FLAG(udef, global);
   const m_bool ret = scan0_union_def(env, udef);
   if(udef->type) {
-/*
-    if(!strcmp(info->base->name, "Option")) {
-      const Type base = known_type(env, info->td->types->td);
-      const m_uint scope = env_push(env, udef->type->info->parent->info->owner_class, udef->type->info->parent->info->owner);
-      const struct Op_Func opfunc0 = { .ck=opck_option_get, .em=opem_option_get };
-      struct Op_Import opi0 = { .lhs=udef->type, .rhs=base, .ret=base,
-       .op=insert_symbol(env->gwion->st, "?=>"), .pos=info->td->pos, .func=&opfunc0 };
-      CHECK_BB(add_op(env->gwion, &opi0))
-      const struct Op_Func opfunc1 = { .ck=opck_option_set, .em=opem_option_set };
-      struct Op_Import opi1 = { .lhs=base, .rhs=udef->type, .ret=udef->type, .func=&opfunc1,
-       .op=insert_symbol(env->gwion->st, "@=>"), .pos=info->td->pos };
-      CHECK_BB(add_op(env->gwion, &opi1))
-      const struct Op_Func opfunc2 = { .ck=opck_option_setn, .em=opem_option_setn };
-      struct Op_Import opi2 = { .lhs=env->gwion->type[et_error], .rhs=udef->type, .ret=udef->type, .func=&opfunc2,
-       .op=insert_symbol(env->gwion->st, "@=>"), .pos=info->td->pos };
-      CHECK_BB(add_op(env->gwion, &opi2))
-      const struct Op_Func opfunc3 = { .em=opem_option_not };
-      struct Op_Import opi3 = { .rhs=udef->type, .ret=env->gwion->type[et_bool], .func=&opfunc3,
-       .op=insert_symbol(env->gwion->st, "!"), .pos=info->td->pos };
-      CHECK_BB(add_op(env->gwion, &opi3))
-      const struct Op_Func opfunc4 = { .em=opem_option_cond };
-      struct Op_Import opi4 = { .rhs=udef->type, .ret=env->gwion->type[et_bool], .func=&opfunc4,
-       .op=insert_symbol(env->gwion->st, "@conditionnal"), .pos=info->td->pos };
-      CHECK_BB(add_op(env->gwion, &opi4))
-      const struct Op_Func opfunc5 = { .em=opem_option_uncond };
-      struct Op_Import opi5 = { .rhs=udef->type, .ret=env->gwion->type[et_bool], .func=&opfunc5,
-       .op=insert_symbol(env->gwion->st, "@unconditionnal"), .pos=info->td->pos };
-      CHECK_BB(add_op(env->gwion, &opi5))
-      env_pop(env, scope);
-    }
-*/
     udef->type->info->udef = udef;// mark as udef
     info->ret = udef->type;
     set_tflag(info->ret, tflag_udef);
-//    set_tflag(info->ret, tflag_tmpl);
   } else
     free_union_def(env->gwion->mp, udef);
   return ret;
@@ -291,6 +256,7 @@ ANN static Type _scan_class(const Env env, struct tmpl_info *info) {
 
 ANN Type tmpl_exists(const Env env, struct tmpl_info *const info);
 ANN Type scan_class(const Env env, const Type t, const Type_Decl *td) {
+puts("here");
   struct tmpl_info info = { .base=t, .td=td, .list=t->info->cdef->base.tmpl->list  };
   const Type exists = tmpl_exists(env, &info);
   if(exists)
@@ -367,5 +333,6 @@ GWION_IMPORT(object_op) {
   GWI_BB(gwi_oper_ini(gwi, "@Compound", NULL, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_struct_scan))
   GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
+
   return GW_OK;
 }
index c0c6852b677651e871edab85992d8dcbc67d8da5..47e5766939c596ad378298281de9bd97da84c134 100644 (file)
@@ -924,26 +924,26 @@ ANN static inline m_bool for_empty(const Env env, const Stmt_For stmt) {
   return GW_OK;
 }
 
+ANN static inline Type foreach_type(const Env env, const Exp exp) {
+  DECL_OO(Type, et, = check_exp(env, exp))
+  if(isa(et, env->gwion->type[et_array]) < 0)
+    ERR_O(exp->pos, _("type '%s' is not array.\n"
+          " This is not allowed in foreach loop"), et->name)
+  DECL_OO(Type, base, = typedef_base(et))
+  DECL_OO(const Type, t, = array_base(base))
+  const m_uint depth = base->array_depth - 1;
+  return depth ? array_type(env, t, depth) : t;
+
+}
+
 ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) {
-  DECL_OB(Type, t, = check_exp(env, stmt->exp))
-  while(tflag(t, tflag_typedef))
-    t = t->info->parent;
-  Type ptr = array_base(t);
-  const m_uint depth = t->array_depth - 1;
-  if(!ptr || isa(t, env->gwion->type[et_array]) < 0)
-    ERR_B(stmt_self(stmt)->pos, _("type '%s' is not array.\n"
-          " This is not allowed in foreach loop"), stmt->exp->info->type->name)
-  if(stmt->is_ptr) {
-    if(depth)
-      ptr = array_type(env, ptr, depth);
-    char c[15 + strlen(ptr->name)];
-    sprintf(c, "Ptr:[%s]", ptr->name);
-    ptr = str2type(env->gwion, c, stmt->exp->pos);
-    const Type base = get_type(ptr);
-    CHECK_BB(ensure_traverse(env, base))
-  }
-  t = (!stmt->is_ptr && depth) ? array_type(env, ptr, depth) : ptr;
-  stmt->v = new_value(env->gwion->mp, t, s_name(stmt->sym));
+  DECL_OB(const Type, ptr, = foreach_type(env, stmt->exp))
+  const Type base = get_type(ptr);
+  CHECK_BB(ensure_traverse(env, base))
+  char c[15 + strlen(ptr->name)];
+  sprintf(c, "@Foreach:[%s]", ptr->name);
+  const Type ret = str2type(env->gwion, c, stmt->exp->pos);
+  stmt->v = new_value(env->gwion->mp, ret, s_name(stmt->sym));
   set_vflag(stmt->v, vflag_valid);
   nspc_add_value(env->curr, stmt->sym, stmt->v);
   return check_conts(env, stmt_self(stmt), stmt->body);
index be0bdafce8122507544bed78f1fac6d27449ee45..03fdc9865f413b775a4133d12cc4fce44394a80b 100644 (file)
@@ -1,4 +1,4 @@
 var int i[2][2];
-foreach(ref a : i)
+foreach(a : i)
    <<< a >>>;
 <<< i >>>;
index 59332d4946c3409ba218b838c8e9914d780e9ed2..92f23720a110f5f796a1280b48ecff5f8041d2a6 100644 (file)
@@ -4,6 +4,6 @@ class C {
 
 var C i[2];
 
-foreach(ref a : i)
+foreach(a : i)
      <<< a >>>;
 
index a9ca992baa342486e60b38372538e4cedcf5986f..0da29291cc6341b6856374d8281de0050b7b69bc 100644 (file)
@@ -1,5 +1,5 @@
-var Ptr:[int] ptr;
 var int i[4];
-foreach(ref a : i)
-  <<< *a >>>;
-<<< ptr >>>;
+foreach(a : i)
+  <<< 1 => a >>>;
+foreach(a : i)
+  <<< a >>>;