From: Jérémie Astor Date: Mon, 14 Dec 2020 23:27:24 +0000 (+0100) Subject: :art: Improve foreach X-Git-Tag: nightly~1105^2~22 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=33fb73154137cb4ef47fd637018ec8bbcd78eb54;p=gwion.git :art: Improve foreach --- diff --git a/ast b/ast index 2183d0dd..1f57eb48 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit 2183d0dd09928316960494532af8b57911341061 +Subproject commit 1f57eb48c6eb8b0379b3d232cb7f3fe1ccf90d67 diff --git a/include/lang_private.h b/include/lang_private.h index caa2f380..7bd61e45 100644 --- a/include/lang_private.h +++ b/include/lang_private.h @@ -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 diff --git a/include/tmpl_info.h b/include/tmpl_info.h index fd2b2b89..30acc1bf 100644 --- a/include/tmpl_info.h +++ b/include/tmpl_info.h @@ -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 diff --git a/src/emit/emit.c b/src/emit/emit.c index 7cb55f3f..af1d0e7a 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -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; diff --git a/src/lib/engine.c b/src/lib/engine.c index 14711919..9dc2eaf6 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -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 index 00000000..37bac3df --- /dev/null +++ b/src/lib/foreach.c @@ -0,0 +1,41 @@ +#include +#include +#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; +} diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 405313fa..01c6e4c7 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -1,5 +1,3 @@ -#include -#include #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; } diff --git a/src/parse/check.c b/src/parse/check.c index c0c6852b..47e57669 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -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); diff --git a/tests/tree/auto_array.gw b/tests/tree/auto_array.gw index be0bdafc..03fdc986 100644 --- a/tests/tree/auto_array.gw +++ b/tests/tree/auto_array.gw @@ -1,4 +1,4 @@ var int i[2][2]; -foreach(ref a : i) +foreach(a : i) <<< a >>>; <<< i >>>; diff --git a/tests/tree/auto_fun.gw b/tests/tree/auto_fun.gw index 59332d49..92f23720 100644 --- a/tests/tree/auto_fun.gw +++ b/tests/tree/auto_fun.gw @@ -4,6 +4,6 @@ class C { var C i[2]; -foreach(ref a : i) +foreach(a : i) <<< a >>>; diff --git a/tests/tree/auto_ptr.gw b/tests/tree/auto_ptr.gw index a9ca992b..0da29291 100644 --- a/tests/tree/auto_ptr.gw +++ b/tests/tree/auto_ptr.gw @@ -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 >>>;