]> Nishi Git Mirror - gwion.git/commitdiff
:art: Stop using cryptic symbols and other stuff :fire:
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Thu, 12 Mar 2020 18:08:59 +0000 (19:08 +0100)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Thu, 12 Mar 2020 18:08:59 +0000 (19:08 +0100)
50 files changed:
ast
examples/vararg.gw
include/emit.h
include/env/nspc.h
include/env/type.h
include/import/cdef.h
include/import/checker.h
include/import/oper.h
include/instr.h
include/lang_private.h
include/operator.h
include/vararg.h
src/emit/emit.c
src/emit/emitter.c
src/env/nspc.c
src/import/cdef.c
src/import/checker.c
src/import/oper.c
src/lib/array.c
src/lib/engine.c
src/lib/event.c
src/lib/object.c
src/lib/object_op.c [new file with mode: 0644]
src/lib/prim.c
src/lib/prim_values.c [new file with mode: 0644]
src/lib/ptr.c
src/lib/string.c
src/lib/ugen.c
src/lib/vararg.c
src/parse/check.c
src/parse/operator.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/type_decl.c
src/vm/vm.c
tests/error/connect_except.gw
tests/error/ev.gw
tests/error/vararg_after.gw [deleted file]
tests/error/vararg_before.gw [deleted file]
tests/error/vararg_invalid_acces.gw
tests/error/vararg_outside_varloop.gw [new file with mode: 0644]
tests/error/variadic_end_no_start.gw [deleted file]
tests/error/variadic_start_twice.gw [deleted file]
tests/error/variadic_test.gw [deleted file]
tests/error/varloop_not_vararg.gw [new file with mode: 0644]
tests/error/varloop_only.gw [deleted file]
tests/import/gwi_oper_emit_var.c [new file with mode: 0644]
tests/import/gwi_oper_emit_var.gw [new file with mode: 0644]
tests/sh/import.sh

diff --git a/ast b/ast
index e3939cd9cdb1f8aeab49df8db855fea945938ba9..318792cdc12f6b9632f89052c2d6cc258031b99c 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit e3939cd9cdb1f8aeab49df8db855fea945938ba9
+Subproject commit 318792cdc12f6b9632f89052c2d6cc258031b99c
index 8d1df413a4b49cdde932efe35cd57e10f852f173..7daaa2b29284f5c8a910d93b4c715a441d8da1c5 100644 (file)
@@ -1,15 +1,14 @@
 fun void test(...) {
   int i;
-  vararg.start;
-
-       if(i == 0)
-               <<< vararg $ int >>>;
-       else if(i == 1)
-               <<< vararg $ float >>>;
-       else if(i == 2)
-               <<< vararg $ Object >>>;
-       i++;
-  vararg.end;
+  varloop vararg {
+       if(i == 0)
+               <<< vararg $ int >>>;
+       else if(i == 1)
+               <<< vararg $ float >>>;
+       else if(i == 2)
+               <<< vararg $ Object >>>;
+         i++;
+  }
 }
 test(1);
 test(1, 2.3, null);
index 2c2c7569f80430535bcec869c51efb038482afeb..ff00f7f86ae4793f98de292507e8eeeffd9fb17b 100644 (file)
@@ -17,7 +17,6 @@ typedef struct Code_ {
 
 struct EmitterInfo_ {
   struct Vector_ pure;
-  struct Vector_ variadic;
   char *escape;
   f_instr finalyzer;
   VM_Code (*emit_code)(const Emitter);
index c0e3546a1c891a215289653564e86a73cdca21c4..efb75b811403d5999c53051ce0483b8ed12d3e53 100644 (file)
@@ -18,7 +18,6 @@ struct Nspc_ {
   struct VM_Code_*   dtor;
   struct NspcInfo_* info;
   HAS_OBJ
-  uint is_union;
 };
 
 extern ANEW ANN Nspc new_nspc(MemPool p, const m_str name);
index deaa596bbd79e7e57e849b2871e146e689431840..874bdf7fdf1bc7a2d9a010859bc3a498392d15e5 100644 (file)
@@ -49,7 +49,7 @@ ANN m_uint get_depth(const Type type);
 typedef enum {
   et_void, et_int, et_bool, et_char, et_float,
   et_null, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack,
-  et_function, et_fptr, et_varloop, et_lambda, et_class, et_union, et_undefined, et_auto,
+  et_function, et_fptr, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto,
   MAX_TYPE
 } type_enum;
 #endif
index 032854930482b53327d2cbe78e4702a374afee7a..f44f185543b53a7038de3dad9698e9755b34ddf2 100644 (file)
@@ -4,4 +4,5 @@ ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str, const m_str parent);
 ANN2(1,2) Type gwi_class_spe(const Gwi gwi, const m_str, const m_uint size);
 ANN2(1) void gwi_class_xtor(const Gwi gwi, const f_xtor ctor, const f_xtor dtor);
 ANN m_int gwi_class_end(const Gwi gwi);
+ANN void inherit(const Type);
 #endif
index 52e8b7a39295c8670a4727a1a59f78d9f26db3ab..510943c6b559d512fdd26bcd400fdc826a33249d 100644 (file)
@@ -41,6 +41,7 @@ typedef struct OperCK { // name_checker ?
   Instr  (*em)(Emitter, void*); // oper
   m_str lhs;// oper
   m_str rhs;// oper
+  m_uint emit_var;
 } OperCK;
 
 struct array_checker {
index cf5bedcff388ed69e5b4b3121b7885e35403ac3b..1bb02818c6999baa2f5d4ec4d32f9a7e4baec3db 100644 (file)
@@ -7,6 +7,9 @@ ANN m_int gwi_oper_emi(const Gwi gwi, const opem);
 ANN2(1) m_int gwi_oper_end(const Gwi gwi, const m_str op, const f_instr f);
 ANN m_int gwi_oper_cond(const Gwi, const m_str,  const f_instr, const f_instr);
 
+//! use this with one if the right side operator's to emit_var is set
+ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset);
+
 #define _EQUALITY_OPER(sz, sign)                                 \
   POP_REG(shred, sz*2 - SZ_INT);                                 \
   *(m_uint*)REG(-SZ_INT) = sign                                  \
index 2565644b5c211e66f45e61a84e0f61a36803f831..4e75bf5bdb1ed94a1e598fecf1e5b981fee94e9f 100644 (file)
@@ -48,11 +48,7 @@ INSTR(ArrayAlloc);
 
 /* vararg */
 INSTR(VarargIni);
-INSTR(VarargTop);
-INSTR(VarargEnd);
 
-INSTR(VecCpy);
-INSTR(VecMember);
 INSTR(PopArrayClass);
 
 INSTR(DotTmpl);
index 96479a3727b435cd171ad6c0a415a369b964bbb9..f33512651dfe6961a97d3560c565038e3a202b20 100644 (file)
@@ -11,4 +11,6 @@ ANN m_bool import_array(const Gwi gwi);
 ANN m_bool import_ptr(const Gwi gwi);
 ANN m_bool import_func(const Gwi gwi);
 ANN m_bool import_modules(const Gwi gwi);
+ANN m_bool import_object_op(const Gwi gwi);
+ANN m_bool import_values(const Gwi gwi);
 #endif
index eae103e53cf5a15583382c7e433d5a4be2144d22..c7453f11f0fa24dd7d5bc42718caaaaeb63f569c 100644 (file)
 typedef Type (*opck)(const Env, void*, m_bool*);
 typedef struct Instr_* (*opem)(const Emitter, void*);
 
-struct Op_Import {
-  Type lhs, rhs, ret;
+struct Op_Func {
   opck ck;
   opem em;
+};
+
+struct Op_Import {
+  Type lhs, rhs, ret;
+  const struct Op_Func *func;
   uintptr_t data;
   loc_t pos;
   Symbol op;
+  m_uint emit_var;
 };
 
 struct Implicit {
index f94f649f64ca9ce2d678260fdca14c6daf8af3cf..76feea9f13f7407779291a34b34e9ffa78b5d07f 100644 (file)
@@ -1,10 +1,11 @@
 #ifndef __VARARG
 #define __VARARG
 struct Vararg_ {
-  m_uint* k;      // sizes
-  Type* t;      // types
-  m_bit* d;  // d(ata)
-  m_uint o, i, s; // o(ffset), i(ndex), s(ize)
+  struct Vector_ t; // types
+  m_bit *d; // d(ata)
+  m_uint o, i, s, l;   // o(ffset), i(ndex), s(ize), l(en)
+  m_uint pc;
 };
+ANN void emit_vararg_end(const Emitter emit, const m_uint pc);
 void free_vararg(MemPool p, struct Vararg_* arg);
 #endif
index f528699cf1aaa2d4b5dcfa31856972042c8e824a..00a36785658667278eb505e8e098674f78a54aaa 100644 (file)
@@ -18,6 +18,7 @@
 #include "parser.h"
 #include "tuple.h"
 #include "specialid.h"
+#include "vararg.h"
 
 #undef insert_symbol
 #define insert_symbol(a) insert_symbol(emit->gwion->st, (a))
@@ -1225,6 +1226,30 @@ ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
   return GW_OK;
 }
 
+ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, const m_uint status) {
+  regpushi(emit, status);
+  CHECK_BB(emit_exp(emit, stmt->exp, 0))
+  emit_add_instr(emit, SetObj);
+  const Instr member = emit_add_instr(emit, DotMember4);
+  member->m_val = SZ_INT;
+  emit_add_instr(emit, int_r_assign);
+  regpop(emit, SZ_INT);
+  return GW_OK;
+}
+
+ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) {
+  CHECK_BB(variadic_state(emit, stmt, 1))
+  CHECK_BB(emit_exp(emit, stmt->exp, 0))
+  const Instr instr = emit_add_instr(emit, BranchEqInt);
+  const m_uint pc = emit_code_size(emit);
+  emit_stmt(emit, stmt->body, 1);
+  CHECK_BB(emit_exp(emit, stmt->exp, 0))
+  emit_vararg_end(emit, pc);
+  instr->m_val = emit_code_size(emit);
+  CHECK_BB(variadic_state(emit, stmt, 0))
+  return GW_OK;
+}
+
 // scope push problem
 ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
   emit_push_stack(emit);
@@ -1545,10 +1570,6 @@ ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List l) {
   return GW_OK;
 }
 
-ANN static inline Instr get_variadic(const Emitter emit) {
-  return (Instr)vector_back(&emit->info->variadic);
-}
-
 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)
@@ -1629,7 +1650,7 @@ ANN static VM_Code emit_func_def_code(const Emitter emit, const Func func) {
     return finalyze(emit, FuncReturn);
 }
 
