]> Nishi Git Mirror - gwion.git/commitdiff
:art: Update and fix machine.remove
authorJérémie Astor <fennecdjay@gmail.com>
Tue, 15 Jun 2021 14:57:57 +0000 (16:57 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Tue, 15 Jun 2021 14:59:54 +0000 (16:59 +0200)
25 files changed:
Makefile
ast
fmt
include/clean.h
include/emit.h
include/env/envset.h
include/operator.h
include/vm.h
plug
src/compile.c
src/emit/emit.c
src/emit/emitter.c
src/env/func.c
src/gwion.c
src/import/import_cdef.c
src/import/import_special.c
src/lib/array.c
src/lib/ptr.c
src/lib/string.c
src/lib/union.c
src/parse/check.c
src/parse/scan1.c
src/vm/vm.c
src/vm/vm_code.c
util

index 18f4f6328db8c390e2e15a149ddecfe322a24cf7..ce5a1275542adaddf843abb9e99eb003023e731e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,15 +11,14 @@ include config.mk
 
 SEVERITY ?= 10
 GWION_TEST_DIR ?= /tmp
-
-src := $(wildcard src/*.c)
-src += $(wildcard src/*/*.c)
-
 test_dir_all := $(wildcard tests/*)
 test_ignore = tests/plug test/driver tests/module
 test_dir := $(filter-out $(test_ignore), $(test_dir_all))
 test_dir += examples
 
+src := $(wildcard src/*.c)
+src += $(wildcard src/*/*.c)
+
 CFLAGS += -Iutil/include -Iast/include -Ilibcmdapp/src -D_GNU_SOURCE
 CFLAGS += -Iast/libprettyerr/src -Ifmt/include
 
@@ -38,6 +37,7 @@ src_obj := $(src:.c=.o)
 gcda := $(src:.c=.gcda)
 gcno := $(src:.c=.gcno)
 lib_obj := $(filter-out src/main.o, ${src_obj})
+almost_obj := $(filter-out src/vm/vm.o, ${src_obj})
 
 CFLAGS  += -Iinclude
 
@@ -45,25 +45,31 @@ ifeq ($(shell uname), Linux)
 LDFLAGS += -lrt
 endif
 
-CFLAGS += -DGWION_BUILTIN
-
-_GWLIBS = util/libgwion_util.a ast/libgwion_ast.a libcmdapp/libcmdapp.a lib${PRG}.a util/libtermcolor/libtermcolor.a ast/libprettyerr/libprettyerr.a fmt/libgwion-fmt.a
-GWLIBS := lib${PRG}.a libcmdapp/libcmdapp.a ast/libgwion_ast.a
-GWLIBS += util/libgwion_util.a ast/libprettyerr/libprettyerr.a util/libtermcolor/libtermcolor.a
-GWLIBS += fmt/libgwion-fmt.a
-_LDFLAGS = ${GWLIBS} ${LDFLAGS}
+ALMOST_LIBS := libcmdapp/libcmdapp.a fmt/libgwion-fmt.a
+ALMOST_LIBS += ast/libgwion_ast.a ast/libprettyerr/libprettyerr.a
+ALMOST_LIBS += util/libgwion_util.a util/libtermcolor/libtermcolor.a
+GWLIBS := lib${PRG}.a ${ALMOST_LIBS}
+LDFLAGS := ${GWLIBS} ${LDFLAGS}
 
 # we are not pedantic
 CFLAGS += -Wno-pedantic
 
-all: options-show ${_GWLIBS} src/main.o
+CFLAGS += -DGWION_BUILTIN
+
+all: options-show ${GWLIBS} src/main.o
        @$(info link ${PRG})
-       @${CC} src/main.o -o ${PRG} ${_LDFLAGS} ${LIBS}
+       @${CC} src/main.o -o ${PRG} ${LDFLAGS} ${LIBS}
 
 options-show:
        @$(call _options)
        @$(info libs: ${GWLIBS})
 
+almost_gwion: ${almost_obj} ${ALMOST_LIBS}
+
+lto:
+       @${MAKE} USE_LTO=1 almost_gwion
+       @${MAKE} USE_LTO=0
+
 lib${PRG}.a: ${lib_obj}
        @${AR} ${AR_OPT}
 
@@ -114,8 +120,6 @@ update: clean-all
        git submodule update --recursive --init
        make
 
-.PHONY: .afl
-
 clean: clean_core
        $(info cleaning ...)
        @rm -f src/*.o src/*/*.o gwion lib${PRG}.a ${gcno} ${gcda}
@@ -148,7 +152,7 @@ test:
 
 scan:
        @rm -rf scan_output
-       @scan-build -o ./scan_output make
+       @scan-build -o ./scan_output make USE_DEBUG=1
        @scan-view ./scan_output/*
 
 include $(wildcard .d/*.d)
diff --git a/ast b/ast
index 6d965961163bf32e912acd09d6cda41b93e24ff7..5796cf89170539636d4f1405c59bc938e055acb0 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 6d965961163bf32e912acd09d6cda41b93e24ff7
+Subproject commit 5796cf89170539636d4f1405c59bc938e055acb0
diff --git a/fmt b/fmt
index 14d746b2d31b99395d8035c8450353afc059eac5..260f256586cbd65f0e5c74484dbe71d26b6db62e 160000 (submodule)
--- a/fmt
+++ b/fmt
@@ -1 +1 @@
-Subproject commit 14d746b2d31b99395d8035c8450353afc059eac5
+Subproject commit 260f256586cbd65f0e5c74484dbe71d26b6db62e
index 40b2e8c4dd5b7ed063a3c9c6da92474adef971d2..2fda18fd6c4907f8819581a18c4c5a4090797ce7 100644 (file)
@@ -6,8 +6,8 @@ void class_def_cleaner(const Gwion, Class_Def);
 void func_def_cleaner(const Gwion, Func_Def);
 #ifdef __CLEAN_IMPL
 typedef struct {
-  m_uint scope;
-  Gwion  gwion;
+  Gwion    gwion;
+  uint16_t scope;
 } Clean;
 
 ANN static void clean_array_sub(Clean *a, Array_Sub b);
index 1b90044a49d0350b98d894069baae6aefdd6830c..2d6a777095375c3ee799b0a87b700147e8771c90 100644 (file)
@@ -3,20 +3,29 @@
 
 typedef struct Frame_ {
   struct Vector_ stack;
-  size_t         curr_offset;
   struct Map_    handlers;
   struct Vector_ defer;
-  m_uint         try_top;
+  m_uint         value_count;
+  uint16_t       curr_offset;
+  uint16_t       try_top;
 } Frame;
 
+typedef struct VMValue_ {
+  Type t;
+  uint16_t offset;
+  uint16_t start;
+  uint16_t end;
+} VMValue;
+
 typedef struct Code_ {
-  Frame *        frame;
-  struct Vector_ instr;
-  size_t         stack_depth;
-  struct Vector_ stack_cont;
-  struct Vector_ stack_break;
-  struct Vector_ stack_return;
-  m_str          name;
+  Frame *          frame;
+  struct Vector_   instr;
+  struct Vector_   stack_cont;
+  struct Vector_   stack_break;
+  struct Vector_   stack_return;
+  struct M_Vector_ live_values;
+  m_str            name;
+  uint16_t         stack_depth;
 } Code;
 
 struct EmitterInfo_ {
@@ -36,8 +45,8 @@ struct Emitter_ {
   struct Gwion_ *      gwion;
   struct EmitterInfo_ *info;
   struct Vector_       stack;
-  m_uint               this_offset;   // reset
-  m_uint               vararg_offset; // reset
+  uint16_t             this_offset;   // reset
+  uint16_t             vararg_offset; // reset
 };
 
 ANEW ANN Emitter new_emitter(MemPool);
index 63f4da4e3736b394cc90dc38150cf58ec3b0f3d2..2c02d912865ae5f4e532795419c83d836d4d67b2 100644 (file)
@@ -6,10 +6,10 @@ struct EnvSet {
   const Env         env;
   const envset_func func;
   const void *      data;
-  const m_int       scope;
   const enum tflag  flag;
   Context           _ctx;
   m_str             _filename;
+  const uint16_t    scope;
   bool              run;
 };
 
index a75fa009181bbb899525fbc7b699953c1038f568..6dadf873199e9cbecfc7884bfb4e2993709ea274 100644 (file)
@@ -85,6 +85,7 @@ ANN void   free_op_map(Map map, struct Gwion_ *gwion);
 
 ANN void               operator_suspend(const Nspc, struct Op_Import *);
 ANN static inline void operator_resume(struct Op_Import *opi) {
+  assert(opi->ret);
   *(uintptr_t *)opi->ret = opi->data;
 }
 
index 6ab8a31fa19b611fa82a9b1844f403fe533c7129..ab824db11d8e39ce3c119768153cfd5a2d3d5beb 100644 (file)
@@ -16,16 +16,16 @@ struct VM_Code_ {
     struct Vector_ instr;
     m_uint         native_func;
   };
-  size_t stack_depth;
   Type   ret_type; // could be `struct Vector_ tmpl_types;`
   union {
     void *   memoize;
     Closure *closure;
   };
-  struct Map_ handlers;
   m_str       name;
+  struct Map_ handlers;
+  struct M_Vector_ live_values;
+  uint16_t    stack_depth;
   uint16_t    ref;
-  ae_flag     flag;
   bool        builtin;
   bool        callback;
   bool        is_memoize;
@@ -97,9 +97,9 @@ struct VM_Shred_ {
   struct ShredInfo_ *info;
 };
 REF_FUNC(VM_Code, vmcode)
-ANN2(1, 5)
-ANEW VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth,
-                        const int builtin, const m_str name);
+ANN2(1,4)
+ANEW VM_Code new_vmcode(MemPool p, const Vector instr, const M_Vector live_values, const m_str name,
+                        const uint16_t stack_depth, const bool builtin);
 ANN ANEW VM_Code vmcode_callback(MemPool p, const VM_Code code);
 
 ANN VM_Shred shreduler_get(const Shreduler s) __attribute__((hot));
@@ -129,7 +129,7 @@ ANN bool  vm_running(VM const *);
 ANN void  free_vm(VM *vm);
 ANN void  vm_ini_shred(const VM *vm, const VM_Shred shred) __attribute__((hot));
 ANN void  vm_add_shred(const VM *vm, const VM_Shred shred) __attribute__((hot));
-ANN void  vm_remove(const VM *vm, const m_uint index) __attribute__((hot));
+ANN bool  vm_remove(const VM *vm, const m_uint index) __attribute__((hot));
 ANN m_str code_name_set(MemPool p, const m_str, const m_str);
 ANN m_str code_name(const m_str, const bool);
 ANN uint32_t gw_rand(uint32_t s[2]);
diff --git a/plug b/plug
index a853cfd9bbaf47604202dda4ecd168a62091b13e..857e0e59f0bb00b6de35ad770814960c3e442d6a 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit a853cfd9bbaf47604202dda4ecd168a62091b13e
+Subproject commit 857e0e59f0bb00b6de35ad770814960c3e442d6a
index 34744434bf109ab2a5deec338cc7efa6b9e9224b..b4a967020316c6f4a7c922a56388f0f93097fbc3 100644 (file)
@@ -174,6 +174,7 @@ ANN m_uint compile_filename_xid(struct Gwion_ *gwion, const m_str filename,
                                 const m_uint xid) {
   struct Compiler c = {.base = filename, .type = COMPILE_NAME};
   if (!compile(gwion, &c)) return 0;
+  assert(c.shred);
   return c.shred->tick->xid = xid;
 }
 
@@ -181,6 +182,7 @@ ANN m_uint compile_string_xid(struct Gwion_ *gwion, const m_str filename,
                               const m_str data, const m_uint xid) {
   struct Compiler c = {.base = filename, .type = COMPILE_MSTR, .data = data};
   if (!compile(gwion, &c)) return 0;
+  assert(c.shred);
   return c.shred->tick->xid = xid;
 }
 
@@ -188,5 +190,6 @@ ANN m_uint compile_file_xid(struct Gwion_ *gwion, const m_str filename,
                             FILE *file, const m_uint xid) {
   struct Compiler c = {.base = filename, .type = COMPILE_FILE, .file = file};
   if (!compile(gwion, &c)) return 0;
+  assert(c.shred);
   return c.shred->tick->xid = xid;
 }
index f5df14131ead0339c393f87d35a56ed36ee89763..2841866482126d93f6e0e12e78e6c0a8935ce843 100644 (file)
@@ -38,6 +38,7 @@ typedef struct Local_ {
   Type   type;
   m_uint offset;
   bool   skip;
+  bool   is_compound;
 } Local;
 
 static inline void emit_pop(const Emitter emit, const m_uint scope) {
@@ -84,14 +85,12 @@ ANN static Local *new_local(MemPool p, const Type type) {
   return local;
 }
 
-ANN static m_uint frame_local(MemPool p, Frame *frame, const Type t,
-                              const bool skip) {
-  Local *local  = new_local(p, t);
-  local->offset = frame->curr_offset;
-  local->skip   = skip;
+ANN static Local *frame_local(MemPool p, Frame *frame, const Type t) {
+  Local *const l = new_local(p, t);
+  l->offset      = frame->curr_offset;
   frame->curr_offset += t->size;
-  vector_add(&frame->stack, (vtype)local);
-  return local->offset;
+  vector_add(&frame->stack, (vtype)l);
+  return l;
 }
 
 ANN static inline void frame_push(Frame *frame) {
@@ -204,12 +203,13 @@ ANN static m_int _frame_pop(const Emitter emit) {
   DECL_OB(const Local *, l, = (Local *)vector_pop(&frame->stack));
   frame->curr_offset -= l->type->size;
   if (l->skip) return _frame_pop(emit);
-  if (tflag(l->type, tflag_struct)) {
-    struct_pop(emit, l->type, l->offset);
-    return _frame_pop(emit);
-  }
-  return isa(l->type, emit->gwion->type[et_object]) > 0 ? (m_int)l->offset
-                                                        : _frame_pop(emit);
+  if (!l->is_compound) return _frame_pop(emit);
+  VMValue *vmval =
+      (VMValue *)m_vector_addr(&emit->code->live_values, --frame->value_count);
+  vmval->end = emit_code_size(emit);
+  if (!tflag(l->type, tflag_struct)) return (m_int)l->offset;
+  struct_pop(emit, l->type, l->offset);
+  return _frame_pop(emit);
 }
 
 ANN static m_int frame_pop(const Emitter emit) {
@@ -230,6 +230,7 @@ ANEW static Code *new_code(const Emitter emit, const m_str name) {
   vector_init(&code->stack_break);
   vector_init(&code->stack_cont);
   vector_init(&code->stack_return);
+  m_vector_init(&code->live_values, sizeof(VMValue), 0);
   code->frame = new_frame(emit->gwion->mp);
   return code;
 }
@@ -239,6 +240,7 @@ ANN static void free_code(MemPool p, Code *code) {
   vector_release(&code->stack_break);
   vector_release(&code->stack_cont);
   vector_release(&code->stack_return);
+  if (code->live_values.ptr) m_vector_release(&code->live_values);
   free_frame(p, code->frame);
   free_mstr(p, code->name);
   mp_free(p, Code, code);
@@ -275,11 +277,21 @@ ANN m_uint emit_code_offset(const Emitter emit) {
 }
 
 ANN m_uint emit_local(const Emitter emit, const Type t) {
-  return frame_local(emit->gwion->mp, emit->code->frame, t, false);
+  Local *const l = frame_local(emit->gwion->mp, emit->code->frame, 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)};
+    m_vector_add(&emit->code->live_values, &vmval);
+    ++emit->code->frame->value_count;
+  }
+  return l->offset;
 }
 
 ANN m_uint emit_localn(const Emitter emit, const Type t) {
-  return frame_local(emit->gwion->mp, emit->code->frame, t, true);
+  Local *const l = frame_local(emit->gwion->mp, emit->code->frame, t);
+  l->skip        = true;
+  return l->offset;
 }
 
 ANN void emit_ext_ctor(const Emitter emit, const Type t);
@@ -289,9 +301,11 @@ ANN static inline void maybe_ctor(const Emitter emit, const Type t) {
 }
 
 ANN static void emit_pre_ctor(const Emitter emit, const Type type) {
-  if (type->info->parent) emit_pre_ctor(emit, type->info->parent);
-  if (tflag(type, tflag_typedef) && type->info->parent->array_depth)
-    emit_array_extend(emit, type, type->info->cdef->base.ext->array->exp);
+  if (type->info->parent) {
+    emit_pre_ctor(emit, type->info->parent);
+    if (tflag(type, tflag_typedef) && type->info->parent->array_depth)
+      emit_array_extend(emit, type, type->info->cdef->base.ext->array->exp);
+  }
   maybe_ctor(emit, type);
 }
 
@@ -585,8 +599,9 @@ ANN static m_bool emit_range(const Emitter emit, Range *range) {
 ANN static m_bool emit_prim_range(const Emitter emit, Range **data) {
   Range *range = *data;
   CHECK_BB(emit_range(emit, range));
-  const Exp        e   = range->start ?: range->end;
-  const Symbol     sym = insert_symbol("@range");
+  const Exp    e   = range->start ?: range->end;
+  const Symbol sym = insert_symbol("@range");
+  assert(e);
   struct Op_Import opi = {.op   = sym,
                           .rhs  = e->type,
                           .pos  = e->pos,
@@ -625,8 +640,9 @@ ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array *array) {
 ANN static m_bool emit_exp_slice(const Emitter emit, const Exp_Slice *range) {
   CHECK_BB(emit_exp(emit, range->base));
   CHECK_BB(emit_range(emit, range->range));
-  const Symbol     sym = insert_symbol("@slice");
-  const Exp        e   = range->range->start ?: range->range->end;
+  const Symbol sym = insert_symbol("@slice");
+  const Exp    e   = range->range->start ?: range->range->end;
+  assert(e);
   struct Op_Import opi = {.op   = sym,
                           .lhs  = e->type,
                           .rhs  = range->base->type,
@@ -1250,7 +1266,8 @@ static inline m_bool push_func_code(const Emitter emit, const Func f) {
   const Instr instr = (Instr)vector_back(&emit->code->instr);
   if (instr->opcode == eDotTmplVal) {
     size_t len = strlen(f->name);
-    size_t sz  = len - strlen(f->value_ref->from->owner_class->name);
+    assert(f->value_ref->from->owner_class);
+    size_t sz = len - strlen(f->value_ref->from->owner_class->name);
     char   c[sz + 1];
     memcpy(c, f->name, sz);
     c[sz]               = '\0';
@@ -1546,6 +1563,7 @@ ANN static m_bool spork_prepare_code(const Emitter         emit,
   emit_add_instr(emit, RegPushImm);
   push_spork_code(emit, sp->is_spork ? SPORK_CODE_PREFIX : FORK_CODE_PREFIX,
                   sp->code->pos);
+  if (emit->env->class_def) stack_alloc(emit);
   if (emit->env->func && vflag(emit->env->func->value_ref, vflag_member))
     stack_alloc(emit);
   return scoped_stmt(emit, sp->code, 0);
@@ -1560,7 +1578,10 @@ ANN static m_bool spork_prepare_func(const Emitter         emit,
 }
 
 ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
-  if (!sp->code) CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call));
+  if (!sp->code) {
+    assert(sp->exp);
+    CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call));
+  }
   if ((sp->code ? spork_prepare_code : spork_prepare_func)(emit, sp) > 0)
     return finalyze(emit, EOC);
   emit_pop_code(emit);
index 95350b2dab35839eecee261f6a0f602c4459c99b..7f6c9075b950c8ad10c496a716237819818b2ca9 100644 (file)
@@ -8,9 +8,12 @@
 #include "escape.h"
 
 static ANEW ANN VM_Code emit_code(const Emitter emit) {
-  Code *const   c = emit->code;
-  const VM_Code code =
-      new_vmcode(emit->gwion->mp, &c->instr, c->stack_depth, 0, c->name);
+  Code *const   c          = emit->code;
+  const bool    has_values = m_vector_size(&c->live_values);
+  const VM_Code code       = new_vmcode(emit->gwion->mp, &c->instr,
+                                  has_values ? &c->live_values : NULL, c->name,
+                                  c->stack_depth, false);
+  if (has_values) c->live_values.ptr = NULL;
   return code;
 }
 
index 5f6e72425190344b6f7112f13a26737dbf9c37b6..1073c5eb66a46674b5be56b1eb92c849d82a4601 100644 (file)
@@ -37,6 +37,6 @@ Symbol func_symbol(const Env env, const m_str nspc, const m_str base,
 
 ANN void builtin_func(const MemPool mp, const Func f, void *func_ptr) {
   set_vflag(f->value_ref, vflag_builtin);
-  f->code              = new_vmcode(mp, NULL, f->def->stack_depth, 1, f->name);
+  f->code = new_vmcode(mp, NULL, NULL, f->name, f->def->stack_depth, true);
   f->code->native_func = (m_uint)func_ptr;
 }
index d39cccdb6529c1be569ef224e6f93e3454629108..adbd7f89693cfe5e7c2879fa045cdca2df446ac2 100644 (file)
@@ -33,7 +33,8 @@ ANN static inline m_bool gwion_engine(const Gwion gwion) {
 }
 
 ANN static void gwion_cleaner(const Gwion gwion) {
-  const VM_Code code       = new_vmcode(gwion->mp, NULL, 0, 1, "in code dtor");
+  const VM_Code code =
+      new_vmcode(gwion->mp, NULL, NULL, "in code dtor", 0, true);
   gwion->vm->cleaner_shred = new_vm_shred(gwion->mp, code);
   vm_ini_shred(gwion->vm, gwion->vm->cleaner_shred);
 }
index 93469d3faeedd0d1680d3e801fee35317f219355..05daf682f82bb95c9f378a5c0ca163294e828035 100644 (file)
@@ -21,7 +21,7 @@ ANN static m_bool mk_xtor(MemPool p, const Type type, const m_uint d,
                           const enum tflag e) {
   VM_Code *code = e == tflag_ctor ? &type->nspc->pre_ctor : &type->nspc->dtor;
   const m_str name     = type->name;
-  *code                = new_vmcode(p, NULL, SZ_INT, 1, name);
+  *code                = new_vmcode(p, NULL, NULL, name, SZ_INT, true);
   (*code)->native_func = (m_uint)d;
   type->tflag |= e;
   return GW_OK;
@@ -66,6 +66,7 @@ ANN static Type type_finish(const Gwi gwi, const Type t) {
   if (gwi->gwion->data->cdoc) {
     lint_indent(gwi->lint);
     gwi->lint->indent++;
+    assert(t->info->cdef);
     lint_class_def(gwi->lint, t->info->cdef);
   }
   return t;
index b57b2a213cf13a901762951db935298c731afb12..d0586769138f3923a5e0b12db6b2e02a66b8b746 100644 (file)
@@ -45,7 +45,7 @@ ANN void gwi_set_loc(const Gwi gwi, const m_str file, const uint line) {
 }
 
 ANN static m_bool mk_gack(MemPool p, const Type type, const f_gack d) {
-  const VM_Code code = new_vmcode(p, NULL, SZ_INT, 1, "@gack");
+  const VM_Code code = new_vmcode(p, NULL, NULL, "@gack", SZ_INT, true);
   code->native_func  = (m_uint)d;
   type->info->gack   = code;
   return GW_OK;
index c47f760a758e835c72cb4c2a06414d930d9cea64..042dc9286171c6898a11049b11fd2936777e442c 100644 (file)
@@ -703,8 +703,8 @@ static OP_CHECK(opck_array_scan) {
   builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 11),
                vm_vector_foldr);
   if (isa(base, env->gwion->type[et_compound]) > 0) {
-    t->nspc->dtor =
-        new_vmcode(env->gwion->mp, NULL, SZ_INT, 1, "array component dtor");
+    t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, NULL,
+                               "array component dtor", SZ_INT, true);
     set_tflag(t, tflag_dtor);
     t->nspc->dtor->native_func = (m_uint)(
         !tflag(base, tflag_struct) ? array_dtor_obj : array_dtor_struct);
@@ -947,6 +947,7 @@ INSTR(ArrayAlloc) {
     gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n",
            shred->tick->xid, shred->code->name);
     vm_shred_exit(shred);
+    if (info->is_obj) free(aai.data);
     return; // TODO make exception vararg
   }
   *(void **)(ref->data + SZ_INT) = aai.data;
index a0693e6570bc9bfabeac912d2ee06072c593762b..b7b1ea7ba70394ba6cf4af519da0c3351e387cd6 100644 (file)
@@ -158,7 +158,8 @@ static OP_CHECK(opck_ptr_scan) {
   env_pop(env, scope);
   nspc_add_type_front(t->info->value->from->owner, info.name, t);
   if (isa(base, env->gwion->type[et_compound]) > 0) {
-    t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, SZ_INT, 1, "@PtrDtor");
+    t->nspc->dtor =
+        new_vmcode(env->gwion->mp, NULL, NULL, "@PtrDtor", SZ_INT, true);
     if (!tflag(base, tflag_struct))
       t->nspc->dtor->native_func = (m_uint)ptr_object_dtor;
     else
index b094c2b45cb6cbbd9f93726c4584cb342133d62c..dd6c827a376ee20074714d62180f52dc40983bcc 100644 (file)
@@ -247,7 +247,7 @@ static MFUN(string_replaceN) {
   }
   char         insert[strlen(STRING(arg)) + 1];
   const m_uint len = strlen(str);
-  memset(insert, 0, len + 1);
+  //  memset(insert, 0, len + 1);
   strcpy(insert, STRING(arg));
   str[len] = '\0';
   if (index > (m_int)len) index = len - 1;
index 66bcb05d5aeb75a80d515eee7c5635990257b17e..c48178d7180c9dfa8619b5fb3102c1889cf542cf 100644 (file)
@@ -107,8 +107,8 @@ static OP_CHECK(opck_union_ctor) {
   Exp_Call *call = (Exp_Call *)data;
   const Exp name = call->args;
   if (!name || !name->next || name->next->next)
-    ERR_N(name->pos, "Union constructor takes two arguments, "
-                     "'id' and 'value'");
+    ERR_N(call->func->pos, "Union constructor takes two arguments, "
+                           "'id' and 'value'");
   if (name->exp_type != ae_exp_primary || name->d.prim.prim_type != ae_prim_id)
     return NULL;
   const Exp  val  = name->next;
index 7b4678c93fa427a6825b52f4f22e1d2bf472f081..b451914fee0551e049f86b5cf624a958b9bab68f 100644 (file)
@@ -182,7 +182,7 @@ ANN static m_bool prim_array_inner(const Env env, Type type, const Exp e,
   gwerr_basic(_("literal contains incompatible types"), fst, NULL, env->name,
               loc, 0);
   // suggested fix: rewrite int 2 as float 2.0"
-  char sec[12 + strlen(e->type->name)];
+  char sec[16 + strlen(e->type->name)];
   sprintf(sec, "got `{+/}%s{0}`", e->type->name);
   gwerr_secondary(sec, env->name, e->pos);
 
@@ -223,7 +223,8 @@ ANN static m_bool check_range(const Env env, Range *range) {
 ANN static Type check_prim_range(const Env env, Range **data) {
   Range *range = *data;
   CHECK_BO(check_range(env, range));
-  const Exp        e   = range->start ?: range->end;
+  const Exp e = range->start ?: range->end;
+  assert(e);
   const Symbol     sym = insert_symbol("@range");
   struct Op_Import opi = {.op   = sym,
                           .rhs  = e->type,
@@ -443,8 +444,9 @@ static ANN Type check_exp_array(const Env env, const Exp_Array *array) {
 static ANN Type check_exp_slice(const Env env, const Exp_Slice *range) {
   CHECK_OO(check_exp(env, range->base));
   CHECK_BO(check_range(env, range->range));
-  const Symbol     sym = insert_symbol("@slice");
-  const Exp        e   = range->range->start ?: range->range->end;
+  const Symbol sym = insert_symbol("@slice");
+  const Exp    e   = range->range->start ?: range->range->end;
+  assert(e);
   struct Op_Import opi = {.op   = sym,
                           .lhs  = e->type,
                           .rhs  = range->base->type,
@@ -744,10 +746,10 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
     free_scope(env->gwion->mp, env->curr->info->value);
     env->curr->info->value = l->def->base->values;
     if (env->class_def) set_vflag(l->def->base->func->value_ref, vflag_member);
+    exp->func->type = l->def->base->func->value_ref->type;
+    if (!l->def->base->ret_type)
+      l->def->base->ret_type = env->gwion->type[et_void];
   }
-  exp->func->type = l->def->base->func->value_ref->type;
-  if (!l->def->base->ret_type)
-    l->def->base->ret_type = env->gwion->type[et_void];
   return ret > 0 ? l->def->base->ret_type : NULL;
 }
 
@@ -1573,7 +1575,8 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) {
   if (ret > 0) {
     set_fflag(fdef->base->func, fflag_valid);
     if (env->class_def && fdef->base->effects.ptr &&
-        !check_effect_overload(&fdef->base->effects, override->d.func_ref))
+        (override &&
+         !check_effect_overload(&fdef->base->effects, override->d.func_ref)))
       ERR_B(fdef->base->pos, _("too much effects in override."),
             s_name(fdef->base->xid))
   }
index b3309684c845bc0b386219b711beecdf9bca71d1..63fd2aab0427d7745ba21b16ed5c0722c48c3eb2 100644 (file)
@@ -404,12 +404,13 @@ ANN static m_bool scan1_args(const Env env, Arg_List list) {
       UNSET_FLAG(list->td, late);
     }
     var->value = arg_value(env, list);
-    nspc_add_value(env->curr, var->xid, var->value);
+    if (var->xid) nspc_add_value(env->curr, var->xid, var->value);
   } while ((list = list->next));
   return GW_OK;
 }
 
 ANN static Type scan1_noret(const Env env, const Func_Base *base) {
+  assert(base->td);
   DECL_OO(const Type, t, = known_type(env, base->td));
   if (!tflag(t, tflag_noret)) return t;
   ERR_O(base->pos, _("Can't use type `{+G}%s{0}` for return"), t->name);
@@ -542,6 +543,7 @@ ANN static m_bool scan1_stmt_list(const Env env, Stmt_List l) {
 }
 
 ANN static m_bool class_internal(const Env env, const Func_Base *base) {
+  assert(base->td);
   if (!env->class_def)
     ERR_B(base->td->pos, _("'%s' must be in class def!!"), s_name(base->xid))
   if (base->args)
@@ -554,12 +556,14 @@ ANN static m_bool class_internal(const Env env, const Func_Base *base) {
 ANN static inline m_bool scan_internal_arg(const Env        env,
                                            const Func_Base *base) {
   if (base->args && !base->args->next) return GW_OK;
+  assert(base->td);
   ERR_B(base->td->pos, _("'%s' must have one (and only one) argument"),
         s_name(base->xid))
 }
 
 ANN static inline m_bool scan_internal_int(const Env        env,
                                            const Func_Base *base) {
+  assert(base->td);
   CHECK_BB(scan_internal_arg(env, base));
   if (isa(base->ret_type, env->gwion->type[et_int]) > 0) return GW_OK;
   ERR_B(base->td->pos, _("'%s' must return 'int'"), s_name(base->xid))
index edd08535e056b0ffcfecc49b6b8c0de4771a85cf..5075d1148235b46adf86b3729a3382e1d7596dd0 100644 (file)
@@ -48,17 +48,28 @@ ANN static inline void shred_unwind(const VM_Shred shred) {
 }
 
 ANN static bool unwind(VM_Shred shred, const Symbol effect, const m_uint size) {
+  const VM_Code code = shred->code;
+  if (code->live_values.ptr) {
+    const uint16_t pc = shred->pc;
+    for (m_uint i = 0; i < m_vector_size(&code->live_values); i++) {
+      VMValue *vmval = (VMValue *)m_vector_addr(&code->live_values, i);
+      if (pc < vmval->start) break;
+      if (pc > vmval->end) continue;
+      m_bit *const data = &*(m_bit *)(shred->mem + vmval->offset);
+      compound_release(shred, vmval->t, data);
+    }
+  }
   if (!size) return true;
-  if (shred->code->handlers.ptr) {
+  if (code->handlers.ptr) {
     const m_uint start = VKEY(&shred->info->frame, size - 1);
     if (start > shred->pc) return true;
-    const Map m  = &shred->code->handlers;
+    const Map m  = &code->handlers;
     m_uint    pc = 0;
     for (m_uint i = 0; i < map_size(m); i++) {
       if (start > shred->pc) break;
       if (start < shred->pc && VKEY(m, i) > shred->pc) {
         const m_uint next  = VKEY(m, i);
-        const Instr  instr = (Instr)vector_at(&shred->code->instr, next + 1);
+        const Instr  instr = (Instr)vector_at(&code->instr, next + 1);
         if (!instr->m_val2 || (Symbol)instr->m_val2 == effect) {
           pc = next + 1;
           break;
@@ -124,13 +135,17 @@ ANN void handle(VM_Shred shred, const m_str effect) {
   vm_shred_exit(shred);
 }
 
-void vm_remove(const VM *vm, const m_uint index) {
+ANN bool vm_remove(const VM *vm, const m_uint index) {
   const Vector v = (Vector)&vm->shreduler->shreds;
   LOOP_OPTIM
   for (m_uint i = vector_size(v) + 1; --i;) {
     const VM_Shred sh = (VM_Shred)vector_at(v, i - 1);
-    if (sh && sh->tick->xid == index) handle(sh, "MsgRemove");
+    if (sh && sh->tick->xid == index) {
+      handle(sh, "MsgRemove");
+      return true;
+    }
   }
+  return false;
 }
 
 ANN void free_vm(VM *vm) {
index 956f47083a1a28bea0c6e6aacf3742a84a47462d..b82334122d0a0b712986a5e5e2111878b7968ba4 100644 (file)
@@ -34,6 +34,7 @@ ANN void free_vmcode(VM_Code a, Gwion gwion) {
       free_code_instr(&a->instr, gwion);
     }
     if (a->handlers.ptr) map_release(&a->handlers);
+    if (a->live_values.ptr) m_vector_release(&a->live_values);
     vector_release(&a->instr);
   }
   free_mstr(gwion->mp, a->name);
@@ -151,8 +152,9 @@ ANN static m_bit *tobytecode(MemPool p, const VM_Code code) {
   return final;
 }
 
-VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth,
-                   const int builtin, const m_str name) {
+VM_Code new_vmcode(MemPool p, const Vector instr, const M_Vector live_values,
+                   const m_str name, const uint16_t stack_depth,
+                   const bool builtin) {
   VM_Code code = mp_calloc(p, VM_Code);
   code->name   = mstrdup(p, name);
   if (instr) {
@@ -160,6 +162,7 @@ VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth,
     vector_copy2(instr, &code->instr);
     code->bytecode = tobytecode(p, code);
   }
+  if (live_values) code->live_values.ptr = live_values->ptr;
   code->stack_depth = stack_depth;
   code->builtin     = builtin;
   code->ref         = 1;
@@ -171,12 +174,12 @@ VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth,
 VM_Code vmcode_callback(MemPool mp, VM_Code base) {
   char name[strlen(base->name) + 11];
   sprintf(name, "%s(callback)", base->name);
-  const Instr instr = (Instr)vector_back(&base->instr);
-  instr->opcode     = eEOC;
-  const VM_Code code =
-      new_vmcode(mp, &base->instr, base->stack_depth, base->builtin, name);
-  code->closure  = base->closure;
-  code->callback = 1;
-  instr->opcode  = eFuncReturn;
+  const Instr instr  = (Instr)vector_back(&base->instr);
+  instr->opcode      = eEOC;
+  const VM_Code code = new_vmcode(mp, &base->instr, &base->live_values, name,
+                                  base->stack_depth, base->builtin);
+  code->closure      = base->closure;
+  code->callback     = 1;
+  instr->opcode      = eFuncReturn;
   return code;
 }
diff --git a/util b/util
index 7364841ef46d456037eec97cdcb3ff3abb41289d..f194f41413c7591d952e1abb399f60ca1da0715c 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 7364841ef46d456037eec97cdcb3ff3abb41289d
+Subproject commit f194f41413c7591d952e1abb399f60ca1da0715c