]> Nishi Git Mirror - gwion.git/commitdiff
:art: Introcude Lambdas :smile:
authorfennecdjay <astor.jeremie@wanadoo.fr>
Mon, 25 Feb 2019 13:58:21 +0000 (14:58 +0100)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Mon, 25 Feb 2019 13:58:21 +0000 (14:58 +0100)
28 files changed:
ast
include/opcode.h
include/parse.h
include/type.h
opcode.txt
src/emit/emit.c
src/lib/engine.c
src/lib/func.c
src/parse/check.c
src/parse/scan1.c
src/parse/scan2.c
src/vm/vm.c
tests/error/empty_member_ptr.gw
tests/error/lambda_mismatch1.gw [new file with mode: 0644]
tests/error/lambda_mismatch2.gw [new file with mode: 0644]
tests/error/lambda_mismatch3.gw [new file with mode: 0644]
tests/new/global_func0.gw [new file with mode: 0644]
tests/new/global_func1.gw [new file with mode: 0644]
tests/new/global_func3.gw [new file with mode: 0644]
tests/new/global_var.gw [new file with mode: 0644]
tests/new/global_var1.gw [new file with mode: 0644]
tests/new/lambda.gw [new file with mode: 0644]
tests/new/lambda2.gw [new file with mode: 0644]
tests/new/lambda3.gw [new file with mode: 0644]
tests/new/local_func.gw [new file with mode: 0644]
tests/new/spork.gw [new file with mode: 0644]
tests/new/stackov.gw [new file with mode: 0644]
tests/new/stackov2.gw [new file with mode: 0644]