-ANN static m_bool _fdef_body(const Emitter emit, const Func_Def fdef) {
+ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
   if(fdef->base->args)
     emit_func_def_args(emit, fdef->base->args);
   if(GET_FLAG(fdef, variadic))
@@ -1640,19 +1661,6 @@ ANN static m_bool _fdef_body(const Emitter emit, const Func_Def fdef) {
   return GW_OK;
 }
 
-ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
-  vector_add(&emit->info->variadic, 0);
-  CHECK_BB(_fdef_body(emit, fdef))
-  if(GET_FLAG(fdef, variadic)) {
-    if(!get_variadic(emit))
-      ERR_B(fdef->pos, _("invalid variadic use"))
-    if(!GET_FLAG(fdef->base->func, empty))
-      ERR_B(fdef->pos, _("invalid variadic use"))
-  }
-  vector_pop(&emit->info->variadic);
-  return GW_OK;
-}
-
 ANN static Instr me_top(MemoizeEmitter *me) {
   const Instr idx = emit_add_instr(me->emit, MemSetImm);
   idx->m_val = me->offset;
index 2527bf4c7830dcbfe312caacd8dad93ca96cb74a..6520d9fa35eefc8cf9a6b20e9a7593df5354e444 100644 (file)
@@ -19,7 +19,6 @@ ANEW Emitter new_emitter(MemPool p) {
   vector_init(&emit->stack);
   emit->info = (struct EmitterInfo_*)mp_calloc(p, EmitterInfo);
   vector_init(&emit->info->pure);
-  vector_init(&emit->info->variadic);
   emit->info->escape = escape_table(p);
   emit->info->emit_code = emit_code;
   emit->info->finalyzer = EOC;
@@ -29,7 +28,6 @@ ANEW Emitter new_emitter(MemPool p) {
 ANN void free_emitter(MemPool p, Emitter a) {
   vector_release(&a->stack);
   vector_release(&a->info->pure);
-  vector_release(&a->info->variadic);
   mp_free2(p, 256, a->info->escape);
   mp_free(p, EmitterInfo, a->info);
   mp_free(p, Emitter, a);
index 54d0f3607702b73a33b7dcc356574a23a7d29e09..e767d722e9dae104e46b68c62eb949158eba6b67 100644 (file)
@@ -24,14 +24,10 @@ ANN static inline void nspc_release_object(const Nspc a, Value value, Gwion gwio
 ANN static void free_nspc_value(const Nspc a, Gwion gwion) {
   struct scope_iter iter = { a->info->value, 0, 0 };
   Value v;
-  if(!a->is_union) {
-    while(scope_iter(&iter, &v) > 0) {
-      if(v) {
-        if(isa(v->type, gwion->type[et_object]) > 0)
-          nspc_release_object(a, v, gwion);
-        REM_REF(v, gwion);
-      }
-    }
+  while(scope_iter(&iter, &v) > 0) {
+    if(isa(v->type, gwion->type[et_object]) > 0)
+      nspc_release_object(a, v, gwion);
+    REM_REF(v, gwion);
   }
   free_scope(gwion->mp, a->info->value);
 }
index eddfa2963122cb4c5d05203bbc468f782d4b8f8b..1f6cd6c592619bc566d5a4a08407b595bb3d42b5 100644 (file)
@@ -26,14 +26,29 @@ ANN static m_bool mk_xtor(MemPool p, const Type type, const m_uint d, const ae_f
   return GW_OK;
 }
 
+ANN2(1,2) static inline m_bool class_parent(const Env env, const Type t) {
+  Type parent = t->e->parent;
+  while(parent && !GET_FLAG(parent, checked)) {
+    if(t->e->def)
+      CHECK_BB(traverse_class_def(env, t->e->def))
+    parent = parent->e->parent;
+  }
+  return GW_OK;
+}
+
+ANN void inherit(const Type t) {
+  const Nspc nspc = t->nspc, parent = t->e->parent->nspc;
+  if(!nspc || !parent)
+    return;
+  nspc->info->offset = parent->info->offset;
+  if(parent->info->vtable.ptr)
+    vector_copy2(&parent->info->vtable, &nspc->info->vtable);
+}
+
 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(t->e->parent && t->e->parent->nspc) {
-    t->nspc->info->offset = t->e->parent->nspc->info->offset;
-    if(t->e->parent->nspc->info->vtable.ptr)
-      vector_copy2(&t->e->parent->nspc->info->vtable, &t->nspc->info->vtable);
-  }
+  inherit(t);
   t->e->owner = env->curr;
   SET_FLAG(t, checked);
   env_push_type(env, t);
@@ -53,6 +68,7 @@ ANN static inline void gwi_type_flag(const Type t) {
 
 ANN static Type type_finish(const Gwi gwi, const Type t) {
   gwi_add_type(gwi, t);
+  CHECK_BO(class_parent(gwi->gwion->env, t))
   import_class_ini(gwi->gwion->env, t);
   return t;
 }
index 62edeaed0ad1b65f0bc13ef9404307f9e80c1ca7..8794839c159315bfec758dafd112d4bcbe8ee379 100644 (file)
@@ -214,7 +214,9 @@ ANN static Type_List str2tl(const Gwi gwi, const m_str s) {
 }
 
 //! convert a string to a Type_Decl
-ANN Type_Decl* str2decl(const Gwi gwi, const m_str s) {
+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 };
@@ -233,6 +235,7 @@ ANN Type_Decl* str2decl(const Gwi gwi, const m_str s) {
     td->array = new_array_sub(gwi->gwion->mp, ck.exp);
     td->array->depth = ck.depth;
   }
+  td->flag |= flag;
   return td;
 }
 
index 7e28045361614d41566f1c5bf91ea2d0e6dd4f00..c810f09655d8a522dba6c9f61c821df05b09eb6c 100644 (file)
 #include "mpool.h"
 #include "specialid.h"
 
-ANN static Type _get_type(const Gwi gwi, const m_str str) {
-  if(str == (m_str)OP_ANY_TYPE)
+ANN static Type _get_type(const Gwi gwi, const m_str s) {
+  if(s == (m_str)OP_ANY_TYPE)
     return OP_ANY_TYPE;
-  struct array_checker ck = { .str=str };
-  DECL_OO(const ID_List, list, = ck2list(gwi, &ck))
-  const Type t = find_type(gwi->gwion->env, list);
-  if(list)
-    free_id_list(gwi->gwion->mp, list);
-  return t ? (ck.depth ? array_type(gwi->gwion->env, t, ck.depth) : t) : NULL;
+  Type_Decl *td = str2decl(gwi, s);
+  const Type t = known_type(gwi->gwion->env, td);
+  free_type_decl(gwi->gwion->mp, td);
+  return t;
 }
 
 ANN2(1) static inline Type get_type(const Gwi gwi, const m_str str) {
@@ -36,8 +34,9 @@ ANN2(1,2) static int import_op(const Gwi gwi, const struct OperCK* op,
   const Type lhs = get_type(gwi, op->lhs),
              rhs = get_type(gwi, op->rhs),
              ret = get_type(gwi, op->ret);
-  const struct Op_Import opi = { lhs, rhs, ret,
-    op->ck, op->em, (uintptr_t)f, gwi->loc, op->sym };
+  const struct Op_Func opfunc = { .ck=op->ck, .em=op->em };
+  const struct Op_Import opi = { .lhs=lhs, .rhs=rhs, .ret=ret,
+    .func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=op->sym, .emit_var=op->emit_var };
   return add_op(gwi->gwion, &opi);
 }
 
@@ -55,6 +54,11 @@ ANN m_int gwi_oper_add(const Gwi gwi, Type (*ck)(Env, void*, m_bool*)) {
   return GW_OK;
 }
 
+ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset) {
+  gwi->oper->emit_var = offset;
+  return GW_OK;
+}
+
 ANN m_int gwi_oper_emi(const Gwi gwi, const opem em) {
   gwi->oper->em = em;
   return GW_OK;
@@ -70,7 +74,7 @@ ANN m_int gwi_oper_end(const Gwi gwi, const m_str op, const f_instr f) {
 
 ANN m_int gwi_oper_cond(const Gwi gwi, const m_str type,
   const f_instr f1, const f_instr f2) {
-  GWI_BB(gwi_oper_ini(gwi, NULL, type, "int"))
+  GWI_BB(gwi_oper_ini(gwi, NULL, type, "bool"))
   GWI_BB(gwi_oper_end(gwi, "@conditionnal", f1))
   GWI_BB(gwi_oper_end(gwi, "@unconditionnal", f2))
   return GW_OK;
index b27651e70f279e7e4262e1efeac647efa2abb336..fff75f3a0f363510117a558c8cd5e6016fe1aba7 100644 (file)
@@ -165,8 +165,6 @@ static OP_EMIT(opem_array_shift) {
   const Type type = bin->rhs->type;
   const Instr pop = emit_add_instr(emit, RegPop);
   pop->m_val = type->size;
-  if(!GET_FLAG(bin->lhs->type, nonnull))
-    emit_add_instr(emit, GWOP_EXCEPT);
   return emit_add_instr(emit, ArrayAppend);
 }
 
@@ -216,9 +214,6 @@ static INSTR(ArraySlice) {
 }
 
 static OP_EMIT(opem_array_slice) {
-  const Exp exp = (Exp)data;
-  if(!GET_FLAG(exp->type, nonnull))
-    emit_add_instr(emit, GWOP_EXCEPT);
   emit_add_instr(emit, ArraySlice);
   return emit_add_instr(emit, GcAdd);
 }
@@ -331,6 +326,7 @@ GWION_IMPORT(array) {
   GWI_BB(gwi_oper_ini(gwi, "@Array", (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_at))
   GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign))
+  GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_shift))
   GWI_BB(gwi_oper_emi(gwi, opem_array_shift))
   GWI_BB(gwi_oper_end(gwi, "<<", NULL))
@@ -338,11 +334,11 @@ GWION_IMPORT(array) {
   GWI_BB(gwi_oper_add(gwi, opck_array_cast))
   GWI_BB(gwi_oper_emi(gwi, opem_basic_cast))
   GWI_BB(gwi_oper_end(gwi, "$", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@Array", "int", "int"))
+  GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", "int", "int"))
   GWI_BB(gwi_oper_add(gwi, opck_array_slice))
   GWI_BB(gwi_oper_emi(gwi, opem_array_slice))
+  GWI_BB(gwi_oper_var(gwi, SZ_INT*2))
   GWI_BB(gwi_oper_end(gwi, "@slice", NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_array_slice))
   GWI_BB(gwi_oper_ini(gwi, "int", (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_not_array))
   GWI_BB(gwi_oper_end(gwi, "@array", NULL))
index c8519b9f6960238ea1c80579bf61b9cc512eaa2d..2bc1d81738216f229ff2a8c09b3f127e4272c6a3 100644 (file)
@@ -17,6 +17,7 @@
 #include "specialid.h"
 #include "gack.h"
 
+#undef insert_symbol
 static GACK(gack_class) {
   const Type type = actual_type(shred->info->vm->gwion, t) ?: t;
   INTERP_PRINTF("class(%s)", type->name)
@@ -73,7 +74,6 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   GWI_BB(gwi_oper_emi(gwi, opem_object_dot))
   GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
   GWI_BB(gwi_gack(gwi, gwi->gwion->type[et_class], gack_class)) // not working yet
-  gwi->gwion->type[et_class] = t_class;
   const Type t_undefined = gwi_mk_type(gwi, "@Undefined", SZ_INT, NULL);
   GWI_BB(gwi_set_global_type(gwi, t_undefined, et_undefined))
   const Type t_auto = gwi_mk_type(gwi, "auto", SZ_INT, NULL);
@@ -82,14 +82,6 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   const Type t_void  = gwi_mk_type(gwi, "void", 0, NULL);
   GWI_BB(gwi_gack(gwi, t_void, gack_void))
   GWI_BB(gwi_set_global_type(gwi, t_void, et_void))
-  const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
-  GWI_BB(gwi_gack(gwi, t_function, gack_function))
-  GWI_BB(gwi_set_global_type(gwi, t_function, et_function))
-  const Type t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, "@function");
-  GWI_BB(gwi_gack(gwi, t_fptr, gack_fptr))
-  GWI_BB(gwi_set_global_type(gwi, t_fptr, et_fptr))
-  const Type t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, "@function");
-  GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda))
   const Type t_gack = gwi_mk_type(gwi, "@Gack", SZ_INT, NULL);
   GWI_BB(gwi_set_global_type(gwi, t_gack, et_gack))
   const Type t_int = gwi_mk_type(gwi, "int", SZ_INT, NULL);
@@ -112,10 +104,22 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   struct SpecialId_ spid = { .type=t_now, .exec=RegPushNow, .is_const=1 };
   gwi_specialid(gwi, "now", &spid);
 
+  GWI_BB(import_object(gwi))
+  GWI_BB(import_prim(gwi))
+  const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
+  GWI_BB(gwi_gack(gwi, t_function, gack_function))
+  GWI_BB(gwi_set_global_type(gwi, t_function, et_function))
+  const Type t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, "@function");
+  GWI_BB(gwi_gack(gwi, t_fptr, gack_fptr))
+  GWI_BB(gwi_set_global_type(gwi, t_fptr, et_fptr))
+  const Type t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, "@function");
+  GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda))
   GWI_BB(gwi_typedef_ini(gwi, "int", "@internal"))
   GWI_BB(gwi_typedef_end(gwi, ae_flag_none))
 
-  GWI_BB(import_object(gwi))
+
+  GWI_BB(import_object_op(gwi))
+  GWI_BB(import_values(gwi))
 
 // TODO: check me
   const Type t_union = gwi_class_ini(gwi, "@Union", NULL);
@@ -131,7 +135,7 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   GWI_BB(gwi_oper_add(gwi, opck_new))
   GWI_BB(gwi_oper_emi(gwi, opem_new))
   GWI_BB(gwi_oper_end(gwi, "new", NULL))
-  GWI_BB(import_prim(gwi))
+//  GWI_BB(import_prim(gwi))
   GWI_BB(import_vararg(gwi))
   GWI_BB(import_string(gwi))
   GWI_BB(import_shred(gwi))
index 1e90b1de246013f8aeb82ca5d3f607daf7369cae..99718565ff05a1b91f3a3e59033c9787f418abe7 100644 (file)
@@ -24,8 +24,6 @@ static OP_CHECK(opck_eventwait) {
 static INSTR(EventWait) {
   POP_REG(shred, SZ_FLOAT);
   const M_Object event = *(M_Object*)REG(-SZ_INT);
-  if(!event)
-    Except(shred, "NullEventWait");
   shreduler_remove(shred->tick->shreduler, shred, 0);
   const Vector v = EV_SHREDS(event);
   vector_add(v, (vtype)shred);
@@ -66,7 +64,8 @@ GWION_IMPORT(event) {
   GWI_BB(gwi_func_ini(gwi, "void", "broadcast"))
   GWI_BB(gwi_func_end(gwi, event_broadcast, ae_flag_none))
   GWI_BB(gwi_class_end(gwi))
-  GWI_BB(gwi_oper_ini(gwi, "Event", "@now", "int"))
+  GWI_BB(gwi_oper_ini(gwi, "nonnull Event", "@now", "int"))
+  GWI_BB(gwi_oper_var(gwi, -SZ_FLOAT))
   _CHECK_OP("=>", eventwait, EventWait)
   return GW_OK;
 }
index 116b24076ab1f5bded7aba0c83b2484d211fa403..c421f141faf132e47f2d9adf6a775e45f28b80f9 100644 (file)
@@ -95,123 +95,6 @@ ANN void free_object(MemPool p, const M_Object o) {
   mp_free(p, M_Object, o);
 }
 
-#define describe_logical(name, op)               \
-static INSTR(name##Object) {\
-  POP_REG(shred, SZ_INT);                        \
-  const M_Object lhs = *(M_Object*)REG(-SZ_INT); \
-  const M_Object rhs = *(M_Object*)REG(0);       \
-  *(m_uint*)REG(-SZ_INT) = (lhs op rhs);         \
-  release(lhs, shred);                           \
-  release(rhs, shred);                           \
-}
-
-describe_logical(Eq,  ==)
-describe_logical(Neq, !=)
-
-static inline m_bool nonnull_check(const Type l, const Type r) {
-  return !GET_FLAG(l, nonnull) && GET_FLAG(r, nonnull);
-}
-
-static inline Type check_nonnull(const Env env, const Type l, const Type r,
-      const m_str action, const loc_t pos) {
-  if(GET_FLAG(r, nonnull)) {
-    if(isa(l, env->gwion->type[et_null]) > 0)
-      ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
-    if(isa(l, r) < 0)
-      ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
-    return r->e->parent;
-  }
-  if(l != env->gwion->type[et_null] && isa(l, r) < 0)
-    ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
-  return r;
-}
-
-static OP_CHECK(at_object) {
-  const Exp_Binary* bin = (Exp_Binary*)data;
-  const Type l = bin->lhs->type;
-  const Type r = bin->rhs->type;
-  if(opck_rassign(env, data, mut) == env->gwion->type[et_null])
-    return env->gwion->type[et_null];
-  if(check_nonnull(env, l, r, "assign", exp_self(bin)->pos) == env->gwion->type[et_null])
-    return env->gwion->type[et_null];
-  if(bin->rhs->exp_type == ae_exp_decl) {
-    SET_FLAG(bin->rhs->d.exp_decl.td, ref);
-    SET_FLAG(bin->rhs->d.exp_decl.list->self->value, ref);
-  }
-  bin->rhs->emit_var = 1;
-  return r;
-}
-
-static OP_EMIT(opem_at_object) {
-  const Exp_Binary* bin = (Exp_Binary*)data;
-  const Type l = bin->lhs->type;
-  const Type r = bin->rhs->type;
-  if(nonnull_check(l, r)) {
-    const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
-    instr->m_val = SZ_INT;
-  }
-  return emit_add_instr(emit, ObjectAssign);
-}
-
-#define STR_FORCE ":force"
-#define STRLEN_FORCE strlen(STR_FORCE)
-
-static inline Type new_force_type(MemPool p, const Type t, const Symbol sym) {
-  const Type ret = type_copy(p, t);
-  if(ret->nspc)
-    ADD_REF(ret->nspc)
-  ret->name = s_name(sym);
-  ret->flag = t->flag | ae_flag_force;
-  nspc_add_type_front(t->e->owner, sym, ret);
-  return ret;
- }
-
-static Type get_force_type(const Env env, const Type t) {
-  const size_t len = strlen(t->name);
-  char name[len + STRLEN_FORCE + 2];
-  strcpy(name, t->name);
-  strcpy(name + len, STR_FORCE);
-  const Symbol sym = insert_symbol(env->gwion->st, name);
-  return nspc_lookup_type1(t->e->owner, sym) ?: new_force_type(env->gwion->mp, t, sym);
-}
-
-static OP_CHECK(opck_object_cast) {
-  const Exp_Cast* cast = (Exp_Cast*)data;
-  const Type l = cast->exp->type;
-  const Type r = exp_self(cast)->type;
-  if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null])
-    return env->gwion->type[et_null];
-  return get_force_type(env, r);
-}
-
-static OP_EMIT(opem_object_cast) {
-  const Exp_Cast* cast = (Exp_Cast*)data;
-  const Type l = cast->exp->type;
-  const Type r = exp_self(cast)->type;
-  if(nonnull_check(l, r))
-    emit_add_instr(emit, GWOP_EXCEPT);
-  return (Instr)GW_OK;
-}
-
-static OP_CHECK(opck_implicit_null2obj) {
-  const struct Implicit* imp = (struct Implicit*)data;
-  const Type l = imp->e->type;
-  const Type r = imp->t;
-  if(check_nonnull(env, l, r, "implicitly cast", imp->e->pos) == env->gwion->type[et_null])
-    return env->gwion->type[et_null];
-  imp->e->cast_to = r;
-  return imp->t;
-}
-
-static OP_EMIT(opem_implicit_null2obj) {
-  const struct Implicit* imp = (struct Implicit*)data;
-  const Type l = imp->e->type;
-  const Type r = imp->t;
-  if(nonnull_check(l, r))
-    emit_add_instr(emit, GWOP_EXCEPT);
-  return (Instr)GW_OK;
-}
-
 static ID_CHECK(check_this) {
   if(!env->class_def)
     ERR_O(exp_self(prim)->pos, _("keyword 'this' can be used only inside class definition..."))
@@ -224,286 +107,13 @@ static GACK(gack_object) {
   INTERP_PRINTF("%p", *(M_Object*)VALUE);
 }
 
-ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td);
-
-static OP_CHECK(opck_object_scan) {
-  struct TemplateScan *ts = (struct TemplateScan*)data;
-  if(ts->td->types)
-    return scan_class(env, ts->t, ts->td);
-  ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name)
-}
-
-static const f_instr dotstatic[]  = { DotStatic, DotStatic2, DotStatic3, RegPushImm };
-ANN Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]);
-ANN static void emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) {
-  const m_uint size = v->type->size;
-  const Instr instr = emit_kind(emit, size, emit_var, dotstatic);
-  instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset);
-  instr->m_val2 = size;
-}
-
-static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 };
-ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) {
-  if(v->d.ptr && GET_FLAG(v, builtin) && GET_FLAG(v, const)) {
-    const m_uint size = v->type->size;
-    const Instr instr = emit_kind(emit, size, emit_addr, regpushimm);
-    instr->m_val = (m_uint)v->d.ptr;
-    instr->m_val2 = size;
-  } else
-    emit_dot_static_data(emit, v, emit_addr);
-}
-static const f_instr dotmember[]  = { DotMember, DotMember2, DotMember3, DotMember4 };
-
-ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
-  const Func f = exp_self(member)->type->e->d.func;
-  if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) {
-    const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
-    func_i->m_val = (m_uint)f->code;
-    return;
-  }
-  if(f->def->base->tmpl)
-    emit_add_instr(emit, DotTmplVal);
-  else {
-    const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc);
-    instr->m_val = f->vt_index;
-  }
-  return;
-}
-
-ANN static inline void emit_member(const Emitter emit, const Value v, const uint emit_addr) {
-  const m_uint size = v->type->size;
-  const Instr instr = emit_kind(emit, size, emit_addr, dotmember);
-  instr->m_val = v->from->offset;
-  instr->m_val2 = size;
-}
-
-ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
-OP_CHECK(opck_object_dot) {
-  const Exp_Dot *member = (Exp_Dot*)data;
-  const m_str str = s_name(member->xid);
-  const m_bool base_static = is_class(env->gwion, member->t_base);
-  const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base;
-  if(!the_base->nspc)
-    ERR_O(member->base->pos,
-          _("type '%s' does not have members - invalid use in dot expression of %s"),
-          the_base->name, str)
-  if(member->xid ==  insert_symbol(env->gwion->st, "this") && base_static)
-    ERR_O(exp_self(member)->pos,
-          _("keyword 'this' must be associated with object instance..."))
-  const Value value = find_value(the_base, member->xid);
-  if(!value) {
-    env_err(env, exp_self(member)->pos,
-          _("class '%s' has no member '%s'"), the_base->name, str);
-    if(member->t_base->nspc)
-      did_you_mean_type(the_base, str);
-    return NULL;
-  }
-  CHECK_BO(not_from_owner_class(env, the_base, value, exp_self(member)->pos))
-  if(!env->class_def || isa(env->class_def, value->from->owner_class) < 0) {
-    if(GET_FLAG(value, private))
-      ERR_O(exp_self(member)->pos,
-          _("can't access private '%s' outside of class..."), value->name)
-    else if(GET_FLAG(value, protect))
-      exp_self(member)->meta = ae_meta_protect;
-  }
-  if(base_static && GET_FLAG(value, member))
-    ERR_O(exp_self(member)->pos,
-          _("cannot access member '%s.%s' without object instance..."),
-          the_base->name, str)
-  if(GET_FLAG(value, const) || GET_FLAG(value, enum))
-    exp_self(member)->meta = ae_meta_value;
-  return value->type;
-}
-
-OP_EMIT(opem_object_dot) {
-  const Exp_Dot *member = (Exp_Dot*)data;
-  const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid);
-  if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
-       (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 &&
-       !is_fptr(emit->gwion, exp_self(member)->type)))) {
-    CHECK_BO(emit_exp(emit, member->base, 0))
-    emit_except(emit, member->t_base);
-  }
-  if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type))
-         emit_member_func(emit, member);
-  else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var);
-  return (Instr)GW_OK;
-}
-
 GWION_IMPORT(object) {
   const Type t_object  = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
   gwi_add_type(gwi, t_object);
   GWI_BB(gwi_gack(gwi, t_object, gack_object))
   SET_FLAG(t_object, checked); // should be set by gwi_add_type
   gwi->gwion->type[et_object] = t_object;
-
-  const Type t_null  = gwi_mk_type(gwi, "@null",  SZ_INT, "Object");
-  gwi->gwion->type[et_null] = t_null;
-  GWI_BB(gwi_set_global_type(gwi, t_null, et_null))
-  GWI_BB(gwi_oper_cond(gwi, "Object", BranchEqInt, BranchNeqInt))
-  GWI_BB(gwi_oper_ini(gwi, "Object", "Object", NULL))
-  GWI_BB(gwi_oper_add(gwi, at_object))
-  GWI_BB(gwi_oper_emi(gwi, opem_at_object))
-  GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign))
-  GWI_BB(gwi_oper_ini(gwi, "Object", "Object", "int"))
-  GWI_BB(gwi_oper_end(gwi, "==",  EqObject))
-  GWI_BB(gwi_oper_end(gwi, "!=", NeqObject))
-  GWI_BB(gwi_oper_add(gwi, opck_object_cast))
-  GWI_BB(gwi_oper_emi(gwi, opem_object_cast))
-  GWI_BB(gwi_oper_end(gwi, "$", NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj))
-  GWI_BB(gwi_oper_emi(gwi, opem_implicit_null2obj))
-  GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@null", "Object", "int"))
-  GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj))
-  GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
-  GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool"))
-  GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
-  GWI_BB(gwi_oper_end(gwi, "!", IntNot))
-  GWI_BB(gwi_oper_ini(gwi, "Object", NULL, NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_object_scan))
-  GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
-  gwi_item_ini(gwi, "@null", "null");
-  gwi_item_end(gwi, 0, NULL);
   struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 };
   gwi_specialid(gwi, "this", &spid);
   return GW_OK;
 }
