f_xfun addr;
};
union {
- Type_List list;// union
+ Union_List list;// union
struct Vector_ v;
// ID_List curr;// enum
};
#define __IMPORT_UNION
ANN2(1) m_int gwi_union_ini(const Gwi gwi, const m_str name);
-ANN m_int gwi_union_add(const Gwi gwi, const __restrict__ m_str type);
+ANN m_int gwi_union_add(const Gwi gwi, const __restrict__ m_str type, const __restrict__ m_str name);
ANN Type gwi_union_end(const Gwi gwi, const ae_flag flag);
ANN void ck_clean_udef(MemPool, ImportCK*);
vector_release(&b->values);
}
+ANN static void clean_union_list(Clean *a, Union_List b) {
+ clean_type_decl(a, b->td);
+ if(b->next)
+ clean_union_list(a, b->next);
+}
+
ANN static void clean_union_def(Clean *a, Union_Def b) {
- clean_type_list(a, b->l);
+ clean_union_list(a, b->l);
if(b->tmpl)
clean_tmpl(a, b->tmpl);
}
return GW_OK;
}
-ANN m_int gwi_union_add(const Gwi gwi, const restrict m_str type) {
+ANN m_int gwi_union_add(const Gwi gwi, const restrict m_str type, const restrict m_str name) {
CHECK_BB(ck_ok(gwi, ck_udef))
DECL_OB(Type_Decl*, td, = str2decl(gwi->gwion, type, gwi->loc))
- gwi->ck->list = new_type_list(gwi->gwion->mp, td, gwi->ck->list);
+ DECL_OB(const Symbol, xid, = str2sym(gwi->gwion, name, gwi->loc))
+ const Union_List l = new_union_list(gwi->gwion->mp, td, xid, loc(gwi));
+ l->next = gwi->ck->list;
+ gwi->ck->list = l;
return GW_OK;
}
ANN void ck_clean_udef(MemPool mp, ImportCK* ck) {
if(ck->list)
- free_type_list(mp, ck->list);
+ free_union_list(mp, ck->list);
if(ck->tmpl)
free_id_list(mp, ck->tmpl);
}
ANN static m_bool scantmpl_union_def(const Env env, struct tmpl_info *info) {
const Union_Def u = info->base->info->udef;
- const Union_Def udef = new_union_def(env->gwion->mp, cpy_type_list(env->gwion->mp, u->l),
+ const Union_Def udef = new_union_def(env->gwion->mp, cpy_union_list(env->gwion->mp, u->l),
loc_cpy(env->gwion->mp, u->pos));
udef->xid = info->name;
udef->tmpl = mk_tmpl(env, u->tmpl, info->td->types);
#include "specialid.h"
#include "gack.h"
-#define UNION_IDX(a) (*(m_uint*)(a->data))
-
static GACK(gack_none) {
INTERP_PRINTF("None")
}
-static OP_CHECK(opck_any_at_union) {
- Exp_Binary *bin = (Exp_Binary*)data;
- CHECK_NN(opck_rassign(env, data, mut)) // check those two lines
- const Type lhs = bin->lhs->info->type;
- const Nspc nspc = bin->rhs->info->type->nspc;
- for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) {
- if(lhs == *(Type*)(nspc->info->class_data + i))
- return bin->rhs->info->type;
- }
- return env->gwion->type[et_error]; // err_msg
-}
-
-static inline Type curr_type(const M_Object o) {
- const m_uint idx = UNION_IDX(o);
- if(!idx)
- return NULL;
- const Type curr = *(Type*)(o->type_ref->nspc->info->class_data + ((idx-1) * SZ_INT));
- return curr;
-}
-
static INSTR(UnionSet) {
- POP_REG(shred, SZ_INT);
- const M_Object o = **(M_Object**)REG(0);
- memcpy(o->data + SZ_INT, REG(-instr->m_val), instr->m_val);
- UNION_IDX(o) = instr->m_val2;
- PUSH_REG(shred, SZ_INT-instr->m_val);
- *(M_Object*)REG(-SZ_INT) = o;
- _release(o, shred);
-}
-
-static OP_EMIT(opem_any_at_union) {
- Exp_Binary *bin = (Exp_Binary*)data;
- const Type lhs = bin->lhs->info->type;
- const Nspc nspc = bin->rhs->info->type->nspc;
- const Instr instr = emit_add_instr(emit, UnionSet);
- for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) {
- if(lhs == *(Type*)(nspc->info->class_data + i)) {
- instr->m_val2 = i/SZ_INT + 1;
- instr->m_val = lhs->size;
- return instr;
- }
- }
- return NULL;
-}
-
-static OP_CHECK(opck_union_at_any) {
- CHECK_NN(opck_rassign(env, data, mut)) // check those two lines
- Exp_Binary *bin = (Exp_Binary*)data;
- const Type rhs = bin->rhs->info->type;
- const Nspc nspc = bin->lhs->info->type->nspc;
- for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) {
- if(rhs == *(Type*)(nspc->info->class_data + i))
- return rhs;
- }
- return env->gwion->type[et_error]; // err_msg
-}
-
-static INSTR(UnionGet) {
- const M_Object o = *(M_Object*)REG(-SZ_INT*2);
- if(UNION_IDX(o) != instr->m_val2)
- Except(shred, "invalid union access");
- memcpy(*(m_bit**)REG(-SZ_INT), o->data + SZ_INT, instr->m_val);
- POP_REG(shred, SZ_INT*2 - instr->m_val);
- memcpy(REG(-instr->m_val), o->data + SZ_INT, instr->m_val);
- _release(o, shred);
-}
-
-static OP_EMIT(opem_union_at_any) {
- Exp_Binary *bin = (Exp_Binary*)data;
- const Type rhs = bin->rhs->info->type;
- const Nspc nspc = bin->lhs->info->type->nspc;
- // TODO: compound
- const Instr instr = emit_add_instr(emit, UnionGet);
- if(isa(rhs, emit->gwion->type[et_object]) > 0) {
- const Instr instr = emit_add_instr(emit, RegAddRef);
- instr->m_val = -SZ_INT;
- }
- for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) {
- if(rhs == *(Type*)(nspc->info->class_data + i)) {
- instr->m_val2 = i/SZ_INT + 1;
- instr->m_val = rhs->size;
- return instr;
- }
- }
- return NULL;
-}
-
-static OP_CHECK(opck_union_eq_class) {
- Exp_Binary *bin = (Exp_Binary*)data;
- const Type rhs = bin->rhs->info->type->info->base_type;
- const Nspc nspc = bin->lhs->info->type->nspc;
- for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) {
- if(rhs == *(Type*)(nspc->info->class_data + i))
- return env->gwion->type[et_bool];
- }
- return NULL; // err_msg
+ const M_Object o = *(M_Object*)REG(-SZ_INT);
+ *(m_uint*)o->data = instr->m_val;
+ memcpy(o->data + SZ_INT, REG(-SZ_INT-instr->m_val2), instr->m_val2);
+ *(m_bit**)REG(-SZ_INT) = o->data + SZ_INT;
}
-static INSTR(UnionEqClass) {
- POP_REG(shred, SZ_INT);
+static INSTR(UnionCheck) {
const M_Object o = *(M_Object*)REG(-SZ_INT);
- *(m_uint*)REG(-SZ_INT) = (UNION_IDX(o) == instr->m_val2);
- _release(o, shred);
+ if(*(m_uint*)o->data != instr->m_val)
+ Except(shred, _("invalid union access"))
+ POP_REG(shred, SZ_INT - instr->m_val2);
+ memcpy(REG(-instr->m_val2), o->data + SZ_INT, instr->m_val2);
}
-static OP_EMIT(opem_union_eq_class) {
- Exp_Binary *bin = (Exp_Binary*)data;
- const Type rhs = bin->rhs->info->type->info->base_type;
- const Nspc nspc = bin->lhs->info->type->nspc;
- const Instr instr = emit_add_instr(emit, UnionEqClass);
- if(!strcmp(s_name(bin->op), "!="))
- (void)emit_add_instr(emit, IntNot);
- for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) {
- if(rhs == *(Type*)(nspc->info->class_data + i)) {
- instr->m_val2 = i/SZ_INT + 1;
+static OP_EMIT(opem_union_dot) {
+ const Exp_Dot *member = (Exp_Dot*)data;
+ const Map map = &member->t_base->nspc->info->value->map;
+ for(m_uint i = 0; i < map_size(map); ++i) {
+ if(VKEY(map, i) == (m_uint)member->xid) {
+ CHECK_BO(emit_exp(emit, member->base))
+ const Instr instr = emit_add_instr(emit,
+ !exp_getvar(exp_self(member)) ? UnionCheck : UnionSet);
+ instr->m_val = i + 1;
+ instr->m_val2 = ((Value)VVAL(map, i))->type->size;
return instr;
}
}
return NULL;
}
-static INSTR(UnionNot) {
- const M_Object o = *(M_Object*)REG(-SZ_INT);
- const m_uint idx = UNION_IDX(o);
- if(idx) {
- const Type none = shred->info->vm->gwion->type[et_none];
- const Type curr = *(Type*)(o->type_ref->nspc->info->class_data + ((idx-1) * SZ_INT));
- *(m_uint*)REG(-SZ_INT) = curr == none;
- } else
- *(m_uint*)REG(-SZ_INT) = 1;
- _release(o, shred);
-}
-
static DTOR(UnionDtor) {
const m_uint idx = *(m_uint*)o->data;
if(idx) {
GWI_BB(gwi_class_end(gwi))
gwi->gwion->type[et_union] = t_union;
- GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@Union", NULL))
- GWI_BB(gwi_oper_add(gwi, opck_any_at_union))
- GWI_BB(gwi_oper_emi(gwi, opem_any_at_union))
- GWI_BB(gwi_oper_end(gwi, "?=>", NULL))
-
GWI_BB(gwi_oper_ini(gwi, "@Union", (m_str)OP_ANY_TYPE, NULL))
- GWI_BB(gwi_oper_add(gwi, opck_union_at_any))
- GWI_BB(gwi_oper_emi(gwi, opem_union_at_any))
- GWI_BB(gwi_oper_end(gwi, "?=>", NULL))
-
- GWI_BB(gwi_oper_ini(gwi, "@Union", "@Class", NULL))
- GWI_BB(gwi_oper_add(gwi, opck_union_eq_class))
- GWI_BB(gwi_oper_emi(gwi, opem_union_eq_class))
- GWI_BB(gwi_oper_end(gwi, "==", NULL))
- GWI_BB(gwi_oper_add(gwi, opck_union_eq_class))
- GWI_BB(gwi_oper_emi(gwi, opem_union_eq_class))
- GWI_BB(gwi_oper_end(gwi, "!=", NULL))
- GWI_BB(gwi_oper_ini(gwi, NULL, "@Union", "bool"))
- GWI_BB(gwi_oper_end(gwi, "!", UnionNot))
+ GWI_BB(gwi_oper_emi(gwi, opem_union_dot))
+ GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
GWI_BB(gwi_union_ini(gwi, "Option:[A]"))
- GWI_BB(gwi_union_add(gwi, "A"))
- GWI_BB(gwi_union_add(gwi, "None"))
+ GWI_BB(gwi_union_add(gwi, "None", "none"))
+ GWI_BB(gwi_union_add(gwi, "A", "val"))
GWI_BB(gwi_union_end(gwi, ae_flag_none))
return GW_OK;
continue;
const M_Operator* mo = operator_find(v, l, r);
if(mo) {
- if(mo->em)
- return mo->em(emit, (void*)opi->data);
- return handle_instr(emit, mo);
+ if(mo->em) {
+ const Instr ret = mo->em(emit, (void*)opi->data);
+ if(ret)
+ return ret;
+ }
+ else if(mo->func || mo->instr)
+ return handle_instr(emit, mo);
}
} while(r && (r = op_parent(emit->env, r)));
} while(l && (l = op_parent(emit->env, l)));
context_global(env);
CHECK_BB(scan0_defined(env, udef->xid, udef->pos))
udef->type = union_type(env, udef->xid);
- Type_List tl = udef->l;
- do udef->type->nspc->info->class_data_size += SZ_INT;
- while((tl = tl->next));
+ Union_List l = udef->l;
+ do udef->type->nspc->info->offset += SZ_INT;
+ while((l = l->next));
+ udef->type->nspc->info->offset += SZ_INT;
SET_ACCESS(udef, udef->type);
if(udef->tmpl)
union_tmpl(env, udef);
ANN static inline m_bool scan1_union_def_inner_loop(const Env env, Union_Def udef) {
nspc_allocdata(env->gwion->mp, udef->type->nspc);
- Type_List l = udef->l;
+ Union_List l = udef->l;
m_uint sz = 0;
- const Nspc nspc = udef->type->nspc;
- for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) {
- DECL_OB(const Type, t, =(*(Type*)(nspc->info->class_data + i) = known_type(env, l->td)))
+ do {
+ DECL_OB(const Type, t, = known_type(env, l->td))
+ if(nspc_lookup_value0(env->curr, l->xid))
+ ERR_B(l->pos, _("'%s' already declared in union"), s_name(l->xid))
+// check name
+puts(env->curr->name);
+ const Value v = new_value(env->gwion->mp, t, s_name(l->xid));
+ v->from->offset = SZ_INT;
+ valuefrom(env ,v->from);
+ nspc_add_value_front(env->curr, l->xid, v);
if(t->size > sz)
sz = t->size;
- l = l->next;
- }
- nspc->info->offset = sz + SZ_INT;
+ } while((l = l->next));
return GW_OK;
}
return GW_OK;
}
-ANN m_bool scan2_union_def(const Env env, const Union_Def udef) {
+ANN m_bool scan2_union_def(const Env env NUSED, const Union_Def udef) {
if(tmpl_base(udef->tmpl))
return GW_OK;
set_tflag(udef->type, tflag_scan2);
#! [contains] must be defined with empty
-union U { int : int [4] };
+union U {
+ int i;
+ int[4] j;
+}
#! [contains] can only be used at class scope.
-union static U { int };
+union static U { int i; }
#! [contains] can only be used at class scope.
-union private static U { int };
+union private static U { int i; }
#! [contains] can only be used at class scope.
-union private U { int };
+union private U { int i; }
GWION_IMPORT(checker) {
GWI_BB(gwi_union_ini(gwi, "U"))
- GWI_BB(gwi_union_add(gwi, "int"))
+ GWI_BB(gwi_union_add(gwi, "int", "i"))
return GW_OK;
}
GWION_IMPORT(union_test) {
GWI_BB(gwi_union_ini(gwi, "U"))
- GWI_BB(gwi_union_add(gwi,"float"))
- GWI_BB(gwi_union_add(gwi,"int"))
+ GWI_BB(gwi_union_add(gwi,"float", "f"))
+ GWI_BB(gwi_union_add(gwi,"int", "i"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
}
GWION_IMPORT(union_test) {
GWI_BB(gwi_union_ini(gwi, "U"))
- GWI_BB(gwi_union_add(gwi,"Float"))
- GWI_BB(gwi_union_add(gwi,"int"))
+ GWI_BB(gwi_union_add(gwi,"Float", "f"))
+ GWI_BB(gwi_union_add(gwi,"int", "i"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
}
GWION_IMPORT(union_member) {
GWI_OB(gwi_class_ini(gwi, "UnionMember", NULL))
GWI_BB(gwi_union_ini(gwi, "U"))
- GWI_BB(gwi_union_add(gwi,"float"))
- GWI_BB(gwi_union_add(gwi,"int[]"))
+ GWI_BB(gwi_union_add(gwi,"float", "f"))
+ GWI_BB(gwi_union_add(gwi,"int[]", "array"))
GWI_OB(gwi_union_end(gwi, ae_flag_none))
GWI_BB(gwi_class_end(gwi))
return GW_OK;
GWION_IMPORT(union_test) {
GWI_BB(gwi_union_ini(gwi, "my_union"))
- GWI_BB(gwi_union_add(gwi,"float"))
- GWI_BB(gwi_union_add(gwi,"int"))
+ GWI_BB(gwi_union_add(gwi,"float", "f"))
+ GWI_BB(gwi_union_add(gwi,"int", "i"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
}
GWION_IMPORT(union_test) {
GWI_BB(gwi_union_ini(gwi, "U:[A]"))
- GWI_BB(gwi_union_add(gwi,"float"))
- GWI_BB(gwi_union_add(gwi,"int"))
- GWI_BB(gwi_union_add(gwi,"A"))
+ GWI_BB(gwi_union_add(gwi,"float", "f"))
+ GWI_BB(gwi_union_add(gwi,"int", "i"))
+ GWI_BB(gwi_union_add(gwi,"A", "a"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
}
GWION_IMPORT(union_test) {
GWI_BB(gwi_union_ini(gwi, "U:[A]"))
- GWI_BB(gwi_union_add(gwi,"float"))
- GWI_BB(gwi_union_add(gwi,"int"))
- GWI_BB(gwi_union_add(gwi,"A"))
+ GWI_BB(gwi_union_add(gwi,"float", "f"))
+ GWI_BB(gwi_union_add(gwi,"int", "i"))
+ GWI_BB(gwi_union_add(gwi,"A", "a"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
}
GWION_IMPORT(union_test) {
GWI_BB(gwi_union_ini(gwi, "U:[A]"))
- GWI_BB(gwi_union_add(gwi,"float"))
- GWI_BB(gwi_union_add(gwi,"int"))
- GWI_BB(gwi_union_add(gwi,"A"))
+ GWI_BB(gwi_union_add(gwi,"float", "f"))
+ GWI_BB(gwi_union_add(gwi,"int", "i"))
+ GWI_BB(gwi_union_add(gwi,"A", "a"))
GWI_BB(gwi_union_ini(gwi, "U:[A]"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
GWION_IMPORT(union_test) {
GWI_BB(gwi_union_ini(gwi, "U:[A]"))
- GWI_BB(gwi_union_add(gwi,"float"))
- GWI_BB(gwi_union_add(gwi,"int"))
- GWI_BB(gwi_union_add(gwi,"A"))
+ GWI_BB(gwi_union_add(gwi,"float", "f"))
+ GWI_BB(gwi_union_add(gwi,"int", "i"))
+ GWI_BB(gwi_union_add(gwi,"A", "a"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
}