]> Nishi Git Mirror - gwion.git/commitdiff
:bomb: Big commit (missing fork)
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Mon, 4 May 2020 21:22:37 +0000 (23:22 +0200)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Mon, 4 May 2020 21:22:37 +0000 (23:22 +0200)
45 files changed:
ast
examples/fork.gw [deleted file]
include/driver.h
include/env/env.h
include/env/envset.h [new file with mode: 0644]
include/env/tuple.h
include/env/type.h
include/gwion_env.h
include/import/checker.h
include/import/internals.h
include/object.h
include/opcode.h
include/template.h
opcode.txt
src/emit/emit.c
src/env/env.c
src/env/env_utils.c
src/env/envset.c [new file with mode: 0644]
src/env/tupleform.c
src/env/type.c
src/import/cdef.c
src/import/checker.c
src/lib/array.c
src/lib/engine.c
src/lib/func.c
src/lib/instr.c
src/lib/object.c
src/lib/object_op.c
src/lib/ptr.c
src/lib/shred.c
src/main.c
src/parse/check.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/template.c
src/parse/type_decl.c
src/vm/shreduler.c
src/vm/vm.c
tests/error/no_namespace.gw [new file with mode: 0644]
tests/tree/fork_clean.gw [deleted file]
tests/tree/fork_in_fork.gw [deleted file]
tests/tree/fork_join.gw [deleted file]
tests/tree/fork_join2.gw [deleted file]
util

diff --git a/ast b/ast
index 50ab3bf5f4dbbbc493e382d0a74cd8a9cd6f2b7b..a65a350359e30f6b8da0af1ba98d282fc9ea1b2f 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 50ab3bf5f4dbbbc493e382d0a74cd8a9cd6f2b7b
+Subproject commit a65a350359e30f6b8da0af1ba98d282fc9ea1b2f
diff --git a/examples/fork.gw b/examples/fork.gw
deleted file mode 100644 (file)
index 63256ea..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-fork {
-  <<< "start" >>>;
-  12::samp => now;
-  me.test_cancel();
-  <<< "stop" >>>;
-} @=> Fork ref f;
-
-1 => f.set_cancel;
-2::samp => now;
-0 => f.set_cancel;
-f.join();
index af2a71b6128a304caa6993b652f5879fbf1646db..06b20f52f8a2937079105d4b8eb0eee60822312f 100644 (file)
@@ -16,7 +16,7 @@ typedef void (*f_bbqset)(struct DriverData_*);
 typedef void (*f_bbqrun)(const struct VM_*);
 
 typedef struct BBQ_ {
-  uint64_t pos;
+  volatile uint64_t pos;
   m_float* in;
   m_float* out;
   struct SoundInfo_ *si;
@@ -27,7 +27,7 @@ typedef struct BBQ_ {
 } Driver;
 
 #define DRVINI(a) ANN m_bool a(struct VM_ *vm NUSED, Driver* di NUSED)
-#define DRVRUN(a) ANN void   a(struct VM_ *vm NUSED, Driverdi NUSED)
+#define DRVRUN(a) ANN void   a(struct VM_ *vm NUSED, Driver *di NUSED)
 #define DRVDEL(a) ANN void   a(struct VM_ *vm NUSED, Driver* di NUSED)
 
 ANN void dummy_driver(DriverData*);
index 7b05267cfd40ee01ab273af5143ef2b979095988..1615a0fd8414cfa30830d7e29bbcddf2d34c6561 100644 (file)
@@ -34,19 +34,20 @@ ANN2(1,3) m_uint env_push(const Env, const Type, const Nspc);
 ANN static inline m_uint env_push_global(const Env env) { return env_push(env, NULL, env->global_nspc); }
 ANN void env_pop(const Env, const m_uint);
 ANN Map env_label(const Env);
-ANN Type scan_type(const Env, const Type, const Type_Decl*);
-ANN Type type_decl_resolve(const Env, const Type_Decl*);
+ANN Type scan_type(const Env, const Type, Type_Decl*);
+//ANN Type type_decl_resolve(const Env, const Type_Decl*);
+ANN Type type_decl_resolve(const Env, Type_Decl*);
 ANN Value mk_class(const Env env, const Type base);
 // tl2str returns a mp_alloced string
 ANEW ANN m_str tl2str(const Env, const Type_List); // in type_decl.c
 ANN m_bool compat_func(const __restrict__ Func_Def, const __restrict__ Func_Def);
-ANN Type known_type(const Env env, const Type_Decl*);
+ANN Type known_type(const Env env, Type_Decl*);
 ANN Type type_nonnull(const Env env, const Type base);
 ANN Type prim_ref(const Env env, const Type t, const Type_Decl* td);
 ANN m_bool env_access(const Env env, const ae_flag flag, const loc_t pos);
 ANN m_bool env_storage(const Env env, ae_flag flag, const loc_t pos);
 ANN void env_add_type(const Env, const Type);
-ANN Type find_type(const Env, ID_List);
+ANN Type find_type(const Env, Type_Decl*);
 ANN m_bool already_defined(const Env env, const Symbol s, const loc_t pos);
 ANN m_bool type_engine_check_prog(const Env, const Ast);
 ANN m_bool traverse_func_template(const Env, const Func_Def);
diff --git a/include/env/envset.h b/include/env/envset.h
new file mode 100644 (file)
index 0000000..e6d5498
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __ENVSET
+#define __ENVSET
+
+typedef m_bool (*envset_func)(const void*,const void*);
+struct EnvSet {
+  const Env env;
+  const envset_func func;
+  const void *data;
+  const m_int scope;
+  const ae_flag flag;
+  m_bool run;
+};
+
+ANN m_bool envset_run(struct EnvSet *es, const Type t);
+ANN m_bool envset_push(struct EnvSet *es, const Type t);
+ANN void   envset_pop(struct EnvSet *es, const Type t);
+#endif
index b4af992b0e8954e9a48dad1a097cb6cfe653a9be..a39d2b7d11b13aaf7b59989f9502b68e5f5e89db 100644 (file)
@@ -8,7 +8,7 @@ struct TupleForm_ {
 };
 
 ANN Type tuple_type(const Env, const Vector, const loc_t);
-ANN void tuple_info(const Env, Type_Decl*, const Var_Decl);
+ANN void tuple_info(const Env, const Value);
 ANN2(1) TupleForm new_tupleform(MemPool p, const Type parent_type);
 ANN void free_tupleform(const TupleForm tuple);
 
index 874bdf7fdf1bc7a2d9a010859bc3a498392d15e5..5f4ce8262787a47e549a0ce7b9da2d97285e33aa 100644 (file)
@@ -2,14 +2,14 @@
 #define __TYPE
 
 struct TypeInfo_ {
-  Type      parent;
-  Nspc      owner;
+  Type parent;
+  Nspc owner;
+  Type owner_class;
   Class_Def def;
   union type_data {
     Func      func;
     Type      base_type;
   } d;
-  struct Vector_ contains;
   struct TupleForm_* tuple;
   struct VM_Code_ *gack;
   struct Context_ *ctx;
index 0c53207f3981455477612f3ad2a68e56aaa15752..61762f1835c3e73e22d473915ceec6aa1dfc2c72 100644 (file)
@@ -10,4 +10,5 @@
 #include "env/func.h"
 #include "env/context.h"
 #include "env/tuple.h"
+#include "env/envset.h"
 #endif
index 52e8b7a39295c8670a4727a1a59f78d9f26db3ab..4465172a866a01364c9c04ad38acf6330e106d69 100644 (file)
@@ -43,20 +43,11 @@ typedef struct OperCK { // name_checker ?
   m_str rhs;// oper
 } OperCK;
 
-struct array_checker {
-  m_str str;
-  Exp base, exp;
-  m_uint depth;
-  m_uint sz;
-  m_bool is_exp;
-};
-
 ANN void func_checker_clean(const Gwi gwi, struct ImportCK *ck);
 ANN m_bool check_typename_def(const Gwi gwi, struct ImportCK *ck);
 ANN ID_List tmpl_valid(const Gwi gwi, const m_str str);
 ANN Symbol str2sym(const Gwi gwi, const m_str path);
 ANN ID_List str2symlist(const Gwi gwi, const m_str path);
-ANN ID_List ck2list(const Gwi gwi, struct array_checker *ck);
 
 ANN m_bool ck_ini(const Gwi, const enum importck_type);
 ANN m_bool ck_ok(const Gwi, const enum importck_type);
index d014f5c6964c07d7e8a841118e0fa52ed73c6fec..fc58056c92d30ffc8612a692484e2c497e763d0d 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef __IMPORT_INTERNALS
 #define __IMPORT_INTERNALS
 
-#define GWI_ERR_B(a,...) { env_err(gwi->gwion->env, gwi->loc, (a), ## __VA_ARGS__); return GW_ERROR; }
-#define GWI_ERR_O(a,...) { env_err(gwi->gwion->env, gwi->loc, (a), ## __VA_ARGS__); return NULL; }
+#define GWI_ERR(a,...) { env_err(gwi->gwion->env, gwi->loc, (a), ## __VA_ARGS__); }
+#define GWI_ERR_B(a,...) { GWI_ERR((a), ## __VA_ARGS__); return GW_ERROR; }
+#define GWI_ERR_O(a,...) { GWI_ERR((a), ## __VA_ARGS__); return NULL; }
 #define ENV_ERR_B(pos, a,...) { env_err(env, pos, (a), ## __VA_ARGS__); return GW_ERROR; }
 #define ENV_ERR_O(pos, a,...) { env_err(env, pos, (a), ## __VA_ARGS__); return NULL; }
 
index 00f76e7fa6dacb97524f993ba7cff8d436a49bf8..dfad90a531cc9436fc47ca23e6e5bfd2d3245f88 100644 (file)
@@ -5,7 +5,7 @@ struct M_Object_ {
   m_bit* data;
   Type type_ref;
   Vector vtable;
-  /* volatile */size_t ref;
+  volatile size_t ref;
 };
 
 ANN void instantiate_object(const VM_Shred, const Type);
@@ -21,6 +21,7 @@ ANN void fork_launch(VM const*, const M_Object, const m_uint);
 ANN void __release(const M_Object, const VM_Shred);
 ANN void exception(const VM_Shred, const m_str);
 ANN void broadcast(const M_Object);
+
 #define STRING(o)    (*(m_str*)    ((M_Object)o)->data)
 #define ME(o)        (*(VM_Shred*) ((M_Object)o)->data)
 #define EV_SHREDS(o) (*(Vector*)   ((M_Object)o)->data)
index 1dc0439555fede0d31ccef6761667f7a04c62ff0..2b33fe5be67c8c5bc82f0d404ea1455253735e3b 100644 (file)
@@ -130,10 +130,10 @@ enum {
   eFuncUsrEnd,
   eFuncMemberEnd,
   eSporkIni,
+  eForkIni,
   eSporkFunc,
   eSporkMemberFptr,
   eSporkExp,
-  eForkEnd,
   eSporkEnd,
   eBranchEqInt,
   eBranchNeqInt,
@@ -308,10 +308,10 @@ enum {
 #define  FuncUsrEnd          (f_instr)eFuncUsrEnd
 #define  FuncMemberEnd       (f_instr)eFuncMemberEnd
 #define  SporkIni            (f_instr)eSporkIni
+#define  ForkIni             (f_instr)eForkIni
 #define  SporkFunc           (f_instr)eSporkFunc
 #define  SporkMemberFptr     (f_instr)eSporkMemberFptr
 #define  SporkExp            (f_instr)eSporkExp
-#define  ForkEnd             (f_instr)eForkEnd
 #define  SporkEnd            (f_instr)eSporkEnd
 #define  BranchEqInt         (f_instr)eBranchEqInt
 #define  BranchNeqInt        (f_instr)eBranchNeqInt
index b8db06a204bce7e1debe53dc533ef53e147ac53f..df61fe13569a5168a7316c2a66a95baa077833a1 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __TEMPLATE
 #define __TEMPLATE
 ANN m_bool template_push_types(const Env, const Tmpl*);
+ANN m_bool template_push(const Env env, const Type t);
 ANN Tmpl* mk_tmpl(const Env, const Tmpl*, const Type_List);
 #define POP_RET(a) { nspc_pop_type(env->gwion->mp, env->curr); return (a); }
 #endif
index 8c1b8863f269f644f6dc25b23a47f9fcc34724ed..62c4fb4b281f79d9b12513b04929475d4382a625 100644 (file)
@@ -127,10 +127,10 @@ Overflow
 FuncUsrEnd
 FuncMemberEnd
 SporkIni
+ForkIni
 SporkFunc
 SporkMemberFptr
 SporkExp
-ForkEnd
 SporkEnd
 BranchEqInt
 BranchNeqInt
index f7988a8718c377312d06379e73a78188dc572d55..93096d75e63017d0e1c6276ec49c1d5611a41a5c 100644 (file)
@@ -491,6 +491,16 @@ ANN static inline void struct_interp(const Emitter emit, const Exp e) {
   }
 }
 
+ANN static void interp_multi(const Emitter emit, Var_Decl_List list) {
+  m_uint offset = 0;
+  while(list->next) {
+    offset += SZ_INT;
+    list = list->next;
+  }
+  if(offset)
+    regpop(emit, offset);
+}
+
 ANN static m_bool emit_interp(const Emitter emit, const Exp exp) {
   regpushi(emit, 0);
   Exp e = exp, next = NULL;
@@ -502,8 +512,11 @@ ANN static m_bool emit_interp(const Emitter emit, const Exp exp) {
       e->next = next;
       return GW_ERROR;
     }
+    const m_bool isobj = isa(e->info->type, emit->gwion->type[et_object]) > 0;
+    if(isobj && e->exp_type == ae_exp_decl) // why only objects?
+      interp_multi(emit, e->d.exp_decl.list);
     regseti(emit, (m_uint)e->info->type);
-    if(isa(e->info->type, emit->gwion->type[et_object]) > 0 && !GET_FLAG(e->info->type, force))
+    if(isobj && !GET_FLAG(e->info->type, force))
       emit_add_instr(emit, GackType);
     const Instr instr = emit_add_instr(emit, Gack);
     instr->m_val = emit_code_offset(emit);
@@ -582,8 +595,7 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *d
   const Array_Sub array = var_decl->array;
   const m_bool is_array = (array && array->exp) || GET_FLAG(decl->td, force);
   const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
-  const uint emit_addr = ((is_ref && !array) || isa(type, emit->gwion->type[et_object]) < 0) ?
-    emit_var : 1;
+  const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1;
   if(is_obj && (is_array || !is_ref))
     CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
   f_instr *exec = (f_instr*)allocmember;
@@ -618,11 +630,9 @@ ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
   const Array_Sub array = var_decl->array;
   const m_bool is_array = array && array->exp;
   const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
-  const uint emit_addr = ((is_ref && !array) || isa(type, emit->gwion->type[et_object]) < 0) ?
-    emit_var : 1;
+  const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1;
   if(is_obj && (is_array || !is_ref))
     CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
-//  const Instr instr = emit_kind(emit, v->type->size, emit_addr, dotstatic);
   const Instr instr = emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, dotstatic);
   v->d.ptr = mp_calloc2(emit->gwion->mp, v->type->size);
   SET_FLAG(v, union);
@@ -645,9 +655,10 @@ ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
 ANN static m_bool emit_class_def(const Emitter, const Class_Def);
 ANN static m_bool emit_cdef(const Emitter, const Class_Def);
 
-ANN static inline m_bool emit_exp_decl_template(const Emitter emit, const Exp_Decl* decl) {
-  const Type t = get_type(decl->type);
-  return !GET_FLAG(t, emit) ? emit_cdef(emit, t->e->def) : GW_OK;
+ANN static inline m_bool ensure_emit(const Emitter emit, const Type t) {
+  struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
+    .scope=emit->env->scope->depth, .flag=ae_flag_emit };
+  return envset_run(&es, t);
 }
 
 ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) {
@@ -670,8 +681,9 @@ ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) {
 }
 
 ANN /*static */m_bool emit_exp_decl(const Emitter emit, const Exp_Decl* decl) {
-  if(GET_FLAG(decl->type, template))
-    CHECK_BB(emit_exp_decl_template(emit, decl))
+  const Type t = get_type(decl->type);
+  if(!GET_FLAG(t, emit) && t->e->def)
+    CHECK_BB(ensure_emit(emit, t))
   const m_bool global = GET_FLAG(decl->td, global);
   const m_uint scope = !global ? emit->env->scope->depth : emit_push_global(emit);
   const m_bool ret = emit_decl(emit, decl);
@@ -828,8 +840,15 @@ ANN static inline m_bool traverse_emit_func_def(const Emitter emit, const Func_D
 }
 
 ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt) {
-  const m_uint scope = emit_push(emit, dt->owner_class, dt->owner);
+  const m_uint scope = emit->env->scope->depth;
+  struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
+    .scope=scope, .flag=ae_flag_emit };
+  if(dt->owner_class)
+    envset_push(&es, dt->owner_class);
+  (void)emit_push(emit, dt->owner_class, dt->owner);
   const m_bool ret = traverse_emit_func_def(emit, dt->def);
+  if(dt->owner_class && dt->owner_class->e->owner_class)
+    envset_pop(&es, dt->owner_class->e->owner_class);
   emit_pop(emit, scope);
   return ret;
 }
@@ -862,8 +881,15 @@ static inline m_bool push_func_code(const Emitter emit, const Func f) {
 
 ANN static m_bool emit_template_code(const Emitter emit, const Func f) {
   const Value v = f->value_ref;
-  size_t scope = emit_push(emit, v->from->owner_class, v->from->owner);
+  size_t scope = emit->env->scope->depth;
+  struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
+    .scope=scope, .flag=ae_flag_emit };
+  if(v->from->owner_class)
+    envset_push(&es, v->from->owner_class);
+  (void)emit_push(emit, v->from->owner_class, v->from->owner);
   const m_bool ret = emit_func_def(emit, f->def);
+  if(v->from->owner_class && v->from->owner_class->e->owner_class)
+    envset_pop(&es, v->from->owner_class->e->owner_class);
   emit_pop(emit, scope);
   return ret > 0 ? push_func_code(emit, f) : GW_ERROR;
 }
@@ -1087,13 +1113,10 @@ ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
 }
 
 ANN void spork_code(const Emitter emit, const struct Sporker *sp) {
-  if(sp->is_spork) {
-    const Instr instr = emit_add_instr(emit, SporkExp);
-    instr->m_val = emit->code->stack_depth;
-  } else {
-    const Instr instr = emit_add_instr(emit, ForkEnd);
-    instr->m_val = sp->emit_var;
-  }
+  const Instr args = emit_add_instr(emit, SporkExp);
+  args->m_val = emit->code->stack_depth;
+  const Instr instr = emit_add_instr(emit, SporkEnd);
+  instr->m_val = sp->emit_var;
 }
 
 ANN void spork_func(const Emitter emit, const struct Sporker *sp) {
@@ -1105,14 +1128,20 @@ ANN void spork_func(const Emitter emit, const struct Sporker *sp) {
     spork->m_val = depth;
   } else
     emit_exp_spork_finish(emit, f->def->stack_depth);
-  const Instr end = emit_add_instr(emit, sp->is_spork ? SporkEnd : ForkEnd);
-  end->m_val2 = f->def->base->ret_type->size;
+  (void)emit_add_instr(emit, SporkEnd);
 }
 
 ANN static Instr spork_ini(const Emitter emit, const struct Sporker *sp) {
-  const Instr instr = emit_add_instr(emit, SporkIni);
+  if(sp->is_spork) {
+    const Instr instr = emit_add_instr(emit, SporkIni);
+    instr->m_val = (m_uint)sp->vm_code;
+    instr->m_val2 = sp->is_spork;
+    return instr;
+  }
+  const Func f = !sp->code ? sp->exp->d.exp_call.m_func : NULL;
+  const Instr instr = emit_add_instr(emit, ForkIni);
   instr->m_val = (m_uint)sp->vm_code;
-  instr->m_val2 = sp->is_spork;
+  instr->m_val2 = f ? f->def->base->ret_type->size : 0;
   return instr;
 }
 
