instr->m_val2 = size;
}
+ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
OP_CHECK(opck_object_dot) {
const Exp_Dot *member = (Exp_Dot*)data;
- const Value value = find_value(actual_type(env->gwion, member->t_base), member->xid);
+ const m_str str = s_name(member->xid);
+ const m_bool base_static = is_class(env->gwion, member->t_base);
+ const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base;
+ if(!the_base->nspc)
+ ERR_O(member->base->pos,
+ _("type '%s' does not have members - invalid use in dot expression of %s"),
+ the_base->name, str)
+ if(member->xid == insert_symbol(env->gwion->st, "this") && base_static)
+ ERR_O(exp_self(member)->pos,
+ _("keyword 'this' must be associated with object instance..."))
+ const Value value = find_value(the_base, member->xid);
+ if(!value) {
+ env_err(env, exp_self(member)->pos,
+ _("class '%s' has no member '%s'"), the_base->name, str);
+ if(member->t_base->nspc)
+ did_you_mean_type(the_base, str);
+ return NULL;
+ }
+ CHECK_BO(not_from_owner_class(env, the_base, value, exp_self(member)->pos))
+ if(!env->class_def || isa(env->class_def, value->from->owner_class) < 0) {
+ if(GET_FLAG(value, private))
+ ERR_O(exp_self(member)->pos,
+ _("can't access private '%s' outside of class..."), value->name)
+ else if(GET_FLAG(value, protect))
+ exp_self(member)->meta = ae_meta_protect;
+ }
+ if(base_static && GET_FLAG(value, member))
+ ERR_O(exp_self(member)->pos,
+ _("cannot access member '%s.%s' without object instance..."),
+ the_base->name, str)
+ if(GET_FLAG(value, const) || GET_FLAG(value, enum))
+ exp_self(member)->meta = ae_meta_value;
return value->type;
}
void free_vararg(MemPool p, struct Vararg_* arg) {
xfree(arg->d);
- xfree(arg->k);
xfree(arg->t);
mp_free(p, Vararg, arg);
}
-INSTR(VarargTop) {
- struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val);
- if(arg) {
- assert(arg->d);
- PUSH_REG(shred, SZ_INT)
- } else
- shred->pc = instr->m_val2 + 1;
-}
-
INSTR(VarargIni) {
struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
POP_REG(shred, instr->m_val - SZ_INT)
*(m_uint*)(arg->d + i) = *(m_uint*)(shred->reg - SZ_INT + i);
const Vector kinds = (Vector)instr->m_val2;
arg->s = vector_size(kinds);
- arg->k = (m_uint*)xmalloc(arg->s * SZ_INT);
arg->t = (Type*)xmalloc(arg->s * SZ_INT);
for(m_uint i = 0; i < arg->s; ++i) {
const Type t = (Type)vector_at(kinds, i);
*(Type*)(arg->t + i) = t;
- *(m_uint*)(arg->k + i) = t->size;
}
*(struct Vararg_**)REG(-SZ_INT) = arg;
}
-INSTR(VarargEnd) {
- struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val);
- PUSH_REG(shred, SZ_INT);
- arg->o += arg->k[arg->i];
+static INSTR(VarargEnd) {
+ struct Vararg_* arg = *(struct Vararg_**)REG(0);
+ arg->o += arg->t[arg->i]->size;
if(++arg->i < arg->s)
- shred->pc = instr->m_val2;
+ shred->pc = instr->m_val;
else
free_vararg(shred->info->mp, arg);
}
}
static INSTR(VarargCast) {
- struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val);
+ struct Vararg_* arg = *(struct Vararg_**)REG(-SZ_INT);
const Type t = (Type)instr->m_val2;
if(isa(arg->t[arg->i], t) < 0){
free_vararg(shred->info->mp, arg);
Except(shred, "InvalidVariadicAccess");
}
for(m_uint i = 0; i < t->size; i += SZ_INT)
- *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + arg->o + i);
- PUSH_REG(shred, t->size - SZ_INT);
+ *(m_uint*)REG(i - SZ_INT*2) = *(m_uint*)(arg->d + arg->o + i);
}
ANN static inline Instr get_variadic(const Emitter emit) {
static OP_EMIT(opem_vararg_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
CHECK_BO(variadic_check(emit, cast->exp->pos))
+ CHECK_BO(emit_exp(emit, cast->exp, 0))
const Instr instr = emit_add_instr(emit, VarargCast);
instr->m_val = get_variadic(emit)->m_val;
instr->m_val2 = (m_uint)exp_self(cast)->type;
+ const Instr pop = emit_add_instr(emit, RegPush);
+ pop->m_val = exp_self(cast)->type->size - SZ_INT *2;
return instr;
}
ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function"))
}
+static ID_EMIT(idem_vararg) {
+ const Instr instr = emit_add_instr(emit, RegPushMem);
+ instr->m_val = emit->code->stack_depth - SZ_INT;
+ return instr;
+}
+
static GACK(gack_vararg) {
- INTERP_PRINTF("%p\n", *(M_Object*)VALUE);
+ INTERP_PRINTF("%p", *(M_Object*)VALUE);
}
ANN static inline m_uint emit_code_size(const Emitter emit) {
return vector_size(&emit->code->instr);
}
ANN static m_bool emit_vararg_start(const Emitter emit, const m_uint offset) {
- const Instr instr = emit_add_instr(emit, VarargTop);
- instr->m_val = offset;
- instr->m_val2 = emit_code_size(emit);
+ const Instr instr = emit_add_instr(emit, BranchEqInt);
+ instr->m_val = emit_code_size(emit);
vector_set(&emit->info->variadic, vector_size(&emit->info->variadic) -1, (vtype)instr);
return GW_OK;
}
ANN static void emit_vararg_end(const Emitter emit, const m_uint offset) {
+ const Instr pop = emit_add_instr(emit, RegPop);
+ pop->m_val = SZ_INT;
const Instr instr = emit_add_instr(emit, VarargEnd),
variadic = get_variadic(emit);
- instr->m_val = offset;
- instr->m_val2 = variadic->m_val2;
- variadic->m_val2 = emit_code_size(emit);
+ instr->m_val = variadic->m_val;
+ variadic->m_val = emit_code_size(emit);
SET_FLAG(emit->env->func, empty);// mark vararg func as complete
}
+static OP_CHECK(opck_vararg_dot) {
+ const Exp_Dot *member = (Exp_Dot*)data;
+ const m_str str = s_name(member->xid);
+ if(!strcmp(str, "start") || !strcmp(str, "end"))
+ return env->gwion->type[et_varloop];
+ ERR_O(exp_self(member)->pos, _("'%s' is not a vararg keyword."), str)
+}
+
static OP_EMIT(opem_vararg_dot) {
const Env env = emit->env;
const Exp_Dot *member = (Exp_Dot*)data;
- m_uint offset = emit->env->class_def ? SZ_INT : 0;
- Arg_List l = emit->env->func->def->base->args;
const m_str str = s_name(member->xid);
- while(l) {
- offset += l->type->size;
- l = l->next;
- }
- if(!strcmp(str, "start")) {
+ const m_uint offset = emit->code->stack_depth - SZ_INT;
+ CHECK_BO(emit_exp(emit, member->base, 0))
+ if(str[0] == 's') {
if(get_variadic(emit))
ERR_O(exp_self(member)->pos, _("vararg.start already used"))
emit_vararg_start(emit, offset);
return (Instr)GW_OK;
}
- assert(!strcmp(str, "end"));
if(!get_variadic(emit))
ERR_O(exp_self(member)->pos, _("vararg.start not used before vararg.end"))
emit_vararg_end(emit, offset);
OP_CHECK(opck_object_dot);
GWION_IMPORT(vararg) {
- const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", SZ_INT, NULL);
+ const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", 0, NULL);
GWI_BB(gwi_set_global_type(gwi, t_varloop, et_varloop))
- const Type t_vararg = gwi_class_spe(gwi, "@Vararg", 0);
+ const Type t_vararg = gwi_mk_type(gwi, "@Vararg", SZ_INT, NULL);
gwi_gack(gwi, t_vararg, gack_vararg);
- GWI_BB(gwi_union_ini(gwi, NULL, NULL))
- GWI_BB(gwi_union_add(gwi, "@VarLoop", "start"))
- GWI_BB(gwi_union_add(gwi, "@VarLoop", "end"))
- GWI_OB(gwi_union_end(gwi, ae_flag_const))
- GWI_BB(gwi_class_end(gwi))
+// gwi_gack(gwi, t_varloop, gack_vararg);// ????
+ GWI_BB(gwi_add_type(gwi, t_vararg))
GWI_BB(gwi_oper_ini(gwi, "@Vararg", (m_str)OP_ANY_TYPE, NULL))
- GWI_BB(gwi_oper_add(gwi, opck_object_dot))
+ GWI_BB(gwi_oper_add(gwi, opck_vararg_dot))
GWI_BB(gwi_oper_emi(gwi, opem_vararg_dot))
GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
- GWI_BB(gwi_oper_ini(gwi, "@Vararg", (m_str)OP_ANY_TYPE, NULL))
GWI_BB(gwi_oper_add(gwi, opck_vararg_cast))
GWI_BB(gwi_oper_emi(gwi, opem_vararg_cast))
- GWI_BB(gwi_oper_end(gwi, "$", VarargCast))
+ GWI_BB(gwi_oper_end(gwi, "$", NULL))
gwi_register_freearg(gwi, VarargIni, freearg_vararg);
- struct SpecialId_ spid = { .type=t_vararg, .exec=RegPushImm, .is_const=1, .ck=idck_vararg};
+ struct SpecialId_ spid = { .type=t_vararg, .is_const=1, .ck=idck_vararg, .em=idem_vararg};
gwi_specialid(gwi, "vararg", &spid);
return GW_OK;
}
return op_check(env, &opi);
}
-ANN static inline m_bool not_from_owner_class(const Env env, const Type t,
+ANN m_bool not_from_owner_class(const Env env, const Type t,
const Value v, const loc_t pos) {
if(!v->from->owner_class || isa(t, v->from->owner_class) < 0) {
ERR_B(pos,
ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
-ANN static Type check_dot(const Env env, const Value v, const Exp_Dot *member) {
- struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
- .rhs=v->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
+ANN static Type check_dot(const Env env, const Exp_Dot *member) {
+ struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
return op_check(env, &opi);
}
prim_exp(data)->meta = ae_meta_value;
if(v->from->owner_class) {
const Exp exp = symbol_owned_exp(env->gwion, data);
- const Type ret = check_dot(env, v, &exp->d.exp_dot);
+ const Type ret = check_dot(env, &exp->d.exp_dot);
prim_exp(data)->nspc = exp->nspc;
free_exp(env->gwion->mp, exp);
CHECK_OO(ret);
}
ANN static Type check_exp_dot(const Env env, Exp_Dot* member) {
- const m_str str = s_name(member->xid);
CHECK_OO((member->t_base = check_exp(env, member->base)))
- const m_bool base_static = is_class(env->gwion, member->t_base);
- const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base;
- if(!the_base->nspc)
- ERR_O(member->base->pos,
- _("type '%s' does not have members - invalid use in dot expression of %s"),
- the_base->name, str)
- if(member->xid == insert_symbol("this") && base_static)
- ERR_O(exp_self(member)->pos,
- _("keyword 'this' must be associated with object instance..."))
- const Value value = find_value(the_base, member->xid);
- if(!value) {
- env_err(env, exp_self(member)->pos,
- _("class '%s' has no member '%s'"), the_base->name, str);
- if(member->t_base->nspc)
- did_you_mean_type(the_base, str);
- return NULL;
- }
- CHECK_BO(not_from_owner_class(env, the_base, value, exp_self(member)->pos))
- if(!env->class_def || isa(env->class_def, value->from->owner_class) < 0) {
- if(GET_FLAG(value, private))
- ERR_O(exp_self(member)->pos,
- _("can't access private '%s' outside of class..."), value->name)
- else if(GET_FLAG(value, protect))
- exp_self(member)->meta = ae_meta_protect;
- }
- if(base_static && GET_FLAG(value, member))
- ERR_O(exp_self(member)->pos,
- _("cannot access member '%s.%s' without object instance..."),
- the_base->name, str)
- if(GET_FLAG(value, const) || GET_FLAG(value, enum))
- exp_self(member)->meta = ae_meta_value;
-// prim_self(member)->value = value;
- CHECK_OO(check_dot(env, value, member))
- return value->type;
+ return check_dot(env, member);
}
ANN m_bool check_type_def(const Env env, const Type_Def tdef) {