-struct tmpl_info {
-  const  Class_Def cdef;
-  Type_List        call;
-  struct Vector_   type;
-  struct Vector_   size;
-  uint8_t index;
-};
-
-ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
-  vector_add(&info->type, (vtype)t);
-  const size_t len = strlen(t->name);
-  vector_add(&info->size, len);
-  return len;
-}
-
-ANN static ssize_t template_size(const Env env, struct tmpl_info* info) {
-  ID_List base = info->cdef->base.tmpl->list;
-  Type_List call = info->call;
-  size_t size = tmpl_set(info, info->cdef->base.type);
-  do {
-    DECL_OB(const Type, t, = known_type(env, call->td))
-    size += tmpl_set(info, t);
-  } while((call = call->next) && (base = base->next) && ++size);
-  return size + 16 + 3;
-}
-
-ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) {
-  const Type t = (Type)vector_at(&info->type, info->index);
-  strcpy(str, t->name);
-  return str += vector_at(&info->size, info->index);
-}
-
-ANN static void template_name(struct tmpl_info* info, m_str s) {
-  m_str str = s;
-  str = tmpl_get(info, str);
-  *str++ = '<';
-  *str++ = '~';
-  const m_uint size = vector_size(&info->type);
-  for(info->index = 1; info->index < size; ++info->index) {
-    str = tmpl_get(info, str);
-    if(info->index < size - 1)
-      *str++ = ',';
-    else {
-      *str++ = '~';
-      *str++ = '>';
-    }
-  }
-  *str = '\0';
-}
-
-ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) {
-  struct tmpl_info info = { .cdef=c, .call=call };
-  vector_init(&info.type);
-  vector_init(&info.size);
-  ssize_t sz = template_size(env, &info);
-  char name[sz];
-  if(sz > GW_ERROR)
-    template_name(&info, name);
-  vector_release(&info.type);
-  vector_release(&info.size);
-  return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL;
-}
-
-ANN m_bool template_match(ID_List base, Type_List call) {
-  while((call = call->next) && (base = base->next));
-  return !call ? GW_OK : GW_ERROR;
-}
-
-ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) {
-  DECL_OO(const Symbol, name, = template_id(env, def, call))
-  if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name))
-     return env->class_def->e->def;
-  const Type t = nspc_lookup_type1(env->curr, name);
-  if(t)
-    return t->e->def;
-  const Class_Def c = cpy_class_def(env->gwion->mp, def);
-  c->base.xid = name;
-  SET_FLAG(c, template | ae_flag_ref);
-  return c;
-
-}
-
-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,
-    loc_cpy(env->gwion->mp, t->e->def->pos));
-  a->union_def->type_xid = a->base.xid;
-  CHECK_BB(scan0_union_def(env, a->union_def))
-  SET_FLAG(a, scan0);
-  a->base.type = a->union_def->type;
-  a->base.type->e->def = a;
-  return GW_OK;
-}
-
-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"))
-  DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
-  if(a->base.type)
-    return a->base.type;
-  a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types);
-  if(t->e->parent !=  env->gwion->type[et_union])
-    CHECK_BO(scan0_class_def(env, a))
-  else
-    CHECK_BO(class2udef(env, a, t))
-  SET_FLAG(a->base.type, template);
-  if(GET_FLAG(t, builtin))
-    SET_FLAG(a->base.type, builtin);
-  CHECK_BO(scan1_cdef(env, a))
-  return a->base.type;
-}
-
-ANN static inline Symbol dot_symbol(SymTable *st, const Value v) {
-  const m_str name = !GET_FLAG(v, static) ? "this" : v->from->owner_class->name;
-  return insert_symbol(st, name);
-}
-
-ANN static inline Type dot_type(SymTable *st, const Value v) {
-  const Type t = v->from->owner_class;
-  if(!GET_FLAG(v, static))
-    return t;
-  const Value  val = nspc_lookup_value1(t->nspc->parent, insert_symbol(st, t->name));
-  return val->type;
-}
-
-ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data) {
-  const Value v = prim_self(data)->value;
-  const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data)));
-  const Exp dot = new_exp_dot(gwion->mp, base, *data);
-  dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v);
-  dot->type = prim_exp(data)->type;
-  dot->emit_var = prim_exp(data)->emit_var;
-  return dot;
-}
diff --git a/src/lib/object_op.c b/src/lib/object_op.c
new file mode 100644 (file)
index 0000000..e0ccb8b
--- /dev/null
@@ -0,0 +1,415 @@
+#include <stdlib.h>
+#include <string.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "instr.h"
+#include "object.h"
+#include "operator.h"
+#include "import.h"
+#include "emit.h"
+#include "traverse.h"
+#include "template.h"
+#include "parse.h"
+#include "specialid.h"
+
+#include "gwi.h"
+
+#undef insert_symbol
+
+#define describe_logical(name, op)               \
+static INSTR(name##Object) {\
+  POP_REG(shred, SZ_INT);                        \
+  const M_Object lhs = *(M_Object*)REG(-SZ_INT); \
+  const M_Object rhs = *(M_Object*)REG(0);       \
+  *(m_uint*)REG(-SZ_INT) = (lhs op rhs);         \
+  release(lhs, shred);                           \
+  release(rhs, shred);                           \
+}
+
+describe_logical(Eq,  ==)
+describe_logical(Neq, !=)
+static inline m_bool nonnull_check(const Type l, const Type r) {
+  return !GET_FLAG(l, nonnull) && GET_FLAG(r, nonnull);
+}
+
+static inline Type check_nonnull(const Env env, const Type l, const Type r,
+      const m_str action, const loc_t pos) {
+  if(GET_FLAG(r, nonnull)) {
+    if(isa(l, env->gwion->type[et_null]) > 0)
+      ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
+    if(isa(l, r) < 0)
+      ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
+    return r->e->parent;
+  }
+  if(l != env->gwion->type[et_null] && isa(l, r) < 0)
+    ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
+  return r;
+}
+
+static OP_CHECK(at_object) {
+  const Exp_Binary* bin = (Exp_Binary*)data;
+  const Type l = bin->lhs->type;
+  const Type r = bin->rhs->type;
+  if(opck_rassign(env, data, mut) == env->gwion->type[et_null])
+    return env->gwion->type[et_null];
+  if(check_nonnull(env, l, r, "assign", exp_self(bin)->pos) == env->gwion->type[et_null])
+    return env->gwion->type[et_null];
+  if(bin->rhs->exp_type == ae_exp_decl) {
+    SET_FLAG(bin->rhs->d.exp_decl.td, ref);
+    SET_FLAG(bin->rhs->d.exp_decl.list->self->value, ref);
+  }
+  bin->rhs->emit_var = 1;
+  return r;
+}
+
+static OP_EMIT(opem_at_object) {
+  const Exp_Binary* bin = (Exp_Binary*)data;
+  const Type l = bin->lhs->type;
+  const Type r = bin->rhs->type;
+  if(nonnull_check(l, r)) {
+    const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
+    instr->m_val = SZ_INT;
+  }
+  return emit_add_instr(emit, ObjectAssign);
+}
+
+#define STR_FORCE ":force"
+#define STRLEN_FORCE strlen(STR_FORCE)
+
+static inline Type new_force_type(MemPool p, const Type t, const Symbol sym) {
+  const Type ret = type_copy(p, t);
+  if(ret->nspc)
+    ADD_REF(ret->nspc)
+  ret->name = s_name(sym);
+  ret->flag = t->flag | ae_flag_force;
+  nspc_add_type_front(t->e->owner, sym, ret);
+  return ret;
+ }
+
+static Type get_force_type(const Env env, const Type t) {
+  const size_t len = strlen(t->name);
+  char name[len + STRLEN_FORCE + 2];
+  strcpy(name, t->name);
+  strcpy(name + len, STR_FORCE);
+  const Symbol sym = insert_symbol(env->gwion->st, name);
+  return nspc_lookup_type1(t->e->owner, sym) ?: new_force_type(env->gwion->mp, t, sym);
+}
+
+static OP_CHECK(opck_object_cast) {
+  const Exp_Cast* cast = (Exp_Cast*)data;
+  const Type l = cast->exp->type;
+  const Type r = exp_self(cast)->type;
+  if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null])
+    return env->gwion->type[et_null];
+  return get_force_type(env, r);
+}
+
+static OP_EMIT(opem_object_cast) {
+  const Exp_Cast* cast = (Exp_Cast*)data;
+  const Type l = cast->exp->type;
+  const Type r = exp_self(cast)->type;
+  if(nonnull_check(l, r))
+    emit_add_instr(emit, GWOP_EXCEPT);
+  return (Instr)GW_OK;
+}
+
+static OP_CHECK(opck_implicit_null2obj) {
+  const struct Implicit* imp = (struct Implicit*)data;
+  const Type l = imp->e->type;
+  const Type r = imp->t;
+  if(check_nonnull(env, l, r, "implicitly cast", imp->e->pos) == env->gwion->type[et_null])
+    return env->gwion->type[et_null];
+  imp->e->cast_to = r;
+  return imp->t;
+}
+
+static OP_EMIT(opem_implicit_null2obj) {
+  const struct Implicit* imp = (struct Implicit*)data;
+  const Type l = imp->e->type;
+  const Type r = imp->t;
+  if(nonnull_check(l, r))
+    emit_add_instr(emit, GWOP_EXCEPT);
+  return (Instr)GW_OK;
+}
+
+ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td);
+
+OP_CHECK(opck_object_scan) {
+  struct TemplateScan *ts = (struct TemplateScan*)data;
+  if(ts->td->types)
+    return scan_class(env, ts->t, ts->td);
+  if(GET_FLAG(ts->t, unary))
+    return ts->t;
+  ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name)
+}
+
+static const f_instr dotstatic[]  = { DotStatic, DotStatic2, DotStatic3, RegPushImm };
+ANN Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]);
+ANN static void emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) {
+  const m_uint size = v->type->size;
+  const Instr instr = emit_kind(emit, size, emit_var, dotstatic);
+  instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset);
+  instr->m_val2 = size;
+}
+
+static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 };
+ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) {
+  if(v->d.ptr && GET_FLAG(v, builtin) && GET_FLAG(v, const)) {
+    const m_uint size = v->type->size;
+    const Instr instr = emit_kind(emit, size, emit_addr, regpushimm);
+    instr->m_val = (m_uint)v->d.ptr;
+    instr->m_val2 = size;
+  } else
+    emit_dot_static_data(emit, v, emit_addr);
+}
+static const f_instr dotmember[]  = { DotMember, DotMember2, DotMember3, DotMember4 };
+
+ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
+  const Func f = exp_self(member)->type->e->d.func;
+  if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) {
+    const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
+    func_i->m_val = (m_uint)f->code;
+    return;
+  }
+  if(f->def->base->tmpl)
+    emit_add_instr(emit, DotTmplVal);
+  else {
+    const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc);
+    instr->m_val = f->vt_index;
+  }
+  return;
+}
+
+ANN static inline void emit_member(const Emitter emit, const Value v, const uint emit_addr) {
+  const m_uint size = v->type->size;
+  const Instr instr = emit_kind(emit, size, emit_addr, dotmember);
+  instr->m_val = v->from->offset;
+  instr->m_val2 = size;
+}
+
+ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
+OP_CHECK(opck_object_dot) {
+  const Exp_Dot *member = (Exp_Dot*)data;
+  const m_str str = s_name(member->xid);
+  const m_bool base_static = is_class(env->gwion, member->t_base);
+  const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base;
+  if(!the_base->nspc)
+    ERR_O(member->base->pos,
+          _("type '%s' does not have members - invalid use in dot expression of %s"),
+          the_base->name, str)
+  if(member->xid ==  insert_symbol(env->gwion->st, "this") && base_static)
+    ERR_O(exp_self(member)->pos,
+          _("keyword 'this' must be associated with object instance..."))
+  const Value value = find_value(the_base, member->xid);
+  if(!value) {
+    env_err(env, exp_self(member)->pos,
+          _("class '%s' has no member '%s'"), the_base->name, str);
+    if(member->t_base->nspc)
+      did_you_mean_type(the_base, str);
+    return NULL;
+  }
+  CHECK_BO(not_from_owner_class(env, the_base, value, exp_self(member)->pos))
+  if(!env->class_def || isa(env->class_def, value->from->owner_class) < 0) {
+    if(GET_FLAG(value, private))
+      ERR_O(exp_self(member)->pos,
+          _("can't access private '%s' outside of class..."), value->name)
+    else if(GET_FLAG(value, protect))
+      exp_self(member)->meta = ae_meta_protect;
+  }
+  if(base_static && GET_FLAG(value, member))
+    ERR_O(exp_self(member)->pos,
+          _("cannot access member '%s.%s' without object instance..."),
+          the_base->name, str)
+  if(GET_FLAG(value, const) || GET_FLAG(value, enum))
+    exp_self(member)->meta = ae_meta_value;
+  return value->type;
+}
+
+OP_EMIT(opem_object_dot) {
+  const Exp_Dot *member = (Exp_Dot*)data;
+  const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid);
+  if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
+       (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 &&
+       !is_fptr(emit->gwion, exp_self(member)->type)))) {
+    CHECK_BO(emit_exp(emit, member->base, 0))
+    emit_except(emit, member->t_base);
+  }
+  if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type))
+         emit_member_func(emit, member);
+  else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var);
+  return (Instr)GW_OK;
+}
+
+struct tmpl_info {
+  const  Class_Def cdef;
+  Type_List        call;
+  struct Vector_   type;
+  struct Vector_   size;
+  uint8_t index;
+};
+
+ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
+  vector_add(&info->type, (vtype)t);
+  const size_t len = strlen(t->name);
+  vector_add(&info->size, len);
+  return len;
+}
+
+ANN static ssize_t template_size(const Env env, struct tmpl_info* info) {
+  ID_List base = info->cdef->base.tmpl->list;
+  Type_List call = info->call;
+  size_t size = tmpl_set(info, info->cdef->base.type);
+  do {
+    DECL_OB(const Type, t, = known_type(env, call->td))
+    size += tmpl_set(info, t);
+  } while((call = call->next) && (base = base->next) && ++size);
+  return size + 16 + 3;
+}
+
+ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) {
+  const Type t = (Type)vector_at(&info->type, info->index);
+  strcpy(str, t->name);
+  return str += vector_at(&info->size, info->index);
+}
+
+ANN static void template_name(struct tmpl_info* info, m_str s) {
+  m_str str = s;
+  str = tmpl_get(info, str);
+  *str++ = '<';
+  *str++ = '~';
+  const m_uint size = vector_size(&info->type);
+  for(info->index = 1; info->index < size; ++info->index) {
+    str = tmpl_get(info, str);
+    if(info->index < size - 1)
+      *str++ = ',';
+    else {
+      *str++ = '~';
+      *str++ = '>';
+    }
+  }
+  *str = '\0';
+}
+
+ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) {
+  struct tmpl_info info = { .cdef=c, .call=call };
+  vector_init(&info.type);
+  vector_init(&info.size);
+  ssize_t sz = template_size(env, &info);
+  char name[sz];
+  if(sz > GW_ERROR)
+    template_name(&info, name);
+  vector_release(&info.type);
+  vector_release(&info.size);
+  return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL;
+}
+
+ANN m_bool template_match(ID_List base, Type_List call) {
+  while((call = call->next) && (base = base->next));
+  return !call ? GW_OK : GW_ERROR;
+}
+
+ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) {
+  DECL_OO(const Symbol, name, = template_id(env, def, call))
+  if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name))
+     return env->class_def->e->def;
+  const Type t = nspc_lookup_type1(env->curr, name);
+  if(t)
+    return t->e->def;
+  const Class_Def c = cpy_class_def(env->gwion->mp, def);
+  c->base.xid = name;
+  SET_FLAG(c, template | ae_flag_ref);
+  return c;
+
+}
+
+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,
+    loc_cpy(env->gwion->mp, t->e->def->pos));
+  a->union_def->type_xid = a->base.xid;
+  CHECK_BB(scan0_union_def(env, a->union_def))
+  SET_FLAG(a, scan0);
+  a->base.type = a->union_def->type;
+  a->base.type->e->def = a;
+  return GW_OK;
+}
+
+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"))
+  DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
+  if(a->base.type)
+    return a->base.type;
+  a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types);
+  if(t->e->parent !=  env->gwion->type[et_union])
+    CHECK_BO(scan0_class_def(env, a))
+  else
+    CHECK_BO(class2udef(env, a, t))
+  SET_FLAG(a->base.type, template);
+  if(GET_FLAG(t, builtin))
+    SET_FLAG(a->base.type, builtin);
+  CHECK_BO(scan1_cdef(env, a))
+  return a->base.type;
+}
+
+ANN static inline Symbol dot_symbol(SymTable *st, const Value v) {
+  const m_str name = !GET_FLAG(v, static) ? "this" : v->from->owner_class->name;
+  return insert_symbol(st, name);
+}
+
+ANN static inline Type dot_type(SymTable *st, const Value v) {
+  const Type t = v->from->owner_class;
+  if(!GET_FLAG(v, static))
+    return t;
+  const Value  val = nspc_lookup_value1(t->nspc->parent, insert_symbol(st, t->name));
+  return val->type;
+}
+
+ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data) {
+  const Value v = prim_self(data)->value;
+  const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data)));
+  const Exp dot = new_exp_dot(gwion->mp, base, *data);
+  dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v);
+  dot->type = prim_exp(data)->type;
+  dot->emit_var = prim_exp(data)->emit_var;
+  return dot;
+}
+
+GWION_IMPORT(object_op) {
+  const Type t_null  = gwi_mk_type(gwi, "@null",  SZ_INT, "Object");
+  gwi->gwion->type[et_null] = t_null;
+  GWI_BB(gwi_set_global_type(gwi, t_null, et_null))
+  GWI_BB(gwi_oper_cond(gwi, "Object", BranchEqInt, BranchNeqInt))
+  GWI_BB(gwi_oper_ini(gwi, "Object", "Object", NULL))
+  GWI_BB(gwi_oper_add(gwi, at_object))
+  GWI_BB(gwi_oper_emi(gwi, opem_at_object))
+  GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign))
+  GWI_BB(gwi_oper_ini(gwi, "Object", "Object", "int"))
+  GWI_BB(gwi_oper_end(gwi, "==",  EqObject))
+  GWI_BB(gwi_oper_end(gwi, "!=", NeqObject))
+  GWI_BB(gwi_oper_add(gwi, opck_object_cast))
+  GWI_BB(gwi_oper_emi(gwi, opem_object_cast))
+  GWI_BB(gwi_oper_end(gwi, "$", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj))
+  GWI_BB(gwi_oper_emi(gwi, opem_implicit_null2obj))
+  GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "@null", "Object", "int"))
+  GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj))
+  GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
+  GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool"))
+  GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
+  GWI_BB(gwi_oper_end(gwi, "!", IntNot))
+  GWI_BB(gwi_oper_ini(gwi, "Object", NULL, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_object_scan))
+  GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
+  gwi_item_ini(gwi, "@null", "null");
+  gwi_item_end(gwi, 0, NULL);
+  return GW_OK;
+}
index dcc518c4b6480c805daf06c8ae60f28e9a9a788d..5127bc6284b82cb42403d3b28bee769875207629 100644 (file)
@@ -123,44 +123,13 @@ static GWION_IMPORT(int_values) {
 }
 
 static GWION_IMPORT(int) {
+  GWI_BB(import_int_values(gwi))
   GWI_BB(gwi_oper_cond(gwi, "int", BranchEqInt, BranchNeqInt))
   GWI_BB(gwi_oper_ini(gwi, "int", "int", "int"))
   GWI_BB(import_int_op(gwi))
   GWI_BB(import_int_logical(gwi))
   GWI_BB(import_int_r(gwi))
   GWI_BB(import_int_unary(gwi))
-  return import_int_values(gwi);
-}
-
-static GWION_IMPORT(values) {
-  VM* vm = gwi_vm(gwi);
-  ALLOC_PTR(gwi->gwion->mp, d_zero, m_float, 0.0);
-  ALLOC_PTR(gwi->gwion->mp, sr,     m_float, (m_float)vm->bbq->si->sr);
-  ALLOC_PTR(gwi->gwion->mp, samp,   m_float, 1.0);
-  ALLOC_PTR(gwi->gwion->mp, ms,     m_float, (m_float)(*sr     / 1000.));
-  ALLOC_PTR(gwi->gwion->mp, second, m_float, (m_float)*sr);
-  ALLOC_PTR(gwi->gwion->mp, minute, m_float, (m_float)(*sr     * 60.0));
-  ALLOC_PTR(gwi->gwion->mp, hour,   m_float, (m_float)(*minute * 60.0));
-  ALLOC_PTR(gwi->gwion->mp, t_zero, m_float, 0.0);
-  ALLOC_PTR(gwi->gwion->mp, pi, m_float, (m_float)M_PI);
-  gwi_item_ini(gwi, "float", "samplerate");
-  gwi_item_end(gwi, ae_flag_const, sr);
-  gwi_item_ini(gwi, "float", "pi");
-  gwi_item_end(gwi, ae_flag_const, pi);
-  gwi_item_ini(gwi, "dur", "d_zero");
-  gwi_item_end(gwi, ae_flag_const, d_zero);
-  gwi_item_ini(gwi, "dur", "samp");
-  gwi_item_end(gwi, ae_flag_const, samp);
-  gwi_item_ini(gwi, "dur", "ms");
-  gwi_item_end(gwi, ae_flag_const, ms);
-  gwi_item_ini(gwi, "dur", "second");
-  gwi_item_end(gwi, ae_flag_const, second);
-  gwi_item_ini(gwi, "dur", "minute");
-  gwi_item_end(gwi, ae_flag_const, minute);
-  gwi_item_ini(gwi, "dur", "hour");
-  gwi_item_end(gwi, ae_flag_const, hour);
-  gwi_item_ini(gwi, "time", "t_zero");
-  gwi_item_end(gwi, ae_flag_const, t_zero);
   return GW_OK;
 }
 
