From: Jérémie Astor Date: Fri, 13 May 2022 16:01:19 +0000 (+0200) Subject: :art: merge dev X-Git-Tag: nightly~273 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=7eede48db3dbe852d09b476ac7a0e07f2b9bd771;p=gwion.git :art: merge dev --- diff --git a/Makefile b/Makefile index 9fa8b986..cc45a093 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,10 @@ clean: clean_core install: all translation-install $(info installing ${GWION_PACKAGE} in ${PREFIX}) - @mkdir -p ${DESTDIR}/${PREFIX}/{bin,lib,include,share} + @mkdir -p ${DESTDIR}/${PREFIX}/bin + @mkdir -p ${DESTDIR}/${PREFIX}/lib + @mkdir -p ${DESTDIR}/${PREFIX}/include + @mkdir -p ${DESTDIR}/${PREFIX}/share @install ${PRG} ${DESTDIR}/${PREFIX}/bin @install lib${PRG}.a ${DESTDIR}/${PREFIX}/lib @PREFIX=${PREFIX} sed 's#PREFIX#${PREFIX}#g' scripts/gwion-config > gwion-config diff --git a/ast b/ast index e09543b3..ff31aff0 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit e09543b39ec51dc344d74dd2c1adb415957c6b5a +Subproject commit ff31aff0f531c0bcf4a8ed9e04bedd0a1eefe9ba diff --git a/include/gack.h b/include/gack.h index d926119b..3515a42f 100644 --- a/include/gack.h +++ b/include/gack.h @@ -10,4 +10,5 @@ ANN void gack(const VM_Shred, const m_uint); } ANN2(2) int gw_asprintf(MemPool mp, char **str, const char *fmt, ...); +ANN m_bool mk_gack(MemPool p, const Type type, const f_gack d); #endif diff --git a/include/vm.h b/include/vm.h index 0ce89d89..deca0f85 100644 --- a/include/vm.h +++ b/include/vm.h @@ -110,6 +110,7 @@ __attribute__((hot)) ANN static inline void vm_shred_exit(const VM_Shred shred) { shreduler_remove(shred->tick->shreduler, shred, true); } +ANN void vm_clean(const VM* vm, const Gwion gwion); void free_vm_shred(const VM_Shred shred) __attribute__((hot, nonnull)); void vm_prepare(const VM *vm, m_bit*) __attribute__((hot)); diff --git a/plug b/plug index 879e1bf7..5a583451 160000 --- a/plug +++ b/plug @@ -1 +1 @@ -Subproject commit 879e1bf7691c0bacdb50ec10fcbac4978c788a9d +Subproject commit 5a583451cd50f26867cf18c9bd309e3cc0f523d2 diff --git a/src/emit/emit.c b/src/emit/emit.c index 2fa8c504..312497ef 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -650,7 +650,7 @@ ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) { regseti(emit, count); const Instr instr = emit_add_instr(emit, ArrayInit); instr->m_val = (m_uint)type; - instr->m_val2 = array_base_simple(type)->size; + instr->m_val2 = type->array_depth == 1 ? array_base_simple(type)->size : SZ_INT; emit_local_exp(emit, prim_exp(data)); emit_notpure(emit); return GW_OK; @@ -931,8 +931,12 @@ ANN static m_bool emit_prim_locale(const Emitter emit, const Symbol *id) { shred->info->me->ref++; vm_run(emit->gwion->vm); emit->gwion->vm->bbq->is_running = true; + const m_float ret = *(m_float*)shred->reg; + if(ret == -1.0) { + ERR_B(prim_pos(id), "error in locale"); + } const Instr instr = emit_add_instr(emit, RegPushImm2); - instr->f = *(m_float*)shred->reg; + instr->f = ret; return GW_OK; } @@ -1277,13 +1281,13 @@ ANN static inline void inline_args_ini(const Emitter emit, const Func f, if(member) emit->this_offset = emit_local(emit, emit->gwion->type[et_int]); const m_uint start_offset = emit_code_offset(emit) - (member ? SZ_INT : 0); - Arg_List arg = f->def->base->args; - while (arg) { - const Value value = arg->var_decl->value; + Arg_List args = f->def->base->args; + for(uint32_t i = 0; i < args->len; i++) { + const Arg *arg = mp_vector_at(args, Arg, i); + const Value value = arg->var_decl.value; vector_add(v, value->from->offset); value->from->offset = emit_local(emit, value->type); - nspc_add_value(emit->env->curr, arg->var_decl->xid, value); - arg = arg->next; + nspc_add_value(emit->env->curr, arg->var_decl.xid, value); } if (fbflag(f->def->base, fbflag_variadic)) emit->vararg_offset = emit_local(emit, emit->gwion->type[et_int]) + SZ_INT; @@ -1294,12 +1298,11 @@ ANN static inline void inline_args_ini(const Emitter emit, const Func f, } ANN static inline void inline_args_end(const Func f, const Vector v) { - Arg_List arg = f->def->base->args; - m_uint i = 0; - while (arg) { - const Value value = arg->var_decl->value; + Arg_List args = f->def->base->args; + for(uint32_t i = 0; i < args->len; i++) { + const Arg *arg = mp_vector_at(args, Arg, i); + const Value value = arg->var_decl.value; value->from->offset = vector_at(v, i++); - arg = arg->next; } } @@ -1346,9 +1349,9 @@ ANN static inline m_bool emit_inline(const Emitter emit, const Func f, return ret; } #endif + ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *exp_call) { -/* - #ifndef GWION_NOINLINE + #ifdef GWION_INLINE const Func _f = is_inlinable(emit, exp_call); if(_f) { const Func base = emit->env->func; @@ -1360,7 +1363,7 @@ ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *exp_call) { return ret; } #endif -*/ + // skip when recursing const Type t = actual_type(emit->gwion, exp_call->func->type); const Func f = t->info->func; diff --git a/src/gwion.c b/src/gwion.c index 7de93762..3342f657 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -157,22 +157,14 @@ ANN void gwion_end_child(const VM_Shred shred, const Gwion gwion) { if (gwion->data->child2.ptr) fork_clean2(shred, &gwion->data->child2); } -ANN static inline void free_killed_shred(const Vector v) { - for (m_uint i = 0; i < vector_size(v); i++) { - const VM_Shred shred = (VM_Shred)vector_at(v, i); - free_vm_shred(shred); - } -} - ANN void gwion_end(const Gwion gwion) { - free_killed_shred(&gwion->vm->shreduler->killed_shreds); - gwion_end_child(gwion->vm->cleaner_shred, gwion); + VM *vm = gwion->vm; + vm_clean(vm, gwion); release_ctx(gwion->env->scope, gwion); if (gwion->data->plugs) free_plug(gwion); free_env(gwion->env); - if (gwion->vm->cleaner_shred) free_vm_shred(gwion->vm->cleaner_shred); free_emitter(gwion->mp, gwion->emit); - free_vm(gwion->vm); + free_vm(vm); pparg_end(gwion->ppa); mp_free(gwion->mp, PPArg, gwion->ppa); free_gwiondata(gwion); diff --git a/src/import/import_special.c b/src/import/import_special.c index bcef3eb1..971a29ee 100644 --- a/src/import/import_special.c +++ b/src/import/import_special.c @@ -44,7 +44,7 @@ ANN void gwi_set_loc(const Gwi gwi, const m_str file, const uint line) { gwi->gwion->env->name = file; } -ANN static m_bool mk_gack(MemPool p, const Type type, const f_gack d) { +ANN m_bool mk_gack(MemPool p, const Type type, const f_gack d) { const VM_Code code = new_vmcode(p, NULL, NULL, "@gack", SZ_INT, true, false); code->native_func = (m_uint)d; type->info->gack = code; diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index 344ffbd8..c6992f6d 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -14,15 +14,60 @@ #include "parse.h" #include "partial.h" -static OP_CHECK(opck_func_call) { - Exp_Binary *bin = (Exp_Binary *)data; - Exp_Call call = {.func = bin->rhs, .args = bin->lhs}; - Exp e = exp_self(bin); +ANN static Exp uncurry(const Env env, const Exp_Binary *bin) { + const Stmt stmt = mp_vector_at(bin->rhs->type->info->func->def->d.code->d.stmt_code.stmt_list, struct Stmt_, 0); + const Exp ecall = stmt->d.stmt_exp.val; + const Exp_Call *call = &ecall->d.exp_call; + Exp args = call->args; + Exp lhs = bin->lhs; + Exp base = NULL, tmp = NULL; + while(args) { + if(args->exp_type != ae_exp_primary || args->d.prim.prim_type != ae_prim_id || *s_name(args->d.prim.d.var) != '@') { + // we should check better => use longer name + const Exp next = args->next; + args->next = NULL; + if(tmp) tmp = (tmp->next = cpy_exp(env->gwion->mp, args)); + else base = (tmp = cpy_exp(env->gwion->mp, args)); + args->next = next; + } else { + if(!lhs) { + free_exp(env->gwion->mp, base); + return NULL; + } + const Exp next = lhs->next; + lhs->next = NULL; + if(tmp) tmp = (tmp->next = cpy_exp(env->gwion->mp, lhs)); + else base = (tmp = cpy_exp(env->gwion->mp, lhs)); + lhs = lhs->next = next; + } + args = args->next; + } + if(traverse_exp(env, base) > 0) { + free_exp(env->gwion->mp, bin->lhs); + return base; + } + free_exp(env->gwion->mp, base); + return NULL; +} + +ANN static Type mk_call(const Env env, const Exp e, const Exp func, const Exp args) { + Exp_Call call = {.func = func, .args = args }; e->exp_type = ae_exp_call; memcpy(&e->d.exp_call, &call, sizeof(Exp_Call)); return check_exp_call1(env, &e->d.exp_call) ?: env->gwion->type[et_error]; } +static OP_CHECK(opck_func_call) { + Exp_Binary *bin = (Exp_Binary *)data; + if(!strncmp(bin->rhs->type->name, "partial:", 8)) { + const Stmt stmt = mp_vector_at(bin->rhs->type->info->func->def->d.code->d.stmt_code.stmt_list, struct Stmt_, 0); + const Exp_Call *call = &stmt->d.stmt_exp.val->d.exp_call; + const Exp args = uncurry(env, bin); + if(args) return mk_call(env, exp_self(bin), call->func, args); + } + return mk_call(env, exp_self(bin), bin->rhs, bin->lhs); +} + ANN static inline Exp cpy_nonext(const Env env, const Exp e) { const MemPool mp = env->gwion->mp; const Exp next = e->next; @@ -688,7 +733,7 @@ static OP_CHECK(opck_spork) { struct Value_ value = { .type = env->gwion->type[et_lambda]}; if(env->class_def) set_vflag(&value, vflag_member); - struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = &upvalues}; + struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = &upvalues, .pos = exp_self(unary)->pos}; set_fbflag(&fbase, fbflag_lambda); struct Func_Def_ fdef = { .base = &fbase}; struct Func_ func = { .name = "in spork", .def = &fdef, .value_ref = &value}; diff --git a/src/lib/locale.c b/src/lib/locale.c index 697caad1..6b7afcdc 100644 --- a/src/lib/locale.c +++ b/src/lib/locale.c @@ -21,9 +21,12 @@ static int basic_note(const char c) { } ANN static m_float basic_locale(m_str str) { - const char base = basic_note(str[0]); + int base = basic_note(str[0]); if(base == -1) return -1; str++; + const char mod = *str; + if(mod == '#') { base++; str++; } + else if(mod == 'b') { base--; str++; } char *remainder; const long octave = strtol(str, &remainder, 10); if(*remainder != '\0') return -1; diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 12ff7c61..984bf45b 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -87,8 +87,7 @@ ANN static void emit_dot_static_data(const Emitter emit, const Value v, ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, const bool emit_addr) { - // if(v->d.ptr && vflag(v, vflag_builtin) && GET_FLAG(v, const)) { - if (vflag(v, vflag_builtin) && GET_FLAG(v, const)) { + if (vflag(v, vflag_builtin) /*&& GET_FLAG(v, const)*/) { const m_uint size = v->type->size; const Instr instr = emit_regpushimm(emit, size, emit_addr); instr->m_val = (m_uint)v->d.ptr; diff --git a/src/lib/prim.c b/src/lib/prim.c index fcaab1fa..a6dc951a 100644 --- a/src/lib/prim.c +++ b/src/lib/prim.c @@ -84,8 +84,8 @@ static inline uint pot(const m_int x) { return (x > 0) && ((x & (x - 1)) == 0); BINARY_INT_FOLD(add, et_int, +,) BINARY_INT_FOLD(sub, et_int, -,) -BINARY_INT_FOLD(mul, et_int, *, POWEROF2_OPT(name, <<)) -BINARY_INT_FOLD_Z(div, et_int, /, POWEROF2_OPT(name, >>)) +BINARY_INT_FOLD(mul, et_int, *, /*POWEROF2_OPT(name, <<)*/) +BINARY_INT_FOLD_Z(div, et_int, /,/* POWEROF2_OPT(name, >>)*/) BINARY_INT_FOLD_Z(mod, et_int, %,) BINARY_INT_FOLD(sl, et_int, <<,) BINARY_INT_FOLD(sr, et_int, >>,) diff --git a/src/lib/ref.c b/src/lib/ref.c index 504e0644..8d9e620a 100644 --- a/src/lib/ref.c +++ b/src/lib/ref.c @@ -18,8 +18,9 @@ #include "tmpl_info.h" ANN Type ref_type(const Gwion gwion, const Type t, const loc_t loc) { - char c[7 + strlen(t->name)]; - sprintf(c, "Ref:[%s]", t->name); + const m_str name = type2str(gwion, t, loc); + char c[7 + strlen(name)]; + sprintf(c, "Ref:[%s]", name); return str2type(gwion, c, loc); } diff --git a/src/lib/string.c b/src/lib/string.c index 8fc945b7..581d7bc5 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -248,7 +248,7 @@ static MFUN(string_find) { static MFUN(string_findStart) { const m_str base = STRING(o); const size_t sz = strlen(base); - const char pos = *(m_int *)MEM(SZ_INT * 2); + const int pos = *(m_int *)MEM(SZ_INT * 2); if (pos >= 0 && (size_t)pos < sz) { const char arg = *(m_int *)MEM(SZ_INT); char * str = strchr(base + pos, arg); @@ -272,7 +272,7 @@ static MFUN(string_findStr) { static MFUN(string_findStrStart) { const m_str base = STRING(o); const size_t sz = strlen(base); - const char pos = *(m_int *)MEM(SZ_INT * 2); + const int pos = *(m_int *)MEM(SZ_INT * 2); const M_Object obj = *(M_Object *)MEM(SZ_INT); if (pos >= 0 && (size_t)pos < sz) { const m_str arg = STRING(obj); @@ -292,7 +292,7 @@ static MFUN(string_rfind) { static MFUN(string_rfindStart) { const m_str base = STRING(o); const size_t sz = strlen(base); - const char pos = *(m_int *)MEM(SZ_INT); + const int pos = *(m_int *)MEM(SZ_INT); if (pos >= 0 && (size_t)pos < sz) { const char arg = *(m_int *)MEM(SZ_INT * 2); char * str = strrchr(base + pos, arg); diff --git a/src/parse/check.c b/src/parse/check.c index 8c592cd2..978ba4c6 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -418,7 +418,6 @@ ANN static Type check_prim_hack(const Env env, const Exp *data) { CHECK_OO(check_prim_interp(env, data)); env_weight(env, 1); return env->gwion->type[et_gack]; -// return (*data)->type; } ANN static Type check_prim_locale(const Env env, const Symbol *data NUSED) { @@ -813,10 +812,12 @@ ANN m_bool func_check(const Env env, Exp_Call *const exp) { ERR_B(exp->func->pos, _("Can't call late function pointer at declaration " "site. did you meant to use `@=>`?")) const Type t = actual_type(env->gwion, exp->func->type); - if (is_func(env->gwion, t) && exp->func->exp_type == ae_exp_dot && - !t->info->value->from->owner_class) { - if (exp->args) CHECK_OB(check_exp(env, exp->args)); - return call2ufcs(env, exp, t->info->func->value_ref) ? GW_OK : GW_ERROR; + if(!is_fptr(env->gwion, t)) { + if (is_func(env->gwion, t) && exp->func->exp_type == ae_exp_dot && + !t->info->value->from->owner_class) { + if (exp->args) CHECK_OB(check_exp(env, exp->args)); + return call2ufcs(env, exp, t->info->func->value_ref) ? GW_OK : GW_ERROR; + } } const Exp e = exp_self(exp); struct Op_Import opi = {.op = insert_symbol("@func_check"), @@ -850,8 +851,10 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) { const Type t = op_check(env, &opi); return t; } - if (_class) // need an instance + if (_class) { + // need an instance ERR_O(exp->func->pos, "can't call a function pointer type"); + } if (t == env->gwion->type[et_op]) return check_op_call(env, exp); if (t == env->gwion->type[et_lambda]) // TODO: effects? return check_lambda_call(env, exp); @@ -1242,7 +1245,8 @@ 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 + .data = (m_uint)exp, + .pos = exp->pos }; return op_check(env, &opi); } diff --git a/src/parse/operator.c b/src/parse/operator.c index fdf03fcf..5179dd44 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -299,6 +299,26 @@ ANN void* op_get(const Env env, struct Op_Import *opi) { return NULL; } +ANN static Type chuck_rewrite(const Env env, const struct Op_Import *opi, const m_str op, const size_t len) { + Exp_Binary *base = (Exp_Binary*)opi->data; + const Exp lhs = cpy_exp(env->gwion->mp, base->lhs); // no need to copy + const Exp call = new_exp_call(env->gwion->mp, cpy_exp(env->gwion->mp, base->rhs), NULL, lhs->pos); + char c[len - 1]; + strncpy(c, op, len - 2); + c[len - 2] = '\0'; + const Exp bin = new_exp_binary(env->gwion->mp, lhs, insert_symbol(env->gwion->st, c), call, exp_self(base)->pos); + base->lhs = bin; + const Symbol orig = base->op; + base->op = insert_symbol(env->gwion->st, "=>"); + const Type ret = check_exp(env, exp_self(base)); + if(ret) return ret; + env->context->error = false; + base->op = orig; + env_warn(env, opi->pos, _("during rewriting operation")); + env->context->error = true; + return NULL; +} + ANN Type op_check(const Env env, struct Op_Import *opi) { for (int i = 0; i < 2; ++i) { Nspc nspc = env->curr; @@ -326,16 +346,21 @@ ANN Type op_check(const Env env, struct Op_Import *opi) { } const Type try_tmpl = op_check_tmpl(env, opi); if (try_tmpl) return try_tmpl; - // this should be an any case - if (opi->op == insert_symbol(env->gwion->st, "$") && opi->rhs == opi->lhs) + const m_str op = s_name(opi->op); + if (!strcmp(op, "$") && opi->rhs == opi->lhs) return opi->rhs; - if (opi->op == insert_symbol(env->gwion->st, "@func_check")) return NULL; - if (opi->op == insert_symbol(env->gwion->st, "@class_check")) + if (!strcmp(op, "@func_check")) return NULL; + if (!strcmp(op, "@class_check")) return env->gwion->type[et_error]; - if(opi->op == insert_symbol(env->gwion->st, "=>") && !strcmp(opi->rhs->name, "@now")) { + if(!strcmp(op, "=>") && !strcmp(opi->rhs->name, "@now")) { gwerr_basic(_("no match found for operator"), "expected duration", "did you try converting to `dur`?", env->name, opi->pos, 0); env->context->error = true; - } else if (opi->op != insert_symbol(env->gwion->st, "@implicit")) { + } else if (strcmp(op, "@implicit")) { + if (opi->rhs && opi->lhs && is_func(env->gwion, opi->rhs)) { + const size_t len = strlen(op); + if (len > 2 && !strcmp(op + len - 2, "=>")) + return chuck_rewrite(env, opi, op, len); + } env_err(env, opi->pos, _("%s %s %s: no match found for operator"), type_name(opi->lhs), s_name(opi->op), type_name(opi->rhs)); } diff --git a/src/parse/partial.c b/src/parse/partial.c index 8a32be05..9979a787 100644 --- a/src/parse/partial.c +++ b/src/parse/partial.c @@ -23,7 +23,8 @@ ANN static Arg_List partial_arg_list(const Env env, const Arg_List base, const E sprintf(c, "@%u", args->len); const Arg *src = mp_vector_at(base, Arg, i); Type_Decl *td = src->td ? cpy_type_decl(env->gwion->mp, src->td) : NULL; - Arg arg = { .td = td, .var_decl = { .xid = insert_symbol(c) }}; + const Array_Sub array = src->var_decl.array ? cpy_array_sub(env->gwion->mp, src->var_decl.array) : NULL; + Arg arg = { .td = td, .var_decl = { .xid = insert_symbol(c), .array = array }}; mp_vector_add(env->gwion->mp, &args, Arg, arg); } i++; @@ -44,21 +45,26 @@ ANN2(1, 2) static inline Func_Base *partial_base(const Env env, const Func_Base return fb; } -ANN static Exp partial_call(const Env env, Exp e) { +ANN static Exp partial_exp(const Env env, Exp e, const uint i) { + if(is_hole(env, e) || is_typed_hole(env, e)) { + char c[256]; + sprintf(c, "@%u", i); + return new_prim_id(env->gwion->mp, insert_symbol(c), e->pos); + } + const Exp next = e->next; + e->next = NULL; + const Exp exp = cpy_exp(env->gwion->mp, e); + e->next = next; + return exp; +} + +ANN2(1) static Exp partial_call(const Env env, Exp e) { Exp base = NULL, arg; uint32_t i = 0; while(e) { - if(is_hole(env, e) || is_typed_hole(env, e)) { - char c[256]; - sprintf(c, "@%u", i++); - const Exp next = new_prim_id(env->gwion->mp, insert_symbol(c), e->pos); - if(base) arg = arg->next = next; - else arg = base = next; - } else { - const Exp next = cpy_exp(env->gwion->mp, e); - if(base) arg = arg->next = next; - else arg = base = next; - } + const Exp exp = partial_exp(env, e, i++); + if(base) arg = arg->next = exp; + else arg = base = exp; e = e->next; } return base; @@ -94,13 +100,11 @@ ANN Func find_match(const Env env, Func func, const Exp exp, const bool implicit } ANN Func find_match_actual(const Env env, const Func up, const Exp args) { - Func func; - if ((func = find_match(env, up, args, false, true)) || - (func = find_match(env, up, args, true, true)) || - (func = find_match(env, up, args, false, true)) || - (func = find_match(env, up, args, true, false))) - return func; - return NULL; + return find_match(env, up, args, false, true) ?: + find_match(env, up, args, true, true) ?: + find_match(env, up, args, false, true) ?: + find_match(env, up, args, true, false) ?: + NULL; } ANN static Func partial_match(const Env env, const Func up, const Exp args, const loc_t loc); @@ -136,15 +140,19 @@ ANN void ambiguity(const Env env, Func f, const Exp args, const loc_t loc) { ANN static Func partial_match(const Env env, const Func up, const Exp args, const loc_t loc) { const Func f = find_match_actual(env, up, args); if(f) { + const Type t = f->value_ref->from->owner_class; if(f->next) { const Func next = partial_match(env, f->next, args, loc); if(next) { - gwerr_basic(_("can't resolve ambiguity"), _("in this partial application"), _("use typed holes: _ $ type"), env->name, loc, 0); - gw_err(_("\nthose functions could match:\n")); - print_signature(f); - ambiguity(env, next, args, loc); - env->context->error = true; - return NULL; + const Type tnext = next->value_ref->from->owner_class; + if(!t || !tnext || isa(t, tnext) < 0) { + gwerr_basic(_("can't resolve ambiguity"), _("in this partial application"), _("use typed holes: _ $ type"), env->name, loc, 0); + gw_err(_("\nthose functions could match:\n")); + print_signature(f); + ambiguity(env, next, args, loc); + env->context->error = true; + return NULL; + } } } return f; diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 518ebbd6..c237c607 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -221,6 +221,12 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) { #define scan0_nspc(env, a) \ GET_FLAG(a, global) ? !env->class_def ? env->global_nspc : NULL : env->curr +#include "gack.h" +static GACK(gack_enum) { + const Value v = (Value)map_at(&t->nspc->info->value->map, *(m_uint*)VALUE); + INTERP_PRINTF("%s", v->name); +} + ANN static Type enum_type(const Env env, const Enum_Def edef) { const Type t = type_copy(env->gwion->mp, env->gwion->type[et_int]); t->name = s_name(edef->xid); @@ -233,6 +239,7 @@ ANN static Type enum_type(const Env env, const Enum_Def edef) { add_type(env, env->curr, t); mk_class(env, t, edef->pos); set_tflag(t, tflag_enum); + CHECK_BO(mk_gack(env->gwion->mp, t, gack_enum)); if (global) env_pop(env, 0); // scan0_implicit_similar(env, t, env->gwion->type[et_int]); // scan0_implicit_similar(env, env->gwion->type[et_int], t); diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index 4ff838a8..d77a7c41 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -46,8 +46,8 @@ ANN static inline Type ref(const Env env, Type_Decl *td) { ANN static Symbol symname(const Env env, Func_Base *const base, bool *global) { GwText text = { .mp = env->gwion->mp }; text_add(&text, "("); - const Type t = known_type(env, base->td); - const m_str name = type2str(env->gwion, t, base->td->pos); + DECL_OO(const Type, t, = known_type(env, base->td)); + DECL_OO(const m_str, name, = type2str(env->gwion, t, base->td->pos)); text_add(&text, name); free_mstr(env->gwion->mp, name); text_add(&text, "("); @@ -56,8 +56,8 @@ ANN static Symbol symname(const Env env, Func_Base *const base, bool *global) { for(uint32_t i = 0; i < base->args->len; i++) { if(i) text_add(&text, ","); Arg *arg = mp_vector_at(base->args, Arg, i); - const Type t = known_type(env, arg->td); - const m_str name = type2str(env->gwion, t, arg->td->pos); + DECL_OO(const Type, t, = known_type(env, arg->td)); + DECL_OO(const m_str, name, = type2str(env->gwion, t, arg->td->pos)); text_add(&text, name); free_mstr(env->gwion->mp, name); if(*global) @@ -73,15 +73,15 @@ ANN static Symbol symname(const Env env, Func_Base *const base, bool *global) { ANN static inline Type find(const Env env, Type_Decl *td) { if (!td->fptr) return find_type(env, td); - bool global; - td->xid = symname(env, td->fptr->base, &global); + bool global = false; + CHECK_OO((td->xid = symname(env, td->fptr->base, &global))); const Fptr_Def fptr = td->fptr; td->fptr = NULL; const Type exists = find_type(env, td); if(exists) return exists; - const m_uint scope = !global - ? env_push_global(env) - : env_push(env, NULL, env->context->nspc); + const m_uint scope = env->context + ? env_push(env, NULL, env->context->nspc) + : env_push_global(env); const m_bool ret = traverse_fptr_def(env, fptr); env_pop(env, scope); const Type t = fptr->type; diff --git a/src/plug.c b/src/plug.c index 9fadddc5..96a1855e 100644 --- a/src/plug.c +++ b/src/plug.c @@ -90,6 +90,12 @@ ANN m_bool plug_ini(const struct Gwion_ *gwion, const Vector list) { } void free_plug(const Gwion gwion) { + const Vector vec = &gwion->data->plugs->vec; + for (m_uint i = vector_size(vec) + 1; --i;) { + const Nspc nspc = (Nspc)vector_at(vec, i-1); + nspc_remref(nspc, gwion); + } + vector_release(&gwion->data->plugs->vec); const Map map = &gwion->data->plugs->map; for (m_uint i = 0; i < map_size(map); ++i) { const Plug plug = (Plug)VVAL(map, i); @@ -99,12 +105,6 @@ void free_plug(const Gwion gwion) { DLCLOSE(plug->dl); } map_release(map); - const Vector vec = &gwion->data->plugs->vec; - for (m_uint i = vector_size(vec) + 1; --i;) { - const Nspc nspc = (Nspc)vector_at(vec, i-1); - nspc_remref(nspc, gwion); - } - vector_release(&gwion->data->plugs->vec); mp_free2(gwion->mp, sizeof(Plugs), gwion->data->plugs); } diff --git a/src/vm/vm.c b/src/vm/vm.c index 26bd184c..e15b86aa 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -103,7 +103,7 @@ ANN static bool unwind(const VM_Shred shred, const Symbol effect, const m_uint s if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG) return false; shred_unwind(shred); - return unwind(shred, effect, size - 1); + return unwind(shred, effect, size - (code != shred->code)); } ANN static void trace(VM_Shred shred, const m_uint size) { @@ -1606,10 +1606,23 @@ VM *new_vm(MemPool p, const bool audio) { return vm; } +ANN static inline void free_killed_shred(const Vector v) { + for (m_uint i = 0; i < vector_size(v); i++) { + const VM_Shred shred = (VM_Shred)vector_at(v, i); + free_vm_shred(shred); + } +} + +ANN void vm_clean(const VM* vm, const Gwion gwion) { + free_killed_shred(&vm->shreduler->killed_shreds); + gwion_end_child(vm->cleaner_shred, gwion); + if (vm->bbq) free_driver(vm->bbq, gwion->vm); +} + ANN void free_vm(VM *vm) { const MemPool mp = vm->gwion->mp; + if (vm->cleaner_shred) free_vm_shred(vm->cleaner_shred); free_shreduler(mp, vm->shreduler); - if (vm->bbq) free_driver(vm->bbq, vm); vector_release(&vm->ugen); mp_free(mp, VM, vm); } diff --git a/tests/chuck_rewrite/chuck_rewrite.gw b/tests/chuck_rewrite/chuck_rewrite.gw new file mode 100644 index 00000000..de8da997 --- /dev/null +++ b/tests/chuck_rewrite/chuck_rewrite.gw @@ -0,0 +1,12 @@ +#! [contains] 42 +2 => var int i; + +fun int test() { + return i; +} + +fun int test(int tmp) { + return tmp => i; +} + +<<< 40 +=> test >>>; diff --git a/tests/chuck_rewrite/chuck_rewrite_error.gw b/tests/chuck_rewrite/chuck_rewrite_error.gw new file mode 100644 index 00000000..4df0fe14 --- /dev/null +++ b/tests/chuck_rewrite/chuck_rewrite_error.gw @@ -0,0 +1,12 @@ +#! [contains] during rewriting operation +2 => var int i; + +fun int test() { + return i; +} + +fun int test(int tmp) { + return tmp => i; +} + +<<< me +=> test >>>; diff --git a/tests/effects/check_ov.gw b/tests/effects/check_ov.gw new file mode 100644 index 00000000..4c3faf31 --- /dev/null +++ b/tests/effects/check_ov.gw @@ -0,0 +1,11 @@ +#! [contains] gotcha +fun void foo() { foo(); } + +fun void run() { + try { + foo(); + } handle StackOverflow { + <<< "gotcha" >>>; + } +} +run(); diff --git a/tests/effects/check_ov_inclass.gw b/tests/effects/check_ov_inclass.gw new file mode 100644 index 00000000..7256d137 --- /dev/null +++ b/tests/effects/check_ov_inclass.gw @@ -0,0 +1,14 @@ +#! [contains] gotcha +fun void foo() { foo(); } + +class C { + fun void run() { + try { + foo(); + } handle StackOverflow { + <<< "gotcha" >>>; + } + } + run(); +} +new C; diff --git a/tests/enum/scoped.gw b/tests/enum/scoped.gw index 27174e3f..93863f9a 100644 --- a/tests/enum/scoped.gw +++ b/tests/enum/scoped.gw @@ -1,4 +1,4 @@ -#! [contains] 1 +#! [contains] one enum MyEnum { zero, one } diff --git a/tests/locale/locale_error.gw b/tests/locale/locale_error.gw new file mode 100644 index 00000000..fc98f1ed --- /dev/null +++ b/tests/locale/locale_error.gw @@ -0,0 +1,2 @@ +#! [contains] invalid value for locale +`foo`;