@@ -1134,9 +1163,7 @@ ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) {
   struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary, .op_type=op_unary };
   if(unary->op != insert_symbol("spork") && unary->op != insert_symbol("fork") && unary->exp) {
     CHECK_BB(emit_exp_pop_next(emit, unary->exp))
-const Exp next = unary->exp->next;
     emit_exp_addref(emit, unary->exp, -exp_size(unary->exp));
-unary->exp->next = next;
     opi.rhs = unary->exp->info->type;
   }
   return op_emit_bool(emit, &opi);
@@ -1185,11 +1212,13 @@ ANN static m_bool emit_exp_lambda(const Emitter emit, const Exp_Lambda * lambda)
     regpushi(emit, SZ_INT);
     return GW_OK;
   }
-  const m_uint scope = !lambda->owner ?
-    emit->env->scope->depth : emit_push_type(emit, lambda->owner);
+  struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
+    .scope=emit->env->scope->depth, .flag=ae_flag_emit };
+  if(lambda->owner)
+    envset_push(&es, lambda->owner);
   const m_bool ret = emit_lambda(emit, lambda);
   if(lambda->owner)
-    emit_pop(emit, scope);
+    envset_push(&es, lambda->owner);
   return ret;
 }
 
@@ -1328,11 +1357,8 @@ ANN static void emit_pop_stack(const Emitter emit, const m_uint index) {
   emit_pop_scope(emit);
 }
 
-// scope push problem
-ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
-  const m_uint index = emit_code_size(emit);
+ANN static m_bool _emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt, const m_uint index) {
   Instr op = NULL;
-  emit_push_stack(emit);
   if(!stmt->is_do)
     op = _flow(emit, stmt->cond, stmt_self(stmt)->stmt_type == ae_stmt_while);
   CHECK_BB(scoped_stmt(emit, stmt->body, 1))
@@ -1344,10 +1370,17 @@ ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
     goto_->m_val = index;
     op->m_val = emit_code_size(emit);
   }
-  emit_pop_stack(emit, index);
   return GW_OK;
 }
 
+ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
+  const m_uint index = emit_code_size(emit);
+  emit_push_stack(emit);
+  const m_bool ret = _emit_stmt_flow(emit, stmt, index);
+  emit_pop_stack(emit, index);
+  return ret;
+}
+
 ANN static Instr variadic_state0(const Emitter emit, const Stmt_VarLoop stmt) {
   CHECK_BO(emit_exp(emit, stmt->exp))
   return emit_add_instr(emit, BranchEqInt);
@@ -1379,14 +1412,12 @@ ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt)
   return GW_OK;
 }
 
-// scope push problem
-ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
-  emit_push_stack(emit);
+ANN static m_bool _emit_stmt_for(const Emitter emit, const Stmt_For stmt, m_uint *action_index) {
   CHECK_BB(emit_stmt(emit, stmt->c1, 1))
   const m_uint index = emit_code_size(emit);
   const Instr op = emit_flow(emit, stmt->c2->d.stmt_exp.val);
   CHECK_BB(scoped_stmt(emit, stmt->body, 1))
-  const m_uint action_index = emit_code_size(emit);
+  *action_index = emit_code_size(emit);
   if(stmt->c3) {
     CHECK_BB(emit_exp(emit, stmt->c3))
     pop_exp(emit, stmt->c3);
@@ -1394,10 +1425,17 @@ ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
   const Instr _goto = emit_add_instr(emit, Goto);
   _goto->m_val = index;
   op->m_val = emit_code_size(emit);
-  emit_pop_stack(emit, action_index);
   return GW_OK;
 }
 
+ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
+  emit_push_stack(emit);
+  m_uint action_index;
+  const m_bool ret = _emit_stmt_for(emit, stmt, &action_index);
+  emit_pop_stack(emit, action_index);
+  return ret;
+}
+
 ANN static Instr emit_stmt_autoptr_init(const Emitter emit, const Type type) {
   const Instr new_obj = emit_add_instr(emit, ObjectInstantiate);
   new_obj->m_val2 = (m_uint)type;
@@ -1406,11 +1444,8 @@ ANN static Instr emit_stmt_autoptr_init(const Emitter emit, const Type type) {
   return emit_add_instr(emit, Reg2Mem);
 }
 
-// scope push problem
-ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
-  CHECK_BB(emit_exp(emit, stmt->exp))
+ANN static m_bool _emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt, m_uint *end_pc) {
   const Instr s1 = emit_add_instr(emit, MemSetImm);
-  emit_push_stack(emit);
   Instr cpy = stmt->is_ptr ? emit_stmt_autoptr_init(emit, stmt->v->type) : NULL;
   emit_local(emit, emit->gwion->type[et_int]); // is ptr released?
   const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
@@ -1420,7 +1455,7 @@ ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
   const Instr loop = emit_add_instr(emit, stmt->is_ptr ? AutoLoopPtr : AutoLoop);
   const Instr end = emit_add_instr(emit, BranchEqInt);
   CHECK_BB(emit_stmt(emit, stmt->body, 1))
-  const m_uint end_pc = emit_code_size(emit);
+  *end_pc = emit_code_size(emit);
   if(stmt->is_ptr) {
     loop->m_val2 = (m_uint)stmt->v->type;
     cpy->m_val = stmt->v->from->offset;
@@ -1430,15 +1465,21 @@ ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
   tgt->m_val = ini_pc;
   s1->m_val = loop->m_val = offset;
   regpop(emit, SZ_INT);
-  emit_pop_stack(emit, end_pc);
   return GW_OK;
 }
 
-// scope push problem
-ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
+ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
+  CHECK_BB(emit_exp(emit, stmt->exp))
   emit_push_stack(emit);
+  m_uint end_pc;
+  const m_bool ret = _emit_stmt_auto(emit, stmt, &end_pc);
+  emit_pop_stack(emit, end_pc);
+  return ret;
+}
+
+ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt, m_uint *index) {
   CHECK_BB(emit_exp_pop_next(emit, stmt->cond))
-  const m_uint index = emit_code_size(emit);
+  *index = emit_code_size(emit);
   const Instr cpy = emit_add_instr(emit, Reg2RegAddr);
   cpy->m_val2 = -SZ_INT;
   regpush(emit, SZ_INT);
@@ -1446,13 +1487,20 @@ ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
   const Instr op = emit_add_instr(emit, BranchEqInt);
   CHECK_BB(scoped_stmt(emit, stmt->body, 1))
   const Instr _goto = emit_add_instr(emit, Goto);
-  _goto->m_val = index;
+  _goto->m_val = *index;
   op->m_val = emit_code_size(emit);
-  emit_pop_stack(emit, index);
   regpop(emit, SZ_INT);
   return GW_OK;
 }
 
+ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
+  emit_push_stack(emit);
+  m_uint index;
+  const m_bool ret = _emit_stmt_loop(emit, stmt, &index);
+  emit_pop_stack(emit, index);
+  return ret;
+}
+
 ANN static m_bool emit_stmt_jump(const Emitter emit, const Stmt_Jump stmt) {
   if(!stmt->is_label)
     stmt->data.instr = emit_add_instr(emit, Goto);
@@ -1513,7 +1561,7 @@ ANN static m_bool emit_union_def(const Emitter emit, const Union_Def udef) {
   if(udef->xid) {
     union_allocdata(emit->gwion->mp, udef);
     Type_Decl *type_decl = new_type_decl(emit->gwion->mp,
-        new_id_list(emit->gwion->mp, udef->xid, loc_cpy(emit->gwion->mp, udef->pos)));
+        udef->xid, loc_cpy(emit->gwion->mp, udef->pos));
     type_decl->flag = udef->flag;
     const Var_Decl var_decl = new_var_decl(emit->gwion->mp, udef->xid, NULL, loc_cpy(emit->gwion->mp, udef->pos));
     const Var_Decl_List var_decl_list = new_var_decl_list(emit->gwion->mp, var_decl, NULL);
@@ -1654,14 +1702,14 @@ ANN static inline void match_unvec(struct Match_ *const match , const m_uint pc)
 }
 
 ANN static m_bool emit_stmt_cases(const Emitter emit, Stmt_List list) {
-  do CHECK_BB(emit_stmt_match_case(emit, &list->stmt->d.stmt_match)) // beware push
+  do CHECK_BB(emit_stmt_match_case(emit, &list->stmt->d.stmt_match))
   while((list = list->next));
   return GW_OK;
 }
 
 ANN static m_bool emit_match(const Emitter emit, const struct Stmt_Match_* stmt) {
   if(stmt->where)
-    CHECK_BB(emit_stmt(emit, stmt->where, 1)) // beware, we have push scope
+    CHECK_BB(emit_stmt(emit, stmt->where, 1))
   MATCH_INI(emit->env->scope)
   vector_init(&m.vec);
   const m_bool ret = emit_stmt_cases(emit, stmt->list);
@@ -1702,15 +1750,7 @@ ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List l) {
   return GW_OK;
 }
 
-ANN static inline m_bool ensure_emit(const Emitter emit, const Type type) {
-  const Type t = actual_type(emit->gwion, type) ?: type;
-  if(!GET_FLAG(t, emit) && t->e->def)
-    CHECK_BB(emit_class_def(emit, t->e->def))
-  return GW_OK;
-}
-
 ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) {
-  CHECK_BB(ensure_emit(emit, member->t_base))
   struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
     .rhs=exp_self(member)->info->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos, .op_type=op_dot };
   return op_emit_bool(emit, &opi);
@@ -1952,24 +1992,24 @@ ANN static m_bool emit_struct_body2(const Emitter emit, Section *const section)
 ANN static m_bool emit_class_def(const Emitter emit, const Class_Def c) {
   if(tmpl_base(c->base.tmpl))
     return GW_OK;
-  const Class_Def cdef = c->base.type->e->def;
+  const Type t = c->base.type;
+  const Class_Def cdef = t->e->def;
   if(GET_FLAG(cdef->base.type, emit))
     return GW_OK;
-  const Type type = cdef->base.type;
-  const Nspc nspc = type->nspc;
-  if(cdef->base.ext && type->e->parent->e->def && !GET_FLAG(type->e->parent, emit))
+  if(cdef->base.ext && t->e->parent->e->def && !GET_FLAG(t->e->parent, emit))
     CHECK_BB(cdef_parent(emit, cdef))
-  SET_FLAG(type, emit);
+  const Nspc nspc = t->nspc;
+  SET_FLAG(t, emit);
   nspc_allocdata(emit->gwion->mp, nspc);
   if(cdef->body) {
     if(!no_ctor(emit, cdef)) {
-      emit_class_code(emit, type->name);
+      emit_class_code(emit, t->name);
       CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
       emit_class_finish(emit, nspc);
     } else
       CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_struct_body2, emit))
   }
-  SET_FLAG(type, emit);
+  SET_FLAG(t, emit);
   return GW_OK;
 }
 
index ca70b0d5e3dc0fa0b0b7d9a316b6655e1b995107..c0d606b4eb5163d3985734d40c9d2cf2b385cbd7 100644 (file)
@@ -87,8 +87,12 @@ ANN void env_add_type(const Env env, const Type type) {
   const Value v = new_value(env->gwion->mp, v_type, s_name(sym));
   SET_FLAG(v, checked | ae_flag_const | ae_flag_global | ae_flag_builtin);
   nspc_add_value(env->curr, insert_symbol(type->name), v);
+//  valuefrom(env, v->from);
+//  typefrom(env, type->e->from);
+//  v->from->owner = type->e->from->owner = env->curr;
+//  type->e->owner = env->curr;
   v->from->owner = type->e->owner = env->curr;
-  v->from->owner_class = env->class_def;
+  v->from->owner_class = type->e->owner_class = env->class_def; // t owner_class ?
   type->xid = ++env->scope->type_xid;
 }
 