@@ -305,6 +274,5 @@ GWION_IMPORT(prim) {
   GWI_BB(import_intfloat(gwi))
   GWI_BB(import_floatint(gwi))
   GWI_BB(import_dur(gwi))
-  GWI_BB(import_time(gwi))
-  return import_values(gwi);
+  return import_time(gwi);
 }
diff --git a/src/lib/prim_values.c b/src/lib/prim_values.c
new file mode 100644 (file)
index 0000000..9a49f76
--- /dev/null
@@ -0,0 +1,49 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "instr.h"
+#include "object.h"
+#include "emit.h"
+#include "operator.h"
+#include "import.h"
+#include "gwi.h"
+#include "driver.h"
+#include "traverse.h"
+#include "parse.h"
+#include "specialid.h"
+#include "array.h"
+#include "gack.h"
+
+GWION_IMPORT(values) {
+  VM* vm = gwi_vm(gwi);
+  ALLOC_PTR(gwi->gwion->mp, d_zero, m_float, 0.0);
+  ALLOC_PTR(gwi->gwion->mp, sr,     m_float, (m_float)vm->bbq->si->sr);
+  ALLOC_PTR(gwi->gwion->mp, samp,   m_float, 1.0);
+  ALLOC_PTR(gwi->gwion->mp, ms,     m_float, (m_float)(*sr     / 1000.));
+  ALLOC_PTR(gwi->gwion->mp, second, m_float, (m_float)*sr);
+  ALLOC_PTR(gwi->gwion->mp, minute, m_float, (m_float)(*sr     * 60.0));
+  ALLOC_PTR(gwi->gwion->mp, hour,   m_float, (m_float)(*minute * 60.0));
+  ALLOC_PTR(gwi->gwion->mp, t_zero, m_float, 0.0);
+  ALLOC_PTR(gwi->gwion->mp, pi, m_float, (m_float)M_PI);
+  gwi_item_ini(gwi, "float", "samplerate");
+  gwi_item_end(gwi, ae_flag_const, sr);
+  gwi_item_ini(gwi, "float", "pi");
+  gwi_item_end(gwi, ae_flag_const, pi);
+  gwi_item_ini(gwi, "dur", "d_zero");
+  gwi_item_end(gwi, ae_flag_const, d_zero);
+  gwi_item_ini(gwi, "dur", "samp");
+  gwi_item_end(gwi, ae_flag_const, samp);
+  gwi_item_ini(gwi, "dur", "ms");
+  gwi_item_end(gwi, ae_flag_const, ms);
+  gwi_item_ini(gwi, "dur", "second");
+  gwi_item_end(gwi, ae_flag_const, second);
+  gwi_item_ini(gwi, "dur", "minute");
+  gwi_item_end(gwi, ae_flag_const, minute);
+  gwi_item_ini(gwi, "dur", "hour");
+  gwi_item_end(gwi, ae_flag_const, hour);
+  gwi_item_ini(gwi, "time", "t_zero");
+  gwi_item_end(gwi, ae_flag_const, t_zero);
+  return GW_OK;
+}
index 3a82cb25c56610a496dff187c29f9680b9642361..ab421ef1205de190037641fb9a0ee3db4f237bd1 100644 (file)
@@ -20,9 +20,14 @@ static OP_CHECK(opck_ptr_assign) {
     ERR_N(exp_self(bin)->pos, _("left side operand is constant"));
   bin->lhs->emit_var = 1;
   Type t = bin->lhs->type;
-  do if(!strcmp(t->name, get_type_name(env, bin->rhs->type->name, 1)))
-    return bin->lhs->type;
-  while((t = t->e->parent));
+  do {
+    Type u = bin->rhs->type;
+    do {
+      const m_str str = get_type_name(env, u->name, 1);
+      if(str && !strcmp(t->name, str))
+        return bin->lhs->type;
+    } while((u = u->e->parent));
+  } while((t = t->e->parent));
   return env->gwion->type[et_null];
 }
 
