From ec4d94cde5544e55168f4793dd19f78d81563611 Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Sun, 31 Mar 2019 18:13:52 +0200 Subject: [PATCH] :art: Allow mutating expressions, make '=> function' syntax sugar only --- include/gwi.h | 1 + include/import.h | 1 + include/operator.h | 1 + src/emit/emit.c | 7 ------- src/lib/func.c | 6 +++++- src/lib/import.c | 7 ++++++- src/parse/check.c | 31 +++++++------------------------ src/parse/operator.c | 8 ++++++-- 8 files changed, 27 insertions(+), 35 deletions(-) diff --git a/include/gwi.h b/include/gwi.h index cf499d1c..70b3122f 100644 --- a/include/gwi.h +++ b/include/gwi.h @@ -26,6 +26,7 @@ typedef struct { m_str ret, lhs, rhs; Type (*ck)(Env, void*); m_bool (*em)(Emitter, void*); + m_bool mut; } DL_Oper; typedef struct { diff --git a/include/import.h b/include/import.h index 8928f5ff..028e8b36 100644 --- a/include/import.h +++ b/include/import.h @@ -57,6 +57,7 @@ ANN m_int gwi_func_end(const Gwi gwi, const ae_flag flag); ANN2(1) m_int gwi_oper_ini(const Gwi gwi, const m_str l, const m_str r, const m_str t); ANN m_int gwi_oper_add(const Gwi gwi, Type (*check)(Env, void*)); ANN m_int gwi_oper_emi(const Gwi gwi, m_bool (*check)(Emitter, void*)); +ANN void gwi_oper_mut(const Gwi, const m_bool); ANN2(1) m_int gwi_oper_end(const Gwi gwi, const Operator op, const f_instr f); ANN Type_Decl* str2decl(const Env, const m_str, m_uint* depth); diff --git a/include/operator.h b/include/operator.h index 55fc5cf0..4eb66006 100644 --- a/include/operator.h +++ b/include/operator.h @@ -10,6 +10,7 @@ struct Op_Import { opck ck; opem em; uintptr_t data; + m_bool mut; }; struct Implicit { diff --git a/src/emit/emit.c b/src/emit/emit.c index d00415a3..66e14f15 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -679,17 +679,10 @@ ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call* exp_call) { return emit_exp_call1(emit, exp_call->m_func); } -ANN static m_bool emit_binary_func(const Emitter emit, const Exp_Binary* bin) { GWDEBUG_EXE - const Exp_Call exp = { .func=bin->rhs, .args=bin->lhs, .m_func=bin->func, .tmpl=bin->tmpl, .self=bin->self }; - return emit_exp_call(emit, &exp); -} - ANN static m_bool emit_exp_binary(const Emitter emit, const Exp_Binary* bin) { GWDEBUG_EXE const Exp lhs = bin->lhs; const Exp rhs = bin->rhs; struct Op_Import opi = { .op=bin->op, .lhs=lhs->type, .rhs=rhs->type, .data = (uintptr_t)bin }; - if(bin->op == op_chuck && isa(rhs->type, t_function) > 0) - return emit_binary_func(emit, bin); CHECK_BB(emit_exp(emit, lhs, 1)) CHECK_BB(emit_exp(emit, rhs, 1)) return op_emit(emit, &opi); diff --git a/src/lib/func.c b/src/lib/func.c index f3767345..8af40ef3 100644 --- a/src/lib/func.c +++ b/src/lib/func.c @@ -27,7 +27,10 @@ static INSTR(LambdaAssign) { GWDEBUG_EXE static OP_CHECK(opck_func_call) { Exp_Binary* bin = (Exp_Binary*)data; Exp_Call call = { .func=bin->rhs, .args=bin->lhs, .self=bin->self }; - return check_exp_call1(env, &call); + Exp e = bin->self; + e->exp_type = ae_exp_call; + memcpy(&e->d.exp_call, &call, sizeof(Exp_Call)); + return check_exp_call1(env, &e->d.exp_call); } static OP_EMIT(opem_func_assign) { @@ -169,6 +172,7 @@ static OP_EMIT(opem_spork) { GWION_IMPORT(func) { CHECK_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@function", NULL)) CHECK_BB(gwi_oper_add(gwi, opck_func_call)) + gwi_oper_mut(gwi, 1); 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)) diff --git a/src/lib/import.c b/src/lib/import.c index ee939d14..9f67a812 100644 --- a/src/lib/import.c +++ b/src/lib/import.c @@ -480,13 +480,14 @@ ANN2(1,2) static int import_op(const Env env, const DL_Oper* op, const Type rhs = op->rhs ? get_type(env, op->rhs) : NULL; const Type ret = get_type(env, op->ret); const struct Op_Import opi = { op->op, lhs, rhs, ret, - op->ck, op->em, (uintptr_t)f }; + op->ck, op->em, (uintptr_t)f, op->mut }; return env_add_op(env, &opi); } ANN2(1) m_int gwi_oper_ini(const Gwi gwi, const restrict m_str l, const restrict m_str r, const restrict m_str t) { + gwi->oper.mut = 0; gwi->oper.ret = t; gwi->oper.rhs = r; gwi->oper.lhs = l; @@ -503,6 +504,10 @@ ANN m_int gwi_oper_emi(const Gwi gwi, m_bool (*em)(Emitter, void*)) { return GW_OK; } +ANN void gwi_oper_mut(const Gwi gwi, const m_bool mut) { + gwi->oper.mut = 1; +} + ANN m_int gwi_oper_end(const Gwi gwi, const Operator op, const f_instr f) { gwi->oper.op = op; const m_bool ret = import_op(gwi->env, &gwi->oper, f); diff --git a/src/parse/check.c b/src/parse/check.c index c26846a5..caa3e392 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -497,15 +497,12 @@ ANN static m_uint get_type_number(ID_List list) { return type_number; } -ANN static Func get_template_func(const Env env, const Exp_Call* func, const Exp base, const Value v) { +ANN static Func get_template_func(const Env env, const Exp_Call* func, const Value v) { const Func f = find_template_match(env, v, func); if(f) { Tmpl_Call* tmpl = new_tmpl_call(func->tmpl->types); tmpl->base = v->d.func_ref->def->tmpl->list; - if(base->exp_type == ae_exp_call) - base->d.exp_call.tmpl = tmpl; - else /* if(base->exp_type == ae_exp_binary) */ - base->d.exp_binary.tmpl = tmpl; + func->self->d.exp_call.tmpl = tmpl; return f; } assert(func->self); @@ -546,11 +543,8 @@ ANN static Type check_exp_call_template(const Env env, const Exp_Call *exp) { ERR_O(call->pos, "not able to guess types for template call.") Tmpl_Call tmpl = { .types=tl[0] }; const Exp_Call tmp_func = { .func=call, .args=args, .tmpl=&tmpl, .self=base }; - const Func func = get_template_func(env, &tmp_func, base, value); - if(base->exp_type == ae_exp_call) - base->d.exp_call.m_func = func; - else /* if(base->exp_type == ae_exp_binary) */ - base->d.exp_binary.func = func; + const Func func = get_template_func(env, &tmp_func, value); + base->d.exp_call.m_func = func; return func ? func->def->ret_type : NULL; } @@ -562,13 +556,6 @@ 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)) @@ -586,7 +573,7 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) { CHECK_BO(traverse_func_def(env, l->def)) if(env->class_def) SET_FLAG(l->def, member); - set_call(exp->self, l->def->func); + exp->self->d.exp_call.m_func = l->def->func; return l->def->ret_type ?: (l->def->ret_type = t_void); } @@ -605,7 +592,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); - set_call(exp->self, func); + exp->self->d.exp_call.m_func = func; return func->def->ret_type; } @@ -614,11 +601,7 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) { GWDEBUG .rhs=check_exp(env, bin->rhs), .data=(uintptr_t)bin }; CHECK_OO(opi.lhs) CHECK_OO(opi.rhs) - const Type op_ret = op_check(env, &opi); - if(!op_ret) - ERR_O(bin->self->pos, "in binary expression") - OPTIMIZE_CONST(bin) - return op_ret; + return op_check(env, &opi); } ANN static Type check_exp_cast(const Env env, const Exp_Cast* cast) { GWDEBUG_EXE diff --git a/src/parse/operator.c b/src/parse/operator.c index 9704ee4a..daf48dba 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -21,6 +21,7 @@ typedef struct M_Operator_{ Func func; Type (*ck)(Env, void*); m_bool (*em)(Emitter, void*); + m_bool mut; } M_Operator; ANN static void free_op(M_Operator* a) { @@ -94,6 +95,7 @@ ANN m_bool add_op(const Nspc nspc, const struct Op_Import* opi) { mo->instr = (f_instr)opi->data; mo->ck = opi->ck; mo->em = opi->em; + mo->mut = opi->mut; vector_add(v, (vtype)mo); if(opi->lhs && opi->lhs != OP_ANY_TYPE) ADD_REF(opi->lhs) @@ -117,12 +119,13 @@ ANN static void set_nspc(struct Op_Import* opi, const Nspc nspc) { ((Exp_Unary*)opi->data)->nspc = nspc; } -ANN static Type op_check_inner(const Env env, const Map map, const struct Op_Import* opi) { +ANN static Type op_check_inner(const Env env, const Map map, struct Op_Import* opi) { Type t, r = opi->rhs; do { const M_Operator* mo; const Vector v = (Vector)map_get(map, (vtype)opi->op); if(v && (mo = operator_find(v, opi->lhs, r))) { + opi->mut = mo->mut; if((mo->ck && (t = mo->ck(env, (void*)opi->data)))) return t; else @@ -147,7 +150,8 @@ ANN Type op_check(const Env env, struct Op_Import* opi) { if(ret) { if(ret == t_null) break; - set_nspc(opi, nspc); + if(!opi2.mut) + set_nspc(opi, nspc); return ret; } } while(l && (l = op_parent(env, l))); -- 2.43.0