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")\""
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}
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)
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
-Subproject commit 03d756298a20ad5629520c2edba71a92325403bb
+Subproject commit d0200183583ab6124c722503bde947730cfb6f04
+-Wall
+-Wextra
-Iutil/include
-Iast/include
-Iast/libprettyerr/src
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
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) {
}
+#define is_new(a) !strcmp(s_name((a)->base->tag.sym), "new")
#endif
*(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
member->base->exp_type == ae_exp_cast;
}
-#define is_new(a) !strcmp(s_name((a)->base->tag.sym), "new")
#endif
#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,
#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 *);
ANN struct SpecialId_ *specialid_get(const Gwion, const Symbol);
#endif
+#endif
--- /dev/null
+#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);
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;
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));
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);
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) {
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);
}
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);
}
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));
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));
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));
.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;
}
!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;
}
}
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))
#include "gwion_util.h"
#include "gwion_ast.h"
#include "gwion_env.h"
+#include "gwfmt.h"
#include "vm.h"
#include "gwion.h"
#include "clean.h"
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);
+}
+
+
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];
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);
}
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;
}
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);
(!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;
}
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;
}
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
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;
}
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;
}
}
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;
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;
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);
#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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
--- /dev/null
+#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);
+}
#include "pass.h"
#include "traverse.h"
#include "sema.h"
+#include "validate.h"
#define N_PASS 3
#define N_SCANPASS 4
scan1_ast(env, ast);
scan2_ast(env, ast);
check_ast(env, ast);
+ ast_validation(env, ast);
return !env->context->error;
}
--- /dev/null
+#! [contains] maybe use a constructor?
+class C {
+ operator new() {};
+}
+
+var C c;
-Subproject commit e774331c8086cc62472148fcb6a32cbf8bfee8e6
+Subproject commit 2cfc28f61565287e7dd4c61411bf547a2e268206