@@ -32,32 +37,24 @@ static INSTR(instr_ptr_assign) {
   *(m_uint**)o->data = *(m_uint**)REG(-SZ_INT);
 }
 
-static OP_EMIT(opem_ptr_assign) {
-  const Exp_Binary* bin = (Exp_Binary*)data;
-  if(!GET_FLAG(bin->rhs->type, nonnull))
-    emit_add_instr(emit, GWOP_EXCEPT);
-  return emit_add_instr(emit, instr_ptr_assign);
-}
-
 static OP_CHECK(opck_ptr_deref) {
   const Exp_Unary* unary = (Exp_Unary*)data;
-  return exp_self(unary)->type = nspc_lookup_type1(env->curr, insert_symbol(get_type_name(env, unary->exp->type->name, 1)));
+  DECL_ON(const m_str, str, = get_type_name(env, unary->exp->type->name, 1))
+  return exp_self(unary)->type = nspc_lookup_type1(env->curr, insert_symbol(str));
 }
 
 static OP_CHECK(opck_ptr_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
   DECL_ON(const Type, t, = type_decl_resolve(env, cast->td))
-  if(!GET_FLAG(t, check)) {
-    assert(t->e->def);
+  if(!GET_FLAG(t, check))
     CHECK_BN(traverse_class_def(env, t->e->def))
-  }
   const Type to = known_type(env, cast->td->types->td);
   if(isa(cast->exp->type, to) > 0)
     return t;
   ERR_N(exp_self(cast)->pos, "invalid pointer cast")
 }
 
