]> Nishi Git Mirror - gwion.git/commitdiff
:fire: move prettyerr, update errors (mac fix?)
authorfennecdjay <fennecdjay@gmail.com>
Sat, 23 Mar 2024 00:38:02 +0000 (01:38 +0100)
committerfennecdjay <fennecdjay@gmail.com>
Sat, 23 Mar 2024 00:38:02 +0000 (01:38 +0100)
26 files changed:
Makefile
ast
compile_flags.txt
include/env/func.h
include/env/type.h
include/gwion_env.h
include/operator.h
include/parse.h
include/partial.h
include/specialid.h
include/validate.h [new file with mode: 0644]
src/emit/emit.c
src/env/func.c
src/env/type.c
src/import/import_cdef.c
src/lib/array.c
src/lib/object_op.c
src/lib/opfunc.c
src/parse/check.c
src/parse/partial.c
src/parse/scan1.c
src/parse/traverse.c
src/parse/validate.c [new file with mode: 0644]
src/pass.c
tests/ctor/maybe_use.gw [new file with mode: 0644]
util

index 54a44f2121cf8ce7098810132be15e0b6b27a16f..90eed62c1e6a5a35dc243e83e71fd91d61b3ac90 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ src := $(wildcard src/*.c)
 src += $(wildcard src/*/*.c)
 
 CFLAGS += -Iutil/include -Iast/include -D_GNU_SOURCE
-CFLAGS += -Iast/libprettyerr/src -Ifmt/include
+CFLAGS += -Ifmt/include
 
 # add commit hash to version for now
 CFLAGS += -DGWION_VERSION="\"$(shell git log -n1 --format="%h%m%cs")\""
@@ -64,7 +64,7 @@ include embed/embed.mk
 endif
 
 ALMOST_LIBS := fmt/libgwion_fmt.a
-ALMOST_LIBS += ast/libgwion_ast.a ast/libprettyerr/libprettyerr.a
+ALMOST_LIBS += ast/libgwion_ast.a
 ALMOST_LIBS += util/libgwion_util.a
 GWLIBS := lib${PRG}.a ${ALMOST_LIBS}
 LDFLAGS := ${GWLIBS} ${LDFLAGS}
@@ -114,9 +114,6 @@ ast/libgwion_ast.a: util/libgwion_util.a
 fmt/libgwion_fmt.a: ast/libgwion_ast.a
        @+${MAKE} -s -C fmt libgwion_fmt.a
 
-ast/libprettyerr/libprettyerr.a: options-show
-       @+CFLAGS=-I$(shell pwd)/util/include ${MAKE} -s -C ast/libprettyerr static
-
 ast: ast/libgwion_ast.a
        @(info build ast)
 
@@ -133,7 +130,6 @@ clean_core:
 clean-all: clean
                ${MAKE} -s -C fmt clean
                ${MAKE} -s -C ast clean
-               ${MAKE} -s -C ast/libprettyerr clean
                ${MAKE} -s -C util clean
 
 update: clean-all
diff --git a/ast b/ast
index 03d756298a20ad5629520c2edba71a92325403bb..d0200183583ab6124c722503bde947730cfb6f04 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 03d756298a20ad5629520c2edba71a92325403bb
+Subproject commit d0200183583ab6124c722503bde947730cfb6f04
index 8de19c2d21bb1b0384fa1ca10b6898eb1d0515c4..c3061ca83abfe212e5bfe3349267ce61b7704c10 100644 (file)
@@ -1,3 +1,5 @@
+-Wall
+-Wextra
 -Iutil/include
 -Iast/include
 -Iast/libprettyerr/src
