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
-Subproject commit e09543b39ec51dc344d74dd2c1adb415957c6b5a
+Subproject commit ff31aff0f531c0bcf4a8ed9e04bedd0a1eefe9ba
}
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
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));
-Subproject commit 879e1bf7691c0bacdb50ec10fcbac4978c788a9d
+Subproject commit 5a583451cd50f26867cf18c9bd309e3cc0f523d2
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;
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;
}
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;
}
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;
}
}
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;
return ret;
}
#endif
-*/
+
// skip when recursing
const Type t = actual_type(emit->gwion, exp_call->func->type);
const Func f = t->info->func;
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);
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;
#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;
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};
}
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;
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;
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, >>,)
#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);
}
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);
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);
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);
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) {
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"),
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);
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);
}
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;
}
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));
}
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++;
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;
}
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);
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;
#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);
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);
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, "(");
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)
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;
}
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);
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);
}
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) {
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);
}
--- /dev/null
+#! [contains] 42
+2 => var int i;
+
+fun int test() {
+ return i;
+}
+
+fun int test(int tmp) {
+ return tmp => i;
+}
+
+<<< 40 +=> test >>>;
--- /dev/null
+#! [contains] during rewriting operation
+2 => var int i;
+
+fun int test() {
+ return i;
+}
+
+fun int test(int tmp) {
+ return tmp => i;
+}
+
+<<< me +=> test >>>;
--- /dev/null
+#! [contains] gotcha
+fun void foo() { foo(); }
+
+fun void run() {
+ try {
+ foo();
+ } handle StackOverflow {
+ <<< "gotcha" >>>;
+ }
+}
+run();
--- /dev/null
+#! [contains] gotcha
+fun void foo() { foo(); }
+
+class C {
+ fun void run() {
+ try {
+ foo();
+ } handle StackOverflow {
+ <<< "gotcha" >>>;
+ }
+ }
+ run();
+}
+new C;
-#! [contains] 1
+#! [contains] one
enum MyEnum {
zero, one
}
--- /dev/null
+#! [contains] invalid value for locale
+`foo`;