-static OP_CHECK(opck_implicit_ptr) {
+static OP_CHECK(opck_ptr_implicit) {
   const struct Implicit* imp = (struct Implicit*)data;
   const Exp e = imp->e;
   if(!strcmp(get_type_name(env, imp->t->name, 1), e->type->name)) {
@@ -65,6 +62,8 @@ static OP_CHECK(opck_implicit_ptr) {
       ERR_N(e->pos, _("can't cast constant to Ptr"));
     e->cast_to = imp->t;
     e->emit_var = 1;
+    if(!GET_FLAG(imp->t, check))
+      CHECK_BN(traverse_class_def(env, imp->t->e->def))
     return imp->t;
   }
   return NULL;
@@ -83,18 +82,25 @@ static INSTR(instr_ptr_deref) {
 }
 
 static INSTR(Cast2Ptr) {
-  const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_ptr]);
+  const M_Object o = new_object(shred->info->mp, shred, (Type)instr->m_val);
   *(m_uint**)o->data = *(m_uint**)REG(-SZ_INT);
   *(M_Object*)REG(-SZ_INT) = o;
 }
-/*
+
 static OP_EMIT(opem_ptr_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
   const Instr instr = emit_add_instr(emit, Cast2Ptr);
   instr->m_val = (m_uint)exp_self(cast)->type;
-  return GW_OK;
+  return instr;
 }
-*/
+
+static OP_EMIT(opem_ptr_implicit) {
+  const struct Implicit* imp = (struct Implicit*)data;
+  const Instr instr = emit_add_instr(emit, Cast2Ptr);
+  instr->m_val = (m_uint)imp->t;
+  return instr;
+}
+
 static OP_EMIT(opem_ptr_deref) {
   const Exp_Unary* unary = (Exp_Unary*)data;
   const Instr instr = emit_add_instr(emit, instr_ptr_deref);
@@ -109,17 +115,17 @@ GWION_IMPORT(ptr) {
   GWI_BB(gwi_item_ini(gwi, "@internal", "@val"))
   GWI_BB(gwi_item_end(gwi, 0, NULL))
   GWI_BB(gwi_class_end(gwi))
-  t_ptr->nspc->info->offset = SZ_INT;
-  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "Ptr", NULL))
+  SET_FLAG(t_ptr, unary);
+  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "nonnull Ptr", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_ptr_assign))
-  GWI_BB(gwi_oper_emi(gwi, opem_ptr_assign))
   GWI_BB(gwi_oper_end(gwi, ":=>", instr_ptr_assign))
-  GWI_BB(gwi_oper_add(gwi, opck_implicit_ptr))
+  GWI_BB(gwi_oper_add(gwi, opck_ptr_implicit))
+  GWI_BB(gwi_oper_emi(gwi, opem_ptr_implicit))
   GWI_BB(gwi_oper_end(gwi, "@implicit", Cast2Ptr))
-  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "Ptr", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_ptr_cast))
+  GWI_BB(gwi_oper_emi(gwi, opem_ptr_cast))
   GWI_BB(gwi_oper_end(gwi, "$", Cast2Ptr))
-  GWI_BB(gwi_oper_ini(gwi, NULL, "Ptr", NULL))
+  GWI_BB(gwi_oper_ini(gwi, NULL, "nonnull Ptr", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_ptr_deref))
   GWI_BB(gwi_oper_emi(gwi, opem_ptr_deref))
   GWI_BB(gwi_oper_end(gwi, "*", instr_ptr_deref))
index 4a3b084ab582073fa2664c3ed592be03fd695379..944d26b494f07fb5a3031a00284e39612d49da4f 100644 (file)
@@ -107,17 +107,17 @@ describe_string(Object, M_Object, SZ_INT,
   "%p%s", (void*)lhs, rhs ? STRING(rhs) : "")
 
 
-#define describe_string_plus(name, offset, type, opt, len, format, ...) \
-static INSTR(name##String_Plus) {\
-  POP_REG(shred, offset);                  \
-  const type lhs = *(type*)REG(-SZ_INT);                  \
-  const M_Object rhs = *(M_Object*)REG(offset - SZ_INT);     \
-  opt;                                              \
-  if(!rhs)                                          \
-    Except(shred, "NullPtrException");              \
-  char c[strlen(STRING(rhs)) + (len) + 1];          \
-  sprintf(c, "%s"format, STRING(rhs), __VA_ARGS__); \
-  push_string(shred, rhs, c);                       \
+#define describe_string_plus(_name, offset, type, opt, len, format, ...) \
+static INSTR(_name##String_Plus) {                       \
+  POP_REG(shred, offset);                                \
+  const type lhs = *(type*)REG(-SZ_INT);                 \
+  const M_Object rhs = *(M_Object*)REG(offset - SZ_INT); \
+  opt;                                                   \
+  if(!rhs)                                               \
+    Except(shred, "NullPtrException");                   \
+  char c[strlen(STRING(rhs)) + (len) + 1];               \
+  sprintf(c, "%s"format, STRING(rhs), __VA_ARGS__);      \
+  push_string(shred, rhs, c);                            \
 }
 describe_string_plus(,SZ_INT, M_Object, release(lhs, shred),
   lhs ? strlen(STRING(lhs)) : 0, "%s", lhs ? STRING(lhs) : "")
index 3c44d32b22d7a19ca6505699fd87fd74ff20dea3..d4c4dc182acee94f09816daebd07b20a8ed10dd2 100644 (file)
@@ -127,23 +127,10 @@ ANN void ugen_ini(const struct Gwion_ *gwion, const UGen u, const uint in, const
   }
 }
 
-ANN static m_bool connect_init(const VM_Shred shred, restrict M_Object* lhs, restrict M_Object* rhs) {
+ANN void connect_init(const VM_Shred shred, restrict M_Object* lhs, restrict M_Object* rhs) {
   POP_REG(shred, SZ_INT * 2);
   *rhs = *(M_Object*)REG(SZ_INT);
   *lhs = *(M_Object*)REG(0);
-  if(!*lhs) {
-    if(*rhs)
-      _release(*rhs, shred);
-    goto end;
-  }
-  if(!*rhs) {
-    _release(*lhs, shred);
-    goto end;
-  }
-  return GW_OK;
-end:
-  exception(shred, "UgenConnectException");
-  return GW_ERROR;
 }
 
 #define describe_connect(name, func)                                                    \
@@ -192,12 +179,12 @@ if(!UGEN(rhs)->module.gen.trig) {       \
   Except(shred, "NonTriggerException"); \
 }
 #define describe_connect_instr(name, func, opt) \
-static INSTR(name##func) {\
+static INSTR(name##func) {                      \
   M_Object lhs, rhs;                            \
-  if(connect_init(shred, &lhs, &rhs) > 0) {     \
-    opt                                         \
-    _do_(func, UGEN(lhs), UGEN(rhs)); /*}*/         \
-  release_connect(shred);      }                 \
+  connect_init(shred, &lhs, &rhs);              \
+  opt                                           \
+  _do_(func, UGEN(lhs), UGEN(rhs));             \
+  release_connect(shred);                       \
 }
 describe_connect_instr(Ugen, Connect,)
 describe_connect_instr(Ugen, Disconnect,)
@@ -355,7 +342,7 @@ GWION_IMPORT(ugen) {
   GWI_BB(gwi_func_end(gwi, ugen_get_last, ae_flag_none))
   GWI_BB(gwi_class_end(gwi))
 
-  GWI_BB(gwi_oper_ini(gwi, "UGen", "UGen", "UGen"))
+  GWI_BB(gwi_oper_ini(gwi, "nonnull UGen", "nonnull UGen", "nonnull UGen"))
   _CHECK_OP("=>", chuck_ugen, UgenConnect)
   _CHECK_OP("=<", chuck_ugen, UgenDisconnect)
   _CHECK_OP(":=>", chuck_ugen, TrigConnect)
index 046ed3246b2312cf13d885e068f84afdee0f0458..e54b3d0bc82568f4709cdb6dda5aa3b00a00902e 100644 (file)
 
 void free_vararg(MemPool p, struct Vararg_* arg) {
   xfree(arg->d);
-  xfree(arg->t);
+  vector_release(&arg->t);
   mp_free(p, Vararg, arg);
 }
 
+static DTOR(vararg_dtor) {
+  struct Vararg_ *arg = *(struct Vararg_**)o->data;
+  m_uint offset = 0;
+  for(m_uint i = 0; i < vector_size(&arg->t); ++i) {
+    const Type t = (Type)vector_at(&arg->t, arg->i);
+    *(m_uint*)(arg->d + offset) = *(m_uint*)(shred->reg - SZ_INT + offset);
+    if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
+      release(*(M_Object*)(arg->d + offset), shred);
+    offset += t->size;
+  }
+  free_vararg(shred->info->vm->gwion->mp, arg);
+}
+
+ANN static M_Object vararg_cpy(VM_Shred shred, struct Vararg_* src) {
+  const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_vararg]);
+  struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
+  vector_copy2(&src->t, &arg->t);
+  arg->l = src->l;
+  arg->d = (m_bit*)xmalloc(round2szint(arg->l));
+  m_uint offset = 0;
+  for(m_uint i = 0; i < vector_size(&arg->t); ++i) {
+    const Type t = (Type)vector_at(&arg->t, arg->i);
+    *(m_uint*)(arg->d + offset) = *(m_uint*)(src->d + offset);
+    if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
+      ++(*(M_Object*)(arg->d + offset))->ref;
+    offset += t->size;
+  }
+  arg->s = vector_size(&arg->t);
+  arg->i = src->i;
+  arg->o = src->o;
+  *(struct Vararg_**)o->data = arg;
+  return o;
+}
+
+static MFUN(mfun_vararg_cpy) {
+  *(M_Object*)RETURN = vararg_cpy(shred, *(struct Vararg_**)o->data);
+}
+
 INSTR(VarargIni) {
+  const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_vararg]);
   struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
   POP_REG(shred, instr->m_val - SZ_INT)
-  arg->d = (m_bit*)xmalloc(round2szint(instr->m_val));
-  for(m_uint i = 0; i < instr->m_val; i += SZ_INT)
-    *(m_uint*)(arg->d + i) = *(m_uint*)(shred->reg - SZ_INT + i);
+  arg->l = instr->m_val;
+  arg->d = (m_bit*)xmalloc(round2szint(arg->l));
   const Vector kinds = (Vector)instr->m_val2;
-  arg->s = vector_size(kinds);
-  arg->t = (Type*)xmalloc(arg->s * SZ_INT);
-  for(m_uint i = 0; i < arg->s; ++i) {
-    const Type t = (Type)vector_at(kinds, i);
-    *(Type*)(arg->t + i) = t;
+  vector_copy2(kinds, &arg->t);
+  m_uint offset = 0;
+  for(m_uint i = 0; i < vector_size(&arg->t); ++i) {
+    const Type t = (Type)vector_at(&arg->t, arg->i);
+    *(m_uint*)(arg->d + offset) = *(m_uint*)(shred->reg - SZ_INT + offset);
+    if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
+      ++(*(M_Object*)(arg->d + offset))->ref;
+    offset += t->size;
   }
-  *(struct Vararg_**)REG(-SZ_INT) = arg;
+  arg->s = vector_size(kinds);
+  *(struct Vararg_**)o->data = arg;
+  *(M_Object*)REG(-SZ_INT) = o;
 }
 
 static INSTR(VarargEnd) {
-  struct Vararg_* arg = *(struct Vararg_**)REG(0);
-  arg->o += arg->t[arg->i]->size;
+  const M_Object o = *(M_Object*)REG(0);
+  struct Vararg_* arg = *(struct Vararg_**)o->data;
+  arg->o += ((Type)vector_at(&arg->t, arg->i))->size;
   if(++arg->i < arg->s)
     shred->pc = instr->m_val;
   else
-    free_vararg(shred->info->mp, arg);
+    arg->i = arg->o = 0;
 }
 
 static OP_CHECK(opck_vararg_cast) {
@@ -51,39 +95,28 @@ static OP_CHECK(opck_vararg_cast) {
   return known_type(env, cast->td);
 }
 
+static OP_CHECK(opck_vararg_at) {
+  return env->gwion->type[et_null];
+}
+
 static INSTR(VarargCast) {
-  struct Vararg_* arg = *(struct Vararg_**)REG(-SZ_INT);
-  const Type t = (Type)instr->m_val2;
-  if(isa(arg->t[arg->i], t) < 0){
-         free_vararg(shred->info->mp, arg);
+  const M_Object o = *(M_Object*)REG(-SZ_INT);
+  if(!*(m_uint*)(o->data + SZ_INT))
+         Except(shred, "Using Vararg outside varloop");
+  struct Vararg_* arg = *(struct Vararg_**)o->data;
+  const Type t = (Type)instr->m_val;
+  if(isa((Type)vector_at(&arg->t, arg->i), t) < 0)
          Except(shred, "InvalidVariadicAccess");
-  }
   for(m_uint i = 0; i < t->size; i += SZ_INT)
-    *(m_uint*)REG(i - SZ_INT*2) = *(m_uint*)(arg->d + arg->o + i);
-}
-
-ANN static inline Instr get_variadic(const Emitter emit) {
-  return (Instr)vector_back(&emit->info->variadic);
-}
-
-ANN m_bool variadic_check(const Emitter emit, const loc_t pos) {
-  const Env env = emit->env;
-  if(!get_variadic(emit))
-      ERR_B(pos, _("vararg.xxx used before vararg.start"))
-  if(GET_FLAG(emit->env->func, empty))
-    ERR_B(pos, _("vararg.xxx used after vararg.end"))
-  return GW_OK;
+    *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + arg->o + i);
 }
 
 static OP_EMIT(opem_vararg_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
-  CHECK_BO(variadic_check(emit, cast->exp->pos))
-  CHECK_BO(emit_exp(emit, cast->exp, 0))
   const Instr instr = emit_add_instr(emit, VarargCast);
-  instr->m_val = get_variadic(emit)->m_val;
-  instr->m_val2 = (m_uint)exp_self(cast)->type;
-  const Instr pop = emit_add_instr(emit, RegPush);
-  pop->m_val = exp_self(cast)->type->size - SZ_INT *2;
+  instr->m_val = (m_uint)exp_self(cast)->type;
+  const Instr push = emit_add_instr(emit, RegPush);
+  push->m_val = exp_self(cast)->type->size - SZ_INT;
   return instr;
 }
 