index ae2db2ef1264fa491cfc131c4322374dd7bab9cc..9fa3959644109582143a7fa08c758b955f4a1ba4 100644 (file)
@@ -41,9 +41,8 @@ ANN Type _find_type(const Env env, const Symbol xid) {
   return type;
 }
 
-ANN Type find_type(const Env env, ID_List path) {
-  Type type = _find_type(env, path->xid);
-  CHECK_OO(type)
+ANN Type find_type(const Env env, Type_Decl *path) {
+  DECL_OO(Type, type, = _find_type(env, path->xid))
   Nspc nspc = type->nspc;
   path = path->next;
   while(path) {
@@ -86,10 +85,8 @@ ANN Value mk_class(const Env env, const Type base) {
   const Type t = class_type(env, base);
   const Symbol sym = insert_symbol(base->name);
   const Value v = new_value(env->gwion->mp, t, s_name(sym));
-  // set from
-  v->from->owner = base->e->owner;
+  valuefrom(env, v->from);
   SET_FLAG(v, const | ae_flag_checked);
-  // should we add t to front, too?
   nspc_add_value_front(base->e->owner, sym, v);
   return v;
 }
diff --git a/src/env/envset.c b/src/env/envset.c
new file mode 100644 (file)
index 0000000..a523d77
--- /dev/null
@@ -0,0 +1,54 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "template.h"
+
+ANN static void check(struct EnvSet *es, const Type t) {
+  const Vector v = &es->env->scope->class_stack;
+  Type owner = t->e->owner_class;
+  for(vtype i = vector_size(v); owner && --i;) {
+    if(owner != (Type)vector_at(v, i - 1)) {
+      es->run = 1;
+      return;
+    }
+    owner = owner->e->owner_class;
+  }
+}
+
+ANN m_bool push(struct EnvSet *es, const Type t) {
+  if(t->e->owner_class)
+    CHECK_BB(push(es, t->e->owner_class))
+  if(!(t->flag & es->flag))
+    CHECK_BB(es->func((void*)es->data, t->e->def))
+  if(GET_FLAG(t, template))
+    CHECK_BB(template_push_types(es->env, t->e->def->base.tmpl))
+  env_push_type((void*)es->env, t);
+  return GW_OK;
+}
+
+ANN m_bool envset_push(struct EnvSet *es, const Type t) {
+  check(es, t);
+  if(es->run)
+    CHECK_BB(envset_push(es, t->e->owner_class))
+  return GW_OK;
+}
+
+ANN void envset_pop(struct EnvSet *es, const Type t) {
+  env_pop(es->env, es->scope);
+  if(GET_FLAG(t, template))
+    nspc_pop_type(es->env->gwion->mp, es->env->curr);
+  if(t->e->owner_class)
+    envset_pop(es, t->e->owner_class);
+}
+
+ANN m_bool envset_run(struct EnvSet *es, const Type t) {
+  check(es, t);
+  if(es->run)
+    CHECK_BB(push(es, t->e->owner_class))
+  const m_bool ret = es->func(es->data, t->e->def);
+  if(es->run)
+    envset_pop(es, t->e->owner_class);
+  return ret;
+}
index 8a8aef40dfa94ea95e9142557232e44a8d52f847..f540321737c6abf0ad67640707c87d4e8c007ab1 100644 (file)
 #include "parse.h"
 #include "array.h"
 
-ANN void tuple_info(const Env env, Type_Decl *base, const Var_Decl var) {
-  const Value v = var->value;
+ANN void tuple_info(const Env env, const Value v) {
   const m_uint offset = vector_back(&env->class_def->e->tuple->offset);
   vector_add(&env->class_def->e->tuple->types, (vtype)v->type);
   vector_add(&env->class_def->e->tuple->offset, offset + v->type->size);
-  Type_Decl *td = cpy_type_decl(env->gwion->mp, base);
-  if(var->array)
-    td->array = cpy_array_sub(env->gwion->mp, var->array);
 }
 
 ANN2(1) TupleForm new_tupleform(MemPool p, const Type parent_type) {
index 1249dd30164f69bf68918c68599f668fa02c5e51..564e8f17703b4be29d4ee4550c713e73721202db 100644 (file)
@@ -29,11 +29,6 @@ ANN static void free_type(Type a, Gwion gwion) {
     REM_REF(a->nspc, gwion);
   if(a->e->tuple)
     free_tupleform(a->e->tuple);
-  if(a->e->contains.ptr) {
-    for(m_uint i = 0; i < vector_size(&a->e->contains); ++i)
-      REM_REF((Type)vector_at(&a->e->contains, i), gwion);
-    vector_release(&a->e->contains);
-  }
   mp_free(gwion->mp, TypeInfo, a->e);
   mp_free(gwion->mp, Type, a);
 }
@@ -53,7 +48,8 @@ Type new_type(MemPool p, const m_uint xid, const m_str name, const Type parent)
 ANN Type type_copy(MemPool p, const Type type) {
   const Type a = new_type(p, type->xid, type->name, type->e->parent);
   a->nspc          = type->nspc;
-  a->e->owner         = type->e->owner;
+  a->e->owner       = type->e->owner;
+  a->e->owner_class = type->e->owner_class;
   a->size          = type->size;
   a->e->d.base_type   = type->e->d.base_type;
   a->array_depth   = type->array_depth;
@@ -117,7 +113,7 @@ ANN Type array_type(const Env env, const Type src, const m_uint depth) {
   t->e->owner = src->e->owner;
   ADD_REF((t->nspc = env->gwion->type[et_array]->nspc))
   SET_FLAG(t, checked);
-  mk_class(env, t); // maybe add_type_front could go in mk_class ?
+  mk_class(env, t);
   nspc_add_type_front(src->e->owner, sym, t);
   return t;
 }
index a751416b768d4b36ada9f90a5d68dec116999e04..60a3e5bce803a9cd08bdda9f940a4bd92b88aa67 100644 (file)
@@ -49,8 +49,9 @@ ANN2(1,2) static void import_class_ini(const Env env, const Type t) {
   t->nspc = new_nspc(env->gwion->mp, t->name);
   t->nspc->parent = env->curr;
   if(isa(t, env->gwion->type[et_object]) > 0)
-  inherit(t);
+    inherit(t);
   t->e->owner = env->curr;
+  t->e->owner_class = env->class_def;
   SET_FLAG(t, checked);
   env_push_type(env, t);
 }
@@ -80,8 +81,12 @@ ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str name, const m_str parent
   DECL_OO(Type_Decl *,td, = str2decl(gwi, parent ?: "Object"))
   Tmpl* tmpl = ck.tmpl ? new_tmpl_base(gwi->gwion->mp, ck.tmpl) : NULL;
   if(tmpl)
-    template_push_types(gwi->gwion->env, tmpl);
+    CHECK_BO(template_push_types(gwi->gwion->env, tmpl))
   const Type p = known_type(gwi->gwion->env, td); // check
+  if(!p) {
+    env_pop(gwi->gwion->env, 0);
+    return NULL;
+  }
   if(tmpl)
     nspc_pop_type(gwi->gwion->mp, gwi->gwion->env->curr);
   const Type t = new_type(gwi->gwion->mp, ++gwi->gwion->env->scope->type_xid, s_name(ck.sym), p);
index 58d8b60fa0866fd3d7c31288193157369d405c71..1da445e368cff043edc0a17ea0461a0ead0f2a09 100644 (file)
 #include "import.h"
 #include "gwi.h"
 
-ANN m_bool array_check(const Gwi gwi, struct array_checker *ck);
-
 __attribute__((returns_nonnull))
 ANN static Symbol gwisym(const Gwi gwi, const m_str str) {
   return insert_symbol(gwi->gwion->st, str);
 }
 
-//! check that there is no illegal character in the string
-// TODO: get rid of second argument, make it useless
-ANN static m_bool check_illegal(const char c, const m_uint i) {
-   return isalnum(c) || c == '_' || (!i && c == '@');
+struct td_checker {
+  m_str str;
+};
+
+struct AC {
+  m_str str;
+  Exp base;
+  Exp exp;
+  m_uint depth;
+};
+
+ANN static m_bool ac_run(const Gwi gwi, struct AC *ac);
+ANN static Array_Sub mk_array(MemPool mp, struct AC *ac) {
+  const Array_Sub array = new_array_sub(mp, ac->base);
+  array->depth = ac->depth;
+  return array;
 }
 
-/** convert a string to a symbol, with error checking **/
-ANN Symbol str2sym(const Gwi gwi, const m_str path) {
-  const size_t sz = strlen(path);
-  m_uint i;
-  char curr[sz + 1];
-  for(i = 0; i < sz; ++i) {
-    const char c = path[i];
-    if(c != '.') {
-      if(!check_illegal(c, i))
-        GWI_ERR_O(_("illegal character '%c' in path '%s'."), c, path)
-      curr[i] = c;
-    } else
+
+ANN static Symbol __str2sym(const Gwi gwi, struct td_checker *tdc) {
+  char buf[strlen(tdc->str) + 1];
+  m_str tmp = buf;
+  if(*tdc->str == '@')
+    *tmp++ = *tdc->str++;
+  while(*tdc->str) {
+    const char c = *tdc->str;
+    if(!isalnum(c) && c != '_')
       break;
+    *tmp++ = *tdc->str++;
   }
-  curr[i++] = '\0';
-  return gwisym(gwi, curr);
+  if(tmp == buf)
+    GWI_ERR_O("empty symbol");
+  *tmp = '\0';
+  return gwisym(gwi, buf);
 }
 
-ANN ID_List str2symlist(const Gwi gwi, const m_str path) {
-  DECL_OO(const Symbol, sym, = str2sym(gwi, path))
-  return new_id_list(gwi->gwion->mp, sym, loc(gwi));
+ANN static inline Symbol _str2sym(const Gwi gwi, struct td_checker *tdc, const m_str path) {
+  const Symbol sym = __str2sym(gwi, tdc);
+  if(*tdc->str)
+    GWI_ERR_O(_("illegal character '%c' in path '%s'."), *tdc->str, path)
+  return sym;
 }
 
-ANN ID_List path_valid(const Gwi gwi, const m_str path) {
-  const size_t sz = strlen(path);
-  if(path[0] == '.' || path[sz] == '.')
-    GWI_ERR_O(_("path '%s' must not ini or end with '.'."), path)
-  DECL_OO(const ID_List, list, = str2symlist(gwi, path))
-  if(strlen(s_name(list->xid)) < sz)
-    list->next = path_valid(gwi, path + strlen(s_name(list->xid)));
-  return list;
+/** convert a string to a symbol, with error checking **/
+ANN Symbol str2sym(const Gwi gwi, const m_str path) {
+  struct td_checker tdc = { .str=path };
+  return _str2sym(gwi, &tdc, path);
 }
 
-// similar to import array_sub ?
-ANN Array_Sub ck_array(MemPool mp, const m_uint depth) {
-  if(!depth)
-    return NULL;
-  const Array_Sub array = new_array_sub(mp, NULL);
-  array->depth = depth;
-  return array;
+// only in enum.c
+ANN ID_List str2symlist(const Gwi gwi, const m_str path) {
+  DECL_OO(const Symbol, sym, = str2sym(gwi, path))
+  return new_id_list(gwi->gwion->mp, sym, loc(gwi));
 }
 
 ANN Var_Decl str2var(const Gwi gwi, const m_str path) {
-  struct array_checker ck = { .str=path };
-  CHECK_BO(array_check(gwi, &ck))
-  const m_uint sz = strlen(path);
-  const m_uint len = sz - ck.sz;
-  char curr[len + 1];
-  memcpy(curr, path, len);
-  curr[len] = '\0';
-  DECL_OO(const Symbol, sym, = str2sym(gwi, curr))
-  const Array_Sub array = ck_array(gwi->gwion->mp, ck.depth);
+  struct td_checker tdc = { .str=path };
+  DECL_OO(const Symbol, sym, = __str2sym(gwi, &tdc))
+  struct AC ac = { .str = tdc.str };
+  CHECK_BO(ac_run(gwi, &ac))
+  const Array_Sub array = ac.depth ?
+    mk_array(gwi->gwion->mp, &ac) : NULL;
   return new_var_decl(gwi->gwion->mp, sym, array, loc(gwi));
 }
 
+// only in udef.c
 ANN Var_Decl_List str2varlist(const Gwi gwi, const m_str path) {
   DECL_OO(const Var_Decl, var, = str2var(gwi, path))
   return new_var_decl_list(gwi->gwion->mp, var, NULL);
 }
 
-struct tmpl_checker {
-  const m_str str;
-  ID_List list;
-};
-
-ANN static m_bool tmpl_list(const Gwi gwi, struct tmpl_checker *ck) {
-  m_str s = ck->str;
-  const size_t sz = strlen(s);
-  char c[sz + 1];
-  for(m_uint i = 0; i < sz; ++i) {
-    if(isalnum(s[i]) || s[i] == '_') {
-      c[i] = s[i];
-      continue;
-    }
-    if(s[i] == '~') {
-      if(!i || s[i+1] != '>')
-        break;
-      c[i] = '\0';
-      ck->list = new_id_list(gwi->gwion->mp, gwisym(gwi, c), loc(gwi));
-      return GW_OK;
-    }
-    if(s[i] == ',') {
-      if(!i)break;
-      c[i] = '\0';
-      ck->list = new_id_list(gwi->gwion->mp, gwisym(gwi, c), loc(gwi));
-      struct tmpl_checker _ck = { .str=ck->str + i + 1 };
-      CHECK_BB(tmpl_list(gwi, &_ck))
-      ck->list->next = _ck.list;
-      return GW_OK;
-    }
-    break;
+ANN static ID_List _tmpl_list(const Gwi gwi, struct td_checker *tdc) {
+  DECL_OO(const Symbol, sym, = __str2sym(gwi, tdc))
+  ID_List next = NULL;
+  if(*tdc->str == ',') {
+    ++tdc->str;
+    if(!(next = _tmpl_list(gwi, tdc)) || next == (ID_List)GW_ERROR)
+      return (ID_List)GW_ERROR;
   }
-  return GW_ERROR;
-}
-
-ANN static m_bool tmpl_check(const m_str str) {
-  if(str[0] != '<')
-    return 0; // TODO: make it GW_PASS
-  if(str[1] != '~')
-    return GW_ERROR;
-  return GW_OK;
+  const ID_List list = new_id_list(gwi->gwion->mp, sym, loc(gwi));
+  list->next = next;
+  return list;
 }
 
-ANN static ID_List _tmpl_valid(const Gwi gwi, const m_str str) {
-  const m_bool ret = tmpl_check(str);
-  if(ret == GW_ERROR)
-    return (ID_List)GW_ERROR;
-  if(!ret)
+ANN static ID_List __tmpl_list(const Gwi gwi, struct td_checker *tdc) {
+  if(tdc->str[0] != '<')
     return NULL;
-  struct tmpl_checker ck = { .str=str+2 };
-  if(tmpl_list(gwi, &ck) == GW_ERROR)
+  if(tdc->str[1] != '~')
+    return (ID_List)GW_ERROR;
+  tdc->str += 2;
+  const ID_List list =  _tmpl_list(gwi, tdc);
+  if(list == (ID_List)GW_ERROR)
+    return (ID_List)GW_ERROR;
+  if(tdc->str[0] != '~' || tdc->str[1] != '>') {
+// unfinished template
+    if(list)
+      free_id_list(gwi->gwion->mp, list);
     return (ID_List)GW_ERROR;
-  return ck.list;
-}
-
-ANN ID_List tmpl_valid(const Gwi gwi, const m_str str) {
-  const ID_List ret = _tmpl_valid(gwi, str);
-  if(ret == (ID_List)GW_ERROR)
-    env_err(gwi->gwion->env, gwi->loc, _("invalid templating definition"));
-  return ret;
-}
-
-ANN ID_List ck2list(const Gwi gwi, struct array_checker *ck) {
-  const m_str base = ck->str;
-  CHECK_BO(array_check(gwi, ck))
-  const m_uint sz = strlen(base);
-  const m_uint len = sz - ck->sz;
-  char curr[len + 1];
-  memcpy(curr, base, len);
-  curr[len] = '\0';
-  return path_valid(gwi, curr);
-}
-
-ANN static Type_List str2tl(const Gwi gwi, const m_str s);
-ANN static Type_List _str2tl(const Gwi gwi, const m_str s) {
-  DECL_OO(Type_Decl*, td, = str2decl(gwi, s))
-  return new_type_list(gwi->gwion->mp, td, NULL);
-}
-
-ANN Type_List tlnext(const Gwi gwi, const m_str s, size_t split) {
-  char curr[split+1];
-  memcpy(curr, s, split);
-  curr[split] = '\0';
-  const Type_List tl = _str2tl(gwi, curr);
-  tl->next = str2tl(gwi, s + split + 1);
-  return tl;
-}
-
-struct GetTl {
-  const m_str str;
-  m_uint i;
-  m_uint lvl;
-  const size_t sz;
-};
-
-//! a funtion factory to open/close the template
-#define tl_xxx(name, tgt, op)                             \
-ANN m_bool tl_##name(struct GetTl *gtl, const m_uint i) { \
-  if(!(i < gtl->sz && gtl->str[i] == tgt))                \
-    return GW_ERROR;                                      \
-  op gtl->lvl;                                            \
-  return GW_OK;                                           \
-}
-tl_xxx(open,  '~', ++)
-tl_xxx(close, '>', --)
-
-ANN static Type_List str2tl(const Gwi gwi, const m_str s) {
-  struct GetTl gtl = { .str=s, .sz = strlen(s) };
-  for(m_uint i = 0; i < gtl.sz; ++i) {
-    if(s[i] == '<')
-      CHECK_BO(tl_open(&gtl, ++i))
-    else if(s[i] == '~')
-      CHECK_BO(tl_close(&gtl, ++i))
-    else if(s[i] == ',' && !gtl.lvl)
-      return tlnext(gwi, s, i);
-  }
-  return _str2tl(gwi, s);
-}
-
-//! convert a string to a Type_Decl
-ANN Type_Decl* str2decl(const Gwi gwi, const m_str str) {
-  const ae_flag flag = strncmp(str, "nonnull ", 8) ? ae_flag_none : ae_flag_nonnull;
-  const m_str s = strncmp(str, "nonnull ", 8) ? str : str + 8;
-// we can do better
-  DECL_OO(const m_str, type_name, = get_type_name(gwi->gwion->env, s, 0))
-  struct array_checker ck = { .str=type_name };
-  DECL_OO(const ID_List, id, = ck2list(gwi, &ck))
-  Type_Decl* td = new_type_decl(gwi->gwion->mp, id);
-  const m_str tl_name = get_type_name(gwi->gwion->env, s, 1);
-  if(tl_name) {
-    if(!(td->types = str2tl(gwi, tl_name))) {
-      free_type_decl(gwi->gwion->mp, td);
-      return NULL;
-    }
-  }
-  if(ck.depth) {
-    td->array = new_array_sub(gwi->gwion->mp, ck.exp);
-    td->array->depth = ck.depth;
-  }
-  td->flag |= flag;
-  return td;
-}
-
-ANN static void array_add_exp(struct array_checker *ck, const Exp exp) {
-  if(ck->exp)
-    ck->exp = (ck->exp->next = exp);
-  else
-    ck->base = ck->exp = exp;
-  ++ck->is_exp;
-}
-
-ANN m_bool _array_check(const Gwi gwi, struct array_checker *ck) {
-  const m_str base = ck->str;
-  const size_t sz = strlen(ck->str);
-  char tmp[sz + 1];
-  for(m_uint i = 0; i < sz; ++i) {
-    const char c = ck->str[i];
-    if(c == ']') {
-      const m_bool is_end = ck->str[i + 1] == '\0';
-      if(!is_end && ck->str[i + 1] != '[')
-        break;
-      ck->str += i + 2;
-      ck->sz += i + 2;
-      if(i) {
-        if(!ck->is_exp && ck->depth)
-          break;
-        tmp[i] = '\0';
-        const m_uint num = strtol(tmp, NULL, 10);// migth use &endptr and check errno
-        const Exp exp = new_prim_int(gwi->gwion->mp, num, loc(gwi));
-        array_add_exp(ck, exp);
-      } else {
-        if(ck->is_exp > 0)
-          break;
-      }
-      ++ck->depth;
-      return is_end ? GW_OK : _array_check(gwi, ck);
-    }
-    if(isdigit(c))
-      tmp[i] = c;
-    else
-      GWI_ERR_B(_("invalid subscript '%c' in '%s'"), c, base)
   }
-  GWI_ERR_B(_("incoherent subscript '%s'"), base)
-}
-
-ANN m_bool array_check(const Gwi gwi, struct array_checker *ck) {
-  ck->str = ck->str ? strchr(ck->str, '[') : NULL;
-  if(!ck->str)
-    return GW_OK;
-  ++ck->str;
-  return _array_check(gwi, ck);
+  tdc->str += 2;
+  return list;
 }
 
 ANN m_bool check_typename_def(const Gwi gwi, ImportCK *ck) {
-  const m_str base = ck->name;
-  char str[strlen(base) + 1];
-  const m_str c = strchr(ck->name, '<');
-  memcpy(str, base, strlen(base) - (c ? strlen(c) : 0));
-  str[strlen(base) - (c ? strlen(c) : 0)] = '\0';
-  ck->name = str;
-  CHECK_OB((ck->sym = str2sym(gwi, str)))
-  ID_List tmpl = NULL;
-  if(c && (tmpl = tmpl_valid(gwi, c)) == (ID_List)GW_ERROR)
+  struct td_checker tdc = { .str= ck->name };
+  ID_List il = __tmpl_list(gwi, &tdc);
+  if(il == (ID_List)GW_ERROR)
+    return GW_ERROR;
+  if(!(ck->sym = _str2sym(gwi, &tdc, tdc.str))) {
+    if(il)
+      free_id_list(gwi->gwion->mp, il);
     return GW_ERROR;
-  ck->tmpl = tmpl;
-  ck->name = base;
+  }
+  ck->tmpl = il;
+  ck->name = s_name(ck->sym);
   return GW_OK;
+
 }
 
 ANN m_bool ck_ini(const Gwi gwi, const enum importck_type t) {
@@ -335,3 +177,145 @@ ANN void ck_clean(const Gwi gwi) {
   memset(gwi->ck, 0, sizeof(ImportCK));
 }
 
+ANN Type_Decl* _str2decl(const Gwi gwi, struct td_checker *tdc);
+ANN Type_List __str2tl(const Gwi gwi, struct td_checker *tdc) {
+  Type_Decl *td = _str2decl(gwi, tdc);
+  if(!td)
+    GWI_ERR_O("invalid types");
+  Type_List next = NULL;
+  if(*tdc->str == ',') {
+    ++tdc->str;
+    if(!(next = __str2tl(gwi, tdc))) {
+      free_type_decl(gwi->gwion->mp, td);
+      return NULL;
+    }
+  }
+  return new_type_list(gwi->gwion->mp, td, next);
+}
+
+ANN Type_List td_tmpl(const Gwi gwi, struct td_checker *tdc) {
+  if(*tdc->str != '<')
+    return NULL; // GW_PASS
+  ++tdc->str;
+  if(*tdc->str != '~') {
+    GWI_ERR("invalid character");
+    return (Type_List)GW_ERROR;
+  }
+  ++tdc->str;
+  Type_List tl = __str2tl(gwi, tdc);
+  if(!tl)
+    return (Type_List)GW_ERROR;
+  if(tdc->str[0] != '~' || tdc->str[1] != '>') {
+    free_type_list(gwi->gwion->mp, tl);
+    GWI_ERR("unfinished template");
+    return (Type_List)GW_ERROR;
+  }
+  tdc->str += 2;
+  return tl;
+}
+
+ANN static void ac_add_exp(struct AC *ac, const Exp exp) {
+  if(ac->exp)
+    ac->exp = (ac->exp->next = exp);
+  else
+    ac->base = ac->exp = exp;
+}
+
+
+ANN Type_Decl* _str2decl(const Gwi gwi, struct td_checker *tdc) {
+  Type_List tl = td_tmpl(gwi, tdc);
+  if(tl == (Type_List)GW_ERROR)
+    return NULL;
+  Type_Decl *next = NULL;
+  const Symbol sym = __str2sym(gwi, tdc);
+  if(!sym) {
+    if(tl)
+      free_type_list(gwi->gwion->mp, tl);
+    return NULL;
+  }
+  struct AC ac = { .str = tdc->str };
+  if(ac_run(gwi, &ac) < 0) {
+    if(tl)free_type_list(gwi->gwion->mp, tl);
+    return NULL;
+  }
+  tdc->str = ac.str;
+  if(*tdc->str == '.') {
+    ++tdc->str;
+    if(!(next =  _str2decl(gwi, tdc))) {
+      if(tl)
+        free_type_list(gwi->gwion->mp, tl);
+      if(ac.base)
+        free_exp(gwi->gwion->mp, ac.base);
+      return NULL;
+    }
+  }
+  Type_Decl *td = new_type_decl(gwi->gwion->mp, sym, loc(gwi));
+  td->next = next;
+  if(ac.depth)
+    td->array = mk_array(gwi->gwion->mp, &ac);
+  return td;
+}
+
+ANN Type_Decl* str2decl(const Gwi gwi, const m_str str) {
+  const ae_flag flag = strncmp(str, "nonnull ", 8) ? ae_flag_none : ae_flag_nonnull;
+  struct td_checker tdc = { .str=str };
+  if(flag == ae_flag_nonnull)
+    tdc.str += 8;
+  DECL_OO(Type_Decl *, td, = _str2decl(gwi, &tdc))
+  if(*tdc.str) {
+    free_type_decl(gwi->gwion->mp, td);
+    GWI_ERR_O("excedental character '%c'", *tdc.str);
+  }
+  td->flag |= flag;
+  return td;
+}
+
+ANN static inline m_bool ac_finish(const Gwi gwi, struct AC *ac) {
+  if(*ac->str == ']')
+    return GW_OK;
+  GWI_ERR_B("unfinished array");
+}
+
+ANN static inline m_bool ac_num(const Gwi gwi, const m_int num) {
+  if(num >= 0)
+    return GW_OK;
+  GWI_ERR_B("negative array dimension")
+}
+
+ANN static inline m_bool ac_exp(const Gwi gwi, struct AC *ac) {
+  if(!ac->depth || ac->base)
+    return GW_OK;
+  GWI_ERR_B("malformed array [][...]")
+}
+
+ANN static inline m_bool ac_noexp(const Gwi gwi, struct AC *ac) {
+  if(!ac->exp)
+    return GW_OK;
+  GWI_ERR_B("malformed array [...][]")
+}
+
+ANN static m_bool _ac_run(const Gwi gwi, struct AC *ac) {
+  const m_str str = ac->str;
+  const m_int num = strtol(str, &ac->str, 10);
+  CHECK_BB(ac_finish(gwi, ac))
+  if(str != ac->str) {
+    CHECK_BB(ac_num(gwi, num))
+    CHECK_BB(ac_exp(gwi, ac))
+    const Exp exp = new_prim_int(gwi->gwion->mp, num, loc(gwi));
+    ac_add_exp(ac, exp);
+  } else
+    CHECK_BB(ac_noexp(gwi, ac))
+  ++ac->str;
+  return GW_OK;
+}
+
+ANN static m_bool ac_run(const Gwi gwi, struct AC *ac) {
+  while(*ac->str) {
+    if(*ac->str != '[')
+      break;
+    ++ac->str;
+    CHECK_BB(_ac_run(gwi, ac))
+    ++ac->depth;
+  }
+  return GW_OK;
+}
index 93ca736852ad92636705c9db0006df6b9a4130d2..3d54713a5b722412e6b0cda2a7d180023b4318bb 100644 (file)
@@ -47,12 +47,16 @@ void free_m_vector(MemPool p, M_Vector a) {
   mp_free(p, M_Vector, a);
 }
 
+ANN static inline int is_array(const Type *types, const Type type) {
+  const Type base = array_base(type);
+  return isa(base, types[et_object]) > 0;
+}
+
 static DTOR(array_dtor) {
   const Type t = !GET_FLAG(o->type_ref, nonnull) ?
     o->type_ref : o->type_ref->e->parent;
-  const Type base = array_base(t);
   struct M_Vector_* a = ARRAY(o);
-  if(t->array_depth > 1 || isa(base, shred->info->vm->gwion->type[et_object]) > 0)
+  if(t->array_depth > 1 || is_array(shred->info->vm->gwion->type, t))
     for(m_uint i = 0; i < ARRAY_LEN(a); ++i)
       release(*(M_Object*)(ARRAY_PTR(a) + i * SZ_INT), shred);
   free_m_vector(shred->info->mp, a);
index 2bc1d81738216f229ff2a8c09b3f127e4272c6a3..688f27212bf511ad3f11e51453a72fbb28646557 100644 (file)
@@ -153,7 +153,7 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
 
 ANN m_bool type_engine_init(const Gwion gwion, const Vector plug_dirs) {
   gwion->env->name = "[builtin]";
-  struct loc_t loc = {};
+  struct loc_t_ loc = {};
   OperCK oper = {};
   struct Gwi_ gwi = { .gwion=gwion, .loc=&loc, .oper=&oper };
   CHECK_BB(import_core_libs(&gwi))
index 78ad9eb09523cb98b66bb43490be80b141496800..23df474ae6715e77652ff5e95146d2d25e9d5c16 100644 (file)
@@ -40,7 +40,6 @@ static OP_EMIT(opem_func_assign) {
     fptr_instr(emit, bin->lhs->info->type->e->d.func, 2);
   const Instr instr = emit_add_instr(emit, int_r_assign);
   if(!is_fptr(emit->gwion, bin->lhs->info->type) && GET_FLAG(bin->rhs->info->type->e->d.func, member)) {
-//exit(3);
     const Instr pop = emit_add_instr(emit, LambdaAssign);
     pop->m_val = SZ_INT;
   }
@@ -70,7 +69,7 @@ ANN static m_bool fptr_tmpl_push(const Env env, struct FptrInfo *info) {
 }
 
 
-static m_bool td_match(const Env env, const Type_Decl *id[2]) {
+static m_bool td_match(const Env env, Type_Decl *id[2]) {
   DECL_OB(const Type, t0, = known_type(env, id[0]))
   DECL_OB(const Type, t1, = known_type(env, id[1]))
   return isa(t0, t1);
@@ -80,7 +79,7 @@ ANN static m_bool fptr_args(const Env env, Func_Base *base[2]) {
   Arg_List arg0 = base[0]->args, arg1 = base[1]->args;
   while(arg0) {
     CHECK_OB(arg1)
-    const Type_Decl* td[2] = { arg0->td, arg1->td };
+    Type_Decl* td[2] = { arg0->td, arg1->td };
     CHECK_BB(td_match(env, td))
     arg0 = arg0->next;
     arg1 = arg1->next;
@@ -109,7 +108,7 @@ ANN static m_bool fptr_check(const Env env, struct FptrInfo *info) {
 }
 
 ANN static inline m_bool fptr_rettype(const Env env, struct FptrInfo *info) {
-  const Type_Decl* td[2] = { info->lhs->def->base->td,
+  Type_Decl* td[2] = { info->lhs->def->base->td,
       info->rhs->def->base->td };
   return td_match(env, td);
 }
@@ -165,13 +164,16 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l, const Func_Def def
   }
   return GW_OK;
 }
+
 ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner,
     Exp_Lambda *l, const Func_Def def) {
-  const m_uint scope = ((l->owner = owner)) ?
-    env_push_type(env, owner) : env->scope->depth;
+  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+    .scope=env->scope->depth, .flag=ae_flag_check };
+  if((l->owner = owner))
+    envset_push(&es, owner);
   const m_bool ret = _check_lambda(env, l, def);
-  if(owner)
-    env_pop(env, scope);
+  if(owner && es.run)
+    envset_pop(&es, owner);
   if(ret < 0)
     return GW_ERROR;
   exp_self(l)->info->type = l->def->base->func->value_ref->type;
@@ -238,8 +240,6 @@ static OP_EMIT(opem_fptr_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
   if(exp_self(cast)->info->type->e->d.func->def->base->tmpl)
     fptr_instr(emit, cast->exp->info->type->e->d.func, 1);
-//  if(GET_FLAG(cast->exp->info->type->e->d.func, member) &&
-//    !(GET_FLAG(cast->exp->info->type, nonnull) || GET_FLAG(exp_self(cast)->info->type, nonnull)))
   if(is_member(cast->exp->info->type, exp_self(cast)->info->type))
     member_fptr(emit);
   return (Instr)GW_OK;
@@ -256,8 +256,6 @@ static OP_CHECK(opck_fptr_impl) {
 static OP_EMIT(opem_fptr_impl) {
   struct Implicit *impl = (struct Implicit*)data;
   if(is_member(impl->e->info->type, impl->t))
-//  if(GET_FLAG(impl->e->info->type->e->d.func, member) &&
-//      !(GET_FLAG(impl->e->info->type, nonnull) || GET_FLAG(impl->t, nonnull)))
     member_fptr(emit);
   if(impl->t->e->d.func->def->base->tmpl)
     fptr_instr(emit, ((Exp)impl->e)->info->type->e->d.func, 1);
@@ -284,7 +282,11 @@ static OP_CHECK(opck_spork) {
 
 static OP_EMIT(opem_spork) {
   const Exp_Unary* unary = (Exp_Unary*)data;
-  return emit_exp_spork(emit, unary);
+  const Env env = emit->env;
+  const Instr ret = emit_exp_spork(emit, unary);
+  if(unary->op == insert_symbol("fork"))
+    emit_add_instr(emit, GcAdd);
+  return ret;
 }
 
 static FREEARG(freearg_xork) {
index 6ed0c88bbf1e812f9439d2b1dcc84fd06772953d..de018cf1652ee2ea4e449b6898ea30851e23922e 100644 (file)
@@ -44,7 +44,6 @@ ANN static Func_Def from_base(const Env env, struct dottmpl_ *const dt, const Ns
   SET_FLAG(def, template);
   return def;
 }
-
 ANN static Func_Def traverse_tmpl(const Emitter emit, struct dottmpl_ *const dt, const Nspc nspc) {
   DECL_OO(const Func_Def, def, = from_base(emit->env, dt, nspc))
   CHECK_BO(traverse_dot_tmpl(emit, dt))
index a5db437c74b7809d5bf4107d9334871823607a72..8d958d493807b2e2c051eba395b07278a9b21f58 100644 (file)
@@ -113,8 +113,8 @@ static ID_CHECK(opck_this) {
   if(env->func && !GET_FLAG(env->func, member))
       ERR_O(exp_self(prim)->pos, _("keyword 'this' cannot be used inside static functions..."))
   if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack") &&
-GET_FLAG(env->class_def, struct))
-  ERR_O(exp_self(prim)->pos, _("can't use 'this' in struct @gack"))
+       GET_FLAG(env->class_def, struct))
+    ERR_O(exp_self(prim)->pos, _("can't use 'this' in struct @gack"))
   return env->class_def;
 }
 
index d33a54d15648e9296756d4933fff7d3e9df1e169..90ab1d1e93422fc6259d4bc051642164e9991329 100644 (file)
@@ -222,8 +222,6 @@ ANN static inline void emit_struct_data(const Emitter emit, const Value v, const
   push->m_val = v->type->size - v->from->owner_class->size;
   if(v->from->offset)
     emit_struct_var(emit, v);
-//  const Instr push = emit_add_instr(emit, RegPush);
-//  push->m_val = v->type->size - SZ_INT;
 }
 
 ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
@@ -271,8 +269,8 @@ OP_EMIT(opem_object_dot) {
   if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
        (isa(exp_self(member)->info->type, emit->gwion->type[et_function]) > 0 &&
        !is_fptr(emit->gwion, exp_self(member)->info->type)))) {
-  if(!GET_FLAG(t_base, struct))
-    CHECK_BO(emit_exp(emit, member->base))
+    if(!GET_FLAG(t_base, struct))
+      CHECK_BO(emit_exp(emit, member->base))
     if(isa(member->t_base, emit->env->gwion->type[et_object]) > 0)
       emit_except(emit, member->t_base);
   }
@@ -374,13 +372,9 @@ ANN static Class_Def template_class(const Env env, const Class_Def def, const Ty
 
 }
 
-extern ANN m_bool scan0_class_def(const Env, const Class_Def);
-extern ANN m_bool scan1_class_def(const Env, const Class_Def);
-extern ANN m_bool traverse_func_def(const Env, const Func_Def);
-extern ANN m_bool traverse_class_def(const Env, const Class_Def);
-
 ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) {
-  a->union_def = new_union_def(env->gwion->mp, a->list,
+puts("\033[35mhere\033[0m");
+  a->union_def = new_union_def(env->gwion->mp, cpy_decl_list(env->gwion->mp, a->list),
     loc_cpy(env->gwion->mp, t->e->def->pos));
   a->union_def->type_xid = a->base.xid;
   if(GET_FLAG(t, global))
@@ -395,7 +389,7 @@ ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) {
 
 ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) {
   if(template_match(t->e->def->base.tmpl->list, td->types) < 0)
-   ERR_O(td->xid->pos, _("invalid template types number"))
+   ERR_O(td->pos, _("invalid template types number"))
   DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
   if(a->base.type)
     return a->base.type;
index a3483dec79fa7fe67a78b9b2aef6e33398a03ad2..c3e78c55d8de4fe866db59973fcf3e7aec79942f 100644 (file)
@@ -52,6 +52,8 @@ static OP_CHECK(opck_ptr_deref) {
 
 static OP_CHECK(opck_ptr_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
+  if(!cast->td->types->td)
+    ERR_N(exp_self(cast)->pos, "'Ptr' needs types to cast")
   DECL_ON(const Type, t, = type_decl_resolve(env, cast->td))
   if(!GET_FLAG(t, check))
     CHECK_BN(traverse_class_def(env, t->e->def))
@@ -64,6 +66,7 @@ static OP_CHECK(opck_ptr_cast) {
 static OP_CHECK(opck_ptr_implicit) {
   const struct Implicit* imp = (struct Implicit*)data;
   const Exp e = imp->e;
+  DECL_OO(const m_str, name, = get_type_name(env, imp->t->name, 1))
   if(!strcmp(get_type_name(env, imp->t->name, 1), e->info->type->name)) {
     const m_str access = exp_access(e);
     if(access)
@@ -118,7 +121,7 @@ static OP_EMIT(opem_ptr_deref) {
 }
 
 GWION_IMPORT(ptr) {
-  const Type t_ptr = gwi_class_ini(gwi, "Ptr<~A~>", NULL);
+  const Type t_ptr = gwi_class_ini(gwi, "<~A~>Ptr", NULL);
   gwi->gwion->type[et_ptr] = t_ptr;
   GWI_BB(gwi_item_ini(gwi, "@internal", "@val"))
   GWI_BB(gwi_item_end(gwi, 0, NULL))
index a54c1af070981add6339e6c64473f9d901e9b048..6a7b428d5df56d452b1c3fcaf74f9713bc6a85a7 100644 (file)
 #include "specialid.h"
 #include "gwi.h"
 
-static m_int o_fork_thread, o_shred_cancel, o_fork_done, o_fork_ev, o_fork_retsize;
+static m_int o_fork_thread, o_fork_cond, o_fork_mutex, o_shred_cancel, o_fork_done, o_fork_ev, o_fork_retsize;
 
 #define FORK_THREAD(o) *(THREAD_TYPE*)(o->data + o_fork_thread)
+#define FORK_COND(o) *(THREAD_COND_TYPE*)(o->data + o_fork_cond)
+#define FORK_MUTEX(o) *(MUTEX_TYPE*)(o->data + o_fork_mutex)
 #define FORK_RETSIZE(o) *(m_int*)(o->data + o_fork_retsize)
 
 VM_Shred new_shred_base(const VM_Shred shred, const VM_Code code) {
@@ -132,8 +134,12 @@ describe_path_and_dir(, s->info->name)
 describe_path_and_dir(_code, s->code->name)
 
 static DTOR(shred_dtor) {
-  if(ME(o))
+  if(ME(o)) {
+    MUTEX_TYPE mutex = ME(o)->tick->shreduler->mutex;
+    MUTEX_LOCK(mutex);
     free_vm_shred(ME(o));
+    MUTEX_UNLOCK(mutex);
+  }
 }
 
 static MFUN(shred_lock) {
@@ -147,42 +153,39 @@ static MFUN(shred_unlock) {
 static void stop(const M_Object o) {
   VM *vm = ME(o)->info->vm;
   MUTEX_LOCK(vm->shreduler->mutex);
-  MUTEX_LOCK(vm->parent->shreduler->mutex);
   vm->shreduler->bbq->is_running = 0;
-  MUTEX_UNLOCK(vm->parent->shreduler->mutex);
+  *(m_int*)(o->data + o_shred_cancel) = 1;
   MUTEX_UNLOCK(vm->shreduler->mutex);
 }
 
 static void join(const M_Object o) {
-  VM *vm = ME(o)->info->vm->parent;
-  MUTEX_LOCK(vm->shreduler->mutex);
-  THREAD_JOIN(FORK_THREAD(o));
-  MUTEX_UNLOCK(vm->shreduler->mutex);
+  VM *vm = ME(o)->info->vm;
+  if(FORK_THREAD(o)) {
+    THREAD_JOIN(FORK_THREAD(o));
+    FORK_THREAD(o) = 0;
+  }
 }
 
 static DTOR(fork_dtor) {
+  *(m_int*)(o->data + o_fork_done) = 1;
   stop(o);
-  VM *vm = ME(o)->info->vm->parent;
-  const m_int idx = vector_find(&vm->gwion->data->child, (vtype)o);
-  VPTR(&vm->gwion->data->child, idx) = 0;
-  if(!vm->gwion->data->child2.ptr)
-    vector_init(&vm->gwion->data->child2);
-  vector_add(&vm->gwion->data->child2, (vtype)ME(o)->info->vm->gwion);
-  gwion_end_child(shred, ME(o)->info->vm->gwion);
-  join(o);
+  VM *parent = ME(o)->info->vm->parent;
+  MUTEX_LOCK(parent->shreduler->mutex);
+  if(parent->gwion->data->child.ptr) {
+    const m_int idx = vector_find(&parent->gwion->data->child, (vtype)o);
+    if(idx > -1)
+    VPTR(&parent->gwion->data->child, idx) = 0;
+  }
+  if(!parent->gwion->data->child2.ptr)
+    vector_init(&parent->gwion->data->child2);
+  vector_add(&parent->gwion->data->child2, (vtype)ME(o)->info->vm->gwion);
+  REM_REF(ME(o)->code, ME(o)->info->vm->gwion);
+  MUTEX_UNLOCK(parent->shreduler->mutex);
 }
 
 static MFUN(fork_join) {
-  MUTEX_LOCK(ME(o)->tick->shreduler->mutex);
-  MUTEX_LOCK(shred->tick->shreduler->mutex);
-  release(o, shred);
-  if(*(m_int*)(o->data + o_fork_done)) {
-    MUTEX_UNLOCK(shred->tick->shreduler->mutex);
-    MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+  if(*(m_int*)(o->data + o_fork_done))
     return;
-  }
-  MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
-  MUTEX_UNLOCK(shred->tick->shreduler->mutex);
   shreduler_remove(shred->tick->shreduler, shred, 0);
   vector_add(EV_SHREDS(*(M_Object*)(o->data + o_fork_ev)), (vtype)shred);
 }
@@ -194,45 +197,67 @@ static MFUN(shred_cancel) {
 }
 
 static MFUN(shred_test_cancel) {
-  MUTEX_LOCK(ME(o)->tick->shreduler->mutex);
+  if(*(m_int*)(o->data + o_shred_cancel))
+    vm_shred_exit(ME(o));
+}
+
+static MFUN(fork_test_cancel) {
   if(*(m_int*)(o->data + o_shred_cancel)) {
-    const m_bool is_me = ME(o) == shred;
-    if(is_me)
-      MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+    stop(o);
+    join(o);
+    _release(o, ME(o));
     vm_shred_exit(ME(o));
-    if(is_me)
-      return;
   }
-  MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+}
+
+struct ThreadLauncher {
+  MUTEX_TYPE mutex;
+  THREAD_COND_TYPE cond;
+  VM *vm;
+};
+
+static inline int fork_running(VM *vm, const M_Object o) {
+  MUTEX_LOCK(vm->shreduler->mutex);
+  const int ret = vm->bbq->is_running && !*(m_int*)(o->data + o_shred_cancel);
+  MUTEX_UNLOCK(vm->shreduler->mutex);
+  return ret;
 }
 
 static ANN THREAD_FUNC(fork_run) {
-  VM *vm = (VM*)data;
-  vm_lock(vm->parent);
-  const M_Object me = vm->bbq->is_running ?
-    vm->shreduler->list->self->info->me : NULL;
-  vm_unlock(vm->parent);
-  if(!me)
-    THREAD_RETURN(0);
-  while(vm->bbq->is_running) {
+struct ThreadLauncher *tl = data;
+  VM *vm = tl->vm;
+  MUTEX_TYPE mutex = tl->mutex;
+  const M_Object me = vm->shreduler->list->self->info->me;
+  ++me->ref;
+  MUTEX_LOCK(mutex);
+  THREAD_COND_SIGNAL(FORK_COND(me));
+  MUTEX_UNLOCK(mutex);
+  while(fork_running(vm, me)) {
     vm_run(vm);
     ++vm->bbq->pos;
   }
-  vm_lock(vm->parent);
-  if(vm_running(vm->parent)) {
-    *(m_int*)(me->data + o_fork_done) = 1;
+  gwion_end_child(ME(me), vm->gwion);
+  MUTEX_LOCK(vm->parent->shreduler->mutex);
+  if(!*(m_int*)(me->data + o_shred_cancel))
     broadcast(*(M_Object*)(me->data + o_fork_ev));
-  } else if(me->ref > 1)
-    release(me, ME(me));
-  vm_unlock(vm->parent);
+  MUTEX_UNLOCK(vm->parent->shreduler->mutex);
+  *(m_int*)(me->data + o_fork_done) = 1;
+//  if(!*(m_int*)(me->data + o_shred_cancel))
+//    _release(me, ME(me));
   THREAD_RETURN(0);
 }
 
 ANN void fork_launch(VM const* vm, const M_Object o, const m_uint sz) {
-  if(vm_running(vm)) {
-    FORK_RETSIZE(o) = sz;
-    THREAD_CREATE(FORK_THREAD(o), fork_run, ME(o)->info->vm);
-  } else release(o, ME(o));
+  FORK_RETSIZE(o) = sz;
+  MUTEX_SETUP(FORK_MUTEX(o));
+  THREAD_COND_SETUP(FORK_COND(o));
+  struct ThreadLauncher tl = { .mutex=FORK_MUTEX(o), .cond=FORK_COND(o), .vm=ME(o)->info->vm };
+  MUTEX_LOCK(tl.mutex);
+  THREAD_CREATE(FORK_THREAD(o), fork_run, &tl);
+  THREAD_COND_WAIT(FORK_COND(o), tl.mutex);
+  MUTEX_UNLOCK(tl.mutex);
+  THREAD_COND_CLEANUP(FORK_COND(o));
+  MUTEX_CLEANUP(FORK_MUTEX(o));
 }
 
 ANN void fork_clean(const VM_Shred shred, const Vector v) {
@@ -241,9 +266,19 @@ ANN void fork_clean(const VM_Shred shred, const Vector v) {
     if(!o)
       continue;
     stop(o);
-    THREAD_JOIN(FORK_THREAD(o));
-    _release(o, shred);
   }
+  for(m_uint i = 0; i < vector_size(v); ++i) {
+    const M_Object o = (M_Object)vector_at(v, i);
+    if(!o)
+      continue;
+    join(o);
+  }
+  for(m_uint i = 0; i < vector_size(v); ++i) {
+    const M_Object o = (M_Object)vector_at(v, i);
+    if(!o)
+      continue;
+    _release(o, shred);
+   }
   vector_release(v);
   v->ptr = NULL;
 }
@@ -325,6 +360,10 @@ GWION_IMPORT(shred) {
 
   gwi_item_ini(gwi, "@internal", "@thread");
   GWI_BB((o_fork_thread = gwi_item_end(gwi, ae_flag_const, NULL)))
+  gwi_item_ini(gwi, "@internal", "@cond");
+  GWI_BB((o_fork_cond = gwi_item_end(gwi, ae_flag_const, NULL)))
+  gwi_item_ini(gwi, "@internal", "@mutex");
+  GWI_BB((o_fork_mutex = gwi_item_end(gwi, ae_flag_const, NULL)))
   gwi_item_ini(gwi, "int", "is_done");
   GWI_BB((o_fork_done = gwi_item_end(gwi, ae_flag_const, NULL)))
   gwi_item_ini(gwi, "Event", "ev");
@@ -333,6 +372,8 @@ GWION_IMPORT(shred) {
   GWI_BB((o_fork_retsize = gwi_item_end(gwi, ae_flag_const, NULL)))
   gwi_func_ini(gwi, "void", "join");
   GWI_BB(gwi_func_end(gwi, fork_join, ae_flag_none))
+  gwi_func_ini(gwi, "void", "test_cancel");
+  GWI_BB(gwi_func_end(gwi, fork_test_cancel, ae_flag_none))
   GWI_BB(gwi_class_end(gwi))
   SET_FLAG((t_fork), abstract);
   return GW_OK;
index c14619689df2d7ce0cf89a3d4c30a9811d764954..d08ae8403a8468f4095c51c3eda34f3f339b0b50 100644 (file)
@@ -22,19 +22,24 @@ ANN static void gwion_reset(const Gwion gwion) {
   push_global(gwion, "[user]");
 }
 
-//#define BUFSIZE 1024
-#define BUFSIZE 256
+#define BUFSIZE 64
 
 static void afl_run(const Gwion gwion) {
   char buf[BUFSIZE];
-  __AFL_INIT();
-  while (__AFL_LOOP(1000)) {
+  struct GwText_ text = { .mp=gwion->mp };
+  while (__AFL_LOOP(5)) {
+    ssize_t sz;
     memset(buf, 0, BUFSIZE);
-    read(0, buf, BUFSIZE);
-    if(compile_string(gwion, "afl", buf))
+    while((sz = read(0, buf, BUFSIZE)) > 0) {
+      buf[sz] = '\0';
+      text_add(&text, buf);
+    }
+    if(compile_string(gwion, "afl", text.str))
       gwion_run(gwion);
+    text_reset(&text);
     gwion_reset(gwion);
   }
+    text_release(&text);
 }
 #define gwion_run(a) afl_run(a)
 #endif
index c4bf2db2d931fe9e5a76f7980b4a38894e8b0a59..34e2beeb72256d22ce7d7bd31009d7d2178e039d 100644 (file)
@@ -73,14 +73,10 @@ ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) {
     t = t->e->parent;
   if(!t->e->d.func)
     return GW_ERROR;
+  if(!env->class_def)
+    return GW_OK;
   const Func  func = t->e->d.func;
   const Type type = func->value_ref->from->owner_class;
-  if(!env->class_def) {
-    if(!type || GET_FLAG(func, global))
-      return GW_OK;
-return GW_OK;
-//    ERR_B(var->pos, _("can't use non public typedef at global scope."))
-  }
   if(type && isa(type, env->class_def) < 0 && !GET_FLAG(func, global))
     ERR_B(var->pos, _("can't use non global fptr of other class."))
   if(GET_FLAG(func, member) && GET_FLAG(v, static))
@@ -96,8 +92,7 @@ ANN Type check_td(const Env env, Type_Decl *td) {
   assert(t);
   if(GET_FLAG(t, template) && !GET_FLAG(t, ref))
     ERR_O(td_pos(td), _("type '%s' needs template types"), t->name)
-  td->xid = new_id_list(env->gwion->mp, insert_symbol("@resolved"),
-      loc_cpy(env->gwion->mp, td->exp->pos));
+  td->xid = insert_symbol("@resolved");
   if(t->array_depth)
     SET_FLAG(td, force);
   return t;
@@ -130,7 +125,7 @@ ANN static m_bool check_var_td(const Env env, const Var_Decl var, Type_Decl *con
     if(GET_FLAG(td, member)) {
       decl_member(env, v);
       if(env->class_def->e->tuple)
-        tuple_info(env, td, var);
+        tuple_info(env, v);
     } else if(GET_FLAG(td, static))
         decl_static(env, v);
   } else if(GET_FLAG(td, global) || (env->func && GET_FLAG(env->func->def, global)))
@@ -152,10 +147,16 @@ ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
   return GW_OK;
 }
 
+ANN static inline m_bool ensure_check(const Env env, const Type t) {
+  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+    .scope=env->scope->depth, .flag=ae_flag_check };
+  return envset_run(&es, t);
+}
+
 ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
   if(!decl->td->xid)
     return no_xid(env, decl);
-  if(decl->td->xid->xid == insert_symbol("auto")) { // should be better
+  if(decl->td->xid == insert_symbol("auto")) { // should be better
     clear_decl(env, decl);
     CHECK_BO(scan1_exp(env, exp_self(decl)))
     CHECK_BO(scan2_exp(env, exp_self(decl)))
@@ -165,11 +166,11 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
   }
   if(!decl->type)
     ERR_O(td_pos(decl->td), _("can't find type"));
-{
-  const Type t = get_type(decl->type);
-  if(GET_FLAG(t, template) && !GET_FLAG(t, check))
-    CHECK_BO(check_cdef(env, t->e->def))
-}
+  {
+    const Type t = get_type(decl->type);
+    if(!GET_FLAG(t, check) && t->e->def)
+      CHECK_BO(ensure_check(env, t))
+  }
   const m_bool global = GET_FLAG(decl->td, global);
   const m_uint scope = !global ? env->scope->depth : env_push_global(env);
   const m_bool ret = check_decl(env, decl);
@@ -360,28 +361,25 @@ static ANN Type check_exp_slice(const Env env, const Exp_Slice* range) {
   return op_check(env, &opi);
 }
 
-ANN static void fill_tl_vector(const Env env, Nspc nspc, const Vector v) {
-  while(nspc->parent) {
-    const Type t = nspc_lookup_type0(nspc->parent, insert_symbol(nspc->name));
-    if(!t)
-      break;
-    vector_add(v, (vtype)insert_symbol(t->name));
-    nspc = nspc->parent;
-  }
+ANN static Type_Decl* prepend_type_decl(MemPool mp, const Symbol xid, Type_Decl* td, const loc_t pos) {
+  Type_Decl *a = new_type_decl(mp, xid, loc_cpy(mp, pos));
+  a->next = td;
+  return a;
 }
 
 ANN static Type_List mk_type_list(const Env env, const Type type, const loc_t pos) {
   struct Vector_ v;
   vector_init(&v);
   vector_add(&v, (vtype)insert_symbol(type->name));
-  if(type->e->owner)
-    fill_tl_vector(env, type->e->owner, &v);
-  ID_List id = NULL;
+  Type owner = type->e->owner_class;
+  while(owner) {
+    vector_add(&v, (vtype)insert_symbol(owner->name));
+    owner = owner->e->owner_class;
+  }
+  Type_Decl *td = NULL;
   for(m_uint i = 0 ; i < vector_size(&v); ++i)
-    id = prepend_id_list(env->gwion->mp, (Symbol)vector_at(&v, i), id, loc_cpy(env->gwion->mp, pos));
+    td = prepend_type_decl(env->gwion->mp, (Symbol)vector_at(&v, i), td, pos);
   vector_release(&v);
-  assert(id);
-  Type_Decl* td = new_type_decl(env->gwion->mp, id);
   return new_type_list(env->gwion->mp, td, NULL);
 }
 
@@ -392,9 +390,7 @@ ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t,
     array_base(e->info->type) == array_base(t);
     if(!match) {
       if(e->info->type == env->gwion->type[et_lambda] && is_fptr(env->gwion, t)) {
-        const Type owner = nspc_lookup_type1(t->e->owner->parent,
-          insert_symbol(t->e->owner->name));
-        const m_bool ret = check_lambda(env, owner, &e->d.exp_lambda, t->e->d.func->def);
+        const m_bool ret = check_lambda(env, t->e->owner_class, &e->d.exp_lambda, t->e->d.func->def);
         exp_setvar(e, 1);
         return ret;
       }
@@ -418,10 +414,11 @@ ANN2(1,2) static Func find_func_match_actual(const Env env, Func func, const Exp
       }
       if(e1->type == env->gwion->type[et_undefined] ||
             (func->def->base->tmpl && is_fptr(env->gwion, func->value_ref->type) > 0)) {
-        if(SAFE_FLAG(func->value_ref->from->owner_class, template))
-          CHECK_BO(template_push_types(env, func->value_ref->from->owner_class->e->def->base.tmpl))
-          e1->type = known_type(env, e1->td);
-        if(SAFE_FLAG(func->value_ref->from->owner_class, template))
+        const Type owner = func->value_ref->from->owner_class;
+        if(owner)
+          CHECK_BO(template_push(env, owner))
+        e1->type = known_type(env, e1->td);
+        if(owner)
           nspc_pop_type(env->gwion->mp, env->curr);
         CHECK_OO(e1->type)
       }
@@ -499,7 +496,12 @@ ANN static Func _find_template_match(const Env env, const Value v, const Exp_Cal
   const Type_List types = exp->tmpl->call;
   Func m_func = NULL, former = env->func;
   DECL_OO(const m_str, tmpl_name, = tl2str(env, types))
-  const m_uint scope = env_push(env, v->from->owner_class, v->from->owner);
+  const m_uint scope = env->scope->depth;
+  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+    .scope=scope, .flag=ae_flag_check };
+  if(v->from->owner_class)
+    envset_push(&es, v->from->owner_class);
+  (void)env_push(env, v->from->owner_class, v->from->owner);
   if(is_fptr(env->gwion, v->type)) {
     const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl_name, 0);
     const Type exists = nspc_lookup_type0(v->from->owner, sym);
@@ -521,7 +523,7 @@ ANN static Func _find_template_match(const Env env, const Value v, const Exp_Cal
           if(m_func)
             nspc_add_type_front(v->from->owner, sym, actual_type(env->gwion, m_func->value_ref->type));
         }
-        free_fptr_def(env->gwion->mp, fptr); // ???? related
+        free_fptr_def(env->gwion->mp, fptr);
       }
     }
   } else {
@@ -555,6 +557,8 @@ ANN static Func _find_template_match(const Env env, const Value v, const Exp_Cal
     }
   }
   free_mstr(env->gwion->mp, tmpl_name);
+  if(v->from->owner_class && v->from->owner_class->e->owner_class && es.run)
+    envset_pop(&es, v->from->owner_class->e->owner_class);
   env_pop(env, scope);
   env->func = former;
   return m_func;
@@ -650,11 +654,18 @@ ANN static Func predefined_func(const Env env, const Value v,
   return v->d.func_ref = func;
 }
 
-ANN static Type check_predefined(const Env env, Exp_Call *exp, const Value value, const Tmpl *tm, const Func_Def fdef) {
-  DECL_OO(const Func, func, = value->d.func_ref ?: predefined_func(env, value, exp, tm))
+ANN static Type check_predefined(const Env env, Exp_Call *exp, const Value v, const Tmpl *tm, const Func_Def fdef) {
+  DECL_OO(const Func, func, = v->d.func_ref ?: predefined_func(env, v, exp, tm))
   if(!fdef->base->ret_type) { // template fptr
-    const m_uint scope = env_push(env, value->from->owner_class, value->from->owner);
+    const m_uint scope = env->scope->depth;
+    struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+      .scope=scope, .flag=ae_flag_check };
+    if(v->from->owner_class)
+      envset_push(&es, v->from->owner_class);
+    (void)env_push(env, v->from->owner_class, v->from->owner);
     const m_bool ret = traverse_func_def(env, func->def);
+    if(v->from->owner_class && v->from->owner_class->e->owner_class && es.run)
+      envset_push(&es, v->from->owner_class);
     env_pop(env, scope);
     CHECK_BO(ret)
   }
@@ -672,9 +683,7 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp, const Tmp
     Arg_List arg = fdef->base->args;
     Exp template_arg = exp->args;
     while(arg && template_arg) {
-      char path[id_list_len(arg->td->xid)];
-      type_path(path, arg->td->xid);
-      if(!strcmp(s_name(list->xid), path)) {
+      if(list->xid == arg->td->xid) {
         tl[args_number] = mk_type_list(env, template_arg->info->type, fdef->pos);
         if(args_number)
           tl[args_number - 1]->next = tl[args_number];
@@ -963,21 +972,19 @@ ANN static m_bool do_stmt_auto(const Env env, const Stmt_Auto stmt) {
     memset(&array, 0, sizeof(struct Array_Sub_));
     memset(&td0, 0, sizeof(Type_Decl));
     memset(&td, 0, sizeof(Type_Decl));
-    id.xid   = insert_symbol("Ptr");
-    id0.xid  = insert_symbol(ptr->name);
-    td0.xid  = &id0;
-    td.xid   = &id;
+    td.xid   = insert_symbol("Ptr");
+    td0.xid  = insert_symbol(ptr->name);
     tl.td    = &td0;
     td.types = &tl;
-    td0.xid->pos = stmt->exp->pos;
-    td.xid->pos = stmt->exp->pos;
+    td0.pos = stmt->exp->pos;
+    td.pos = stmt->exp->pos;
     if(depth) {
       array.depth = depth;
       td.array = &array;
     }
     ptr = known_type(env, &td);
     if(!GET_FLAG(ptr, checked) && ptr->e->def)
-      CHECK_BB(traverse_cdef(env, ptr->e->def))
+      CHECK_BB(ensure_check(env, ptr))
   }
   t = depth ? array_type(env, ptr, depth) : ptr;
   stmt->v = new_value(env->gwion->mp, t, s_name(stmt->sym));
@@ -1028,9 +1035,8 @@ ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) {
   if(stmt->val) {
     if(env->func->def->base->xid == insert_symbol("@implicit") && ret_type == env->func->def->base->args->type)
       ERR_B(stmt_self(stmt)->pos, _("can't use implicit casting while defining it"))
-    const m_bool ret = check_implicit(env, stmt->val, env->func->def->base->ret_type);
-    if(ret > 0)
-      return ret;
+    if(check_implicit(env, stmt->val, env->func->def->base->ret_type) > 0)
+      return GW_OK;
     ERR_B(stmt_self(stmt)->pos, _("invalid return type: got '%s', expected '%s'"),
         ret_type->name, env->func->def->base->ret_type->name)
   }
@@ -1351,18 +1357,19 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
 ANN m_bool check_class_def(const Env env, const Class_Def c) {
   if(tmpl_base(c->base.tmpl))
     return GW_OK;
-  const Class_Def cdef = c->base.type->e->def;
-  if(GET_FLAG(cdef->base.type, checked))return GW_OK;
-  const Type type = cdef->base.type;
-  SET_FLAG(type, check);
+  const Type t = c->base.type;
+  const Class_Def cdef = t->e->def;
+  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, check))
+    CHECK_BB(check_class_def(env, t->e->owner_class->e->def))
+  if(GET_FLAG(t, checked))return GW_OK;
+  SET_FLAG(t, check);
   if(cdef->base.ext)
     CHECK_BB(cdef_parent(env, cdef))
-  assert(type->e->parent || GET_FLAG(cdef, struct));
   if(!GET_FLAG(cdef, struct))
-    inherit(type);
+    inherit(t);
   if(cdef->body)
     CHECK_BB(env_body(env, cdef, check_section))
-  SET_FLAG(type, checked);
+  SET_FLAG(t, checked);
   return GW_OK;
 }
 
index 6d4cb056ac71f0145850ae249f4e446ab0840ddc..ce6459876e47c50db382066043855b7a6a2d85f7 100644 (file)
@@ -77,29 +77,31 @@ ANN static m_bool check_tmpl_args(const Env env, const Func_Base *base) {
   return GW_OK;
 }
 
+ANN static m_bool scan0_fptr_args(const Env env, const Fptr_Def fptr) {
+  nspc_push_type(env->gwion->mp, env->curr);
+  const m_bool ret = check_tmpl_args(env, fptr->base);
+  nspc_pop_type(env->gwion->mp, env->curr);
+  return ret;
+}
+
 ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) {
   CHECK_BB(env_access(env, fptr->base->td->flag, td_pos(fptr->base->td)))
   CHECK_OB(known_type(env, fptr->base->td))
   CHECK_BB(scan0_defined(env, fptr->base->xid, td_pos(fptr->base->td)));
   const m_str name = s_name(fptr->base->xid);
-if(fptr->base->tmpl && fptr->base->args) {
-  nspc_push_type(env->gwion->mp, env->curr);
-  const m_bool ret = check_tmpl_args(env, fptr->base);
-  nspc_pop_type(env->gwion->mp, env->curr);
-  CHECK_BB(ret);
-}
+  if(fptr->base->tmpl && fptr->base->args)
+    CHECK_BB(scan0_fptr_args(env, fptr))
   const Type t = scan0_type(env, env->gwion->type[et_fptr]->xid, name, env->gwion->type[et_fptr]);
   t->e->owner = !(!env->class_def && GET_FLAG(fptr->base->td, global)) ?
     env->curr : env->global_nspc;
+  t->e->owner_class = env->class_def;
   if(GET_FLAG(fptr->base->td, global))
     context_global(env);
   t->nspc = new_nspc(env->gwion->mp, name);
   t->flag = fptr->base->td->flag;
   fptr->type = t;
   fptr->value = mk_class(env, t);
-// set owner ?
-  fptr->value->from->owner = env->curr;
-  fptr->value->from->owner_class = env->class_def;
+  valuefrom(env, fptr->value->from);
   fptr_def(env, fptr);
   if(env->class_def)
     fptr_assign(env, fptr);
@@ -139,6 +141,7 @@ ANN static void typedef_simple(const Env env, const Type_Def tdef, const Type ba
     context_global(env);
   add_type(env, nspc, t);
   t->e->owner = nspc;
+  t->e->owner_class = env->class_def;
   tdef->type = t;
   if(base->nspc)
     ADD_REF((t->nspc = base->nspc));
@@ -171,7 +174,7 @@ ANN static void typedef_fptr(const Env env, const Type_Def tdef, const Type base
 
 ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) {
   CHECK_BB(env_access(env, tdef->ext->flag, td_pos(tdef->ext)))
-  DECL_OB(const Type, base, = tdef->tmpl ? find_type(env, tdef->ext->xid) : known_type(env, tdef->ext))
+  DECL_OB(const Type, base, = tdef->tmpl ? find_type(env, tdef->ext) : known_type(env, tdef->ext))
   CHECK_BB(scan0_defined(env, tdef->xid, td_pos(tdef->ext)))
   if(isa(base, env->gwion->type[et_function]) < 0) {
     if(!tdef->ext->types && (!tdef->ext->array || !tdef->ext->array->exp))
@@ -201,6 +204,7 @@ ANN static Type enum_type(const Env env, const Enum_Def edef) {
   t->e->parent = env->gwion->type[et_int];
   const Nspc nspc = GET_FLAG(edef, global) ? env->global_nspc : env->curr;
   t->e->owner = nspc;
+  t->e->owner_class = env->class_def;
   add_type(env, nspc, t);
   mk_class(env, t);
   scan0_implicit_similar(env, t, env->gwion->type[et_int]);
@@ -223,6 +227,7 @@ ANN static Type union_type(const Env env, const Symbol s, const m_bool add) {
   t->name = name;
   t->nspc = new_nspc(env->gwion->mp, name);
   t->e->owner = t->nspc->parent = env->curr;
+  t->e->owner_class = env->class_def;
   t->e->parent = env->gwion->type[et_union];
   add_type(env, env->curr, t);
   if(add) {
@@ -236,11 +241,11 @@ ANN static void union_tmpl(const Env env, const Union_Def udef) {
   if(tmpl_base(udef->tmpl)) {
     assert(udef->type_xid);
     const Class_Def cdef = new_class_def(env->gwion->mp, udef->flag, udef->type_xid,
-        NULL, (Ast)udef->l, loc_cpy(env->gwion->mp, udef->pos));
+        NULL, (Ast)cpy_decl_list(env->gwion->mp, udef->l), loc_cpy(env->gwion->mp, udef->pos));
     udef->type->e->def = cdef;
     cdef->base.tmpl = cpy_tmpl(env->gwion->mp, udef->tmpl);
     cdef->base.type = udef->type;
-    cdef->list = cpy_decl_list(env->gwion->mp, udef->l);
+//    cdef->list = cpy_decl_list(env->gwion->mp, udef->l);
     SET_FLAG(cdef, union);
     SET_FLAG(udef->type, pure);
     SET_FLAG(udef, template);
@@ -299,19 +304,13 @@ ANN static m_bool scan0_class_def_pre(const Env env, const Class_Def cdef) {
   return GW_OK;
 }
 
-ANN static void set_template(const Type t, const Class_Def cdef) {
-  SET_FLAG(t, template);
-  SET_FLAG(cdef, template);
-}
-
-
-ANN static void inherit_tmpl(const Env env, const Class_Def cdef) {
-  const ID_List list = env->class_def->e->def->base.tmpl->list;
-  const ID_List prev_list = cpy_id_list(env->gwion->mp, list);
-  ID_List il = prev_list;
-  while(il->next && (il = il->next));
-  il->next = cdef->base.tmpl->list;
-  cdef->base.tmpl->list = prev_list;
+ANN static void cdef_flag(const Class_Def cdef, const Type t) {
+  if(cdef->base.tmpl) {
+    SET_FLAG(t, template);
+    SET_FLAG(cdef, template);
+  }
+  if(cdef->base.ext && cdef->base.ext->array)
+    SET_FLAG(t, typedef);
 }
 
 ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
@@ -324,20 +323,13 @@ ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
   }
   t->e->tuple = new_tupleform(env->gwion->mp, parent);
   t->e->owner = env->curr;
+  t->e->owner_class = env->class_def;
   t->nspc = new_nspc(env->gwion->mp, t->name);
   t->nspc->parent = env->curr;
   t->e->def = cdef;
   t->flag = cdef->flag;
   add_type(env, t->e->owner, t);
-  if(cdef->base.tmpl) {
-    if(SAFE_FLAG(env->class_def, template) && env->class_def->e->def->base.tmpl->call == (Type_List)1)
-      inherit_tmpl(env, cdef);
-    set_template(t, cdef);
-  } else if(SAFE_FLAG(env->class_def, template)) {
-    cdef->base.tmpl = new_tmpl_base(env->gwion->mp, cpy_id_list(env->gwion->mp, env->class_def->e->def->base.tmpl->list));
-//    cdef->base.tmpl = cpy_tmpl(env->gwion->mp, env->class_def->e->def->base.tmpl);
-    set_template(t, cdef);
-  }
+  cdef_flag(cdef, t);
   if(cdef->base.ext && cdef->base.ext->array)
     SET_FLAG(t, typedef);
   return t;
@@ -360,18 +352,15 @@ ANN static m_bool scan0_section(const Env env, const Section* section) {
 ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
   CHECK_OB((cdef->base.type = scan0_class_def_init(env, cdef)))
   SET_FLAG(cdef->base.type, scan0);
-  if(cdef->body) {
-    int call = cdef->base.tmpl && !cdef->base.tmpl->call;
-    if(call)cdef->base.tmpl->call = (Type_List)1;
-    const m_bool ret = env_body(env, cdef, scan0_section);
-    if(call)cdef->base.tmpl->call = NULL;
-    CHECK_BB(ret);
-  }
+  if(cdef->body)
+    CHECK_BB(env_body(env, cdef, scan0_section))
   (void)mk_class(env, cdef->base.type);
   return GW_OK;
 }
 
-ANN m_bool scan0_class_def(const Env env, const Class_Def cdef) {
+ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
+  const Class_Def cdef = !(GET_FLAG(c, global) || (c->base.tmpl && !c->base.tmpl->call)) ?
+    c : cpy_class_def(env->gwion->mp, c);
   if(GET_FLAG(cdef, global)) {
     vector_add(&env->scope->nspc_stack, (vtype)env->curr);
     env->curr = env->global_nspc;
@@ -382,11 +371,8 @@ ANN m_bool scan0_class_def(const Env env, const Class_Def cdef) {
   if(GET_FLAG(cdef, global))
     env->curr = (Nspc)vector_pop(&env->scope->nspc_stack);
   CHECK_BB(ret)
-  if(GET_FLAG(cdef, global) || (cdef->base.tmpl && !cdef->base.tmpl->call)) {
-    const Class_Def c = cpy_class_def(env->gwion->mp, cdef);
+  if(GET_FLAG(cdef, global) || (cdef->base.tmpl && !cdef->base.tmpl->call))
     c->base.type = cdef->base.type;
-    c->base.type->e->def = c;
-  }
   return GW_OK;
 }
 
index 265f339e0c2909de1580d44db1f0ab0bb9e1795f..b00d0d75f439adb0229f97fa17862811164e26d2 100644 (file)
@@ -9,32 +9,17 @@
 ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list);
 ANN static m_bool scan1_stmt(const Env env, Stmt stmt);
 
-ANN static inline void type_contains(const Type base, const Type t) {
-  const Vector v = &base->e->contains;
-  if(!v->ptr)
-    vector_init(v);
-  if(vector_find(v, (vtype)t) == GW_ERROR) {
-    vector_add(v, (vtype)t);
-    if(base != t)
-      ADD_REF(t);
-  }
-}
-
 ANN static m_bool type_recursive(const Env env, const Type_Decl *td, const Type t) {
   if(env->class_def && !env->scope->depth) {
-    type_contains(env->class_def, t);
-    if(t->e->contains.ptr) {
-      for(m_uint i = 0; i < vector_size(&t->e->contains); ++i) {
-        if(env->class_def == (Type)vector_at(&t->e->contains, i) && !GET_FLAG(td, ref))
-          ERR_B(td_pos(td), _("%s declared inside %s\n. (make it a ref ?)"),
-              t->name, t == env->class_def ? "itself" : env->class_def->name);
-      }
-    }
+    const m_int idx = vector_find(&env->scope->class_stack, (vtype)t);
+    if(idx > -1 || t == env->class_def)
+      ERR_B(td_pos(td), _("%s declared inside %s\n. (make it a ref ?)"),
+            t->name, t == env->class_def ? "itself" : env->class_def->name);
   }
   return GW_OK;
 }
 
-ANN static Type void_type(const Env env, const Type_Decl* td) {
+ANN static Type void_type(const Env env, Type_Decl* td) {
   DECL_OO(const Type, type, = known_type(env, td))
   const Type t = get_type(type);
   if(isa(t, env->gwion->type[et_object]) > 0 || GET_FLAG(t, struct))
@@ -48,7 +33,7 @@ ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) {
   if(decl->type)
     return decl->type;
   DECL_OO(const Type ,t, = void_type(env, decl->td))
-  if(decl->td->xid && decl->td->xid->xid == insert_symbol("auto") && decl->type)
+  if(decl->td->xid == insert_symbol("auto") && decl->type)
     return decl->type;
   if(!env->scope->depth && env->class_def && !GET_FLAG(decl->td, static))
     SET_FLAG(decl->td, member);
@@ -78,13 +63,11 @@ ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) {
       }
       t = array_type(env, decl->type, var->array->depth);
     } else if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref)) {
-      if(decl->td->xid && decl->td->xid->xid == insert_symbol("auto"))
+      if(decl->td->xid == insert_symbol("auto"))
         SET_FLAG(decl->td, ref);
       else
         ERR_B(exp_self(decl)->pos, _("Type '%s' is abstract, declare as ref. (use @)"), t->name)
     }
-    if(env->class_def)
-      type_contains(env->class_def, t);
     const Value v = var->value = former ?: new_value(env->gwion->mp, t, s_name(var->xid));
     if(SAFE_FLAG(env->class_def, struct) && !GET_FLAG(decl->td, static)) {
       v->from->offset = env->class_def->size;
@@ -310,12 +293,18 @@ ANN static m_bool scan1_args(const Env env, Arg_List list) {
 ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
   if(tmpl_base(fptr->base->tmpl))
     return GW_OK;
+  if(!fptr->base->func) {
+    fptr->base->func = nspc_lookup_value0(env->curr, fptr->base->xid)->d.func_ref;
+    fptr->type = nspc_lookup_type0(env->curr, fptr->base->xid);
+  }
   const Func_Def fdef = fptr->base->func->def;
   CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)))
   return fdef->base->args ? scan1_args(env, fdef->base->args) : GW_OK;
 }
 
 ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
+  if(!tdef->type)
+    tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
   if(!tdef->type->e->def)return GW_OK;
   return !is_fptr(env->gwion, tdef->type) ? scan1_cdef(env, tdef->type->e->def) : GW_OK;
 }
@@ -368,7 +357,7 @@ ANN m_bool scan1_union_def(const Env env, const Union_Def udef) {
   }
   const m_bool ret = scan1_union_def_inner(env, udef);
   union_pop(env, udef, scope);
-  const Type type = udef->xid || udef->type_xid ? udef->value->type : udef->type;
+  const Type type = udef->xid || !udef->type_xid ? udef->value->type : udef->type;
   SET_FLAG(type, scan1);
   return ret;
 }
@@ -516,8 +505,11 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
 ANN m_bool scan1_class_def(const Env env, const Class_Def c) {
   if(tmpl_base(c->base.tmpl))
     return GW_OK;
-  const Class_Def cdef = c->base.type->e->def;
-  if(GET_FLAG(cdef->base.type, scan1))return GW_OK;
+  const Type t = c->base.type;
+  const Class_Def cdef = t->e->def;
+  if(GET_FLAG(t, scan1))return GW_OK;
+  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan1))
+    CHECK_BB(scan1_class_def(env, t->e->owner_class->e->def))
   SET_FLAG(cdef->base.type, scan1);
   if(cdef->base.ext)
     CHECK_BB(cdef_parent(env, cdef))
index 6dd4cdb7c9c89dd90cf8b7d876821552289b33f7..8f38e9359d62fd1eb3f9a29351420159181fd907 100644 (file)
 ANN static m_bool scan2_stmt(const Env, const Stmt);
 ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
 
+ANN static inline m_bool ensure_scan2(const Env env, const Type t) {
+  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan2_cdef,
+    .scope=env->scope->depth, .flag=ae_flag_scan2 };
+  return envset_run(&es, t);
+}
+
 ANN static m_bool scan2_decl(const Env env, const Exp_Decl* decl) {
   const Type t = get_type(decl->type);
-  if(GET_FLAG(t, template) && !GET_FLAG(t, scan2))
-    CHECK_BB(scan2_cdef(env, t->e->def))
+  if(!GET_FLAG(t, scan2) && t->e->def)
+    CHECK_BB(ensure_scan2(env, t))
   Var_Decl_List list = decl->list;
   do {
     const Var_Decl var = list->self;
@@ -37,7 +43,7 @@ ANN m_bool scan2_exp_decl(const Env env, const Exp_Decl* decl) {
   return ret;
 }
 
-ANN static m_bool scan2_args(const Env env, const Func_Def f) {
+ANN static m_bool scan2_args(const Func_Def f) {
   Arg_List list = f->base->args;
   do {
     const Value v = list->var_decl->value;
@@ -64,11 +70,11 @@ ANN static Value scan2_func_assign(const Env env, const Func_Def d,
 }
 
 
-ANN m_bool scan2_fptr_def(const Env env, const Fptr_Def fptr) {
+ANN m_bool scan2_fptr_def(const Env env NUSED, const Fptr_Def fptr) {
   if(!tmpl_base(fptr->base->tmpl)) {
     const Func_Def def = fptr->type->e->d.func->def;
     if(def->base->args)
-      CHECK_BB(scan2_args(env, def))
+      CHECK_BB(scan2_args(def))
   } else
     SET_FLAG(fptr->type, func);
   return GW_OK;
@@ -259,6 +265,7 @@ ANN static m_bool scan2_stmt_jump(const Env env, const Stmt_Jump stmt) {
 ANN static m_bool scan2_union_decl(const Env env, const Decl_List list) {
   Decl_List l = list;
   do CHECK_BB(scan2_exp_decl(env, &l->self->d.exp_decl))
+//  do CHECK_BB(scan2_exp(env, l->self))
   while((l = l->next));
   return GW_OK;
 }
@@ -323,6 +330,7 @@ ANN static Type func_type(const Env env, const Func func) {
   t->e->parent = env->gwion->type[func->def->base->td ? et_function : et_lambda];
   t->name = func->name;
   t->e->owner = env->curr;
+  t->e->owner_class = env->class_def;
   if(GET_FLAG(func, member))
     t->size += SZ_INT;
   t->e->d.func = func;
@@ -391,7 +399,6 @@ ANN2(1, 2) static m_bool scan2_fdef_tmpl(const Env env, const Func_Def f, const
   const Symbol sym = func_symbol(env, env->curr->name, name, "template", i);
   nspc_add_value(env->curr, sym, value);
   if(!overload) {
-//    func->vt_index = i; // ?????
     ADD_REF(value)
     nspc_add_value(env->curr, f->base->xid, value);
     nspc_add_func(env->curr, f->base->xid, func);
@@ -445,7 +452,6 @@ ANN static m_str func_tmpl_name(const Env env, const Func_Def f) {
   do {
     const Type t = nspc_lookup_type0(env->curr, id->xid);
     if(!t)return NULL;
-//    assert(t);
     vector_add(&v, (vtype)t);
     tlen += strlen(t->name);
   } while((id = id->next) && ++tlen);
@@ -495,7 +501,7 @@ ANN2(1,2) m_bool scan2_fdef_std(const Env env, const Func_Def f, const Value ove
   else
     f->base->func = base;
   if(f->base->args)
-    CHECK_BB(scan2_args(env, f))
+    CHECK_BB(scan2_args(f))
   if(!GET_FLAG(f, builtin) && f->d.code)
     CHECK_BB(scan2_func_def_code(env, f))
   if(!base) {
@@ -573,9 +579,12 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
 ANN m_bool scan2_class_def(const Env env, const Class_Def c) {
   if(tmpl_base(c->base.tmpl))
     return GW_OK;
-  const Class_Def cdef = c->base.type->e->def;
-  if(GET_FLAG(cdef->base.type, scan2))return GW_OK;
-  SET_FLAG(cdef->base.type, scan2);
+  const Type t = c->base.type;
+  const Class_Def cdef = t->e->def;
+  if(GET_FLAG(t, scan2))return GW_OK;
+  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan2))
+    CHECK_BB(scan2_class_def(env, t->e->owner_class->e->def))
+  SET_FLAG(t, scan2);
   if(cdef->base.ext)
     CHECK_BB(cdef_parent(env, cdef))
   if(cdef->body)
index cd5beb766efdab389f6f0e3f2d5d678b08372434..8e47c8cba49a80a7a191a4a6704284ccd7cd8544 100644 (file)
@@ -17,22 +17,39 @@ struct tmpl_info {
   uint8_t index;
 };
 
-ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
+ANN static m_bool push_types(const Env env, const Tmpl *tmpl) {
   ID_List list = tmpl->list;
   Type_List call = tmpl->call;
-  nspc_push_type(env->gwion->mp, env->curr);
   do {
     if(!call)
       break;
     const Type t = known_type(env, call->td);
     if(!t)
-      return GW_ERROR;
+      return 1;
     nspc_add_type(env->curr, list->xid, t);
     call = call->next;
   } while((list = list->next));
-  if(!call)
+  return !call;
+}
+
+ANN static m_bool _template_push(const Env env, const Type t) {
+  if(t->e->owner_class)
+    CHECK_BB(template_push(env, t->e->owner_class))
+  if(GET_FLAG(t, template))
+    return push_types(env, t->e->def->base.tmpl);
+  return GW_OK;
+}
+
+ANN m_bool template_push(const Env env, const Type t) {
+  nspc_push_type(env->gwion->mp, env->curr);
+  return _template_push(env, t);
+}
+
+ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
+  nspc_push_type(env->gwion->mp, env->curr);
+  if(push_types(env, tmpl))
     return GW_OK;
-  POP_RET(-1);
+  POP_RET(GW_ERROR);
 }
 
 ANN Tmpl* mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) {
@@ -60,7 +77,7 @@ static ANN Type scan_func(const Env env, const Type t, const Type_Decl* td) {
   func->flag = def->flag;
   value->d.func_ref = func;
   value->from->owner = t->e->owner;
-  value->from->owner_class = t->e->d.func->value_ref->from->owner_class;
+  value->from->owner_class = t->e->owner_class;
   func->value_ref = value;
   func->def->base->tmpl = mk_tmpl(env, t->e->d.func->def->base->tmpl, td->types);
   def->base->func = func;
@@ -71,11 +88,11 @@ static ANN Type scan_func(const Env env, const Type t, const Type_Decl* td) {
 static ANN Type maybe_func(const Env env, const Type t, const Type_Decl* td) {
   if(isa(t, env->gwion->type[et_function]) > 0 && t->e->d.func->def->base->tmpl)
      return scan_func(env, t, td);
-   ERR_O(td->xid->pos,
-      _("type '%s' is not template. You should not provide template types"), t->name)
+  ERR_O(td->pos,
+     _("type '%s' is not template. You should not provide template types"), t->name)
 }
 
-ANN Type scan_type(const Env env, const Type t, const Type_Decl* td) {
+ANN Type _scan_type(const Env env, const Type t, const Type_Decl* td) {
   if(GET_FLAG(t, template)) {
     if(GET_FLAG(t, ref))
       return t;
@@ -84,5 +101,29 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* td) {
     return op_check(env, &opi);
   } else if(td->types)
     return maybe_func(env, t, td);
-  return t;
+  return td->xid ? nspc_lookup_type1(env->curr, td->xid) : t;
 }
+
+ANN Type scan_type(const Env env, const Type t, Type_Decl* td) {
+  if(td->next) {
+    Type_Decl *next = td->next;
+    td->next = NULL;
+    const Type owner = known_type(env, td);
+    td->next = next;
+    CHECK_OO(owner)
+    if(!owner->nspc)
+      ERR_O(td_pos(td), "type '%s' has no namespace", owner->name)
+    const Tmpl *tmpl = GET_FLAG(owner, template) ?
+      owner->e->def->base.tmpl : NULL;
+    if(tmpl)
+      CHECK_BO(template_push_types(env, tmpl))
+    const m_uint scope = env_push(env, owner, owner->nspc);
+    const Type ret = scan_type(env, t, td->next);
+    env_pop(env, scope);
+    if(tmpl)
+      nspc_pop_type(env->gwion->mp, env->curr);
+    return ret;
+  }
+  return _scan_type(env, t, td);
+}
+
index c03cc6e1167bb4ffe5e93ebe67019ef83278cc6a..ea9746d0ef3fc62ce1487f4dd5c8c3fc3a7903a6 100644 (file)
@@ -27,8 +27,8 @@ ANN Type type_nonnull(const Env env, const Type base) {
   return t;
 }
 
-ANN Type type_decl_resolve(const Env env, const Type_Decl* td) {
-  DECL_OO(const Type, base, = find_type(env, td->xid))
+ANN Type type_decl_resolve(const Env env, Type_Decl* td) {
+  DECL_OO(const Type, base, = find_type(env, td))
   if(base->e->ctx && base->e->ctx->error)
     ERR_O(td_pos(td), _("type '%s' is invalid"), base->name)
   DECL_OO(const Type, t, = scan_type(env, base, td))
@@ -65,16 +65,13 @@ ANEW ANN m_str tl2str(const Env env, Type_List tl) {
   return info.text.str;
 }
 
-ANN static inline void* type_unknown(const Env env, const ID_List id) {
-  char path[id_list_len(id)];
-  type_path(path, id);
-  env_err(env, id->pos, _("unknown type '%s'"), path);
-  did_you_mean_nspc(env->curr, s_name(id->xid));
+ANN static inline void* type_unknown(const Env env, const Type_Decl* td) {
+  env_err(env, td->pos, _("unknown type '%s'"), s_name(td->xid));
   return NULL;
 }
 
-ANN Type known_type(const Env env, const Type_Decl* td) {
+ANN Type known_type(const Env env, Type_Decl* td) {
   if(!td->xid)
     return env->gwion->type[et_undefined];
-  return type_decl_resolve(env, td) ?:type_unknown(env, td->xid);
+  return type_decl_resolve(env, td) ?:type_unknown(env, td);
 }
index 95967a3b8179302c8514a252cf5dbed5f52e629c..0822589e1bda264c09f58b8eb4fc2fe67dd5fb22 100644 (file)
@@ -54,9 +54,8 @@ ANN static void shreduler_erase(const Shreduler s, struct ShredTick_ *tk) {
 }
 
 ANN void shreduler_remove(const Shreduler s, const VM_Shred out, const m_bool erase) {
-  struct ShredTick_ *tk = out->tick;
-  assert(tk);
   MUTEX_LOCK(s->mutex);
+  struct ShredTick_ *tk = out->tick;
   if(tk == s->curr)
     s->curr = NULL;
   else if(tk == s->list)
index 2cb7dd0f467a4e94a8a0825222e54c2d6d992b3f..13b0d0ba655149d1522709e2fc2861f01d028d39 100644 (file)
@@ -75,8 +75,9 @@ ANN void vm_ini_shred(const VM* vm, const VM_Shred shred) {
 }
 
 ANN void vm_lock(VM const *vm) {
-  do MUTEX_LOCK(vm->shreduler->mutex);
-  while((vm = vm->parent));
+  if(vm->parent)
+    vm_lock(vm->parent);
+  MUTEX_LOCK(vm->shreduler->mutex);
 }
 
 ANN void vm_unlock(VM const *vm) {
@@ -92,17 +93,6 @@ ANN m_bool vm_running(VM const *vm) {
   return vm->shreduler->bbq->is_running = vm_running(vm->parent);
 }
 
-ANN static void vm_fork(VM* src, const VM_Shred shred) {
-  VM* vm = (shred->info->vm = gwion_cpy(src));
-  vm->parent = src;
-  const M_Object o = shred->info->me = new_shred(shred, 0);
-  ++shred->info->me->ref;
-  if(!src->gwion->data->child.ptr)
-    vector_init(&src->gwion->data->child);
-  vector_add(&src->gwion->data->child, (vtype)o);
-  shreduler_add(vm->shreduler, shred);
-}
-
 __attribute__((hot))
 ANN static inline void vm_ugen_init(const VM* vm) {
   const Vector v = (Vector)&vm->ugen;
@@ -145,17 +135,18 @@ ANN static inline VM_Shred init_spork_shred(const VM_Shred shred, const VM_Code
   return sh;
 }
 
-ANN static inline VM_Shred fork_shred(const VM_Shred shred, const VM_Code code) {
+ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, const m_uint retsz) {
+  VM* parent = shred->info->vm;
   const VM_Shred sh = new_shred_base(shred, code);
-  vm_fork(shred->info->vm, sh);
-  return sh;
-}
-
-ANN static inline VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code) {
-  VM *vm = shred->info->vm;
-  vm_lock(vm);
-  const VM_Shred sh = vm_running(vm) ? fork_shred(shred, code) : NULL;
-  vm_unlock(vm);
+  VM* vm = (sh->info->vm = gwion_cpy(parent));
+  vm->parent = parent;
+  const M_Object o = sh->info->me = new_shred(sh, 0);
+  ++sh->info->me->ref;
+  if(!parent->gwion->data->child.ptr)
+    vector_init(&parent->gwion->data->child);
+  vector_add(&parent->gwion->data->child, (vtype)o);
+  shreduler_add(vm->shreduler, sh);
+  fork_launch(parent, sh->info->me, retsz);
   return sh;
 }
 
@@ -333,7 +324,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
     &&timeadv,
     &&setcode,
     &&regpop, &&regpush, &&regtomem, &&regtomemother, &&overflow, &&funcusrend, &&funcmemberend,
-    &&sporkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&forkend, &&sporkend,
+    &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkend,
     &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat,
     &&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid,
     &&newobj, &&addref, &&addrefaddr, &&objassign, &&assign, &&remref,
@@ -672,10 +663,10 @@ funcmemberend:
   }
   PC_DISPATCH(shred->pc)
 sporkini:
-  if(!(child = (VAL2 ? init_spork_shred : init_fork_shred)(shred, (VM_Code)VAL))) {
-    exception(shred, "[SporkAbortedException]");
-    continue;
-  }
+  child = init_spork_shred(shred, (VM_Code)VAL);
+  DISPATCH()
+forkini:
+  child = init_fork_shred(shred, (VM_Code)VAL, VAL2),
   DISPATCH()
 sporkfunc:
 //  LOOP_OPTIM
@@ -697,8 +688,6 @@ sporkexp:
   for(m_uint i = 0; i < VAL; i+= SZ_INT)
     *(m_uint*)(child->mem + i) = *(m_uint*)(mem+i);
   DISPATCH()
-forkend:
-  fork_launch(vm, child->info->me, VAL2);
 sporkend:
   assert(!VAL); // spork are not mutable
   *(M_Object*)(reg-SZ_INT) = child->info->me;
@@ -916,6 +905,10 @@ VM* new_vm(MemPool p, const m_bool audio) {
   vector_init(&vm->shreduler->shreds);
   MUTEX_SETUP(vm->shreduler->mutex);
   vm->shreduler->bbq = vm->bbq;
+#ifndef __AFL_COMPILER
   gw_seed(vm->rand, (uint64_t)time(NULL));
+#else
+  gw_seed(vm->rand, 0);
+#endif
   return vm;
 }
diff --git a/tests/error/no_namespace.gw b/tests/error/no_namespace.gw
new file mode 100644 (file)
index 0000000..e2dd944
--- /dev/null
@@ -0,0 +1,5 @@
+#! [contains] has no namespace
+class C{
+  class private D{}
+}
+int->D d;
diff --git a/tests/tree/fork_clean.gw b/tests/tree/fork_clean.gw
deleted file mode 100644 (file)
index 4e6877b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-fork { <<< __func__ >>>; second => now; };
diff --git a/tests/tree/fork_in_fork.gw b/tests/tree/fork_in_fork.gw
deleted file mode 100644 (file)
index 395710b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-fork {
-  fork {
-    <<< __func__ >>>;
-    second => now;
-  };
-  <<< __func__ >>>;
-  second => now;
-};
diff --git a/tests/tree/fork_join.gw b/tests/tree/fork_join.gw
deleted file mode 100644 (file)
index e0b85d7..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fork { <<< __func__ >>>; } @=> Fork ref f;
-second => now;
-f.join();
diff --git a/tests/tree/fork_join2.gw b/tests/tree/fork_join2.gw
deleted file mode 100644 (file)
index dd8d58f..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-fork { <<< __func__ >>>; minute => now; } @=> Fork ref f;
-f.join();
diff --git a/util b/util
index 8054afd48c0b7c13a6e0d53e044df5812dc99ca5..b83174c4c45a7f372d317cd6cb1b0c357fba7afb 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 8054afd48c0b7c13a6e0d53e044df5812dc99ca5
+Subproject commit b83174c4c45a7f372d317cd6cb1b0c357fba7afb