-Subproject commit 50ab3bf5f4dbbbc493e382d0a74cd8a9cd6f2b7b
+Subproject commit a65a350359e30f6b8da0af1ba98d282fc9ea1b2f
+++ /dev/null
-fork {
- <<< "start" >>>;
- 12::samp => now;
- me.test_cancel();
- <<< "stop" >>>;
-} @=> Fork ref f;
-
-1 => f.set_cancel;
-2::samp => now;
-0 => f.set_cancel;
-f.join();
typedef void (*f_bbqrun)(const struct VM_*);
typedef struct BBQ_ {
- uint64_t pos;
+ volatile uint64_t pos;
m_float* in;
m_float* out;
struct SoundInfo_ *si;
} Driver;
#define DRVINI(a) ANN m_bool a(struct VM_ *vm NUSED, Driver* di NUSED)
-#define DRVRUN(a) ANN void a(struct VM_ *vm NUSED, Driver* di NUSED)
+#define DRVRUN(a) ANN void a(struct VM_ *vm NUSED, Driver *di NUSED)
#define DRVDEL(a) ANN void a(struct VM_ *vm NUSED, Driver* di NUSED)
ANN void dummy_driver(DriverData*);
ANN static inline m_uint env_push_global(const Env env) { return env_push(env, NULL, env->global_nspc); }
ANN void env_pop(const Env, const m_uint);
ANN Map env_label(const Env);
-ANN Type scan_type(const Env, const Type, const Type_Decl*);
-ANN Type type_decl_resolve(const Env, const Type_Decl*);
+ANN Type scan_type(const Env, const Type, Type_Decl*);
+//ANN Type type_decl_resolve(const Env, const Type_Decl*);
+ANN Type type_decl_resolve(const Env, Type_Decl*);
ANN Value mk_class(const Env env, const Type base);
// tl2str returns a mp_alloced string
ANEW ANN m_str tl2str(const Env, const Type_List); // in type_decl.c
ANN m_bool compat_func(const __restrict__ Func_Def, const __restrict__ Func_Def);
-ANN Type known_type(const Env env, const Type_Decl*);
+ANN Type known_type(const Env env, Type_Decl*);
ANN Type type_nonnull(const Env env, const Type base);
ANN Type prim_ref(const Env env, const Type t, const Type_Decl* td);
ANN m_bool env_access(const Env env, const ae_flag flag, const loc_t pos);
ANN m_bool env_storage(const Env env, ae_flag flag, const loc_t pos);
ANN void env_add_type(const Env, const Type);
-ANN Type find_type(const Env, ID_List);
+ANN Type find_type(const Env, Type_Decl*);
ANN m_bool already_defined(const Env env, const Symbol s, const loc_t pos);
ANN m_bool type_engine_check_prog(const Env, const Ast);
ANN m_bool traverse_func_template(const Env, const Func_Def);
--- /dev/null
+#ifndef __ENVSET
+#define __ENVSET
+
+typedef m_bool (*envset_func)(const void*,const void*);
+struct EnvSet {
+ const Env env;
+ const envset_func func;
+ const void *data;
+ const m_int scope;
+ const ae_flag flag;
+ m_bool run;
+};
+
+ANN m_bool envset_run(struct EnvSet *es, const Type t);
+ANN m_bool envset_push(struct EnvSet *es, const Type t);
+ANN void envset_pop(struct EnvSet *es, const Type t);
+#endif
};
ANN Type tuple_type(const Env, const Vector, const loc_t);
-ANN void tuple_info(const Env, Type_Decl*, const Var_Decl);
+ANN void tuple_info(const Env, const Value);
ANN2(1) TupleForm new_tupleform(MemPool p, const Type parent_type);
ANN void free_tupleform(const TupleForm tuple);
#define __TYPE
struct TypeInfo_ {
- Type parent;
- Nspc owner;
+ Type parent;
+ Nspc owner;
+ Type owner_class;
Class_Def def;
union type_data {
Func func;
Type base_type;
} d;
- struct Vector_ contains;
struct TupleForm_* tuple;
struct VM_Code_ *gack;
struct Context_ *ctx;
#include "env/func.h"
#include "env/context.h"
#include "env/tuple.h"
+#include "env/envset.h"
#endif
m_str rhs;// oper
} OperCK;
-struct array_checker {
- m_str str;
- Exp base, exp;
- m_uint depth;
- m_uint sz;
- m_bool is_exp;
-};
-
ANN void func_checker_clean(const Gwi gwi, struct ImportCK *ck);
ANN m_bool check_typename_def(const Gwi gwi, struct ImportCK *ck);
ANN ID_List tmpl_valid(const Gwi gwi, const m_str str);
ANN Symbol str2sym(const Gwi gwi, const m_str path);
ANN ID_List str2symlist(const Gwi gwi, const m_str path);
-ANN ID_List ck2list(const Gwi gwi, struct array_checker *ck);
ANN m_bool ck_ini(const Gwi, const enum importck_type);
ANN m_bool ck_ok(const Gwi, const enum importck_type);
#ifndef __IMPORT_INTERNALS
#define __IMPORT_INTERNALS
-#define GWI_ERR_B(a,...) { env_err(gwi->gwion->env, gwi->loc, (a), ## __VA_ARGS__); return GW_ERROR; }
-#define GWI_ERR_O(a,...) { env_err(gwi->gwion->env, gwi->loc, (a), ## __VA_ARGS__); return NULL; }
+#define GWI_ERR(a,...) { env_err(gwi->gwion->env, gwi->loc, (a), ## __VA_ARGS__); }
+#define GWI_ERR_B(a,...) { GWI_ERR((a), ## __VA_ARGS__); return GW_ERROR; }
+#define GWI_ERR_O(a,...) { GWI_ERR((a), ## __VA_ARGS__); return NULL; }
#define ENV_ERR_B(pos, a,...) { env_err(env, pos, (a), ## __VA_ARGS__); return GW_ERROR; }
#define ENV_ERR_O(pos, a,...) { env_err(env, pos, (a), ## __VA_ARGS__); return NULL; }
m_bit* data;
Type type_ref;
Vector vtable;
- /* volatile */size_t ref;
+ volatile size_t ref;
};
ANN void instantiate_object(const VM_Shred, const Type);
ANN void __release(const M_Object, const VM_Shred);
ANN void exception(const VM_Shred, const m_str);
ANN void broadcast(const M_Object);
+
#define STRING(o) (*(m_str*) ((M_Object)o)->data)
#define ME(o) (*(VM_Shred*) ((M_Object)o)->data)
#define EV_SHREDS(o) (*(Vector*) ((M_Object)o)->data)
eFuncUsrEnd,
eFuncMemberEnd,
eSporkIni,
+ eForkIni,
eSporkFunc,
eSporkMemberFptr,
eSporkExp,
- eForkEnd,
eSporkEnd,
eBranchEqInt,
eBranchNeqInt,
#define FuncUsrEnd (f_instr)eFuncUsrEnd
#define FuncMemberEnd (f_instr)eFuncMemberEnd
#define SporkIni (f_instr)eSporkIni
+#define ForkIni (f_instr)eForkIni
#define SporkFunc (f_instr)eSporkFunc
#define SporkMemberFptr (f_instr)eSporkMemberFptr
#define SporkExp (f_instr)eSporkExp
-#define ForkEnd (f_instr)eForkEnd
#define SporkEnd (f_instr)eSporkEnd
#define BranchEqInt (f_instr)eBranchEqInt
#define BranchNeqInt (f_instr)eBranchNeqInt
#ifndef __TEMPLATE
#define __TEMPLATE
ANN m_bool template_push_types(const Env, const Tmpl*);
+ANN m_bool template_push(const Env env, const Type t);
ANN Tmpl* mk_tmpl(const Env, const Tmpl*, const Type_List);
#define POP_RET(a) { nspc_pop_type(env->gwion->mp, env->curr); return (a); }
#endif
FuncUsrEnd
FuncMemberEnd
SporkIni
+ForkIni
SporkFunc
SporkMemberFptr
SporkExp
-ForkEnd
SporkEnd
BranchEqInt
BranchNeqInt
}
}
+ANN static void interp_multi(const Emitter emit, Var_Decl_List list) {
+ m_uint offset = 0;
+ while(list->next) {
+ offset += SZ_INT;
+ list = list->next;
+ }
+ if(offset)
+ regpop(emit, offset);
+}
+
ANN static m_bool emit_interp(const Emitter emit, const Exp exp) {
regpushi(emit, 0);
Exp e = exp, next = NULL;
e->next = next;
return GW_ERROR;
}
+ const m_bool isobj = isa(e->info->type, emit->gwion->type[et_object]) > 0;
+ if(isobj && e->exp_type == ae_exp_decl) // why only objects?
+ interp_multi(emit, e->d.exp_decl.list);
regseti(emit, (m_uint)e->info->type);
- if(isa(e->info->type, emit->gwion->type[et_object]) > 0 && !GET_FLAG(e->info->type, force))
+ if(isobj && !GET_FLAG(e->info->type, force))
emit_add_instr(emit, GackType);
const Instr instr = emit_add_instr(emit, Gack);
instr->m_val = emit_code_offset(emit);
const Array_Sub array = var_decl->array;
const m_bool is_array = (array && array->exp) || GET_FLAG(decl->td, force);
const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
- const uint emit_addr = ((is_ref && !array) || isa(type, emit->gwion->type[et_object]) < 0) ?
- emit_var : 1;
+ const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1;
if(is_obj && (is_array || !is_ref))
CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
f_instr *exec = (f_instr*)allocmember;
const Array_Sub array = var_decl->array;
const m_bool is_array = array && array->exp;
const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
- const uint emit_addr = ((is_ref && !array) || isa(type, emit->gwion->type[et_object]) < 0) ?
- emit_var : 1;
+ const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1;
if(is_obj && (is_array || !is_ref))
CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
-// const Instr instr = emit_kind(emit, v->type->size, emit_addr, dotstatic);
const Instr instr = emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, dotstatic);
v->d.ptr = mp_calloc2(emit->gwion->mp, v->type->size);
SET_FLAG(v, union);
ANN static m_bool emit_class_def(const Emitter, const Class_Def);
ANN static m_bool emit_cdef(const Emitter, const Class_Def);
-ANN static inline m_bool emit_exp_decl_template(const Emitter emit, const Exp_Decl* decl) {
- const Type t = get_type(decl->type);
- return !GET_FLAG(t, emit) ? emit_cdef(emit, t->e->def) : GW_OK;
+ANN static inline m_bool ensure_emit(const Emitter emit, const Type t) {
+ struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
+ .scope=emit->env->scope->depth, .flag=ae_flag_emit };
+ return envset_run(&es, t);
}
ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) {
}
ANN /*static */m_bool emit_exp_decl(const Emitter emit, const Exp_Decl* decl) {
- if(GET_FLAG(decl->type, template))
- CHECK_BB(emit_exp_decl_template(emit, decl))
+ const Type t = get_type(decl->type);
+ if(!GET_FLAG(t, emit) && t->e->def)
+ CHECK_BB(ensure_emit(emit, t))
const m_bool global = GET_FLAG(decl->td, global);
const m_uint scope = !global ? emit->env->scope->depth : emit_push_global(emit);
const m_bool ret = emit_decl(emit, decl);
}
ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt) {
- const m_uint scope = emit_push(emit, dt->owner_class, dt->owner);
+ const m_uint scope = emit->env->scope->depth;
+ struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
+ .scope=scope, .flag=ae_flag_emit };
+ if(dt->owner_class)
+ envset_push(&es, dt->owner_class);
+ (void)emit_push(emit, dt->owner_class, dt->owner);
const m_bool ret = traverse_emit_func_def(emit, dt->def);
+ if(dt->owner_class && dt->owner_class->e->owner_class)
+ envset_pop(&es, dt->owner_class->e->owner_class);
emit_pop(emit, scope);
return ret;
}
ANN static m_bool emit_template_code(const Emitter emit, const Func f) {
const Value v = f->value_ref;
- size_t scope = emit_push(emit, v->from->owner_class, v->from->owner);
+ size_t scope = emit->env->scope->depth;
+ struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
+ .scope=scope, .flag=ae_flag_emit };
+ if(v->from->owner_class)
+ envset_push(&es, v->from->owner_class);
+ (void)emit_push(emit, v->from->owner_class, v->from->owner);
const m_bool ret = emit_func_def(emit, f->def);
+ if(v->from->owner_class && v->from->owner_class->e->owner_class)
+ envset_pop(&es, v->from->owner_class->e->owner_class);
emit_pop(emit, scope);
return ret > 0 ? push_func_code(emit, f) : GW_ERROR;
}
}
ANN void spork_code(const Emitter emit, const struct Sporker *sp) {
- if(sp->is_spork) {
- const Instr instr = emit_add_instr(emit, SporkExp);
- instr->m_val = emit->code->stack_depth;
- } else {
- const Instr instr = emit_add_instr(emit, ForkEnd);
- instr->m_val = sp->emit_var;
- }
+ const Instr args = emit_add_instr(emit, SporkExp);
+ args->m_val = emit->code->stack_depth;
+ const Instr instr = emit_add_instr(emit, SporkEnd);
+ instr->m_val = sp->emit_var;
}
ANN void spork_func(const Emitter emit, const struct Sporker *sp) {
spork->m_val = depth;
} else
emit_exp_spork_finish(emit, f->def->stack_depth);
- const Instr end = emit_add_instr(emit, sp->is_spork ? SporkEnd : ForkEnd);
- end->m_val2 = f->def->base->ret_type->size;
+ (void)emit_add_instr(emit, SporkEnd);
}
ANN static Instr spork_ini(const Emitter emit, const struct Sporker *sp) {
- const Instr instr = emit_add_instr(emit, SporkIni);
+ if(sp->is_spork) {
+ const Instr instr = emit_add_instr(emit, SporkIni);
+ instr->m_val = (m_uint)sp->vm_code;
+ instr->m_val2 = sp->is_spork;
+ return instr;
+ }
+ const Func f = !sp->code ? sp->exp->d.exp_call.m_func : NULL;
+ const Instr instr = emit_add_instr(emit, ForkIni);
instr->m_val = (m_uint)sp->vm_code;
- instr->m_val2 = sp->is_spork;
+ instr->m_val2 = f ? f->def->base->ret_type->size : 0;
return instr;
}
struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary, .op_type=op_unary };
if(unary->op != insert_symbol("spork") && unary->op != insert_symbol("fork") && unary->exp) {
CHECK_BB(emit_exp_pop_next(emit, unary->exp))
-const Exp next = unary->exp->next;
emit_exp_addref(emit, unary->exp, -exp_size(unary->exp));
-unary->exp->next = next;
opi.rhs = unary->exp->info->type;
}
return op_emit_bool(emit, &opi);
regpushi(emit, SZ_INT);
return GW_OK;
}
- const m_uint scope = !lambda->owner ?
- emit->env->scope->depth : emit_push_type(emit, lambda->owner);
+ struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
+ .scope=emit->env->scope->depth, .flag=ae_flag_emit };
+ if(lambda->owner)
+ envset_push(&es, lambda->owner);
const m_bool ret = emit_lambda(emit, lambda);
if(lambda->owner)
- emit_pop(emit, scope);
+ envset_push(&es, lambda->owner);
return ret;
}
emit_pop_scope(emit);
}
-// scope push problem
-ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
- const m_uint index = emit_code_size(emit);
+ANN static m_bool _emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt, const m_uint index) {
Instr op = NULL;
- emit_push_stack(emit);
if(!stmt->is_do)
op = _flow(emit, stmt->cond, stmt_self(stmt)->stmt_type == ae_stmt_while);
CHECK_BB(scoped_stmt(emit, stmt->body, 1))
goto_->m_val = index;
op->m_val = emit_code_size(emit);
}
- emit_pop_stack(emit, index);
return GW_OK;
}
+ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
+ const m_uint index = emit_code_size(emit);
+ emit_push_stack(emit);
+ const m_bool ret = _emit_stmt_flow(emit, stmt, index);
+ emit_pop_stack(emit, index);
+ return ret;
+}
+
ANN static Instr variadic_state0(const Emitter emit, const Stmt_VarLoop stmt) {
CHECK_BO(emit_exp(emit, stmt->exp))
return emit_add_instr(emit, BranchEqInt);
return GW_OK;
}
-// scope push problem
-ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
- emit_push_stack(emit);
+ANN static m_bool _emit_stmt_for(const Emitter emit, const Stmt_For stmt, m_uint *action_index) {
CHECK_BB(emit_stmt(emit, stmt->c1, 1))
const m_uint index = emit_code_size(emit);
const Instr op = emit_flow(emit, stmt->c2->d.stmt_exp.val);
CHECK_BB(scoped_stmt(emit, stmt->body, 1))
- const m_uint action_index = emit_code_size(emit);
+ *action_index = emit_code_size(emit);
if(stmt->c3) {
CHECK_BB(emit_exp(emit, stmt->c3))
pop_exp(emit, stmt->c3);
const Instr _goto = emit_add_instr(emit, Goto);
_goto->m_val = index;
op->m_val = emit_code_size(emit);
- emit_pop_stack(emit, action_index);
return GW_OK;
}
+ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
+ emit_push_stack(emit);
+ m_uint action_index;
+ const m_bool ret = _emit_stmt_for(emit, stmt, &action_index);
+ emit_pop_stack(emit, action_index);
+ return ret;
+}
+
ANN static Instr emit_stmt_autoptr_init(const Emitter emit, const Type type) {
const Instr new_obj = emit_add_instr(emit, ObjectInstantiate);
new_obj->m_val2 = (m_uint)type;
return emit_add_instr(emit, Reg2Mem);
}
-// scope push problem
-ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
- CHECK_BB(emit_exp(emit, stmt->exp))
+ANN static m_bool _emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt, m_uint *end_pc) {
const Instr s1 = emit_add_instr(emit, MemSetImm);
- emit_push_stack(emit);
Instr cpy = stmt->is_ptr ? emit_stmt_autoptr_init(emit, stmt->v->type) : NULL;
emit_local(emit, emit->gwion->type[et_int]); // is ptr released?
const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
const Instr loop = emit_add_instr(emit, stmt->is_ptr ? AutoLoopPtr : AutoLoop);
const Instr end = emit_add_instr(emit, BranchEqInt);
CHECK_BB(emit_stmt(emit, stmt->body, 1))
- const m_uint end_pc = emit_code_size(emit);
+ *end_pc = emit_code_size(emit);
if(stmt->is_ptr) {
loop->m_val2 = (m_uint)stmt->v->type;
cpy->m_val = stmt->v->from->offset;
tgt->m_val = ini_pc;
s1->m_val = loop->m_val = offset;
regpop(emit, SZ_INT);
- emit_pop_stack(emit, end_pc);
return GW_OK;
}
-// scope push problem
-ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
+ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
+ CHECK_BB(emit_exp(emit, stmt->exp))
emit_push_stack(emit);
+ m_uint end_pc;
+ const m_bool ret = _emit_stmt_auto(emit, stmt, &end_pc);
+ emit_pop_stack(emit, end_pc);
+ return ret;
+}
+
+ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt, m_uint *index) {
CHECK_BB(emit_exp_pop_next(emit, stmt->cond))
- const m_uint index = emit_code_size(emit);
+ *index = emit_code_size(emit);
const Instr cpy = emit_add_instr(emit, Reg2RegAddr);
cpy->m_val2 = -SZ_INT;
regpush(emit, SZ_INT);
const Instr op = emit_add_instr(emit, BranchEqInt);
CHECK_BB(scoped_stmt(emit, stmt->body, 1))
const Instr _goto = emit_add_instr(emit, Goto);
- _goto->m_val = index;
+ _goto->m_val = *index;
op->m_val = emit_code_size(emit);
- emit_pop_stack(emit, index);
regpop(emit, SZ_INT);
return GW_OK;
}
+ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
+ emit_push_stack(emit);
+ m_uint index;
+ const m_bool ret = _emit_stmt_loop(emit, stmt, &index);
+ emit_pop_stack(emit, index);
+ return ret;
+}
+
ANN static m_bool emit_stmt_jump(const Emitter emit, const Stmt_Jump stmt) {
if(!stmt->is_label)
stmt->data.instr = emit_add_instr(emit, Goto);
if(udef->xid) {
union_allocdata(emit->gwion->mp, udef);
Type_Decl *type_decl = new_type_decl(emit->gwion->mp,
- new_id_list(emit->gwion->mp, udef->xid, loc_cpy(emit->gwion->mp, udef->pos)));
+ udef->xid, loc_cpy(emit->gwion->mp, udef->pos));
type_decl->flag = udef->flag;
const Var_Decl var_decl = new_var_decl(emit->gwion->mp, udef->xid, NULL, loc_cpy(emit->gwion->mp, udef->pos));
const Var_Decl_List var_decl_list = new_var_decl_list(emit->gwion->mp, var_decl, NULL);
}
ANN static m_bool emit_stmt_cases(const Emitter emit, Stmt_List list) {
- do CHECK_BB(emit_stmt_match_case(emit, &list->stmt->d.stmt_match)) // beware push
+ do CHECK_BB(emit_stmt_match_case(emit, &list->stmt->d.stmt_match))
while((list = list->next));
return GW_OK;
}
ANN static m_bool emit_match(const Emitter emit, const struct Stmt_Match_* stmt) {
if(stmt->where)
- CHECK_BB(emit_stmt(emit, stmt->where, 1)) // beware, we have push scope
+ CHECK_BB(emit_stmt(emit, stmt->where, 1))
MATCH_INI(emit->env->scope)
vector_init(&m.vec);
const m_bool ret = emit_stmt_cases(emit, stmt->list);
return GW_OK;
}
-ANN static inline m_bool ensure_emit(const Emitter emit, const Type type) {
- const Type t = actual_type(emit->gwion, type) ?: type;
- if(!GET_FLAG(t, emit) && t->e->def)
- CHECK_BB(emit_class_def(emit, t->e->def))
- return GW_OK;
-}
-
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) {
- CHECK_BB(ensure_emit(emit, member->t_base))
struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
.rhs=exp_self(member)->info->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos, .op_type=op_dot };
return op_emit_bool(emit, &opi);
ANN static m_bool emit_class_def(const Emitter emit, const Class_Def c) {
if(tmpl_base(c->base.tmpl))
return GW_OK;
- const Class_Def cdef = c->base.type->e->def;
+ const Type t = c->base.type;
+ const Class_Def cdef = t->e->def;
if(GET_FLAG(cdef->base.type, emit))
return GW_OK;
- const Type type = cdef->base.type;
- const Nspc nspc = type->nspc;
- if(cdef->base.ext && type->e->parent->e->def && !GET_FLAG(type->e->parent, emit))
+ if(cdef->base.ext && t->e->parent->e->def && !GET_FLAG(t->e->parent, emit))
CHECK_BB(cdef_parent(emit, cdef))
- SET_FLAG(type, emit);
+ const Nspc nspc = t->nspc;
+ SET_FLAG(t, emit);
nspc_allocdata(emit->gwion->mp, nspc);
if(cdef->body) {
if(!no_ctor(emit, cdef)) {
- emit_class_code(emit, type->name);
+ emit_class_code(emit, t->name);
CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
emit_class_finish(emit, nspc);
} else
CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_struct_body2, emit))
}
- SET_FLAG(type, emit);
+ SET_FLAG(t, emit);
return GW_OK;
}
const Value v = new_value(env->gwion->mp, v_type, s_name(sym));
SET_FLAG(v, checked | ae_flag_const | ae_flag_global | ae_flag_builtin);
nspc_add_value(env->curr, insert_symbol(type->name), v);
+// valuefrom(env, v->from);
+// typefrom(env, type->e->from);
+// v->from->owner = type->e->from->owner = env->curr;
+// type->e->owner = env->curr;
v->from->owner = type->e->owner = env->curr;
- v->from->owner_class = env->class_def;
+ v->from->owner_class = type->e->owner_class = env->class_def; // t owner_class ?
type->xid = ++env->scope->type_xid;
}
return type;
}
-ANN Type find_type(const Env env, ID_List path) {
- Type type = _find_type(env, path->xid);
- CHECK_OO(type)
+ANN Type find_type(const Env env, Type_Decl *path) {
+ DECL_OO(Type, type, = _find_type(env, path->xid))
Nspc nspc = type->nspc;
path = path->next;
while(path) {
const Type t = class_type(env, base);
const Symbol sym = insert_symbol(base->name);
const Value v = new_value(env->gwion->mp, t, s_name(sym));
- // set from
- v->from->owner = base->e->owner;
+ valuefrom(env, v->from);
SET_FLAG(v, const | ae_flag_checked);
- // should we add t to front, too?
nspc_add_value_front(base->e->owner, sym, v);
return v;
}
--- /dev/null
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "template.h"
+
+ANN static void check(struct EnvSet *es, const Type t) {
+ const Vector v = &es->env->scope->class_stack;
+ Type owner = t->e->owner_class;
+ for(vtype i = vector_size(v); owner && --i;) {
+ if(owner != (Type)vector_at(v, i - 1)) {
+ es->run = 1;
+ return;
+ }
+ owner = owner->e->owner_class;
+ }
+}
+
+ANN m_bool push(struct EnvSet *es, const Type t) {
+ if(t->e->owner_class)
+ CHECK_BB(push(es, t->e->owner_class))
+ if(!(t->flag & es->flag))
+ CHECK_BB(es->func((void*)es->data, t->e->def))
+ if(GET_FLAG(t, template))
+ CHECK_BB(template_push_types(es->env, t->e->def->base.tmpl))
+ env_push_type((void*)es->env, t);
+ return GW_OK;
+}
+
+ANN m_bool envset_push(struct EnvSet *es, const Type t) {
+ check(es, t);
+ if(es->run)
+ CHECK_BB(envset_push(es, t->e->owner_class))
+ return GW_OK;
+}
+
+ANN void envset_pop(struct EnvSet *es, const Type t) {
+ env_pop(es->env, es->scope);
+ if(GET_FLAG(t, template))
+ nspc_pop_type(es->env->gwion->mp, es->env->curr);
+ if(t->e->owner_class)
+ envset_pop(es, t->e->owner_class);
+}
+
+ANN m_bool envset_run(struct EnvSet *es, const Type t) {
+ check(es, t);
+ if(es->run)
+ CHECK_BB(push(es, t->e->owner_class))
+ const m_bool ret = es->func(es->data, t->e->def);
+ if(es->run)
+ envset_pop(es, t->e->owner_class);
+ return ret;
+}
#include "parse.h"
#include "array.h"
-ANN void tuple_info(const Env env, Type_Decl *base, const Var_Decl var) {
- const Value v = var->value;
+ANN void tuple_info(const Env env, const Value v) {
const m_uint offset = vector_back(&env->class_def->e->tuple->offset);
vector_add(&env->class_def->e->tuple->types, (vtype)v->type);
vector_add(&env->class_def->e->tuple->offset, offset + v->type->size);
- Type_Decl *td = cpy_type_decl(env->gwion->mp, base);
- if(var->array)
- td->array = cpy_array_sub(env->gwion->mp, var->array);
}
ANN2(1) TupleForm new_tupleform(MemPool p, const Type parent_type) {
REM_REF(a->nspc, gwion);
if(a->e->tuple)
free_tupleform(a->e->tuple);
- if(a->e->contains.ptr) {
- for(m_uint i = 0; i < vector_size(&a->e->contains); ++i)
- REM_REF((Type)vector_at(&a->e->contains, i), gwion);
- vector_release(&a->e->contains);
- }
mp_free(gwion->mp, TypeInfo, a->e);
mp_free(gwion->mp, Type, a);
}
ANN Type type_copy(MemPool p, const Type type) {
const Type a = new_type(p, type->xid, type->name, type->e->parent);
a->nspc = type->nspc;
- a->e->owner = type->e->owner;
+ a->e->owner = type->e->owner;
+ a->e->owner_class = type->e->owner_class;
a->size = type->size;
a->e->d.base_type = type->e->d.base_type;
a->array_depth = type->array_depth;
t->e->owner = src->e->owner;
ADD_REF((t->nspc = env->gwion->type[et_array]->nspc))
SET_FLAG(t, checked);
- mk_class(env, t); // maybe add_type_front could go in mk_class ?
+ mk_class(env, t);
nspc_add_type_front(src->e->owner, sym, t);
return t;
}
t->nspc = new_nspc(env->gwion->mp, t->name);
t->nspc->parent = env->curr;
if(isa(t, env->gwion->type[et_object]) > 0)
- inherit(t);
+ inherit(t);
t->e->owner = env->curr;
+ t->e->owner_class = env->class_def;
SET_FLAG(t, checked);
env_push_type(env, t);
}
DECL_OO(Type_Decl *,td, = str2decl(gwi, parent ?: "Object"))
Tmpl* tmpl = ck.tmpl ? new_tmpl_base(gwi->gwion->mp, ck.tmpl) : NULL;
if(tmpl)
- template_push_types(gwi->gwion->env, tmpl);
+ CHECK_BO(template_push_types(gwi->gwion->env, tmpl))
const Type p = known_type(gwi->gwion->env, td); // check
+ if(!p) {
+ env_pop(gwi->gwion->env, 0);
+ return NULL;
+ }
if(tmpl)
nspc_pop_type(gwi->gwion->mp, gwi->gwion->env->curr);
const Type t = new_type(gwi->gwion->mp, ++gwi->gwion->env->scope->type_xid, s_name(ck.sym), p);
#include "import.h"
#include "gwi.h"
-ANN m_bool array_check(const Gwi gwi, struct array_checker *ck);
-
__attribute__((returns_nonnull))
ANN static Symbol gwisym(const Gwi gwi, const m_str str) {
return insert_symbol(gwi->gwion->st, str);
}
-//! check that there is no illegal character in the string
-// TODO: get rid of second argument, make it useless
-ANN static m_bool check_illegal(const char c, const m_uint i) {
- return isalnum(c) || c == '_' || (!i && c == '@');
+struct td_checker {
+ m_str str;
+};
+
+struct AC {
+ m_str str;
+ Exp base;
+ Exp exp;
+ m_uint depth;
+};
+
+ANN static m_bool ac_run(const Gwi gwi, struct AC *ac);
+ANN static Array_Sub mk_array(MemPool mp, struct AC *ac) {
+ const Array_Sub array = new_array_sub(mp, ac->base);
+ array->depth = ac->depth;
+ return array;
}
-/** convert a string to a symbol, with error checking **/
-ANN Symbol str2sym(const Gwi gwi, const m_str path) {
- const size_t sz = strlen(path);
- m_uint i;
- char curr[sz + 1];
- for(i = 0; i < sz; ++i) {
- const char c = path[i];
- if(c != '.') {
- if(!check_illegal(c, i))
- GWI_ERR_O(_("illegal character '%c' in path '%s'."), c, path)
- curr[i] = c;
- } else
+
+ANN static Symbol __str2sym(const Gwi gwi, struct td_checker *tdc) {
+ char buf[strlen(tdc->str) + 1];
+ m_str tmp = buf;
+ if(*tdc->str == '@')
+ *tmp++ = *tdc->str++;
+ while(*tdc->str) {
+ const char c = *tdc->str;
+ if(!isalnum(c) && c != '_')
break;
+ *tmp++ = *tdc->str++;
}
- curr[i++] = '\0';
- return gwisym(gwi, curr);
+ if(tmp == buf)
+ GWI_ERR_O("empty symbol");
+ *tmp = '\0';
+ return gwisym(gwi, buf);
}
-ANN ID_List str2symlist(const Gwi gwi, const m_str path) {
- DECL_OO(const Symbol, sym, = str2sym(gwi, path))
- return new_id_list(gwi->gwion->mp, sym, loc(gwi));
+ANN static inline Symbol _str2sym(const Gwi gwi, struct td_checker *tdc, const m_str path) {
+ const Symbol sym = __str2sym(gwi, tdc);
+ if(*tdc->str)
+ GWI_ERR_O(_("illegal character '%c' in path '%s'."), *tdc->str, path)
+ return sym;
}
-ANN ID_List path_valid(const Gwi gwi, const m_str path) {
- const size_t sz = strlen(path);
- if(path[0] == '.' || path[sz] == '.')
- GWI_ERR_O(_("path '%s' must not ini or end with '.'."), path)
- DECL_OO(const ID_List, list, = str2symlist(gwi, path))
- if(strlen(s_name(list->xid)) < sz)
- list->next = path_valid(gwi, path + strlen(s_name(list->xid)));
- return list;
+/** convert a string to a symbol, with error checking **/
+ANN Symbol str2sym(const Gwi gwi, const m_str path) {
+ struct td_checker tdc = { .str=path };
+ return _str2sym(gwi, &tdc, path);
}
-// similar to import array_sub ?
-ANN Array_Sub ck_array(MemPool mp, const m_uint depth) {
- if(!depth)
- return NULL;
- const Array_Sub array = new_array_sub(mp, NULL);
- array->depth = depth;
- return array;
+// only in enum.c
+ANN ID_List str2symlist(const Gwi gwi, const m_str path) {
+ DECL_OO(const Symbol, sym, = str2sym(gwi, path))
+ return new_id_list(gwi->gwion->mp, sym, loc(gwi));
}
ANN Var_Decl str2var(const Gwi gwi, const m_str path) {
- struct array_checker ck = { .str=path };
- CHECK_BO(array_check(gwi, &ck))
- const m_uint sz = strlen(path);
- const m_uint len = sz - ck.sz;
- char curr[len + 1];
- memcpy(curr, path, len);
- curr[len] = '\0';
- DECL_OO(const Symbol, sym, = str2sym(gwi, curr))
- const Array_Sub array = ck_array(gwi->gwion->mp, ck.depth);
+ struct td_checker tdc = { .str=path };
+ DECL_OO(const Symbol, sym, = __str2sym(gwi, &tdc))
+ struct AC ac = { .str = tdc.str };
+ CHECK_BO(ac_run(gwi, &ac))
+ const Array_Sub array = ac.depth ?
+ mk_array(gwi->gwion->mp, &ac) : NULL;
return new_var_decl(gwi->gwion->mp, sym, array, loc(gwi));
}
+// only in udef.c
ANN Var_Decl_List str2varlist(const Gwi gwi, const m_str path) {
DECL_OO(const Var_Decl, var, = str2var(gwi, path))
return new_var_decl_list(gwi->gwion->mp, var, NULL);
}
-struct tmpl_checker {
- const m_str str;
- ID_List list;
-};
-
-ANN static m_bool tmpl_list(const Gwi gwi, struct tmpl_checker *ck) {
- m_str s = ck->str;
- const size_t sz = strlen(s);
- char c[sz + 1];
- for(m_uint i = 0; i < sz; ++i) {
- if(isalnum(s[i]) || s[i] == '_') {
- c[i] = s[i];
- continue;
- }
- if(s[i] == '~') {
- if(!i || s[i+1] != '>')
- break;
- c[i] = '\0';
- ck->list = new_id_list(gwi->gwion->mp, gwisym(gwi, c), loc(gwi));
- return GW_OK;
- }
- if(s[i] == ',') {
- if(!i)break;
- c[i] = '\0';
- ck->list = new_id_list(gwi->gwion->mp, gwisym(gwi, c), loc(gwi));
- struct tmpl_checker _ck = { .str=ck->str + i + 1 };
- CHECK_BB(tmpl_list(gwi, &_ck))
- ck->list->next = _ck.list;
- return GW_OK;
- }
- break;
+ANN static ID_List _tmpl_list(const Gwi gwi, struct td_checker *tdc) {
+ DECL_OO(const Symbol, sym, = __str2sym(gwi, tdc))
+ ID_List next = NULL;
+ if(*tdc->str == ',') {
+ ++tdc->str;
+ if(!(next = _tmpl_list(gwi, tdc)) || next == (ID_List)GW_ERROR)
+ return (ID_List)GW_ERROR;
}
- return GW_ERROR;
-}
-
-ANN static m_bool tmpl_check(const m_str str) {
- if(str[0] != '<')
- return 0; // TODO: make it GW_PASS
- if(str[1] != '~')
- return GW_ERROR;
- return GW_OK;
+ const ID_List list = new_id_list(gwi->gwion->mp, sym, loc(gwi));
+ list->next = next;
+ return list;
}
-ANN static ID_List _tmpl_valid(const Gwi gwi, const m_str str) {
- const m_bool ret = tmpl_check(str);
- if(ret == GW_ERROR)
- return (ID_List)GW_ERROR;
- if(!ret)
+ANN static ID_List __tmpl_list(const Gwi gwi, struct td_checker *tdc) {
+ if(tdc->str[0] != '<')
return NULL;
- struct tmpl_checker ck = { .str=str+2 };
- if(tmpl_list(gwi, &ck) == GW_ERROR)
+ if(tdc->str[1] != '~')
+ return (ID_List)GW_ERROR;
+ tdc->str += 2;
+ const ID_List list = _tmpl_list(gwi, tdc);
+ if(list == (ID_List)GW_ERROR)
+ return (ID_List)GW_ERROR;
+ if(tdc->str[0] != '~' || tdc->str[1] != '>') {
+// unfinished template
+ if(list)
+ free_id_list(gwi->gwion->mp, list);
return (ID_List)GW_ERROR;
- return ck.list;
-}
-
-ANN ID_List tmpl_valid(const Gwi gwi, const m_str str) {
- const ID_List ret = _tmpl_valid(gwi, str);
- if(ret == (ID_List)GW_ERROR)
- env_err(gwi->gwion->env, gwi->loc, _("invalid templating definition"));
- return ret;
-}
-
-ANN ID_List ck2list(const Gwi gwi, struct array_checker *ck) {
- const m_str base = ck->str;
- CHECK_BO(array_check(gwi, ck))
- const m_uint sz = strlen(base);
- const m_uint len = sz - ck->sz;
- char curr[len + 1];
- memcpy(curr, base, len);
- curr[len] = '\0';
- return path_valid(gwi, curr);
-}
-
-ANN static Type_List str2tl(const Gwi gwi, const m_str s);
-ANN static Type_List _str2tl(const Gwi gwi, const m_str s) {
- DECL_OO(Type_Decl*, td, = str2decl(gwi, s))
- return new_type_list(gwi->gwion->mp, td, NULL);
-}
-
-ANN Type_List tlnext(const Gwi gwi, const m_str s, size_t split) {
- char curr[split+1];
- memcpy(curr, s, split);
- curr[split] = '\0';
- const Type_List tl = _str2tl(gwi, curr);
- tl->next = str2tl(gwi, s + split + 1);
- return tl;
-}
-
-struct GetTl {
- const m_str str;
- m_uint i;
- m_uint lvl;
- const size_t sz;
-};
-
-//! a funtion factory to open/close the template
-#define tl_xxx(name, tgt, op) \
-ANN m_bool tl_##name(struct GetTl *gtl, const m_uint i) { \
- if(!(i < gtl->sz && gtl->str[i] == tgt)) \
- return GW_ERROR; \
- op gtl->lvl; \
- return GW_OK; \
-}
-tl_xxx(open, '~', ++)
-tl_xxx(close, '>', --)
-
-ANN static Type_List str2tl(const Gwi gwi, const m_str s) {
- struct GetTl gtl = { .str=s, .sz = strlen(s) };
- for(m_uint i = 0; i < gtl.sz; ++i) {
- if(s[i] == '<')
- CHECK_BO(tl_open(>l, ++i))
- else if(s[i] == '~')
- CHECK_BO(tl_close(>l, ++i))
- else if(s[i] == ',' && !gtl.lvl)
- return tlnext(gwi, s, i);
- }
- return _str2tl(gwi, s);
-}
-
-//! convert a string to a Type_Decl
-ANN Type_Decl* str2decl(const Gwi gwi, const m_str str) {
- const ae_flag flag = strncmp(str, "nonnull ", 8) ? ae_flag_none : ae_flag_nonnull;
- const m_str s = strncmp(str, "nonnull ", 8) ? str : str + 8;
-// we can do better
- DECL_OO(const m_str, type_name, = get_type_name(gwi->gwion->env, s, 0))
- struct array_checker ck = { .str=type_name };
- DECL_OO(const ID_List, id, = ck2list(gwi, &ck))
- Type_Decl* td = new_type_decl(gwi->gwion->mp, id);
- const m_str tl_name = get_type_name(gwi->gwion->env, s, 1);
- if(tl_name) {
- if(!(td->types = str2tl(gwi, tl_name))) {
- free_type_decl(gwi->gwion->mp, td);
- return NULL;
- }
- }
- if(ck.depth) {
- td->array = new_array_sub(gwi->gwion->mp, ck.exp);
- td->array->depth = ck.depth;
- }
- td->flag |= flag;
- return td;
-}
-
-ANN static void array_add_exp(struct array_checker *ck, const Exp exp) {
- if(ck->exp)
- ck->exp = (ck->exp->next = exp);
- else
- ck->base = ck->exp = exp;
- ++ck->is_exp;
-}
-
-ANN m_bool _array_check(const Gwi gwi, struct array_checker *ck) {
- const m_str base = ck->str;
- const size_t sz = strlen(ck->str);
- char tmp[sz + 1];
- for(m_uint i = 0; i < sz; ++i) {
- const char c = ck->str[i];
- if(c == ']') {
- const m_bool is_end = ck->str[i + 1] == '\0';
- if(!is_end && ck->str[i + 1] != '[')
- break;
- ck->str += i + 2;
- ck->sz += i + 2;
- if(i) {
- if(!ck->is_exp && ck->depth)
- break;
- tmp[i] = '\0';
- const m_uint num = strtol(tmp, NULL, 10);// migth use &endptr and check errno
- const Exp exp = new_prim_int(gwi->gwion->mp, num, loc(gwi));
- array_add_exp(ck, exp);
- } else {
- if(ck->is_exp > 0)
- break;
- }
- ++ck->depth;
- return is_end ? GW_OK : _array_check(gwi, ck);
- }
- if(isdigit(c))
- tmp[i] = c;
- else
- GWI_ERR_B(_("invalid subscript '%c' in '%s'"), c, base)
}
- GWI_ERR_B(_("incoherent subscript '%s'"), base)
-}
-
-ANN m_bool array_check(const Gwi gwi, struct array_checker *ck) {
- ck->str = ck->str ? strchr(ck->str, '[') : NULL;
- if(!ck->str)
- return GW_OK;
- ++ck->str;
- return _array_check(gwi, ck);
+ tdc->str += 2;
+ return list;
}
ANN m_bool check_typename_def(const Gwi gwi, ImportCK *ck) {
- const m_str base = ck->name;
- char str[strlen(base) + 1];
- const m_str c = strchr(ck->name, '<');
- memcpy(str, base, strlen(base) - (c ? strlen(c) : 0));
- str[strlen(base) - (c ? strlen(c) : 0)] = '\0';
- ck->name = str;
- CHECK_OB((ck->sym = str2sym(gwi, str)))
- ID_List tmpl = NULL;
- if(c && (tmpl = tmpl_valid(gwi, c)) == (ID_List)GW_ERROR)
+ struct td_checker tdc = { .str= ck->name };
+ ID_List il = __tmpl_list(gwi, &tdc);
+ if(il == (ID_List)GW_ERROR)
+ return GW_ERROR;
+ if(!(ck->sym = _str2sym(gwi, &tdc, tdc.str))) {
+ if(il)
+ free_id_list(gwi->gwion->mp, il);
return GW_ERROR;
- ck->tmpl = tmpl;
- ck->name = base;
+ }
+ ck->tmpl = il;
+ ck->name = s_name(ck->sym);
return GW_OK;
+
}
ANN m_bool ck_ini(const Gwi gwi, const enum importck_type t) {
memset(gwi->ck, 0, sizeof(ImportCK));
}
+ANN Type_Decl* _str2decl(const Gwi gwi, struct td_checker *tdc);
+ANN Type_List __str2tl(const Gwi gwi, struct td_checker *tdc) {
+ Type_Decl *td = _str2decl(gwi, tdc);
+ if(!td)
+ GWI_ERR_O("invalid types");
+ Type_List next = NULL;
+ if(*tdc->str == ',') {
+ ++tdc->str;
+ if(!(next = __str2tl(gwi, tdc))) {
+ free_type_decl(gwi->gwion->mp, td);
+ return NULL;
+ }
+ }
+ return new_type_list(gwi->gwion->mp, td, next);
+}
+
+ANN Type_List td_tmpl(const Gwi gwi, struct td_checker *tdc) {
+ if(*tdc->str != '<')
+ return NULL; // GW_PASS
+ ++tdc->str;
+ if(*tdc->str != '~') {
+ GWI_ERR("invalid character");
+ return (Type_List)GW_ERROR;
+ }
+ ++tdc->str;
+ Type_List tl = __str2tl(gwi, tdc);
+ if(!tl)
+ return (Type_List)GW_ERROR;
+ if(tdc->str[0] != '~' || tdc->str[1] != '>') {
+ free_type_list(gwi->gwion->mp, tl);
+ GWI_ERR("unfinished template");
+ return (Type_List)GW_ERROR;
+ }
+ tdc->str += 2;
+ return tl;
+}
+
+ANN static void ac_add_exp(struct AC *ac, const Exp exp) {
+ if(ac->exp)
+ ac->exp = (ac->exp->next = exp);
+ else
+ ac->base = ac->exp = exp;
+}
+
+
+ANN Type_Decl* _str2decl(const Gwi gwi, struct td_checker *tdc) {
+ Type_List tl = td_tmpl(gwi, tdc);
+ if(tl == (Type_List)GW_ERROR)
+ return NULL;
+ Type_Decl *next = NULL;
+ const Symbol sym = __str2sym(gwi, tdc);
+ if(!sym) {
+ if(tl)
+ free_type_list(gwi->gwion->mp, tl);
+ return NULL;
+ }
+ struct AC ac = { .str = tdc->str };
+ if(ac_run(gwi, &ac) < 0) {
+ if(tl)free_type_list(gwi->gwion->mp, tl);
+ return NULL;
+ }
+ tdc->str = ac.str;
+ if(*tdc->str == '.') {
+ ++tdc->str;
+ if(!(next = _str2decl(gwi, tdc))) {
+ if(tl)
+ free_type_list(gwi->gwion->mp, tl);
+ if(ac.base)
+ free_exp(gwi->gwion->mp, ac.base);
+ return NULL;
+ }
+ }
+ Type_Decl *td = new_type_decl(gwi->gwion->mp, sym, loc(gwi));
+ td->next = next;
+ if(ac.depth)
+ td->array = mk_array(gwi->gwion->mp, &ac);
+ return td;
+}
+
+ANN Type_Decl* str2decl(const Gwi gwi, const m_str str) {
+ const ae_flag flag = strncmp(str, "nonnull ", 8) ? ae_flag_none : ae_flag_nonnull;
+ struct td_checker tdc = { .str=str };
+ if(flag == ae_flag_nonnull)
+ tdc.str += 8;
+ DECL_OO(Type_Decl *, td, = _str2decl(gwi, &tdc))
+ if(*tdc.str) {
+ free_type_decl(gwi->gwion->mp, td);
+ GWI_ERR_O("excedental character '%c'", *tdc.str);
+ }
+ td->flag |= flag;
+ return td;
+}
+
+ANN static inline m_bool ac_finish(const Gwi gwi, struct AC *ac) {
+ if(*ac->str == ']')
+ return GW_OK;
+ GWI_ERR_B("unfinished array");
+}
+
+ANN static inline m_bool ac_num(const Gwi gwi, const m_int num) {
+ if(num >= 0)
+ return GW_OK;
+ GWI_ERR_B("negative array dimension")
+}
+
+ANN static inline m_bool ac_exp(const Gwi gwi, struct AC *ac) {
+ if(!ac->depth || ac->base)
+ return GW_OK;
+ GWI_ERR_B("malformed array [][...]")
+}
+
+ANN static inline m_bool ac_noexp(const Gwi gwi, struct AC *ac) {
+ if(!ac->exp)
+ return GW_OK;
+ GWI_ERR_B("malformed array [...][]")
+}
+
+ANN static m_bool _ac_run(const Gwi gwi, struct AC *ac) {
+ const m_str str = ac->str;
+ const m_int num = strtol(str, &ac->str, 10);
+ CHECK_BB(ac_finish(gwi, ac))
+ if(str != ac->str) {
+ CHECK_BB(ac_num(gwi, num))
+ CHECK_BB(ac_exp(gwi, ac))
+ const Exp exp = new_prim_int(gwi->gwion->mp, num, loc(gwi));
+ ac_add_exp(ac, exp);
+ } else
+ CHECK_BB(ac_noexp(gwi, ac))
+ ++ac->str;
+ return GW_OK;
+}
+
+ANN static m_bool ac_run(const Gwi gwi, struct AC *ac) {
+ while(*ac->str) {
+ if(*ac->str != '[')
+ break;
+ ++ac->str;
+ CHECK_BB(_ac_run(gwi, ac))
+ ++ac->depth;
+ }
+ return GW_OK;
+}
mp_free(p, M_Vector, a);
}
+ANN static inline int is_array(const Type *types, const Type type) {
+ const Type base = array_base(type);
+ return isa(base, types[et_object]) > 0;
+}
+
static DTOR(array_dtor) {
const Type t = !GET_FLAG(o->type_ref, nonnull) ?
o->type_ref : o->type_ref->e->parent;
- const Type base = array_base(t);
struct M_Vector_* a = ARRAY(o);
- if(t->array_depth > 1 || isa(base, shred->info->vm->gwion->type[et_object]) > 0)
+ if(t->array_depth > 1 || is_array(shred->info->vm->gwion->type, t))
for(m_uint i = 0; i < ARRAY_LEN(a); ++i)
release(*(M_Object*)(ARRAY_PTR(a) + i * SZ_INT), shred);
free_m_vector(shred->info->mp, a);
ANN m_bool type_engine_init(const Gwion gwion, const Vector plug_dirs) {
gwion->env->name = "[builtin]";
- struct loc_t loc = {};
+ struct loc_t_ loc = {};
OperCK oper = {};
struct Gwi_ gwi = { .gwion=gwion, .loc=&loc, .oper=&oper };
CHECK_BB(import_core_libs(&gwi))
fptr_instr(emit, bin->lhs->info->type->e->d.func, 2);
const Instr instr = emit_add_instr(emit, int_r_assign);
if(!is_fptr(emit->gwion, bin->lhs->info->type) && GET_FLAG(bin->rhs->info->type->e->d.func, member)) {
-//exit(3);
const Instr pop = emit_add_instr(emit, LambdaAssign);
pop->m_val = SZ_INT;
}
}
-static m_bool td_match(const Env env, const Type_Decl *id[2]) {
+static m_bool td_match(const Env env, Type_Decl *id[2]) {
DECL_OB(const Type, t0, = known_type(env, id[0]))
DECL_OB(const Type, t1, = known_type(env, id[1]))
return isa(t0, t1);
Arg_List arg0 = base[0]->args, arg1 = base[1]->args;
while(arg0) {
CHECK_OB(arg1)
- const Type_Decl* td[2] = { arg0->td, arg1->td };
+ Type_Decl* td[2] = { arg0->td, arg1->td };
CHECK_BB(td_match(env, td))
arg0 = arg0->next;
arg1 = arg1->next;
}
ANN static inline m_bool fptr_rettype(const Env env, struct FptrInfo *info) {
- const Type_Decl* td[2] = { info->lhs->def->base->td,
+ Type_Decl* td[2] = { info->lhs->def->base->td,
info->rhs->def->base->td };
return td_match(env, td);
}
}
return GW_OK;
}
+
ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner,
Exp_Lambda *l, const Func_Def def) {
- const m_uint scope = ((l->owner = owner)) ?
- env_push_type(env, owner) : env->scope->depth;
+ struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+ .scope=env->scope->depth, .flag=ae_flag_check };
+ if((l->owner = owner))
+ envset_push(&es, owner);
const m_bool ret = _check_lambda(env, l, def);
- if(owner)
- env_pop(env, scope);
+ if(owner && es.run)
+ envset_pop(&es, owner);
if(ret < 0)
return GW_ERROR;
exp_self(l)->info->type = l->def->base->func->value_ref->type;
const Exp_Cast* cast = (Exp_Cast*)data;
if(exp_self(cast)->info->type->e->d.func->def->base->tmpl)
fptr_instr(emit, cast->exp->info->type->e->d.func, 1);
-// if(GET_FLAG(cast->exp->info->type->e->d.func, member) &&
-// !(GET_FLAG(cast->exp->info->type, nonnull) || GET_FLAG(exp_self(cast)->info->type, nonnull)))
if(is_member(cast->exp->info->type, exp_self(cast)->info->type))
member_fptr(emit);
return (Instr)GW_OK;
static OP_EMIT(opem_fptr_impl) {
struct Implicit *impl = (struct Implicit*)data;
if(is_member(impl->e->info->type, impl->t))
-// if(GET_FLAG(impl->e->info->type->e->d.func, member) &&
-// !(GET_FLAG(impl->e->info->type, nonnull) || GET_FLAG(impl->t, nonnull)))
member_fptr(emit);
if(impl->t->e->d.func->def->base->tmpl)
fptr_instr(emit, ((Exp)impl->e)->info->type->e->d.func, 1);
static OP_EMIT(opem_spork) {
const Exp_Unary* unary = (Exp_Unary*)data;
- return emit_exp_spork(emit, unary);
+ const Env env = emit->env;
+ const Instr ret = emit_exp_spork(emit, unary);
+ if(unary->op == insert_symbol("fork"))
+ emit_add_instr(emit, GcAdd);
+ return ret;
}
static FREEARG(freearg_xork) {
SET_FLAG(def, template);
return def;
}
-
ANN static Func_Def traverse_tmpl(const Emitter emit, struct dottmpl_ *const dt, const Nspc nspc) {
DECL_OO(const Func_Def, def, = from_base(emit->env, dt, nspc))
CHECK_BO(traverse_dot_tmpl(emit, dt))
if(env->func && !GET_FLAG(env->func, member))
ERR_O(exp_self(prim)->pos, _("keyword 'this' cannot be used inside static functions..."))
if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack") &&
-GET_FLAG(env->class_def, struct))
- ERR_O(exp_self(prim)->pos, _("can't use 'this' in struct @gack"))
+ GET_FLAG(env->class_def, struct))
+ ERR_O(exp_self(prim)->pos, _("can't use 'this' in struct @gack"))
return env->class_def;
}
push->m_val = v->type->size - v->from->owner_class->size;
if(v->from->offset)
emit_struct_var(emit, v);
-// const Instr push = emit_add_instr(emit, RegPush);
-// push->m_val = v->type->size - SZ_INT;
}
ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
(isa(exp_self(member)->info->type, emit->gwion->type[et_function]) > 0 &&
!is_fptr(emit->gwion, exp_self(member)->info->type)))) {
- if(!GET_FLAG(t_base, struct))
- CHECK_BO(emit_exp(emit, member->base))
+ if(!GET_FLAG(t_base, struct))
+ CHECK_BO(emit_exp(emit, member->base))
if(isa(member->t_base, emit->env->gwion->type[et_object]) > 0)
emit_except(emit, member->t_base);
}
}
-extern ANN m_bool scan0_class_def(const Env, const Class_Def);
-extern ANN m_bool scan1_class_def(const Env, const Class_Def);
-extern ANN m_bool traverse_func_def(const Env, const Func_Def);
-extern ANN m_bool traverse_class_def(const Env, const Class_Def);
-
ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) {
- a->union_def = new_union_def(env->gwion->mp, a->list,
+puts("\033[35mhere\033[0m");
+ a->union_def = new_union_def(env->gwion->mp, cpy_decl_list(env->gwion->mp, a->list),
loc_cpy(env->gwion->mp, t->e->def->pos));
a->union_def->type_xid = a->base.xid;
if(GET_FLAG(t, global))
ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) {
if(template_match(t->e->def->base.tmpl->list, td->types) < 0)
- ERR_O(td->xid->pos, _("invalid template types number"))
+ ERR_O(td->pos, _("invalid template types number"))
DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
if(a->base.type)
return a->base.type;
static OP_CHECK(opck_ptr_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
+ if(!cast->td->types->td)
+ ERR_N(exp_self(cast)->pos, "'Ptr' needs types to cast")
DECL_ON(const Type, t, = type_decl_resolve(env, cast->td))
if(!GET_FLAG(t, check))
CHECK_BN(traverse_class_def(env, t->e->def))
static OP_CHECK(opck_ptr_implicit) {
const struct Implicit* imp = (struct Implicit*)data;
const Exp e = imp->e;
+ DECL_OO(const m_str, name, = get_type_name(env, imp->t->name, 1))
if(!strcmp(get_type_name(env, imp->t->name, 1), e->info->type->name)) {
const m_str access = exp_access(e);
if(access)
}
GWION_IMPORT(ptr) {
- const Type t_ptr = gwi_class_ini(gwi, "Ptr<~A~>", NULL);
+ const Type t_ptr = gwi_class_ini(gwi, "<~A~>Ptr", NULL);
gwi->gwion->type[et_ptr] = t_ptr;
GWI_BB(gwi_item_ini(gwi, "@internal", "@val"))
GWI_BB(gwi_item_end(gwi, 0, NULL))
#include "specialid.h"
#include "gwi.h"
-static m_int o_fork_thread, o_shred_cancel, o_fork_done, o_fork_ev, o_fork_retsize;
+static m_int o_fork_thread, o_fork_cond, o_fork_mutex, o_shred_cancel, o_fork_done, o_fork_ev, o_fork_retsize;
#define FORK_THREAD(o) *(THREAD_TYPE*)(o->data + o_fork_thread)
+#define FORK_COND(o) *(THREAD_COND_TYPE*)(o->data + o_fork_cond)
+#define FORK_MUTEX(o) *(MUTEX_TYPE*)(o->data + o_fork_mutex)
#define FORK_RETSIZE(o) *(m_int*)(o->data + o_fork_retsize)
VM_Shred new_shred_base(const VM_Shred shred, const VM_Code code) {
describe_path_and_dir(_code, s->code->name)
static DTOR(shred_dtor) {
- if(ME(o))
+ if(ME(o)) {
+ MUTEX_TYPE mutex = ME(o)->tick->shreduler->mutex;
+ MUTEX_LOCK(mutex);
free_vm_shred(ME(o));
+ MUTEX_UNLOCK(mutex);
+ }
}
static MFUN(shred_lock) {
static void stop(const M_Object o) {
VM *vm = ME(o)->info->vm;
MUTEX_LOCK(vm->shreduler->mutex);
- MUTEX_LOCK(vm->parent->shreduler->mutex);
vm->shreduler->bbq->is_running = 0;
- MUTEX_UNLOCK(vm->parent->shreduler->mutex);
+ *(m_int*)(o->data + o_shred_cancel) = 1;
MUTEX_UNLOCK(vm->shreduler->mutex);
}
static void join(const M_Object o) {
- VM *vm = ME(o)->info->vm->parent;
- MUTEX_LOCK(vm->shreduler->mutex);
- THREAD_JOIN(FORK_THREAD(o));
- MUTEX_UNLOCK(vm->shreduler->mutex);
+ VM *vm = ME(o)->info->vm;
+ if(FORK_THREAD(o)) {
+ THREAD_JOIN(FORK_THREAD(o));
+ FORK_THREAD(o) = 0;
+ }
}
static DTOR(fork_dtor) {
+ *(m_int*)(o->data + o_fork_done) = 1;
stop(o);
- VM *vm = ME(o)->info->vm->parent;
- const m_int idx = vector_find(&vm->gwion->data->child, (vtype)o);
- VPTR(&vm->gwion->data->child, idx) = 0;
- if(!vm->gwion->data->child2.ptr)
- vector_init(&vm->gwion->data->child2);
- vector_add(&vm->gwion->data->child2, (vtype)ME(o)->info->vm->gwion);
- gwion_end_child(shred, ME(o)->info->vm->gwion);
- join(o);
+ VM *parent = ME(o)->info->vm->parent;
+ MUTEX_LOCK(parent->shreduler->mutex);
+ if(parent->gwion->data->child.ptr) {
+ const m_int idx = vector_find(&parent->gwion->data->child, (vtype)o);
+ if(idx > -1)
+ VPTR(&parent->gwion->data->child, idx) = 0;
+ }
+ if(!parent->gwion->data->child2.ptr)
+ vector_init(&parent->gwion->data->child2);
+ vector_add(&parent->gwion->data->child2, (vtype)ME(o)->info->vm->gwion);
+ REM_REF(ME(o)->code, ME(o)->info->vm->gwion);
+ MUTEX_UNLOCK(parent->shreduler->mutex);
}
static MFUN(fork_join) {
- MUTEX_LOCK(ME(o)->tick->shreduler->mutex);
- MUTEX_LOCK(shred->tick->shreduler->mutex);
- release(o, shred);
- if(*(m_int*)(o->data + o_fork_done)) {
- MUTEX_UNLOCK(shred->tick->shreduler->mutex);
- MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+ if(*(m_int*)(o->data + o_fork_done))
return;
- }
- MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
- MUTEX_UNLOCK(shred->tick->shreduler->mutex);
shreduler_remove(shred->tick->shreduler, shred, 0);
vector_add(EV_SHREDS(*(M_Object*)(o->data + o_fork_ev)), (vtype)shred);
}
}
static MFUN(shred_test_cancel) {
- MUTEX_LOCK(ME(o)->tick->shreduler->mutex);
+ if(*(m_int*)(o->data + o_shred_cancel))
+ vm_shred_exit(ME(o));
+}
+
+static MFUN(fork_test_cancel) {
if(*(m_int*)(o->data + o_shred_cancel)) {
- const m_bool is_me = ME(o) == shred;
- if(is_me)
- MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+ stop(o);
+ join(o);
+ _release(o, ME(o));
vm_shred_exit(ME(o));
- if(is_me)
- return;
}
- MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+}
+
+struct ThreadLauncher {
+ MUTEX_TYPE mutex;
+ THREAD_COND_TYPE cond;
+ VM *vm;
+};
+
+static inline int fork_running(VM *vm, const M_Object o) {
+ MUTEX_LOCK(vm->shreduler->mutex);
+ const int ret = vm->bbq->is_running && !*(m_int*)(o->data + o_shred_cancel);
+ MUTEX_UNLOCK(vm->shreduler->mutex);
+ return ret;
}
static ANN THREAD_FUNC(fork_run) {
- VM *vm = (VM*)data;
- vm_lock(vm->parent);
- const M_Object me = vm->bbq->is_running ?
- vm->shreduler->list->self->info->me : NULL;
- vm_unlock(vm->parent);
- if(!me)
- THREAD_RETURN(0);
- while(vm->bbq->is_running) {
+struct ThreadLauncher *tl = data;
+ VM *vm = tl->vm;
+ MUTEX_TYPE mutex = tl->mutex;
+ const M_Object me = vm->shreduler->list->self->info->me;
+ ++me->ref;
+ MUTEX_LOCK(mutex);
+ THREAD_COND_SIGNAL(FORK_COND(me));
+ MUTEX_UNLOCK(mutex);
+ while(fork_running(vm, me)) {
vm_run(vm);
++vm->bbq->pos;
}
- vm_lock(vm->parent);
- if(vm_running(vm->parent)) {
- *(m_int*)(me->data + o_fork_done) = 1;
+ gwion_end_child(ME(me), vm->gwion);
+ MUTEX_LOCK(vm->parent->shreduler->mutex);
+ if(!*(m_int*)(me->data + o_shred_cancel))
broadcast(*(M_Object*)(me->data + o_fork_ev));
- } else if(me->ref > 1)
- release(me, ME(me));
- vm_unlock(vm->parent);
+ MUTEX_UNLOCK(vm->parent->shreduler->mutex);
+ *(m_int*)(me->data + o_fork_done) = 1;
+// if(!*(m_int*)(me->data + o_shred_cancel))
+// _release(me, ME(me));
THREAD_RETURN(0);
}
ANN void fork_launch(VM const* vm, const M_Object o, const m_uint sz) {
- if(vm_running(vm)) {
- FORK_RETSIZE(o) = sz;
- THREAD_CREATE(FORK_THREAD(o), fork_run, ME(o)->info->vm);
- } else release(o, ME(o));
+ FORK_RETSIZE(o) = sz;
+ MUTEX_SETUP(FORK_MUTEX(o));
+ THREAD_COND_SETUP(FORK_COND(o));
+ struct ThreadLauncher tl = { .mutex=FORK_MUTEX(o), .cond=FORK_COND(o), .vm=ME(o)->info->vm };
+ MUTEX_LOCK(tl.mutex);
+ THREAD_CREATE(FORK_THREAD(o), fork_run, &tl);
+ THREAD_COND_WAIT(FORK_COND(o), tl.mutex);
+ MUTEX_UNLOCK(tl.mutex);
+ THREAD_COND_CLEANUP(FORK_COND(o));
+ MUTEX_CLEANUP(FORK_MUTEX(o));
}
ANN void fork_clean(const VM_Shred shred, const Vector v) {
if(!o)
continue;
stop(o);
- THREAD_JOIN(FORK_THREAD(o));
- _release(o, shred);
}
+ for(m_uint i = 0; i < vector_size(v); ++i) {
+ const M_Object o = (M_Object)vector_at(v, i);
+ if(!o)
+ continue;
+ join(o);
+ }
+ for(m_uint i = 0; i < vector_size(v); ++i) {
+ const M_Object o = (M_Object)vector_at(v, i);
+ if(!o)
+ continue;
+ _release(o, shred);
+ }
vector_release(v);
v->ptr = NULL;
}
gwi_item_ini(gwi, "@internal", "@thread");
GWI_BB((o_fork_thread = gwi_item_end(gwi, ae_flag_const, NULL)))
+ gwi_item_ini(gwi, "@internal", "@cond");
+ GWI_BB((o_fork_cond = gwi_item_end(gwi, ae_flag_const, NULL)))
+ gwi_item_ini(gwi, "@internal", "@mutex");
+ GWI_BB((o_fork_mutex = gwi_item_end(gwi, ae_flag_const, NULL)))
gwi_item_ini(gwi, "int", "is_done");
GWI_BB((o_fork_done = gwi_item_end(gwi, ae_flag_const, NULL)))
gwi_item_ini(gwi, "Event", "ev");
GWI_BB((o_fork_retsize = gwi_item_end(gwi, ae_flag_const, NULL)))
gwi_func_ini(gwi, "void", "join");
GWI_BB(gwi_func_end(gwi, fork_join, ae_flag_none))
+ gwi_func_ini(gwi, "void", "test_cancel");
+ GWI_BB(gwi_func_end(gwi, fork_test_cancel, ae_flag_none))
GWI_BB(gwi_class_end(gwi))
SET_FLAG((t_fork), abstract);
return GW_OK;
push_global(gwion, "[user]");
}
-//#define BUFSIZE 1024
-#define BUFSIZE 256
+#define BUFSIZE 64
static void afl_run(const Gwion gwion) {
char buf[BUFSIZE];
- __AFL_INIT();
- while (__AFL_LOOP(1000)) {
+ struct GwText_ text = { .mp=gwion->mp };
+ while (__AFL_LOOP(5)) {
+ ssize_t sz;
memset(buf, 0, BUFSIZE);
- read(0, buf, BUFSIZE);
- if(compile_string(gwion, "afl", buf))
+ while((sz = read(0, buf, BUFSIZE)) > 0) {
+ buf[sz] = '\0';
+ text_add(&text, buf);
+ }
+ if(compile_string(gwion, "afl", text.str))
gwion_run(gwion);
+ text_reset(&text);
gwion_reset(gwion);
}
+ text_release(&text);
}
#define gwion_run(a) afl_run(a)
#endif
t = t->e->parent;
if(!t->e->d.func)
return GW_ERROR;
+ if(!env->class_def)
+ return GW_OK;
const Func func = t->e->d.func;
const Type type = func->value_ref->from->owner_class;
- if(!env->class_def) {
- if(!type || GET_FLAG(func, global))
- return GW_OK;
-return GW_OK;
-// ERR_B(var->pos, _("can't use non public typedef at global scope."))
- }
if(type && isa(type, env->class_def) < 0 && !GET_FLAG(func, global))
ERR_B(var->pos, _("can't use non global fptr of other class."))
if(GET_FLAG(func, member) && GET_FLAG(v, static))
assert(t);
if(GET_FLAG(t, template) && !GET_FLAG(t, ref))
ERR_O(td_pos(td), _("type '%s' needs template types"), t->name)
- td->xid = new_id_list(env->gwion->mp, insert_symbol("@resolved"),
- loc_cpy(env->gwion->mp, td->exp->pos));
+ td->xid = insert_symbol("@resolved");
if(t->array_depth)
SET_FLAG(td, force);
return t;
if(GET_FLAG(td, member)) {
decl_member(env, v);
if(env->class_def->e->tuple)
- tuple_info(env, td, var);
+ tuple_info(env, v);
} else if(GET_FLAG(td, static))
decl_static(env, v);
} else if(GET_FLAG(td, global) || (env->func && GET_FLAG(env->func->def, global)))
return GW_OK;
}
+ANN static inline m_bool ensure_check(const Env env, const Type t) {
+ struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+ .scope=env->scope->depth, .flag=ae_flag_check };
+ return envset_run(&es, t);
+}
+
ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
if(!decl->td->xid)
return no_xid(env, decl);
- if(decl->td->xid->xid == insert_symbol("auto")) { // should be better
+ if(decl->td->xid == insert_symbol("auto")) { // should be better
clear_decl(env, decl);
CHECK_BO(scan1_exp(env, exp_self(decl)))
CHECK_BO(scan2_exp(env, exp_self(decl)))
}
if(!decl->type)
ERR_O(td_pos(decl->td), _("can't find type"));
-{
- const Type t = get_type(decl->type);
- if(GET_FLAG(t, template) && !GET_FLAG(t, check))
- CHECK_BO(check_cdef(env, t->e->def))
-}
+ {
+ const Type t = get_type(decl->type);
+ if(!GET_FLAG(t, check) && t->e->def)
+ CHECK_BO(ensure_check(env, t))
+ }
const m_bool global = GET_FLAG(decl->td, global);
const m_uint scope = !global ? env->scope->depth : env_push_global(env);
const m_bool ret = check_decl(env, decl);
return op_check(env, &opi);
}
-ANN static void fill_tl_vector(const Env env, Nspc nspc, const Vector v) {
- while(nspc->parent) {
- const Type t = nspc_lookup_type0(nspc->parent, insert_symbol(nspc->name));
- if(!t)
- break;
- vector_add(v, (vtype)insert_symbol(t->name));
- nspc = nspc->parent;
- }
+ANN static Type_Decl* prepend_type_decl(MemPool mp, const Symbol xid, Type_Decl* td, const loc_t pos) {
+ Type_Decl *a = new_type_decl(mp, xid, loc_cpy(mp, pos));
+ a->next = td;
+ return a;
}
ANN static Type_List mk_type_list(const Env env, const Type type, const loc_t pos) {
struct Vector_ v;
vector_init(&v);
vector_add(&v, (vtype)insert_symbol(type->name));
- if(type->e->owner)
- fill_tl_vector(env, type->e->owner, &v);
- ID_List id = NULL;
+ Type owner = type->e->owner_class;
+ while(owner) {
+ vector_add(&v, (vtype)insert_symbol(owner->name));
+ owner = owner->e->owner_class;
+ }
+ Type_Decl *td = NULL;
for(m_uint i = 0 ; i < vector_size(&v); ++i)
- id = prepend_id_list(env->gwion->mp, (Symbol)vector_at(&v, i), id, loc_cpy(env->gwion->mp, pos));
+ td = prepend_type_decl(env->gwion->mp, (Symbol)vector_at(&v, i), td, pos);
vector_release(&v);
- assert(id);
- Type_Decl* td = new_type_decl(env->gwion->mp, id);
return new_type_list(env->gwion->mp, td, NULL);
}
array_base(e->info->type) == array_base(t);
if(!match) {
if(e->info->type == env->gwion->type[et_lambda] && is_fptr(env->gwion, t)) {
- const Type owner = nspc_lookup_type1(t->e->owner->parent,
- insert_symbol(t->e->owner->name));
- const m_bool ret = check_lambda(env, owner, &e->d.exp_lambda, t->e->d.func->def);
+ const m_bool ret = check_lambda(env, t->e->owner_class, &e->d.exp_lambda, t->e->d.func->def);
exp_setvar(e, 1);
return ret;
}
}
if(e1->type == env->gwion->type[et_undefined] ||
(func->def->base->tmpl && is_fptr(env->gwion, func->value_ref->type) > 0)) {
- if(SAFE_FLAG(func->value_ref->from->owner_class, template))
- CHECK_BO(template_push_types(env, func->value_ref->from->owner_class->e->def->base.tmpl))
- e1->type = known_type(env, e1->td);
- if(SAFE_FLAG(func->value_ref->from->owner_class, template))
+ const Type owner = func->value_ref->from->owner_class;
+ if(owner)
+ CHECK_BO(template_push(env, owner))
+ e1->type = known_type(env, e1->td);
+ if(owner)
nspc_pop_type(env->gwion->mp, env->curr);
CHECK_OO(e1->type)
}
const Type_List types = exp->tmpl->call;
Func m_func = NULL, former = env->func;
DECL_OO(const m_str, tmpl_name, = tl2str(env, types))
- const m_uint scope = env_push(env, v->from->owner_class, v->from->owner);
+ const m_uint scope = env->scope->depth;
+ struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+ .scope=scope, .flag=ae_flag_check };
+ if(v->from->owner_class)
+ envset_push(&es, v->from->owner_class);
+ (void)env_push(env, v->from->owner_class, v->from->owner);
if(is_fptr(env->gwion, v->type)) {
const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl_name, 0);
const Type exists = nspc_lookup_type0(v->from->owner, sym);
if(m_func)
nspc_add_type_front(v->from->owner, sym, actual_type(env->gwion, m_func->value_ref->type));
}
- free_fptr_def(env->gwion->mp, fptr); // ???? related
+ free_fptr_def(env->gwion->mp, fptr);
}
}
} else {
}
}
free_mstr(env->gwion->mp, tmpl_name);
+ if(v->from->owner_class && v->from->owner_class->e->owner_class && es.run)
+ envset_pop(&es, v->from->owner_class->e->owner_class);
env_pop(env, scope);
env->func = former;
return m_func;
return v->d.func_ref = func;
}
-ANN static Type check_predefined(const Env env, Exp_Call *exp, const Value value, const Tmpl *tm, const Func_Def fdef) {
- DECL_OO(const Func, func, = value->d.func_ref ?: predefined_func(env, value, exp, tm))
+ANN static Type check_predefined(const Env env, Exp_Call *exp, const Value v, const Tmpl *tm, const Func_Def fdef) {
+ DECL_OO(const Func, func, = v->d.func_ref ?: predefined_func(env, v, exp, tm))
if(!fdef->base->ret_type) { // template fptr
- const m_uint scope = env_push(env, value->from->owner_class, value->from->owner);
+ const m_uint scope = env->scope->depth;
+ struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+ .scope=scope, .flag=ae_flag_check };
+ if(v->from->owner_class)
+ envset_push(&es, v->from->owner_class);
+ (void)env_push(env, v->from->owner_class, v->from->owner);
const m_bool ret = traverse_func_def(env, func->def);
+ if(v->from->owner_class && v->from->owner_class->e->owner_class && es.run)
+ envset_push(&es, v->from->owner_class);
env_pop(env, scope);
CHECK_BO(ret)
}
Arg_List arg = fdef->base->args;
Exp template_arg = exp->args;
while(arg && template_arg) {
- char path[id_list_len(arg->td->xid)];
- type_path(path, arg->td->xid);
- if(!strcmp(s_name(list->xid), path)) {
+ if(list->xid == arg->td->xid) {
tl[args_number] = mk_type_list(env, template_arg->info->type, fdef->pos);
if(args_number)
tl[args_number - 1]->next = tl[args_number];
memset(&array, 0, sizeof(struct Array_Sub_));
memset(&td0, 0, sizeof(Type_Decl));
memset(&td, 0, sizeof(Type_Decl));
- id.xid = insert_symbol("Ptr");
- id0.xid = insert_symbol(ptr->name);
- td0.xid = &id0;
- td.xid = &id;
+ td.xid = insert_symbol("Ptr");
+ td0.xid = insert_symbol(ptr->name);
tl.td = &td0;
td.types = &tl;
- td0.xid->pos = stmt->exp->pos;
- td.xid->pos = stmt->exp->pos;
+ td0.pos = stmt->exp->pos;
+ td.pos = stmt->exp->pos;
if(depth) {
array.depth = depth;
td.array = &array;
}
ptr = known_type(env, &td);
if(!GET_FLAG(ptr, checked) && ptr->e->def)
- CHECK_BB(traverse_cdef(env, ptr->e->def))
+ CHECK_BB(ensure_check(env, ptr))
}
t = depth ? array_type(env, ptr, depth) : ptr;
stmt->v = new_value(env->gwion->mp, t, s_name(stmt->sym));
if(stmt->val) {
if(env->func->def->base->xid == insert_symbol("@implicit") && ret_type == env->func->def->base->args->type)
ERR_B(stmt_self(stmt)->pos, _("can't use implicit casting while defining it"))
- const m_bool ret = check_implicit(env, stmt->val, env->func->def->base->ret_type);
- if(ret > 0)
- return ret;
+ if(check_implicit(env, stmt->val, env->func->def->base->ret_type) > 0)
+ return GW_OK;
ERR_B(stmt_self(stmt)->pos, _("invalid return type: got '%s', expected '%s'"),
ret_type->name, env->func->def->base->ret_type->name)
}
ANN m_bool check_class_def(const Env env, const Class_Def c) {
if(tmpl_base(c->base.tmpl))
return GW_OK;
- const Class_Def cdef = c->base.type->e->def;
- if(GET_FLAG(cdef->base.type, checked))return GW_OK;
- const Type type = cdef->base.type;
- SET_FLAG(type, check);
+ const Type t = c->base.type;
+ const Class_Def cdef = t->e->def;
+ if(t->e->owner_class && !GET_FLAG(t->e->owner_class, check))
+ CHECK_BB(check_class_def(env, t->e->owner_class->e->def))
+ if(GET_FLAG(t, checked))return GW_OK;
+ SET_FLAG(t, check);
if(cdef->base.ext)
CHECK_BB(cdef_parent(env, cdef))
- assert(type->e->parent || GET_FLAG(cdef, struct));
if(!GET_FLAG(cdef, struct))
- inherit(type);
+ inherit(t);
if(cdef->body)
CHECK_BB(env_body(env, cdef, check_section))
- SET_FLAG(type, checked);
+ SET_FLAG(t, checked);
return GW_OK;
}
return GW_OK;
}
+ANN static m_bool scan0_fptr_args(const Env env, const Fptr_Def fptr) {
+ nspc_push_type(env->gwion->mp, env->curr);
+ const m_bool ret = check_tmpl_args(env, fptr->base);
+ nspc_pop_type(env->gwion->mp, env->curr);
+ return ret;
+}
+
ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) {
CHECK_BB(env_access(env, fptr->base->td->flag, td_pos(fptr->base->td)))
CHECK_OB(known_type(env, fptr->base->td))
CHECK_BB(scan0_defined(env, fptr->base->xid, td_pos(fptr->base->td)));
const m_str name = s_name(fptr->base->xid);
-if(fptr->base->tmpl && fptr->base->args) {
- nspc_push_type(env->gwion->mp, env->curr);
- const m_bool ret = check_tmpl_args(env, fptr->base);
- nspc_pop_type(env->gwion->mp, env->curr);
- CHECK_BB(ret);
-}
+ if(fptr->base->tmpl && fptr->base->args)
+ CHECK_BB(scan0_fptr_args(env, fptr))
const Type t = scan0_type(env, env->gwion->type[et_fptr]->xid, name, env->gwion->type[et_fptr]);
t->e->owner = !(!env->class_def && GET_FLAG(fptr->base->td, global)) ?
env->curr : env->global_nspc;
+ t->e->owner_class = env->class_def;
if(GET_FLAG(fptr->base->td, global))
context_global(env);
t->nspc = new_nspc(env->gwion->mp, name);
t->flag = fptr->base->td->flag;
fptr->type = t;
fptr->value = mk_class(env, t);
-// set owner ?
- fptr->value->from->owner = env->curr;
- fptr->value->from->owner_class = env->class_def;
+ valuefrom(env, fptr->value->from);
fptr_def(env, fptr);
if(env->class_def)
fptr_assign(env, fptr);
context_global(env);
add_type(env, nspc, t);
t->e->owner = nspc;
+ t->e->owner_class = env->class_def;
tdef->type = t;
if(base->nspc)
ADD_REF((t->nspc = base->nspc));
ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) {
CHECK_BB(env_access(env, tdef->ext->flag, td_pos(tdef->ext)))
- DECL_OB(const Type, base, = tdef->tmpl ? find_type(env, tdef->ext->xid) : known_type(env, tdef->ext))
+ DECL_OB(const Type, base, = tdef->tmpl ? find_type(env, tdef->ext) : known_type(env, tdef->ext))
CHECK_BB(scan0_defined(env, tdef->xid, td_pos(tdef->ext)))
if(isa(base, env->gwion->type[et_function]) < 0) {
if(!tdef->ext->types && (!tdef->ext->array || !tdef->ext->array->exp))
t->e->parent = env->gwion->type[et_int];
const Nspc nspc = GET_FLAG(edef, global) ? env->global_nspc : env->curr;
t->e->owner = nspc;
+ t->e->owner_class = env->class_def;
add_type(env, nspc, t);
mk_class(env, t);
scan0_implicit_similar(env, t, env->gwion->type[et_int]);
t->name = name;
t->nspc = new_nspc(env->gwion->mp, name);
t->e->owner = t->nspc->parent = env->curr;
+ t->e->owner_class = env->class_def;
t->e->parent = env->gwion->type[et_union];
add_type(env, env->curr, t);
if(add) {
if(tmpl_base(udef->tmpl)) {
assert(udef->type_xid);
const Class_Def cdef = new_class_def(env->gwion->mp, udef->flag, udef->type_xid,
- NULL, (Ast)udef->l, loc_cpy(env->gwion->mp, udef->pos));
+ NULL, (Ast)cpy_decl_list(env->gwion->mp, udef->l), loc_cpy(env->gwion->mp, udef->pos));
udef->type->e->def = cdef;
cdef->base.tmpl = cpy_tmpl(env->gwion->mp, udef->tmpl);
cdef->base.type = udef->type;
- cdef->list = cpy_decl_list(env->gwion->mp, udef->l);
+// cdef->list = cpy_decl_list(env->gwion->mp, udef->l);
SET_FLAG(cdef, union);
SET_FLAG(udef->type, pure);
SET_FLAG(udef, template);
return GW_OK;
}
-ANN static void set_template(const Type t, const Class_Def cdef) {
- SET_FLAG(t, template);
- SET_FLAG(cdef, template);
-}
-
-
-ANN static void inherit_tmpl(const Env env, const Class_Def cdef) {
- const ID_List list = env->class_def->e->def->base.tmpl->list;
- const ID_List prev_list = cpy_id_list(env->gwion->mp, list);
- ID_List il = prev_list;
- while(il->next && (il = il->next));
- il->next = cdef->base.tmpl->list;
- cdef->base.tmpl->list = prev_list;
+ANN static void cdef_flag(const Class_Def cdef, const Type t) {
+ if(cdef->base.tmpl) {
+ SET_FLAG(t, template);
+ SET_FLAG(cdef, template);
+ }
+ if(cdef->base.ext && cdef->base.ext->array)
+ SET_FLAG(t, typedef);
}
ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
}
t->e->tuple = new_tupleform(env->gwion->mp, parent);
t->e->owner = env->curr;
+ t->e->owner_class = env->class_def;
t->nspc = new_nspc(env->gwion->mp, t->name);
t->nspc->parent = env->curr;
t->e->def = cdef;
t->flag = cdef->flag;
add_type(env, t->e->owner, t);
- if(cdef->base.tmpl) {
- if(SAFE_FLAG(env->class_def, template) && env->class_def->e->def->base.tmpl->call == (Type_List)1)
- inherit_tmpl(env, cdef);
- set_template(t, cdef);
- } else if(SAFE_FLAG(env->class_def, template)) {
- cdef->base.tmpl = new_tmpl_base(env->gwion->mp, cpy_id_list(env->gwion->mp, env->class_def->e->def->base.tmpl->list));
-// cdef->base.tmpl = cpy_tmpl(env->gwion->mp, env->class_def->e->def->base.tmpl);
- set_template(t, cdef);
- }
+ cdef_flag(cdef, t);
if(cdef->base.ext && cdef->base.ext->array)
SET_FLAG(t, typedef);
return t;
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)))
SET_FLAG(cdef->base.type, scan0);
- if(cdef->body) {
- int call = cdef->base.tmpl && !cdef->base.tmpl->call;
- if(call)cdef->base.tmpl->call = (Type_List)1;
- const m_bool ret = env_body(env, cdef, scan0_section);
- if(call)cdef->base.tmpl->call = NULL;
- CHECK_BB(ret);
- }
+ if(cdef->body)
+ CHECK_BB(env_body(env, cdef, scan0_section))
(void)mk_class(env, cdef->base.type);
return GW_OK;
}
-ANN m_bool scan0_class_def(const Env env, const Class_Def cdef) {
+ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
+ const Class_Def cdef = !(GET_FLAG(c, global) || (c->base.tmpl && !c->base.tmpl->call)) ?
+ c : cpy_class_def(env->gwion->mp, c);
if(GET_FLAG(cdef, global)) {
vector_add(&env->scope->nspc_stack, (vtype)env->curr);
env->curr = env->global_nspc;
if(GET_FLAG(cdef, global))
env->curr = (Nspc)vector_pop(&env->scope->nspc_stack);
CHECK_BB(ret)
- if(GET_FLAG(cdef, global) || (cdef->base.tmpl && !cdef->base.tmpl->call)) {
- const Class_Def c = cpy_class_def(env->gwion->mp, cdef);
+ if(GET_FLAG(cdef, global) || (cdef->base.tmpl && !cdef->base.tmpl->call))
c->base.type = cdef->base.type;
- c->base.type->e->def = c;
- }
return GW_OK;
}
ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list);
ANN static m_bool scan1_stmt(const Env env, Stmt stmt);
-ANN static inline void type_contains(const Type base, const Type t) {
- const Vector v = &base->e->contains;
- if(!v->ptr)
- vector_init(v);
- if(vector_find(v, (vtype)t) == GW_ERROR) {
- vector_add(v, (vtype)t);
- if(base != t)
- ADD_REF(t);
- }
-}
-
ANN static m_bool type_recursive(const Env env, const Type_Decl *td, const Type t) {
if(env->class_def && !env->scope->depth) {
- type_contains(env->class_def, t);
- if(t->e->contains.ptr) {
- for(m_uint i = 0; i < vector_size(&t->e->contains); ++i) {
- if(env->class_def == (Type)vector_at(&t->e->contains, i) && !GET_FLAG(td, ref))
- ERR_B(td_pos(td), _("%s declared inside %s\n. (make it a ref ?)"),
- t->name, t == env->class_def ? "itself" : env->class_def->name);
- }
- }
+ const m_int idx = vector_find(&env->scope->class_stack, (vtype)t);
+ if(idx > -1 || t == env->class_def)
+ ERR_B(td_pos(td), _("%s declared inside %s\n. (make it a ref ?)"),
+ t->name, t == env->class_def ? "itself" : env->class_def->name);
}
return GW_OK;
}
-ANN static Type void_type(const Env env, const Type_Decl* td) {
+ANN static Type void_type(const Env env, Type_Decl* td) {
DECL_OO(const Type, type, = known_type(env, td))
const Type t = get_type(type);
if(isa(t, env->gwion->type[et_object]) > 0 || GET_FLAG(t, struct))
if(decl->type)
return decl->type;
DECL_OO(const Type ,t, = void_type(env, decl->td))
- if(decl->td->xid && decl->td->xid->xid == insert_symbol("auto") && decl->type)
+ if(decl->td->xid == insert_symbol("auto") && decl->type)
return decl->type;
if(!env->scope->depth && env->class_def && !GET_FLAG(decl->td, static))
SET_FLAG(decl->td, member);
}
t = array_type(env, decl->type, var->array->depth);
} else if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref)) {
- if(decl->td->xid && decl->td->xid->xid == insert_symbol("auto"))
+ if(decl->td->xid == insert_symbol("auto"))
SET_FLAG(decl->td, ref);
else
ERR_B(exp_self(decl)->pos, _("Type '%s' is abstract, declare as ref. (use @)"), t->name)
}
- if(env->class_def)
- type_contains(env->class_def, t);
const Value v = var->value = former ?: new_value(env->gwion->mp, t, s_name(var->xid));
if(SAFE_FLAG(env->class_def, struct) && !GET_FLAG(decl->td, static)) {
v->from->offset = env->class_def->size;
ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
if(tmpl_base(fptr->base->tmpl))
return GW_OK;
+ if(!fptr->base->func) {
+ fptr->base->func = nspc_lookup_value0(env->curr, fptr->base->xid)->d.func_ref;
+ fptr->type = nspc_lookup_type0(env->curr, fptr->base->xid);
+ }
const Func_Def fdef = fptr->base->func->def;
CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)))
return fdef->base->args ? scan1_args(env, fdef->base->args) : GW_OK;
}
ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
+ if(!tdef->type)
+ tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
if(!tdef->type->e->def)return GW_OK;
return !is_fptr(env->gwion, tdef->type) ? scan1_cdef(env, tdef->type->e->def) : GW_OK;
}
}
const m_bool ret = scan1_union_def_inner(env, udef);
union_pop(env, udef, scope);
- const Type type = udef->xid || udef->type_xid ? udef->value->type : udef->type;
+ const Type type = udef->xid || !udef->type_xid ? udef->value->type : udef->type;
SET_FLAG(type, scan1);
return ret;
}
ANN m_bool scan1_class_def(const Env env, const Class_Def c) {
if(tmpl_base(c->base.tmpl))
return GW_OK;
- const Class_Def cdef = c->base.type->e->def;
- if(GET_FLAG(cdef->base.type, scan1))return GW_OK;
+ const Type t = c->base.type;
+ const Class_Def cdef = t->e->def;
+ if(GET_FLAG(t, scan1))return GW_OK;
+ if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan1))
+ CHECK_BB(scan1_class_def(env, t->e->owner_class->e->def))
SET_FLAG(cdef->base.type, scan1);
if(cdef->base.ext)
CHECK_BB(cdef_parent(env, cdef))
ANN static m_bool scan2_stmt(const Env, const Stmt);
ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
+ANN static inline m_bool ensure_scan2(const Env env, const Type t) {
+ struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan2_cdef,
+ .scope=env->scope->depth, .flag=ae_flag_scan2 };
+ return envset_run(&es, t);
+}
+
ANN static m_bool scan2_decl(const Env env, const Exp_Decl* decl) {
const Type t = get_type(decl->type);
- if(GET_FLAG(t, template) && !GET_FLAG(t, scan2))
- CHECK_BB(scan2_cdef(env, t->e->def))
+ if(!GET_FLAG(t, scan2) && t->e->def)
+ CHECK_BB(ensure_scan2(env, t))
Var_Decl_List list = decl->list;
do {
const Var_Decl var = list->self;
return ret;
}
-ANN static m_bool scan2_args(const Env env, const Func_Def f) {
+ANN static m_bool scan2_args(const Func_Def f) {
Arg_List list = f->base->args;
do {
const Value v = list->var_decl->value;
}
-ANN m_bool scan2_fptr_def(const Env env, const Fptr_Def fptr) {
+ANN m_bool scan2_fptr_def(const Env env NUSED, const Fptr_Def fptr) {
if(!tmpl_base(fptr->base->tmpl)) {
const Func_Def def = fptr->type->e->d.func->def;
if(def->base->args)
- CHECK_BB(scan2_args(env, def))
+ CHECK_BB(scan2_args(def))
} else
SET_FLAG(fptr->type, func);
return GW_OK;
ANN static m_bool scan2_union_decl(const Env env, const Decl_List list) {
Decl_List l = list;
do CHECK_BB(scan2_exp_decl(env, &l->self->d.exp_decl))
+// do CHECK_BB(scan2_exp(env, l->self))
while((l = l->next));
return GW_OK;
}
t->e->parent = env->gwion->type[func->def->base->td ? et_function : et_lambda];
t->name = func->name;
t->e->owner = env->curr;
+ t->e->owner_class = env->class_def;
if(GET_FLAG(func, member))
t->size += SZ_INT;
t->e->d.func = func;
const Symbol sym = func_symbol(env, env->curr->name, name, "template", i);
nspc_add_value(env->curr, sym, value);
if(!overload) {
-// func->vt_index = i; // ?????
ADD_REF(value)
nspc_add_value(env->curr, f->base->xid, value);
nspc_add_func(env->curr, f->base->xid, func);
do {
const Type t = nspc_lookup_type0(env->curr, id->xid);
if(!t)return NULL;
-// assert(t);
vector_add(&v, (vtype)t);
tlen += strlen(t->name);
} while((id = id->next) && ++tlen);
else
f->base->func = base;
if(f->base->args)
- CHECK_BB(scan2_args(env, f))
+ CHECK_BB(scan2_args(f))
if(!GET_FLAG(f, builtin) && f->d.code)
CHECK_BB(scan2_func_def_code(env, f))
if(!base) {
ANN m_bool scan2_class_def(const Env env, const Class_Def c) {
if(tmpl_base(c->base.tmpl))
return GW_OK;
- const Class_Def cdef = c->base.type->e->def;
- if(GET_FLAG(cdef->base.type, scan2))return GW_OK;
- SET_FLAG(cdef->base.type, scan2);
+ const Type t = c->base.type;
+ const Class_Def cdef = t->e->def;
+ if(GET_FLAG(t, scan2))return GW_OK;
+ if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan2))
+ CHECK_BB(scan2_class_def(env, t->e->owner_class->e->def))
+ SET_FLAG(t, scan2);
if(cdef->base.ext)
CHECK_BB(cdef_parent(env, cdef))
if(cdef->body)
uint8_t index;
};
-ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
+ANN static m_bool push_types(const Env env, const Tmpl *tmpl) {
ID_List list = tmpl->list;
Type_List call = tmpl->call;
- nspc_push_type(env->gwion->mp, env->curr);
do {
if(!call)
break;
const Type t = known_type(env, call->td);
if(!t)
- return GW_ERROR;
+ return 1;
nspc_add_type(env->curr, list->xid, t);
call = call->next;
} while((list = list->next));
- if(!call)
+ return !call;
+}
+
+ANN static m_bool _template_push(const Env env, const Type t) {
+ if(t->e->owner_class)
+ CHECK_BB(template_push(env, t->e->owner_class))
+ if(GET_FLAG(t, template))
+ return push_types(env, t->e->def->base.tmpl);
+ return GW_OK;
+}
+
+ANN m_bool template_push(const Env env, const Type t) {
+ nspc_push_type(env->gwion->mp, env->curr);
+ return _template_push(env, t);
+}
+
+ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
+ nspc_push_type(env->gwion->mp, env->curr);
+ if(push_types(env, tmpl))
return GW_OK;
- POP_RET(-1);
+ POP_RET(GW_ERROR);
}
ANN Tmpl* mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) {
func->flag = def->flag;
value->d.func_ref = func;
value->from->owner = t->e->owner;
- value->from->owner_class = t->e->d.func->value_ref->from->owner_class;
+ value->from->owner_class = t->e->owner_class;
func->value_ref = value;
func->def->base->tmpl = mk_tmpl(env, t->e->d.func->def->base->tmpl, td->types);
def->base->func = func;
static ANN Type maybe_func(const Env env, const Type t, const Type_Decl* td) {
if(isa(t, env->gwion->type[et_function]) > 0 && t->e->d.func->def->base->tmpl)
return scan_func(env, t, td);
- ERR_O(td->xid->pos,
- _("type '%s' is not template. You should not provide template types"), t->name)
+ ERR_O(td->pos,
+ _("type '%s' is not template. You should not provide template types"), t->name)
}
-ANN Type scan_type(const Env env, const Type t, const Type_Decl* td) {
+ANN Type _scan_type(const Env env, const Type t, const Type_Decl* td) {
if(GET_FLAG(t, template)) {
if(GET_FLAG(t, ref))
return t;
return op_check(env, &opi);
} else if(td->types)
return maybe_func(env, t, td);
- return t;
+ return td->xid ? nspc_lookup_type1(env->curr, td->xid) : t;
}
+
+ANN Type scan_type(const Env env, const Type t, Type_Decl* td) {
+ if(td->next) {
+ Type_Decl *next = td->next;
+ td->next = NULL;
+ const Type owner = known_type(env, td);
+ td->next = next;
+ CHECK_OO(owner)
+ if(!owner->nspc)
+ ERR_O(td_pos(td), "type '%s' has no namespace", owner->name)
+ const Tmpl *tmpl = GET_FLAG(owner, template) ?
+ owner->e->def->base.tmpl : NULL;
+ if(tmpl)
+ CHECK_BO(template_push_types(env, tmpl))
+ const m_uint scope = env_push(env, owner, owner->nspc);
+ const Type ret = scan_type(env, t, td->next);
+ env_pop(env, scope);
+ if(tmpl)
+ nspc_pop_type(env->gwion->mp, env->curr);
+ return ret;
+ }
+ return _scan_type(env, t, td);
+}
+
return t;
}
-ANN Type type_decl_resolve(const Env env, const Type_Decl* td) {
- DECL_OO(const Type, base, = find_type(env, td->xid))
+ANN Type type_decl_resolve(const Env env, Type_Decl* td) {
+ DECL_OO(const Type, base, = find_type(env, td))
if(base->e->ctx && base->e->ctx->error)
ERR_O(td_pos(td), _("type '%s' is invalid"), base->name)
DECL_OO(const Type, t, = scan_type(env, base, td))
return info.text.str;
}
-ANN static inline void* type_unknown(const Env env, const ID_List id) {
- char path[id_list_len(id)];
- type_path(path, id);
- env_err(env, id->pos, _("unknown type '%s'"), path);
- did_you_mean_nspc(env->curr, s_name(id->xid));
+ANN static inline void* type_unknown(const Env env, const Type_Decl* td) {
+ env_err(env, td->pos, _("unknown type '%s'"), s_name(td->xid));
return NULL;
}
-ANN Type known_type(const Env env, const Type_Decl* td) {
+ANN Type known_type(const Env env, Type_Decl* td) {
if(!td->xid)
return env->gwion->type[et_undefined];
- return type_decl_resolve(env, td) ?:type_unknown(env, td->xid);
+ return type_decl_resolve(env, td) ?:type_unknown(env, td);
}
}
ANN void shreduler_remove(const Shreduler s, const VM_Shred out, const m_bool erase) {
- struct ShredTick_ *tk = out->tick;
- assert(tk);
MUTEX_LOCK(s->mutex);
+ struct ShredTick_ *tk = out->tick;
if(tk == s->curr)
s->curr = NULL;
else if(tk == s->list)
}
ANN void vm_lock(VM const *vm) {
- do MUTEX_LOCK(vm->shreduler->mutex);
- while((vm = vm->parent));
+ if(vm->parent)
+ vm_lock(vm->parent);
+ MUTEX_LOCK(vm->shreduler->mutex);
}
ANN void vm_unlock(VM const *vm) {
return vm->shreduler->bbq->is_running = vm_running(vm->parent);
}
-ANN static void vm_fork(VM* src, const VM_Shred shred) {
- VM* vm = (shred->info->vm = gwion_cpy(src));
- vm->parent = src;
- const M_Object o = shred->info->me = new_shred(shred, 0);
- ++shred->info->me->ref;
- if(!src->gwion->data->child.ptr)
- vector_init(&src->gwion->data->child);
- vector_add(&src->gwion->data->child, (vtype)o);
- shreduler_add(vm->shreduler, shred);
-}
-
__attribute__((hot))
ANN static inline void vm_ugen_init(const VM* vm) {
const Vector v = (Vector)&vm->ugen;
return sh;
}
-ANN static inline VM_Shred fork_shred(const VM_Shred shred, const VM_Code code) {
+ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, const m_uint retsz) {
+ VM* parent = shred->info->vm;
const VM_Shred sh = new_shred_base(shred, code);
- vm_fork(shred->info->vm, sh);
- return sh;
-}
-
-ANN static inline VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code) {
- VM *vm = shred->info->vm;
- vm_lock(vm);
- const VM_Shred sh = vm_running(vm) ? fork_shred(shred, code) : NULL;
- vm_unlock(vm);
+ VM* vm = (sh->info->vm = gwion_cpy(parent));
+ vm->parent = parent;
+ const M_Object o = sh->info->me = new_shred(sh, 0);
+ ++sh->info->me->ref;
+ if(!parent->gwion->data->child.ptr)
+ vector_init(&parent->gwion->data->child);
+ vector_add(&parent->gwion->data->child, (vtype)o);
+ shreduler_add(vm->shreduler, sh);
+ fork_launch(parent, sh->info->me, retsz);
return sh;
}
&&timeadv,
&&setcode,
&®pop, &®push, &®tomem, &®tomemother, &&overflow, &&funcusrend, &&funcmemberend,
- &&sporkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&forkend, &&sporkend,
+ &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkend,
&&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat,
&&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid,
&&newobj, &&addref, &&addrefaddr, &&objassign, &&assign, &&remref,
}
PC_DISPATCH(shred->pc)
sporkini:
- if(!(child = (VAL2 ? init_spork_shred : init_fork_shred)(shred, (VM_Code)VAL))) {
- exception(shred, "[SporkAbortedException]");
- continue;
- }
+ child = init_spork_shred(shred, (VM_Code)VAL);
+ DISPATCH()
+forkini:
+ child = init_fork_shred(shred, (VM_Code)VAL, VAL2),
DISPATCH()
sporkfunc:
// LOOP_OPTIM
for(m_uint i = 0; i < VAL; i+= SZ_INT)
*(m_uint*)(child->mem + i) = *(m_uint*)(mem+i);
DISPATCH()
-forkend:
- fork_launch(vm, child->info->me, VAL2);
sporkend:
assert(!VAL); // spork are not mutable
*(M_Object*)(reg-SZ_INT) = child->info->me;
vector_init(&vm->shreduler->shreds);
MUTEX_SETUP(vm->shreduler->mutex);
vm->shreduler->bbq = vm->bbq;
+#ifndef __AFL_COMPILER
gw_seed(vm->rand, (uint64_t)time(NULL));
+#else
+ gw_seed(vm->rand, 0);
+#endif
return vm;
}
--- /dev/null
+#! [contains] has no namespace
+class C{
+ class private D{}
+}
+int->D d;
+++ /dev/null
-fork { <<< __func__ >>>; second => now; };
+++ /dev/null
-fork {
- fork {
- <<< __func__ >>>;
- second => now;
- };
- <<< __func__ >>>;
- second => now;
-};
+++ /dev/null
-fork { <<< __func__ >>>; } @=> Fork ref f;
-second => now;
-f.join();
+++ /dev/null
-fork { <<< __func__ >>>; minute => now; } @=> Fork ref f;
-f.join();
-Subproject commit 8054afd48c0b7c13a6e0d53e044df5812dc99ca5
+Subproject commit b83174c4c45a7f372d317cd6cb1b0c357fba7afb