index 17db4102dce8ccd8b2f1377034c578b9d8506b38..3836052db4cddfb51c037baed59f0bf15245da51 100644 (file)
@@ -50,4 +50,6 @@ ANN static inline m_uint captures_sz(const Capture_List captures) {
 ANN static inline bool is_ctor(const Func_Def fdef) {
   return !strcmp(s_name(fdef->base->tag.sym), "@ctor");
 }
+
+ANN void print_signature(const Gwion gwion, const Func f);
 #endif
index b215a0b6a996e4ebef7e81794180e48034ef854a..be29078a519d340977592daa80fd9f11d225c4ea 100644 (file)
@@ -82,6 +82,7 @@ ANN Type      actual_type(const struct Gwion_ *gwion, const Type t);
 ANN static inline m_uint env_push_type(const Env env, const Type type) {
   return env_push(env, type, type->nspc);
 }
+ANN bool is_object(const struct Gwion_ *, const Type t);
 ANN bool is_func(const struct Gwion_ *, const Type t);
 ANN bool is_class(const struct Gwion_ *, const Type t);
 ANN __attribute__((returns_nonnull)) static inline Type _class_base(Type t) {
index cf17aa7d62efc13ed8fab02e54da66761f523a17..0de1a33fb15c3fd3d84cdb0e74f9b7fbff6a84e1 100644 (file)
@@ -39,5 +39,6 @@ ANN static inline void defined_here(const Value v) {
 }
 
 
+#define is_new(a) !strcmp(s_name((a)->base->tag.sym), "new")
 #endif
 
index 4f3b5cca189d37543ea87ad94823e3b75704ea98..e1f40d4fcda3010185d908f461d49edd82d13429 100644 (file)
@@ -87,11 +87,6 @@ ANN static inline void operator_resume(struct Op_Import *opi) {
   *(uintptr_t *)opi->ret = opi->data;
 }
 
-ANN static inline void set_decl_ref(Exp* e) {
-  if (e->exp_type == ae_exp_decl)
-    SET_FLAG(e->d.exp_decl.var.vd.value, late);
-}
-
 ANN void func_operator(const Func_Def fdef, struct Op_Import *opi);
 ANN bool add_op_func_check(const Env env, const Type t, const struct Op_Func *opfunc, const m_uint idx);
 #endif
index 4edcfb7986ac795adbf7212437f48e068c04efed..6a66929e7676e7290f31302503449b8aae114bcf 100644 (file)
@@ -171,5 +171,4 @@ ANN static inline bool is_static_call(const Gwion gwion, Exp* e) {
          member->base->exp_type == ae_exp_cast;
 }
 
-#define is_new(a) !strcmp(s_name((a)->base->tag.sym), "new")
 #endif
index 0966a81ced8bad93c98ae6cf778de35fcd8ba1ce..88aa1439e4155cc28714a3f0377f91491c0485e3 100644 (file)
@@ -2,7 +2,6 @@
 #define __PARTIAL_APPLICATION
 
 ANN Type partial_type(const Env, Exp_Call *const);
-ANN void print_signature(const Func f);
 
 ANN static inline bool func_match_inner(const Env env, Exp* e,
                                         const Type t, const bool implicit,
index 787010608e8b1c1133e5d888e55d49d08942d56e..5bddb51556ec1cfed2182a9c29e1e13e7ded6de2 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __SPECIALID
 #define __SPECIALID
 
+ANN struct SpecialId_ *specialid_get(const Gwion, const Symbol);
+#ifndef __NO_EMIT
+
 typedef Type (*idck)(const Env, const Exp_Primary *);
 typedef bool (*idem)(const Emitter, const Exp_Primary *);
 
@@ -26,3 +29,4 @@ ANN static inline Type specialid_type(const Env env, struct SpecialId_ *spid,
 
 ANN struct SpecialId_ *specialid_get(const Gwion, const Symbol);
 #endif
+#endif
diff --git a/include/validate.h b/include/validate.h
new file mode 100644 (file)
index 0000000..885930b
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma once
+
+ANN bool exp_validation(Env env, Exp* b);
+ANN bool func_def_validation(Env env, Func_Def b);
+ANN bool union_def_validation(Env env, Union_Def b);
+ANN bool enum_def_validation(Env env, Enum_Def b);
+ANN bool fptr_def_validation(Env env, Fptr_Def b);
+ANN bool type_def_validation(Env env, Type_Def b);
+ANN bool class_def_validation(Env env, Class_Def b);
+ANN bool ast_validation(Env env, Ast *ast);
index 0e7c031f7f48999452187e06d94f26a74971eb40..892576d55a651cdaa9e7c31bc50f63ef8fd912d9 100644 (file)
@@ -452,8 +452,7 @@ ANN static bool emit_symbol_builtin(const Emitter emit, const Symbol *data) {
     const m_uint size  = v->type->size;
     emit_dotstatic(emit, (m_uint)&v->d.ptr, size, emit_addr);
     // prevent invalid access to global variables
-    if(!emit_addr &&
-       isa(v->type, emit->gwion->type[et_object]))
+    if(!emit_addr && is_object(emit->gwion, v->type))
       emit_fast_except(emit, v->from, prim_pos(data));
   } else {
     const m_uint size = v->type->size;
@@ -464,7 +463,7 @@ ANN static bool emit_symbol_builtin(const Emitter emit, const Symbol *data) {
   return true;
 }
 
-ANN static bool _emit_symbol(const Emitter emit, const Symbol *data) {
+ANN static bool emit_symbol(const Emitter emit, const Symbol *data) {
   const Value v = prim_self(data)->value;
   if (is_class(emit->gwion, v->type)) {
     emit_pushimm(emit, (m_uint)actual_type(emit->gwion, v->type));
@@ -502,17 +501,11 @@ ANN static bool _emit_symbol(const Emitter emit, const Symbol *data) {
   else
     emit_regpushbase(emit, v->from->offset, size, exp_getvar(prim_exp(data)));
   if (GET_FLAG(v, late) && !exp_getvar(prim_exp(data)) &&
-      isa(v->type, emit->gwion->type[et_object]))
+      is_object(emit->gwion, v->type))
     emit_fast_except(emit, v->from, prim_pos(data));
   return true;
 }
 
-ANN static bool emit_symbol(const Emitter emit, const Exp_Primary *prim) {
-  if (!prim->value) // assume it's an operator
-    ERR_B(exp_self(prim)->loc, "missing value for operator");
-  return _emit_symbol(emit, &prim->d.var);
-}
-
 ANN VM_Code finalyze(const Emitter emit, const f_instr exec) {
   emit_add_instr(emit, exec);
   const VM_Code code = emit->info->emit_code(emit);
@@ -725,7 +718,7 @@ ANN static bool emit_prim_id(const Emitter emit, const Symbol *data) {
   struct SpecialId_ *spid = specialid_get(emit->gwion, *data);
   if (unlikely(spid))
     return specialid_instr(emit, spid, prim_self(data));
-  return emit_symbol(emit, prim_self(data));
+  return emit_symbol(emit, data);
 }
 
 ANN static bool emit_prim_perform(const Emitter emit, const Symbol *xid) {
@@ -783,7 +776,7 @@ ANN static void emit_gack_type(const Emitter emit, Exp* e) {
   if (e->exp_type == ae_exp_cast ||
       (e->exp_type == ae_exp_primary && e->d.prim.prim_type == ae_prim_str))
      return;
-  const bool isobj = isa(e->type, emit->gwion->type[et_object]);
+  const bool isobj = is_object(emit->gwion, e->type);
   if (isobj  && (tflag(e->type, tflag_ref) || !GET_FLAG(e->type, final)))
     emit_add_instr(emit, GackType);
 }
@@ -943,11 +936,12 @@ ANN static bool emit_exp_decl_static(const Emitter emit, const Exp_Decl *decl,
                                        const bool     is_ref,
                                        const bool     emit_addr) {
   const Value v = var_decl->value;
-  if (isa(v->type, emit->gwion->type[et_object]) && !is_ref)
+  bool isobj = is_object(emit->gwion, v->type);
+  if (isobj && !is_ref)
     CHECK_B(decl_static(emit, decl, var_decl, 0));
   CHECK_B(emit_dot_static_data(emit, v, !struct_ctor(v) ? emit_addr : 1));
   if (tflag(v->type, tflag_struct)) CHECK_B(struct_finish(emit, decl));
-  if (isa(v->type, emit->gwion->type[et_object]) && !is_ref) {
+  if (isobj && !is_ref) {
     if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
       emit_object_addref(emit, 0, emit_addr);
   }
@@ -1009,7 +1003,7 @@ ANN static bool emit_exp_decl_non_static(const Emitter   emit,
                                            const uint      emit_var) {
   const Value     v        = var_decl->value;
   const Type      type     = v->type;
-  const bool      is_obj   = isa(type, emit->gwion->type[et_object]);
+  const bool      is_obj   = is_object(emit->gwion, type);
   const bool emit_addr = (!is_obj || is_ref) ? emit_var : true;
   if (is_obj && !is_ref && !exp_self(decl)->ref) {
     if(!decl->args) CHECK_B(emit_instantiate_decl(emit, type, decl->var.td, is_ref));
@@ -1052,7 +1046,7 @@ ANN static bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
                                        const uint is_ref, const bool emit_var) {
   const Value     v        = var_decl->value;
   const Type      type     = v->type;
-  const bool      is_obj   = isa(type, emit->gwion->type[et_object]);
+  const bool      is_obj   = is_object(emit->gwion, type);
   const bool emit_addr = (!is_obj || is_ref) ? emit_var : true;
   if (is_obj && !is_ref) {
     if(!decl->args) CHECK_B(emit_instantiate_decl(emit, type, decl->var.td, is_ref));
@@ -1074,18 +1068,6 @@ ANN static bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
   return true;
 }
 
-ANN static void set_late(const Exp_Decl *decl, const Var_Decl *var) {
-  const Value v         = var->value;
-  if (!exp_getvar(exp_self(decl)) &&
-      (GET_FLAG(array_base_simple(v->type), abstract) || GET_FLAG(decl->var.td, late)))
-    SET_FLAG(v, late);
-  else UNSET_FLAG(v, late);
-}
-
-static inline bool late_array(const Type_Decl* td) {
-  return !td->array || !td->array->exp;
-}
-
 ANN static bool emit_decl(const Emitter emit, Exp_Decl *const decl) {
   const bool  global = GET_FLAG(decl->var.td, global);
   const uint    var    = exp_getvar(exp_self(decl));
@@ -1106,26 +1088,8 @@ ANN static bool emit_decl(const Emitter emit, Exp_Decl *const decl) {
                             .op  = insert_symbol("@implicit"),
                             .rhs = t};
     CHECK_B(op_emit(emit, &opi));
-  }
-  set_late(decl, vd);
-  if (!decl->args && !exp_getvar(exp_self(decl)) && GET_FLAG(array_base_simple(v->type), abstract) && !GET_FLAG(decl->var.td, late) &&
-      GET_FLAG(v, late) && late_array(decl->var.td)
-      && GET_FLAG(v->type, abstract)) {
-    env_err(emit->env, decl->var.td->tag.loc, _("Type '%s' is abstract, use {+G}late{0} instead of {G+}%s{0}"),
-             v->type->name, !GET_FLAG(decl->var.td, const) ? "var" : "const");
-    if(v->type->nspc->vtable.ptr) {
-      const Vector vec = &v->type->nspc->vtable;
-      for(m_uint i = 0; i < vector_size(vec); i++) {
-        const Func f = (Func)vector_at(vec, i);
-        if(is_new(f->def)) {
-          gw_err(_("maybe use a constructor?\n"));
-          break;
-        }
-      }
-    }
-    return false;
-  }
-  if(isa(v->type, emit->gwion->type[et_object]) && GET_FLAG(v, late) && exp_getuse(exp_self(decl)))
+  } 
+  if(is_object(emit->gwion, v->type) /*&& GET_FLAG(v, late) */&& exp_getuse(exp_self(decl)) && !exp_getvar(exp_self(decl)))
     emit_add_instr(emit, GWOP_EXCEPT);
   return true;
 }
@@ -1140,7 +1104,7 @@ ANN /*static */ bool emit_exp_decl(const Emitter emit, Exp_Decl *const decl) {
       !global ? emit->env->scope->depth : emit_push_global(emit);
   const bool ret = emit_decl(emit, decl);
   if (global) emit_pop(emit, scope);
-  if(emit->status.in_return && GET_FLAG(decl->var.vd.value, late) && isa(t, emit->gwion->type[et_object]))
+  if(emit->status.in_return && GET_FLAG(decl->var.vd.value, late) && is_object(emit->gwion, t))
     emit_add_instr(emit, GWOP_EXCEPT);
   return ret;
 }
@@ -1957,8 +1921,8 @@ ANN2(1) /*static */ bool emit_exp(const Emitter emit, /* const */ Exp* e) {
     }
     CHECK_B(emit_exp_func[exp->exp_type](emit, &exp->d));
     if (exp->cast_to) CHECK_B(emit_implicit_cast(emit, exp, exp->cast_to));
-    if (isa(e->type, emit->gwion->type[et_object]) &&
-        (e->cast_to ? isa(e->cast_to, emit->gwion->type[et_object]) : 1) &&
+    if (is_object(emit->gwion, exp->type) &&
+        (e->cast_to ? is_object(emit->gwion, e->cast_to) : true) &&
         e->exp_type == ae_exp_decl && GET_FLAG(e->d.exp_decl.var.td, late) &&
         exp_getuse(e) && !exp_getvar(e) &&
         GET_FLAG(e->d.exp_decl.var.vd.value, late))
index fba8b6b8e101e9530c3c3b9636cde2ad50901851..54e9dc32e5b670e5812d4dc71305a4eaf5908706 100644 (file)
@@ -1,6 +1,7 @@
 #include "gwion_util.h"
 #include "gwion_ast.h"
 #include "gwion_env.h"
+#include "gwfmt.h"
 #include "vm.h"
 #include "gwion.h"
 #include "clean.h"
@@ -54,7 +55,17 @@ ANN void builtin_func(const Gwion gwion, const Func f, void *func_ptr) {
         if(likely(arg.type == tmplarg_td))
           mp_vector_set(f->code->types, Type, n++, known_type(gwion->env, arg.d.td));
       }
-//      f->code->types->len = n;
     }
   }
 }
+
+ANN void print_signature(const Gwion gwion, const Func f) {
+  struct GwfmtState ls = {.minimize=true, .ppa = gwion->ppa};
+  text_init(&ls.text, gwion->mp);
+  Gwfmt l = {.mp = gwion->mp, .st = gwion->st, .ls = &ls, .line = 1, .last = cht_nl };
+  gwfmt_func_def(&l, f->def);
+  gwlog_related_from(ls.text.str, f->value_ref->from); 
+  text_release(&ls.text);
+}
+
+
index a30ce4a769563c5cd61939d77cdb6c2322025162..ffd2f39cb73b14ffa317efcc1fdf4f37b6f09ab3 100644 (file)
@@ -139,6 +139,10 @@ ANN bool is_func(const struct Gwion_ *gwion, const Type t) {
   return isa(actual_type(gwion, t), gwion->type[et_function]);
 }
 
+ANN bool is_object(const struct Gwion_ *gwion, const Type t) {
+  return isa(t, gwion->type[et_object]);
+}
+
 ANN inline bool is_class(const struct Gwion_ *gwion, const Type t) {
 //  return isa(t, gwion->type[et_class]);
   return t->info->parent ==  gwion->type[et_class];
index 18c5726f6e622223603b4a3b13d60159968ab816..b7e2270305ceeca81e43a352ec8ab655649e4bde 100644 (file)
@@ -26,7 +26,8 @@ ANN static void mk_dtor(MemPool p, const Type t, const m_uint d) {
 ANN2(1, 2) static void import_class_ini(const Env env, const Type t) {
   t->nspc         = new_nspc(env->gwion->mp, t->name);
   t->nspc->parent = env->curr;
-  if (isa(t, env->gwion->type[et_object])) inherit(t);
+  if (is_object(env->gwion, t))
+    inherit(t);
   env_push_type(env, t);
 }
 
index cf399a26890c9863f0015501cbc874c22172bcb6..2d4142517eb585bad7044121e60e3cdbe6e89ad8 100644 (file)
@@ -403,7 +403,7 @@ ANN static inline bool array_do(const Emitter emit, const Array_Sub array,
     access = emit_add_instr(emit, ArrayAccess);
     access->m_val      = (i+1) * SZ_INT - offset;
     access->udata.one  = offset;
-    if(i < get_depth(t) || isa(array_base(t), emit->gwion->type[et_object])) {
+    if(i < get_depth(t) || is_object(emit->gwion, array_base(t))) {
       const Instr ex     = emit_add_instr(emit, GWOP_EXCEPT);
       ex->m_val          = -SZ_INT;
     }
index 4e3446376f122abaee4f6487dd2f95dc0e669f0a..37962697a8e4caa7f9e50ca8532c034887007ac4 100644 (file)
@@ -264,7 +264,7 @@ OP_EMIT(opem_object_dot) {
     assert(GET_FLAG(value, static));
     emit_dot_static_import_data(emit, value, exp_getvar(exp_self(member)));
   }
-  if(isa(value->type, emit->gwion->type[et_object]) &&
+  if(is_object(emit->gwion, value->type) &&
      !exp_getvar(exp_self(member)) &&
     (GET_FLAG(value, static) || GET_FLAG(value, late)))
     emit_fast_except(emit, value->from, exp_self(member)->loc);
index b6ce9ced949a050835795ff46e5af3100979ebb0..794ca80b6b2236011946790ebdb9e046a29e2dab 100644 (file)
@@ -152,7 +152,7 @@ OP_CHECK(opck_new) {
      (!array || (array->exp && exp_is_zero(array->exp))))
     ERR_N(unary->ctor.td->tag.loc, _("can't use 'new' on abstract type '%s'\n"),
           t->name);
-  if (!isa(t, env->gwion->type[et_object]))
+  if (!is_object(env->gwion, t))
     ERR_N(exp_self(unary)->loc, _("can't use 'new' on non-object types...\n"));
   return t;
 }
index 17106ef1440a07392bab2bb1c0e31a46ff93d703..131dd8cd766c5b6c42ba6a7917b15817ee7077e6 100644 (file)
@@ -189,7 +189,7 @@ ANN Type check_exp_decl(const Env env, Exp_Decl *const decl) {
     env_pop(env, scope);
     set_vflag(decl->var.vd.value, vflag_direct);
   }
-  env_weight(env, 1 + isa(decl->type, env->gwion->type[et_object]));
+  env_weight(env, 1 + is_object(env->gwion, decl->type));
   return ret ? decl->var.vd.value->type : NULL;
 }
 
@@ -709,9 +709,9 @@ static void function_alternative(const Env env, const Type t, Exp* args,
   gwlog_error("Argument type mismatch", "call site",
               env->name, loc, 0);
   // TODO: hint valid alternatives
-  do print_signature(f);
+  do print_signature(env->gwion, f);
   while ((f = f->next));
-  gw_err(_("and not\n  "));
+  gw_err(_("and not:\n  "));
   if (args)
     print_current_args(args);
   else
@@ -1144,7 +1144,7 @@ ANN static Type check_exp_post(const Env env, const Exp_Postfix *post) {
   CHECK_O(opi.lhs);
   exp_setuse(post->exp, 1);
   const Type t = op_check(env, &opi);
-  if (t && !isa(t, env->gwion->type[et_object]))
+  if (t && !is_object(env->gwion, t))
     exp_setmeta(exp_self(post), 1);
   return t;
 }
index f96893a328620e67d8d74006f0e49aceb17fc88c..60df61ea79ae3a9c9c0f9319a93e0074df64cef6 100644 (file)
@@ -114,30 +114,11 @@ ANN Func find_match_actual(const Env env, const Func up, Exp* args) {
 
 ANN static Func partial_match(const Env env, const Func up, Exp* args, const loc_t loc);
 
-ANN static void print_arg(Arg_List args) {
-  for(uint32_t i = 0; i < args->len; i++) {
-    Arg *arg = mp_vector_at(args, Arg, i);
-    gw_err("{G}%s{0} {/}%s{0}", arg->type ? arg->type->name : NULL,
-           arg->var.vd.tag.sym ? s_name(arg->var.vd.tag.sym) : "");
-    if(i < args->len - 1) gw_err(", ");
-  }
-}
-
-ANN void print_signature(const Func f) {
-  gw_err("  {-}(%s){0}  ", f->name);
-  const Arg_List args = f->def->base->args;
-  if (args)
-    print_arg(args);
-  else
-    gw_err("{G}void{0}");
-  gw_err("\n");
-}
-
 ANN void ambiguity(const Env env, Func f, Exp* args, const loc_t loc) {
-  print_signature(f);
+  print_signature(env->gwion, f);
   while(f->next) {
     const Func next = partial_match(env, f->next, args, loc);
-    if(next) print_signature(next);
+    if(next) print_signature(env->gwion, next);
     f = f->next;
   }
 }
@@ -154,7 +135,7 @@ ANN static Func partial_match(const Env env, const Func up, Exp* args, const loc
           gwlog_error(_("can't resolve ambiguity"), _("in this partial application"), env->name, loc, 0);
           gwlog_hint(_("use typed holes: `_ $ type`"), env->name, loc);
           gw_err(_("\nthose functions could match:\n"));
-          print_signature(f);
+          print_signature(env->gwion, f);
           ambiguity(env, next, args, loc);
           env_set_error(env,  true);
           return NULL;
index 122a6b330b7c5a59e32236ee334d24b283dbf65b..7a70b2a15279918e1aa625d8835b1f069e0058fc 100644 (file)
@@ -133,7 +133,7 @@ ANN static bool scan1_decl(const Env env, Exp_Decl *const decl) {
         set_vflag(v, vflag_member);
         if(tflag(t, tflag_release))
           set_tflag(env->class_def, tflag_release);
-        if(isa(t, env->gwion->type[et_object]))
+        if(is_object(env->gwion, t))
           set_vflag(v, vflag_release);
         if (tflag(env->class_def, tflag_struct)) {
           v->from->offset = env->class_def->size;
@@ -815,7 +815,7 @@ ANN static bool scan1_parent(const Env env, const Class_Def cdef) {
   if (cdef->base.ext->array && cdef->base.ext->array->exp)
     CHECK_B(scan1_exp(env, cdef->base.ext->array->exp));
   DECL_B(const Type, parent, = scan1_get_parent(env, &cdef->base));
-  if (!isa(parent, env->gwion->type[et_object]) &&
+  if (!is_object(env->gwion, parent) &&
 //      !(tflag(cdef->base.type, tflag_cdef) || tflag(cdef->base.type, tflag_udef)))
       !(tflag(cdef->base.type, tflag_cdef) || tflag(cdef->base.type, tflag_union)))
     ERR_B(loc, _("cannot extend primitive type '%s'"), parent->name);
index 0e60249256de5b150d6e01be46cebabb632244bf..83012cae279683cfd69675cd673afdfa86caa840 100644 (file)
@@ -2,19 +2,13 @@
 #include "gwion_ast.h"
 #include "gwion_env.h"
 #include "traverse.h"
-
-ANN bool traverse_ast(const Env env, Ast *const ast) {
-  CHECK_B(scan0_ast(env, ast));
-  CHECK_B(scan1_ast(env, ast));
-  CHECK_B(scan2_ast(env, ast));
-  CHECK_B(check_ast(env, ast));
-  return true;
-}
+#include "validate.h"
 
 ANN bool traverse_exp(const Env env, Exp* exp) {
   CHECK_B(scan1_exp(env, exp));
   CHECK_B(scan2_exp(env, exp));
   CHECK_B(check_exp(env, exp));
+  CHECK_B(exp_validation(env, exp));
   return true;
 }
 
@@ -23,6 +17,7 @@ ANN static bool _traverse_func_def(const Env env, const Func_Def fdef) {
   CHECK_B(scan1_func_def(env, fdef));
   CHECK_B(scan2_func_def(env, fdef));
   CHECK_B(check_func_def(env, fdef));
+  CHECK_B(func_def_validation(env, fdef));
   return true;
 }
 
@@ -40,6 +35,7 @@ ANN bool traverse_union_def(const Env env, const Union_Def def) {
   CHECK_B(scan2_union_def(env, def));
   //  if(!GET_FLAG(def, check))
   CHECK_B(check_union_def(env, def));
+  CHECK_B(union_def_validation(env, def));
   return true;
 }
 
@@ -48,6 +44,7 @@ ANN bool traverse_enum_def(const Env env, const Enum_Def def) {
   CHECK_B(scan1_enum_def(env, def));
   //  CHECK_B(scan2_enum_def(env, def));
   //  CHECK_B(check_enum_def(env, def));
+  CHECK_B(enum_def_validation(env, def));
   return true;
 }
 
@@ -56,6 +53,7 @@ ANN bool traverse_fptr_def(const Env env, const Fptr_Def def) {
   CHECK_B(scan1_fptr_def(env, def));
   CHECK_B(scan2_fptr_def(env, def));
   CHECK_B(check_fptr_def(env, def));
+  CHECK_B(fptr_def_validation(env, def));
   return true;
 }
 
@@ -64,6 +62,7 @@ ANN bool traverse_type_def(const Env env, const Type_Def def) {
   CHECK_B(scan1_type_def(env, def));
   CHECK_B(scan2_type_def(env, def));
   CHECK_B(check_type_def(env, def));
+  CHECK_B(type_def_validation(env, def));
   return true;
 }
 
@@ -72,5 +71,15 @@ ANN bool traverse_class_def(const Env env, const Class_Def def) {
   if (!tflag(t, tflag_scan1)) CHECK_B(scan1_class_def(env, def));
   if (!tflag(t, tflag_scan2)) CHECK_B(scan2_class_def(env, def));
   if (!tflag(t, tflag_check)) CHECK_B(check_class_def(env, def));
+  CHECK_B(class_def_validation(env, def));
+  return true;
+}
+
+ANN bool traverse_ast(const Env env, Ast *const ast) {
+  CHECK_B(scan0_ast(env, ast));
+  CHECK_B(scan1_ast(env, ast));
+  CHECK_B(scan2_ast(env, ast));
+  CHECK_B(check_ast(env, ast));
+  CHECK_B(ast_validation(env, ast));
   return true;
 }
diff --git a/src/parse/validate.c b/src/parse/validate.c
new file mode 100644 (file)
index 0000000..e83665d
--- /dev/null
@@ -0,0 +1,537 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "validate.h"
+#define __NO_EMIT
+#include "specialid.h"
+
+typedef struct {
+  Env env;
+  uint32_t jumps;
+} Validate;
+
+ANN static bool validate_type_decl(Validate *a, Type_Decl *b);
+ANN static bool validate_exp(Validate *a, Exp* b);
+ANN static bool validate_stmt(Validate *a, Stmt* b);
+ANN static bool validate_stmt_list(Validate *a, Stmt_List b);
+ANN static bool validate_func_def(Validate *a, Func_Def b);
+ANN static bool validate_type_def(Validate *a, Type_Def b);
+ANN static bool validate_ast(Validate *a, Ast b);
+
+#define CHECK_RET(a, ret) \
+do {                      \
+  if(!(a))                \
+    ret = false;          \
+} while(0) 
+
+ANN static bool validate_array_sub(Validate *a, Array_Sub b) {
+  return b->exp ? validate_exp(a, b->exp) : true;
+}
+
+ANN static bool validate_specialized(Validate *a, Specialized *b) {
+  return b->td ? validate_type_decl(a, b->td) : true;
+}
+
+ANN static bool validate_specialized_list(Validate *a, Specialized_List b) {
+  bool ret = true;
+  for(uint32_t i = 0; i < b->len; i++) {
+    Specialized * c = mp_vector_at(b, Specialized  , i);
+    if(!validate_specialized(a, c))
+      ret = false;
+  }
+  return ret;
+}
+
+ANN static bool validate_tmplarg(Validate *a, TmplArg *b) {
+  bool ret = true;
+  if (b->type == tmplarg_td)
+    CHECK_RET(validate_type_decl(a, b->d.td), ret);
+  else CHECK_RET(validate_exp(a, b->d.exp), ret);
+  return ret;
+}
+
+ANN static bool validate_tmplarg_list(Validate *a, TmplArg_List b) {
+  bool ret = true;
+  for(uint32_t i = 0; i < b->len; i++) {
+    TmplArg *c = mp_vector_at(b, TmplArg, i);
+    if(!validate_tmplarg(a, c))
+      ret = false;
+  }
+  return ret;
+}
+
+ANN static bool validate_tmpl(Validate *a, Tmpl *b) {
+  bool ret = true;
+  if(b->list) CHECK_RET(validate_specialized_list(a, b->list), ret);
+  if(b->call) CHECK_RET(validate_tmplarg_list(a, b->call), ret);
+  return ret;
+}
+
+ANN static bool validate_range(Validate *a, Range *b) {
+  bool ret = true;
+  if(b->start) CHECK_RET(validate_exp(a, b->start), ret);
+  if(b->end) CHECK_RET(validate_exp(a , b->end), ret);
+  return ret;
+}
+
+ANN static bool validate_type_decl(Validate *a, Type_Decl *b) {
+  bool ret = true;
+  if(b->array) CHECK_RET(validate_array_sub(a, b->array), ret);
+  if(b->types) CHECK_RET(validate_tmplarg_list(a, b->types), ret);
+  return ret;
+}
+
+ANN static bool validate_prim_id(Validate *a, Exp_Primary *b) {
+  struct SpecialId_ *spid = specialid_get(a->env->gwion, b->d.var);
+  if(spid) return true;
+  if (!b->value) {// assume it's an operator
+    env_err(a->env, exp_self(b)->loc, "missing value for operator");
+    return false;
+  }
+  return true;
+}
+
+ANN static bool validate_prim(Validate *a, Exp_Primary *b) {
+  if(b->prim_type == ae_prim_id)
+    return validate_prim_id(a, b);
+  if(b->prim_type == ae_prim_dict ||
+     b->prim_type == ae_prim_hack ||
+     b->prim_type == ae_prim_interp)
+    return validate_exp(a, b->d.exp);
+  if(b->prim_type == ae_prim_array)
+    return validate_array_sub(a, b->d.array);
+  if(b->prim_type == ae_prim_range)
+    return validate_range(a, b->d.range);
+  return true;
+}
+
+ANN static bool validate_variable(Validate *a, Variable *b) {
+  return b->td ? validate_type_decl(a, b->td) : true;
+}
+
+ANN static void set_late(const Exp_Decl *decl, const Var_Decl *var) {
+  const Value v         = var->value;
+  if (!decl->args &&
+      (GET_FLAG(array_base_simple(v->type), abstract) || GET_FLAG(decl->var.td, late)))
+    SET_FLAG(v, late);
+  else UNSET_FLAG(v, late);
+}
+
+static inline bool late_array(const Type_Decl* td) {
+  return !td->array || !td->array->exp;
+}
+
+ANN static bool validate_exp_decl(Validate *a, Exp_Decl *b) {
+  if(b->args && !strncmp(b->args->type->name, "partial:", 8)) {
+    env_err(a->env, b->args->loc, "unresolved partial");
+    return false;
+  }
+  CHECK_B(validate_variable(a, &b->var));
+  Var_Decl *vd = &b->var.vd;
+  Value v = vd->value;
+  if(!v) return true;
+  if(is_object(a->env->gwion, v->type) && !b->args) {
+    set_late(b, vd);
+  if (!exp_getvar(exp_self(b)) && GET_FLAG(array_base_simple(v->type), abstract) && !GET_FLAG(b->var.td, late) &&
+      /*GET_FLAG(v, late) && */late_array(b->var.td)
+      && GET_FLAG(v->type, abstract)) {
+    env_err(a->env, b->var.td->tag.loc, _("Type '%s' is abstract, use {+G}late{0} instead of {G+}%s{0}"),
+             v->type->name, !GET_FLAG(b->var.td, const) ? "var" : "const");
+    if(v->type->nspc->vtable.ptr) {
+      bool has_new = false;
+      const Vector vec = &v->type->nspc->vtable;
+      for(m_uint i = 0; i < vector_size(vec); i++) {
+        const Func f = (Func)vector_at(vec, i);
+        if(is_new(f->def)) {
+          if(!has_new) {
+            gwlog_hint(_("maybe use a constructor?"), a->env->name, b->var.td->tag.loc);
+            has_new = true;
+          }
+          print_signature(a->env->gwion, f);
+        }
+      }
+    }
+    return false;
+  }
+  }
+  return true;
+}
+
+ANN static bool validate_exp_binary(Validate *a, Exp_Binary *b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->lhs), ret);
+  CHECK_RET(validate_exp(a, b->rhs), ret);
+  return ret;
+}
+
+ANN static bool validate_exp_unary(Validate *a, Exp_Unary *b) {
+  bool ret = true;
+  const enum unary_type type = b->unary_type;
+  if(type == unary_exp)
+    CHECK_RET(validate_exp(a, b->exp), ret);
+  else if(type == unary_td)
+    CHECK_RET(validate_type_decl(a, b->ctor.td), ret);
+  else
+    CHECK_RET(validate_stmt_list(a, b->code), ret);
+  return ret;
+}
+
+ANN static bool validate_exp_cast(Validate *a, Exp_Cast *b) {
+  bool ret = true;
+  CHECK_RET(validate_type_decl(a, b->td), ret);
+  CHECK_RET(validate_exp(a, b->exp), ret);
+  return ret;
+}
+
+ANN static bool validate_exp_post(Validate *a, Exp_Postfix *b) {
+  return validate_exp(a, b->exp);
+}
+
+ANN static bool validate_exp_call(Validate *a, Exp_Call *b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->func), ret);
+  if(b->args) CHECK_RET(validate_exp(a, b->args), ret);
+  if(b->tmpl) CHECK_RET(validate_tmpl(a, b->tmpl), ret);
+  return ret;
+}
+
+ANN static bool validate_exp_array(Validate *a, Exp_Array *b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->base), ret);
+  CHECK_RET(validate_array_sub(a, b->array), ret);
+  return ret;
+}
+
+ANN static bool validate_exp_slice(Validate *a, Exp_Slice *b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->base), ret);
+  CHECK_RET(validate_range(a, b->range), ret);
+  return ret;
+}
+
+ANN static bool validate_exp_if(Validate *a, Exp_If *b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->cond), ret);
+  if(b->if_exp) CHECK_RET(validate_exp(a, b->if_exp), ret);
+  CHECK_RET(validate_exp(a, b->else_exp), ret);
+  return ret;
+}
+
+ANN static bool validate_exp_dot(Validate *a, Exp_Dot *b) {
+  return validate_exp(a, b->base);
+}
+
+ANN static bool validate_exp_lambda(Validate *a, Exp_Lambda *b) {
+  return validate_func_def(a, b->def);
+}
+
+ANN static bool validate_exp_td(Validate *a, Type_Decl *b) {
+  return validate_type_decl(a, b);
+}
+
+DECL_EXP_FUNC(validate, bool, Validate*)
+ANN static bool validate_exp(Validate *a, Exp* b) {
+  bool ret = true;
+  if(!b->poison)
+    CHECK_RET(validate_exp_func[b->exp_type](a, &b->d), ret);
+  if(b->next) CHECK_RET(validate_exp(a, b ->next), ret);
+  return ret;
+}
+
+ANN static bool validate_stmt_exp(Validate *a, Stmt_Exp b) {
+  bool ret = true;
+  if(b->val) CHECK_RET(validate_exp(a,  b->val), ret);
+  return ret;
+}
+
+ANN static bool validate_stmt_jump(Validate *a, Stmt *stmt) {
+  a->jumps++;
+  const bool ret = validate_stmt(a, stmt);
+  a->jumps--;
+  return ret;
+}
+
+ANN static bool validate_stmt_flow(Validate *a, Stmt_Flow b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->cond), ret);
+  CHECK_RET(validate_stmt_jump(a, b->body), ret);
+  return ret;
+}
+#define validate_stmt_while validate_stmt_flow
+#define validate_stmt_until validate_stmt_flow
+
+ANN static bool validate_stmt_for(Validate *a, Stmt_For b) {
+  CHECK_B(validate_stmt(a, b->c1));
+  if(b->c2) CHECK_B(validate_stmt(a, b->c2));
+  if(b->c3) CHECK_B(validate_exp(a, b->c3));
+  CHECK_B(validate_stmt_jump(a, b->body));
+  return true;
+}
+
+ANN static bool validate_stmt_each(Validate *a, Stmt_Each b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->exp), ret);
+  CHECK_RET(validate_stmt_jump(a, b->body), ret);
+  return ret;
+}
+
+ANN static bool validate_stmt_loop(Validate *a, Stmt_Loop b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a,  b->cond), ret);
+  CHECK_RET(validate_stmt_jump(a, b->body), ret);
+  return ret;
+}
+
+ANN static bool validate_stmt_if(Validate *a, Stmt_If b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a,  b->cond), ret);
+  CHECK_RET(validate_stmt(a, b->if_body), ret);
+  if(b->else_body) CHECK_RET(validate_stmt(a, b->else_body), ret);
+  return ret;
+}
+
+ANN static bool validate_stmt_code(Validate *a, Stmt_Code b) {
+  bool ret = true;
+  if(b->stmt_list) CHECK_RET(validate_stmt_list(a, b->stmt_list), ret);
+  return ret;
+}
+
+ANN static inline bool validate_stmt_index(Validate *a, const Stmt_Index stmt) {
+  if (stmt->idx > a->jumps) {
+    env_err(a->env, stmt_self(stmt)->loc, _("too many jumps required."));
+    return false;
+  }
+  return true;
+}
+
+ANN static bool validate_stmt_break(Validate *a, Stmt_Index b) {
+  return validate_stmt_index(a, b);
+}
+
+ANN static bool validate_stmt_continue(Validate *a, Stmt_Index b) {
+  return validate_stmt_index(a, b);
+}
+
+ANN static bool validate_stmt_return(Validate *a, Stmt_Exp b) {
+  bool ret = true;
+  if(b->val) CHECK_RET(validate_exp(a, b-> val), ret);
+  return ret;
+}
+
+ANN static bool validate_stmt_case(Validate *a, Stmt_Match b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->cond), ret);
+  CHECK_RET(validate_stmt_list(a, b->list), ret);
+  if(b->when) CHECK_RET(validate_exp(a, b->when), ret);
+  return ret;
+}
+
+ANN static bool validate_case_list(Validate *a, Stmt_List b) {
+  bool ret = true;
+  for(uint32_t i = 0; i < b->len; i++) {
+    Stmt* c = mp_vector_at(b, Stmt, i);
+    if(!validate_stmt_case(a, &c->d.stmt_match))
+      ret = false;
+  }
+  return ret;
+}
+
+ANN static bool validate_stmt_match(Validate *a, Stmt_Match b) {
+  bool ret = true;
+  CHECK_RET(validate_exp(a, b->cond), ret);
+  CHECK_RET(validate_case_list(a, b->list), ret);
+  if(b->where) CHECK_RET(validate_stmt(a, b->where), ret);
+  return ret;
+}
+
+ANN static bool validate_stmt_pp(Validate *a NUSED, Stmt_PP b NUSED) {
+  if(b->pp_type == ae_pp_include)
+    a->env->name = b->data;
+  return true;
+}
+
+#define validate_stmt_retry dummy_func
+
+ANN static bool validate_handler(Validate *a, Handler *b) {
+  return validate_stmt(a, b->stmt);
+}
+
+ANN static bool validate_handler_list(Validate *a, Handler_List b) {
+  bool ret = true;
+  for(uint32_t i = 0; i < b->len; i++) {
+    Handler *handler = mp_vector_at(b, Handler, i);
+    if(!validate_handler(a, handler))
+      ret = false;
+  }
+  return ret;
+}
+
+ANN static bool validate_stmt_try(Validate *a, Stmt_Try b) {
+  bool ret = true;
+  CHECK_RET(validate_stmt(a, b->stmt), ret);
+  CHECK_RET(validate_handler_list(a, b->handler), ret);
+  return ret;
+}
+
+ANN static bool validate_stmt_defer(Validate *a, Stmt_Defer b) {
+  return validate_stmt(a, b->stmt);
+}
+
+ANN static bool validate_stmt_spread(Validate *a NUSED, Spread_Def b NUSED) {
+  return true;
+}
+DECL_STMT_FUNC(validate, bool, Validate*)
+ANN static bool validate_stmt(Validate *a, Stmt* b) {
+  if(b->poison) return false;
+  if(!validate_stmt_func[b->stmt_type](a, &b->d))
+    b->poison = true;
+  return !b->poison;
+}
+
+ANN static bool validate_arg(Validate *a, Arg *b) {
+  return validate_variable(a, &b->var);
+}
+
+ANN static bool validate_arg_list(Validate *a, Arg_List b) {
+  bool ret = true;
+  for(uint32_t i = 0; i < b->len; i++) {
+    Arg *c = mp_vector_at(b, Arg, i);
+    if(!validate_arg(a, c))
+      ret = false;
+  }
+  return ret;
+}
+
+ANN static bool validate_variable_list(Validate *a, Variable_List b) {
+  bool ret = true;
+  for(uint32_t i = 0; i < b->len; i++) {
+    Variable *c = mp_vector_at(b, Variable, i);
+    if(!validate_variable(a, c))
+      return true;
+  }
+  return ret;
+}
+
+ANN static bool validate_stmt_list(Validate *a, Stmt_List b) {
+  bool ret = true;
+  for(uint32_t i = 0; i < b->len; i++) {
+    Stmt* c = mp_vector_at(b, Stmt, i);
+    if(!validate_stmt(a, c))
+      ret = false;
+  }
+  return ret;
+}
+
+ANN static bool validate_func_base(Validate *a, Func_Base *b) {
+  bool ret = true;
+  if(b->td)   CHECK_RET(validate_type_decl(a, b->td), ret);
+  if(b->args) CHECK_RET(validate_arg_list(a, b->args), ret);
+  if(b->tmpl) CHECK_RET(validate_tmpl(a, b->tmpl), ret);
+  return ret;
+}
+
+ANN static bool validate_func_def(Validate *a, Func_Def b) {
+  bool ret = true;
+  CHECK_RET(validate_func_base(a, b->base), ret);
+  if(!b->builtin && b->d.code)
+    CHECK_RET(validate_stmt_list(a, b->d.code), ret);
+  return ret;
+}
+
+ANN static bool validate_class_def(Validate *a, Class_Def b) {
+  bool ret = true;
+  CHECK_RET(validate_type_def(a, &b->base), ret);
+  if(b->body) return validate_ast(a, b->body);
+  return ret;
+}
+
+ANN static bool validate_trait_def(Validate *a, Trait_Def b) {
+  bool ret = true;
+  if(b->body) CHECK_RET(validate_ast(a, b->body), ret);
+  return ret;
+}
+
+#define validate_enum_def dummy_func
+
+ANN static bool validate_union_def(Validate *a, Union_Def b) {
+  bool ret = true;
+  CHECK_RET(validate_variable_list(a, b->l), ret);
+  if(b->tmpl) CHECK_RET(validate_tmpl(a, b->tmpl), ret);
+  return ret;
+}
+
+ANN static bool validate_fptr_def(Validate *a, Fptr_Def b) {
+  return validate_func_base(a, b->base);
+}
+
+ANN static bool validate_type_def(Validate *a, Type_Def b) {
+  bool ret = true;
+  if(b->ext)  CHECK_RET(validate_type_decl(a, b->ext), ret);
+  if(b->tmpl) CHECK_RET(validate_tmpl(a, b->tmpl), ret);
+  if(b->when) CHECK_RET(validate_exp(a, b->when), ret);
+  return ret;
+}
+
+ANN static bool validate_extend_def(Validate *a, Extend_Def b) {
+  return validate_type_decl(a, b->td);
+}
+
+#define validate_prim_def dummy_func
+
+DECL_SECTION_FUNC(validate, bool, Validate*)
+ANN static bool validate_section(Validate *a, Section *b) {
+  if(b->poison) return false;
+  if(!validate_section_func[b->section_type](a, *(void**)&b->d))
+    b->poison = true;
+  return !b->poison;
+}
+
+ANN static bool validate_ast(Validate *a, Ast b) {
+  bool ret = true;
+  for(uint32_t i = 0; i < b->len; i++) {
+    Section *c = mp_vector_at(b, Section, i);
+    if(!validate_section(a, c))
+      ret = false;
+  }
+  return ret;
+}
+
+ANN bool exp_validation(Env env, Exp* b) {
+  Validate a = { .env = env };
+  return validate_exp(&a , b);
+}
+
+ANN bool func_def_validation(Env env, Func_Def b) {
+  Validate a = { .env = env };
+  return validate_func_def(&a , b);
+}
+
+ANN bool union_def_validation(Env env, Union_Def b) {
+  Validate a = { .env = env };
+  return validate_union_def(&a , b);
+}
+
+ANN bool type_def_validation(Env env, Type_Def b) {
+  Validate a = { .env = env };
+  return validate_type_def(&a , b);
+}
+
+ANN bool enum_def_validation(Env env, Enum_Def b) {
+  Validate a = { .env = env };
+  return validate_enum_def(&a , b);
+}
+
+ANN bool fptr_def_validation(Env env, Fptr_Def b) {
+  Validate a = { .env = env };
+  return validate_fptr_def(&a , b);
+}
+
+ANN bool class_def_validation(Env env, Class_Def b) {
+  Validate a = { .env = env };
+  return validate_class_def(&a , b);
+}
+
+ANN bool ast_validation(Env env, Ast *ast) {
+  Validate a = { .env = env };
+  return validate_ast(&a , *ast);
+}
index 25ffb45f1f0ded9f9c59b9f8d34be301457c9975..cd8ec8051f74c907476f064d3e25d1520586b0e6 100644 (file)
@@ -8,6 +8,7 @@
 #include "pass.h"
 #include "traverse.h"
 #include "sema.h"
+#include "validate.h"
 
 #define N_PASS     3
 #define N_SCANPASS 4
@@ -17,6 +18,7 @@ static bool typecheck_ast(const Env env, Ast *ast) {
   scan1_ast(env, ast);
   scan2_ast(env, ast);
   check_ast(env, ast);
+  ast_validation(env, ast);
   return !env->context->error;
 }
 
diff --git a/tests/ctor/maybe_use.gw b/tests/ctor/maybe_use.gw
new file mode 100644 (file)
index 0000000..10ade3d
--- /dev/null
@@ -0,0 +1,6 @@
+#! [contains] maybe use a constructor?
+class C {
+  operator new() {};
+}
+
+var C c;
diff --git a/util b/util
index e774331c8086cc62472148fcb6a32cbf8bfee8e6..2cfc28f61565287e7dd4c61411bf547a2e268206 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit e774331c8086cc62472148fcb6a32cbf8bfee8e6
+Subproject commit 2cfc28f61565287e7dd4c61411bf547a2e268206