]> Nishi Git Mirror - gwion.git/commitdiff
:art: Semantic pass
authorfennecdjay <fennecdjay@gmail.com>
Sun, 10 Mar 2024 13:40:45 +0000 (14:40 +0100)
committerfennecdjay <fennecdjay@gmail.com>
Sun, 10 Mar 2024 13:40:45 +0000 (14:40 +0100)
26 files changed:
ast
fmt
include/default_args.h
include/env/env.h
include/env/envset.h
include/gwiondata.h
include/sema.h
include/sema_private.h
include/spread.h [deleted file]
src/emit/emit.c
src/gwion.c
src/lib/object_op.c
src/parse/check.c
src/parse/check_traits.c
src/parse/func_resolve_tmpl.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/spread.c [deleted file]
src/parse/template.c
src/parse/type_decl.c
src/sema/default_arg.c [moved from src/parse/default_arg.c with 74% similarity]
src/sema/sema.c
tests/pp/define_text.gw
tests/spread/spread_func.gw
util

diff --git a/ast b/ast
index f5b426bcc8570dabb40dcccc8f5b5ba3236b002e..a6e7b8a3b30f8e7e01f99547f38693c888ac0957 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit f5b426bcc8570dabb40dcccc8f5b5ba3236b002e
+Subproject commit a6e7b8a3b30f8e7e01f99547f38693c888ac0957
diff --git a/fmt b/fmt
index b6a9fa7512897dc1420549c511561b94f722d34c..16503e30235be57175d6ee2645bbbadb44ac1f98 160000 (submodule)
--- a/fmt
+++ b/fmt
@@ -1 +1 @@
-Subproject commit b6a9fa7512897dc1420549c511561b94f722d34c
+Subproject commit 16503e30235be57175d6ee2645bbbadb44ac1f98
index 96373374991b4f3393bc08470c841b63e086e9fe..6258ca8cdf31fa4c5de9a8855005efd82234de6d 100644 (file)
@@ -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
index 3e46f75f7e00c360df4668131a2006ca71d738c6..a9cfdb309131e335ae84f72a8019e01113030d77 100644 (file)
@@ -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);
index 798d4c7105d65bd2469fbfc80ebf50f9477dd05c..86b1c27ad46fff8321234bd01f93c57f8d4ccb53 100644 (file)
@@ -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);
index fec1d4e2d3767e57b0062e37c69953aca4e3deea..6b6df9667821f4483da9a5feb3e6adf5611ae842 100644 (file)
@@ -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);
index 8b8a37639a17d4102af702892f635271056eaeb4..7dab714d23750f96d542084d467741f901038247 100644 (file)
@@ -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 
index bff82abdd637f14b02ddf78a1d34d61e4bd23ba4..d6eee9f5aaa436ff1b2d9282b64a2bc609eec13c 100644 (file)
@@ -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 (file)
index 5cf9426..0000000
+++ /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
index 8df95410dbb6483fb469f84a852996ef9482eda0..0e7c031f7f48999452187e06d94f26a74971eb40 100644 (file)
@@ -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);
index 0138a719937eb2bf0857cf43a465251fa0659ec6..8b362e57acf328f57bfd9569ea4a7a425f215475 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdbool.h>
 #include <unistd.h>
 #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);
index 5f1dcb400ed612e96fcb899807c7861c9e255437..04fb501b80a6d837f202606805d2e7b829ef4c43 100644 (file)
@@ -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;
 }
index 56b176cd9b8ba56a45e1350c8a4d503894fa6762..57f8c1ae3947d133ba79e436fc21eb5970bf5304 100644 (file)
@@ -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) {
index 3576e14be91499e684a2b618bd0b31f04a0b1fc6..019d56d2e89556afe77e341f66e80ca10c9f2075 100644 (file)
@@ -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;
 }
 
index 1d46d318b5f394f11d653004c1d9496430220109..a8d21e8a6294ad72994c616c08f2d24f76d201ba 100644 (file)
@@ -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;
 }
index d1dede595b90e53c27b6bb7101a842111a5c6594..ab98f37ac1be996f7e2a66101683cab5261b7e7d 100644 (file)
@@ -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;
index 93cf66a1ab83408ca2ad3e2289be85e61e6933f4..a9f75ee5fafd8fe2cd81f05775948462e44531c6 100644 (file)
@@ -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;
index 5cf63d2e94c2365094a737ff952bfe0c8e30c401..9ed2f744c4416a2121df22b2484ff3c3369b6eba 100644 (file)
@@ -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 (file)
index 4a569e0..0000000
+++ /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;
-}
index a1371caa75af530ce6a77a1f2a6822a736873796..71db9389283a4cead8824ed5b1b2ae7b22279ff3 100644 (file)
@@ -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) {
index 75dc8fab2aa8236337086586ec9c763bf2309449..e30896f97f9c604e08cdaf09e7461b6127280f82 100644 (file)
@@ -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;
 }
 
similarity index 74%
rename from src/parse/default_arg.c
rename to src/sema/default_arg.c
index f46bf76d144c1992cadadd4083691353f97a974c..338bec923ccb661c3a359e0e02740659ada39be3 100644 (file)
@@ -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;
 }
index 8deb9e04d1770a5d74d55fe5b1baf8a5e24e6e45..1967ea05b3e485ad8e2c166fc72f1e66e6c286fc 100644 (file)
@@ -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 <ctype.h>
-#include <stdlib.h>
+#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;
 }
index 479402d96ce6fac473750a9c1f98c34681903945..879771a19cd7a887085213166db0d8bf7aeddf44 100644 (file)
@@ -1,3 +1,3 @@
-#! [contains] test
+#! [contains] this is a test
 #define macro "test"
-<<< macro >>>;
+<<< "this is a ", macro >>>;
index 549639d5e3539a10124bab72df2929028d633fab..b848630aa76c4eda9a1cb377719e6c7eb5ddbe9b 100644 (file)
@@ -3,6 +3,5 @@ fun void t:[...]() {
      <<< "${T} ${arg}" >>>;
   }...
 }
-
 t(2.2);
 t(2);
diff --git a/util b/util
index b2b8760fd8ba2f996d016bf14655ef7aad476ef6..e774331c8086cc62472148fcb6a32cbf8bfee8e6 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit b2b8760fd8ba2f996d016bf14655ef7aad476ef6
+Subproject commit e774331c8086cc62472148fcb6a32cbf8bfee8e6