<<< 1 => v.y >>>;
<<< 1 => v.z >>>;
<<< 1 => v.w >>>;
-<<< Vec3(.1, .2, .4, .5) => v >>>;
+<<< Vec4(.1, .2, .4, .5) => v >>>;
<<< "set ", v.set(1,2,3,4) >>>;
<<< "setAll ", v.setAll(1.2) >>>;
#ifndef __ARRAY
#define __ARRAY
+
+struct ArrayAccessInfo {
+ struct Array_Sub_ array;
+ const Type type;
+ const m_bool is_var;
+};
+
typedef struct M_Vector_ * M_Vector;
typedef struct ArrayInfo_ {
m_int depth;
ANN void m_vector_rem(const M_Vector, const m_uint);
ANEW M_Vector new_m_vector(MemPool, const m_uint size, const m_uint len);
ANN void free_m_vector(MemPool, M_Vector);
+ANN Type check_array_access(const Env env, const Array_Sub array);
+ANN m_bool emit_array_access(const Emitter emit, struct ArrayAccessInfo *const info);
#endif
ANN static inline void emit_except(const Emitter emit, const Type t) {
emit_add_instr(emit, !GET_FLAG(t, nonnull) ? GWOP_EXCEPT : SetObj);
}
-
#endif
ANN m_uint get_depth(const Type type);
typedef enum {
- et_void, et_int, et_bool, et_char, et_float, et_complex, et_polar, et_vec3, et_vec4,
+ et_void, et_int, et_bool, et_char, et_float,
et_null, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack,
- et_function, et_fptr, et_varloop, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto, et_tuple,
+ et_function, et_fptr, et_varloop, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto,
MAX_TYPE
} type_enum;
#endif
__attribute__((returns_nonnull))
ANN Type get_type(const Type t);
-ANN m_bool check_subscripts(const Env, const Array_Sub);
+ANN m_bool check_subscripts(const Env, const Array_Sub, const m_bool is_decl);
+ANN m_bool check_implicit(const Env env, const Exp e, const Type t);
#endif
return size == SZ_INT ? KIND_INT : size == SZ_FLOAT ? KIND_FLOAT : KIND_OTHER;
}
-ANN static Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]) {
+ANN /*static */Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]) {
const enum Kind kind = kindof(size, addr);
const Instr instr = emit_add_instr(emit, func[kind]);
instr->m_val2 = size;
static const f_instr regpushmem[] = { RegPushMem, RegPushMem2, RegPushMem3, RegPushMem4 };
static const f_instr regpushbase[] = { RegPushBase, RegPushBase2, RegPushBase3, RegPushBase4 };
static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm };
-static const f_instr dotmember[] = { DotMember, DotMember2, DotMember3, DotMember4 };
static const f_instr allocmember[] = { RegPushImm, RegPushImm2, RegPushImm3, AllocMember4 };
static const f_instr allocword[] = { AllocWord, AllocWord2, AllocWord3, RegPushMem4 };
-ANN static inline Exp this_exp(const Emitter emit, const Type t, const loc_t pos) {
- const Exp exp = new_prim_id(emit->gwion->mp, insert_symbol("this"),
- loc_cpy(emit->gwion->mp, pos));
- exp->type = t;
- return exp;
-}
-
-ANN static inline Exp dot_this_exp(const Emitter emit, const Symbol *data, const Type t) {
- const Exp exp = this_exp(emit, t, prim_pos(data));
- const Exp dot = new_exp_dot(emit->gwion->mp, exp, *data);
- dot->d.exp_dot.t_base = t;
- return dot;
-}
-
-ANN static inline Exp dot_static_exp(const Emitter emit, const Symbol *data, const Type t) {
- const Symbol s = insert_symbol(t->name);
- const Exp e = new_prim_id(emit->gwion->mp, s,
- loc_cpy(emit->gwion->mp, prim_pos(data)));
- const Value val = nspc_lookup_value1(t->nspc->parent, s);
- const Exp dot = new_exp_dot(emit->gwion->mp, e, *data);
- dot->d.exp_dot.t_base = val->type;
- return dot;
-}
-
+ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
ANN static m_bool emit_symbol_owned(const Emitter emit, const Symbol *data) {
- const Value v = prim_self(data)->value;
- const Exp dot = (!GET_FLAG(v, static) ? dot_this_exp : dot_static_exp)(emit, data, v->from->owner_class);
- dot->type = prim_exp(data)->type;
- dot->emit_var = prim_exp(data)->emit_var;
+ const Exp dot = symbol_owned_exp(emit->gwion, data);
+ dot->nspc = prim_exp(data)->nspc;
const m_bool ret = emit_exp_dot(emit, &dot->d.exp_dot);
free_exp(emit->gwion->mp, dot);
return ret;
return GW_OK;
}
-ANN static void array_loop(const Emitter emit, const m_uint depth) {
- regpop(emit, depth * SZ_INT);
- emit_add_instr(emit, GWOP_EXCEPT);
- for(m_uint i = 0; i < depth - 1; ++i) {
- const Instr access = emit_add_instr(emit, ArrayAccess);
- access->m_val = i;
- const Instr get = emit_add_instr(emit, ArrayGet);
- get->m_val = i;
- get->m_val2 = -SZ_INT;
- emit_add_instr(emit, GWOP_EXCEPT);
- }
- regpop(emit, SZ_INT);
- const Instr access = emit_add_instr(emit, ArrayAccess);
- access->m_val = depth;
-}
-
-ANN static void array_finish(const Emitter emit, const m_uint depth,
- const m_uint size, const m_bool is_var) {
- const Instr get = emit_add_instr(emit, is_var ? ArrayAddr : ArrayGet);
- get->m_val = depth;
- const Instr push = emit_add_instr(emit, ArrayValid);
- push->m_val = is_var ? SZ_INT : size;
-}
-
-ANN static inline m_bool array_do(const Emitter emit, const Array_Sub array, const m_bool is_var) {
- emit_add_instr(emit, GcAdd);
- CHECK_BB(emit_exp(emit, array->exp, 0))
- array_loop(emit, array->depth);
- array_finish(emit, array->depth, array->type->size, is_var);
- return GW_OK;
-}
-
-ANN static inline void tuple_access(const Emitter emit, const m_uint idx,
- const m_bool is_var) {
- const Instr instr = emit_add_instr(emit, TupleMember);
- instr->m_val = idx;
- instr->m_val2 = is_var;
- emit_add_instr(emit, DotMember); // just a place holder.
-}
-
-struct ArrayAccessInfo {
- struct Array_Sub_ array;
- const Type type;
- const m_bool is_var;
-};
-
-ANN static inline m_bool _emit_indexes(const Emitter emit, struct ArrayAccessInfo *const info);
-
-ANN void emit_except(const Emitter emit, const Type t) {
- if(!GET_FLAG(t, nonnull))
- emit_add_instr(emit, GWOP_EXCEPT);
- else
- emit_add_instr(emit, SetObj);
-}
-
-ANN static inline m_bool tuple_index(const Emitter emit, struct ArrayAccessInfo *const info) {
- assert(isa(info->array.type, emit->gwion->type[et_tuple]) > 0);
- const m_uint idx = info->array.exp->d.prim.d.num;
- emit_except(emit, info->array.type);
- tuple_access(emit, info->array.exp->d.prim.d.num, (info->array.depth -1)? 0 : info->is_var);
- if(!info->array.exp->next)
- return GW_OK;
- const Type type = (Type)vector_at(&info->array.type->e->tuple->types, idx);
- struct Array_Sub_ next = { info->array.exp->next, type, info->array.depth - 1 };
- info->array = next;
- return _emit_indexes(emit, info);
-}
-
-ANN static inline Exp emit_n_exp(const Emitter emit, struct ArrayAccessInfo *const info) {
- const Exp e = take_exp(info->array.exp, info->array.depth);
- const Exp next = e->next;
- e->next = NULL;
- struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.depth };
- const m_bool ret = array_do(emit, &partial, 0);
- e->next = next;
- return ret > 0 ? next : NULL;
-}
-
-ANN static inline m_bool emit_partial_indexes(const Emitter emit, struct ArrayAccessInfo *const info) {
- struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.type->array_depth };
- struct Array_Sub_ next = { info->array.exp, array_base(info->array.type), info->array.depth - info->array.type->array_depth };
- info->array = partial;
- DECL_OB(const Exp, exp, = emit_n_exp(emit, info))
- next.exp = exp;
- info->array = next;
- return _emit_indexes(emit, info);
-}
-
-ANN static inline m_bool _emit_indexes(const Emitter emit, struct ArrayAccessInfo *const info) {
+ANN m_bool emit_array_access(const Emitter emit, struct ArrayAccessInfo *const info) {
if(GET_FLAG(info->array.type, typedef)) {
info->array.type = info->array.type->e->parent;
- return _emit_indexes(emit, info);
+ return emit_array_access(emit, info);
}
- if(info->array.type->array_depth >= info->array.depth) {
- struct Array_Sub_ next = { info->array.exp, info->type, info->array.depth };
- return array_do(emit, &next, info->is_var);
- }
- return (info->array.type->array_depth ? emit_partial_indexes : tuple_index)(emit, info);
+ struct Op_Import opi = { .op=insert_symbol("@array"), .lhs=info->array.exp->type, .rhs=info->array.type, .data=(uintptr_t)info };
+ return op_emit(emit, &opi) != (Instr)GW_ERROR ? GW_OK : GW_ERROR;
}
ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) {
CHECK_BB(emit_exp(emit, array->base, 0))
const Exp e = exp_self(array);
struct ArrayAccessInfo info = { *array->array, e->type, e->emit_var };
- return _emit_indexes(emit, &info);
+ return emit_array_access(emit, &info);
}
ANN static m_bool emit_exp_slice(const Emitter emit, const Exp_Slice* range) {
return GW_OK;
}
-#define emit_prim_complex emit_prim_vec
-#define emit_prim_polar emit_prim_vec
#define emit_prim_nil (void*)dummy_func
ANN static m_bool emit_interp(const Emitter emit, const Exp exp) {
return GW_OK;
}
-ANN static m_bool emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) {
- if(v->d.ptr && GET_FLAG(v, builtin) && GET_FLAG(v, const)) {
- const m_uint size = v->type->size;
- const Instr instr = emit_kind(emit, size, emit_addr, regpushimm);
- instr->m_val = (m_uint)v->d.ptr;
- instr->m_val2 = size;
- return GW_OK;
- }
- return emit_dot_static_data(emit, v, emit_addr);
-}
-
-ANN static m_bool emit_complex_member(const Emitter emit, const Exp_Dot* member) {
- const Exp base = member->base;
- base->emit_var = 1;
- CHECK_BB(emit_exp(emit, base, 0))
- const m_bool is_complex = !strcmp((isa(base->type, emit->gwion->type[et_complex]) > 0 ? "re" : "phase") ,
- s_name(member->xid));
- if(is_complex && exp_self(member)->emit_var)
- return GW_OK;
- const Instr instr = emit_add_instr(emit, is_complex ? ComplexReal : ComplexImag);
- instr->m_val = exp_self(member)->emit_var;
- return GW_OK;
-}
-
-ANN static m_bool emit_VecMember(const Emitter emit, const Exp_Dot* member) {
- member->base->emit_var = 1;
- CHECK_BB(emit_exp(emit, member->base, 0))
- const Value v = find_value(member->base->type, member->xid);
- if(GET_FLAG(v, func)) {
- regpushi(emit, (m_uint)v->d.func_ref->code);
- return GW_OK;
- }
- if(!v->from->offset && exp_self(member)->emit_var)
- return GW_OK;
- const Instr instr = emit_add_instr(emit, VecMember);
- instr->m_val2 = v->from->offset;
- instr->m_val = exp_self(member)->emit_var;
- return GW_OK;
-}
-
-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);
- 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);
}
-ANN static void emit_vararg_end(const Emitter emit, const m_uint offset) {
- 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);
- SET_FLAG(emit->env->func, empty);// mark vararg func as complete
-}
-
-ANN static m_bool emit_vararg(const Emitter emit, const Exp_Dot* member) {
- 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")) {
- if(get_variadic(emit))
- ERR_B(exp_self(member)->pos, _("vararg.start already used"))
- emit_vararg_start(emit, offset);
- return GW_OK;
- }
- if(!strcmp(str, "end")) {
- if(!get_variadic(emit))
- ERR_B(exp_self(member)->pos, _("vararg.start not used before vararg.end"))
- emit_vararg_end(emit, offset);
- 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) {
- const Type t = member->t_base;
- if(isa(t, emit->gwion->type[et_complex]) > 0 || isa(t, emit->gwion->type[et_polar]) > 0)
- return emit_complex_member(emit, member);
- else if(isa(t, emit->gwion->type[et_vec3]) > 0 || isa(t, emit->gwion->type[et_vec4]) > 0)
- return emit_VecMember(emit, member);
- return emit_vararg(emit, member);
-}
-
-ANN static m_bool emit_member_func(const Emitter emit, const Exp_Dot* member) {
- const Func f = exp_self(member)->type->e->d.func;
- if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) {
- const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
- func_i->m_val = (m_uint)f->code;
- return GW_OK;
- }
- if(f->def->base->tmpl)
- emit_add_instr(emit, DotTmplVal);
- else {
- const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc);
- instr->m_val = f->vt_index;
- }
- return GW_OK;
-}
-
-ANN static inline m_bool emit_member(const Emitter emit, const Value v, const uint emit_addr) {
- const m_uint size = v->type->size;
- const Instr instr = emit_kind(emit, size, emit_addr, dotmember);
- instr->m_val = v->from->offset;
- instr->m_val2 = size;
- return GW_OK;
-}
-
-ANN static m_bool ensure_emit(const Emitter emit, const Type type) {
+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))
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) {
CHECK_BB(ensure_emit(emit, member->t_base))
- if(is_special(emit, member->t_base) > 0)
- 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)))) {
- CHECK_BB(emit_exp(emit, member->base, 0))
- 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);
- return (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data) (emit, value, exp_self(member)->emit_var);
+ struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
+ .rhs=exp_self(member)->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
+ return op_emit_bool(emit, &opi);
}
ANN static inline void emit_func_def_global(const Emitter emit, const Value value) {
mp_free(((Gwion)gwion)->mp, ArrayInfo, info);
}
-ANN Type at_depth(const Env env, const Array_Sub array);
-ANN static Type partial_depth(const Env env, const Array_Sub array) {
- const Exp curr = take_exp(array->exp, array->type->array_depth);
- struct Array_Sub_ next = { curr->next, array_base(array->type), array->depth - array->type->array_depth };
- return at_depth(env, &next);
-}
-
static OP_CHECK(opck_not_array) {
const Array_Sub array = (Array_Sub)data;
ERR_O(array->exp->pos, _("array subscripts (%"UINT_F") exceeds defined dimension (%"UINT_F")"),
array->depth, get_depth(array->type))
}
+ANN Type check_array_access(const Env env, const Array_Sub array);
+
static OP_CHECK(opck_array) {
const Array_Sub array = (Array_Sub)data;
- return partial_depth(env, array);
+ const Type t_int = env->gwion->type[et_int];
+ Exp e = array->exp;
+ do CHECK_BO(check_implicit(env, e, t_int))
+ while((e = e->next));
+ const Type t = array->type;
+ if(t->array_depth >= array->depth)
+ return array_type(env, array_base(t), t->array_depth - array->depth);
+ const Exp curr = take_exp(array->exp, array->type->array_depth);
+ struct Array_Sub_ next = { curr->next, array_base(array->type), array->depth - array->type->array_depth };
+ return check_array_access(env, &next);
+}
+
+ANN static void array_loop(const Emitter emit, const m_uint depth) {
+ const Instr pre_pop = emit_add_instr(emit, RegPop);
+ pre_pop->m_val = depth * SZ_INT;
+ emit_add_instr(emit, GWOP_EXCEPT);
+ for(m_uint i = 0; i < depth - 1; ++i) {
+ const Instr access = emit_add_instr(emit, ArrayAccess);
+ access->m_val = i;
+ const Instr get = emit_add_instr(emit, ArrayGet);
+ get->m_val = i;
+ get->m_val2 = -SZ_INT;
+ emit_add_instr(emit, GWOP_EXCEPT);
+ }
+ const Instr post_pop = emit_add_instr(emit, RegPop);
+ post_pop->m_val = SZ_INT;
+ const Instr access = emit_add_instr(emit, ArrayAccess);
+ access->m_val = depth;
+}
+
+ANN static void array_finish(const Emitter emit, const m_uint depth,
+ const m_uint size, const m_bool is_var) {
+ const Instr get = emit_add_instr(emit, is_var ? ArrayAddr : ArrayGet);
+ get->m_val = depth;
+ const Instr push = emit_add_instr(emit, ArrayValid);
+ push->m_val = is_var ? SZ_INT : size;
+}
+
+ANN static inline m_bool array_do(const Emitter emit, const Array_Sub array, const m_bool is_var) {
+ emit_add_instr(emit, GcAdd);
+ CHECK_BB(emit_exp(emit, array->exp, 0))
+ array_loop(emit, array->depth);
+ array_finish(emit, array->depth, array->type->size, is_var);
+ return GW_OK;
+}
+ANN static inline Exp emit_n_exp(const Emitter emit, struct ArrayAccessInfo *const info) {
+ const Exp e = take_exp(info->array.exp, info->array.depth);
+ const Exp next = e->next;
+ e->next = NULL;
+ struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.depth };
+ const m_bool ret = array_do(emit, &partial, 0);
+ e->next = next;
+ return ret > 0 ? next : NULL;
+}
+static OP_EMIT(opem_array_access) {
+ struct ArrayAccessInfo *const info = (struct ArrayAccessInfo*)data;
+ if(info->array.type->array_depth >= info->array.depth) {
+ struct Array_Sub_ next = { .exp=info->array.exp, .type=info->type, .depth=info->array.depth };
+ return (Instr)(m_uint)array_do(emit, &next, info->is_var);
+ }
+ struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.type->array_depth };
+ struct Array_Sub_ next = { info->array.exp, array_base(info->array.type), info->array.depth - info->array.type->array_depth };
+ info->array = partial;
+ const Exp exp = emit_n_exp(emit, info);
+ next.exp = exp;
+ info->array = next;
+ return (Instr)(m_uint)(exp ? emit_array_access(emit, info) : GW_ERROR);
}
GWION_IMPORT(array) {
GWI_BB(gwi_oper_end(gwi, "@array", NULL))
GWI_BB(gwi_oper_ini(gwi, "int", "@Array", NULL))
GWI_BB(gwi_oper_add(gwi, opck_array))
+ GWI_BB(gwi_oper_emi(gwi, opem_array_access))
GWI_BB(gwi_oper_end(gwi, "@array", NULL))
gwi_register_freearg(gwi, ArrayAlloc, freearg_array);
return GW_OK;
#include "gwi.h"
#include "gack.h"
+#include "emit.h"
#define describe(name, op) \
static INSTR(Complex##name) {\
}
EQUALITY_OPER(complex, SZ_COMPLEX)
-OP_CHECK(vecx_ck);
+OP_CHECK(opck_vecx_ctor);
+
+#define opem(type, first_name) static OP_EMIT(opem_##type##_dot) { \
+ const Exp_Dot *dot = (Exp_Dot*)data; \
+ const Exp base = dot->base; \
+ base->emit_var = 1; \
+ if(emit_exp(emit, base, 0) < 0) return (Instr)GW_OK; \
+ const m_bool is_first = !strcmp(#first_name, s_name(dot->xid)); \
+ if(is_first && exp_self(dot)->emit_var) \
+ return (Instr)GW_OK; \
+ const Instr instr = emit_add_instr(emit, is_first ? ComplexReal : ComplexImag);\
+ instr->m_val = exp_self(dot)->emit_var; \
+ return (Instr)GW_OK; \
+}
+opem(complex, re)
+opem(polar, mod)
+
+OP_CHECK(opck_object_dot);
GWION_IMPORT(complex) {
-// should be special
const Type t_complex = gwi_class_spe(gwi, "complex", SZ_COMPLEX);
GWI_BB(gwi_gack(gwi, t_complex, gack_complex))
- gwi->gwion->type[et_complex] = t_complex; // use func
gwi_item_ini(gwi, "float", "re");
GWI_BB(gwi_item_end(gwi, ae_flag_member, NULL))
gwi_item_ini(gwi, "float", "im");
GWI_BB(gwi_item_end(gwi, ae_flag_member, NULL))
GWI_BB(gwi_class_end(gwi))
-// should be special
const Type t_polar = gwi_class_spe(gwi, "polar", SZ_COMPLEX);
- gwi->gwion->type[et_polar] = t_polar;
GWI_BB(gwi_gack(gwi, t_polar, gack_polar))
GWI_BB(gwi_item_ini(gwi, "float", "mod"))
GWI_BB(gwi_item_end(gwi, ae_flag_member, NULL))
GWI_BB(gwi_class_end(gwi))
GWI_BB(gwi_oper_ini(gwi, "complex", NULL, NULL))
- GWI_BB(gwi_oper_add(gwi, vecx_ck))
+ GWI_BB(gwi_oper_add(gwi, opck_vecx_ctor))
GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
GWI_BB(gwi_oper_ini(gwi, "polar", NULL, NULL))
- GWI_BB(gwi_oper_add(gwi, vecx_ck))
+ GWI_BB(gwi_oper_add(gwi, opck_vecx_ctor))
GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
GWI_BB(gwi_oper_ini(gwi, "complex", "complex", "bool"))
GWI_BB(gwi_oper_end(gwi, "==", complex_eq))
GWI_BB(gwi_oper_end(gwi, "*=>", PolarRMul))
GWI_BB(gwi_oper_add(gwi, opck_rassign))
GWI_BB(gwi_oper_end(gwi, "/=>", PolarRDiv))
+ GWI_BB(gwi_oper_ini(gwi, "complex", (m_str)OP_ANY_TYPE, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_object_dot))
+ GWI_BB(gwi_oper_emi(gwi, opem_complex_dot))
+ GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
+ GWI_BB(gwi_oper_ini(gwi, "polar", (m_str)OP_ANY_TYPE, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_object_dot))
+ GWI_BB(gwi_oper_emi(gwi, opem_polar_dot))
+ GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
return GW_OK;
}
mk_class_instr(le, r, l)
mk_class_instr(lt, r, l, && l != r)
+OP_CHECK(opck_object_dot);
+OP_EMIT(opem_object_dot);
ANN static m_bool import_core_libs(const Gwi gwi) {
const Type t_class = gwi_mk_type(gwi, "@Class", SZ_INT, NULL);
gwi->gwion->type[et_class] = t_class;
GWI_BB(gwi_add_type(gwi, t_class))
+ GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, (m_str)OP_ANY_TYPE, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_object_dot))
+ GWI_BB(gwi_oper_emi(gwi, opem_object_dot))
+ GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
GWI_BB(gwi_gack(gwi, gwi->gwion->type[et_class], gack_class)) // not working yet
gwi->gwion->type[et_class] = t_class;
const Type t_undefined = gwi_mk_type(gwi, "@Undefined", SZ_INT, NULL);
if(GET_FLAG(t, nonnull))
t = t->e->parent;
if(!t->nspc)
- continue; // return ?
+ continue;
struct scope_iter iter = { t->nspc->info->value, 0, 0 };\
Value v;
while(scope_iter(&iter, &v) > 0) {
ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
return r->e->parent;
}
-/* if(nonnull_check(l, r))
- ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); */
if(l != env->gwion->type[et_null] && isa(l, r) < 0)
ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
return r;
ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name)
}
+static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm };
+ANN Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]);
+ANN static void emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) {
+ const m_uint size = v->type->size;
+ const Instr instr = emit_kind(emit, size, emit_var, dotstatic);
+ instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset);
+ instr->m_val2 = size;
+}
+
+static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 };
+ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) {
+ if(v->d.ptr && GET_FLAG(v, builtin) && GET_FLAG(v, const)) {
+ const m_uint size = v->type->size;
+ const Instr instr = emit_kind(emit, size, emit_addr, regpushimm);
+ instr->m_val = (m_uint)v->d.ptr;
+ instr->m_val2 = size;
+ } else
+ emit_dot_static_data(emit, v, emit_addr);
+}
+static const f_instr dotmember[] = { DotMember, DotMember2, DotMember3, DotMember4 };
+
+ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
+ const Func f = exp_self(member)->type->e->d.func;
+ if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) {
+ const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
+ func_i->m_val = (m_uint)f->code;
+ return;
+ }
+ if(f->def->base->tmpl)
+ emit_add_instr(emit, DotTmplVal);
+ else {
+ const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc);
+ instr->m_val = f->vt_index;
+ }
+ return;
+}
+
+ANN static inline void emit_member(const Emitter emit, const Value v, const uint emit_addr) {
+ const m_uint size = v->type->size;
+ const Instr instr = emit_kind(emit, size, emit_addr, dotmember);
+ instr->m_val = v->from->offset;
+ instr->m_val2 = size;
+}
+
+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);
+ return value->type;
+}
+
+OP_EMIT(opem_object_dot) {
+ const Exp_Dot *member = (Exp_Dot*)data;
+ 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)))) {
+ CHECK_BO(emit_exp(emit, member->base, 0))
+ 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))
+ emit_member_func(emit, member);
+ else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var);
+ return (Instr)GW_OK;
+}
+
GWION_IMPORT(object) {
const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
gwi_add_type(gwi, t_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_end(gwi, "@=>", ObjectAssign))
GWI_BB(gwi_oper_ini(gwi, "Object", "Object", NULL))
GWI_BB(gwi_oper_add(gwi, at_object))
GWI_BB(gwi_oper_emi(gwi, opem_at_object))
GWI_BB(gwi_oper_emi(gwi, opem_implicit_null2obj))
GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
GWI_BB(gwi_oper_ini(gwi, "@null", "Object", "int"))
- GWI_BB(gwi_oper_end(gwi, "==", EqObject))
- GWI_BB(gwi_oper_end(gwi, "!=", NeqObject))
- 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_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"))
GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
GWI_BB(gwi_oper_end(gwi, "!", IntNot))
CHECK_BO(scan1_cdef(env, a))
return a->base.type;
}
+
+ANN static inline Symbol dot_symbol(SymTable *st, const Value v) {
+ const m_str name = !GET_FLAG(v, static) ? "this" : v->from->owner_class->name;
+ return insert_symbol(st, name);
+}
+
+ANN static inline Type dot_type(SymTable *st, const Value v) {
+ const Type t = v->from->owner_class;
+ if(!GET_FLAG(v, static))
+ return t;
+ const Value val = nspc_lookup_value1(t->nspc->parent, insert_symbol(st, t->name));
+ return val->type;
+}
+
+ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data) {
+ const Value v = prim_self(data)->value;
+ const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data)));
+ const Exp dot = new_exp_dot(gwion->mp, base, *data);
+ dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v);
+ dot->type = prim_exp(data)->type;
+ dot->emit_var = prim_exp(data)->emit_var;
+ return dot;
+}
ERR_N(td_pos(unary->td), _("can't use 'new' on abstract type '%s'\n"), t->name)
UNSET_FLAG(unary->td, ref);
if(unary->td->array)
- CHECK_BN(check_subscripts(env, unary->td->array))
+ CHECK_BN(check_subscripts(env, unary->td->array, 1))
return t;
}
GWI_BB(gwi_oper_end(gwi, "-", int_minus))
GWI_BB(gwi_oper_end(gwi, "*", int_mul))
GWI_BB(gwi_oper_end(gwi, "/", int_div))
- GWI_BB(gwi_oper_end(gwi, "%", int_modulo))
- GWI_BB(gwi_oper_end(gwi, "@access", NULL))
- return gwi_oper_end(gwi, "@repeat", NULL);
+ return gwi_oper_end(gwi, "%", int_modulo);
}
static GWION_IMPORT(int_logical) {
return env->gwion->type[et_null];
}
-static OP_CHECK(opck_repeat_f2i) {
- struct Implicit* imp = (struct Implicit*)data;
- return imp->e->cast_to = env->gwion->type[et_int];
-}
-
static OP_CHECK(opck_implicit_i2f) {
struct Implicit* imp = (struct Implicit*)data;
return imp->e->cast_to = env->gwion->type[et_float];
CHECK_FI("/=>", rassign, r_div)
_CHECK_OP("$", basic_cast, CastF2I)
_CHECK_OP("@implicit", implicit_f2i, CastF2I)
- _CHECK_OP("@repeat", repeat_f2i, CastF2I)
return GW_OK;
}
#include "specialid.h"
#include "gwi.h"
-static m_int o_fork_thread, o_shred_cancel, o_fork_done, o_fork_ev, o_fork_retsize, o_fork_retval;
+static m_int o_fork_thread, 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_RETSIZE(o) *(m_int*)(o->data + o_fork_retsize)
-#define FORK_RETVAL(o) (o->data + o_fork_retval)
VM_Shred new_shred_base(const VM_Shred shred, const VM_Code code) {
const VM_Shred sh = new_vm_shred(shred->info->mp, code);
MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
}
-void fork_retval(const M_Object o) {
- const m_uint sz = FORK_RETSIZE(o);
- memcpy(FORK_RETVAL(o), ME(o)->reg - sz, sz);
-}
-
static ANN void* fork_run(void* data) {
VM *vm = (VM*)data;
const M_Object me = vm->shreduler->list->self->info->me;
}
vm_lock(vm->parent);
if(vm_running(vm->parent)) {
- fork_retval(me);
*(m_int*)(me->data + o_fork_done) = 1;
broadcast(*(M_Object*)(me->data + o_fork_ev));
} else if(me->ref > 1)
GWI_BB((o_fork_ev = gwi_item_end(gwi, ae_flag_const, NULL)))
gwi_item_ini(gwi, "int", "retsize");
GWI_BB((o_fork_retsize = gwi_item_end(gwi, ae_flag_const, NULL)))
- o_fork_retval = t_fork->nspc->info->offset;
- GWI_BB(gwi_union_ini(gwi, NULL, NULL))
- GWI_BB(gwi_union_add(gwi, "int", "i"))
- GWI_BB(gwi_union_add(gwi, "float", "f"))
- GWI_BB(gwi_union_add(gwi, "Vec3", "v"))
- GWI_BB(gwi_union_add(gwi, "Vec4", "w"))
- GWI_BB(gwi_union_add(gwi, "VarObject", "o"))
- GWI_OB(gwi_union_end(gwi, ae_flag_const))
gwi_func_ini(gwi, "void", "join");
GWI_BB(gwi_func_end(gwi, fork_join, ae_flag_none))
GWI_BB(gwi_class_end(gwi))
#include "tuple.h"
#include "array.h"
+#define TUPLE_NAME "Tuple"
struct TupleEmit {
Exp e;
Vector v;
unpack_instr_decl(emit, te);
if(te->sz)
emit_unpack_instr_inner(emit, te);
- if(te->e && (te->e = te->e->next)) // antepenultimate ?
+ if(te->e && (te->e = te->e->next))
emit_unpack_instr(emit, te);
}
Except(shred, _("can't cast\n"));
}
- // TODO: do not emit Tuple2Object if full match
-#define mk_opem_tuple2object(name, type, rhs) \
-static OP_EMIT(opem_##name##_tuple_object) { \
- const type exp = (type)data; \
- const Instr instr = emit_add_instr(emit, Tuple2Object); \
- instr->m_val = (m_uint)rhs; \
- instr->m_val2 = SZ_INT; \
- return instr; \
+// TODO: do not emit Tuple2Object if full match
+static OP_EMIT(opem_cast_tuple_object) {
+ const Exp_Cast* exp = (Exp_Cast*)data;
+ const Instr instr = emit_add_instr(emit, Tuple2Object);
+ instr->m_val = (m_uint)exp_self(exp)->type;
+ instr->m_val2 = SZ_INT;
+ return instr;
}
-static OP_EMIT(opem_at_tuple_object) { \
- const Exp_Binary *bin = (Exp_Binary*)data; \
- const Instr instr = emit_add_instr(emit, Tuple2Object); \
- instr->m_val = (m_uint)bin->rhs->type; \
- instr->m_val2 = SZ_INT*2; \
-
- const Instr assign = emit_add_instr(emit, ObjectAssign); \
-
-return assign;
+static OP_EMIT(opem_at_tuple_object) {
+ const Exp_Binary *bin = (Exp_Binary*)data;
+ const Instr instr = emit_add_instr(emit, Tuple2Object);
+ instr->m_val = (m_uint)bin->rhs->type;
+ instr->m_val2 = SZ_INT*2;
+ return emit_add_instr(emit, ObjectAssign);
}
-mk_opem_tuple2object(cast, Exp_Cast *, exp_self(exp)->type)
static OP_CHECK(opck_cast_tuple) {
const Exp_Cast *cast = (Exp_Cast*)data;
ANN static Symbol tuple_sym(const Env env, const Vector v) {
GwText text = { .mp=env->gwion->mp };
- text_add(&text, env->gwion->type[et_tuple]->name);
+ text_add(&text, TUPLE_NAME);
text_add(&text, "<~");
for(m_uint i = 0; i < vector_size(v); ++i) {
const Type t = (Type)vector_at(v, i);
}
Section * section = new_section_stmt_list(env->gwion->mp, base);
Ast body = new_ast(env->gwion->mp, section, NULL);
- const ID_List ilist = new_id_list(env->gwion->mp, insert_symbol(env->gwion->type[et_tuple]->name),
+ const ID_List ilist = new_id_list(env->gwion->mp, insert_symbol(TUPLE_NAME),
loc_cpy(env->gwion->mp, pos));
Type_Decl *td = new_type_decl(env->gwion->mp, ilist);
Class_Def cdef = new_class_def(env->gwion->mp, ae_flag_template,
free_type_list(p, tuple->list);
}
-ANN /*static*/ Type at_depth(const Env env, const Array_Sub array);
+ANN Type check_array_access(const Env env, const Array_Sub array);
+
static OP_CHECK(opck_tuple) {
const Array_Sub array = (Array_Sub)data;
const Vector v = &array->type->e->tuple->types;
if(!exp->next)
return type;
struct Array_Sub_ next = { exp->next, type, array->depth - 1 };
- return at_depth(env, &next);
+ return check_array_access(env, &next);
}
-static OP_CHECK(tuple_ck) {
+static OP_CHECK(opck_tuple_ctor) {
const Exp_Call *call = (Exp_Call*)data;
const Exp exp = call->args;
if(exp)
return ret;
}
-static OP_EMIT(tuple_em) {
+static OP_EMIT(opem_tuple_ctor) {
const Exp_Call *call = (Exp_Call*)data;
const Instr instr = emit_add_instr(emit, TupleCtor);
instr->m_val = (m_uint)exp_self(call)->type;
return NULL;
}
+static void parents(const Env env, const Type t, const Vector v) {
+ const Nspc parent = t->e->owner;
+ if(parent->parent && parent != env->context->nspc && parent != env->global_nspc) {
+ const Type older = nspc_lookup_type1(parent->parent, insert_symbol(parent->name));
+ parents(env, older, v);
+ }
+ vector_add(v, (vtype)insert_symbol(t->name));
+}
+
static OP_CHECK(opck_at_unpack) {
const Exp_Binary *bin = (Exp_Binary*)data;
Exp e = bin->rhs->d.exp_call.args;
while(e) {
if(e->exp_type == ae_exp_decl) {
DECL_OO(const Type, t, = (Type)VPTR(&bin->lhs->type->e->tuple->types, i))
- e->d.exp_decl.td->xid->xid = insert_symbol(t->name);
+ struct Vector_ v; // hoist?
+ vector_init(&v);
+ parents(env, t, &v);
+ ID_List id = e->d.exp_decl.td->xid;
+ id->xid = (Symbol)vector_front(&v);
+ for(m_uint i = 1; i < vector_size(&v); ++i)
+ id = (id->next = new_id_list(env->gwion->mp, (Symbol)vector_at(&v, i), loc_cpy(env->gwion->mp, e->pos)));
+ vector_release(&v);
const Exp next = e->next;
e->d.exp_decl.type = NULL;
e->next = NULL;
return (Instr)GW_OK;
}
-ANN static Type scan_tuple(const Env env, const Type_Decl *td);
+static ANN Type scan_tuple(const Env env, const Type_Decl *td) {
+ struct Vector_ v;
+ vector_init(&v);
+ Type_List tl = td->types;
+ do {
+ const Type t = tl->td->xid->xid != insert_symbol("_") ?
+ known_type(env, tl->td) : (Type)1;
+ if(t)
+ vector_add(&v, (m_uint)t);
+ else {
+ vector_release(&v);
+ return env->gwion->type[et_null];
+ }
+ } while((tl = tl->next));
+ const Type ret = tuple_type(env, &v, td_pos(td));
+ vector_release(&v);
+ return ret;
+}
+
static OP_CHECK(opck_tuple_scan) {
struct TemplateScan *ts = (struct TemplateScan*)data;
return ts->td->types ? scan_tuple(env, ts->td) : ts->t;
}
+ANN static void tuple_access(const Emitter emit, const m_uint idx,
+ const m_bool is_var) {
+ const Instr instr = emit_add_instr(emit, TupleMember);
+ instr->m_val = idx;
+ instr->m_val2 = is_var;
+ emit_add_instr(emit, DotMember); // just a place holder.
+}
+
+static OP_EMIT(opem_tuple_access) {
+ struct ArrayAccessInfo *info = (struct ArrayAccessInfo*)data;
+ const m_uint idx = info->array.exp->d.prim.d.num;
+ emit_except(emit, info->array.type);
+ tuple_access(emit, info->array.exp->d.prim.d.num, (info->array.depth -1)? 0 : info->is_var);
+ if(!info->array.exp->next)
+ return (Instr)GW_OK;
+ const Type type = (Type)vector_at(&info->array.type->e->tuple->types, idx);
+ struct Array_Sub_ next = { info->array.exp->next, type, info->array.depth - 1 };
+ info->array = next;
+ return (Instr)(m_uint)emit_array_access(emit, info);
+}
+
GWION_IMPORT(tuple) {
- const Type t_tuple = gwi_mk_type(gwi, "Tuple", SZ_INT, "Object");
+ const Type t_tuple = gwi_mk_type(gwi, TUPLE_NAME, SZ_INT, "Object");
gwi_add_type(gwi, t_tuple);
SET_FLAG(t_tuple, checked | ae_flag_scan2 | ae_flag_check | ae_flag_emit);
- gwi->gwion->type[et_tuple] = t_tuple;
SET_FLAG(t_tuple, abstract | ae_flag_template);
- GWI_BB(gwi_oper_ini(gwi, "Tuple", NULL, NULL))
- GWI_BB(gwi_oper_add(gwi, tuple_ck))
- GWI_BB(gwi_oper_emi(gwi, tuple_em))
+ GWI_BB(gwi_oper_ini(gwi, TUPLE_NAME, NULL, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_tuple_ctor))
+ GWI_BB(gwi_oper_emi(gwi, opem_tuple_ctor))
GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
GWI_BB(gwi_oper_add(gwi, opck_tuple_scan))
GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
- GWI_BB(gwi_oper_ini(gwi, "Object", "Tuple", NULL))
+ GWI_BB(gwi_oper_ini(gwi, "Object", TUPLE_NAME, NULL))
GWI_BB(gwi_oper_add(gwi, opck_at_object_tuple))
GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign))
GWI_BB(gwi_oper_add(gwi, opck_cast_tuple))
GWI_BB(gwi_oper_end(gwi, "$", NoOp))
GWI_BB(gwi_oper_add(gwi, opck_impl_tuple))
GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
- GWI_BB(gwi_oper_ini(gwi, "Tuple", "Object", NULL))
+ GWI_BB(gwi_oper_ini(gwi, TUPLE_NAME, "Object", NULL))
GWI_BB(gwi_oper_add(gwi, opck_at_tuple_object))
GWI_BB(gwi_oper_emi(gwi, opem_at_tuple_object))
GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
GWI_BB(gwi_oper_end(gwi, "$", NULL))
GWI_BB(gwi_oper_add(gwi, opck_impl_tuple))
GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
- GWI_BB(gwi_oper_ini(gwi, "Tuple", "Tuple", NULL))
+ GWI_BB(gwi_oper_ini(gwi, TUPLE_NAME, "Tuple", NULL))
GWI_BB(gwi_oper_add(gwi, opck_at_object_tuple))
GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign))
- GWI_BB(gwi_oper_ini(gwi, "int", "Tuple", NULL))
+ GWI_BB(gwi_oper_ini(gwi, "int", TUPLE_NAME, NULL))
GWI_BB(gwi_oper_add(gwi, opck_tuple))
-// GWI_BB(gwi_oper_emi(gwi, opem_at_tuple))
+ GWI_BB(gwi_oper_emi(gwi, opem_tuple_access))
GWI_BB(gwi_oper_end(gwi, "@array", NULL))
gwi_register_freearg(gwi, TupleUnpack, freearg_tuple_at);
const Type t_unpack = gwi_mk_type(gwi, "Unpack", 0, NULL);
gwi_add_type(gwi, t_unpack);
SET_FLAG(t_unpack, checked | ae_flag_scan2 | ae_flag_check | ae_flag_emit);
-// SET_FLAG(t_unpack, abstract | ae_flag_template);
GWI_BB(gwi_oper_ini(gwi, "Unpack", NULL, NULL))
GWI_BB(gwi_oper_add(gwi, unpack_ck))
GWI_BB(gwi_oper_emi(gwi, unpack_em))
GWI_BB(gwi_oper_add(gwi, opck_at_unpack))
GWI_BB(gwi_oper_emi(gwi, opem_at_unpack))
GWI_BB(gwi_oper_end(gwi, "==", NULL))
- GWI_BB(gwi_oper_ini(gwi, "Tuple", "Unpack", NULL))
- GWI_BB(gwi_oper_add(gwi, opck_at_unpack))
- GWI_BB(gwi_oper_emi(gwi, opem_at_unpack))
- GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
- GWI_BB(gwi_oper_add(gwi, opck_at_unpack))
- GWI_BB(gwi_oper_emi(gwi, opem_at_unpack))
- GWI_BB(gwi_oper_end(gwi, "==", NULL))
return GW_OK;
}
-
-static ANN Type scan_tuple(const Env env, const Type_Decl *td) {
- struct Vector_ v;
- vector_init(&v);
- Type_List tl = td->types;
- do {
- const Type t = tl->td->xid->xid != insert_symbol("_") ?
- known_type(env, tl->td) : (Type)1;
- if(t)
- vector_add(&v, (m_uint)t);
- else {
- vector_release(&v);
- return env->gwion->type[et_null];
- }
- } while((tl = tl->next));
- const Type ret = tuple_type(env, &v, td_pos(td));
- vector_release(&v);
- return ret;
-}
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;
+ return known_type(env, cast->td);
}
static INSTR(VarargCast) {
free_vararg(shred->info->mp, arg);
Except(shred, "InvalidVariadicAccess");
}
-// 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);
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;
+ instr->m_val = get_variadic(emit)->m_val;
+ instr->m_val2 = (m_uint)exp_self(cast)->type;
return instr;
}
-static OP_CHECK(at_varobj) {
- const Exp_Binary* bin = (Exp_Binary*)data;
- return bin->rhs->type;
-}
-
-static INSTR(VarargAssign) {
- POP_REG(shred, SZ_INT);
- *(M_Object**)REG(0) = &*(M_Object*)REG(-SZ_INT);
-}
-
static FREEARG(freearg_vararg) {
if(instr->m_val2)
free_vector(((Gwion)gwion)->mp, (Vector)instr->m_val2);
INTERP_PRINTF("%p\n", *(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);
+ 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 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);
+ SET_FLAG(emit->env->func, empty);// mark vararg func as complete
+}
+
+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")) {
+ 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);
+ return (Instr)GW_OK;
+}
+OP_CHECK(opck_object_dot);
+
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_spe(gwi, "@Vararg", 0);
gwi_gack(gwi, t_vararg, gack_vararg);
GWI_BB(gwi_union_add(gwi, "@VarLoop", "end"))
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_add(gwi, at_varobj))
- GWI_BB(gwi_oper_end(gwi, "@=>", VarargAssign))
- 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_object_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))
#include "driver.h"
#include "gwi.h"
#include "gack.h"
+#include "emit.h"
INSTR(VecCpy) {
POP_REG(shred, instr->m_val2);
EQUALITY_OPER(vec3, SZ_VEC3);
-OP_CHECK(vecx_ck) {
+OP_CHECK(opck_vecx_ctor) {
Exp_Call *call = (Exp_Call*)data;
Exp e = call->args, last = NULL;
if(call->args)
}
return t;
}
+OP_CHECK(opck_object_dot);
+
+static OP_EMIT(opem_vec_dot) {
+ Exp_Dot *member = (Exp_Dot*)data;
+ member->base->emit_var = 1;
+ CHECK_BO(emit_exp(emit, member->base, 0))
+ const Value v = find_value(member->base->type, member->xid);
+ if(GET_FLAG(v, func)) {
+ /*regpushi(emit, (m_uint)v->d.func_ref->code);*/
+ const Instr instr = emit_add_instr(emit, RegPushImm);
+ instr->m_val = (m_uint)v->d.func_ref->code;
+ return instr;
+ }
+ if(!v->from->offset && exp_self(member)->emit_var)
+ return (Instr)GW_OK;
+ const Instr instr = emit_add_instr(emit, VecMember);
+ instr->m_val2 = v->from->offset;
+ instr->m_val = exp_self(member)->emit_var;
+ return instr;
+}
GWION_IMPORT(vec3) {
const Type t_vec3 = gwi_class_spe(gwi, "Vec3", SZ_VEC3);
- gwi->gwion->type[et_vec3] = t_vec3;
GWI_BB(gwi_gack(gwi, t_vec3, gack_vec3))
vecx_base(gwi);
gwi_func_ini(gwi, "void", "set");
GWI_BB(gwi_class_end(gwi))
GWI_BB(gwi_oper_ini(gwi, "Vec3", NULL, NULL))
- GWI_BB(gwi_oper_add(gwi, vecx_ck))
+ GWI_BB(gwi_oper_add(gwi, opck_vecx_ctor))
GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
+ GWI_BB(gwi_oper_ini(gwi, "Vec3", (m_str)OP_ANY_TYPE, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_object_dot))
+ GWI_BB(gwi_oper_emi(gwi, opem_vec_dot))
+ GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
+
GWI_BB(gwi_oper_ini(gwi, "Vec3", "Vec3", "bool"))
GWI_BB(gwi_oper_end(gwi, "==", vec3_eq))
GWI_BB(gwi_oper_end(gwi, "!=", vec3_ne))
GWION_IMPORT(vec4) {
const Type t_vec4 = gwi_class_spe(gwi, "Vec4", SZ_VEC4);
- gwi->gwion->type[et_vec4] = t_vec4;
GWI_BB(gwi_gack(gwi, t_vec4, gack_vec4))
vecx_base(gwi);
gwi_item_ini(gwi, "float", "w");
CHECK_BB(gwi_class_end(gwi))
GWI_BB(gwi_oper_ini(gwi, "Vec4", NULL, NULL))
- GWI_BB(gwi_oper_add(gwi, vecx_ck))
+ GWI_BB(gwi_oper_add(gwi, opck_vecx_ctor))
GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
+ GWI_BB(gwi_oper_ini(gwi, "Vec4", (m_str)OP_ANY_TYPE, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_object_dot))
+ GWI_BB(gwi_oper_emi(gwi, opem_vec_dot))
+ GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
+
GWI_BB(gwi_oper_ini(gwi, "Vec4", "Vec4", "bool"))
GWI_BB(gwi_oper_end(gwi, "==", vec4_eq))
GWI_BB(gwi_oper_end(gwi, "!=", vec4_ne))
return GW_OK;
}
-ANN /*static inline */m_bool check_implicit(const Env env, const Exp e, const Type t) {
+ANN m_bool check_implicit(const Env env, const Exp e, const Type t) {
+ if(e->type == t)
+ return GW_OK;
const Symbol sym = insert_symbol("@implicit");
return check_internal(env, sym, e, t);
}
-ANN m_bool check_subscripts(Env env, const Array_Sub array) {
+ANN m_bool check_subscripts(Env env, const Array_Sub array, const m_bool is_decl) {
CHECK_OB(check_exp(env, array->exp))
m_uint depth = 0;
Exp e = array->exp;
- const Symbol sym = insert_symbol("@access");
- do CHECK_BB(check_internal(env, sym, e, env->gwion->type[et_int]))
- while(++(depth) && (e = e->next));
+ do if(is_decl)
+ CHECK_BB(check_implicit(env, e, env->gwion->type[et_int]))
+ while(++depth && (e = e->next));
if(depth != array->depth)
ERR_B(array->exp->pos, _("invalid array acces expression."))
return GW_OK;
if(!env->class_def) {
if(!type || GET_FLAG(func, global))
return GW_OK;
- ERR_B(var->pos, _("can't use non public typedef at global scope."))
+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(env->class_def && !env->scope->depth && env->class_def->e->parent)
CHECK_BB(check_exp_decl_parent(env, var))
if(var->array && var->array->exp)
- return check_subscripts(env, var->array);
+ return check_subscripts(env, var->array, 1);
return GW_OK;
}
return value;
}
+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 };
+ return op_check(env, &opi);
+}
+
ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
const Symbol var = *data;
const Value v = check_non_res_value(env, data);
UNSET_FLAG(env->func, pure);
SET_FLAG(v, used);
prim_self(data)->value = v;
- if(GET_FLAG(v, const) || !strcmp(s_name(var), "maybe"))
+ if(GET_FLAG(v, const))
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);
+ prim_exp(data)->nspc = exp->nspc;
+ free_exp(env->gwion->mp, exp);
+ CHECK_OO(ret);
+ }
return v->type;
}
return exp_self(prim)->type = check_prim_func[prim->prim_type](env, &prim->d);
}
-ANN Type at_depth(const Env env, const Array_Sub array) {
- const Type t = array->type;
- const m_uint depth = array->depth;
- if(GET_FLAG(t, typedef)) {
- struct Array_Sub_ next = { array->exp, t->e->parent, depth };
- return at_depth(env, &next);
- }
- if(t->array_depth >= depth)
- return array_type(env, array_base(array->type), t->array_depth - depth);
+ANN Type check_array_access(const Env env, const Array_Sub array) {
const Symbol sym = insert_symbol("@array");
struct Op_Import opi = { .op=sym, .lhs=array->exp->type, .rhs=array->type, .pos=array->exp->pos, .data=(uintptr_t)array };
- const Type ret = op_check(env, &opi);
- return ret;
+ return op_check(env, &opi);
}
static ANN Type check_exp_array(const Env env, const Exp_Array* array) {
CHECK_OO((array->array->type = check_exp(env, array->base)))
- CHECK_BO(check_subscripts(env, array->array))
- return at_depth(env, array->array);
+ CHECK_BO(check_subscripts(env, array->array, 0))
+ return check_array_access(env, array->array);
}
static ANN Type check_exp_slice(const Env env, const Exp_Slice* range) {
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;
}
}
ANN static inline m_bool cond_type(const Env env, const Exp e) {
- const Symbol sym = insert_symbol("@repeat");
const Type t_int = env->gwion->type[et_int];
- return check_internal(env, sym, e, t_int);
+ return check_implicit(env, e, t_int);
}
#define stmt_func_xxx(name, type, prolog, exp) describe_stmt_func(check, name, type, prolog, exp)
const Type parent = cdef->base.type->e->parent;
const Type_Decl *td = cdef->base.ext;
if(td->array)
- CHECK_BB(check_subscripts(env, td->array))
+ CHECK_BB(check_subscripts(env, td->array, 1))
if(parent->e->def && !GET_FLAG(parent, check))
CHECK_BB(scanx_parent(parent, traverse_cdef, env))
if(GET_FLAG(parent, typedef))
}
ANN static void set_nspc(struct OpChecker* ock, const Nspc nspc) {
-printf("here %s\n", nspc->name);
if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@array")) {
Array_Sub array = (Array_Sub)ock->opi->data;
array->exp->nspc = nspc;
return;
}
- if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@implicit") ||
- ock->opi->op == insert_symbol(ock->env->gwion->st, "@access") ||
- ock->opi->op == insert_symbol(ock->env->gwion->st, "@repeat")) {
+ if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@implicit")) {
struct Implicit* imp = (struct Implicit*)ock->opi->data;
imp->e->nspc = nspc;
return;
}
ANN static Nspc get_nspc(SymTable *st, const struct Op_Import* opi) {
+ if(opi->op == insert_symbol(st, "@array")) {
+ struct ArrayAccessInfo *info = (struct ArrayAccessInfo*)opi->data;
+ return info->array.exp->nspc;
+ }
if(opi->op == insert_symbol(st, "@implicit")) {
struct Implicit* imp = (struct Implicit*)opi->data;
return imp->e->nspc;
Type r = opi->rhs;
do {
const Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
-if(!v)continue;
-assert(v);
+ if(!v)continue;
const M_Operator* mo = operator_find(v, l, r);
if(mo) {
if(mo->em)
return class_internal(env, base);
if(op == insert_symbol("@implicit"))
return scan_internal_arg(env, base);
- if(op == insert_symbol("@access") ||
- op == insert_symbol("@repeat") ||
- op == insert_symbol("@conditionnal") ||
+ if(op == insert_symbol("@conditionnal") ||
op == insert_symbol("@unconditionnal"))
return scan_internal_int(env, base);
return GW_OK;
-#! [contains] can't use non public typedef at global scope
+#! [contains] NullPtrException
class C {
typedef void t_ptr();
}
C->t_ptr ptr;
+ptr();
#! [contains] must return
-operator @access Object (int i) {}
+operator @conditionnal Object (int i) {}
#! [contains] must have one
-operator @access int(Vec3 v, int i) {}
+operator @implicit int(Vec3 v, int i) {}
-int i;
-for(i=0; i< 3; i++) {
+for(int i; i< 3; i++) {
if(maybe)
break;
else continue;