-Subproject commit f5b426bcc8570dabb40dcccc8f5b5ba3236b002e
+Subproject commit a6e7b8a3b30f8e7e01f99547f38693c888ac0957
-Subproject commit b6a9fa7512897dc1420549c511561b94f722d34c
+Subproject commit 16503e30235be57175d6ee2645bbbadb44ac1f98
#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
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);
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);
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);
+#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
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);
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);
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
+++ /dev/null
-#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
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;
}
{
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;
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;
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;
// 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));
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);
+#include <stdbool.h>
#include <unistd.h>
#include "gwion_util.h"
#include "gwion_ast.h"
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);
#include "parse.h"
#include "gwi.h"
#include "tmpl_info.h"
+#include "sema.h"
#undef insert_symbol
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);
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;
}
#include "specialid.h"
#include "tmp_resolve.h"
#include "partial.h"
-#include "spread.h"
#include "array.h"
ANN bool check_stmt(const Env env, Stmt*);
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;
}
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);
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)) ||
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) {
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;
}
#include "emit.h"
#include "specialid.h"
#include "tmp_resolve.h"
-#include "spread.h"
+#include "sema.h"
struct ResolverArgs {
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;
}
#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) {
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++) {
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) {
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;
}
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,
#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;
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");
}
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;
#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*);
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);
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;
}
+++ /dev/null
-#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;
-}
#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) {
#include "gwion_util.h"
#include "gwion_ast.h"
#include "gwion_env.h"
+#include "symbol.h"
#include "vm.h"
#include "traverse.h"
#include "parse.h"
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;
}
#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);
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);
}
-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;
}
#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 <ctype.h>
-#include <stdlib.h>
+#include "default_args.h"
+#undef __SEMA_IMPLEMENTATION__
#define POISON(a, b) \
do { \
}
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;
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;
}
}
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) {
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;
}
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;
}
}
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) {
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;
}
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) {
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;
}
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;
}
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;
}
-#! [contains] test
+#! [contains] this is a test
#define macro "test"
-<<< macro >>>;
+<<< "this is a ", macro >>>;
<<< "${T} ${arg}" >>>;
}...
}
-
t(2.2);
t(2);
-Subproject commit b2b8760fd8ba2f996d016bf14655ef7aad476ef6
+Subproject commit e774331c8086cc62472148fcb6a32cbf8bfee8e6