class C {
- fun int test:[A](A a) { <<< " A ", a >>>; }
- fun int test:[A](A a, int i) { <<< " ", a >>>; }
- fun int test:[A](A a, int i, int j) { <<< a >>>; }
+ fun void test:[A](A a) { <<< " A ", a >>>; }
+ fun void test:[A](A a, int i) { <<< " ", a >>>; }
+ fun void test:[A](A a, int i, int j) { <<< a >>>; }
}
class D extends C {
- fun int test:[A](A a, int i) { <<< this, " extent ", a, __func__ >>>; }
+ fun void test:[A](A a, int i) { <<< this, " extent ", a, __func__ >>>; }
}
class E extends D {
- fun int test:[A](A a, int i) { <<< this, " Extent ", a, __func__ >>>; }
+ fun void test:[A](A a, int i) { <<< this, " Extent ", a, __func__ >>>; }
}
#ifndef __NSPC
#define __NSPC
struct NspcInfo_ {
- m_bit* class_data;
- struct Vector_ vtable;
- struct Map_ op_map;
- Scope value;
- Scope type;
- Scope func;
- size_t offset;
- size_t class_data_size;
+ m_bit* class_data;
+ struct Map_ op_map;
+ Scope value;
+ Scope type;
+ Scope func;
+ Scope trait;
+ size_t offset;
+ size_t class_data_size;
};
struct Nspc_ {
struct NspcInfo_* info;
- Nspc parent;
- m_str name;
- struct VM_Code_* pre_ctor;
- struct VM_Code_* dtor;
- uint16_t ref;
+ Nspc parent;
+ m_str name;
+ struct Vector_ vtable;
+ struct VM_Code_* pre_ctor;
+ struct VM_Code_* dtor;
+ uint16_t ref;
};
REF_FUNC(Nspc, nspc)
describe_nspc_func(Value, value)
describe_nspc_func(Type, type)
describe_nspc_func(Func, func)
+describe_nspc_func(Trait, trait)
/* howere there is no need for lookup_func0, push_func, pop_func */
ANN void did_you_mean_nspc(const Nspc, const char*);
ANN void did_you_mean_type(const Type, const char*);
--- /dev/null
+#ifndef __TRAIT
+#define __TRAIT
+
+typedef struct Trait_ {
+ struct Vector_ requested_values;
+ struct Vector_ requested_funcs;
+ m_str filename;
+ loc_t loc;
+} *Trait;
+
+ANN Trait new_trait(MemPool, const loc_t);
+ANN void free_trait(MemPool, Trait);
+#endif
Type base_type;
struct TupleForm_* tuple;
struct VM_Code_ *gack;
+ ID_List traits;
};
enum tflag {
#include "import/internals.h"
static inline Tmpl* gwi_tmpl(const Gwi gwi) {
- return new_tmpl_base(gwi->gwion->mp, gwi->ck->tmpl);
+ return new_tmpl_base(gwi->gwion->mp, gwi->ck->sl);
}
ANN void gwi_effects(const Gwi gwi, const m_str name);
#define __GWION_ENV
#include "env/oo.h"
+#include "env/trait.h"
#include "env/nspc.h"
#include "env/env.h"
Symbol sym;
union {
ID_List tmpl;
+ Specialized_List sl;
Exp exp;
};
union {
#define _TMPL_INFO
struct tmpl_info {
Symbol name;
- ID_List list;
+ Specialized_List list;
const Type_Decl* td;
Type ret;
Type base;
-Subproject commit fb296d97fea12ee3e44a1120c47033dfe5325a62
+Subproject commit bbba0ebd0da010c4fdaaa53aee5da38e7513c3ff
clean_id_list(a, b->next);
}
+ANN static void clean_specialized_list(Clean *a, Specialized_List b) {
+ if(b->traits)
+ clean_id_list(a, b->traits);
+ if(b->next)
+ clean_specialized_list(a, b->next);
+}
+
ANN static void clean_type_list(Clean *a, Type_List b) {
clean_type_decl(a, b->td);
if(b->next)
ANN static void clean_tmpl(Clean *a, Tmpl *b) {
if(b->base < 0 && b->list)
- clean_id_list(a, b->list);
+ clean_specialized_list(a, b->list);
if(b->call)
clean_type_list(a, b->call);
}
ANN static void clean_class_def(Clean *a, Class_Def b) {
clean_type_def(a, &b->base);
+ if(b->traits)
+ clean_id_list(a, b->traits);
if(b->body)
clean_ast(a, b->body);
}
if(b->tmpl)
clean_tmpl(a, b->tmpl);
}
+
+ANN static void clean_trait_def(Clean *a, Trait_Def b) {
+ if(b->traits)
+ clean_id_list(a, b->traits);
+ if(b->body)
+ clean_ast(a, b->body);
+}
+
DECL_SECTION_FUNC(clean, void, Clean*)
ANN static inline void clean_section(Clean *a, Section *b) {
}
ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call* exp_call) {
+/*
#ifndef GWION_NOINLINE
const Func f = is_inlinable(emit, exp_call);
if(f)
return emit_inline(emit, f, exp_call);
#endif
+*/
CHECK_BB(prepare_call(emit, exp_call));
const Type t = actual_type(emit->gwion, exp_call->func->type);
if(isa(t, emit->gwion->type[et_function]) > 0)
ANN static m_bool emit_extend_def(const Emitter emit, const Extend_Def xdef);
#define emit_fptr_def dummy_func
+#define emit_trait_def dummy_func
HANDLE_SECTION_FUNC(emit, m_bool, Emitter)
ANN static inline m_bool emit_ast_inner(const Emitter emit, Ast ast) {
scope_commit(nspc->info->value);
scope_commit(nspc->info->func);
scope_commit(nspc->info->type);
+ scope_commit(nspc->info->trait);
}
ANN static inline void nspc_release_object(const Nspc a, Value value, Gwion gwion) {
describe_nspc_free(Func, func)
describe_nspc_free(Type, type)
+ANN static void nspc_free_trait(Nspc n, Gwion gwion) {
+ struct scope_iter iter = { n->info->trait, 0, 0 };
+ Trait a;
+ while(scope_iter(&iter, &a) > 0)
+ free_trait(gwion->mp, a);
+ free_scope(gwion->mp, n->info->trait);
+}
ANN void free_nspc(const Nspc a, const Gwion gwion) {
free_nspc_value(a, gwion);
nspc_free_func(a, gwion);
+ nspc_free_trait(a, gwion);
if(a->info->op_map.ptr)
free_op_map(&a->info->op_map, gwion);
nspc_free_type(a, gwion);
if(a->info->class_data && a->info->class_data_size)
mp_free2(gwion->mp, a->info->class_data_size, a->info->class_data);
- if(a->info->vtable.ptr)
- vector_release(&a->info->vtable);
+ if(a->vtable.ptr)
+ vector_release(&a->vtable);
mp_free(gwion->mp, NspcInfo, a->info);
if(a->pre_ctor)
vmcode_remref(a->pre_ctor, gwion);
a->name = name;
a->info = mp_calloc(p, NspcInfo);
a->info->value = new_scope(p);
- a->info->type = new_scope(p);
- a->info->func = new_scope(p);
+ a->info->type = new_scope(p);
+ a->info->func = new_scope(p);
+ a->info->trait = new_scope(p);
a->ref = 1;
return a;
}
--- /dev/null
+#include <gwion_util.h>
+#include <gwion_ast.h>
+#include <gwion_env.h>
+
+ANN Trait new_trait(MemPool mp, const loc_t loc) {
+ const Trait a = mp_calloc(mp, Trait);
+ a->loc = loc;
+ return a;
+}
+
+ANN void free_trait(MemPool mp, Trait a) {
+ if(a->requested_values.ptr)
+ vector_release(&a->requested_values);
+ if(a->requested_funcs.ptr)
+ vector_release(&a->requested_funcs);
+ mp_free(mp, Trait, a);
+}
if(!nspc || !parent)
return;
nspc->info->offset = parent->info->offset;
- if(parent->info->vtable.ptr)
- vector_copy2(&parent->info->vtable, &nspc->info->vtable);
+ if(parent->vtable.ptr)
+ vector_copy2(&parent->vtable, &nspc->vtable);
}
Tmpl* tmpl = t->info->cdef->base.tmpl;
if(tmpl) {
nspc_push_type(env->gwion->mp, env->curr);//
- ID_List il = tmpl->list;
+ Specialized_List il = tmpl->list;
do nspc_add_type(env->curr, il->xid, env->gwion->type[et_auto]);
while((il = il->next));
}
struct ImportCK ck = { .name=name };
CHECK_BO(check_typename_def(gwi, &ck));
DECL_OO(Type_Decl *,td, = gwi_str2td(gwi, parent ?: "Object"));
- Tmpl* tmpl = ck.tmpl ? new_tmpl_base(gwi->gwion->mp, ck.tmpl) : NULL;
+ Tmpl* tmpl = ck.sl ? new_tmpl_base(gwi->gwion->mp, ck.sl) : NULL;
if(tmpl)
CHECK_BO(template_push_types(gwi->gwion->env, tmpl));
const Type base = find_type(gwi->gwion->env, td);
t->info->parent = p;
if(td->array)
set_tflag(t, tflag_typedef);
- if(ck.tmpl)
+ if(ck.sl)
set_tflag(t, tflag_tmpl | tflag_ntmpl);
else
gwi_type_flag(t);
CHECK_BO(check_typename_def(gwi, &ck));
const Type t = new_type(gwi->gwion->mp, s_name(ck.sym), gwi->gwion->type[et_compound]);
set_tflag(t, tflag_struct);
- if(!ck.tmpl)
+ if(!ck.sl)
gwi_type_flag(t);
else {
t->info->cdef = new_class_def(gwi->gwion->mp, 0, ck.sym, NULL, NULL, gwi->loc);
t->info->cdef->base.type = t;
- t->info->cdef->base.tmpl = new_tmpl_base(gwi->gwion->mp, ck.tmpl);
+ t->info->cdef->base.tmpl = new_tmpl_base(gwi->gwion->mp, ck.sl);
t->info->tuple = new_tupleform(gwi->gwion->mp, NULL);
t->info->parent = NULL;
t->info->cdef->cflag |= cflag_struct;
return new_var_decl_list(gwion->mp, var, NULL);
}
-ANN static ID_List _tmpl_list(const Gwion gwion, struct td_checker *tdc) {
+#define SPEC_ERROR (Specialized_List)GW_ERROR
+ANN static Specialized_List _tmpl_list(const Gwion gwion, struct td_checker *tdc) {
DECL_OO(const Symbol, sym, = __str2sym(gwion, tdc));
- ID_List next = NULL;
+ Specialized_List next = NULL;
if(*tdc->str == ',') {
++tdc->str;
- if(!(next = _tmpl_list(gwion, tdc)) || next == (ID_List)GW_ERROR)
- return (ID_List)GW_ERROR;
+ if(!(next = _tmpl_list(gwion, tdc)) || next == SPEC_ERROR)
+ return SPEC_ERROR;
}
- const ID_List list = new_id_list(gwion->mp, sym);
+ // TODO: handle traits?
+ const Specialized_List list = new_specialized_list(gwion->mp, sym, NULL, tdc->pos);
list->next = next;
return list;
}
-ANN static ID_List __tmpl_list(const Gwion gwion, struct td_checker *tdc) {
+ANN static Specialized_List __tmpl_list(const Gwion gwion, struct td_checker *tdc) {
if(tdc->str[0] != ':')
return NULL;
if(tdc->str[1] != '[')
- return (ID_List)GW_ERROR;
+ return SPEC_ERROR;
tdc->str += 2;
- const ID_List list = _tmpl_list(gwion, tdc);
- if(list == (ID_List)GW_ERROR)
- return (ID_List)GW_ERROR;
+ const Specialized_List list = _tmpl_list(gwion, tdc);
+ if(list == SPEC_ERROR)
+ return SPEC_ERROR;
if(tdc->str[0] != ']') { // unfinished template
if(list)
- free_id_list(gwion->mp, list);
- return (ID_List)GW_ERROR;
+ free_specialized_list(gwion->mp, list);
+ return SPEC_ERROR;
}
++tdc->str;
return list;
struct td_checker tdc = { .str= ck->name, .pos=gwi->loc };
if(!(ck->sym = _str2sym(gwi->gwion, &tdc, tdc.str)))
return GW_ERROR;
- ID_List il = __tmpl_list(gwi->gwion, &tdc);
- if(il == (ID_List)GW_ERROR)
+ Specialized_List sl = __tmpl_list(gwi->gwion, &tdc);
+ if(sl == SPEC_ERROR)
return GW_ERROR;
- ck->tmpl = il;
+ ck->sl = sl;
ck->name = s_name(ck->sym);
return GW_OK;
set_tflag(t, tflag_cdef | tflag_tmpl);
void* rem = isa(base, env->gwion->type[et_compound]) > 0 ?
!tflag(base, tflag_struct) ? vm_vector_rem_obj : vm_vector_rem_struct : vm_vector_rem;
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 0), rem);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 0), rem);
void* insert = isa(base, env->gwion->type[et_compound]) > 0 ?
!tflag(base, tflag_struct) ? vm_vector_insert_obj : vm_vector_insert_struct : vm_vector_insert;
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 1), insert);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 2), vm_vector_size);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 3), vm_vector_depth);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 4), vm_vector_cap);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 5), vm_vector_random);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 6), vm_vector_map);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 7), vm_vector_compactmap);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 8), vm_vector_filter);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 9), vm_vector_count);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 10), vm_vector_foldl);
- builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 11), vm_vector_foldr);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 1), insert);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 2), vm_vector_size);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 3), vm_vector_depth);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 4), vm_vector_cap);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 5), vm_vector_random);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 6), vm_vector_map);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 7), vm_vector_compactmap);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 8), vm_vector_filter);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 9), vm_vector_count);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 10), vm_vector_foldl);
+ builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 11), vm_vector_foldr);
if(isa(base, env->gwion->type[et_compound]) > 0) {
t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, SZ_INT, 1, "array component dtor");
set_tflag(t, tflag_dtor);
Type_List tl = tmpl->call;
if(!tl)
return;
- ID_List il = tmpl->list;
+ Specialized_List il = tmpl->list;
while(il) {
const Type t = known_type(env, tl->td);
nspc_add_type(env->curr, il->xid, t);
a->ref = 1;
a->type_ref = t;
if(t->nspc) {
- a->vtable.ptr = t->nspc->info->vtable.ptr;
+ a->vtable.ptr = t->nspc->vtable.ptr;
if(t->nspc->info->offset)
a->data = (m_bit*)_mp_calloc(p, t->nspc->info->offset);
}
return sym;
}
-ANN static m_bool template_match(ID_List base, Type_List call) {
+ANN static m_bool template_match(Specialized_List base, Type_List call) {
while((call = call->next) && (base = base->next));
return !call ? GW_OK : GW_ERROR;
}
CHECK_BB(emit_exp(emit, member->base));
if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0) {
const Instr instr = emit_add_instr(emit, RegPushImm);
- const Func f = (Func)vector_front(&member->base->type->info->parent->nspc->info->vtable);
+ const Func f = (Func)vector_front(&member->base->type->info->parent->nspc->vtable);
instr->m_val = (m_uint)f->code;
return GW_OK;
}
GWI_BB(gwi_oper_emi(gwi, opem_union_ctor))
GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
- const Func f = (Func)vector_front(&t_union->nspc->info->vtable);
+ const Func f = (Func)vector_front(&t_union->nspc->vtable);
const struct Op_Func opfunc = { .ck=opck_union_is };
const struct Op_Import opi = { .rhs=f->value_ref->type,
.func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=insert_symbol(gwi->gwion->st, "@func_check") };
gw_err(_("and not:\n {G}void{0}\n"));
}
-ANN static m_uint get_type_number(ID_List list) {
+ANN static m_uint get_type_number(Specialized_List list) {
m_uint type_number = 0;
do ++type_number;
while((list = list->next));
const m_uint type_number = get_type_number(tm->list);
Type_List tl[type_number];
tl[0] = NULL;
- ID_List list = tm->list;
+ Specialized_List list = tm->list;
while(list) {
Arg_List arg = fdef->base->args;
Exp template_arg = exp->args;
CHECK_BB(check_signature_match(env, fdef, parent_func));
if(!fdef->base->tmpl) {
fdef->base->func->vt_index = parent_func->vt_index;
- vector_set(&env->curr->info->vtable, fdef->base->func->vt_index, (vtype)fdef->base->func);
+ vector_set(&env->curr->vtable, fdef->base->func->vt_index, (vtype)fdef->base->func);
}
return GW_OK;
}
ANN static m_bool check_parent_match(const Env env, const Func_Def fdef) {
const Func func = fdef->base->func;
const Type parent = env->class_def->info->parent;
- if(!env->curr->info->vtable.ptr)
- vector_init(&env->curr->info->vtable);
+ if(!env->curr->vtable.ptr)
+ vector_init(&env->curr->vtable);
if(parent) {
const Value v = find_value(parent, fdef->base->xid);
if(v && isa(v->type, env->gwion->type[et_function]) > 0) {
return match;
}
}
- func->vt_index = vector_size(&env->curr->info->vtable);
- vector_add(&env->curr->info->vtable, (vtype)func);
+ func->vt_index = vector_size(&env->curr->vtable);
+ vector_add(&env->curr->vtable, (vtype)func);
return GW_OK;
}
return ret;
}
+ANN static m_bool _check_trait_def(const Env env, const Trait_Def pdef) {
+ const Trait trait = nspc_lookup_trait1(env->curr, pdef->xid);
+ Ast ast = pdef->body;
+ while(ast) {
+ Section * section = ast->section;
+ if(section->section_type == ae_section_stmt) {
+ Stmt_List list = section->d.stmt_list;
+ while(list) {
+ const Stmt stmt = list->stmt;
+ if(stmt->stmt_type == ae_stmt_exp) {
+ CHECK_BB(traverse_exp(env, stmt->d.stmt_exp.val));
+ Var_Decl_List list = stmt->d.stmt_exp.val->d.exp_decl.list;
+ while(list) {
+ const Value value = list->self->value;
+ valuefrom(env, value->from, list->self->pos); // we do not need owner
+ if(!trait->requested_values.ptr)
+ vector_init(&trait->requested_values);
+ vector_add(&trait->requested_values, (m_uint)value);
+ list = list->next;
+ }
+ }
+ list = list->next;
+ }
+ }
+ ast = ast->next;
+ }
+ return GW_OK;
+}
+
+ANN static m_bool check_trait_def(const Env env, const Trait_Def pdef) {
+ RET_NSPC(_check_trait_def(env, pdef));
+}
+
#define check_fptr_def dummy_func
HANDLE_SECTION_FUNC(check, m_bool, Env)
}
ANN m_bool check_abstract(const Env env, const Class_Def cdef) {
- if(!cdef->base.type->nspc->info->vtable.ptr)
+ if(!cdef->base.type->nspc->vtable.ptr)
return GW_OK;
bool err = false;
- for(m_uint i = 0; i < vector_size(&cdef->base.type->nspc->info->vtable); ++i) {
- Func f = (Func)vector_at(&cdef->base.type->nspc->info->vtable, i);
+ for(m_uint i = 0; i < vector_size(&cdef->base.type->nspc->vtable); ++i) {
+ Func f = (Func)vector_at(&cdef->base.type->nspc->vtable, i);
if(f && GET_FLAG(f->def->base, abstract)) {
if(!err) {
err = true;
return false;
}
+ANN static bool request_var(const Env env, const Type t, const Value request) {
+ const Value value = nspc_lookup_value0(t->nspc, insert_symbol(request->name));
+ if(!value) {
+ gwerr_basic("missing requested variable", NULL, NULL,
+ request->from->filename, request->from->loc, 0);
+ return false;
+ }
+ bool error = true;
+ if(isa(value->type, request->type) < 0) {
+ gwerr_basic("invalid variable type", NULL, NULL,
+ value->from->filename, value->from->loc, 0);
+ // can we point to the type decl?
+ error = false;
+ }
+ if(GET_FLAG(value, const) && !GET_FLAG(request, const)) {
+ gwerr_basic("variable differs in {/}constness{0}", NULL, NULL,
+ value->from->filename, value->from->loc, 0);
+ // can we point to the flag?
+ error = false;
+ }
+ if(error)
+ return true;
+ gwerr_secondary("from requested variable", request->from->filename, request->from->loc);
+ return error;
+}
+
+ANN static bool check_trait_variables(const Env env, const Type t, const Trait trait) {
+ bool error = false;
+ for(m_uint i = 0; i < vector_size(&trait->requested_values); i++) {
+ const Value request = (Value)vector_at(&trait->requested_values, i);
+ if(!request_var(env, t, request))
+ error = true;
+ }
+ return error;
+}
+
+ANN static bool request_fun(const Env env, const Type t, const Func_Def request) {
+ const Value v = nspc_lookup_value0(t->nspc, request->base->xid);
+if(v) {
+ if(isa(v->type, env->gwion->type[et_function]) < 0 || is_fptr(env->gwion, v->type)) {
+ gwerr_basic("is not a function", NULL, NULL,
+ v->from->filename, v->from->loc, 0);
+ return false;
+ }
+ Func f = v->d.func_ref;
+ do {
+ if(compat_func(f->def, request) > 0) {
+ if(!GET_FLAG(f->def->base, abstract))
+ return true;
+ }
+ } while ((f = f->next));
+}
+ if(!GET_FLAG(request->base, abstract)){
+ const m_uint scope = env_push_type(env, t);
+ const Func_Def cpy = cpy_func_def(env->gwion->mp, request);
+ const m_bool ret = traverse_func_def(env, cpy);
+ env_pop(env, scope);
+ if(ret > 0){
+ Section *section = new_section_func_def(env->gwion->mp, cpy);
+ const Ast ast = new_ast(env->gwion->mp, section, NULL);
+ Ast last = t->info->cdef->body;
+ while(last->next)
+ last = last->next;
+ last->next = ast;
+ return true;
+ } else
+ free_func_def(env->gwion->mp, cpy);
+ }
+ if(!v) {
+ gwerr_basic("missing requested function", NULL, NULL,
+ env->name, request->base->pos, 0);
+ return false;
+ }
+ return true;
+}
+
+ANN static bool check_trait_functions(const Env env, const Type t, const Trait trait) {
+ bool error = false;
+ for(m_uint i = 0; i < vector_size(&trait->requested_funcs); i++) {
+ const Func_Def request = (Func_Def)vector_at(&trait->requested_funcs, i);
+ if(!request_fun(env, t, request))
+ error = true;
+ }
+ return error;
+}
+
+ANN2(1,2,3) static inline bool trait_nodup(Type t, const Symbol trait, ID_List list) {
+ bool nodup = true;
+ do {
+ while(list) {
+ if(trait == list->xid)
+// return false;
+ nodup = false;
+ list = list->next;
+ }
+ } while ((t = t->info->parent));
+ return nodup;
+}
+
+ANN static bool check_trait_requests(const Env env, const Type t, const ID_List list) {
+ const Trait trait = nspc_lookup_trait1(env->curr, list->xid);
+ if(!trait_nodup(t, list->xid, list->next)) {
+ gwerr_secondary("duplicated trait", trait->filename, trait->loc);
+ return false;
+ }
+ const bool value_error = check_trait_variables(env, t, trait);
+ const bool funcs_error = check_trait_functions(env, t, trait);
+ if(!value_error && !funcs_error)
+ return true;
+ const Value request = (Value)vector_front(&trait->requested_values);
+ gwerr_secondary("from trait", request->from->filename, trait->loc);
+ return false;
+}
+
ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
const Type t = cdef->base.type;
if(cdef->base.ext)
}
if(!GET_FLAG(cdef, abstract))
CHECK_BB(check_abstract(env, cdef));
+ if(cdef->traits) {
+ ID_List list = cdef->traits;
+ bool value_error = false;
+ do if(!check_trait_requests(env, t, list))
+ value_error = true;
+ while((list = list->next));
+
+ if(value_error) {
+ env->class_def = t;
+ env_error_footer(env);
+ env->context->error = true;
+ return GW_ERROR;
+ }
+ }
+
Value value;
struct scope_iter iter = { t->nspc->info->value, 0, 0 };
while(scope_iter(&iter, &value) > 0) {
struct scope_iter inner = { value->type->nspc->info->value, 0, 0 };
while(scope_iter(&inner, &v) > 0) {
if(isa(v->type, t) > 0 || isa(t, v->type) > 0) {
-//exit(3);
env_err(env, v->from->loc, _("recursive type"));
-env->context->error = false;
+ env->context->error = false;
env_err(env, value->from->loc, _("recursive type"));
-env->context->error = true;
+ env->context->error = true;
return GW_ERROR;
}
}
return m_func;
}
-ANN static Func _find_template_match(const Env env, const Value v, Exp_Call *const exp) {
+ANN static Func __find_template_match(const Env env, const Value v, Exp_Call *const exp) {
DECL_OO(const m_str, tmpl_name, = tl2str(env->gwion, exp->tmpl->call, exp->func->pos));
const Func f = find_tmpl(env, v, exp, tmpl_name);
free_mstr(env->gwion->mp, tmpl_name);
return f;
}
+ANN static inline bool has_trait(const Type t, const Symbol trait) {
+ ID_List list = t->info->traits;
+ while(list) {
+ if(list->xid == trait)
+ return true;
+ list = list->next;
+ }
+ return false;
+}
+
+ANN static inline bool has_traits(const Type t, ID_List traits) {
+ while(traits) {
+ if(!has_trait(t, traits->xid))
+ return false;
+ traits = traits->next;
+ }
+ return true;
+}
+
+ANN static Func _find_template_match(const Env env, const Value v, Exp_Call *const exp) {
+ DECL_OO(const Func, f, = __find_template_match(env, v, exp));
+ Type_List tl = exp->tmpl->call;
+ Specialized_List sl = f->def->base->tmpl->list;
+ while(tl) {
+ DECL_OO(const Type, t, = known_type(env, tl->td));
+ if(!has_traits(t, sl->traits))
+ return NULL;
+ tl = tl->next;
+ }
+ return f;
+}
+
ANN static inline m_bool check_call(const Env env, const Exp_Call* exp) {
const ae_exp_t et = exp->func->exp_type;
if(et != ae_exp_primary && et != ae_exp_dot && et != ae_exp_cast)
return t ?: (Type)GW_ERROR;
}
+ANN static m_bool cdef_traits(const Env env, ID_List traits, const loc_t pos) {
+ do {
+ if(!nspc_lookup_trait1(env->curr, traits->xid))
+ ERR_B(pos, _("can't find trait"));
+ } while((traits = traits->next));
+ return GW_OK;
+}
+
ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos));
const Type parent = cdef_parent(env, cdef);
if(parent == (Type)GW_ERROR)
return NULL;
+ if(cdef->traits)
+ CHECK_BO(cdef_traits(env, cdef->traits, cdef->pos));
const Type t = scan0_type(env, s_name(cdef->base.xid), parent);
if(cflag(cdef, cflag_struct)) {
t->size = 0;
return GW_OK;
}
+ANN static m_bool _scan0_trait_def(const Env env, const Trait_Def pdef) {
+ const Trait trait = new_trait(env->gwion->mp, pdef->pos);
+ trait->loc = pdef->pos;
+ trait->filename = env->name;
+ nspc_add_trait(env->curr, pdef->xid, trait);
+ Ast ast = pdef->body;
+ while(ast) {
+ Section * section = ast->section;
+ if(section->section_type == ae_section_func) {
+ const Func_Def fdef = section->d.func_def;
+ if(!trait->requested_funcs.ptr)
+ vector_init(&trait->requested_funcs);
+ vector_add(&trait->requested_funcs, (m_uint)fdef);
+ }
+ ast = ast->next;
+ }
+ return GW_OK;
+}
+
+ANN static m_bool scan0_trait_def(const Env env, const Trait_Def pdef) {
+ const Symbol s = pdef->xid;
+ const Trait exists = nspc_lookup_trait1(env->curr, s);
+ if(exists) {
+ gwerr_basic("trait already defined", NULL, NULL, env->name, pdef->pos, 0);
+ gwerr_secondary("defined here", env->name, exists->loc);
+ env->context->error = true;
+ return already_defined(env, s, pdef->pos);
+ }
+ _scan0_trait_def(env, pdef);
+ return GW_OK;
+}
+
HANDLE_SECTION_FUNC(scan0, m_bool, Env)
ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
CHECK_OB((cdef->base.type = scan0_class_def_init(env, cdef)));
+ cdef->base.type->info->traits = cdef->traits;
set_tflag(cdef->base.type, tflag_scan0);
(void)mk_class(env, cdef->base.type, cdef->pos);
add_type(env, cdef->base.type->info->value->from->owner, cdef->base.type);
env->class_def->size += t->size;
}
}
- } else
- set_vflag(v, vflag_fglobal);// file global
- }
+ }
+ set_vflag(v, vflag_fglobal);// file global
+ } else
if(GET_FLAG(decl->td, global))
SET_FLAG(v, global);
} while((list = list->next));
}
ANN static m_bool _scan1_fdef_base_tmpl(const Env env, Func_Base *base) {
- ID_List id = base->tmpl->list;
+ Specialized_List id = base->tmpl->list;
do nspc_add_type(env->curr, id->xid, env->gwion->type[et_auto]);
while((id = id->next));
CHECK_OB((base->ret_type = scan1_noret(env, base)));
return ret;
}
+#define scan1_trait_def dummy_func
HANDLE_SECTION_FUNC(scan1, m_bool, Env)
ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) {
ANN static m_str func_tmpl_name(const Env env, const Func_Def f) {
const m_str name = s_name(f->base->xid);
struct Vector_ v;
- ID_List id = f->base->tmpl->list;
+ Specialized_List id = f->base->tmpl->list;
m_uint tlen = 0;
vector_init(&v);
do {
}
#define scan2_enum_def dummy_func
+#define scan2_trait_def dummy_func
+
HANDLE_SECTION_FUNC(scan2, m_bool, Env)
ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) {
#include "import.h"
ANN static m_bool push_types(const Env env, const Tmpl *tmpl) {
- ID_List list = tmpl->list;
+ Specialized_List list = tmpl->list;
Type_List call = tmpl->call;
do {
if(!call)