From 41e555fdb96231a7eed643c9850d686057855eb6 Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Sun, 10 Mar 2024 14:40:45 +0100 Subject: [PATCH] :art: Semantic pass --- ast | 2 +- fmt | 2 +- include/default_args.h | 2 +- include/env/env.h | 1 + include/env/envset.h | 3 +- include/gwiondata.h | 1 + include/sema.h | 4 + include/sema_private.h | 16 +- include/spread.h | 12 -- src/emit/emit.c | 20 +- src/gwion.c | 8 +- src/lib/object_op.c | 52 ++--- src/parse/check.c | 35 ++- src/parse/check_traits.c | 4 + src/parse/func_resolve_tmpl.c | 5 +- src/parse/scan0.c | 71 +----- src/parse/scan1.c | 15 +- src/parse/scan2.c | 27 --- src/parse/spread.c | 129 ----------- src/parse/template.c | 1 - src/parse/type_decl.c | 19 +- src/{parse => sema}/default_arg.c | 24 +-- src/sema/sema.c | 346 ++++++++++++++++++++++++++---- tests/pp/define_text.gw | 4 +- tests/spread/spread_func.gw | 1 - util | 2 +- 26 files changed, 430 insertions(+), 376 deletions(-) delete mode 100644 include/spread.h delete mode 100644 src/parse/spread.c rename src/{parse => sema}/default_arg.c (74%) diff --git a/ast b/ast index f5b426bc..a6e7b8a3 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit f5b426bcc8570dabb40dcccc8f5b5ba3236b002e +Subproject commit a6e7b8a3b30f8e7e01f99547f38693c888ac0957 diff --git a/fmt b/fmt index b6a9fa75..16503e30 160000 --- a/fmt +++ b/fmt @@ -1 +1 @@ -Subproject commit b6a9fa7512897dc1420549c511561b94f722d34c +Subproject commit 16503e30235be57175d6ee2645bbbadb44ac1f98 diff --git a/include/default_args.h b/include/default_args.h index 96373374..6258ca8c 100644 --- a/include/default_args.h +++ b/include/default_args.h @@ -1,4 +1,4 @@ #ifndef __DEFAULT_ARGS #define __DEFAULT_ARGS -ANN Func_Def default_args(const Env env, Func_Base *fb, Ast *acc, uint32_t max); +ANN Func_Def default_args(const Sema *sema, Func_Base *fb, Ast *acc, uint32_t max); #endif diff --git a/include/env/env.h b/include/env/env.h index 3e46f75f..a9cfdb30 100644 --- a/include/env/env.h +++ b/include/env/env.h @@ -57,6 +57,7 @@ ANN Value mk_class(const Env env, const Type base, const loc_t); ANN bool compat_func(const __restrict__ Func_Def, const __restrict__ Func_Def); ANN Type known_type(const Env env, Type_Decl *); +ANN m_str tdpp(MemPool, SymTable*, const Type_Decl*, const bool no_color); ANN Type prim_ref(const Env env, const Type t, const Type_Decl *td); ANN bool env_access(const Env env, const ae_flag flag, const loc_t); ANN bool env_storage(const Env env, ae_flag flag, const loc_t); diff --git a/include/env/envset.h b/include/env/envset.h index 798d4c71..86b1c27a 100644 --- a/include/env/envset.h +++ b/include/env/envset.h @@ -28,7 +28,8 @@ ANN2(1) static inline void envset_popv(struct EnvSet *es, const Value v) { ANN static inline bool envset_pushf(struct EnvSet *es, const Value owner) { CHECK_B(envset_pushv(es, owner)); - return env_pushv(es->env, owner); + /*return*/ env_pushv(es->env, owner); + return true; } ANN2(1) static inline void envset_popf(struct EnvSet *es, const Value owner) { env_pop(es->env, es->scope); diff --git a/include/gwiondata.h b/include/gwiondata.h index fec1d4e2..6b6df966 100644 --- a/include/gwiondata.h +++ b/include/gwiondata.h @@ -17,6 +17,7 @@ typedef struct GwionData_ { threadpool_t *tpool; bool cdoc; bool errored; + bool color; } GwionData; ANN GwionData *new_gwiondata(const MemPool, const uint32_t thread_count, const uint32_t queue_size); diff --git a/include/sema.h b/include/sema.h index 8b8a3763..7dab714d 100644 --- a/include/sema.h +++ b/include/sema.h @@ -1 +1,5 @@ +#ifndef __SEMA ANN bool sema_pass(Env a, Ast *b); +ANN bool sema_variadic_class(Env, Class_Def); +ANN bool sema_variadic_func(Env, Func_Def); +#endif diff --git a/include/sema_private.h b/include/sema_private.h index bff82abd..d6eee9f5 100644 --- a/include/sema_private.h +++ b/include/sema_private.h @@ -1,12 +1,18 @@ typedef struct { char *filename; MemPool mp; - //Context context; + SymTable *st; + MP_Vector *tmpls; + Stmt_List *stmt_list; + struct PPArg_ *ppa; bool error; bool func; + bool scope; bool handling; + bool in_variadic; } Sema; +#ifdef __SEMA_IMPLEMENTATION__ ANN static bool sema_array_sub(Sema *a, Array_Sub b); ANN static bool sema_tmpl(Sema *a, Tmpl *b); ANN static bool sema_range(Sema *a, Range *b); @@ -57,9 +63,8 @@ ANN static bool sema_stmt_pp(Sema *a, Stmt_PP b); ANN static bool sema_stmt_retry(Sema *a, Stmt_Exp b); ANN static bool sema_stmt_try(Sema *a, Stmt_Try b); ANN static bool sema_stmt_defer(Sema *a, Stmt_Defer b); -ANN static bool sema_stmt(Sema *a, Stmt* b); -ANN static bool sema_stmt_list(Sema *a, Stmt_List b); -ANN static bool sema_func_base(Sema *a, Func_Base *b); +ANN static bool sema_stmt(Sema *a, Stmt* b, bool in_list); +ANN static bool sema_stmt_list(Sema *a, Stmt_List *b); ANN static bool sema_func_def(Sema *a, Func_Def b); ANN static bool sema_class_def(Sema *a, Class_Def b); ANN static bool sema_trait_def(Sema *a, Trait_Def b); @@ -69,4 +74,5 @@ ANN static bool sema_fptr_def(Sema *a, Fptr_Def b); ANN static bool sema_type_def(Sema *a, Type_Def b); ANN static bool sema_extend_def(Sema *a, Extend_Def b); ANN static bool sema_section(Sema *a, Section *b); -ANN static bool sema_ast(Sema *a, Ast b); +ANN static bool sema_ast(Sema *a, Ast *b); +#endif diff --git a/include/spread.h b/include/spread.h deleted file mode 100644 index 5cf9426a..00000000 --- a/include/spread.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __SPREAD -#define __SPREAD - -ANN static inline bool is_spread_tmpl(const Tmpl *tmpl) { - const Specialized *spec = mp_vector_at(tmpl->list, Specialized, tmpl->list->len - 1); - return !strcmp(s_name(spec->tag.sym), "..."); -} - -ANN bool spread_ast(const Env env, const Spread_Def spread, const Tmpl *tmpl); -ANN Stmt_List spread_func(const Env env, const Stmt_List body); - -#endif diff --git a/src/emit/emit.c b/src/emit/emit.c index 8df95410..0e7c031f 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -599,10 +599,10 @@ ANN static inline bool emit_exp_pop_next(const Emitter emit, Exp* e); ANN static bool emit_range(const Emitter emit, Range *range) { if (range->start) - CHECK_B(emit_exp_pop_next(emit, range->start)); + CHECK_B(emit_exp(emit, range->start)); else emit_pushimm(emit, 0); if (range->end) - CHECK_B(emit_exp_pop_next(emit, range->end)); + CHECK_B(emit_exp(emit, range->end)); else emit_pushimm(emit, -1); return true; } @@ -1624,12 +1624,14 @@ ANN bool emit_exp_call1(const Emitter emit, const Func f, { const Type t = f->value_ref->from->owner_class; if(t && (!emit->env->curr || !isa(t, emit->env->class_def))) -//!is_new(f->def) || f->value_ref->from->owner_class->array_depth) -//if(f->value_ref->from->owner_class->array_depth) + + //!is_new(f->def) || f->value_ref->from->owner_class->array_depth) + + //if(f,->value_ref->from->owner_class->array_depth) CHECK_B(emit_ensure_func(emit, f)); } } else if(is_static) - push_func_code(emit, f); + push_func_code(emit, f); call_finish(emit, f, size, is_static); emit->status = status; return true; @@ -1860,7 +1862,7 @@ ANN static bool emit_exp_if(const Emitter emit, const Exp_If *exp_if) { const m_uint nval = m_vector_size(&emit->code->live_values); const uint16_t offset = emit->code->frame->curr_offset; const uint16_t vcount = emit->code->frame->value_count; - CHECK_B(emit_exp_pop_next(emit, e)); + CHECK_B(emit_exp(emit, e)); const m_uint nval_if = m_vector_size(&emit->code->live_values); if(nval < nval_if) { const m_uint diff = nval_if - nval; @@ -1874,7 +1876,7 @@ ANN static bool emit_exp_if(const Emitter emit, const Exp_If *exp_if) { const Instr op2 = emit_add_instr(emit, Goto); op->m_val = emit_code_size(emit); - const bool ret = emit_exp_pop_next(emit, exp_if->else_exp); + const bool ret = emit_exp(emit, exp_if->else_exp); const m_uint nval_else = m_vector_size(&emit->code->live_values); if(nval < nval_else) { const m_uint diff = nval_else - nval; @@ -2022,7 +2024,7 @@ ANN static bool emit_stmt_return(const Emitter emit, const Stmt_Exp stmt) { // if(!stmt->val->ref && tflag(stmt->val->type, tflag_compound)) // emit_local(emit, stmt->val->type); emit->status.in_return = true; - CHECK_B(emit_exp_pop_next(emit, stmt->val)); + CHECK_B(emit_exp(emit, stmt->val)); emit->status.in_return = false; } vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto)); @@ -2321,7 +2323,7 @@ ANN static bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt, emit_memsetimm(emit, offset, -1); stmt->idx.value->from->offset = offset; } - CHECK_B(emit_exp_pop_next(emit, stmt->cond)); + CHECK_B(emit_exp(emit, stmt->cond)); emit_regmove(emit, -SZ_INT); emit_regtomem(emit, offset + !!stmt->idx.tag.sym * SZ_INT, 0); *index = emit_code_size(emit); diff --git a/src/gwion.c b/src/gwion.c index 0138a719..8b362e57 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -1,3 +1,4 @@ +#include #include #include "gwion_util.h" #include "gwion_ast.h" @@ -119,11 +120,12 @@ ANN bool gwion_ini(const Gwion gwion, CliArg *arg) { new_passes(gwion); CHECK_B(arg_parse(gwion, arg)); if (arg->color == COLOR_NEVER) - tcol_override_color_checks(0); + gwion->data->color = false; else if (arg->color == COLOR_AUTO) - tcol_override_color_checks(isatty(1)); + gwion->data->color = isatty(1); else if (arg->color == COLOR_ALWAYS) - tcol_override_color_checks(1); + gwion->data->color = true; + tcol_override_color_checks(gwion->data->color); if(!vector_size(&gwion->data->passes->vec)) { if (!gwion->data->cdoc) pass_default(gwion); diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 5f1dcb40..04fb501b 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -13,6 +13,7 @@ #include "parse.h" #include "gwi.h" #include "tmpl_info.h" +#include "sema.h" #undef insert_symbol @@ -279,7 +280,8 @@ ANN static bool scantmpl_class_def(const Env env, struct tmpl_info *info) { if(c->body) cdef->body = cpy_ast(env->gwion->mp, c->body); cdef->cflag = c->cflag; cdef->base.tmpl = mk_tmpl(env, c->base.tmpl, info->td->types); - const bool ret = scan0_class_def(env, cdef); + const bool ret = (!is_spread_tmpl(cdef->base.tmpl) || sema_variadic_class(env, cdef)) && + scan0_class_def(env, cdef); if ((info->ret = cdef->base.type)) { info->ret->info->cdef = cdef; set_tflag(info->ret, tflag_cdef); @@ -374,29 +376,29 @@ static OP_EMIT(opem_cond_object) { GWION_IMPORT(object_op) { const Type t_error = gwi_mk_type(gwi, "@error", 0, NULL); gwi->gwion->type[et_error] = t_error; - GWI_B(gwi_set_global_type(gwi, t_error, et_error)) - GWI_B(gwi_oper_ini(gwi, "Object", "Object", NULL)) - GWI_B(gwi_oper_add(gwi, opck_object_at)) - GWI_B(gwi_oper_emi(gwi, opem_object_at)) - GWI_B(gwi_oper_end(gwi, ":=>", NULL)) - GWI_B(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@Compound", NULL)) - GWI_B(gwi_oper_add(gwi, opck_object_instance)) - GWI_B(gwi_oper_end(gwi, "=>", NULL)) - GWI_B(gwi_oper_ini(gwi, "Object", "Object", "bool")) - GWI_B(gwi_oper_end(gwi, "==", EqObject)) - GWI_B(gwi_oper_end(gwi, "!=", NeqObject)) - GWI_B(gwi_oper_add(gwi, opck_object_cast)) - GWI_B(gwi_oper_end(gwi, "$", NULL)) - GWI_B(gwi_oper_ini(gwi, NULL, "Object", "bool")) - GWI_B(gwi_oper_emi(gwi, opem_uncond_object)) - GWI_B(gwi_oper_end(gwi, "@unconditional", NULL)) - GWI_B(gwi_oper_emi(gwi, opem_cond_object)) - GWI_B(gwi_oper_end(gwi, "@conditional", NULL)) - GWI_B(gwi_oper_add(gwi, opck_unary_meta2)) - GWI_B(gwi_oper_emi(gwi, opem_not_object)) - GWI_B(gwi_oper_end(gwi, "!", NULL)) - GWI_B(gwi_oper_ini(gwi, "@Compound", NULL, NULL)) - GWI_B(gwi_oper_add(gwi, opck_struct_scan)) - GWI_B(gwi_oper_end(gwi, "class", NULL)) + gwi_set_global_type(gwi, t_error, et_error); + GWI_B(gwi_oper_ini(gwi, "Object", "Object", NULL)) + GWI_B(gwi_oper_add(gwi, opck_object_at)) + GWI_B(gwi_oper_emi(gwi, opem_object_at)) + GWI_B(gwi_oper_end(gwi, ":=>", NULL)) + GWI_B(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@Compound", NULL)) + GWI_B(gwi_oper_add(gwi, opck_object_instance)) + GWI_B(gwi_oper_end(gwi, "=>", NULL)) + GWI_B(gwi_oper_ini(gwi, "Object", "Object", "bool")) + GWI_B(gwi_oper_end(gwi, "==", EqObject)) + GWI_B(gwi_oper_end(gwi, "!=", NeqObject)) + GWI_B(gwi_oper_add(gwi, opck_object_cast)) + GWI_B(gwi_oper_end(gwi, "$", NULL)) + GWI_B(gwi_oper_ini(gwi, NULL, "Object", "bool")) + GWI_B(gwi_oper_emi(gwi, opem_uncond_object)) + GWI_B(gwi_oper_end(gwi, "@unconditional", NULL)) + GWI_B(gwi_oper_emi(gwi, opem_cond_object)) + GWI_B(gwi_oper_end(gwi, "@conditional", NULL)) + GWI_B(gwi_oper_add(gwi, opck_unary_meta2)) + GWI_B(gwi_oper_emi(gwi, opem_not_object)) + GWI_B(gwi_oper_end(gwi, "!", NULL)) + GWI_B(gwi_oper_ini(gwi, "@Compound", NULL, NULL)) + GWI_B(gwi_oper_add(gwi, opck_struct_scan)) + GWI_B(gwi_oper_end(gwi, "class", NULL)) return true; } diff --git a/src/parse/check.c b/src/parse/check.c index 56b176cd..57f8c1ae 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -15,7 +15,6 @@ #include "specialid.h" #include "tmp_resolve.h" #include "partial.h" -#include "spread.h" #include "array.h" ANN bool check_stmt(const Env env, Stmt*); @@ -833,16 +832,18 @@ ANN static TmplArg_List check_template_args(const Env env, Exp_Call *exp, if(spread) { Exp* e = exp->args; - if(fdef->base->args) - for(uint32_t i = 0; i < fdef->base->args->len && e; i++) e = e->next; - while(e) { - TmplArg targ = { - .type = tmplarg_td, - .d = { .td = type2td(env->gwion, e->type, e->loc) } - }; - mp_vector_add(env->gwion->mp, &tl, TmplArg, targ); - e = e->next; - } + const uint32_t len = fdef->base->args ? fdef->base->args->len : 0; +// if(fdef->base->args) { + for(uint32_t i = 0; i < len && e; i++) e = e->next; + while(e) { + TmplArg targ = { + .type = tmplarg_td, + .d = { .td = type2td(env->gwion, e->type, e->loc) } + }; + mp_vector_add(env->gwion->mp, &tl, TmplArg, targ); + e = e->next; + } + // } } return tl; } @@ -1400,15 +1401,6 @@ ANN static bool check_conts(const Env env, Stmt* a, Stmt* b) { return true; } -ANN static inline bool for_empty(const Env env, const Stmt_For stmt) { - if (!stmt->c2 || !stmt->c2->d.stmt_exp.val) - ERR_B(stmt_self(stmt)->loc, - _("empty for loop condition..." - "...(note: explicitly use 'true' if it's the intent)" - "...(e.g., 'for(; true;){{ /*...*/ }')")); - return true; -} - ANN static void check_idx(const Env env, const Type base, Var_Decl *const idx) { idx->value = new_value(env, base, idx->tag); valid_value(env, idx->tag.sym, idx->value); @@ -1482,7 +1474,6 @@ stmt_func_xxx(flow, Stmt_Flow, env_inline_mult(env, 1.5), stmt_self(stmt)->stmt_type != ae_stmt_while) || !check_conts(env, stmt_self(stmt), stmt->body)) ? true : false) stmt_func_xxx(for, Stmt_For, env_inline_mult(env, 1.5), !( - !for_empty(env, stmt) || !check_stmt(env, stmt->c1) || !check_flow(env, stmt->c2->d.stmt_exp.val) || (stmt->c3 && !check_exp(env, stmt->c3)) || @@ -2231,8 +2222,6 @@ ANN static bool recursive_type_base(const Env env, const Type t) { return !error; } -ANN bool check_trait_requests(const Env env, const Type t, const ID_List list, const ValueFrom *from); - ANN static bool check_class_tmpl(const Env env, const Tmpl *tmpl, const Nspc nspc) { bool ok = true; if(tmplarg_ntypes(tmpl->list) != tmpl->list->len) { diff --git a/src/parse/check_traits.c b/src/parse/check_traits.c index 3576e14b..019d56d2 100644 --- a/src/parse/check_traits.c +++ b/src/parse/check_traits.c @@ -60,9 +60,13 @@ ANN static bool trait_inherit(const Env env, const Type t, const Func_Def req) { const bool ret = traverse_func_def(env, cpy); nspc_pop_type(env->gwion->mp, env->curr); Section section = MK_SECTION(func, func_def, cpy, t->info->value->from->loc); + if(!env->context->extend) env->context->extend = new_mp_vector(env->gwion->mp, Section, 0); mp_vector_add(env->gwion->mp, &env->context->extend, Section, section); + + // sema_ast, traverse_ast + // mp_vector_add(env->gwion->mp, &t->info->cdef->body, Section, section); return ret; } diff --git a/src/parse/func_resolve_tmpl.c b/src/parse/func_resolve_tmpl.c index 1d46d318..a8d21e8a 100644 --- a/src/parse/func_resolve_tmpl.c +++ b/src/parse/func_resolve_tmpl.c @@ -13,7 +13,7 @@ #include "emit.h" #include "specialid.h" #include "tmp_resolve.h" -#include "spread.h" +#include "sema.h" struct ResolverArgs { const Value v; @@ -32,7 +32,8 @@ ANN static inline Value template_get_ready(const Env env, const Value v, ANN static inline bool tmpl_valid(const Env env, const Func_Def fdef) { if (safe_fflag(fdef->base->func, fflag_valid)) return true; - const bool ret = check_traverse_fdef(env, fdef); + const bool ret = (fdef->builtin || sema_variadic_func(env, fdef)) && + check_traverse_fdef(env, fdef); if(!fdef->base->func) free_func_def(env->gwion->mp, fdef); return ret; } diff --git a/src/parse/scan0.c b/src/parse/scan0.c index d1dede59..ab98f37a 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -10,7 +10,6 @@ #include "instr.h" #include "operator.h" #include "import.h" -#include "spread.h" #include "emit.h" static inline void add_type(const Env env, const Nspc nspc, const Type t) { @@ -370,41 +369,6 @@ ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) { return t; } - -ANN static bool _spread_tmpl(const Env env, const Type t, const Spread_Def spread) { - if(t->info->value->from->owner_class) - CHECK_B(_spread_tmpl(env, t->info->value->from->owner_class, spread)); - const Tmpl *tmpl = get_tmpl(t); - if(!tmpl || !tmpl->call) return true; - if(is_spread_tmpl(tmpl)) - CHECK_B(spread_ast(env, spread, tmpl)); - return true; -} - -ANN static bool spread_tmpl(const Env env, const Spread_Def spread) { - if(env->class_def) CHECK_B(_spread_tmpl(env, env->class_def, spread)); - if(!env->func) return true; - const Tmpl *tmpl = env->func->def->base->tmpl; - if(!tmpl || !tmpl->call) return true; - if(is_spread_tmpl(tmpl)) - CHECK_B(spread_ast(env, spread, tmpl)); - return true; -} - -ANN static bool spreadable(const Env env) { - const Func f = env->func; - if(f && f->def->base->tmpl && is_spread_tmpl(f->def->base->tmpl)) - return true; - Type t = env->class_def; - while(t) { - const Tmpl *tmpl = get_tmpl(t); - if(tmpl && is_spread_tmpl(tmpl)) - return true; - t = t->info->value->from->owner_class; - } - return false; -} - ANN static bool scan0_stmt_list(const Env env, Stmt_List l) { bool ok = true; for(m_uint i = 0; i < l->len; i++) { @@ -417,34 +381,26 @@ ANN static bool scan0_stmt_list(const Env env, Stmt_List l) { if(!plugin_ini(env->gwion, stmt->d.stmt_pp.data, stmt->loc)) POISON_NODE(ok, env, stmt); } - } else if (stmt->stmt_type == ae_stmt_spread) { - if(!spreadable(env)) + } /*else if (stmt->stmt_type == ae_stmt_spread) { + if(!spreadable(env)) // TODO: we can prolly get rid of this ERR_OK_NODE(ok, stmt, stmt->loc, "spread statement outside of variadic environment"); - if(!env->context->extend) - env->context->extend = new_mp_vector(env->gwion->mp, Section, 0); - if(!spread_tmpl(env, &stmt->d.stmt_spread)) - POISON_NODE(ok, env, stmt); - } + }*/ } return ok; } ANN bool scan0_func_def(const Env env, const Func_Def fdef) { - const Ast old_extend = env->context ? env->context->extend : NULL; if(!fdef->base->tmpl || !fdef->base->tmpl->call) return true; - if(env->context) { - if(fdef->base->tmpl && fdef->base->tmpl->call && is_spread_tmpl(fdef->base->tmpl)) { - struct Func_ fake = {.name = s_name(fdef->base->tag.sym), .def = fdef }, *const former = - env->func; + bool ok = true; + if(fdef->base->tmpl && fdef->base->tmpl->call && is_spread_tmpl(fdef->base->tmpl)) { + struct Func_ fake = {.name = s_name(fdef->base->tag.sym), .def = fdef }; + const Func former = env->func; env->func = &fake; if(!fdef->builtin && fdef->d.code) scan0_stmt_list(env, fdef->d.code); - if(env->context->extend) - fdef->d.code = spread_func(env, fdef->d.code); env->func = former; - env->context->extend = old_extend; - }} - return true; + } + return ok; } ANN static bool scan0_extend_def(const Env env, const Extend_Def xdef) { @@ -544,22 +500,13 @@ ANN static bool scan0_class_def_inner(const Env env, const Class_Def cdef) { return cdef->body ? env_body(env, cdef, scan0_section) : true; } -ANN Ast spread_class(const Env env, const Ast body); - ANN bool scan0_class_def(const Env env, const Class_Def c) { bool global = false; CHECK_B(scan0_global(env, c->flag, c->base.tag.loc, &global)); - const Ast old_extend = env->context ? env->context->extend : NULL; const int cpy = tmpl_base(c->base.tmpl) || GET_FLAG(c, global); const Class_Def cdef = !cpy ? c : cpy_class_def(env->gwion->mp, c); const bool ret = scan0_class_def_inner(env, cdef); - if (cpy && cdef->base.type) c->base.type = cdef->base.type; - if(env->context) { - if(!tmpl_base(c->base.tmpl) && env->context->extend) - cdef->body = spread_class(env, cdef->body); - env->context->extend = old_extend; - } if(cflag(cdef, cflag_struct)) scan0_struct_assign(env, cdef->base.type); if (GET_FLAG(cdef, global)) env_pop(env, 0); return ret; diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 93cf66a1..a9f75ee5 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -27,7 +27,6 @@ ANN static inline bool type_cyclic(const Env env, const Type t, } ANN static inline bool ensure_scan1(const Env env, const Type t) { -// if (tflag(t, tflag_scan1) || !(tflag(t, tflag_cdef) || tflag(t, tflag_udef))) if (tflag(t, tflag_scan1) || !(tflag(t, tflag_cdef) || tflag(t, tflag_union))) return true; struct EnvSet es = {.env = env, @@ -595,9 +594,6 @@ ANN bool scan1_union_def(const Env env, const Union_Def udef) { #define scan1_stmt_retry dummy_func ANN static bool scan1_stmt_return(const Env env, const Stmt_Exp stmt) { - if (!env->func || is_ctor(env->func->def)) - ERR_B(stmt_self(stmt)->loc, - _("'return' statement found outside function definition")); if (env->scope->depth == 1) env->func->memoize = 1; if(stmt->val) CHECK_B(scan1_exp(env, stmt->val)); return true; @@ -617,6 +613,7 @@ ANN static bool scan1_stmt_defer(const Env env, const Stmt_Defer stmt) { return scan1_stmt(env, stmt->stmt); } +// TODO: get rid of this function ANN static bool scan1_stmt_spread(const Env env, const Spread_Def spread) { ERR_B(stmt_self(spread)->loc, "spread statement outside of variadic environment"); } @@ -877,23 +874,13 @@ ANN static bool scan1_class_tmpl(const Env env, const Class_Def c) { TmplArg_List tl = c->base.tmpl->call; env_push_type(env, c->base.type); bool ret = true; -// check len for(uint32_t i = 0; i < sl->len; i++) { const TmplArg targ = *mp_vector_at(tl, TmplArg, i); -// const Specialized spec = *mp_vector_at(sl, Specialized, i); if (targ.type == tmplarg_td) continue; if(!scan1_exp(env, targ.d.exp)) { ret = false; break; } -/* - const Value v = new_value(env, env->gwion->type[et_int], s_name(spec.xid), targ.d.exp->loc); - valuefrom(env, v->from); - valid_value(env, spec.xid, v); - SET_FLAG(v, const| ae_flag_static); - set_vflag(v, vflag_builtin); - v->d.num = targ.d.exp->d.prim.d.gwint.num; -*/ } env_pop(env, 0); return ret; diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 5cf63d2e..9ed2f744 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -10,8 +10,6 @@ #include "object.h" #include "instr.h" #include "import.h" -#include "default_args.h" -#include "spread.h" #include "closure.h" ANN static bool scan2_stmt(const Env, Stmt*); @@ -613,23 +611,8 @@ ANN bool scan2_class_def(const Env env, const Class_Def cdef) { return true; } -ANN void scan2_default_args(const Env env, const Section *s, Ast *acc) { - Func_Base *const fb = s->d.func_def->base; - Arg_List args = fb->args; - uint32_t len = args->len; - while(args->len--) { - const Arg *arg = mp_vector_at(args, Arg, args->len); - if(!arg->exp) break; - const Func_Def fdef = default_args(env, fb, acc, len); - scan1_func_def(env, fdef); - scan2_func_def(env, fdef); - } - args->len = len; -} - ANN bool scan2_ast(const Env env, Ast *ast) { Ast a = *ast; - Ast acc = new_mp_vector(env->gwion->mp, Section, 0); bool ok = true; for(m_uint i = 0; i < a->len; i++) { Section *section = mp_vector_at(a, Section, i); @@ -638,16 +621,6 @@ ANN bool scan2_ast(const Env env, Ast *ast) { POISON_SECTION(ok, env, section); continue; } - if (section->section_type == ae_section_func && - fbflag(section->d.func_def->base, fbflag_default)) - mp_vector_add(env->gwion->mp, &acc, Section, *section); - } - if(ok) { - for(uint32_t i = 0; i < acc->len; i++) { - Section *section = mp_vector_at(acc, Section, i); - scan2_default_args(env, section, ast); - } } - free_mp_vector(env->gwion->mp, Section, acc); return ok; } diff --git a/src/parse/spread.c b/src/parse/spread.c deleted file mode 100644 index 4a569e03..00000000 --- a/src/parse/spread.c +++ /dev/null @@ -1,129 +0,0 @@ -#include "gwion_util.h" -#include "gwion_ast.h" -#include "gwion_env.h" -#include "vm.h" -#include "traverse.h" -#include "template.h" -#include "parse.h" -#include "object.h" -#include "instr.h" -#include "operator.h" -#include "import.h" - -ANN bool spread_ast(const Env env, const Spread_Def spread, const Tmpl *tmpl) { - const m_str data = spread->data; - char c[256]; - DECL_B(FILE *,f, = fmemopen(data, strlen(data), "r")); - for(uint32_t i = tmpl->list->len - 1; i < tmpl->call->len; i++) { - fseek(f, 0, SEEK_SET); - const TmplArg targ = *mp_vector_at(tmpl->call, TmplArg, i); - if(targ.type != tmplarg_td) { - gwerr_basic("invalid const expression in variadic template", NULL, "can't use expression in spread", env->name, targ.d.exp->loc, 0); - Specialized *spec = mp_vector_at(tmpl->list, Specialized, tmpl->list->len - 1); - gwerr_secondary("spread starts here", env->name, spec->tag.loc); - env_set_error(env, true); - return false; - } - DECL_B(const Type, t, = known_type(env, targ.d.td)); - struct AstGetter_ arg = {env->name, f, env->gwion->st, .ppa = env->gwion->ppa}; - const m_str type = type2str(env->gwion, t, targ.d.td->tag.loc); - sprintf(c, "%s=%s", s_name(spread->tag.sym), type); - free_mstr(env->gwion->mp, type); - pparg_add(env->gwion->ppa, c); - for(uint32_t j = 0; j < spread->list->len; j++) { - const Symbol sym = *mp_vector_at(spread->list, Symbol, j); - m_str name = s_name(sym); - sprintf(c, "%s=%s%u", name, name, i); - pparg_add(env->gwion->ppa, c); - } - Ast ast = parse_pos(&arg, spread->tag.loc.first); - pparg_rem(env->gwion->ppa, s_name(spread->tag.sym)); - for(uint32_t j = 0; j < spread->list->len;j++) { - const Symbol sym = *mp_vector_at(spread->list, Symbol, j); - m_str name = s_name(sym); - pparg_rem(env->gwion->ppa, name); - } - if(!ast) return false; - CHECK_B(scan0_ast(env, &ast)); - for(uint32_t i = 0; i < ast->len; i++) { - const Section section = *mp_vector_at(ast, Section, i); - mp_vector_add(env->gwion->mp, &env->context->extend, Section, section); - } - free_mp_vector(env->gwion->mp, Section , ast); - } - fclose(f); - mp_vector_add(env->gwion->mp, &env->context->extend, Section, MK_SECTION(stmt, stmt_list, NULL, spread->tag.loc)); - return true; -} - -ANN Ast spread_class(const Env env, const Ast body) { - const Ast extend = env->context->extend; - Ast new_body = new_mp_vector(env->gwion->mp, Section, 0); - uint32_t offset = 0; - for(uint32_t i = 0; i < body->len; i++) { - const Section section = *mp_vector_at(body, Section, i); - if(section.section_type == ae_section_stmt) { - Stmt_List list = section.d.stmt_list; - Stmt_List acc = NULL; - for(uint32_t j = 0; j < list->len; j++) { - const Stmt stmt = *mp_vector_at(list, Stmt, j); - if(stmt.stmt_type == ae_stmt_spread) { - if(acc) { - mp_vector_add(env->gwion->mp, &new_body, Section, MK_SECTION(stmt, stmt_list, acc, stmt.loc)); - acc = NULL; - } - const Ast extend = env->context->extend; - for(; offset < extend->len; offset++) { - const Section section = *mp_vector_at(extend, Section, offset); - if(section.section_type == ae_section_stmt && !section.d.stmt_list) - { - ++offset; - break; - } - mp_vector_add(env->gwion->mp, &new_body, Section, section); - } - } else { - if(!acc) - acc = new_mp_vector(env->gwion->mp, Stmt, 0); - mp_vector_add(env->gwion->mp, &acc, Stmt, stmt); - } - } - if(acc) { - mp_vector_add(env->gwion->mp, &new_body, Section, MK_SECTION(stmt, stmt_list, acc, section.loc)); - } - } - } - free_mp_vector(env->gwion->mp, Section, body); - free_mp_vector(env->gwion->mp, Section, extend); - return new_body; -} - -ANN Stmt_List spread_func(const Env env, const Stmt_List body) { - const Ast extend = env->context->extend; - Ast new_body = new_mp_vector(env->gwion->mp, Stmt, 0); - uint32_t offset = 0; - bool ok = true; - for(uint32_t i = 0; i < body->len; i++) { - Stmt stmt = *mp_vector_at(body, Stmt, i); - if(stmt.stmt_type == ae_stmt_spread) { - for(; offset < extend->len; offset++) { - const Section section = *mp_vector_at(extend, Section, offset); - if(section.section_type == ae_section_stmt && !section.d.stmt_list) - break; - if(section.section_type != ae_section_stmt) - ERR_OK_NODE(ok, &stmt, stmt.loc, "invalid section in variadic func"); - const Stmt_List list = section.d.stmt_list; - for(uint32_t j = 0; j < list->len; j++) { - const Stmt stmt = *mp_vector_at(list, Stmt, j); - mp_vector_add(env->gwion->mp, &new_body, Stmt, stmt); - } - } - } else { - mp_vector_add(env->gwion->mp, &new_body, Stmt, stmt); - } - } - free_mp_vector(env->gwion->mp, Stmt_List, body); - free_mp_vector(env->gwion->mp, Section, extend); - if(ok) return new_body; - return NULL; -} diff --git a/src/parse/template.c b/src/parse/template.c index a1371caa..71db9389 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -12,7 +12,6 @@ #include "instr.h" #include "object.h" #include "import.h" -#include "spread.h" ANN static bool _push_types(const Env env, const Nspc nspc, const Tmpl *tmpl) { diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index 75dc8fab..e30896f9 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -1,6 +1,7 @@ #include "gwion_util.h" #include "gwion_ast.h" #include "gwion_env.h" +#include "symbol.h" #include "vm.h" #include "traverse.h" #include "parse.h" @@ -116,13 +117,21 @@ ANN static Type resolve(const Env env, Type_Decl *td) { return !array ? ret : array_type(env, ret, array->depth, td->tag.loc); } -ANN static inline void *type_unknown(const Env env, const Type_Decl *td) { +ANN m_str tdpp(MemPool mp, SymTable *st, const Type_Decl *td, bool no_color) { struct GwfmtState ls = {}; - text_init(&ls.text, env->gwion->mp); - Gwfmt gwfmter = {.mp = env->gwion->mp, .ls = &ls, .st = env->gwion->st }; + text_init(&ls.text, mp); + Gwfmt gwfmter = {.mp = mp, .ls = &ls, .st = st }; + bool has_color = tcol_has_color(); + if(no_color) tcol_override_color_checks(false); gwfmt_type_decl(&gwfmter, td); - env_err(env, td->tag.loc, _("unknown type '%s'"), s_name(td->tag.sym)); - free_mstr(env->gwion->mp, ls.text.str); + tcol_override_color_checks(has_color); + return ls.text.str; +} + +ANN static inline void *type_unknown(const Env env, const Type_Decl *td) { + m_str str = tdpp(env->gwion->mp, env->gwion->st, td, false); + env_err(env, td->tag.loc, _("unknown type '%s'"), str); + free_mstr(env->gwion->mp, str); return NULL; } diff --git a/src/parse/default_arg.c b/src/sema/default_arg.c similarity index 74% rename from src/parse/default_arg.c rename to src/sema/default_arg.c index f46bf76d..338bec92 100644 --- a/src/parse/default_arg.c +++ b/src/sema/default_arg.c @@ -4,7 +4,7 @@ #include "vm.h" #include "gwion.h" #include "traverse.h" - +#include "sema_private.h" ANN2(1,2) static Exp* base_args(const MemPool p, const Arg_List args, Exp* next, const uint32_t min) { for(uint32_t i = min; i--;) { Arg *arg = mp_vector_at(args, Arg, i); @@ -40,15 +40,15 @@ ANN static Stmt_List code(const MemPool p, Exp* func, const Arg_List lst, return code; } -ANN static Stmt_List std_code(const Env env, Func_Base *base, const uint32_t max) { - const MemPool p = env->gwion->mp; +ANN static Stmt_List std_code(const Sema *sema, Func_Base *base, const uint32_t max) { + const MemPool p = sema->mp; Exp* func = new_prim_id(p, base->tag.sym, base->tag.loc); return code(p, func, base->args, max, ae_stmt_return); } -ANN static Stmt_List new_code(const Env env, Func_Base *base, const uint32_t max) { - const MemPool p = env->gwion->mp; - SymTable *st = env->gwion->st; +ANN static Stmt_List new_code(const Sema *sema, Func_Base *base, const uint32_t max) { + const MemPool p = sema->mp; + SymTable *st = sema->st; Exp* dbase = new_prim_id(p, insert_symbol(st, "this"), base->tag.loc); const Symbol sym = insert_symbol(st, "new"); Exp* func = new_exp_dot(p, dbase, sym, base->tag.loc); @@ -56,13 +56,13 @@ ANN static Stmt_List new_code(const Env env, Func_Base *base, const uint32_t max } -ANN Func_Def default_args(const Env env, Func_Base *fb, Ast *acc, uint32_t max) { - Func_Base *const base = cpy_func_base(env->gwion->mp, fb); +ANN Func_Def default_args(const Sema *sema, Func_Base *fb, Ast *acc, uint32_t max) { + Func_Base *const base = cpy_func_base(sema->mp, fb); Stmt_List code = strcmp(s_name(base->tag.sym), "new") - ? std_code(env, fb, max) - : new_code(env, fb, max); - const Func_Def fdef = new_func_def(env->gwion->mp, base, code); + ? std_code(sema, fb, max) + : new_code(sema, fb, max); + const Func_Def fdef = new_func_def(sema->mp, base, code); Section section = MK_SECTION(func, func_def, fdef, fb->tag.loc); - mp_vector_add(env->gwion->mp, acc, Section, section); + mp_vector_add(sema->mp, acc, Section, section); return fdef; } diff --git a/src/sema/sema.c b/src/sema/sema.c index 8deb9e04..1967ea05 100644 --- a/src/sema/sema.c +++ b/src/sema/sema.c @@ -1,13 +1,13 @@ #include "gwion_util.h" #include "gwion_ast.h" #include "gwion_env.h" -#include "loc.h" #include "vm.h" #include "gwion.h" #include "sema.h" +#define __SEMA_IMPLEMENTATION__ #include "sema_private.h" -#include -#include +#include "default_args.h" +#undef __SEMA_IMPLEMENTATION__ #define POISON(a, b) \ do { \ @@ -176,7 +176,6 @@ ANN static bool sema_variable(Sema *a, Variable *b) { } ANN static bool sema_exp_decl(Sema *a, Exp_Decl *b) { -// TODO: arguments? bool ok = sema_variable(a, &b->var); if(b->args && !sema_exp(a, b->args)) ok = false; @@ -196,7 +195,7 @@ ANN static bool sema_exp_unary(Sema *a, Exp_Unary *b) { POISON(a, exp_self(b)); if(b->ctor.exp) return sema_exp(a, b->ctor.exp); } else - return sema_stmt_list(a, b->code); + return sema_stmt_list(a, &b->code); return !exp_self(b)->poison; } @@ -236,7 +235,7 @@ ANN static bool sema_exp_if(Sema *a, Exp_If *b) { } ANN static bool sema_exp_dot(Sema *a, Exp_Dot *b) { - return sema_exp(a, b->base); + return unique_expression(a, b->base, "in dot expression"); } ANN static bool sema_exp_lambda(Sema *a, Exp_Lambda *b) { @@ -262,45 +261,58 @@ ANN static bool sema_stmt_exp(Sema *a, Stmt_Exp b) { ANN static bool sema_stmt_while(Sema *a, Stmt_Flow b) { const bool ok = sema_exp(a, b->cond); - return sema_stmt(a, b->body) && ok; + return sema_stmt(a, b->body, false) && ok; } ANN static bool sema_stmt_until(Sema *a, Stmt_Flow b) { const bool ok = sema_exp(a, b->cond); - return sema_stmt(a, b->body) && ok; + return sema_stmt(a, b->body, false) && ok; } ANN static bool sema_stmt_for(Sema *a, Stmt_For b) { - bool ok = sema_stmt(a, b->c1); - if(b->c2 && !sema_stmt(a, b->c2)) + bool ok = sema_stmt(a, b->c1, false); + if (!b->c2 || !b->c2->d.stmt_exp.val) { + gwerr_basic( + _("empty for loop condition..."), + _("...(note: explicitly use 'true' if it's the intent)"), + _("...(e.g., 'for(; true;){{ /*...*/ }')"), + a->filename, stmt_self(b)->loc, 0); + ok = false; + } else if(!sema_stmt(a, b->c2, false)) ok = false; if(b->c3 && !sema_exp(a, b->c3)) ok = false; - return sema_stmt(a, b->body) && ok; + return sema_stmt(a, b->body, false) && ok; } ANN static bool sema_stmt_each(Sema *a, Stmt_Each b) { const bool ok = unique_expression(a, b->exp, "in foreach statement"); - return sema_stmt(a, b->body) && ok; + return sema_stmt(a, b->body, false) && ok; } // TODO: rename loop to repeat ANN static bool sema_stmt_loop(Sema *a, Stmt_Loop b) { const bool ok = unique_expression(a, b->cond, "in repeat statement"); - return sema_stmt(a, b->body) && ok; + return sema_stmt(a, b->body, false) && ok; } ANN static bool sema_stmt_if(Sema *a, Stmt_If b) { bool ok = sema_exp(a, b->cond); - if(!sema_stmt(a, b->if_body)) + if(!sema_stmt(a, b->if_body, false)) ok = false; - if(b->else_body && !sema_stmt(a, b->else_body)) + if(b->else_body && !sema_stmt(a, b->else_body, false)) ok = false; return ok; } ANN static bool sema_stmt_code(Sema *a, Stmt_Code b) { - if(b->stmt_list) return sema_stmt_list(a, b->stmt_list); + if(b->stmt_list) { + const bool scope = a->scope; + a->scope = true; + const bool ret = sema_stmt_list(a, &b->stmt_list); + a->scope = scope; + return ret; + } return true; } @@ -339,14 +351,14 @@ ANN static bool sema_stmt_match(Sema *a, Stmt_Match b) { bool ok = sema_exp(a, b->cond); if(!sema_case_list(a, b->list)) ok = false; - if(b->where && !sema_stmt(a, b->where)) + if(b->where && !sema_stmt(a, b->where, false)) ok = false; return ok; } ANN static bool sema_stmt_case(Sema *a, Stmt_Match b) { bool ok = sema_exp(a, b->cond); - if(!sema_stmt_list(a, b->list)) + if(!sema_stmt_list(a, &b->list)) ok = false; if(b->when && !sema_exp(a, b->when)) ok = false; @@ -384,7 +396,7 @@ ANN static bool sema_handler(Sema *a, Handler *b, ID_List *tags) { } } mp_vector_add(a->mp, tags, Tag, b->tag); - return sema_stmt(a, b->stmt) && ok; + return sema_stmt(a, b->stmt, false) && ok; } ANN static bool sema_handler_list(Sema *a, Handler_List b) { @@ -402,7 +414,7 @@ ANN static bool sema_handler_list(Sema *a, Handler_List b) { ANN static bool sema_stmt_try(Sema *a, Stmt_Try b) { const bool handling = a->handling; a->handling = true; - bool ok = sema_stmt(a, b->stmt); + bool ok = sema_stmt(a, b->stmt, false); if(!sema_handler_list(a, b->handler)) ok = false; a->handling = handling; @@ -410,16 +422,148 @@ ANN static bool sema_stmt_try(Sema *a, Stmt_Try b) { } ANN static bool sema_stmt_defer(Sema *a, Stmt_Defer b) { - return sema_stmt(a, b->stmt); + return sema_stmt(a, b->stmt, false); +} + +ANN2(1, 2) static bool sema_spread(Sema *a, const Spread_Def spread, MP_Vector **acc) { + char c[256]; // dangerous? + const m_str data = spread->data; + DECL_B(FILE *,f, = fmemopen(data, strlen(data), "r")); + struct AstGetter_ arg = {a->filename, f, a->st, .ppa = a->ppa}; + if(!a->tmpls) { // we are trying this to prevent too many errors + DECL_B(Ast, ast, = parse_pos(&arg, spread->tag.loc.first)); + const bool ret = sema_ast(a, &ast); + free_ast(a->mp, ast); + return ret; + } + bool ok = true; + for(uint32_t i = 0; i < a->tmpls->len; i++) { + const Type_Decl *td = *mp_vector_at(a->tmpls, Type_Decl*, i); + fseek(f, 0, SEEK_SET); + + const m_str type = tdpp(a->mp, a->st, td, true); + sprintf(c, "%s=%s", s_name(spread->tag.sym), type); + pparg_add(a->ppa, c); + free_mstr(a->mp, type); + for(uint32_t j = 0; j < spread->list->len; j++) { + const Symbol sym = *mp_vector_at(spread->list, Symbol, j); + m_str name = s_name(sym); + char c[256]; // dangerous? + sprintf(c, "%s=%s%i", name, name, i); + pparg_add(a->ppa, c); + } + Ast ast = parse_pos(&arg, spread->tag.loc.first); + pparg_rem(a->ppa, s_name(spread->tag.sym)); + for(uint32_t j = 0; j < spread->list->len;j++) { + const Symbol sym = *mp_vector_at(spread->list, Symbol, j); + m_str name = s_name(sym); + pparg_rem(a->ppa, name); + } + // we should only *sema* the first one + if(ast /*&& sema_ast(a, &ast)*/) { + for(uint32_t i = 0; i < ast->len; i++) { + const Section section = *mp_vector_at(ast, Section, i); + mp_vector_add(a->mp, acc, Section, section); + } + free_mp_vector(a->mp, Section , ast); + } else { + ok = false; + break; + } + } + fclose(f); + return ok; } -ANN static bool sema_stmt_spread(Sema *a NUSED, Spread_Def b NUSED) { - return true; +ANN static Stmt_List spread_to_stmt_list(Sema *a, const Spread_Def spread) { + bool ok = true; + Ast ast = new_mp_vector(a->mp, Section, 0); + if(!sema_spread(a, spread, &ast)) { + free_ast(a->mp, ast); + return NULL; + } + Stmt_List stmt_list = new_mp_vector(a->mp, Stmt, 0); + for(uint32_t i = 0; i < ast->len; i++) { + Section *section = mp_vector_at(ast, Section, i); + if(section->section_type != ae_section_stmt) { + ok = false; + break; + } + for(uint32_t j = 0; j < section->d.stmt_list->len; j++) { + Stmt stmt = *mp_vector_at(section->d.stmt_list, Stmt, j); + mp_vector_add(a->mp, &stmt_list, Stmt, stmt); + } + } + if(ok) { + free_mstr(a->mp, spread->data); + free_id_list(a->mp, spread->list); + free_mp_vector(a->mp, Section, ast); + return stmt_list; + } + gwerr_basic(_("invalid spread section"), NULL, NULL, a->filename, spread->tag.loc, 0); + free_ast(a->mp, ast); + return NULL; +} + + +ANN static bool sema_stmt_spread(Sema *a, Spread_Def b) { + if(!a->tmpls) { + if(a->in_variadic) return sema_spread(a, b, NULL); + else { + gwerr_basic(_("spread statement outside of variadic environment"), NULL, NULL, + a->filename, b->tag.loc, 0); + return false; + } + } + bool ok = true; + DECL_B(Stmt_List, stmt_list, = spread_to_stmt_list(a, b)); + Stmt *stmt = mp_vector_at(stmt_list, Stmt, 0); + if(!sema_stmt(a, stmt, false)) { //bin + free_stmt_list(a->mp, stmt_list); + return false; + } + if(a->stmt_list) { + + Stmt_List base = *a->stmt_list; + const uint32_t index = ((uint8_t*)stmt_self(b) - base->ptr) / sizeof(Stmt); + // for now we will litteraly create a new vector + // TODO: a function to extends array len (and allocate if needed) + MP_Vector *result = new_mp_vector(a->mp, Stmt, base->len + stmt_list->len - 1); + // store the first part of the list in it + // TODO: use memcpy + // or berrer, use the above function to just start at part two + for(uint32_t i = 0; i < index; i++) { + Stmt stmt = *mp_vector_at(base, Stmt, i); + mp_vector_set(result, Stmt, i, stmt); + } + for(uint32_t i = 0; i < stmt_list->len; i++) { + Stmt stmt = *mp_vector_at(stmt_list, Stmt, i); + mp_vector_set(result, Stmt, i + index, stmt); + } + for(uint32_t i = index + 1; i < base->len; i++) { + Stmt stmt = *mp_vector_at(base, Stmt, i); + mp_vector_set(result, Stmt, stmt_list->len + i - 1, stmt); + } + // we can now free the base list + free_mp_vector(a->mp, Stmt, base); + *a->stmt_list = result; + } else { + Stmt_List result = spread_to_stmt_list(a, b); + Stmt *stmt = stmt_self(b); + stmt->stmt_type = ae_stmt_code; + stmt->d.stmt_code.stmt_list = result; + } + return ok; } DECL_STMT_FUNC(sema, bool, Sema*) -ANN static bool sema_stmt(Sema *a, Stmt* b) { - return sema_stmt_func[b->stmt_type](a, &b->d); +ANN static bool sema_stmt(Sema *a, Stmt* b, bool in_list) { + Stmt_List *stmt_list = a->stmt_list; + if(!in_list) a->stmt_list = NULL; + const bool ret = sema_stmt_func[b->stmt_type](a, &b->d); + if(!ret) b->poison = true; + a->stmt_list = stmt_list; + return ret; } ANN static bool sema_arg(Sema *a, Arg *b, const bool no_default) { @@ -461,13 +605,16 @@ ANN static bool sema_arg_list(Sema *a, Arg_List b, return ok; } -ANN static bool sema_stmt_list(Sema *a, Stmt_List b) { +ANN static bool sema_stmt_list(Sema *a, Stmt_List *b) { bool ok = true; - for(uint32_t i = 0; i < b->len; i++) { - Stmt* c = mp_vector_at(b, Stmt, i); - if(!sema_stmt(a, c)) + Stmt_List *stmt_list = a->stmt_list; + a->stmt_list = b; + for(uint32_t i = 0; i < (*b)->len; i++) { + Stmt* c = mp_vector_at(*b, Stmt, i); + if(!sema_stmt(a, c, true)) POISON_OK(a, c, ok); } + a->stmt_list = stmt_list; return ok; } @@ -486,30 +633,77 @@ ANN static bool sema_func_base(Sema *a, Func_Base *b, const bool arg_need_sym) { return ok; } +ANN static bool fill(Sema *a, const Tmpl *tmpl) { + bool ok = true; + const uint32_t len = a->tmpls->len; + for(uint32_t i = tmpl->list->len - 1; i < tmpl->call->len; i++) { + TmplArg targ = *mp_vector_at(tmpl->call, TmplArg, i); + if(targ.type != tmplarg_td) { + gwerr_basic("invalid const expression in variadic template", NULL, + "can't use expression in spread", + a->filename, targ.d.exp->loc, 0); + Specialized *spec = mp_vector_at(tmpl->list, Specialized, + tmpl->list->len - 1); + gwerr_secondary("spread starts here", a->filename, spec->tag.loc); + ok = false; + } + mp_vector_add(a->mp, &a->tmpls, Type_Decl*, targ.d.td); + } + if(ok) return true; + a->tmpls->len = len; + return false; +} + +ANN static void unfill(Sema *a, const Tmpl *b) { + a->tmpls->len -= b->call->len - (b->list->len) - 1; +} + ANN static bool sema_func_def(Sema *a, Func_Def b) { + const Tmpl *tmpl = b->base->tmpl; + const bool is_base = tmpl && tmpl_base(tmpl); + const bool is_spread = tmpl && is_spread_tmpl(tmpl); + const bool in_variadic = a->in_variadic; + const bool is_fill = !is_base && is_spread; + a->in_variadic = in_variadic || is_spread; + if(is_fill && !fill(a, tmpl)) + return false; bool ok = sema_func_base(a, b->base, !GET_FLAG(b->base, abstract)); if(b->d.code) { const bool func = a->func; a->func = true; - (void)sema_stmt_list(a, b->d.code); // ignore code in return value + (void)sema_stmt_list(a, &b->d.code); // ignore code in return value a->func = func; } + if(is_fill) unfill(a, tmpl); + a->in_variadic = in_variadic; return ok; } + ANN static bool sema_class_def(Sema *a, Class_Def b) { + const Tmpl *tmpl = b->base.tmpl; + const bool is_base = tmpl && tmpl_base(tmpl); + const bool is_spread = tmpl && is_spread_tmpl(b->base.tmpl); + const bool in_variadic = a->in_variadic; + const bool is_fill = !is_base && is_spread; + a->in_variadic = a->in_variadic || is_spread; + if(is_fill && !fill(a, tmpl)) + return false; bool ok = sema_type_def( a, &b->base); // TODO: what about typedeffing an array type? if(b->base.ext && b->base.ext->array && !array_not_empty(a, b->base.ext->array, "in class extends", b->base.ext->tag.loc)) ok = false; - if(b->body) sema_ast(a, b->body); // ignore code in return value + if(b->body && !sema_ast(a, &b->body)) + ok = false; + if(is_fill) unfill(a, tmpl); + a->in_variadic = in_variadic; return ok; } ANN static bool sema_trait_def(Sema *a, Trait_Def b) { - if(b->body) return sema_ast(a, b->body); + if(b->body) return sema_ast(a, &b->body); return true; } @@ -571,21 +765,95 @@ ANN static bool sema_prim_def(Sema *a NUSED, Prim_Def b NUSED) { DECL_SECTION_FUNC(sema, bool, Sema*) ANN static bool sema_section(Sema *a, Section *b) { - return sema_section_func[b->section_type](a, *(void**)&b->d); + if(b->section_type != ae_section_stmt) + return sema_section_func[b->section_type](a, *(void**)&b->d); + return sema_section_func[b->section_type](a, &b->d); +} + +ANN void sema_default_args(const Sema *a, const Section *s, Ast *acc) { + Func_Base *const fb = s->d.func_def->base; + Arg_List args = fb->args; + uint32_t len = args->len; + while(args->len--) { + const Arg *arg = mp_vector_at(args, Arg, args->len); + if(!arg->exp) break; + default_args(a, fb, acc, len); + } + args->len = len; } -ANN static bool sema_ast(Sema *a, Ast b) { +ANN static bool sema_ast(Sema *a, Ast *b) { bool ok = true; - for(uint32_t i = 0; i < b->len; i++) { - Section *c = mp_vector_at(b, Section, i); - if(!sema_section(a, c)) + Ast acc = new_mp_vector(a->mp, Section, 0); + for(uint32_t i = 0; i < (*b)->len; i++) { + Section *c = mp_vector_at((*b), Section, i); + if(!sema_section(a, c)) { POISON_OK(a, c, ok); + continue; + } + if (c->section_type == ae_section_func && + fbflag(c->d.func_def->base, fbflag_default)) + mp_vector_add(a->mp, &acc, Section, *c); + } + for(uint32_t i = 0; i < acc->len; i++) { + Section *section = mp_vector_at(acc, Section, i); + sema_default_args(a, section, b); } + free_mp_vector(a->mp, Section, acc); return ok; } +ANN static bool ext_fill(const Gwion gwion, MP_Vector **vec, const Tmpl *tmpl) { + for(uint32_t i = tmpl->list->len - 1; i < tmpl->call->len; i++) { + TmplArg targ = *mp_vector_at(tmpl->call, TmplArg, i); + if(targ.type != tmplarg_td) { + gwerr_basic("invalid const expression in variadic template", NULL, + "can't use expression in spread", + gwion->env->name, targ.d.exp->loc, 0); + Specialized *spec = mp_vector_at(tmpl->list, Specialized, + tmpl->list->len - 1); + gwerr_secondary("spread starts here", gwion->env->name, spec->tag.loc); + return false; + } + mp_vector_add(gwion->mp, vec, Type_Decl*, targ.d.td); + } + return true; +} + +ANN static bool spread_class_vector(const Env env, const Type t, MP_Vector **vec) { + if(t->info->value->from->owner_class) + CHECK_B(spread_class_vector(env, t->info->value->from->owner_class, vec)); + if(!tflag(t, tflag_cdef)) return true; + Tmpl *tmpl = t->info->cdef->base.tmpl; + // TODO: unallow spread tmpl outside of class/struct/func + if(!tmpl || !is_spread_tmpl(tmpl)) return true; + return ext_fill(env->gwion, vec, tmpl); +} + +ANN bool sema_variadic_func(Env a, Func_Def fdef) { + Sema sema = { .filename = a->name, .mp = a->gwion->mp, .st = a->gwion->st, .tmpls = new_mp_vector(a->gwion->mp, Type_Decl*, 0), + .ppa = a->gwion->ppa }; + if(a->class_def) + spread_class_vector(a, a->class_def, &sema.tmpls); + bool ret = sema_func_def(&sema, fdef); + free_mp_vector(a->gwion->mp, Type_Decl*, sema.tmpls); + return ret; +} + + +ANN bool sema_variadic_class(Env a, Class_Def cdef) { + Sema sema = { .filename = a->name, .mp = a->gwion->mp, .st = a->gwion->st, .tmpls = new_mp_vector(a->gwion->mp, Type_Decl*, 0), + .ppa = a->gwion->ppa}; + if(a->class_def) + spread_class_vector(a, a->class_def, &sema.tmpls); + bool ret = sema_class_def(&sema, cdef); + free_mp_vector(a->gwion->mp, Type_Decl*, sema.tmpls); + return ret; +} + ANN bool sema_pass(Env a, Ast *b) { - Sema sema = { .filename = a->name, .mp = a->gwion->mp }; - /*return*/ sema_ast(&sema, *b); + Sema sema = { .filename = a->name, .mp = a->gwion->mp, .st = a->gwion->st, + .ppa = a->gwion->ppa}; + /*return*/ sema_ast(&sema, b); return !sema.error; } diff --git a/tests/pp/define_text.gw b/tests/pp/define_text.gw index 479402d9..879771a1 100644 --- a/tests/pp/define_text.gw +++ b/tests/pp/define_text.gw @@ -1,3 +1,3 @@ -#! [contains] test +#! [contains] this is a test #define macro "test" -<<< macro >>>; +<<< "this is a ", macro >>>; diff --git a/tests/spread/spread_func.gw b/tests/spread/spread_func.gw index 549639d5..b848630a 100644 --- a/tests/spread/spread_func.gw +++ b/tests/spread/spread_func.gw @@ -3,6 +3,5 @@ fun void t:[...]() { <<< "${T} ${arg}" >>>; }... } - t(2.2); t(2); diff --git a/util b/util index b2b8760f..e774331c 160000 --- a/util +++ b/util @@ -1 +1 @@ -Subproject commit b2b8760fd8ba2f996d016bf14655ef7aad476ef6 +Subproject commit e774331c8086cc62472148fcb6a32cbf8bfee8e6 -- 2.43.0