-Subproject commit 787c2856a8ec0e24b9d174b003e9b395d01080e7
+Subproject commit f0e1cb2cfe0ea1fe5ee0d73f94a1f5c4ef05c955
RegPushBase3,
RegPushBase4,
RegDup,
+ RegDup2,
MemSetImm,
RegPop,
RegPushMe,
#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
(_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) \
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);
RegPushBase3
RegPushBase4
RegDup
+RegDup2
MemSetImm
RegPop
RegPushMe
}
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);
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;
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
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)))
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) {
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;
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) {
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) {
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))
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;
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))
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;
}
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
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;
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;
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)
} 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;
}
++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))
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;
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)
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);
&®pushmem, &®pushmemfloat, &®pushmemother, &®pushmemaddr,
&&pushnow,
&&baseint, &&basefloat, &&baseother, &&baseaddr,
- &®dup,
+ &®dup, &®dup2,
&&memsetimm,
&®pop, &®pushme, &®pushmaybe,
&&funcreturn,
*(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();
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;
}
typedef void test();
test t;
}
-C c;
+<<<C c>>>;
+<<<c.t>>>;
c.t();
--- /dev/null
+// [contains] argument number does not match for lambda
+`a b`{ <<<a, " ", b>>>; }(1);
--- /dev/null
+// [contains] argument number does not match for lambda
+typedef void ptr_t(int i);
+`a b`{ <<<a, " ", b>>>; } @=> ptr_t ptr;
+ptr(2);
--- /dev/null
+// [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);
--- /dev/null
+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()>>>;
--- /dev/null
+<<<g_i>>>;
+<<<g_c>>>;
+<<<g_c.i>>>;
+<<<g_test>>>;
+g_test();
+
+//g_test();
+//g_test();
--- /dev/null
+<<<int i>>>;
+fun global void this_global_func_will_fail_to_compile() {
+ <<<i>>>;
+}
--- /dev/null
+<<<global int g_i>>>;
--- /dev/null
+<<<g_i>>>;
--- /dev/null
+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;
--- /dev/null
+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);
--- /dev/null
+12 => int i;
+`a b` { <<<"i: ", i, " ", a, " ", b>>>; }(1,2);
--- /dev/null
+fun void test() {
+ <<<test>>>;
+}
+test();
--- /dev/null
+int i;
+spork { <<<"test">>>; };
+me.yield();
+//samp => now;
+fun void t() { <<<__func__>>>; }
+spork t();
+me.yield();
+samp => now;
--- /dev/null
+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);
--- /dev/null
+fun void launch(int i) {
+<<<" launch ", i>>>;
+}
+//spork launch(2);
+me.yield();