From affc15deb2f880a1cb8a70453018409721592654 Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Sat, 21 Sep 2019 00:49:21 +0200 Subject: [PATCH] :art: Expose internal operator --- ast | 2 +- include/import.h | 1 + src/emit/emit.c | 10 +++--- src/lib/opfunc.c | 6 ++++ src/parse/check.c | 64 ++++++++++++++++++--------------------- src/parse/operator.c | 52 +++++++++++++++---------------- src/parse/scan2.c | 20 +++++++++--- tests/tree/class_union.gw | 2 +- tests/tree/union.gw | 2 +- 9 files changed, 87 insertions(+), 72 deletions(-) diff --git a/ast b/ast index 59f14732..0a0c0d67 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit 59f147324289f644940968e3125cef2bde3a3f94 +Subproject commit 0a0c0d67d0ccfd81b1011e917e031a364fc07d6f diff --git a/include/import.h b/include/import.h index e9ae4665..d8bd808d 100644 --- a/include/import.h +++ b/include/import.h @@ -78,6 +78,7 @@ OP_CHECK(opck_post); OP_CHECK(opck_rassign); OP_CHECK(opck_rhs_emit_var); OP_CHECK(opck_basic_cast); +OP_CHECK(opck_usr_implicit); OP_CHECK(opck_new); OP_EMIT(opem_basic_cast); OP_EMIT(opem_new); diff --git a/src/emit/emit.c b/src/emit/emit.c index 594535dc..4577270c 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1112,8 +1112,9 @@ ANN static m_bool emit_implicit_cast(const Emitter emit, } ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) { - CHECK_BO(emit_exp_pop_next(emit, e, 0)) - struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"), .rhs=e->type, .pos=e->pos }; + CHECK_BO(emit_exp_pop_next(emit, e, 1)) + struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"), + .rhs=e->type, .pos=e->pos, .data=(uintptr_t)e}; return op_emit(emit, &opi); } #define emit_flow(emit,b) _flow(emit, b, 1) @@ -1433,8 +1434,9 @@ ANN static m_bool emit_stmt_exp(const Emitter emit, const struct Stmt_Exp_* exp) ANN static m_bool emit_case_head(const Emitter emit, const Exp base, const Exp e, const Symbol op) { CHECK_BB(emit_exp(emit, base, 1)) CHECK_BB(emit_exp(emit, e, 1)) - Exp_Binary bin = { .lhs=base, .rhs=e, .op=op, .nspc=emit->env->curr }; - struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type, .data=(uintptr_t)&bin, .pos=e->pos }; + const Exp_Binary bin = { .lhs=base, .rhs=e, .op=op }; + struct Exp_ ebin = { .d={.exp_binary=bin}, .nspc=emit->env->curr}; + struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type, .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos }; CHECK_OB(op_emit(emit, &opi)) regpop(emit, base->type->size); return GW_OK; diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index 28ddad2f..0f4a9dfc 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -23,6 +23,12 @@ OP_CHECK(opck_basic_cast) { exp_self(cast)->type : t_null; } +OP_CHECK(opck_usr_implicit) { + struct Implicit* imp = (struct Implicit*)data; + imp->e->cast_to = imp->t; + return imp->t; +} + OP_EMIT(opem_basic_cast) { return (Instr)GW_OK; } diff --git a/src/parse/check.c b/src/parse/check.c index a9851dc7..d6092133 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -157,20 +157,25 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) { return decl->type; } -ANN static m_bool prim_array_inner(const Env env, const Type t, Type type, const Exp e) { - const Type common = find_common_anc(t, type); + +ANN static inline void set_cast(const Env env, Type type, const Exp e) { + e->cast_to = type; + e->nspc = env->curr; +} + +ANN static m_bool prim_array_inner(const Env env, Type type, const Exp e) { + const Type common = find_common_anc(e->type, type); if(common) return GW_OK; - else if(isa(t, t_int) > 0 && isa(type, t_float) > 0) { - e->cast_to = type; - return GW_OK; - } - ERR_B(e->pos, _("array init [...] contains incompatible types ...")) + else if(!(isa(e->type, t_int) > 0 && isa(type, t_float) > 0)) + ERR_B(e->pos, _("array init [...] contains incompatible types ...")) + set_cast(env, type, e); + return GW_OK; } ANN static inline Type prim_array_match(const Env env, Exp e) { const Type type = e->type; - do CHECK_BO(prim_array_inner(env, e->type, type, e)) + do CHECK_BO(prim_array_inner(env, type, e)) while((e = e->next)); return array_type(env, type->array_depth ? array_base(type) : type, type->array_depth + 1); } @@ -283,7 +288,7 @@ ANN static m_bool vec_value(const Env env, Exp e, const m_str s) { const Type t = e->type; if(isa(t, t_float) < 0) { if(isa(t, t_int) > 0) - e->cast_to = t_float; + set_cast(env, t_float, e); else ERR_B(e->pos, _("invalid type '%s' in %s value #%d...\n" " (must be of type 'int' or 'float')"), t->name, s, count) @@ -463,7 +468,7 @@ ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t, const struct Implicit imp = { e, t, e->pos }; struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=e->type, .rhs=t, .data=(m_uint)&imp, .pos=e->pos }; return op_check(env, &opi) ? GW_OK : GW_ERROR; - } + } } return match ? 1 : -1; } @@ -866,16 +871,18 @@ ANN static Type check_exp_unary(const Env env, const Exp_Unary* unary) { return op_check(env, &opi); } -ANN static m_bool check_flow(const Env env, const Exp exp) { - struct Op_Import opi = { .op=insert_symbol("@conditionnal"), .rhs=exp->type, .pos=exp->pos }; - return op_check(env, &opi) ? GW_OK : GW_ERROR; +ANN static Type _flow(const Env env, const Exp e, const m_bool b) { + DECL_OO(const Type, type, = check_exp(env, e)) + struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"), + .rhs=type, .pos=e->pos, .data=(uintptr_t)e }; + return op_check(env, &opi); } +#define check_flow(emit,b) _flow(emit, b, 1) ANN static Type check_exp_if(const Env env, const Exp_If* exp_if) { - DECL_OO(const Type, cond, = check_exp(env, exp_if->cond)) + DECL_OO(const Type, cond, = check_flow(env, exp_if->cond)) DECL_OO(const Type, if_exp, = (exp_if->if_exp ? check_exp(env, exp_if->if_exp) : cond)) DECL_OO(const Type, else_exp, = check_exp(env, exp_if->else_exp)) - CHECK_BO(check_flow(env, exp_if->cond)) const Type ret = find_common_anc(if_exp, else_exp); if(!ret) ERR_O(exp_self(exp_if)->pos, @@ -1020,7 +1027,6 @@ ANN static m_bool do_stmt_auto(const Env env, const Stmt_Auto stmt) { array.depth = depth; td.array = &array; } -// ptr = type_decl_resolve(env, &td); exit(3); ptr = known_type(env, &td); if(!GET_FLAG(ptr, checked)) check_class_def(env, ptr->e->def); @@ -1041,24 +1047,25 @@ ANN static m_bool cond_type(const Env env, const Exp e) { return GW_OK; if(isa(t, t_float) > 0) { e->cast_to = t_int; + e->nspc = env->curr; return GW_OK; } ERR_B(e->pos, _("conditional must be of type 'int'...")) } #define stmt_func_xxx(name, type, prolog, exp) describe_stmt_func(check, name, type, prolog, exp) -stmt_func_xxx(if, Stmt_If,, !(!check_exp(env, stmt->cond) || - check_flow(env, stmt->cond) < 0 || +stmt_func_xxx(if, Stmt_If,, !(!check_flow(env, stmt->cond) || check_stmt(env, stmt->if_body) < 0 || (stmt->else_body && check_stmt(env, stmt->else_body) < 0)) ? 1 : -1) stmt_func_xxx(flow, Stmt_Flow,, !(!check_exp(env, stmt->cond) || - check_flow(env, stmt->cond) < 0 || + !_flow(env, stmt->cond, !stmt->is_do ? + stmt_self(stmt)->stmt_type == ae_stmt_while : + stmt_self(stmt)->stmt_type != ae_stmt_while) || check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1) stmt_func_xxx(for, Stmt_For,, !( for_empty(env, stmt) < 0 || check_stmt(env, stmt->c1) < 0 || - check_stmt(env, stmt->c2) < 0 || - check_flow(env, stmt->c2->d.stmt_exp.val) < 0 || + !check_flow(env, stmt->c2->d.stmt_exp.val) || (stmt->c3 && !check_exp(env, stmt->c3)) || check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1) stmt_func_xxx(loop, Stmt_Loop,, !(!check_exp(env, stmt->cond) || @@ -1189,7 +1196,7 @@ ANN static m_bool match_case_exp(const Env env, Exp e) { ANN static m_bool _check_stmt_case(const Env env, const Stmt_Match stmt) { CHECK_BB(match_case_exp(env, stmt->cond)) if(stmt->when) - CHECK_OB(check_exp(env, stmt->when)) + CHECK_OB(check_flow(env, stmt->when)) return check_stmt_list(env, stmt->list); } @@ -1329,15 +1336,6 @@ ANN static Value set_variadic(const Env env) { return variadic; } -ANN static void operator_func(const Func f) { - const Arg_List a = f->def->base->args; - const m_bool is_unary = GET_FLAG(f->def, unary); - const Type l = is_unary ? NULL : a->type; - const Type r = is_unary ? a->type : a->next ? a->next->type : NULL; - struct Op_Import opi = { .op=f->def->base->xid, .lhs=l, .rhs=r, .data=(m_uint)f, .pos=f->def->pos }; - operator_set_func(&opi); -} - ANN m_bool check_func_def(const Env env, const Func_Def fdef) { const Func func = get_func(env, fdef); m_bool ret = GW_OK; @@ -1370,8 +1368,6 @@ ANN m_bool check_func_def(const Env env, const Func_Def fdef) { REM_REF(variadic, env->gwion) if(GET_FLAG(fdef, builtin)) func->code->stack_depth = fdef->stack_depth; - else if(GET_FLAG(fdef, op)) - operator_func(func); } if(fdef->base->tmpl) nspc_pop_type(env->gwion->mp, env->curr); @@ -1398,7 +1394,7 @@ ANN static m_bool check_class_parent(const Env env, const Class_Def cdef) { return GW_OK; } -ANN /*static inline */void inherit(const Type t) { +ANN static inline void inherit(const Type t) { const Nspc nspc = t->nspc, parent = t->e->parent->nspc; nspc->info->offset = parent->info->offset; if(parent->info->vtable.ptr) diff --git a/src/parse/operator.c b/src/parse/operator.c index c8fd1fe5..c38d3f53 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -126,17 +126,17 @@ ANN m_bool add_op(const Gwion gwion, const struct Op_Import* opi) { } ANN static void set_nspc(struct OpChecker* ock, const Nspc nspc) { - if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@implicit"))return; - if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@conditionnal"))return; - if(ock->opi->op == insert_symbol(ock->env->gwion->st, "$")) - ((Exp_Cast*)ock->opi->data)->nspc = nspc; - if(ock->opi->lhs) { - if(ock->opi->rhs) - ((Exp_Binary*)ock->opi->data)->nspc = nspc; - else - ((Exp_Postfix*)ock->opi->data)->nspc = nspc; - } else - ((Exp_Unary*)ock->opi->data)->nspc = nspc; + if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@implicit")) { + struct Implicit* imp = (struct Implicit*)ock->opi->data; + imp->e->nspc = nspc; + return; + } + if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@conditionnal") || + ock->opi->op == insert_symbol(ock->env->gwion->st, "@unconditionnal")) { + ((Exp)ock->opi->data)->nspc = nspc; + return; + } + exp_self((union exp_data*)ock->opi->data)->nspc = nspc; } ANN static Type op_check_inner(struct OpChecker* ock) { @@ -195,27 +195,27 @@ ANN m_bool operator_set_func(const struct Op_Import* opi) { ANN static Instr handle_instr(const Emitter emit, const M_Operator* mo) { if(mo->func) { - const Instr instr = emit_add_instr(emit, mo->func->code ? RegPushImm : PushStaticCode); - instr->m_val = ((m_uint)mo->func->code ?:(m_uint)mo->func); - return emit_exp_call1(emit, mo->func); + const Instr push = emit_add_instr(emit, mo->func->code ? RegPushImm : PushStaticCode); + push->m_val = ((m_uint)mo->func->code ?:(m_uint)mo->func); + const Instr instr = emit_exp_call1(emit, mo->func); + if(mo->func->def->base->xid == insert_symbol(emit->gwion->st, "@conditionnal")) + return emit_add_instr(emit, BranchEqInt); + if(mo->func->def->base->xid == insert_symbol(emit->gwion->st, "@unconditionnal")) + return emit_add_instr(emit, BranchNeqInt); + return instr; } return emit_add_instr(emit, mo->instr); } ANN static Nspc get_nspc(SymTable *st, const struct Op_Import* opi) { - if(opi->op == insert_symbol(st, "@implicit") || - opi->op == insert_symbol(st, "@conditionnal") || - opi->op == insert_symbol(st, "@unconditionnal")) - return opi->rhs->e->owner; - if(opi->op == insert_symbol(st, "$")) - return ((Exp_Cast*)opi->data)->nspc; - if(opi->lhs) { - if(opi->rhs) - return ((Exp_Binary*)opi->data)->nspc; - else - return ((Exp_Postfix*)opi->data)->nspc; + if(opi->op == insert_symbol(st, "@implicit")) { + struct Implicit* imp = (struct Implicit*)opi->data; + return imp->e->nspc; } - return ((Exp_Unary*)opi->data)->nspc; + if(opi->op == insert_symbol(st, "@conditionnal") || + opi->op == insert_symbol(st, "@unconditionnal")) + return ((Exp)opi->data)->nspc; + return exp_self((union exp_data*)opi->data)->nspc; } ANN static inline Nspc ensure_nspc(SymTable *st, const struct Op_Import* opi) { diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 64180c5b..83c15b15 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -13,6 +13,10 @@ #include "parse.h" #include "nspc.h" #include "operator.h" +#include "object.h" + +#include "instr.h" +#include "import.h" ANN static m_bool scan2_stmt(const Env, const Stmt); ANN static m_bool scan2_stmt_list(const Env, Stmt_List); @@ -398,13 +402,19 @@ ANN static m_bool scan2_func_def_builtin(MemPool p, const Func func, const m_str } ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f) { - assert(f->base->args); - const Type l = GET_FLAG(f, unary) ? NULL : + const m_str str = s_name(f->base->xid); + const uint is_unary = GET_FLAG(f, unary) + (!strcmp(str, "@conditionnal") || !strcmp(str, "@unconditionnal")); + const Type l = is_unary ? NULL : f->base->args->var_decl->value->type; - const Type r = GET_FLAG(f, unary) ? f->base->args->var_decl->value->type : - f->base->args->next ? f->base->args->next->var_decl->value->type : NULL; - struct Op_Import opi = { .op=f->base->xid, .lhs=l, .rhs=r, .ret=f->base->ret_type, .pos=f->pos }; + const Type r = 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; + 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; CHECK_BB(add_op(env->gwion, &opi)) + operator_set_func(&opi); return GW_OK; } diff --git a/tests/tree/class_union.gw b/tests/tree/class_union.gw index 89962f55..4a27e0e2 100644 --- a/tests/tree/class_union.gw +++ b/tests/tree/class_union.gw @@ -2,7 +2,7 @@ class C { union { int one; - string @ two; + string two; }; <<< one, " ", two >>>; } diff --git a/tests/tree/union.gw b/tests/tree/union.gw index 92af3a6e..5cc3de06 100644 --- a/tests/tree/union.gw +++ b/tests/tree/union.gw @@ -1,6 +1,6 @@ union { int one; - string @ two; + string two; }; <<< one, " ", two >>>; -- 2.43.0