@@ -94,7 +127,7 @@ static FREEARG(freearg_vararg) {
 
 static ID_CHECK(idck_vararg) {
   if(env->func && GET_FLAG(env->func->def, variadic))
-    return exp_self(prim)->type;
+    return type_nonnull(env, exp_self(prim)->type);
   ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function"))
 }
 
@@ -108,67 +141,33 @@ static GACK(gack_vararg) {
   INTERP_PRINTF("%p", *(M_Object*)VALUE);
 }
 
-ANN static inline m_uint emit_code_size(const Emitter emit) {
-  return vector_size(&emit->code->instr);
-}
-ANN static m_bool emit_vararg_start(const Emitter emit, const m_uint offset) {
-  const Instr instr = emit_add_instr(emit, BranchEqInt);
-  instr->m_val = emit_code_size(emit);
-  vector_set(&emit->info->variadic, vector_size(&emit->info->variadic) -1, (vtype)instr);
-  return GW_OK;
-}
-
-ANN static void emit_vararg_end(const Emitter emit, const m_uint offset) {
+ANN void emit_vararg_end(const Emitter emit, const m_uint pc) {
   const Instr pop = emit_add_instr(emit, RegPop);
   pop->m_val = SZ_INT;
-  const Instr instr = emit_add_instr(emit, VarargEnd),
-    variadic = get_variadic(emit);
-  instr->m_val = variadic->m_val;
-  variadic->m_val = emit_code_size(emit);
-  SET_FLAG(emit->env->func, empty);// mark vararg func as complete
-}
-
-static OP_CHECK(opck_vararg_dot) {
-  const Exp_Dot *member = (Exp_Dot*)data;
-  const m_str str = s_name(member->xid);
-  if(!strcmp(str, "start") || !strcmp(str, "end"))
-    return env->gwion->type[et_varloop];
-  ERR_O(exp_self(member)->pos, _("'%s' is not a vararg keyword."), str)
-}
-
-static OP_EMIT(opem_vararg_dot) {
-  const Env env = emit->env;
-  const Exp_Dot *member = (Exp_Dot*)data;
-  const m_str str = s_name(member->xid);
-  const m_uint offset = emit->code->stack_depth - SZ_INT;
-  CHECK_BO(emit_exp(emit, member->base, 0))
-  if(str[0] == 's') {
-    if(get_variadic(emit))
-      ERR_O(exp_self(member)->pos, _("vararg.start already used"))
-    emit_vararg_start(emit, offset);
-    return (Instr)GW_OK;
-  }
-  if(!get_variadic(emit))
-    ERR_O(exp_self(member)->pos, _("vararg.start not used before vararg.end"))
-  emit_vararg_end(emit, offset);
-  return (Instr)GW_OK;
+  const Instr instr = emit_add_instr(emit, VarargEnd);
+  instr->m_val = pc;
 }
-OP_CHECK(opck_object_dot);
 
 GWION_IMPORT(vararg) {
-  const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", 0, NULL);
-  GWI_BB(gwi_set_global_type(gwi, t_varloop, et_varloop))
-  const Type t_vararg  = gwi_mk_type(gwi, "@Vararg", SZ_INT, NULL);
+  const Type t_vararg  = gwi_class_ini(gwi, "Vararg", "Object");
+  gwi_class_xtor(gwi, NULL, vararg_dtor);
   gwi_gack(gwi, t_vararg, gack_vararg);
-//  gwi_gack(gwi, t_varloop, gack_vararg);// ????
-  GWI_BB(gwi_add_type(gwi, t_vararg))
-  GWI_BB(gwi_oper_ini(gwi, "@Vararg", (m_str)OP_ANY_TYPE, NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_vararg_dot))
-  GWI_BB(gwi_oper_emi(gwi, opem_vararg_dot))
-  GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
+  CHECK_BB(gwi_item_ini(gwi, "@internal", "@data"))
+  CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL))
+  CHECK_BB(gwi_item_ini(gwi, "int", "@inLoop"))
+  CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL))
+  CHECK_BB(gwi_func_ini(gwi, "Vararg", "cpy"))
+  CHECK_BB(gwi_func_end(gwi, mfun_vararg_cpy, ae_flag_none))
+  GWI_BB(gwi_class_end(gwi))
+  SET_FLAG(t_vararg, abstract | ae_flag_const);
+  CHECK_BB(gwi_set_global_type(gwi, t_vararg, et_vararg))
+  GWI_BB(gwi_oper_ini(gwi, "nonnull Vararg", (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_vararg_cast))
   GWI_BB(gwi_oper_emi(gwi, opem_vararg_cast))
   GWI_BB(gwi_oper_end(gwi, "$", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "Vararg", (m_str)OP_ANY_TYPE, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_vararg_at))
+  GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
   gwi_register_freearg(gwi, VarargIni, freearg_vararg);
   struct SpecialId_ spid = { .type=t_vararg, .is_const=1, .ck=idck_vararg, .em=idem_vararg};
   gwi_specialid(gwi, "vararg", &spid);
index 133f8364d9d12961737e1475ea0bb6d544770734..dd6410d8ad3ee68c2d4ac87708663c745fedbfee 100644 (file)
@@ -389,7 +389,7 @@ ANN static m_bool func_match_inner(const Env env, const Exp e, const Type 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);
-        e->emit_var = 1;
+//        e->emit_var = 1;
         return ret;
       }
       if(implicit)
@@ -873,17 +873,13 @@ ANN static Type check_exp_interp(const Env env, const Exp_Interp* exp) {
 DECL_EXP_FUNC(check, Type, Env)
 
 ANN Type check_exp(const Env env, const Exp exp) {
-  Exp curr = exp, next = NULL, prev = NULL;
+  Exp curr = exp;
   do {
-    next = curr->next;
     CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d)))
-    if(env->gwion->type[et_varloop] && isa(curr->type, env->gwion->type[et_varloop]) > 0 && (prev || next))
-      ERR_O(exp->pos, _("Varloop must be the only expression"))
     if(env->func && isa(curr->type, env->gwion->type[et_lambda]) < 0 && isa(curr->type, env->gwion->type[et_function]) > 0 &&
         !GET_FLAG(curr->type->e->d.func, pure))
       UNSET_FLAG(env->func, pure);
-    prev = curr;
-  } while((curr = next));
+  } while((curr = curr->next));
   return exp->type;
 }
 
@@ -901,6 +897,14 @@ ANN static m_bool check_stmt_code(const Env env, const Stmt_Code stmt) {
   return GW_OK;
 }
 
+ANN static m_bool check_stmt_varloop(const Env env, const Stmt_VarLoop stmt) {
+  CHECK_OB(check_exp(env, stmt->exp))
+  if(isa(stmt->exp->type, env->gwion->type[et_vararg]) < 0)
+    ERR_B(stmt->exp->pos, "varloop expression type must be '%s', not '%s'",
+      env->gwion->type[et_vararg]->name, stmt->exp->type->name)
+  return check_stmt(env, stmt->body);
+}
+
 ANN static inline m_bool _check_breaks(const Env env, const Stmt b) {
   RET_NSPC(check_stmt(env, b))
 }
@@ -1314,15 +1318,6 @@ ANN static m_bool check_parent(const Env env, const Class_Def cdef) {
   return GW_OK;
 }
 
-ANN static inline void inherit(const Type t) {
-  const Nspc nspc = t->nspc, parent = t->e->parent->nspc;
-  if(!parent)
-    return;
-  nspc->info->offset = parent->info->offset;
-  if(parent->info->vtable.ptr)
-    vector_copy2(&parent->info->vtable, &nspc->info->vtable);
-}
-
 ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
   if(cdef->base.tmpl && cdef->base.tmpl->list)
     CHECK_BB(template_push_types(env, cdef->base.tmpl))
index 46bd2b19c6330af73d5bda0b486fed098cb2e00f..723fa8b554ceb01eb6290267aed8328c2e059def 100644 (file)
@@ -19,6 +19,7 @@ typedef struct M_Operator_{
   Func func;
   opck ck;
   opem em;
+  m_uint emit_var;
 } M_Operator;
 
 ANN void free_op_map(Map map, struct Gwion_ *gwion) {
@@ -52,7 +53,6 @@ static m_bool op_match(const restrict Type t, const restrict Type mo) {
     return GW_OK;
   Type type = t;
   while(SAFE_FLAG(type, template) && type->e->def && type->e->def->base.tmpl && type->e->def->base.tmpl->call) type = type->e->parent;
-//  if((t && mo && mo->xid == t->xid) || (!t && !mo))
   if((type && mo && mo->xid == type->xid) || (!type && !mo))
     return GW_OK;
   return 0;
@@ -91,8 +91,11 @@ ANN static M_Operator* new_mo(MemPool p, const struct Op_Import* opi) {
   mo->rhs       = opi->rhs;
   mo->ret       = opi->ret;
   mo->instr     = (f_instr)opi->data;
-  mo->ck     = opi->ck;
-  mo->em     = opi->em;
+  if(opi->func) {
+    mo->ck     = opi->func->ck;
+    mo->em     = opi->func->em;
+  }
+  mo->emit_var = opi->emit_var;
   return mo;
 }
 
@@ -257,6 +260,15 @@ ANN static inline Nspc ensure_nspc(SymTable *st, const struct Op_Import* opi) {
   return nspc;
 }
 
+ANN void op_emit_nonnull(const Emitter emit, const Type mo, const Type opi, const m_uint offset) {
+  if(!mo || mo == OP_ANY_TYPE)
+    return;
+  if(GET_FLAG(mo, nonnull) && !GET_FLAG(opi, nonnull)) {
+    const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
+    instr->m_val = offset;
+   }
+}
+
 ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) {
   DECL_OO(Nspc, nspc, = ensure_nspc(emit->gwion->st, opi))
   Type l = opi->lhs;
@@ -267,6 +279,9 @@ ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) {
       if(!v)continue;
       const M_Operator* mo = operator_find(v, l, r);
       if(mo) {
+        const m_uint sz = opi->rhs ? opi->rhs->size : 0;
+        op_emit_nonnull(emit, mo->lhs, opi->lhs, mo->emit_var ?: sz);
+        op_emit_nonnull(emit, mo->rhs, opi->rhs, 0);
         if(mo->em)
           return mo->em(emit, (void*)opi->data);
         return handle_instr(emit, mo);
index c8fe689b334eaa1f860a64ba242ee43bb218a701..b9fbc2425f7084d95d049201e9e020e3dd97d8d9 100644 (file)
@@ -119,12 +119,13 @@ static OP_CHECK(opck_cast_similar) {
 }
 
 ANN static void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) {
-  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .ck=opck_cast_similar };
+  struct Op_Func opfunc = { .ck=opck_cast_similar };
+  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .func=&opfunc };
   add_op(env->gwion, &opi);
   opi.lhs=rhs;
   opi.rhs=lhs;
   add_op(env->gwion, &opi);
-  opi.ck = opck_implicit_similar;
+  opfunc.ck = opck_implicit_similar;
   opi.op=insert_symbol("@implicit");
   add_op(env->gwion, &opi);
 }
