From: Jérémie Astor Date: Tue, 26 Apr 2022 11:04:32 +0000 (+0200) Subject: :bug: Fix array bug wrt Refs X-Git-Tag: nightly~275^2~42 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=b2f49a6593b1438a1dde6008df1f77b9e1f19a62;p=gwion.git :bug: Fix array bug wrt Refs --- diff --git a/include/env/value.h b/include/env/value.h index 8b93a5ca..35d5d513 100644 --- a/include/env/value.h +++ b/include/env/value.h @@ -51,4 +51,9 @@ ANN static inline void defined_here(const Value v) { if (v->from->filename) // TODO: check why is that from check gwerr_secondary(_("defined here"), v->from->filename, v->from->loc); } + +ANN static inline void valid_value(const Env env, const Symbol xid, const Value v) { + set_vflag(v, vflag_valid); + nspc_add_value(env->curr, xid, v); +} #endif diff --git a/include/opcode.h b/include/opcode.h index 76b978cb..a9e0912e 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -159,6 +159,8 @@ enum { eSporkFunc, eSporkMemberFptr, eSporkExp, + eSporkCode, + eForkEnd, eSporkEnd, eBranchEqInt, eBranchNeqInt, @@ -376,6 +378,8 @@ enum { #define SporkFunc (f_instr)eSporkFunc #define SporkMemberFptr (f_instr)eSporkMemberFptr #define SporkExp (f_instr)eSporkExp +#define SporkCode (f_instr)eSporkCode +#define ForkEnd (f_instr)eForkEnd #define SporkEnd (f_instr)eSporkEnd #define BranchEqInt (f_instr)eBranchEqInt #define BranchNeqInt (f_instr)eBranchNeqInt @@ -1153,6 +1157,15 @@ ANN static inline void dump_opcodes(const VM_Code code) { gw_out(" {-R}%-14"UINT_F"{0}", instr->m_val); gw_out("\n"); break; + case eSporkCode: + gw_out("{Y}┃{0}{-}% 4lu{0}: SporkCode ", j); + gw_out(" {-R}%-14"UINT_F"{0}", instr->m_val); + gw_out("\n"); + break; + case eForkEnd: + gw_out("{Y}┃{0}{-}% 4lu{0}: ForkEnd ", j); + gw_out("\n"); + break; case eSporkEnd: gw_out("{Y}┃{0}{-}% 4lu{0}: SporkEnd ", j); gw_out("\n"); diff --git a/opcode.txt b/opcode.txt index 1ef10f3b..2de1c0f6 100644 --- a/opcode.txt +++ b/opcode.txt @@ -156,6 +156,8 @@ ForkIni~p~i SporkFunc SporkMemberFptr~u SporkExp~u +SporkCode~u +ForkEnd SporkEnd BranchEqInt~pc BranchNeqInt~pc diff --git a/src/emit/emit.c b/src/emit/emit.c index dc7d90c0..4b3fcd97 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1860,6 +1860,7 @@ struct Sporker { const Exp exp; VM_Code vm_code; const Type type; + const Capture_List captures; const bool emit_var; const bool is_spork; }; @@ -1900,7 +1901,7 @@ ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) { ANN void spork_code(const Emitter emit, const struct Sporker *sp) { const Instr args = emit_add_instr(emit, SporkExp); args->m_val = emit->code->stack_depth; - const Instr instr = emit_add_instr(emit, SporkEnd); + const Instr instr = emit_add_instr(emit, sp->is_spork ? SporkEnd : ForkEnd); instr->m_val = sp->emit_var; } @@ -1943,12 +1944,41 @@ ANN m_bool emit_exp_spork(const Emitter emit, const Exp_Unary *unary) { .exp = unary->unary_type == unary_exp ? unary->exp : NULL, .code = unary->unary_type == unary_code ? unary->code : NULL, .type = exp_self(unary)->type, + .captures = unary->captures, .is_spork = (unary->op == insert_symbol("spork")), .emit_var = exp_getvar(exp_self(unary))}; CHECK_OB((sporker.vm_code = spork_prepare(emit, &sporker))); if(!sporker.is_spork) emit_local_exp(emit, exp_self(unary)); spork_ini(emit, &sporker); + +if(sporker.captures) { + Capture_List caps = sporker.captures; +// what about types? + uint32_t offset = 0; + for (uint32_t i = 0; i < caps->len; i++) { + Capture *cap = mp_vector_at(caps, Capture, i); + const Value v = nspc_lookup_value1(emit->env->curr, cap->xid); + struct Exp_ exp = { + .d = { .prim = { + .d = { .var = cap->xid }, + .value = v, + .prim_type = ae_prim_id + }}, + .type = v->type, + .exp_type = ae_exp_primary + }; +// handle emit var? +//exp_setvar(&exp, false); + emit_exp(emit, &exp); + } +// pop_exp(emit, &exp); +regpop(emit, SZ_INT); + const Instr args = emit_add_instr(emit, SporkCode); + args->m_val = 8; //emit->code->stack_depth; + } + +// emit_local_exp(emit, exp_self(unary)); (unary->unary_type == unary_code ? spork_code : spork_func)(emit, &sporker); return GW_OK; } @@ -2470,10 +2500,14 @@ ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt, loop_idx->m_val = key_offset; loop_idx->m_val2 = -1; stmt->v->from->offset = val_offset; +//value_addref(stmt->v); +nspc_add_value(emit->env->curr, stmt->sym, stmt->v); emit_debug(emit, stmt->v); if (stmt->idx) { stmt->idx->v->from->offset = key_offset; - emit_debug(emit, stmt->v); +nspc_add_value(emit->env->curr, stmt->idx->sym, stmt->idx->v); +//value_addref(stmt->idx->v); + emit_debug(emit, stmt->idx->v); } struct Looper loop = {.exp = stmt->exp, .stmt = stmt->body, diff --git a/src/lib/array.c b/src/lib/array.c index 3614edbe..7400d199 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -763,8 +763,14 @@ ANN static inline Type foreach_type(const Env env, const Exp exp) { const Type et = exp->type; DECL_OO(Type, base, = typedef_base(et)); DECL_OO(const Type, t, = array_base_simple(base)); - const m_uint depth = base->array_depth - 1; - return depth ? array_type(env, t, depth) : t; + if(!tflag(base, tflag_ref)) { + const m_uint depth = base->array_depth - 1; + return depth ? array_type(env, t, depth) : t; + } + const Type inner = (Type)vector_front(&base->info->tuple->contains); + const Type refbase = array_base_simple(inner); + const m_uint depth = inner->array_depth - 1; + return depth ? array_type(env, refbase, depth) : refbase; } // rewrite me diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index 834b5634..3edb530d 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -615,9 +615,7 @@ static OP_EMIT(opem_op_impl) { instr->m_val2 = -SZ_INT; return ret; } - -ANN Type check_exp_unary_spork(const Env env, const Stmt code); - +/* ANN static void fork_exp(const Env env, const Exp_Unary *unary) { Stmt_List slist = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 1); mp_vector_set(slist, struct Stmt_, 0, @@ -630,10 +628,10 @@ ANN static void fork_exp(const Env env, const Exp_Unary *unary) { ((Exp_Unary *)unary)->code = code; ((Exp_Unary *)unary)->unary_type = unary_code; } - +*/ ANN static Type fork_type(const Env env, const Exp_Unary *unary) { const Type t = unary->exp->type; - fork_exp(env, unary); +// fork_exp(env, unary); if (t == env->gwion->type[et_void]) return env->gwion->type[et_fork]; char c[21 + strlen(t->name)]; sprintf(c, "TypedFork:[%s]", t->name); @@ -650,6 +648,16 @@ ANN static Type fork_type(const Env env, const Exp_Unary *unary) { return ret; } +ANN Type upvalue_type(const Env env, Capture *cap) { + const Value v = nspc_lookup_value1(env->curr, cap->xid); + if(!v)exit(3); + if(cap->is_ref && not_upvalue(env, v)) + ERR_O(cap->pos, _("can't take ref of a scoped value")); + cap->v = v; + const Type base_type = !tflag(v->type, tflag_ref) ? v->type : (Type)vector_front(&v->type->info->tuple->contains); + return !cap->is_ref ? base_type : ref_type(env->gwion, base_type, cap->pos); +} + static OP_CHECK(opck_spork) { const Exp_Unary *unary = (Exp_Unary *)data; if (unary->unary_type == unary_exp && unary->exp->exp_type == ae_exp_call) { @@ -657,10 +665,36 @@ static OP_CHECK(opck_spork) { return is_spork ? env->gwion->type[et_shred] : fork_type(env, unary); } if (unary->unary_type == unary_code) { + if(unary->captures) { + uint32_t offset = 0; + for(uint32_t i = 0; i < unary->captures->len; i++) { + Capture *const cap = mp_vector_at(unary->captures, Capture, i); + DECL_OO(const Type, t, = upvalue_type(env, cap)); + cap->v = new_value(env->gwion->mp, t, s_name(cap->xid)); + cap->v->from->offset = offset; + offset += cap->v->type->size; + } + } ++env->scope->depth; - nspc_push_value(env->gwion->mp, env->curr); + const Scope scope = env->curr->info->value; + env->curr->info->value = new_scope(env->gwion->mp); + if(unary->captures) { + for(uint32_t i = 0; i < unary->captures->len; i++) { + Capture *const cap = mp_vector_at(unary->captures, Capture, i); + valid_value(env, cap->xid, cap->v); + } + } + const Func f = env->func; + struct Value_ value = {}; + set_vflag(&value, vflag_member); + struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = scope}; + struct Func_Def_ fdef = { .base = &fbase}; + struct Func_ func = { .name = "in spork", .def = &fdef, .value_ref = &value}; + env->func = &func; const m_bool ret = check_stmt(env, unary->code); - nspc_pop_value(env->gwion->mp, env->curr); + env->func = f; + free_scope(env->gwion->mp, env->curr->info->value); + env->curr->info->value = scope; --env->scope->depth; CHECK_BN(ret); return env->gwion diff --git a/src/parse/check.c b/src/parse/check.c index 81587e2e..a374bf54 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -113,11 +113,6 @@ ANN static m_bool check_var_td(const Env env, const Var_Decl var, return GW_OK; } -ANN static inline void valid_value(const Env env, const Symbol xid, const Value v) { - set_vflag(v, vflag_valid); - nspc_add_value(env->curr, xid, v); -} - ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) { Var_Decl_List list = decl->list; for(uint32_t i = 0; i < list->len; i++) { @@ -369,7 +364,9 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) { prim_self(data)->value = env->gwion->type[et_op]->info->value; return env->gwion->type[et_op]; } - gwerr_basic(_("Invalid variable"), _("not legit at this point."), NULL, + const m_str hint = (!env->func || strcmp(env->func->name, "in spork")) ? + NULL : "vapturelist?"; + gwerr_basic(_("Invalid variable"), _("not legit at this point."), hint, env->name, prim_pos(data), 0); did_you_mean_nspc(v ? value_owner(env, v) : env->curr, s_name(sym)); env_set_error(env); @@ -724,6 +721,7 @@ ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) { func->def->base->ret_type : exp->func->d.exp_dot.base->type; } +ANN Type upvalue_type(const Env env, Capture *cap); ANN static Type check_lambda_call(const Env env, Exp_Call *const exp) { const Func_Def fdef = exp->func->d.exp_lambda.def; if (exp->args) { @@ -739,13 +737,7 @@ ANN static Type check_lambda_call(const Env env, Exp_Call *const exp) { fdef->base->args = new_mp_vector(env->gwion->mp, sizeof(Arg), 0); for(uint32_t i = 0; i < fdef->captures->len; i++) { Capture *const cap = mp_vector_at(fdef->captures, Capture, i); - const Value v = nspc_lookup_value1(env->curr, cap->xid); - if(!v)exit(3); - if(cap->is_ref && not_upvalue(env, v)) - ERR_O(cap->pos, _("can't take ref of a scoped value")); - cap->v = v; - const Type base_type = !tflag(v->type, tflag_ref) ? v->type : (Type)vector_front(&v->type->info->tuple->contains); - const Type t = !cap->is_ref ? base_type : ref_type(env->gwion, base_type, cap->pos); + DECL_OO(const Type, t, = upvalue_type(env, cap)); // could leak Arg arg = { .td = type2td(env->gwion, t, exp->func->pos), .var_decl = { .xid = cap->xid } diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 128519f1..8dba5259 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -236,6 +236,7 @@ ANN static m_bool scan1_exp_if(const Env env, const Exp_If *exp_if) { ANN static inline m_bool scan1_exp_unary(const restrict Env env, Exp_Unary *const unary) { if (unary->unary_type == unary_code) { +if(strcmp("fork", s_name(unary->op))) { const loc_t pos = exp_self(unary)->pos; const Symbol sym = lambda_name(env->gwion->st, pos.first); Exp lambda = new_exp_lambda(env->gwion->mp, sym, NULL, unary->code, pos); @@ -244,6 +245,10 @@ ANN static inline m_bool scan1_exp_unary(const restrict Env env, mp_free(env->gwion->mp, Stmt, unary->code); unary->exp = new_exp_call(env->gwion->mp, lambda, NULL, pos); unary->unary_type = unary_exp; +} else { +return scan1_stmt(env, unary->code); +} + } return unary->unary_type == unary_exp ? scan1_exp(env, unary->exp) : GW_OK; } diff --git a/src/vm/vm.c b/src/vm/vm.c index deb2b8eb..71e90553 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -267,7 +267,6 @@ ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, VM * vm = shred->info->vm; if (!vm->gwion->data->child.ptr) vector_init(&vm->gwion->data->child); vector_add(&vm->gwion->data->child, (vtype)o); - fork_launch(o); return ME(o); } @@ -471,8 +470,8 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto] &®tomem, &®tomemother, &&overflow, &&funcusrend, &&funcusrend2, &&funcmemberend, - &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, - &&sporkend, &&brancheqint, &&branchneint, &&brancheqfloat, + &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkcode, + &&forkend, &&sporkend, &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat, &&unroll, &&arrayappend, &&autounrollinit, &&autoloop, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&newobj, &&addref, &&addrefaddr, &&structaddref, &&structaddrefaddr, &&objassign, &&assign, @@ -540,7 +539,7 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto] regpushmemaddr: *(m_bit **)reg = &*(m_bit *)(mem + IVAL); reg += SZ_INT; - DISPATCH() + DISPATCH(); regpushmemderef: memcpy(reg, *(m_bit **)(mem + IVAL), VAL2); reg += VAL2; @@ -981,6 +980,13 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto] for (m_uint i = 0; i < VAL; i += SZ_INT) *(m_uint *)(child->mem + i) = *(m_uint *)(mem + i); DISPATCH() + sporkcode: + // LOOP_OPTIM + for (m_uint i = 0; i < VAL; i += SZ_INT) + *(m_uint *)(child->mem + i) = *(m_uint *)(reg + i); + DISPATCH() + forkend: + fork_launch(child->info->me); sporkend: assert(!VAL); // spork are not mutable *(M_Object *)(reg - SZ_INT) = child->info->me; @@ -1308,7 +1314,7 @@ static void *_dispatch[] = { &&_regtomem, &&_regtomemother, &&_overflow, &&_funcusrend, &&_funcusrend2, &&_funcmemberend, - &&_sporkini, &&_forkini, &&_sporkfunc, &&_sporkmemberfptr, &&_sporkexp, + &&_sporkini, &&_forkini, &&_sporkfunc, &&_sporkmemberfptr, &&_sporkexp, &&_sporkcode, &&_forkend, &&_sporkend, &&_brancheqint, &&_branchneint, &&_brancheqfloat, &&_branchnefloat, &&_unroll, &&_arrayappend, &&_autounrollinit, &&_autoloop, &&_arraytop, &&_arrayaccess, &&_arrayget, &&_arrayaddr, &&_newobj, &&_addref, @@ -1512,6 +1518,8 @@ return; PREPARE(sporkfunc); PREPARE(sporkmemberfptr); PREPARE(sporkexp); + PREPARE(sporkcode); + PREPARE(forkend); PREPARE(sporkend); PREPARE(brancheqint); PREPARE(branchneint);