From fd88a13a56b8df38af71add325af160b606e5aba Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Tue, 5 Apr 2022 21:48:31 +0200 Subject: [PATCH] :art: default args, and more --- Makefile | 6 ++-- ast | 2 +- include/default_args.h | 4 +++ include/env/func.h | 1 - src/arg.c | 2 +- src/env/type.c | 4 +-- src/lib/object_op.c | 15 ++++++-- src/parse/check.c | 47 +++++++++++++------------ src/parse/default_arg.c | 78 +++++++++++++++++++++++++++++++++++++++++ src/parse/scan0.c | 71 ++----------------------------------- src/parse/scan2.c | 35 ++++++++++++++---- 11 files changed, 157 insertions(+), 108 deletions(-) create mode 100644 include/default_args.h create mode 100644 src/parse/default_arg.c diff --git a/Makefile b/Makefile index 02d8fd2e..4d192ae4 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,9 @@ CFLAGS += -Wno-pedantic CFLAGS += -DGWION_BUILTIN -all: options-show ${GWLIBS} src/main.o +all: options-show ${PRG} + +${PRG}: ${GWLIBS} src/main.o @$(info link ${PRG}) @${CC} src/main.o -o ${PRG} ${LDFLAGS} ${LIBS} @@ -149,7 +151,7 @@ uninstall: translation-uninstall @rm ${DESTDIR}/${PREFIX}/include/gwion/*.h @rmdir --ignore-fail-on-non-empty ${DESTDIR}/${PREFIX}/include/gwion -test: +test: ${PRG} @bash scripts/test.sh ${test_dir} scan: diff --git a/ast b/ast index c02c76b8..1f60e2df 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit c02c76b8d22fdf40fd407861e625b6e741f64ffc +Subproject commit 1f60e2df75ddd542a0cdf1853c37d5b685bf9641 diff --git a/include/default_args.h b/include/default_args.h new file mode 100644 index 00000000..3e1e1782 --- /dev/null +++ b/include/default_args.h @@ -0,0 +1,4 @@ +#ifndef __DEFAULT_ARGS +#define __DEFAULT_ARGS +ANN void default_args(const Env, const Section *, Ast *acc); +#endif diff --git a/include/env/func.h b/include/env/func.h index 34f63624..286a4773 100644 --- a/include/env/func.h +++ b/include/env/func.h @@ -9,7 +9,6 @@ enum fflag { fflag_valid = 1 << 4, fflag_emit = 1 << 5, fflag_return = 1 << 6, - fflag_recurs = 1 << 7, } __attribute__((packed)); struct Func_ { diff --git a/src/arg.c b/src/arg.c index 8f1e453a..4a9d2b8c 100644 --- a/src/arg.c +++ b/src/arg.c @@ -40,7 +40,7 @@ enum { ANN static inline void config_end(const Vector config) { for (m_uint i = 0; i < vector_size(config); ++i) { const Vector v = (Vector)vector_at(config, i); - for (m_uint i = 1; i < vector_size(v); ++i) xfree((m_str)vector_at(v, i)); + for (m_uint i = 0; i < vector_size(v); ++i) xfree((m_str)vector_at(v, i)); vector_release(v); xfree(v); } diff --git a/src/env/type.c b/src/env/type.c index 8801e95e..577bf69d 100644 --- a/src/env/type.c +++ b/src/env/type.c @@ -22,8 +22,8 @@ ANN void free_type(const Type a, struct Gwion_ *const gwion) { else if (tflag(a, tflag_cdef)) class_def_cleaner(gwion, a->info->cdef); } - if (tflag(a, tflag_cdef) && a->info->parent) - type_remref(a->info->parent, gwion); +// if (tflag(a, tflag_cdef) && a->info->parent) +// type_remref(a->info->parent, gwion); if (a->effects.ptr) vector_release(&a->effects); if (a->nspc) nspc_remref(a->nspc, gwion); if (a->info->tuple) free_tupleform(a->info->tuple, gwion); diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 36ab071b..055aacb2 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -172,6 +172,16 @@ ANN static inline Value get_value(const Env env, const Exp_Dot *member, return NULL; } +ANN static Type class_type(const Env env, const Exp_Dot *member, const Type base) { + const Type parent = actual_type(env->gwion, base); + if(!tflag(parent, tflag_tmpl)) return parent; + Type_Decl td = { + .xid=insert_symbol(env->gwion->st, parent->name), + .types = member->is_call->tmpl ? member->is_call->tmpl->call : NULL + }; + return known_type(env, &td); +} + OP_CHECK(opck_object_dot) { Exp_Dot *const member = (Exp_Dot *)data; const m_str str = s_name(member->xid); @@ -192,12 +202,11 @@ OP_CHECK(opck_object_dot) { if (is_func(env->gwion, v->type) && (!v->from->owner_class || isa(the_base, v->from->owner_class) > 0)) return v->type; if (is_class(env->gwion, v->type)) { - const Type parent = actual_type(env->gwion, v->type); - if (isa(the_base, parent) > 0 && parent->nspc) { // beware templates + DECL_OO(const Type, parent, = class_type(env, member, v->type)); + if (isa(the_base, parent) > 0 && parent->nspc) { const Symbol sym = insert_symbol(env->gwion->st, "new"); const Value ret = nspc_lookup_value1(parent->nspc, sym); member->xid = sym; -// member->base->type = parent; if(ret) return ret->type; } diff --git a/src/parse/check.c b/src/parse/check.c index d93ab1c6..8f1426dc 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -787,7 +787,7 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) { ANN m_bool func_check(const Env env, Exp_Call *const exp) { if(exp->func->exp_type == ae_exp_dot) - exp->func->d.exp_dot.is_call = true; + exp->func->d.exp_dot.is_call = exp; CHECK_OB(check_exp(env, exp->func)); if (exp->func->exp_type == ae_exp_decl) ERR_B(exp->func->pos, _("Can't call late function pointer at declaration " @@ -863,7 +863,7 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) { } exp->func->type = func->value_ref->type; call_add_effect(env, func, exp->func->pos); - if (func == env->func) set_fflag(env->func, fflag_recurs); +// if (func == env->func) set_fflag(env->func, fflag_recurs); return func->def->base->ret_type != env->gwion->type[et_auto] ? func->def->base->ret_type : exp->func->d.exp_dot.base->type; } @@ -943,6 +943,26 @@ ANN2(1) static inline bool curried(const Env env, Exp exp) { return false; } +ANN static Type check_exp_call_tmpl(const Env env, Exp_Call *exp, const Type t) { + if(isa(t, env->gwion->type[et_lambda]) > 0) + if (!t->info->func) + ERR_O(exp->func->pos, _("invalid lambda use.")) + if (exp->args) CHECK_OO(check_exp(env, exp->args)); + if (!t->info->func->def->base->tmpl) + ERR_O(exp_self(exp)->pos, _("template call of non-template function.")) + if (t->info->func->def->base->tmpl->call) { + if (env->func == t->info->func) { + exp->func->type = env->func->value_ref->type; + return env->func->def->base->ret_type; + } else + CHECK_BO(predefined_call(env, t, exp_self(exp)->pos)); + } + const Value v = type_value(env->gwion, t); + DECL_OO(const Func, f, = find_template_match(env, v, exp)); + exp->func->type = f->value_ref->type; + return f->def->base->ret_type; +} + ANN static Type check_exp_call(const Env env, Exp_Call *exp) { if (exp->apms && curried(env, exp->args)) return env->gwion->type[et_curry]; @@ -951,23 +971,8 @@ ANN static Type check_exp_call(const Env env, Exp_Call *exp) { if (!ret) return exp_self(exp)->type; const Type t = actual_type(env->gwion, exp->func->type); if (!is_func(env->gwion, t)) return check_exp_call1(env, exp); - if(isa(t, env->gwion->type[et_lambda]) > 0) - if (!t->info->func) - ERR_O(exp->func->pos, _("invalid lambda use.")) - if (exp->args) CHECK_OO(check_exp(env, exp->args)); - if (!t->info->func->def->base->tmpl) - ERR_O(exp_self(exp)->pos, _("template call of non-template function.")) - if (t->info->func->def->base->tmpl->call) { - if (env->func == t->info->func) { - exp->func->type = env->func->value_ref->type; - return env->func->def->base->ret_type; - } else - CHECK_BO(predefined_call(env, t, exp_self(exp)->pos)); - } - const Value v = type_value(env->gwion, t); - DECL_OO(const Func, f, = find_template_match(env, v, exp)); - exp->func->type = f->value_ref->type; - return f->def->base->ret_type; + if(strcmp("new", s_name(t->info->func->def->base->xid))) + return check_exp_call_tmpl(env, exp, t); } return check_exp_call1(env, exp); } @@ -1736,8 +1741,6 @@ ANN static m_bool check_extend_def(const Env env, const Extend_Def xdef) { ANN static m_bool _check_trait_def(const Env env, const Trait_Def pdef) { const Trait trait = nspc_lookup_trait1(env->curr, pdef->xid); Ast ast = pdef->body; -// while (ast) { -// Section *section = ast->section; for(m_uint i = 0; i < ast->len; i++) { Section * section = mp_vector_at(ast, Section, i); if (section->section_type == ae_section_stmt) { @@ -1757,10 +1760,8 @@ ANN static m_bool _check_trait_def(const Env env, const Trait_Def pdef) { vector_add(&trait->requested_values, (m_uint)value); } } -// list = list->next; } } -// ast = ast->next; } return GW_OK; } diff --git a/src/parse/default_arg.c b/src/parse/default_arg.c new file mode 100644 index 00000000..8e6dba64 --- /dev/null +++ b/src/parse/default_arg.c @@ -0,0 +1,78 @@ +#include "gwion_util.h" +#include "gwion_ast.h" +#include "gwion_env.h" +#include "vm.h" +#include "gwion.h" +#include "traverse.h" + +ANN static Exp mk_default_args(const MemPool p, const Arg_List args, const uint32_t max) { + Exp exp = NULL, base_exp = NULL; + for(uint32_t i = 0; i < args->len; i++) { + Arg *arg = mp_vector_at(args, Arg, i); + const Exp arg_exp = new_prim_id(p, arg->var_decl.xid, arg->var_decl.pos); + if(exp) + exp = (exp->next = arg_exp); + else + base_exp = exp = arg_exp; + } + // now add default args + for(uint32_t i = args->len; i < max; i++) { + Arg *arg = mp_vector_at(args, Arg, i); + const Exp arg_exp = cpy_exp(p, arg->exp); + if(exp) + exp = (exp->next = arg_exp); + else + base_exp = exp = arg_exp; + } + return base_exp; +} + +ANN static Stmt_List std_code(const MemPool p, Func_Base *base, const Arg_List args, const uint32_t len) { + const Exp efunc = new_prim_id(p, base->xid, base->pos); + const Exp exp_arg = mk_default_args(p, args, len); + const Exp ecall = new_exp_call(p, efunc, exp_arg, base->pos); + Stmt_List slist = new_mp_vector(p, sizeof(struct Stmt_), 1); + mp_vector_set(slist, struct Stmt_, 0, + ((struct Stmt_) { + .stmt_type = ae_stmt_return, .d = { .stmt_exp = { .val = ecall }}, + .pos = base->pos + })); + return slist; +} + +ANN static Stmt_List new_code(const Env env, Func_Base *base, const Arg_List args, const uint32_t len) { + const MemPool p = env->gwion->mp; + const Exp dbase = new_prim_id(p, insert_symbol(env->gwion->st, "this"), base->pos); + const Exp dot = new_exp_dot(p, dbase, insert_symbol(env->gwion->st, env->class_def->name), base->pos); + const Exp exp_args = mk_default_args(p, args, len); + const Exp ecall = new_exp_call(p, dot, exp_args, base->pos); + Stmt_List slist = new_mp_vector(p, sizeof(struct Stmt_), 1); + mp_vector_set(slist, struct Stmt_, 0, + ((struct Stmt_) { + .stmt_type = ae_stmt_exp, .d = { .stmt_exp = { .val = ecall }}, + .pos = base->pos + })); + return slist; +} + +ANN void default_args(const Env env, const Section *s, Ast *acc) { + const MemPool p = env->gwion->mp; + const Func_Def base_fdef = s->d.func_def; + Arg_List args = base_fdef->base->args; + uint32_t len = args->len; + while(args->len--) { + Arg *arg = mp_vector_at(args, Arg, args->len); + if(!arg->exp) break; + Func_Base *const base = cpy_func_base(p, base_fdef->base); + Stmt_List slist = strcmp("new", s_name(base->xid)) + ? std_code(env->gwion->mp, base, args, len) + : new_code(env, base, args, len); + const Stmt body = new_stmt_code(p, slist, base->pos); + const Func_Def fdef = new_func_def(p, base, body); + scan1_func_def(env, fdef); + scan2_func_def(env, fdef); + Section section = MK_SECTION(func, func_def, fdef); + mp_vector_add(p, acc, Section, section); + } + args->len = len; +} diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 1c8eb9c6..99feeb47 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -348,7 +348,7 @@ ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) { CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos)); const Type parent = cdef_parent(env, cdef); if (parent == (Type)GW_ERROR) return NULL; - if(parent) type_addref(parent); + //if(parent) type_addref(parent); if (cdef->traits) CHECK_BO(find_traits(env, cdef->traits, cdef->pos)); const Type t = scan0_type(env, s_name(cdef->base.xid), parent); if (cflag(cdef, cflag_struct)) { @@ -378,57 +378,6 @@ ANN static m_bool scan0_stmt_list(const Env env, Stmt_List l) { return GW_OK; } -ANN static Exp mk_default_args(const MemPool p, const Arg_List args, const uint32_t max) { - Exp exp = NULL, base_exp = NULL; - for(uint32_t i = 0; i < args->len; i++) { - Arg *arg = mp_vector_at(args, Arg, i); - const Exp arg_exp = new_prim_id(p, arg->var_decl.xid, arg->var_decl.pos); - if(exp) - exp = (exp->next = arg_exp); - else - base_exp = exp = arg_exp; - } - // now add default args - for(uint32_t i = args->len; i < max; i++) { - Arg *arg = mp_vector_at(args, Arg, i); - const Exp arg_exp = cpy_exp(p, arg->exp); - if(exp) - exp = (exp->next = arg_exp); - else - base_exp = exp = arg_exp; - } - return base_exp; -} - -ANN2(1) static void scan0_func_def_default(const MemPool p, const Section *s, - Ast *acc) { - const Func_Def base_fdef = s->d.func_def; - Arg_List args = base_fdef->base->args; - const uint32_t len = args->len; - while(args->len--) { - Arg *arg = mp_vector_at(args, Arg, args->len); - if(!arg->exp) break; - Func_Base *base = new_func_base( - p, base_fdef->base->td ? cpy_type_decl(p, base_fdef->base->td) : NULL, base_fdef->base->xid, - cpy_arg_list(p, args), - base_fdef->base->flag, base_fdef->base->pos); - const Exp efunc = new_prim_id(p, base->xid, base->pos); - const Exp exp_arg = mk_default_args(p, args, len); - const Exp ecall = new_exp_call(p, efunc, exp_arg, base->pos); - Stmt_List slist = new_mp_vector(p, sizeof(struct Stmt_), 1); - mp_vector_set(slist, struct Stmt_, 0, - ((struct Stmt_) { - .stmt_type = ae_stmt_return, .d = { .stmt_exp = { .val = ecall }}, - .pos = base_fdef->base->pos - })); - const Stmt body = new_stmt_code(p, slist, base->pos); - const Func_Def fdef = new_func_def(p, base, body); - Section section = MK_SECTION(func, func_def, fdef); - mp_vector_add(p, acc, Section, section); - } - args->len = len; -} - #define scan0_func_def dummy_func ANN static m_bool scan0_extend_def(const Env env, const Extend_Def xdef) { @@ -490,9 +439,9 @@ ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) { set_tflag(cdef->base.type, tflag_scan0); (void)mk_class(env, cdef->base.type, cdef->pos); add_type(env, cdef->base.type->info->value->from->owner, cdef->base.type); - const m_uint scope = env_push(env, cdef->base.type->info->value->from->owner_class, cdef->base.type->info->value->from->owner); +// const m_uint scope = env_push(env, cdef->base.type->info->value->from->owner_class, cdef->base.type->info->value->from->owner); const m_bool ret = cdef->body ? env_body(env, cdef, scan0_section) : GW_OK; - env_pop(env, scope); +// env_pop(env, scope); return ret; } @@ -523,23 +472,9 @@ ANN m_bool scan0_class_def(const Env env, const Class_Def c) { ANN m_bool scan0_ast(const Env env, Ast *ast) { Ast a = *ast; - Ast acc = new_mp_vector(env->gwion->mp, sizeof(Section), 0); for(m_uint i = 0; i < a->len; i++) { Section * section = mp_vector_at(a, Section, i); CHECK_BB(scan0_section(env, section)); - - if (section->section_type != ae_section_func || - !fbflag(section->d.func_def->base, fbflag_default)) - continue; - scan0_func_def_default(env->gwion->mp, section, &acc); - } - - for(m_uint i = 0; i < acc->len; i++) { - Section * section = mp_vector_at(acc, Section, i); - mp_vector_add(env->gwion->mp, ast, Section, *section); - } - free_mp_vector(env->gwion->mp, sizeof(Section), acc); - return GW_OK; } diff --git a/src/parse/scan2.c b/src/parse/scan2.c index da9eff7e..d4971301 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -10,6 +10,7 @@ #include "object.h" #include "instr.h" #include "import.h" +#include "default_args.h" ANN static m_bool scan2_stmt(const Env, const Stmt); ANN static m_bool scan2_stmt_list(const Env, Stmt_List); @@ -145,7 +146,7 @@ ANN static inline m_bool scan2_exp_binary(const Env env, const Exp_Binary *bin) { CHECK_BB(scan2_exp(env, bin->lhs)); CHECK_BB(scan2_exp(env, bin->rhs)); -if(bin->rhs->exp_type == ae_exp_call)bin->rhs->d.exp_call.apms = true; + if(bin->rhs->exp_type == ae_exp_call)bin->rhs->d.exp_call.apms = true; CHECK_BB(multi_decl(env, bin->lhs, bin->op)); return multi_decl(env, bin->rhs, bin->op); } @@ -511,13 +512,11 @@ static m_str func_name(const Env env, const Func_Def f, const Value v) { ANN2(1, 2) m_bool scan2_fdef_std(const Env env, const Func_Def f, const Value overload) { - const m_str name = func_name(env, f, overload ?: NULL); + const m_str name = func_name(env, f, overload); if (!name) return GW_ERROR; const Func base = f->base->func; if (!base) CHECK_OB(func_create(env, f, overload, name)); - else - f->base->func = base; if (f->base->args) CHECK_BB(scan2_args(f)); if (!f->builtin && f->d.code) CHECK_BB(scan2_func_def_code(env, f)); if (!base) { @@ -637,15 +636,37 @@ ANN m_bool scan2_class_def(const Env env, const Class_Def cdef) { if (tflag(t, tflag_scan2)) return GW_OK; set_tflag(t, tflag_scan2); if (c->base.ext) CHECK_BB(cdef_parent(env, c)); - if (c->body) CHECK_BB(env_body(env, c, scan2_section)); + if (c->body) { + const m_uint scope = env_push_type(env, t); + const Tmpl *tmpl = cdef->base.tmpl; + if(tmpl && tmpl->call && tmpl->call != (Type_List)1 && tmpl->list) + template_push_types(env, tmpl); + const m_bool ret = scan2_ast(env, &c->body); + if(tmpl && tmpl->call && tmpl->call != (Type_List)1 && tmpl->list) + nspc_pop_type(env->gwion->mp, env->curr); + env_pop(env, scope); + return ret; + } return GW_OK; } ANN m_bool scan2_ast(const Env env, Ast *ast) { Ast a = *ast; + Ast acc = new_mp_vector(env->gwion->mp, sizeof(Section), 0); + m_bool ret = GW_OK; for(m_uint i = 0; i < a->len; i++) { Section *section = mp_vector_at(a, Section, i); - CHECK_BB(scan2_section(env, section)); + if((ret = scan2_section(env, section)) < 0) break; + if (section->section_type == ae_section_func && + fbflag(section->d.func_def->base, fbflag_default)) { + mp_vector_add(env->gwion->mp, &acc, Section, *section); + } } - return GW_OK; + + for(uint32_t i = 0; i < acc->len; i++) { + Section * section = mp_vector_at(acc, Section, i); + default_args(env, section, ast); + } + free_mp_vector(env->gwion->mp, sizeof(Section), acc); + return ret; } -- 2.43.0