@@ -222,7 +223,6 @@ 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->nspc->is_union = 1;
   t->e->parent = env->gwion->type[et_union];
   add_type(env, env->curr, t);
   if(add) {
index 3fa4ebaa92b50fa41c599428dfc3df1b15c4a2c0..7b4c8ab8e679becd85a0a2c32c51ffc758d6a430 100644 (file)
@@ -105,6 +105,9 @@ ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) {
   CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos))
   ((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl);
   CHECK_OB(decl->type)
+  if(GET_FLAG(decl->type, const))
+    exp_self(decl)->meta = ae_meta_value;
+//    SET_FLAG(decl->td, const);
   const m_bool global = GET_FLAG(decl->td, global);
   if(global && decl->type->e->owner != env->global_nspc)
     ERR_B(exp_self(decl)->pos, _("type '%s' is not global"), decl->type->name)
@@ -228,6 +231,8 @@ ANN static inline m_bool scan1_stmt_match(const restrict Env env, const Stmt_Mat
 #define describe_ret_nspc(name, type, prolog, exp) describe_stmt_func(scan1, name, type, prolog, exp)
 describe_ret_nspc(flow, Stmt_Flow,, !(scan1_exp(env, stmt->cond) < 0 ||
     scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
+describe_ret_nspc(varloop, Stmt_VarLoop,, !(scan1_exp(env, stmt->exp) < 0 ||
+    scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
 describe_ret_nspc(for, Stmt_For,, !(scan1_stmt(env, stmt->c1) < 0 ||
     scan1_stmt(env, stmt->c2) < 0 ||
     (stmt->c3 && scan1_exp(env, stmt->c3) < 0) ||
@@ -267,6 +272,13 @@ ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) {
   return GW_OK;
 }
 
+ANN static Value arg_value(MemPool p, const Arg_List list) {
+  const Var_Decl var = list->var_decl;
+  const Value v = new_value(p, list->type, var->xid ? s_name(var->xid) : (m_str)__func__);
+  if(list->td)
+    v->flag = list->td->flag | ae_flag_arg;
+  return v;
+}
 ANN static m_bool scan1_args(const Env env, Arg_List list) {
   do {
     const Var_Decl var = list->var_decl;
@@ -274,6 +286,8 @@ ANN static m_bool scan1_args(const Env env, Arg_List list) {
       CHECK_BB(isres(env, var->xid, var->pos))
     if(list->td)
       CHECK_OB((list->type = void_type(env, list->td)))
+    var->value = arg_value(env->gwion->mp, list);
+    nspc_add_value(env->curr, var->xid, var->value);
   } while((list = list->next));
   return GW_OK;
 }
@@ -304,6 +318,12 @@ ANN m_bool scan1_union_def_action(const Env env, const Union_Def udef,
   else if(GET_FLAG(udef, static))
     SET_FLAG(decl.td, static);
   CHECK_BB(scan1_exp(env, l->self))
+
+Var_Decl_List list = decl.list;
+do ADD_REF(list->self->value)
+while((list = list->next));
+
+
   if(global)
     SET_FLAG(decl.td, global);
   return GW_OK;
@@ -400,6 +420,14 @@ ANN static m_bool scan_internal(const Env env, const Func_Base *base) {
   return GW_OK;
 }
 
+ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) {
+  if(fdef->base->args)
+    CHECK_BB(scan1_args(env, fdef->base->args))
+  if(!GET_FLAG(fdef, builtin) && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list)
+    CHECK_BB(scan1_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list))
+  return GW_OK;
+}
+
 ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) {
   if(fdef->base->td)
     CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)))
@@ -407,10 +435,7 @@ ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) {
     CHECK_BB(scan_internal(env, fdef->base))
   else if(GET_FLAG(fdef, op) && env->class_def)
     SET_FLAG(fdef, static);
-  if(fdef->base->args)
-    CHECK_BB(scan1_args(env, fdef->base->args))
-  if(!GET_FLAG(fdef, builtin) && fdef->d.code)
-    CHECK_BB(scan1_stmt_code(env, &fdef->d.code->d.stmt_code))
+  RET_NSPC(scan1_fbody(env, fdef))
   return GW_OK;
 }
 
index f58c26940d9f028c94c6fd9c461f69c4a1a89c68..ec8b2f5ec5d9ebc696e11a23d2c4ca0eb96d87d7 100644 (file)
@@ -38,21 +38,12 @@ ANN m_bool scan2_exp_decl(const Env env, const Exp_Decl* decl) {
   return ret;
 }
 
-ANN static Value arg_value(MemPool p, const Arg_List list) {
-  const Var_Decl var = list->var_decl;
-  const Value v = new_value(p, list->type, var->xid ? s_name(var->xid) : (m_str)__func__);
-  if(list->td)
-    v->flag = list->td->flag | ae_flag_arg;
-  return v;
-}
-
 ANN static m_bool scan2_args(const Env env, const Func_Def f) {
   Arg_List list = f->base->args;
   do {
     const Var_Decl var = list->var_decl;
     if(var->array)
       list->type = array_type(env, list->type, var->array->depth);
-    var->value = arg_value(env->gwion->mp, list);
     var->value->from->offset = f->stack_depth;
     f->stack_depth += list->type->size;
   } while((list = list->next));
@@ -222,6 +213,8 @@ HANDLE_EXP_FUNC(scan2, m_bool, Env)
 #define scan2_stmt_func(name, type, prolog, exp) describe_stmt_func(scan2, name, type, prolog, exp)
 scan2_stmt_func(flow, Stmt_Flow,, !(scan2_exp(env, stmt->cond) < 0 ||
     scan2_stmt(env, stmt->body) < 0) ? 1 : -1)
+scan2_stmt_func(varloop, Stmt_VarLoop,, !(scan2_exp(env, stmt->exp) < 0 ||
+    scan2_stmt(env, stmt->body) < 0) ? 1 : -1)
 scan2_stmt_func(for, Stmt_For,, !(scan2_stmt(env, stmt->c1) < 0 ||
     scan2_stmt(env, stmt->c2) < 0 ||
     (stmt->c3 && scan2_exp(env, stmt->c3) < 0) ||
@@ -427,10 +420,9 @@ ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f) {
   const Type r = f->base->args ? is_unary ? f->base->args->var_decl->value->type :
     f->base->args->next ? f->base->args->next->var_decl->value->type :
     f->base->ret_type : NULL;
+  struct Op_Func opfunc = { .ck=strcmp(str, "@implicit") ? 0 : opck_usr_implicit };
   struct Op_Import opi = { .op=f->base->xid, .lhs=l, .rhs=r, .ret=f->base->ret_type,
-                           .pos=f->pos, .data=(uintptr_t)f->base->func };
-  if(!strcmp(str, "@implicit"))
-    opi.ck = opck_usr_implicit;
+                           .pos=f->pos, .data=(uintptr_t)f->base->func, .func=&opfunc };
   CHECK_BB(add_op(env->gwion, &opi))
   operator_set_func(&opi);
   return GW_OK;
index 42290b6e1500e69a7d693454007f7cf52b26d3b5..c03cc6e1167bb4ffe5e93ebe67019ef83278cc6a 100644 (file)
@@ -23,6 +23,7 @@ ANN Type type_nonnull(const Env env, const Type base) {
   t->flag = base->flag;
   SET_FLAG(t, nonnull);
   nspc_add_type_front(t->e->owner, sym, t);
+  mk_class(env, t);
   return t;
 }
 
index deef382dfd181145b42e4ee29c395574c1c44cfc..599c3dfe8936acef9e3e08b54f01ec2af658c863 100644 (file)
@@ -356,7 +356,9 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
       M_Object obj;
       VM_Code code;
     } a;
+PRAGMA_PUSH()
     register VM_Shred child;
+PRAGMA_POP()
   MUTEX_LOCK(s->mutex);
   do {
     SDISPATCH();
index a71e9bd892e676d1d1704b160f6a82b60e60ea70..893c5b6edfe5475072796bbe6bb391cd68976607 100644 (file)
@@ -1,3 +1,3 @@
-#! [contains] UgenConnectException
+#! [contains] NullPtrException
 UGen ref u;
 adc => u;
index 09b835200707e311331cb81c2ae2633aaa874f8d..974c769d1eea61cbee6ecaddfa4d6213cb466b13 100644 (file)
@@ -1,3 +1,3 @@
-#! [contains] NullEventWait
+#! [contains] NullPtrException
 Event ref e;
 e => now;
diff --git a/tests/error/vararg_after.gw b/tests/error/vararg_after.gw
deleted file mode 100644 (file)
index 93375f6..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#! [contains] used after
-fun void test(...) {
-  vararg.start;
-  vararg.end;
-  vararg $ int;
-}
diff --git a/tests/error/vararg_before.gw b/tests/error/vararg_before.gw
deleted file mode 100644 (file)
index 9159d48..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#! [contains] used before
-fun void test(...) {
-  vararg $ int;
-}
index 16fc011c37657d8d0ccef749070376a1f76e6770..36ca072b85e720a35a53df01d1c9c1d40cf90beb 100644 (file)
@@ -1,7 +1,7 @@
 #! [contains] InvalidVariadicAccess
 fun void test(...) {
-  vararg.start;
-  <<<vararg $ int >>>;
-  vararg.end;
+  varloop vararg {
+    <<<vararg $ int >>>;
+  }
 }
 new Object => test;
diff --git a/tests/error/vararg_outside_varloop.gw b/tests/error/vararg_outside_varloop.gw
new file mode 100644 (file)
index 0000000..1c0abef
--- /dev/null
@@ -0,0 +1,5 @@
+#! [contains] outside varloop
+fun void test(...) {
+  <<<vararg $ int >>>;
+}
+new Object => test;
diff --git a/tests/error/variadic_end_no_start.gw b/tests/error/variadic_end_no_start.gw
deleted file mode 100644 (file)
index 7dc0c9d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#! [contains] vararg.start not used before vararg.end
-fun void test(int i, ...) {
-       vararg.end;
-#!     vararg.start;
-}
-
-test(1, 2.3, null);
diff --git a/tests/error/variadic_start_twice.gw b/tests/error/variadic_start_twice.gw
deleted file mode 100644 (file)
index dd192f7..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! [contains] vararg.start already used
-fun void test(...) { vararg.start; vararg.start;}
diff --git a/tests/error/variadic_test.gw b/tests/error/variadic_test.gw
deleted file mode 100644 (file)
index 7dc0c9d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#! [contains] vararg.start not used before vararg.end
-fun void test(int i, ...) {
-       vararg.end;
-#!     vararg.start;
-}
-
-test(1, 2.3, null);
diff --git a/tests/error/varloop_not_vararg.gw b/tests/error/varloop_not_vararg.gw
new file mode 100644 (file)
index 0000000..75d5a95
--- /dev/null
@@ -0,0 +1,4 @@
+#! varloop expression type must be
+varloop 1 {
+
+}
diff --git a/tests/error/varloop_only.gw b/tests/error/varloop_only.gw
deleted file mode 100644 (file)
index 551f231..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#! [contains] Varloop must be the only expression
-fun void test(...) {
-  <<<"test">>>, vararg.start;
-  vararg.end;
-}
diff --git a/tests/import/gwi_oper_emit_var.c b/tests/import/gwi_oper_emit_var.c
new file mode 100644 (file)
index 0000000..ea28b4a
--- /dev/null
@@ -0,0 +1,42 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "object.h"
+#include "instr.h"
+#include "gwion.h"
+#include "operator.h"
+#include "import.h"
+
+static OP_CHECK(opck_ptrext_assign) {
+  const Exp_Binary* bin = (Exp_Binary*)data;
+  if(bin->rhs->meta != ae_meta_var)
+    ERR_N(exp_self(bin)->pos, _("left side operand is constant"));
+  bin->rhs->emit_var = 1;
+  Type t = bin->rhs->type;
+  do {
+    Type u = bin->lhs->type;
+    do {
+      const m_str str = get_type_name(env, u->name, 1);
+      if(str && !strcmp(t->name, str))
+      return bin->lhs->type;
+    } while((u = u->e->parent));
+  } while((t = t->e->parent));
+  return env->gwion->type[et_null];
+}
+
+static INSTR(instr_ptrext_assign) {
+  POP_REG(shred, SZ_INT)
+  const M_Object o = *(M_Object*)REG(-SZ_INT);
+  *(m_float**)o->data = *(m_float**)REG(0);
+}
+
+GWION_IMPORT(typedef_test) {
+  GWI_OB(gwi_class_ini(gwi, "PtrExt", "Ptr<~float~>"))
+  GWI_BB(gwi_class_end(gwi))
+  GWI_BB(gwi_oper_ini(gwi, "nonnull PtrExt", "float", NULL))
+  GWI_BB(gwi_oper_var(gwi, SZ_INT))
+  GWI_BB(gwi_oper_add(gwi, opck_ptrext_assign))
+  GWI_BB(gwi_oper_end(gwi, "<=:", instr_ptrext_assign))
+  return GW_OK;
+}
diff --git a/tests/import/gwi_oper_emit_var.gw b/tests/import/gwi_oper_emit_var.gw
new file mode 100644 (file)
index 0000000..31a9b50
--- /dev/null
@@ -0,0 +1,5 @@
+1234.5 => float f;
+PtrExt ref ptr;
+<<< ptr >>>;
+ptr <=: f;
+<<< f >>>;
index e4b35b689dd623e5f626acb05f36873540c9af94..c9f2ab760c9b20f6a997267d930a514949222da8 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/bash
-# [test] #74
+# [test] #75
 
 n=0
 [ "$1" ] && n="$1"