static inline void release(const restrict M_Object obj, const restrict VM_Shred shred) {
if(obj)_release(obj, shred);
}
+typedef void (f_release)(const VM_Shred shred, const Type t NUSED, const m_bit* ptr);
+#define RELEASE_FUNC(a) void (a)(const VM_Shred shred, const Type t NUSED, const m_bit* ptr)
+static inline RELEASE_FUNC(object_release) { release(*(M_Object*)ptr, shred); }
+RELEASE_FUNC(struct_release);
+
#endif
regxxx(pushi, PushImm)
regxxx(seti, SetImm)
+ANN static void struct_expand(const Emitter emit, const Type t) {
+ const Instr instr = emit_add_instr(emit, Reg2RegDeref);
+ instr->m_val = -SZ_INT;
+ instr->m_val2 = t->size;
+// regpush(emit, t->size - SZ_INT);
+}
+
+
+INSTR(ArrayStruct);
+
ANN static void emit_pre_constructor_array(const Emitter emit, const Type type) {
const m_uint start_index = emit_code_size(emit);
const Instr top = emit_add_instr(emit, ArrayTop);
top->m_val2 = (m_uint)type;
+ if(GET_FLAG(type, struct)) {
+ const Instr instr = emit_add_instr(emit, ArrayStruct);
+ instr->m_val = type->size;
+ }
emit_pre_ctor(emit, type);
- const Instr bottom = emit_add_instr(emit, ArrayBottom);
+ if(!GET_FLAG(type, struct))
+ emit_add_instr(emit, ArrayBottom);
+ else
+ regpop(emit, SZ_INT);
regpop(emit, SZ_INT);
const Instr pc = emit_add_instr(emit, Goto);
pc->m_val = start_index;
top->m_val = emit_code_size(emit);
- bottom->m_val = start_index;
regpop(emit, SZ_INT*3);
emit_add_instr(emit, ArrayPost);
}
ANN static inline void arrayinfo_ctor(const Emitter emit, ArrayInfo *info) {
const Type base = info->base;
-// TODO: needed for coumpund?
- if(isa(base, emit->gwion->type[et_object]) > 0 && !GET_FLAG(base, abstract)) {
+ if(isa(base, emit->gwion->type[et_compound]) > 0 && !GET_FLAG(base, abstract)) {
emit_pre_constructor_array(emit, base);
+// if(isa(base, emit->gwion->type[et_object]) > 0)
info->is_obj = 1;
}
}
regpop(emit, offset);
}
-ANN static void interp_size(const Emitter emit, const Type t) {
- const m_uint sz = (isa(t, emit->gwion->type[et_object]) < 0 ||
- (!GET_FLAG(t, builtin) && isa(t, emit->gwion->type[et_compound]) > 0))?
- t->size : SZ_INT;
- const Instr instr = regseti(emit, sz);
+ANN static inline void interp_size(const Emitter emit, const Type t) {
+ const Instr instr = regseti(emit, t->size);
instr->m_val2 = SZ_INT;
}
regseti(emit, (m_uint)e->info->type);
interp_size(emit, e->info->type);
const m_bool isobj = isa(e->info->type, emit->gwion->type[et_object]) > 0;
- if(isobj) {
- if(!GET_FLAG(e->info->type, force))
- emit_add_instr(emit, GackType);
- }
+ 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);
} while((e = e->next = next));
}
ANN static inline int struct_ctor(const Value v) {
- return GET_FLAG(v->type, struct) && !GET_FLAG(v->type, builtin);
+ return GET_FLAG(v->type, struct) && v->type->nspc->pre_ctor;
}
ANN static void decl_expand(const Emitter emit, const Type t) {
- const Instr instr = emit_add_instr(emit, Reg2RegDeref);
- instr->m_val = -SZ_INT;
- instr->m_val2 = t->size;
+ struct_expand(emit, t);
regpush(emit, t->size - SZ_INT);
}
emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, exec) : emit_struct_decl(emit, v, !struct_ctor(v) ? emit_addr : 1);
instr->m_val = v->from->offset;
if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref)) {
- emit_add_instr(emit, Assign);
+ if(!emit_var)
+ emit_add_instr(emit, Assign);
+ else {
+ regpop(emit, SZ_INT);
+ const Instr instr = emit_add_instr(emit, Reg2Reg);
+ instr->m_val = -SZ_INT;
+ }
const size_t missing_depth = type->array_depth - (array ? array->depth : 0);
if(missing_depth && !GET_FLAG(decl->td, force)) {
const Instr push = emit_add_instr(emit, Reg2Reg);
}
const Exp e = exp_self(exp_call);
if(exp_getvar(e)) {
+puts("here");
regpop(emit, exp_self(exp_call)->info->type->size - SZ_INT);
const Instr instr = emit_add_instr(emit, Reg2RegAddr);
instr->m_val = -SZ_INT;
ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop) {
CHECK_BB(emit_stmt_func[stmt->stmt_type](emit, &stmt->d))
- if(pop && stmt->stmt_type == ae_stmt_exp && stmt->d.stmt_exp.val)
+ if(pop && stmt->stmt_type == ae_stmt_exp && stmt->d.stmt_exp.val) {
pop_exp(emit, stmt->d.stmt_exp.val);
+ }
return GW_OK;
}
ADD_REF(f->code)
return f->code;
} else if(f->def->base->xid == insert_symbol("@gack")) {
- regpop(emit, SZ_INT*2);
+ regpop(emit, SZ_INT + f->value_ref->from->owner_class->size);
const Instr instr = emit_add_instr(emit, RegPushMem);
instr->m_val = SZ_INT;
f->code = finalyze(emit, FuncReturn);
ANN static m_bool emit_parent(const Emitter emit, const Class_Def cdef) {
const Type parent = cdef->base.type->e->parent;
- return !GET_FLAG(parent, emit) ? scanx_parent(parent, emit_cdef, emit) : GW_OK;
+ return !GET_FLAG(parent, emit) ? ensure_emit(emit, parent) : GW_OK;
}
ANN static inline m_bool emit_cdef(const Emitter emit, const Class_Def cdef) {
ANN static m_bool cdef_parent(const Emitter emit, const Class_Def cdef) {
if(cdef->base.tmpl && cdef->base.tmpl->list)
CHECK_BB(template_push_types(emit->env, cdef->base.tmpl))
- const m_bool ret = scanx_parent(cdef->base.type, emit_parent, emit);
+ const m_bool ret = emit_parent(emit, cdef);
if(cdef->base.tmpl && cdef->base.tmpl->list)
nspc_pop_type(emit->gwion->mp, emit->env->curr);
return ret;
if(GET_FLAG(t, emit))
return GW_OK;
SET_FLAG(t, emit);
+ if(t->e->owner_class && !GET_FLAG(t->e->owner_class, emit))
+ CHECK_BB(ensure_emit(emit, t->e->owner_class))
if(cdef->base.ext && t->e->parent->e->def && !GET_FLAG(t->e->parent, emit))
CHECK_BB(cdef_parent(emit, cdef))
nspc_allocdata(emit->gwion->mp, t->nspc);
#include "parse.h"
#include "gwion.h"
#include "clean.h"
+#include "object.h"
ANN static inline m_bool freeable(const Type a) {
return !GET_FLAG(a, nonnull) && GET_FLAG(a, template);
t->array_depth = depth + src->array_depth;
t->e->d.base_type = array_base(src) ?: src;
t->e->owner = src->e->owner;
+ if(depth > 1 || isa(src, env->gwion->type[et_compound]) > 0) {
+ t->nspc = new_nspc(env->gwion->mp, s_name(sym));
+ inherit(t);
+ t->nspc->info->class_data_size = SZ_INT;
+ nspc_allocdata(env->gwion->mp, t->nspc);
+ *(f_release**)(t->nspc->info->class_data) = (depth > 1 || !GET_FLAG(src, struct)) ?
+ object_release : struct_release;
+ } else
ADD_REF((t->nspc = env->gwion->type[et_array]->nspc))
SET_FLAG(t, valid);
mk_class(env, t);
return GW_OK;
}
-ANN2(1,2) static inline m_bool class_parent(const Env env, const Type t) {
- Type parent = t->e->parent;
- while(parent && !GET_FLAG(parent, valid)) {
+ANN2(1,2) static inline m_bool class_parent(const Env env, Type t) {
+ while(t && !GET_FLAG(t, valid)) {
if(t->e->def)
CHECK_BB(traverse_class_def(env, t->e->def))
- parent = parent->e->parent;
+ t = t->e->parent;
}
return GW_OK;
}
ANN static Type type_finish(const Gwi gwi, const Type t) {
gwi_add_type(gwi, t);
- CHECK_BO(class_parent(gwi->gwion->env, t))
import_class_ini(gwi->gwion->env, t);
return t;
}
+ANN2(1,2) Type handle_class(const Gwi gwi, Type_Decl *td) {
+ DECL_OO(const Type, p, = known_type(gwi->gwion->env, td))
+ CHECK_BO(class_parent(gwi->gwion->env, p))
+ return p;
+}
+
ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str name, const m_str parent) {
struct ImportCK ck = { .name=name };
CHECK_BO(check_typename_def(gwi, &ck))
Tmpl* tmpl = ck.tmpl ? new_tmpl_base(gwi->gwion->mp, ck.tmpl) : NULL;
if(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;
- }
+ const Type base = find_type(gwi->gwion->env, td);
+ const Type_List tl = td->types;
+ if(GET_FLAG(base, unary))
+ td->types = NULL;
+ const Type p = !td->types ? handle_class(gwi, td) : NULL;
+ td->types = tl;
if(tmpl)
nspc_pop_type(gwi->gwion->mp, gwi->gwion->env->curr);
+ CHECK_OO(p)
const Type t = new_type(gwi->gwion->mp, ++gwi->gwion->env->scope->type_xid, s_name(ck.sym), p);
t->e->def = new_class_def(gwi->gwion->mp, 0, ck.sym, td, NULL, loc(gwi));
t->e->def->base.tmpl = tmpl;
}
static DTOR(array_dtor) {
- const Type t = !GET_FLAG(o->type_ref, nonnull) ?
- o->type_ref : o->type_ref->e->parent;
+ const Type t = unflag_type(o->type_ref);
if(*(void**)(o->data + SZ_INT))
xfree(*(void**)(o->data + SZ_INT));
struct M_Vector_* a = ARRAY(o);
if(!a)
return;
- if(t->array_depth > 1 || is_array(shred->info->vm->gwion->type, t))
+ if(t->nspc->info->class_data_size) {
for(m_uint i = 0; i < ARRAY_LEN(a); ++i)
- release(*(M_Object*)(ARRAY_PTR(a) + i * SZ_INT), shred);
+ (*(f_release**)t->nspc->info->class_data)(shred, array_base(t), ARRAY_PTR(a) + i * ARRAY_SIZE(a));
+ }
free_m_vector(shred->info->mp, a);
}
ANN void m_vector_rem(const M_Vector v, m_uint index) {
const m_uint size = ARRAY_SIZE(v);
- memmove(ARRAY_PTR(v) + index * size, ARRAY_PTR(v) + (index + 1) * size,
- (ARRAY_SIZE(v) - index - 1) *size);
+ if(index < ARRAY_LEN(v) - 1)
+ memmove(ARRAY_PTR(v) + index * size, ARRAY_PTR(v) + (index + 1) * size,
+ (ARRAY_SIZE(v) - index - 1) *size);
--ARRAY_LEN(v);
if(ARRAY_LEN(v) < ARRAY_CAP(v) / 2) {
const m_uint cap = ARRAY_CAP(v) /= 2;
const M_Vector v = ARRAY(o);
if(index < 0 || (m_uint)index >= ARRAY_LEN(v))
return;
- if(isa(o->type_ref, shred->info->vm->gwion->type[et_object]) > 0) {
- M_Object obj;
- m_vector_get(v, (vtype)index, &obj);
- release(obj,shred);
- }
+ const Type t = unflag_type(o->type_ref);
+ if(t->nspc->info->class_data_size)
+ (*(f_release**)t->nspc->info->class_data)(shred, array_base(t), ARRAY_PTR(v) + index * ARRAY_SIZE(v));
m_vector_rem(v, (vtype)index);
}
return GW_OK;
}
+INSTR(ArrayStruct) {
+ const M_Object ref = *(M_Object*)(REG(-SZ_INT * 5));
+ const m_int idx = (*(m_int*)((shred->reg -SZ_INT * 3)))++;
+ *(m_bit**)(shred->reg) = m_vector_addr(ARRAY(ref), idx);
+ shred->reg += SZ_INT; // regpush
+}
+
INSTR(ArrayBottom) {
*(M_Object*)(*(m_uint**)REG(-SZ_INT * 4))[(*(m_int*)REG(-SZ_INT * 3))++] = *(M_Object*)REG(-SZ_INT);
}
*num_obj *= *(m_uint*)REG(SZ_INT * curr);
++curr;
}
- return *num_obj > 0 ? (M_Object*)xcalloc(*num_obj, SZ_INT) : NULL;
+ return *num_obj > 0 ? (M_Object*)xcalloc(*num_obj, info->base->size) : NULL;
}
INSTR(ArrayAlloc) {
*(m_uint*) REG(-SZ_INT) = num_obj;
}
}
+
}
static GACK(gack_compound) {
- INTERP_PRINTF("%p", *(void**)VALUE);
+ INTERP_PRINTF("%p", VALUE);
}
#define mk_class_instr(op, arg0, arg1, ...) \
static INSTR(instr_class_##op) { \
return (Instr)GW_OK;
}
-ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td);
+ANN /*static*/ Type scan_class(const Env env, const Type t, const Type_Decl* td);
static Type opck_object_scan(const Env env, const struct TemplateScan *ts) {
if(ts->td->types)
return GW_OK;
}
-ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) {
+ANN 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->pos, _("invalid template types number"))
DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
return dot;
}
+ANN void struct_release(const VM_Shred shred, const Type base, const m_bit *ptr) {
+ const Vector types = &base->e->tuple->types;
+ const Vector offsets = &base->e->tuple->offset;
+ for(m_uint i = 0; i < vector_size(types); ++i) {
+ const Type t = (Type)vector_at(types, i);
+ if(isa(t, shred->info->vm->gwion->type[et_compound]) < 0)
+ continue;
+ const m_uint offset = vector_at(offsets, i);
+ if(!GET_FLAG(t, struct))
+ release(*(M_Object*)(ptr + offset), shred);
+ else
+ struct_release(shred, t, *(m_bit**)(ptr + offset));
+ }
+}
+
GWION_IMPORT(object_op) {
const Type t_null = gwi_mk_type(gwi, "@null", SZ_INT, "Object");
gwi->gwion->type[et_null] = t_null;
exp_setvar(bin->lhs, 1);
Type t = bin->lhs->info->type;
do {
+// t = unflag_type(t);
Type u = bin->rhs->info->type;
do {
+// u = unflag_type(u);
const m_str str = get_type_name(env, u, 1);
if(str && !strcmp(t->name, str))
- return bin->lhs->info->type;
+ return bin->lhs->info->type; // use rhs?
} while((u = u->e->parent));
} while((t = t->e->parent));
return env->gwion->type[et_null];
POP_REG(shred, SZ_INT)
const M_Object o = *(M_Object*)REG(0);
*(m_uint**)o->data = *(m_uint**)REG(-SZ_INT);
+ _release(o, shred);
}
static OP_CHECK(opck_ptr_deref) {
return instr;
}
+ANN Type scan_class(const Env env, const Type t, const Type_Decl* td);
+
+static DTOR(ptr_object_dtor) {
+ release(*(M_Object*)o->data, shred);
+}
+
+static DTOR(ptr_struct_dtor) {
+ const Type t = (Type)vector_front(&o->type_ref->e->tuple->types);
+ struct_release(shred, t, *(m_bit**)o->data);
+}
+
+static OP_CHECK(opck_ptr_scan) {
+ struct TemplateScan *ts = (struct TemplateScan*)data;
+ const Type t = (Type)scan_class(env, ts->t, ts->td);
+ const Type base = known_type(env, t->e->def->base.tmpl->call->td);
+ if(isa(base, env->gwion->type[et_compound]) > 0 && !t->nspc->dtor) {
+ t->nspc->dtor = new_vm_code(env->gwion->mp, NULL, SZ_INT, ae_flag_member | ae_flag_builtin, "@PtrDtor");
+ if(!GET_FLAG(t, struct))
+ t->nspc->dtor->native_func = (m_uint)ptr_object_dtor;
+ else
+ t->nspc->dtor->native_func = (m_uint)ptr_struct_dtor;
+ SET_FLAG(t, dtor);
+ }
+ return t;
+}
+
GWION_IMPORT(ptr) {
- const Type t_ptr = gwi_class_ini(gwi, "<~A~>Ptr", NULL);
+ const Type _t_ptr = gwi_class_ini(gwi, "@Ptr", NULL);
+ GWI_BB(gwi_class_end(gwi))
+ SET_FLAG(_t_ptr, unary);
+ GWI_BB(gwi_oper_ini(gwi, "@Ptr", NULL, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_ptr_scan))
+ GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
+ const Type t_ptr = gwi_class_ini(gwi, "<~A~>Ptr", "@Ptr");
+// 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))
const Type t = (Type)vector_at(&arg->t, i);
if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
release(*(M_Object*)(arg->d + offset), shred);
+ else if(GET_FLAG(t, struct))
+ struct_release(shred, t, *(m_bit**)(arg->d + offset));
offset += t->size;
}
}
ANN static Type check_prim_interp(const Env env, const Exp* exp) {
CHECK_OO(check_exp(env, *exp))
- Exp e = *exp;
- do if(GET_FLAG(e->info->type, struct) && !GET_FLAG(e->info->type, builtin))
- exp_setvar(e, 1);
- while((e = e->next));
return env->gwion->type[et_string];
}
if(td->array)
CHECK_BB(check_subscripts(env, td->array, 1))
if(parent->e->def && !GET_FLAG(parent, check))
- CHECK_BB(scanx_parent(parent, check_cdef, env))
+ CHECK_BB(ensure_check(env, parent))
if(GET_FLAG(parent, typedef))
SET_FLAG(cdef->base.type, typedef);
return GW_OK;
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
if(cdef->base.tmpl && cdef->base.tmpl->list)
CHECK_BB(template_push_types(env, cdef->base.tmpl))
- const m_bool ret = scanx_parent(cdef->base.type, check_parent, env);
+ const m_bool ret = check_parent(env, cdef);
if(cdef->base.tmpl && cdef->base.tmpl->list)
nspc_pop_type(env->gwion->mp, env->curr);
return ret;
return GW_OK;
const Type t = cdef->base.type;
if(t->e->owner_class && !GET_FLAG(t->e->owner_class, check))
- CHECK_BB(check_class_def(env, t->e->owner_class->e->def))
+ CHECK_BB(ensure_check(env, t->e->owner_class))
if(GET_FLAG(t, check))return GW_OK;
SET_FLAG(t, check);
if(cdef->base.ext)
if(isa(parent, env->gwion->type[et_object]) < 0)
ERR_B(pos, _("cannot extend primitive type '%s'"), parent->name)
if(parent->e->def && !GET_FLAG(parent, scan1))
- CHECK_BB(scanx_parent(parent, scan1_cdef, env))
+ CHECK_BB(ensure_scan1(env, parent))
if(type_ref(parent))
ERR_B(pos, _("can't use ref type in class extend"))
if(GET_FLAG(parent, nonnull))
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
if(cdef->base.tmpl && cdef->base.tmpl->list)
CHECK_BB(template_push_types(env, cdef->base.tmpl))
- const m_bool ret = scanx_parent(cdef->base.type, scan1_parent, env);
+ const m_bool ret = scan1_parent(env, cdef);
if(cdef->base.tmpl && cdef->base.tmpl->list)
nspc_pop_type(env->gwion->mp, env->curr);
return ret;
ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) {
const Type parent = cdef->base.type->e->parent;
-// if(parent->e->def && !GET_FLAG(parent, scan2))
if(parent->e->def && !GET_FLAG(parent, scan2))
- CHECK_BB(scanx_parent(parent, scan2_cdef, env))
+ CHECK_BB(ensure_scan2(env, parent))
if(cdef->base.ext->array)
CHECK_BB(scan2_exp(env, cdef->base.ext->array->exp))
return GW_OK;
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
if(cdef->base.tmpl && cdef->base.tmpl->list)
CHECK_BB(template_push_types(env, cdef->base.tmpl))
- const m_bool ret = scanx_parent(cdef->base.type, scan2_parent, env);
+// const m_bool ret = scanx_parent(cdef->base.type, scan2_parent, env);
+ const m_bool ret = scan2_parent(env, cdef);
if(cdef->base.tmpl && cdef->base.tmpl->list)
nspc_pop_type(env->gwion->mp, env->curr);
return ret;
const Type t = cdef->base.type;
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))
+ CHECK_BB(ensure_scan2(env, t->e->owner_class))
SET_FLAG(t, scan2);
if(cdef->base.ext)
CHECK_BB(cdef_parent(env, cdef))
struct EnvSet es = { .env=env, .data=env,
.scope=env->scope->depth, .flag=ae_flag_none };
envset_push(&es, owner, owner->nspc);
- (void)env_push(env, owner, owner->nspc);
+ (void)env_push(env, owner, owner->nspc);// TODO: is this needed?
const Type ret = scan_type(env, t, td->next);
env_pop(env, es.scope);
if(es.run)
*(m_uint*)(shred->mem + SZ_INT*3) = shred->pc;
*(m_uint*)(shred->mem + SZ_INT*4) = SZ_INT;
shred->mem += SZ_INT*5;
- *(M_Object*)(shred->mem) = *(M_Object*)(shred->reg - SZ_INT);
shred->pc = 0;
}
POP_REG(shred, sz);
} else {
prepare_call(shred, offset);
+ if(GET_FLAG(t, struct))
+ *(void**)(shred->mem) = (void*)(shred->reg - t->size);
+ else
+ *(M_Object*)(shred->mem) = *(M_Object*)(shred->reg - SZ_INT);
shred->code = code;
}
return;
*(m_bit**)(reg-SZ_INT) = *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
DISPATCH()
structmemberfloat:
+printf("struct: %p\n", *(m_bit**)(reg-SZ_INT));
*(m_bit**)(reg-SZ_INT) = *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
DISPATCH()
structmemberother:
reg += SZ_FLOAT;
DISPATCH()
allocother:
+puts("here!!!");
// LOOP_OPTIM
for(m_uint i = 0; i <= VAL2; i += SZ_INT)
*(m_uint*)(reg+i) = (*(m_uint*)(mem+VAL+i) = 0);