fun void test<~A~>(...) {
vararg.start;
- <<< vararg.i >>>;
+ <<< vararg $ int >>>;
vararg.end;
}
test<~int~>(1, 2);
vararg.start;
if(i == 0)
- <<< vararg.i >>>;
+ <<< vararg $ int >>>;
else if(i == 1)
- <<< vararg.f >>>;
+ <<< vararg $ float >>>;
else if(i == 2)
- <<< vararg.c >>>;
+ <<< vararg $ complex >>>;
else if(i == 3)
- <<< vararg.p >>>;
+ <<< vararg $ polar >>>;
else if(i == 4)
- <<< vararg.v3 >>>;
+ <<< vararg $ Vec3 >>>;
else if(i == 5)
- <<< vararg.v4 >>>;
+ <<< vararg $ Vec4 >>>;
else if(i == 6)
- <<< vararg.o >>>;
+ <<< vararg $ Object >>>;
i++;
vararg.end;
}
ANN m_uint emit_code_offset(const Emitter emit);
ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj);
ANN Instr emit_exp_spork(const Emitter, const Exp_Unary*);
+ANN m_bool emit_exp(const Emitter, const Exp, const m_bool add_ref);
+ANN static inline void emit_except(const Emitter emit, const Type t) {
+ emit_add_instr(emit, !GET_FLAG(t, nonnull) ? GWOP_EXCEPT : SetObj);
+}
+
#endif
INSTR(VarargIni);
INSTR(VarargTop);
INSTR(VarargEnd);
-INSTR(VarargMember);
INSTR(VecCpy);
INSTR(VecMember);
#define __VARARG
struct Vararg_ {
m_uint* k; // sizes
+ Type* t; // types
m_bit* d; // d(ata)
m_uint o, i, s; // o(ffset), i(ndex), s(ize)
};
return l->is_obj ? (m_int)l->offset : frame_pop(frame);
}
-ANN static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool add_ref);
+ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool add_ref);
ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop);
ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list);
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member);
while(e) {
if(!l) {
size += e->type->size;
- vector_add(kinds, e->type->size);
+ vector_add(kinds, (vtype)e->type); // ->size
} else
l = l->next;
e = e->next;
return op_emit_bool(emit, &opi);
}
-ANN static m_bool is_special(const Emitter emit, const Type t) {
- if(isa(t, emit->gwion->type[et_complex]) > 0 || isa(t, emit->gwion->type[et_polar]) > 0 ||
- isa(t, emit->gwion->type[et_vec3]) > 0 || isa(t, emit->gwion->type[et_vec4]) > 0 ||
- isa(t, emit->gwion->type[et_vararg]) > 0)
- return GW_OK;
- return GW_ERROR;
+ANN static inline m_bool is_special(const Emitter emit, const Type t) {
+ return isa(t, emit->gwion->type[et_object]) < 0 &&
+ isa(t, emit->gwion->type[et_class]) < 0 ?
+ GW_OK : GW_ERROR;
}
ANN static inline m_bool traverse_emit_func_def(const Emitter emit, const Func_Def fdef) {
DECL_EXP_FUNC(emit, m_bool, Emitter)
-ANN2(1) static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) {
+ANN2(1) /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) {
do {
CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
if(ref && isa(exp->type, emit->gwion->type[et_object]) > 0) {
vector_set(&emit->info->variadic, vector_size(&emit->info->variadic) -1, (vtype)instr);
return GW_OK;
}
+
ANN static inline Instr get_variadic(const Emitter emit) {
return (Instr)vector_back(&emit->info->variadic);
}
emit_vararg_end(emit, offset);
return GW_OK;
}
- if(!get_variadic(emit))
- ERR_B(exp_self(member)->pos, _("vararg.%s used before vararg.start"), s_name(member->xid))
- if(GET_FLAG(emit->env->func, empty))
- ERR_B(exp_self(member)->pos, _("vararg.%s used after vararg.end"), s_name(member->xid))
- const Instr instr = emit_add_instr(emit, VarargMember);
- instr->m_val = offset;
- instr->m_val2 = exp_self(member)->type->size;
- return GW_OK;
+// should not be reached now
+ return GW_ERROR;
}
ANN static m_bool emit_exp_dot_special(const Emitter emit, const Exp_Dot* member) {
return emit_exp_dot_special(emit, member);
const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid);
if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
-(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type)))
-) {
+ (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 &&
+ !is_fptr(emit->gwion, exp_self(member)->type)))) {
CHECK_BB(emit_exp(emit, member->base, 0))
- emit_add_instr(emit, GWOP_EXCEPT);
-
-// emit_except(emit, member->t_base);
+ emit_except(emit, member->t_base);
}
if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type))
return emit_member_func(emit, member);
#include "traverse.h"
#include "parse.h"
#include "gwi.h"
+#include "emit.h"
struct M_Vector_ {
m_bit* ptr;
const Type t_void = gwi_mk_type(gwi, "void", 0, NULL);
GWI_BB(gwi_gack(gwi, t_void, gack_void))
GWI_BB(gwi_set_global_type(gwi, t_void, et_void))
- const Type t_null = gwi_mk_type(gwi, "@null", SZ_INT, NULL);
- GWI_BB(gwi_set_global_type(gwi, t_null, et_null))
const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
GWI_BB(gwi_gack(gwi, t_function, gack_function))
GWI_BB(gwi_set_global_type(gwi, t_function, et_function))
}
GWION_IMPORT(object) {
-const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
-gwi_add_type(gwi, t_object);
+ const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
+ gwi_add_type(gwi, t_object);
GWI_BB(gwi_gack(gwi, t_object, gack_object))
-//assert(GET_FLAG(t_object, checked));
SET_FLAG(t_object, checked); // should be set by gwi_add_type
gwi->gwion->type[et_object] = t_object;
+ const Type t_null = gwi_mk_type(gwi, "@null", SZ_INT, "Object");
+ gwi->gwion->type[et_null] = t_null;
+ GWI_BB(gwi_set_global_type(gwi, t_null, et_null))
GWI_BB(gwi_oper_cond(gwi, "Object", BranchEqInt, BranchNeqInt))
GWI_BB(gwi_oper_ini(gwi, "@null", "Object", "Object"))
GWI_BB(gwi_oper_add(gwi, at_object))
GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj))
GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
GWI_BB(gwi_oper_ini(gwi, "Object", "@null", "int"))
+// GWI_BB(gwi_oper_add(gwi, opck_object_cast))
+// GWI_BB(gwi_oper_emi(gwi, opem_object_cast))
+// GWI_BB(gwi_oper_end(gwi, "$", NULL))
GWI_BB(gwi_oper_end(gwi, "==", EqObject))
GWI_BB(gwi_oper_end(gwi, "!=", NeqObject))
GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool"))
#include "object.h"
#include "parse.h"
#include "tuple.h"
+#include "array.h"
struct TupleEmit {
Exp e;
#include "specialid.h"
#include "traverse.h"
#include "parse.h"
+#include "gack.h"
void free_vararg(MemPool p, struct Vararg_* arg) {
xfree(arg->d);
xfree(arg->k);
+ xfree(arg->t);
mp_free(p, Vararg, arg);
}
const Vector kinds = (Vector)instr->m_val2;
arg->s = vector_size(kinds);
arg->k = (m_uint*)xmalloc(arg->s * SZ_INT);
- for(m_uint i = 0; i < arg->s; ++i)
- *(m_uint*)(arg->k + i) = vector_at(kinds, i);
+ 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;
}
free_vararg(shred->info->mp, arg);
}
-INSTR(VarargMember) {
+static OP_CHECK(opck_vararg_cast) {
+ const Exp_Cast* cast = (Exp_Cast*)data;
+ const Type t = known_type(env, cast->td);
+//puts(t->name);
+ return t;
+}
+
+static INSTR(VarargCast) {
struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val);
- if(instr->m_val2 != arg->k[arg->i]) { // TODO: differnciate object and primitives
- free_vararg(shred->info->mp, arg);
- Except(shred, "InvalidVariadicAccess");
+ 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 < instr->m_val2; i += SZ_INT)
- *(m_uint*)REG(i) = *(m_uint*)(arg->d + arg->o + i);
- PUSH_REG(shred, instr->m_val2);
+// POP_REG(shred, SZ_INT);
+ 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);
+}
+
+ANN static inline Instr get_variadic(const Emitter emit) {
+ return (Instr)vector_back(&emit->info->variadic);
+}
+
+ANN m_bool variadic_check(const Emitter emit, const loc_t pos) {
+ const Env env = emit->env;
+ if(!get_variadic(emit))
+ ERR_B(pos, _("vararg.xxx used before vararg.start"))
+ if(GET_FLAG(emit->env->func, empty))
+ ERR_B(pos, _("vararg.xxx used after vararg.end"))
+ return GW_OK;
+}
+
+static OP_EMIT(opem_vararg_cast) {
+ const Exp_Cast* cast = (Exp_Cast*)data;
+ CHECK_BO(variadic_check(emit, cast->exp->pos))
+ const Instr instr = emit_add_instr(emit, VarargCast);
+ const Instr variadic = (Instr)vector_back(&emit->info->variadic);
+ instr->m_val = variadic->m_val;
+ const Type t = known_type(emit->env, cast->td);
+ instr->m_val2 = (m_uint)t;
+ return instr;
}
static OP_CHECK(at_varobj) {
ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function"))
}
+static GACK(gack_vararg) {
+ INTERP_PRINTF("%p\n", *(M_Object*)VALUE);
+}
+
GWION_IMPORT(vararg) {
const Type t_varobj = gwi_mk_type(gwi, "VarObject", SZ_INT, "Object");
SET_FLAG(t_varobj, abstract);
const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", SZ_INT, NULL);
GWI_BB(gwi_add_type(gwi, t_varobj))
GWI_BB(gwi_set_global_type(gwi, t_varloop, et_varloop))
- const Type t_vararg = gwi_class_ini(gwi, "@Vararg", NULL);
+ const Type t_vararg = gwi_class_spe(gwi, "@Vararg", 0);
+ gwi_gack(gwi, t_vararg, gack_vararg);
gwi->gwion->type[et_vararg] = t_vararg; // use func
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_BB(gwi_union_add(gwi, "int", "i"))
- GWI_BB(gwi_union_add(gwi, "float", "f"))
- GWI_BB(gwi_union_add(gwi, "time", "t"))
- GWI_BB(gwi_union_add(gwi, "dur", "d"))
- GWI_BB(gwi_union_add(gwi, "complex", "c"))
- GWI_BB(gwi_union_add(gwi, "polar", "p"))
- GWI_BB(gwi_union_add(gwi, "Vec3", "v3"))
- GWI_BB(gwi_union_add(gwi, "Vec4", "v4"))
- GWI_BB(gwi_union_add(gwi, "VarObject", "o"))
GWI_OB(gwi_union_end(gwi, ae_flag_const))
GWI_BB(gwi_class_end(gwi))
GWI_BB(gwi_oper_ini(gwi, "VarObject", "Object", NULL))
GWI_BB(gwi_oper_ini(gwi, "Object", "VarObject", NULL))
GWI_BB(gwi_oper_add(gwi, at_varobj))
GWI_BB(gwi_oper_end(gwi, "@=>", VarargAssign))
+ 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_register_freearg(gwi, VarargIni, freearg_vararg);
struct SpecialId_ spid = { .type=t_vararg, .exec=RegPushImm, .is_const=1, .ck=idck_vararg};
gwi_specialid(gwi, "vararg", &spid);
return check_internal(env, sym, e, t);
}
-
ANN m_bool check_subscripts(Env env, const Array_Sub array) {
CHECK_OB(check_exp(env, array->exp))
m_uint depth = 0;
#include "instr.h"
#include "emit.h"
#include "operator.h"
+#include "object.h"
+#include "array.h"
typedef Type (*f_type)(const Env env, const Exp exp);
fun void test(...) {
vararg.start;
vararg.end;
- vararg.i;
+ vararg $ int;
}
#! [contains] used before
fun void test(...) {
- vararg.i;
+ vararg $ int;
}
#! [contains] InvalidVariadicAccess
fun void test(...) {
vararg.start;
- <<<vararg.i>>>;
+ <<<vararg $ int >>>;
vararg.end;
}
Vec3(1.3) => test;
fun void test(...) {
<<< this, " ", __func__ >>>;
vararg.start;
- <<< vararg.i >>>;
+ <<< vararg $ int >>>;
vararg.end;
}
fun int test(...){
vararg.start;
- <<< "test" >>>;
- <<< vararg.i >>>;
+ <<< "test" >>>;
+ <<< vararg $ int >>>;
vararg.end;
return 1;
}
fun void test(...) {
Object o;
vararg.start;
- vararg.o @=> o;
+ vararg $ Object @=> o;
vararg.end;
}