]> Nishi Git Mirror - gwion.git/commitdiff
:art: merge dev
authorJérémie Astor <fennecdjay@gmail.com>
Fri, 13 May 2022 16:01:19 +0000 (18:01 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Fri, 13 May 2022 16:01:19 +0000 (18:01 +0200)
27 files changed:
Makefile
ast
include/gack.h
include/vm.h
plug
src/emit/emit.c
src/gwion.c
src/import/import_special.c
src/lib/lib_func.c
src/lib/locale.c
src/lib/object_op.c
src/lib/prim.c
src/lib/ref.c
src/lib/string.c
src/parse/check.c
src/parse/operator.c
src/parse/partial.c
src/parse/scan0.c
src/parse/type_decl.c
src/plug.c
src/vm/vm.c
tests/chuck_rewrite/chuck_rewrite.gw [new file with mode: 0644]
tests/chuck_rewrite/chuck_rewrite_error.gw [new file with mode: 0644]
tests/effects/check_ov.gw [new file with mode: 0644]
tests/effects/check_ov_inclass.gw [new file with mode: 0644]
tests/enum/scoped.gw
tests/locale/locale_error.gw [new file with mode: 0644]

index 9fa8b9863d870acf8c82daf40f304b02b8076a4a..cc45a093e66e7f89d75bd72ef01985adbcad53d4 100644 (file)
--- 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 e09543b39ec51dc344d74dd2c1adb415957c6b5a..ff31aff0f531c0bcf4a8ed9e04bedd0a1eefe9ba 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit e09543b39ec51dc344d74dd2c1adb415957c6b5a
+Subproject commit ff31aff0f531c0bcf4a8ed9e04bedd0a1eefe9ba
index d926119bbae4501cd5924f2298819a9a9de815b9..3515a42faf561ada462fa520420490d282d47001 100644 (file)
@@ -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
index 0ce89d89310bc6b03158455145f720c3ae454f38..deca0f85ea7eb4a912cd6e113b286375312820f9 100644 (file)
@@ -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 879e1bf7691c0bacdb50ec10fcbac4978c788a9d..5a583451cd50f26867cf18c9bd309e3cc0f523d2 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit 879e1bf7691c0bacdb50ec10fcbac4978c788a9d
+Subproject commit 5a583451cd50f26867cf18c9bd309e3cc0f523d2
index 2fa8c50476e7d64c08cfa1d1bad8a264b46dc534..312497ef092b1b076738c79b38289c71e8ffcd66 100644 (file)
@@ -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;
index 7de937623e646a39e11581def4c790d15b2b3b73..3342f657c392385153ad746ad55af2ec3abc1efb 100644 (file)
@@ -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);
index bcef3eb15b401c842cd6417ed21998e9623ee89e..971a29eec7c91965472ab2e56a822b26871eed4e 100644 (file)
@@ -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;
index 344ffbd87b08560c7972b3e6f03a3d8841e6586a..c6992f6dca6d19870ffadc08909984f30f97da77 100644 (file)
 #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};
index 697caad1ed8cf38dc259cdf1443f8b671a166741..6b7afcdc82b17e15a07da2844b2e73058a0d822f 100644 (file)
@@ -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;
index 12ff7c616dc77ed7e925d6825dadef7691652de2..984bf45beb52453ee3a19377f22dc688f608de5c 100644 (file)
@@ -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;
index fcaab1fad4bd66cab3bac8111f3b458c84c9bd6e..a6dc951a297e1ee458dfd111a44c9c4750e3f652 100644 (file)
@@ -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, >>,)
index 504e06447f0c10c027b3f18deb56bfb59de5cef0..8d9e620a16ba8ecfae55e6f7279bf59e15b2615c 100644 (file)
@@ -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);
 }
 
index 8fc945b739ed24a3859daf2105d9f5359dfa98f7..581d7bc5cda477120b64fb07a8748f43d2fac5d0 100644 (file)
@@ -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);
index 8c592cd22a67cafba9695d3ef1f9df76e7c1addf..978ba4c6add605735870718e3a1f7ef1be700431 100644 (file)
@@ -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);
 }
index fdf03fcf1f5639cea574b739586b59eb882e3794..5179dd4488f4e3c9075193952dc1c37089548b3c 100644 (file)
@@ -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));
   }
index 8a32be05f0c4c5ef98f1a7c3c77f6668fa5a8a98..9979a787ab13f0b1fc40e49bc7093c052c84eae6 100644 (file)
@@ -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;
index 518ebbd64a03e55182c773610c37af5984578f90..c237c60783dd111e58816fe8cfacc307d9d472df 100644 (file)
@@ -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);
index 4ff838a8774fc1dedf4335eaf9aa517b95952f32..d77a7c410308de1e8de078ebf7a557bc033404b2 100644 (file)
@@ -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;
index 9fadddc5913ca113879c95a315baad15dbf1feec..96a1855e5b4255efa54115c3574e32597a696c30 100644 (file)
@@ -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);
 }
 
index 26bd184c1ecc3508f3c73dc25d14f969d05ecf89..e15b86aac3b642ba9b07efb5c456e913b685b297 100644 (file)
@@ -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 (file)
index 0000000..de8da99
--- /dev/null
@@ -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 (file)
index 0000000..4df0fe1
--- /dev/null
@@ -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 (file)
index 0000000..4c3faf3
--- /dev/null
@@ -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 (file)
index 0000000..7256d13
--- /dev/null
@@ -0,0 +1,14 @@
+#! [contains] gotcha
+fun void foo() { foo(); }
+
+class C {
+  fun void run() {
+    try {
+      foo();
+    } handle StackOverflow {
+      <<< "gotcha" >>>;
+    }
+  }
+  run();
+}
+new C;
index 27174e3f904dccce59d740212a9fa42e917865fe..93863f9a2abc16978f3e2f8e8e9d140b328314ea 100644 (file)
@@ -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 (file)
index 0000000..fc98f1e
--- /dev/null
@@ -0,0 +1,2 @@
+#! [contains] invalid value for locale
+`foo`;