From c2bcfbfae7579c6e7fa6497b99f86e832d63bfbb Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Fri, 5 Nov 2021 11:07:24 +0100 Subject: [PATCH] :smile: Push tmp branch --- fmt | 2 +- include/emit.h | 1 + include/looper.h | 22 +++++ include/object.h | 6 +- src/emit/emit.c | 172 +++++++++++++++++----------------- src/env/value.c | 2 +- src/lib/array.c | 69 +++++++++----- src/lib/dict.c | 103 +++++++++++++++++--- src/lib/instr.c | 4 +- src/lib/object.c | 20 ++-- src/lib/object_op.c | 2 +- src/lib/opfunc.c | 4 +- src/parse/check.c | 73 +++++++++------ src/vm/vm.c | 4 +- tests/error/auto_not_array.gw | 4 - util | 2 +- 16 files changed, 317 insertions(+), 173 deletions(-) create mode 100644 include/looper.h delete mode 100644 tests/error/auto_not_array.gw diff --git a/fmt b/fmt index 35dae816..f7c8eadc 160000 --- a/fmt +++ b/fmt @@ -1 +1 @@ -Subproject commit 35dae816a65843488b03d4dce27b1dfa8ddc09ea +Subproject commit f7c8eadcf1727a3132a8a5b970f1fc879e44138e diff --git a/include/emit.h b/include/emit.h index 4e55dce8..de188b50 100644 --- a/include/emit.h +++ b/include/emit.h @@ -12,6 +12,7 @@ typedef struct Frame_ { typedef struct VMValue_ { Type t; + void *local; /// :..... uint16_t offset; uint16_t start; uint16_t end; diff --git a/include/looper.h b/include/looper.h new file mode 100644 index 00000000..d5553c86 --- /dev/null +++ b/include/looper.h @@ -0,0 +1,22 @@ +#ifndef __LOOPER +#define __LOOPER + +typedef struct Looper Looper; + +typedef Instr (*f_looper)(const Emitter, const Looper *); + +struct Looper { + const Exp exp; + const Stmt stmt; + /*const */ m_uint offset; + const m_uint n; + const f_looper roll; + const f_looper unroll; +// union { + struct Vector_ unroll_v; + Instr instr; +// }; + struct EachIdx_ *idx; + bool init; +}; +#endif diff --git a/include/object.h b/include/object.h index 45048912..dae95eb4 100644 --- a/include/object.h +++ b/include/object.h @@ -3,9 +3,9 @@ typedef struct M_Object_ *M_Object; struct M_Object_ { Type type_ref; - struct Vector_ vtable; - /*volatile */uint32_t ref; - uint32_t offset; +// struct Vector_ vtable; + /*volatile */uint64_t ref; +// uint32_t offset; m_bit data[]; }; diff --git a/src/emit/emit.c b/src/emit/emit.c index f0296493..9e476de7 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -17,6 +17,7 @@ #include "match.h" #include "specialid.h" #include "vararg.h" +#include "looper.h" #undef insert_symbol #define insert_symbol(a) insert_symbol(emit->gwion->st, (a)) @@ -80,8 +81,8 @@ ANN static void free_frame(MemPool p, Frame *a) { mp_free(p, Frame, a); } -ANN static Local *new_local(MemPool p, const Type type) { - Local *local = mp_calloc(p, Local); +ANN static inline Local *new_local(MemPool p, const Type type) { + Local *const local = mp_calloc(p, Local); local->type = type; return local; } @@ -292,7 +293,7 @@ ANN m_uint emit_local(const Emitter emit, const Type t) { if (isa(t, emit->gwion->type[et_compound]) > 0) { l->is_compound = true; VMValue vmval = { - .t = t, .offset = l->offset, .start = emit_code_size(emit)}; + .t = t, .local = l, .offset = l->offset, .start = emit_code_size(emit)}; m_vector_add(&emit->code->live_values, &vmval); ++emit->code->frame->value_count; } @@ -303,7 +304,7 @@ ANN void* emit_localx(const Emitter emit, const Type t) { Local *const l = frame_local(emit->gwion->mp, emit->code->frame, t); l->is_compound = true; VMValue vmval = { - .t = t, .offset = l->offset, .start = emit_code_size(emit)}; + .t = t, .local = l, .offset = l->offset, .start = emit_code_size(emit)}; m_vector_add(&emit->code->live_values, &vmval); ++emit->code->frame->value_count; l->instr = emit_add_instr(emit, Reg2Mem); @@ -960,21 +961,26 @@ ANN static Instr emit_struct_decl(const Emitter emit, const Value v, } ANN void unset_local(const Emitter emit, Local *const l) { +puts("unset"); l->instr->opcode = eNoOp; for(m_uint i = m_vector_size(&emit->code->live_values) + 1; --i;) { VMValue vmval = *(VMValue*)(ARRAY_PTR((&emit->code->live_values)) + (i-1) * sizeof(VMValue)); - if(vmval.offset != l->offset) continue; +// if(vmval.offset != l->offset) continue; + if(vmval.local != l) continue; m_vector_rem(&emit->code->live_values, i-1); + vector_rem2(&emit->code->frame->stack, (vtype)l); +//vector_rem2(&emit->code->instr, l->instr); +// free instr + --emit->code->frame->value_count; break; } - --emit->code->frame->value_count; } ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *decl, const Type t) { - if(!exp_self(decl)->data) +// if(!exp_self(decl)->data) return emit_local(emit, t); - Local *const l = exp_self(decl)->data; - return l->offset; +// Local *const l = exp_self(decl)->data; +// return l->offset; } ANN static m_bool emit_exp_decl_non_static(const Emitter emit, @@ -988,7 +994,8 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const bool is_array = array && array->exp; const bool is_obj = isa(type, emit->gwion->type[et_object]) > 0; const bool emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : true; - if (is_obj && (is_array || !is_ref)) + if (is_obj && (is_array || !is_ref) && !exp_self(decl)->ref) +// if (is_obj && ((is_array && !exp_self(decl)->ref) || !is_ref)) CHECK_BB(emit_instantiate_decl(emit, type, decl->td, array, is_ref)); f_instr *exec = (f_instr *)allocmember; if (!emit->env->scope->depth) emit_debug(emit, v); @@ -1007,7 +1014,7 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, exec) : emit_struct_decl(emit, v, !struct_ctor(v) ? emit_addr : 1); instr->m_val = v->from->offset; - if (is_obj && (is_array || !is_ref)) { + if (is_obj && (is_array || !is_ref) && !exp_self(decl)->ref) { if (!emit_var) emit_add_instr(emit, Assign); else { @@ -1326,10 +1333,11 @@ ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call *exp_call) { const Instr instr = emit_add_instr(emit, Reg2RegAddr); instr->m_val = -SZ_INT; } else { -// if(isa(t, emit->gwion->type[et_object]) > 0) -// if(isa(t, emit->gwion->type[et_object]) > 0) -// emit_local_exp(emit, e); -// emit_localx(emit, t); + if(isa(t, emit->gwion->type[et_object]) > 0) { +//emit_object_addref(emit, -SZ_INT, 0); + emit_local_exp(emit, e); +// emit_localx(emit, t); + } if (!is_func(emit->gwion, exp_call->func->type) && tflag(e->type, tflag_struct)) regpop(emit, SZ_INT); @@ -2219,59 +2227,40 @@ ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) { return ret; } -struct Looper; -typedef Instr (*f_looper_init)(const Emitter, const struct Looper *); -typedef void (*f_looper)(const Emitter, const struct Looper *); -struct Looper { - const Exp exp; - const Stmt stmt; - /*const */ m_uint offset; - const m_uint n; - const f_looper_init roll; - const f_looper_init unroll; -// union { - struct Vector_ unroll_v; - Instr instr; -// }; -}; - -ANN static inline m_bool roll(const Emitter emit, struct Looper *const loop) { - const Instr instr = loop->roll(emit, loop); - CHECK_BB(scoped_stmt(emit, loop->stmt, 1)); - instr->m_val = emit_code_size(emit) + 1; // pass after goto - return GW_OK; -} - -ANN static Instr stmt_each_roll(const Emitter emit, const struct Looper *loop) { -// const Instr instr = emit_add_instr(emit, AutoLoop); -// instr->m_val2 = loop->offset + SZ_INT; -// return instr; +ANN static Instr each_op(const Emitter emit, const Looper *loop) { struct Op_Import opi = { .lhs = loop->exp->type, - .op = insert_symbol("@autoloop"), + .op = insert_symbol("@each"), .data = (m_uint)loop }; CHECK_BO(op_emit(emit, &opi)); return loop->instr; } +ANN static inline m_bool roll(const Emitter emit, Looper*const loop) { +const Instr instr = loop->roll(emit, loop); +// DECL_OB(const Instr, instr, = each_op(emit, loop)); // maybe check in check.c + CHECK_BB(scoped_stmt(emit, loop->stmt, 1)); + instr->m_val = emit_code_size(emit) + 1; // pass after goto + return GW_OK; +} + ANN static inline void unroll_init(const Emitter emit, const m_uint n) { - emit->info->unroll = 0; const Instr instr = emit_add_instr(emit, MemSetImm); instr->m_val = emit_local(emit, emit->gwion->type[et_int]); instr->m_val2 = n; } ANN static inline m_bool unroll_run(const Emitter emit, - struct Looper *const loop) { - const Instr instr = loop->unroll ? loop->unroll(emit, loop) : NULL; + struct Looper *loop) { + const Instr instr = each_op(emit, loop); CHECK_BB(scoped_stmt(emit, loop->stmt, 1)); if(instr) vector_add(&loop->unroll_v, (m_uint)instr); return GW_OK; } -ANN static m_bool _unroll(const Emitter emit, struct Looper *loop) { +ANN static m_bool _unroll(const Emitter emit, Looper *loop) { scoped_ini(emit); const Instr unroll = emit_add_instr(emit, Unroll); unroll->m_val = loop->offset; @@ -2286,71 +2275,63 @@ ANN static m_bool _unroll(const Emitter emit, struct Looper *loop) { return GW_OK; } -ANN static m_bool unroll(const Emitter emit, struct Looper *loop) { +ANN static m_bool unroll(const Emitter emit, Looper *loop) { if(loop->unroll) vector_init(&loop->unroll_v); const m_bool ret = _unroll(emit, loop); if(loop->unroll) { for(m_uint i = 0; i < vector_size(&loop->unroll_v); i++) { const Instr instr = (Instr)vector_at(&loop->unroll_v, i); - instr->m_val = emit_code_size(emit) + 2; + instr->m_val = emit_code_size(emit) + 1; // + 2 for arrays } vector_release(&loop->unroll_v); } return ret; } -ANN static Instr stmt_each_unroll(const Emitter emit, - const struct Looper *loop) { - struct Op_Import opi = { - .lhs = loop->exp->type, - .op = insert_symbol("@autoloop"), - .data = (m_uint)loop - }; - CHECK_BO(op_emit(emit, &opi)); - return loop->instr; -// const Instr instr = emit_add_instr(emit, AutoLoop); -// instr->m_val2 = loop->offset + SZ_INT * 2; -// return instr; -} ANN static inline m_bool looper_run(const Emitter emit, - struct Looper *const loop) { + Looper *const loop) { return (!loop->n ? roll : unroll)(emit, loop); } ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt, m_uint *end_pc) { const uint n = emit->info->unroll; - if (n) { - unroll_init(emit, n); - emit_local(emit, emit->gwion->type[et_int]); - } - - CHECK_BB(emit_exp(emit, stmt->exp)); // add ref? - regpop(emit, SZ_INT); - const m_uint offset = emit_local(emit, emit->gwion->type[et_int]); // array? - emit_local(emit, emit->gwion->type[et_int]); - emit_local(emit, emit->gwion->type[et_int]); + const m_uint arr_offset = emit_local(emit, emit->gwion->type[et_int]); // array? + const m_uint key_offset = /*!stmt->idx + ? */emit_local(emit, emit->gwion->type[et_int]) + /*: emit_local(emit, stmt->idx->v->type)*/; + const m_uint val_offset = emit_local(emit, stmt->v->type); const Instr tomem = emit_add_instr(emit, Reg2Mem); - tomem->m_val = offset; + tomem->m_val = arr_offset; const Instr loop_idx = emit_add_instr(emit, MemSetImm); - loop_idx->m_val = offset + SZ_INT; + loop_idx->m_val = key_offset; loop_idx->m_val2 = -1; - stmt->v->from->offset = offset + SZ_INT * 2; + stmt->v->from->offset = val_offset; emit_debug(emit, stmt->v); - if (stmt->idx) stmt->idx->v->from->offset = offset + SZ_INT; - if (n) { - const Instr instr = emit_add_instr(emit, AutoUnrollInit); - instr->m_val = offset - SZ_INT; + if (stmt->idx) { + stmt->idx->v->from->offset = key_offset; + emit_debug(emit, stmt->v); } - const m_uint ini_pc = emit_code_size(emit); struct Looper loop = {.exp = stmt->exp, .stmt = stmt->body, - .offset = offset, + .offset = arr_offset, .n = n, - .roll = stmt_each_roll, - .unroll = stmt_each_unroll}; - if (n) loop.offset -= SZ_INT; + .roll = each_op, + .unroll = each_op, + .idx = stmt->idx, +.init = false + }; + if (n) { + loop.offset -= SZ_INT; + struct Op_Import opi = { + .lhs = loop.exp->type, + .op = insert_symbol("@each_init"), + .data = (m_uint)&loop + }; + CHECK_BB(op_emit(emit, &opi)); + } + const m_uint ini_pc = emit_code_size(emit); CHECK_BB(looper_run(emit, &loop)); *end_pc = emit_code_size(emit); const Instr tgt = emit_add_instr(emit, Goto); @@ -2359,21 +2340,32 @@ ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt, } ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) { + const uint n = emit->info->unroll; + + CHECK_BB(emit_exp(emit, stmt->exp)); // add ref? + regpop(emit, SZ_INT); + + if (n) { + unroll_init(emit, n); + emit_local(emit, emit->gwion->type[et_int]); + } + emit_push_stack(emit); m_uint end_pc = 0; const m_bool ret = _emit_stmt_each(emit, stmt, &end_pc); emit_pop_stack(emit, end_pc); + emit->info->unroll = 0; return ret; } -ANN static Instr stmt_loop_roll(const Emitter emit, const struct Looper *loop) { +ANN static Instr stmt_loop_roll(const Emitter emit, const Looper *loop) { const Instr eq = emit_add_instr(emit, Repeat); eq->m_val2 = loop->offset; return eq; } ANN static Instr stmt_loop_roll_idx(const Emitter emit, - const struct Looper *loop) { + const Looper *loop) { const Instr instr = emit_add_instr(emit, RepeatIdx); instr->m_val2 = loop->offset; return instr; @@ -2382,7 +2374,10 @@ ANN static Instr stmt_loop_roll_idx(const Emitter emit, ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt, m_uint *index) { const uint n = emit->info->unroll; - if (n) unroll_init(emit, n); + if (n) { + unroll_init(emit, n); + emit->info->unroll = 0; + } const m_uint offset = emit_local(emit, emit->gwion->type[et_int]); if (stmt->idx) { const Instr instr = emit_add_instr(emit, MemSetImm); @@ -2787,6 +2782,7 @@ ANN static VM_Code emit_func_def_code(const Emitter emit, const Func func) { } ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) { + if (fdef->base->xid == insert_symbol("@dtor")) emit_local(emit, emit->gwion->type[et_int]); if (fdef->base->args) emit_func_def_args(emit, fdef->base->args); if (fbflag(fdef->base, fbflag_variadic)) stack_alloc(emit); if (fdef->d.code) { diff --git a/src/env/value.c b/src/env/value.c index 616c92e1..5d144c9a 100644 --- a/src/env/value.c +++ b/src/env/value.c @@ -29,7 +29,7 @@ ANN Value new_value(MemPool p, const Type type, const m_str name) { ANN void valuefrom(const Env env, struct ValueFrom_ *from, const loc_t loc) { from->owner = env->curr; - from->owner_class = env->class_def; + from->owner_class = env->scope->depth ? NULL : env->class_def; from->ctx = env->context; from->filename = env->name; from->loc = loc; diff --git a/src/lib/array.c b/src/lib/array.c index fad912e1..3d73d2f5 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -13,7 +13,7 @@ #include "parse.h" #include "gwi.h" #include "emit.h" - +#include "looper.h" static DTOR(array_dtor) { if (*(void **)(o->data + SZ_INT)) xfree(*(void **)(o->data + SZ_INT)); struct M_Vector_ *a = ARRAY(o); @@ -124,6 +124,10 @@ static OP_CHECK(opck_array_at) { ERR_N(exp_self(bin)->pos, _("do not provide array for 'xxx => declaration'.")); } + bin->rhs->ref = bin->lhs; +// bin->rhs->data = bin->lhs; + if(bin->rhs->exp_type == ae_exp_decl) + SET_FLAG(bin->rhs->d.exp_decl.list->self->value, late); exp_setvar(bin->rhs, 1); return bin->rhs->type; } @@ -725,32 +729,43 @@ static OP_CHECK(opck_array_implicit) { return imp->t; } -struct Looper; -typedef Instr (*f_looper_init)(const Emitter, const struct Looper *); -typedef void (*f_looper)(const Emitter, const struct Looper *); -struct Looper { - const Exp exp; - const Stmt stmt; - /*const */ m_uint offset; - const m_uint n; - const f_looper_init roll; - const f_looper_init unroll; -// union { - struct Vector_ unroll_v; - Instr instr; -// }; -}; - -static OP_EMIT(opem_array_autoloop) { - struct Looper *loop = (struct Looper *)data; +static OP_EMIT(opem_array_each_init) { + Looper *loop = (Looper *)data; + const Instr instr = emit_add_instr(emit, AutoUnrollInit); + instr->m_val = loop->offset; + return GW_OK; +} + + +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; +} + +// rewrite me +static OP_CHECK(opck_array_each_val) { + const Exp exp = (const Exp) data; + DECL_ON(const Type, base, = foreach_type(env, exp)); + CHECK_BN(ensure_traverse(env, base)); + const m_str basename = type2str(env->gwion, base, exp->pos); + char c[15 + strlen(basename)]; + sprintf(c, "Ref:[%s]", basename); + return str2type(env->gwion, c, exp->pos); +} + +static OP_EMIT(opem_array_each) { + Looper *loop = (Looper *)data; const Instr instr = emit_add_instr(emit, AutoLoop); if(!loop->n) { instr->m_val2 = loop->offset + SZ_INT; + loop->instr = instr; } else { instr->m_val2 = loop->offset + SZ_INT*2; vector_add(&loop->unroll_v, (m_uint)instr); } - loop->instr = instr; return GW_OK; } @@ -877,9 +892,17 @@ GWION_IMPORT(array) { GWI_BB(gwi_oper_add(gwi, opck_array)) GWI_BB(gwi_oper_emi(gwi, opem_array_access)) GWI_BB(gwi_oper_end(gwi, "@array", NULL)) + GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "void")) + GWI_BB(gwi_oper_emi(gwi, opem_array_each_init)) + GWI_BB(gwi_oper_end(gwi, "@each_init", NULL)) + GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "int")) + GWI_BB(gwi_oper_emi(gwi, opem_array_each)) + GWI_BB(gwi_oper_end(gwi, "@each", NULL)) + GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, NULL)) + GWI_BB(gwi_oper_add(gwi, opck_array_each_val)) + GWI_BB(gwi_oper_end(gwi, "@each_val", NULL)) GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "int")) - GWI_BB(gwi_oper_emi(gwi, opem_array_autoloop)) - GWI_BB(gwi_oper_end(gwi, "@autoloop", NULL)) + GWI_BB(gwi_oper_end(gwi, "@each_idx", NULL)) GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, NULL)) GWI_BB(gwi_oper_add(gwi, opck_array_scan)) GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) @@ -980,7 +1003,7 @@ INSTR(ArrayAlloc) { if (!ref) { gw_err("{-}[{0}{+}Gwion{0}{-}](VM):{0} (note: in shred[id=%" UINT_F ":%s])\n", shred->tick->xid, shred->code->name); - if (info->is_obj) free(aai.data); + if (info->is_obj) xfree(aai.data); handle(shred, "ArrayAllocException"); return; // TODO make exception vararg } diff --git a/src/lib/dict.c b/src/lib/dict.c index 1a900fb8..c796da82 100644 --- a/src/lib/dict.c +++ b/src/lib/dict.c @@ -15,6 +15,7 @@ #include "gwi.h" #include "tmpl_info.h" #include "array.h" +#include "looper.h" #define HMAP_MIN_CAP 32 #define HMAP_MAX_LOAD 0.75 @@ -167,17 +168,17 @@ INSTR(dict_lit_ctor) { static CTOR(dict_ctor) { const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data; - HMap *a = &*(struct HMap*)o->data; - a->key_size = hinfo->key->size; - a->val_size = hinfo->val->size; - a->data = (m_bit*)mp_calloc2(shred->info->mp, hinfo->sz * HMAP_MIN_CAP); - a->state = (m_bit*)mp_calloc2(shred->info->mp, sizeof(HState) * HMAP_MIN_CAP); - a->capacity = HMAP_MIN_CAP; - a->count = 0; + HMap *const a = &*(struct HMap*)o->data; + a->key_size = hinfo->key->size; + a->val_size = hinfo->val->size; + a->data = (m_bit*)mp_calloc2(shred->info->mp, hinfo->sz * HMAP_MIN_CAP); + a->state = (m_bit*)mp_calloc2(shred->info->mp, sizeof(HState) * HMAP_MIN_CAP); + a->capacity = HMAP_MIN_CAP; + a->count = 0; } static DTOR(dict_dtor) { - HMap *a = &*(struct HMap*)o->data; + HMap *const a = &*(struct HMap*)o->data; const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data; mp_free2(shred->info->mp, hinfo->sz * a->capacity, a->data); mp_free2(shred->info->mp, sizeof(HState) * a->capacity, a->state); @@ -295,7 +296,7 @@ static INSTR(hmap_grow_dec) { *(m_uint*)(shred->reg -SZ_INT) = 1; } -static INSTR(hmap_wtf) { +static INSTR(hmap_find) { const M_Object o = *(M_Object*)(shred->reg - SZ_INT*6); HMap *const hmap = (HMap*)o->data; const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data; @@ -435,7 +436,7 @@ if(info->is_var) { const Instr endgrow = emit_add_instr(emit, BranchNeqInt); emit_exp(emit, call.d.exp_call.func); emit_exp_call1(emit, call.d.exp_call.func->type->info->func, true); - emit_add_instr(emit, hmap_wtf); + emit_add_instr(emit, hmap_find); const Instr regrow = emit_add_instr(emit, BranchEqInt); regrow->m_val = grow_pc; nogrow->m_val = emit_code_size(emit); @@ -572,6 +573,71 @@ static OP_CHECK(opck_dict_access) { return check_array_access(env, &next) ?: env->gwion->type[et_error]; } +static INSTR(DictEach) { + const M_Object o = *(M_Object *)(shred->mem + instr->m_val2); + HMapInfo *const hinfo = (HMapInfo*)o->type_ref->nspc->class_data; + const HMap *hmap = (HMap*)o->data; + m_uint bucket = ++*(m_uint *)(shred->mem + instr->m_val2 + SZ_INT); + while(bucket < hmap->capacity) { + const HState *state = (HState *)(hmap->state + bucket * sizeof(HState)); + if (state->set && !state->deleted) + break; + bucket++; + } + *(m_uint *)(shred->mem + instr->m_val2 + SZ_INT) = bucket; + memcpy(shred->mem + instr->m_val2 + SZ_INT*2, hmap->data + (bucket * hinfo->sz) + hinfo->key->size, hinfo->val->size); + *(m_uint*)shred->reg = (bucket == hmap->capacity); + PUSH_REG(shred, SZ_INT); +} + +static INSTR(DictEachIdx) { + const M_Object o = *(M_Object *)(shred->mem + instr->m_val2); + HMapInfo *const hinfo = (HMapInfo*)o->type_ref->nspc->class_data; + const HMap *hmap = (HMap*)o->data; + DictEach(shred, instr); + const m_int bucket = *(m_uint *)(shred->mem + instr->m_val2 + SZ_INT); + memcpy(shred->mem + instr->m_val, hmap->data + (bucket * hinfo->sz), hinfo->key->size); +} + +static OP_EMIT(opem_dict_each) { + Looper *loop = (Looper *)data; + HMapInfo *const hinfo = (HMapInfo*)loop->exp->type->nspc->class_data; + if(loop->idx && !loop->init) loop->idx->v->from->offset = emit_localn(emit, hinfo->key); + const Instr instr = emit_add_instr(emit, !loop->idx ? DictEach : DictEachIdx); + instr->m_val2 = loop->offset; + if(loop->idx) instr->m_val = loop->idx->v->from->offset; + if(loop->n)instr->m_val2 += SZ_INT; + const Instr go = emit_add_instr(emit, BranchNeqInt); + if(!loop->n) loop->instr = go; + else vector_add(&loop->unroll_v, (m_uint)go); + loop->init = true; + return GW_OK; +} + +static INSTR(DictEachInit) { + const M_Object o = *(M_Object *)(shred->mem + instr->m_val + SZ_INT); + *(m_uint *)(shred->mem + instr->m_val) = ((HMap*)o->data)->capacity; +} + +static OP_EMIT(opem_dict_each_init) { + const Looper *loop = (Looper *)data; + const Instr instr = emit_add_instr(emit, DictEachInit); + instr->m_val = loop->offset; + return GW_OK; +} + +static OP_CHECK(opck_dict_each_key) { + const Exp exp = (const Exp)data; + HMapInfo *const hinfo = (HMapInfo*)exp->type->nspc->class_data; + return hinfo->key; +} + +static OP_CHECK(opck_dict_each_val) { + const Exp exp = (const Exp)data; + HMapInfo *const hinfo = (HMapInfo*)exp->type->nspc->class_data; + return hinfo->val; +} + static OP_CHECK(opck_dict_scan) { struct TemplateScan *ts = (struct TemplateScan *)data; struct tmpl_info info = { @@ -621,7 +687,6 @@ static OP_CHECK(opck_dict_scan) { } return ret > 0 ? t : NULL; -// return t; } GWION_IMPORT(dict) { @@ -646,6 +711,22 @@ GWION_IMPORT(dict) { GWI_BB(gwi_oper_add(gwi, opck_dict_scan)) GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) + GWI_BB(gwi_oper_ini(gwi, "Dict", NULL, "int")) + GWI_BB(gwi_oper_emi(gwi, opem_dict_each)) + GWI_BB(gwi_oper_end(gwi, "@each", NULL)) + + GWI_BB(gwi_oper_ini(gwi, "Dict", NULL, "void")) + GWI_BB(gwi_oper_emi(gwi, opem_dict_each_init)) + GWI_BB(gwi_oper_end(gwi, "@each_init", NULL)) + + GWI_BB(gwi_oper_ini(gwi, "Dict", NULL, NULL)) + GWI_BB(gwi_oper_add(gwi, opck_dict_each_val)) + GWI_BB(gwi_oper_end(gwi, "@each_val", NULL)) + + GWI_BB(gwi_oper_ini(gwi, "Dict", NULL, NULL)) + GWI_BB(gwi_oper_add(gwi, opck_dict_each_key)) + GWI_BB(gwi_oper_end(gwi, "@each_idx", NULL)) + GWI_BB(gwi_func_ini(gwi, "int", "hash")); GWI_BB(gwi_func_arg(gwi, "int", "key")); GWI_BB(gwi_func_end(gwi, mfun_int_h, ae_flag_none)); diff --git a/src/lib/instr.c b/src/lib/instr.c index a6697344..7d32b2dd 100644 --- a/src/lib/instr.c +++ b/src/lib/instr.c @@ -13,7 +13,7 @@ #include "import.h" #include "emit.h" #include "template.h" - +/* INSTR(DTOR_EOC) { const M_Object o = *(M_Object *)MEM(0); o->type_ref = o->type_ref->info->parent; @@ -21,7 +21,7 @@ INSTR(DTOR_EOC) { shred->info->me->ref = 1; vm_shred_exit(shred); } - +*/ ANN static Func_Def from_base(const Env env, struct dottmpl_ *const dt, const Nspc nspc) { const Func_Def fdef = dt->def ?: dt->base; diff --git a/src/lib/object.c b/src/lib/object.c index ab73235d..01184047 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -25,8 +25,6 @@ M_Object new_object(MemPool p, const Type t) { const M_Object a = _mp_calloc(p, offset); a->ref = 1; a->type_ref = t; - a->offset = t->nspc->offset; - a->vtable.ptr = t->nspc->vtable.ptr; return a; } @@ -37,11 +35,11 @@ M_Object new_string(const struct Gwion_ *gwion, const m_str str) { } ANN static void user_dtor(const M_Object o, const VM_Shred shred, const Type t) { - o->type_ref = t; - const VM_Shred sh = new_vm_shred(shred->info->mp, o->type_ref->nspc->dtor); - vmcode_addref(o->type_ref->nspc->dtor); + const VM_Shred sh = new_vm_shred(shred->info->mp, t->nspc->dtor); + vmcode_addref(t->nspc->dtor); sh->base = shred->base; *(M_Object *)sh->mem = o; + *(Type *)(sh->mem + SZ_INT) = t; vm_add_shred(shred->info->vm, sh); ++sh->info->me->ref; } @@ -80,13 +78,21 @@ ANN static void do_release(const M_Object o, return do_release(o, shred, t->info->parent); } + +INSTR(DTOR_EOC) { + const M_Object o = *(M_Object *)MEM(0); + const Type t = *(Type *)MEM(SZ_INT); + do_release(o, shred, t->info->parent); + shred->info->me->ref = 1; + vm_shred_exit(shred); +} + ANN void __release(const M_Object o, const VM_Shred shred) { -// vector_rem2(&shred->gc, (vtype)o); do_release(o, shred, o->type_ref); } ANN void free_object(MemPool p, const M_Object o) { - mp_free2(p, o->offset, o); + mp_free2(p, o->type_ref->nspc->offset, o); } static ID_CHECK(opck_this) { diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 13997249..3765540d 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -35,6 +35,7 @@ static OP_CHECK(opck_object_at) { exp_setvar(bin->rhs, 1); CHECK_BO(isa(bin->lhs->type, bin->rhs->type)); bin->lhs->ref = bin->rhs; +// bin->lhs->acquire = true; // bin->rhs-> = bin->lhs; return bin->rhs->type; } @@ -51,7 +52,6 @@ static bool exp_func(const Exp exp) { ANN void unset_local(const Emitter emit, void *const l); static OP_EMIT(opem_object_at) { const Exp_Binary *bin = (Exp_Binary *)data; - if(!bin->rhs->data) { const Instr addref = emit_add_instr(emit, RegAddRef); addref->m_val = -SZ_INT * 2; diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index e05348a9..1bcb49f5 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -150,7 +150,7 @@ OP_EMIT(opem_new) { const Exp_Unary *unary = (Exp_Unary *)data; CHECK_BB(emit_instantiate_object(emit, exp_self(unary)->type, unary->ctor.td->array, 0)); - if(!unary->ctor.exp) - emit_localx(emit, exp_self(unary)->type); +// if(!unary->ctor.exp) +// emit_local_exp(emit, exp_self(unary)->type); return GW_OK; } diff --git a/src/parse/check.c b/src/parse/check.c index 0fb7affb..8c09181d 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -112,6 +112,11 @@ 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; do { @@ -119,9 +124,8 @@ ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) { CHECK_BB(check_var(env, var)); CHECK_BB(check_var_td(env, var, decl->td)); if (is_fptr(env->gwion, decl->type)) CHECK_BB(check_fptr_decl(env, var)); - set_vflag(var->value, vflag_valid); + valid_value(env, var->xid, var->value); // set_vflag(var->value, vflag_used)); - nspc_add_value(env->curr, var->xid, var->value); } while ((list = list->next)); return GW_OK; } @@ -583,8 +587,7 @@ ANN static m_bool check_func_args(const Env env, Arg_List arg_list) { const Var_Decl decl = arg_list->var_decl; const Value v = decl->value; CHECK_BB(already_defined(env, decl->xid, decl->pos)); - set_vflag(v, vflag_valid); - nspc_add_value(env->curr, decl->xid, v); + valid_value(env, decl->xid, v); } while ((arg_list = arg_list->next)); return GW_OK; } @@ -1161,7 +1164,7 @@ ANN static inline m_bool for_empty(const Env env, const Stmt_For stmt) { } ANN static inline Type foreach_type(const Env env, const Exp exp) { - DECL_OO(Type, et, = check_exp(env, exp)); + const Type et = exp->type; if (isa(et, env->gwion->type[et_array]) < 0) ERR_O(exp->pos, _("type '%s' is not array.\n" @@ -1173,36 +1176,53 @@ ANN static inline Type foreach_type(const Env env, const Exp exp) { return depth ? array_type(env, t, depth) : t; } -ANN static void check_idx(const Env env, struct EachIdx_ *const idx) { - idx->v = - new_value(env->gwion->mp, env->gwion->type[et_int], s_name(idx->sym)); +ANN static void check_idx(const Env env, const Type base, struct EachIdx_ *const idx) { + idx->v = new_value(env->gwion->mp, base, s_name(idx->sym)); valuefrom(env, idx->v->from, idx->pos); - idx->v->from->owner_class = NULL; - set_vflag(idx->v, vflag_valid); - nspc_add_value(env->curr, idx->sym, idx->v); + valid_value(env, idx->sym, idx->v); +} + +/** sets for the key expression value + with eg type *int* for an array or the *Key* type of a Dict **/ +ANN static m_bool check_each_idx(const Env env, const Exp exp, struct EachIdx_ *const idx) { + struct Op_Import opi = { + .lhs = exp->type, + .op = insert_symbol("@each_idx"), + .data = exp, + .pos = idx->pos + }; + DECL_OB(const Type, t, = op_check(env, &opi)); + check_idx(env, t, idx); + return GW_OK; +} + +/** return the base type for the foreach expression + eg the base type of an array or the *Val* type of a Dict **/ +ANN static Type check_each_val(const Env env, const Exp exp) { + struct Op_Import opi = { + .lhs = exp->type, + .op = insert_symbol("@each_val"), + .data = (m_uint)exp + }; + return op_check(env, &opi); } ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) { - DECL_OB(const Type, base, = foreach_type(env, stmt->exp)); - CHECK_BB(ensure_traverse(env, base)); - const m_str basename = type2str(env->gwion, base, stmt->exp->pos); - char c[15 + strlen(basename)]; - sprintf(c, "Ref:[%s]", basename); - const Type ret = str2type(env->gwion, c, stmt->exp->pos); - if (base->array_depth) set_tflag(ret, tflag_typedef); + CHECK_OB(check_exp(env, stmt->exp)); + if (stmt->idx) + CHECK_BB(check_each_idx(env, stmt->exp, stmt->idx)); + DECL_OB(const Type, ret, = check_each_val(env, stmt->exp)); 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); - if (stmt->idx) check_idx(env, stmt->idx); + valid_value(env, stmt->sym, stmt->v); return check_conts(env, stmt_self(stmt), stmt->body); } ANN static m_bool do_stmt_repeat(const Env env, const Stmt_Loop stmt) { - if (stmt->idx) check_idx(env, stmt->idx); + if (stmt->idx) check_idx(env, env->gwion->type[et_int], stmt->idx); return check_conts(env, stmt_self(stmt), stmt->body); } -ANN static inline m_bool cond_type(const Env env, const Exp e) { +ANN static inline m_bool repeat_type(const Env env, const Exp e) { const Type t_int = env->gwion->type[et_int]; if (check_implicit(env, e, t_int) < 0) { char explain[40 + strlen(e->type->name)]; @@ -1234,7 +1254,7 @@ stmt_func_xxx(for, Stmt_For, env_inline_mult(env, 1.5), !( (stmt->c3 && !check_exp(env, stmt->c3)) || check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1) stmt_func_xxx(loop, Stmt_Loop, env_inline_mult(env, 1.5); check_idx(env, stmt->idx), !(!check_exp(env, stmt->cond) || - cond_type(env, stmt->cond) < 0 || + repeat_type(env, stmt->cond) < 0 || do_stmt_repeat(env, stmt) < 0) ? 1 : -1) stmt_func_xxx(each, Stmt_Each, env_inline_mult(env, 1.5), do_stmt_each(env, stmt)) @@ -1301,8 +1321,7 @@ ANN static Value match_value(const Env env, const Type base, const Exp_Primary *prim) { const Symbol sym = prim->d.var; const Value v = new_value(env->gwion->mp, base, s_name(sym)); - set_vflag(v, vflag_valid); - nspc_add_value(env->curr, sym, v); + valid_value(env, sym, v); return v; } @@ -1914,13 +1933,13 @@ ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) { ANN m_bool check_class_def(const Env env, const Class_Def cdef) { if (tmpl_base(cdef->base.tmpl)) return GW_OK; const Type t = cdef->base.type; + if (tflag(t, tflag_check)) return GW_OK; const Class_Def c = t->info->cdef; struct Op_Import opi = {.op = insert_symbol("@class_check"), .lhs = t, .data = (uintptr_t)c, .pos = c->pos}; CHECK_OB(op_check(env, &opi)); - if (tflag(t, tflag_check)) return GW_OK; set_tflag(t, tflag_check); return _check_class_def(env, c); } diff --git a/src/vm/vm.c b/src/vm/vm.c index f9338f4a..2ada2d4c 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -1032,7 +1032,7 @@ vm_run(const VM *vm) { // lgtm [cpp/use-of-goto] DISPATCH() autounrollinit: *(m_uint *)(mem + VAL) = - m_vector_size(ARRAY(*(M_Object *)(mem + VAL + SZ_INT))); + m_vector_size(ARRAY(*(M_Object *)(mem + VAL + SZ_INT))) + 1; DISPATCH() autoloop: { const M_Vector array = ARRAY(*(M_Object *)(mem + VAL2 - SZ_INT)); @@ -1217,7 +1217,7 @@ vm_run(const VM *vm) { // lgtm [cpp/use-of-goto] DISPATCH() dotfunc: *(VM_Code *)(reg + (m_uint)VAL2) = - ((Func)(*(M_Object *)(reg - SZ_INT))->vtable.ptr[OFFSET + VAL])->code; + ((Func)(*(M_Object *)(reg - SZ_INT))->type_ref->nspc->vtable.ptr[OFFSET + VAL])->code; DISPATCH() gacktype : { const M_Object o = *(M_Object *)(reg - SZ_INT); diff --git a/tests/error/auto_not_array.gw b/tests/error/auto_not_array.gw deleted file mode 100644 index 9ee67a4d..00000000 --- a/tests/error/auto_not_array.gw +++ /dev/null @@ -1,4 +0,0 @@ -#! [contains] not allowed in foreach loop -var Object i; -foreach(a: i) - <<< a >>>; diff --git a/util b/util index 7643ceba..7b668adb 160000 --- a/util +++ b/util @@ -1 +1 @@ -Subproject commit 7643ceba751766ae5cd42da19667e1377a2b89d0 +Subproject commit 7b668adba0cd3d9e6af45e9c30456b5a6f171d74 -- 2.43.0