diff --git a/ast b/ast
index 787c2856a8ec0e24b9d174b003e9b395d01080e7..f0e1cb2cfe0ea1fe5ee0d73f94a1f5c4ef05c955 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 787c2856a8ec0e24b9d174b003e9b395d01080e7
+Subproject commit f0e1cb2cfe0ea1fe5ee0d73f94a1f5c4ef05c955
index b10319aae77df53d39909495ae8fa3460e5a7fde..93547db2e34391dd8b90b63aba0f91636b0e9376 100644 (file)
@@ -16,6 +16,7 @@ enum {
   RegPushBase3,
   RegPushBase4,
   RegDup,
+  RegDup2,
   MemSetImm,
   RegPop,
   RegPushMe,
@@ -171,6 +172,7 @@ enum {
 #define  RegPushBase3        (f_instr)RegPushBase3
 #define  RegPushBase4        (f_instr)RegPushBase4
 #define  RegDup              (f_instr)RegDup
+#define  RegDup2             (f_instr)RegDup2
 #define  MemSetImm           (f_instr)MemSetImm
 #define  RegPop              (f_instr)RegPop
 #define  RegPushMe           (f_instr)RegPushMe
index 8b5b554a6502a830788c44e9c7b7a029ff0a26b0..8fa50e4e0c0cf86583bd40c2c0c8beefc024c271 100644 (file)
@@ -22,7 +22,7 @@ static const _exp_func exp_func[] = {
   (_exp_func)prefix##_exp_decl,    (_exp_func)prefix##_exp_binary, (_exp_func)prefix##_exp_unary, \
   (_exp_func)prefix##_exp_primary, (_exp_func)prefix##_exp_cast,   (_exp_func)prefix##_exp_post,  \
   (_exp_func)prefix##_exp_call,    (_exp_func)prefix##_exp_array,  (_exp_func)prefix##_exp_if,    \
-  (_exp_func)prefix##_exp_dot,     (_exp_func)prefix##_exp_dur                                    \
+  (_exp_func)prefix##_exp_dot,     (_exp_func)prefix##_exp_dur,    (_exp_func)prefix##_exp_lambda \
 };
 
 #define DECL_SECTION_FUNC(prefix)                                                                 \
index 9a99411c5a56c803e16ec4ec1c3044d13afa19d6..cda59b784f2f73f468079b3ed7ed936e73a99b0b 100644 (file)
@@ -21,7 +21,7 @@ struct Type_ {
 
 Type t_void, t_int, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4,
   t_null, t_object, t_shred, t_event, t_ugen, t_string, t_ptr, t_array, t_gack,
-  t_function, t_fptr, t_vararg, t_class, t_union;
+  t_function, t_fptr, t_vararg, t_lambda, t_class, t_union;
 
 ANN2(2) ANEW Type new_type(const m_uint xid, const m_str name, const Type);
 ANEW ANN Type type_copy(const Type type);
index bd71508383d467183d900900833036cef6be98e5..217f8ee063f4661fc8d46f1ca403c0e417cc2c57 100644 (file)
@@ -13,6 +13,7 @@ RegPushBase2
 RegPushBase3
 RegPushBase4
 RegDup
+RegDup2
 MemSetImm
 RegPop
 RegPushMe
index e425fbfacd4e71957c5203ca74afcbdd4e5f5c50..16fb4e65dad92abf81428ee064a89053af429a77 100644 (file)
@@ -185,7 +185,8 @@ ANN ArrayInfo* emit_array_extend_inner(const Emitter emit, const Type t, const E
 }
 
 ANN void emit_ext_ctor(const Emitter emit, const VM_Code code) { GWDEBUG_EXE
-  emit_add_instr(emit, RegDup);
+  const Instr dup = emit_add_instr(emit, RegDup);
+//  dup->m_val = SZ_INT;
   const Instr push_f = emit_add_instr(emit, RegPushImm);
   push_f->m_val = (m_uint)code;
   const Instr offset = emit_add_instr(emit, RegSetImm);
@@ -757,7 +758,9 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) { GWDEBUG_EXE
     m_bit exec = back->opcode;
     m_uint val = back->m_val;
     m_uint val2 = back->m_val2;
-    back->opcode = RegDup;
+    back->opcode = RegDup2;
+    back->m_val = f->def->stack_depth;
+printf("exec %lu %p\n", exec, f->code);
     const Instr instr = emit_add_instr(emit, exec);
     instr->m_val = val;
     instr->m_val2 = val2;
@@ -889,6 +892,20 @@ ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) { GWDEBU
   return ret;
 }
 
+ANN static m_bool emit_exp_lambda(const Emitter emit, const Exp_Lambda * lambda) { GWDEBUG_EXE
+  if(lambda->def) {
+  const m_uint scope = !lambda->owner ?
+    emit->env->scope : emit_push_type(emit, lambda->owner);
+  CHECK_BB(emit_func_def(emit, lambda->def))
+  const Instr instr = emit_add_instr(emit, RegPushImm);
+  instr->m_val = lambda->def->func->code;
+  if(lambda->owner)
+    emit_pop(emit, scope);
+  } else
+    emit_add_instr(emit, RegPushImm);
+  return GW_OK;
+}
+
 DECL_EXP_FUNC(emit)
 
 ANN2(1) static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) { GWDEBUG_EXE
index 1234f44e83544eb020b86e349c7beb629351aa02..680d97e51e847619a83aec2de3466b0f08ceae32 100644 (file)
@@ -25,6 +25,8 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   CHECK_BB(gwi_add_type(gwi, t_function))
   CHECK_OB((t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, t_function)))
   CHECK_BB(gwi_add_type(gwi, t_fptr))
+  CHECK_OB((t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, t_function)))
+  CHECK_BB(gwi_add_type(gwi, t_fptr))
   CHECK_OB((t_gack = gwi_mk_type(gwi, "@Gack", SZ_INT, NULL)))
   CHECK_BB(gwi_add_type(gwi, t_gack))
   CHECK_OB((t_int = gwi_mk_type(gwi, "int", SZ_INT, NULL)))
index 907fa8db17fbaa33f60fb622b4706eb271b5ac16..f0e273dfe480ee075781ddef4c67f0e45f9d67fa 100644 (file)
@@ -20,8 +20,16 @@ ANN m_bool emit_exp_spork(const Emitter, const Exp_Unary*);
 static INSTR(FuncAssign) { GWDEBUG_EXE
   POP_REG(shred, SZ_INT)
   **(Func**)REG(0) = *(Func*)REG(-SZ_INT);
-  if(GET_FLAG(*(Func*)REG(-SZ_INT), member))
+}
+
+static INSTR(LambdaAssign) { GWDEBUG_EXE
+  POP_REG(shred, SZ_INT)
+  **(Func**)REG(0) = *(Func*)REG(-SZ_INT);
+//  if(GET_FLAG(*(Func*)REG(-SZ_INT), member))
+//  if(instr->m_val) {
     POP_REG(shred, SZ_INT)
+    *(Func*)REG(-SZ_INT) = *(Func*)REG(0);
+//  }
 }
 
 static OP_CHECK(opck_func_call) {
@@ -30,6 +38,25 @@ static OP_CHECK(opck_func_call) {
   return check_exp_call1(env, &call);
 }
 
+static OP_EMIT(opem_func_assign) {
+  Exp_Binary* bin = (Exp_Binary*)data;
+  if(isa(bin->lhs->type, t_lambda) < 0 && GET_FLAG(bin->rhs->type->d.func, member)) 
+{
+//  if(GET_FLAG(bin->rhs->type->d.func, member)) {
+    const Instr instr = emit_add_instr(emit, LambdaAssign);
+instr->m_val = SZ_INT;
+    return GW_OK;
+  }
+  const Instr instr = emit_add_instr(emit, FuncAssign);
+  if(GET_FLAG(bin->rhs->type->d.func, member)) {
+//instr->m_val = 1;
+//emit_add_instr(emit, RegDup);
+//instr->m_val = -SZ_INT;
+//    const Instr emit_add_instr
+//    exit(2);
+  }
+  return GW_OK;
+}
 ANN static Type fptr_type(Exp_Binary* bin) {
   const Func l_func = bin->lhs->type->d.func;
   const Func r_func = bin->rhs->type->d.func;
@@ -48,15 +75,52 @@ ANN static Type fptr_type(Exp_Binary* bin) {
   return NULL;
 }
 
+ANN2(1,3,4) m_bool check_lambda(Env env, Type owner, Exp_Lambda *lambda, Func_Def def) {
+  const m_uint scope = ((lambda->owner = owner)) ?
+    env_push_type(env, owner) : env->scope;
+  Arg_List base = def->arg_list, arg = lambda->arg;
+  while(base && arg) {
+    arg->td = base->td;
+    base = base->next;
+    arg = arg->next;
+  }
+  if(base || arg)
+    ERR_B(lambda->self->pos, "argument number does not match for lambda")
+  lambda->def = new_func_def(def->td, insert_symbol("lambda"),
+    lambda->arg, lambda->code, def->flag);
+  const m_bool ret = traverse_func_def(env, lambda->def);
+  arg=lambda->arg;
+  while(arg) {
+    arg->td = NULL;
+    arg = arg->next;
+  }
+  if(owner)
+    env_pop(env, scope);
+  return ret;
+}
+
 static OP_CHECK(opck_fptr_at) {
   Exp_Binary* bin = (Exp_Binary*)data;
+  bin->rhs->emit_var = 1;
+  if(isa(bin->lhs->type, t_lambda) > 0) {
+    Exp_Lambda *lambda = &bin->lhs->d.exp_lambda;
+/*
+    lambda->def = new_func_def(bin->rhs->type->d.func->def->td,
+      insert_symbol("lambda"), bin->rhs->type->d.func->def->arg_list,
+      lambda->code, bin->rhs->type->d.func->def->flag);
+    CHECK_BO(traverse_func_def(env, lambda->def))
+*/
+    const Type owner = nspc_lookup_type1(bin->rhs->type->owner->parent,
+       insert_symbol(bin->rhs->type->owner->name));
+    CHECK_BO(check_lambda(env, owner, lambda, bin->rhs->type->d.func->def))
+    return bin->rhs->type;
+  }
   const Func l_func = bin->lhs->type->d.func;
   const Func_Def l_fdef = l_func->def;
   const Type l_type = l_func->value_ref->owner_class;
   const Func r_func = bin->rhs->type->d.func;
   const Func_Def r_fdef = r_func->def;
   const Type r_type = r_func->value_ref->owner_class;
-  bin->rhs->emit_var = 1;
   if(!r_type && l_type)
     ERR_N(bin->self->pos, "can't assign member function to non member function pointer")
   else if(r_type && !l_type) {
@@ -95,6 +159,18 @@ static OP_CHECK(opck_fptr_cast) {
   return t;
 }
 
+static OP_EMIT(opem_fptr_cast) {
+  CHECK_BB(opem_basic_cast(emit, data))
+  Exp_Cast* cast = (Exp_Cast*)data;
+  if(GET_FLAG(cast->exp->type->d.func, member)) {
+    const Instr instr = emit_add_instr(emit, RegPop);
+    instr->m_val = SZ_INT*2;
+    const Instr dup = emit_add_instr(emit, RegDup);
+    dup->m_val = -SZ_INT*2;
+  }
+  return GW_OK;
+}
+
 ANN Type check_exp_unary_spork(const Env env, const Stmt code);
 
 static OP_CHECK(opck_spork) {
@@ -119,9 +195,10 @@ GWION_IMPORT(func) {
   CHECK_BB(gwi_oper_end(gwi, op_chuck, NULL))
   CHECK_BB(gwi_oper_ini(gwi, "@function", "@func_ptr", NULL))
   CHECK_BB(gwi_oper_add(gwi, opck_fptr_at))
-  CHECK_BB(gwi_oper_end(gwi, op_ref, FuncAssign))
+  CHECK_BB(gwi_oper_emi(gwi, opem_func_assign))
+  CHECK_BB(gwi_oper_end(gwi, op_ref, NULL /*FuncAssign*/))
   CHECK_BB(gwi_oper_add(gwi, opck_fptr_cast))
-  CHECK_BB(gwi_oper_emi(gwi, opem_basic_cast))
+  CHECK_BB(gwi_oper_emi(gwi, opem_fptr_cast))
   CHECK_BB(gwi_oper_end(gwi, op_cast, NULL))
   CHECK_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL))
   CHECK_BB(gwi_oper_add(gwi, opck_spork))
index f9a6ab580ed18434682b0650394b431ecfc0ed46..df5ffea6abdb3e5574aa01ec31687c9cf2be9de4 100644 (file)
@@ -321,7 +321,14 @@ ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t,
   const m_bool match = (specific ? e->type == t : isa(e->type, t) > 0) &&
     e->type->array_depth == t->array_depth &&
     array_base(e->type) == array_base(t);
-  if(!match && implicit) {
+  if(!match) {
+    if(e->type == t_lambda && isa(t, t_fptr) > 0) {
+      const Type owner = nspc_lookup_type1(t->owner->parent,
+        insert_symbol(t->owner->name));
+      return check_lambda(env, owner, &e->d.exp_lambda, t->d.func->def);
+    }
+  }
+  if(implicit) {
     const struct Implicit imp = { e, t };
     struct Op_Import opi = { .op=op_impl, .lhs=e->type, .rhs=t, .data=(m_uint)&imp };
     return op_check(env, &opi) ? 1 : -1;
@@ -571,8 +578,37 @@ ANN static m_bool check_exp_call1_check(const Env env, const Exp exp) {
   return GW_OK;
 }
 
+ANN static inline void set_call(const Exp e, const Func f) {
+  if(e->exp_type == ae_exp_call)
+    e->d.exp_call.m_func = f;
+  else // if(e->exp_type == ae_exp_binary)
+    e->d.exp_binary.func = f;
+}
+
+ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
+  if(exp->args)
+    CHECK_OO(check_exp(env, exp->args))
+  Exp_Lambda *lambda = &exp->func->d.exp_lambda;
+  Arg_List arg = lambda->arg;
+  Exp e = exp->args;
+  while(arg && e) {
+    arg->type = e->type;
+    arg = arg->next;
+    e = e->next;
+  }
+  if(arg || e)
+    ERR_O(exp->self->pos, "argument number does not match for lambda")
+  lambda->def = new_func_def(NULL, insert_symbol("lambda"),
+    lambda->arg, lambda->code, 0);
+  CHECK_BO(traverse_func_def(env, lambda->def))
+  set_call(exp->self, lambda->def->func);
+  return lambda->def->ret_type ?: (lambda->def->ret_type = t_void);
+}
+
 ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
   CHECK_BO(check_exp_call1_check(env, exp->func))
+  if(exp->func->type == t_lambda)
+    return check_lambda_call(env, exp);
   if(GET_FLAG(exp->func->type->d.func, ref)) {
     const Value value = exp->func->type->d.func->value_ref;
     CHECK_BO(traverse_template(env, value->owner_class->def))
@@ -584,10 +620,7 @@ ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
   const Func func = find_func_match(env, exp->func->type->d.func, exp->args);
   if(!func)
     return function_alternative(exp->func->type, exp->args);
-  if(exp->self->exp_type == ae_exp_call)
-    exp->self->d.exp_call.m_func = func;
-  else // if(exp->self->exp_type == ae_exp_binary)
-    exp->self->d.exp_binary.func = func;
+  set_call(exp->self, func);
   return func->def->ret_type;
 }
 
@@ -721,12 +754,13 @@ ANN static Type check_exp_dot(const Env env, Exp_Dot* member) { GWDEBUG_EXE
 ANN static m_bool check_stmt_type(const Env env, const Stmt_Type stmt) { GWDEBUG_EXE
   return stmt->type->def ? check_class_def(env, stmt->type->def) : 1;
 }
+ANN static Type check_exp_lambda(const Env env, const Exp_If* exp_if) { return t_lambda; }
 
 static const _type_func exp_func[] = {
   (_type_func)check_exp_decl,    (_type_func)check_exp_binary, (_type_func)check_exp_unary,
   (_type_func)check_exp_primary, (_type_func)check_exp_cast,   (_type_func)check_exp_post,
   (_type_func)check_exp_call,    (_type_func)check_exp_array,  (_type_func)check_exp_if,
-  (_type_func)check_exp_dot,     (_type_func)check_exp_dur
+  (_type_func)check_exp_dot,     (_type_func)check_exp_dur, (_type_func)check_exp_lambda
 };
 
 ANN static inline Type check_exp(const Env env, const Exp exp) { GWDEBUG_EXE
@@ -865,6 +899,17 @@ ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) { GWDEBU
     ERR_B(stmt->self->pos, "'return' statement found outside function definition")
   const Type ret_type = stmt->val ? check_exp(env, stmt->val) : t_void;
   CHECK_OB(ret_type)
+if(env->func->value_ref->type == t_lambda) {
+  if(env->func->def->ret_type) {
+    if(isa(ret_type, env->func->def->ret_type) < 0) {
+      if(isa(env->func->def->ret_type, ret_type) < 0) {
+        ERR_B(stmt->self->pos, "return types do not match for lambda expression")
+      }
+    }
+  }
+  env->func->value_ref->type = ret_type;
+  return GW_OK;
+}
   if(isa(ret_type, t_null) > 0 &&
      isa(env->func->def->ret_type, t_object) > 0)
     return GW_OK;
@@ -1101,17 +1146,18 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
   env->func = func;
   ++env->scope;
   nspc_push_value(env->curr);
-  if(f->arg_list)
-    ret = check_func_args(env, f->arg_list);
+  if((f->arg_list && (ret = check_func_args(env, f->arg_list)) > 0) || !f->arg_list) {
   const Value variadic = GET_FLAG(f, variadic) ? set_variadic(env) : NULL;
   if(!GET_FLAG(f, builtin) && check_stmt_code(env, &f->d.code->d.stmt_code) < 0)
-    ret = err_msg(f->td->xid->pos, "...in function '%s'", s_name(f->name));
+    ret = err_msg(f->td ? f->td->xid->pos : 0, "...in function '%s'", 
+       s_name(f->name));
   if(variadic)
     REM_REF(variadic)
   if(GET_FLAG(f, builtin))
     func->code->stack_depth = f->stack_depth;
   else if(GET_FLAG(f, op))
     operator_func(func);
+  }
   nspc_pop_value(env->curr);
   --env->scope;
   env->func = former;
index 166fe4463f966789b60ef0af6b44699ea48afe0f..c15c2d1e5f7da0f3f23c4eed422f3766896ef24d 100644 (file)
@@ -145,6 +145,7 @@ ANN static inline m_bool scan1_exp_unary(const restrict Env env, const Exp_Unary
   return !(unary->op == op_spork && unary->code) ? GW_OK : scan1_stmt(env, unary->code);
 }
 
+#define scan1_exp_lambda dummy_func
 HANDLE_EXP_FUNC(scan1, m_bool, 1)
 
 #define describe_ret_nspc(name, type, prolog, exp) describe_stmt_func(scan1, name, type, prolog, exp)
@@ -195,12 +196,13 @@ ANN m_bool scan1_stmt_enum(const Env env, const Stmt_Enum stmt) { GWDEBUG_EXE
   } while((list = list->next));
   return GW_OK;
 }
-
+#include "func.h"
 ANN static m_bool scan1_args(const Env env, Arg_List list) { GWDEBUG_EXE
   do {
     const Var_Decl var = list->var_decl;
     CHECK_BB(isres(var->xid))
-    CHECK_OB((list->type = void_type(env, list->td, var->pos)))
+    if(list->td) // lambda
+      CHECK_OB((list->type = void_type(env, list->td, var->pos)))
   } while((list = list->next));
   return GW_OK;
 }
@@ -277,7 +279,8 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
   ++env->scope;
   if(GET_FLAG(f, dtor) && !env->class_def)
     ERR_B(f->td->xid->pos, "dtor must be in class def!!")
-  CHECK_OB((f->ret_type = known_type(env, f->td)))
+  if(f->td)//lambda
+    CHECK_OB((f->ret_type = known_type(env, f->td)))
   if(f->arg_list)
     CHECK_BB(scan1_args(env, f->arg_list))
   if(!GET_FLAG(f, builtin))
index c215813c6e05da247c156564ac9bac3d94130768..d19090643292517da4d767c6e2e0d9702ef9019e 100644 (file)
@@ -52,7 +52,8 @@ ANN static Value arg_value(const Env env, const Arg_List list) {
   const Var_Decl var = list->var_decl;
   if(!var->value) {
     const Value v = new_value(env->gwion, list->type, s_name(var->xid));
-    v->flag = list->td->flag | ae_flag_arg;
+    if(list->td) // lambda
+      v->flag = list->td->flag | ae_flag_arg;
     return v;
   }
   var->value->type = list->type;
@@ -214,6 +215,7 @@ ANN static m_bool scan2_exp_unary(const Env env, const Exp_Unary * unary) {
   return GW_OK;
 }
 
+#define scan2_exp_lambda dummy_func
 HANDLE_EXP_FUNC(scan2, m_bool, 1)
 
 #define scan2_stmt_func(name, type, prolog, exp) describe_stmt_func(scan2, name, type, prolog, exp)
@@ -504,7 +506,8 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
     const Func func = nspc_lookup_func1(env->curr, insert_symbol(func_name));
     if(func) {
       f->ret_type = type_decl_resolve(env, f->td);
-      return f->arg_list ? scan2_args(env, f) : GW_OK;
+      // check arg_list->type for lambdas
+      return (f->arg_list && f->arg_list->type) ? scan2_args(env, f) : GW_OK;
     }
   }
   const Func base = get_func(env, f);
index c8fc3022ffe86d7735f708fbfcc05d40e29e8e18..c06e0a86100dbb24cdf91ab0fe985553469209b2 100644 (file)
@@ -226,7 +226,7 @@ ANN void vm_run(const VM* vm) {
     &&regpushmem, &&regpushmemfloat, &&regpushmemother, &&regpushmemaddr,
     &&pushnow,
     &&baseint, &&basefloat, &&baseother, &&baseaddr,
-    &&regdup,
+    &&regdup, &&regdup2,
     &&memsetimm,
     &&regpop, &&regpushme, &&regpushmaybe,
     &&funcreturn,
@@ -361,6 +361,10 @@ regdup:
   *(m_uint*)reg = *(m_uint*)(reg-SZ_INT);
   reg += SZ_INT;
   DISPATCH()
+regdup2:
+  *(m_uint*)(reg+SZ_INT) = *(m_uint*)(reg);
+  reg += SZ_INT;
+  DISPATCH()
 memsetimm:
   *(m_uint*)(mem+instr->m_val) = instr->m_val2;
   DISPATCH();
@@ -562,10 +566,12 @@ funcusr:
   code = *(VM_Code*)reg;
   ip = code->instr->ptr + OFFSET;
   m_uint stack_depth = code->stack_depth;
+printf("stack_depth %lu\n", stack_depth);
   *(m_uint*)  mem = stack_depth; mem += SZ_INT;
   if(stack_depth) {
     register const m_uint f = GET_FLAG(code, member) ? SZ_INT : 0;
     if(f) {
+printf("%p\n", *(m_uint*)(reg - SZ_INT*3));
       *(m_uint*)mem = *(m_uint*)(reg - SZ_INT);
       stack_depth -= SZ_INT;
     }
index 4f233108bbe8a414773bc0c06bba871dbd66d402..8a81406d4e1635db1c270744700a52cc8326f6be 100644 (file)
@@ -4,5 +4,6 @@ class C
        typedef void test();
        test t;
 }
-C c;
+<<<C c>>>;
+<<<c.t>>>;
 c.t();
diff --git a/tests/error/lambda_mismatch1.gw b/tests/error/lambda_mismatch1.gw
new file mode 100644 (file)
index 0000000..6b92169
--- /dev/null
@@ -0,0 +1,2 @@
+// [contains] argument number does not match for lambda
+`a b`{ <<<a, " ", b>>>; }(1);
diff --git a/tests/error/lambda_mismatch2.gw b/tests/error/lambda_mismatch2.gw
new file mode 100644 (file)
index 0000000..98c67f5
--- /dev/null
@@ -0,0 +1,4 @@
+// [contains] argument number does not match for lambda
+typedef void ptr_t(int i);
+`a b`{ <<<a, " ", b>>>; } @=> ptr_t ptr;
+ptr(2);
diff --git a/tests/error/lambda_mismatch3.gw b/tests/error/lambda_mismatch3.gw
new file mode 100644 (file)
index 0000000..74b7601
--- /dev/null
@@ -0,0 +1,7 @@
+// [contains] argument number does not match for lambda
+typedef void ptr_t(int i);
+`a b`{ <<<a, " ", b>>>; } @=> ptr_t ptr;
+fun void test(ptr_t ptr) {
+  ptr(2);
+}
+test(ptr);
diff --git a/tests/new/global_func0.gw b/tests/new/global_func0.gw
new file mode 100644 (file)
index 0000000..cc852b4
--- /dev/null
@@ -0,0 +1,11 @@
+123 => global int g_i;
+class global C {
+  13 => int i;
+}
+<<<g_i>>>;
+global C g_c;
+<<<g_c, "->i => ", g_c.i>>>;
+fun global void g_test() { <<<g_i>>>; <<<g_c>>>; <<<g_c.i>>>; <<<"test">>>; }
+//fun global void g_test() { <<<"test">>>; }
+<<<g_test>>>;
+<<<g_test()>>>;
diff --git a/tests/new/global_func1.gw b/tests/new/global_func1.gw
new file mode 100644 (file)
index 0000000..4222465
--- /dev/null
@@ -0,0 +1,8 @@
+<<<g_i>>>;
+<<<g_c>>>;
+<<<g_c.i>>>;
+<<<g_test>>>;
+g_test();
+
+//g_test();
+//g_test();
diff --git a/tests/new/global_func3.gw b/tests/new/global_func3.gw
new file mode 100644 (file)
index 0000000..fea54e5
--- /dev/null
@@ -0,0 +1,4 @@
+<<<int i>>>;
+fun global void this_global_func_will_fail_to_compile() {
+  <<<i>>>;
+}
diff --git a/tests/new/global_var.gw b/tests/new/global_var.gw
new file mode 100644 (file)
index 0000000..97ac7a6
--- /dev/null
@@ -0,0 +1 @@
+<<<global int g_i>>>;
diff --git a/tests/new/global_var1.gw b/tests/new/global_var1.gw
new file mode 100644 (file)
index 0000000..1e65cc5
--- /dev/null
@@ -0,0 +1 @@
+<<<g_i>>>;
diff --git a/tests/new/lambda.gw b/tests/new/lambda.gw
new file mode 100644 (file)
index 0000000..0842724
--- /dev/null
@@ -0,0 +1,32 @@
+class C {
+  typedef void ptr_t(int i,int j);
+  `a b` { <<<this, " ", a, " ", b, " test">>>; } @=> ptr_t ptr;
+//  `a,b` { <<<"test">>>; } @=> 
+//  ptr_t ptr;
+//  ptr(1,2);
+  fun void test(int i, int j) { <<<this, " ", i, " ", j>>>; }
+//  fun void test(ptr_t t, int i) {
+//<<<t>>>;
+//    t(2,i);
+//  }
+//  test(`a,b` { <<<this, " lambda argument">>>; }, 2);
+}
+//<<<C c>>>;
+C c;
+<<<c>>>;
+//<<<c.test>>>;
+//<<<c.ptr>>>;
+//c.ptr(1,2);
+//<<<c.test>>>;
+c.test @=> c.ptr;
+//c.ptr;
+//<<<c.ptr>>>;
+//c.test(1,2);
+c.ptr(1, 2);
+//c.ptr(1, 2);
+//c.ptr(1, 2);
+//(1,2) => c.ptr;
+//c.test(`a,b` { <<<this, "lambda argument">>>; }, 2);
+//c.test(c.ptr, 2);
+//<<<c.ptr>>>;
+//c.ptr;
diff --git a/tests/new/lambda2.gw b/tests/new/lambda2.gw
new file mode 100644 (file)
index 0000000..4f82711
--- /dev/null
@@ -0,0 +1,21 @@
+class C {
+typedef void ptr_t(int i);
+`a` { <<<this, " ", a>>>; } @=> 
+ptr_t ptr;
+//ptr(3);
+fun void t1(int i) { <<<this, " t1 ", i>>>; }
+fun void test(ptr_t ptr) {
+<<<this>>>;
+ ptr(1);
+}
+t1 @=> ptr_t t1p;
+//test(t1$ptr_t);
+test(t1p);
+//test(ptr);
+//<<<t1>>>;
+//<<<t1$ptr_t>>>;
+}
+<<<C c>>>;
+<<<c.test(c.ptr)>>>;
+<<<c.ptr(1)>>>;
+c.test(c.t1p);
diff --git a/tests/new/lambda3.gw b/tests/new/lambda3.gw
new file mode 100644 (file)
index 0000000..f949784
--- /dev/null
@@ -0,0 +1,2 @@
+12 => int i;
+`a b` { <<<"i: ", i, " ", a, " ", b>>>; }(1,2);
diff --git a/tests/new/local_func.gw b/tests/new/local_func.gw
new file mode 100644 (file)
index 0000000..1d0e7cc
--- /dev/null
@@ -0,0 +1,4 @@
+fun void test() {
+  <<<test>>>;
+}
+test();
diff --git a/tests/new/spork.gw b/tests/new/spork.gw
new file mode 100644 (file)
index 0000000..9ce4a97
--- /dev/null
@@ -0,0 +1,8 @@
+int i;
+spork { <<<"test">>>; };
+me.yield();
+//samp => now;
+fun void t() { <<<__func__>>>; }
+spork t();
+me.yield();
+samp => now;
diff --git a/tests/new/stackov.gw b/tests/new/stackov.gw
new file mode 100644 (file)
index 0000000..283adec
--- /dev/null
@@ -0,0 +1,16 @@
+fun void test(int i) {
+  <<<"test ", i>>>; 
+  if(i > 1)
+    test(i-1);
+}
+
+fun void launch(int i) {
+  test(12);
+  <<<" launch ", i>>>;
+}
+
+spork launch(2);
+//second => now;
+me.yield();
+//.1::samp => now;
+launch(12);
diff --git a/tests/new/stackov2.gw b/tests/new/stackov2.gw
new file mode 100644 (file)
index 0000000..08c1c9e
--- /dev/null
@@ -0,0 +1,5 @@
+fun void launch(int i) {
+<<<" launch ", i>>>;
+}
+//spork launch(2);
+me.yield();