typedef enum {
et_void, et_int, et_bool, et_char, et_float,
et_error, et_compound, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack,
- et_function, et_fptr, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto,
+ et_function, et_fptr, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto, et_none,
MAX_TYPE
} type_enum;
#endif
INSTR(ArrayPost);
INSTR(ArrayInit);
INSTR(ArrayAlloc);
+INSTR(ArrayStruct);
/* vararg */
INSTR(VarargIni);
ANN static void clean_enum_def(Clean *a, Enum_Def b) {
clean_id_list(a, b->list);
+ if(b->values.ptr)
+ vector_release(&b->values);
}
ANN static void clean_union_def(Clean *a, Union_Def b) {
}
-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);
return GW_OK;
}
+ANN2(1,2) m_bool emit_instantiate_decl(const Emitter emit, const Type type,
+ const Type_Decl *td, const Array_Sub array, const m_bool is_ref) {
+ Exp base = td->array ? td->array->exp : NULL, exp = base,
+ next = array ? array->exp : NULL;
+ const m_uint depth = (td->array ? td->array->depth : 0) + (array ? array->depth : 0);
+ if(exp) {
+ while(exp->next)
+ exp = exp->next;
+ exp->next = next;
+ } else base = next;
+ struct Array_Sub_ a = { .exp=base, .depth=depth };
+ const m_bool ret = emit_instantiate_object(emit, type, &a, is_ref);
+ if(td->array && td->array->exp)
+ exp->next = NULL;
+ return ret;
+}
+
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 Exp dot = symbol_owned_exp(emit->gwion, data);
return GW_OK;
}
-ANN static m_bool decl_static(const Emitter emit, const Var_Decl var_decl, const uint is_ref) {
+ANN static m_bool decl_static(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl, const uint is_ref) {
const Value v = var_decl->value;
Code* code = emit->code;
emit->code = (Code*)vector_back(&emit->stack);
- CHECK_BB(emit_instantiate_object(emit, v->type, var_decl->array, is_ref))
+ CHECK_BB(emit_instantiate_decl(emit, v->type, decl->td, var_decl->array, is_ref))
CHECK_BB(emit_dot_static_data(emit, v, 1))
emit_add_instr(emit, Assign);
(void)emit_addref(emit, 0);
emit->code->frame->curr_offset -= t->size + SZ_INT;
}
-ANN static m_bool emit_exp_decl_static(const Emitter emit, const Var_Decl var_decl, const uint is_ref, const uint emit_addr) {
+ANN static m_bool emit_exp_decl_static(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl, const uint is_ref, const uint emit_addr) {
const Value v = var_decl->value;
if(isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
- CHECK_BB(decl_static(emit, var_decl, 0))
+ CHECK_BB(decl_static(emit, decl, var_decl, 0))
CHECK_BB(emit_dot_static_data(emit, v, !struct_ctor(v) ? emit_addr : 1))
if(struct_ctor(v))
emit_struct_decl_finish(emit, v->type, emit_addr);
const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1;
if(is_obj && (is_array || !is_ref))
- CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
+ CHECK_BB(emit_instantiate_decl(emit, type, decl->td, array, is_ref))
f_instr *exec = (f_instr*)allocmember;
if(!vflag(v, vflag_member)) {
v->from->offset = emit_local(emit, type);
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);
+/*
+ const size_t missing_depth = type->array_depth - (array ? array->depth : 0) - (decl->td->array ? decl->td->array->depth : 0);
if(missing_depth) {
const Instr push = emit_add_instr(emit, Reg2Reg);
push->m_val = -(missing_depth) * SZ_INT;
}
+*/
} else if(struct_ctor(v))
emit_struct_decl_finish(emit, v->type, emit_addr);
return GW_OK;
}
-ANN static m_bool emit_exp_decl_global(const Emitter emit, const Var_Decl var_decl,
+ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl,
const uint is_ref, const uint emit_var) {
const Value v = var_decl->value;
const Type type = v->type;
const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1;
if(is_obj && (is_array || !is_ref))
- CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
+ CHECK_BB(emit_instantiate_decl(emit, type, decl->td, array, is_ref))
const Instr instr = emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, dotstatic);
v->d.ptr = mp_calloc2(emit->gwion->mp, v->type->size);
if(isa(type, emit->gwion->type[et_union]) < 0)
instr->m_val2 = v->type->size;
if(is_obj && (is_array || !is_ref)) {
const Instr assign = emit_add_instr(emit, Assign);
- const size_t missing_depth = type->array_depth - (array ? array->depth : 0);
+ assign->m_val = emit_var;
+/*
+ const size_t missing_depth = type->array_depth - (array ? array->depth : 0) - (decl->td->array ? decl->td->array->depth : 0);
if(missing_depth) {
const Instr push = emit_add_instr(emit, Reg2Reg);
push->m_val = -(missing_depth) * SZ_INT;
}
- assign->m_val = emit_var;
+*/
(void)emit_addref(emit, emit_var);
} else if(struct_ctor(v))
emit_struct_decl_finish(emit, v->type, emit_addr);
Var_Decl_List list = decl->list;
do {
if(GET_FLAG(decl->td, static))
- CHECK_BB(emit_exp_decl_static(emit, list->self, ref, var))
+ CHECK_BB(emit_exp_decl_static(emit, decl, list->self, ref, var))
else if(!global)
CHECK_BB(emit_exp_decl_non_static(emit, decl, list->self, ref, var))
else
- CHECK_BB(emit_exp_decl_global(emit, list->self, ref, var))
- if(!var && !GET_FLAG(decl->td, optionnal) && (GET_FLAG(decl->td, ref) || is_fptr(emit->gwion, list->self->value->type)))
+ CHECK_BB(emit_exp_decl_global(emit, decl, list->self, ref, var))
+ if(!var && !decl->td->option && (GET_FLAG(decl->td, ref) || is_fptr(emit->gwion, list->self->value->type)))
ERR_B(list->self->pos, "kljlkj")
} while((list = list->next));
return GW_OK;
const m_bool ret = traverse_enum_def(gwion->env, edef);
import_enum_end(gwi, &edef->values);
const Type t = ret > 0 ? edef->t : NULL;
+ if(edef->values.ptr)
+ vector_release(&edef->values);
free_enum_def(gwion->mp, edef);
vector_release(&gwi->ck->v);
gwi->ck->v.ptr = NULL;
ERR_N(exp_self(call)->pos, _("can't call a non-callable value"))
}
+#define UNION_IDX(a) (*(m_uint*)(a->data))
static OP_CHECK(opck_any_at_union) {
Exp_Binary *bin = (Exp_Binary*)data;
CHECK_NN(opck_rassign(env, data, mut)) // check those two lines
- exp_setvar(bin->rhs, 0);
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 lhs;
+ 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);
- *(m_uint*)(o->data) = instr->m_val2;
+ 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) {
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 + 1;
+ instr->m_val2 = i/SZ_INT + 1;
instr->m_val = lhs->size;
return instr;
}
}
static OP_CHECK(opck_union_at_any) {
- Exp_Binary *bin = (Exp_Binary*)data;
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) {
static INSTR(UnionGet) {
const M_Object o = *(M_Object*)REG(-SZ_INT*2);
- if(*(m_uint*)(o->data) != instr->m_val2)
+ 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 + 1;
+ instr->m_val2 = i/SZ_INT + 1;
instr->m_val = rhs->size;
return instr;
}
static INSTR(UnionEqClass) {
POP_REG(shred, SZ_INT);
const M_Object o = *(M_Object*)REG(-SZ_INT);
- *(m_uint*)REG(-SZ_INT) = *(m_uint*)(o->data) == instr->m_val2;
-
+ *(m_uint*)REG(-SZ_INT) = (UNION_IDX(o) == instr->m_val2);
+ _release(o, shred);
}
static OP_EMIT(opem_union_eq_class) {
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 + 1;
+ instr->m_val2 = i/SZ_INT + 1;
return instr;
}
}
return NULL;
}
-DTOR(UnionDtor) {
+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) {
- const Type t = *(Type*)(o->type_ref->nspc->info->class_data + idx * SZ_INT);
+ const Type t = *(Type*)(o->type_ref->nspc->info->class_data + (idx-1) * SZ_INT);
if(isa(t, shred->info->vm->gwion->type[et_compound]) > 0)
- compound_release(shred, t, *(m_bit**)(o->data + SZ_INT));
+ compound_release(shred, t, (o->data + SZ_INT));
}
}
-static ID_CHECK(idck_none) {
- struct loc_t_ loc = {};
- return str2type(env->gwion, "None", &loc);
-}
-
-static ID_EMIT(idem_none) {
- return (Instr)1;
-}
-
ANN static m_bool import_core_libs(const Gwi gwi) {
const Type t_class = gwi_mk_type(gwi, "@Class", SZ_INT, NULL);
set_tflag(t_class, tflag_infer);
GWI_BB(gwi_set_global_type(gwi, t_compound, et_compound))
const Type t_none = gwi_mk_type(gwi, "None", 0, NULL);
+ GWI_BB(gwi_set_global_type(gwi, t_none, et_none))
GWI_BB(gwi_gack(gwi, t_none, gack_none))
gwi_add_type(gwi, t_none);
{
- struct SpecialId_ spid = { .ck=idck_none, .em=idem_none, .is_const=1 };
+// struct SpecialId_ spid = { .ck=idck_none, .em=idem_none, .is_const=1 };
+ struct SpecialId_ spid = { .type=gwi->gwion->type[et_none], .exec=NoOp, .is_const=1 };
gwi_specialid(gwi, "None", &spid);
}
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_union_ini(gwi, "Option:[A]"))
- GWI_BB(gwi_union_add(gwi, "None"))
GWI_BB(gwi_union_add(gwi, "A"))
+ GWI_BB(gwi_union_add(gwi, "None"))
GWI_BB(gwi_union_end(gwi, ae_flag_none))
return GW_OK;
CHECK_BB(scan0_defined(env, edef->xid, edef->pos))
CHECK_BB(scan0_global(env, edef->flag, edef->pos))
edef->t = enum_type(env, edef);
+ vector_init(&edef->values);
if(GET_FLAG(edef, global))
context_global(env);
return GW_OK;
ANN static Type union_type(const Env env, const Symbol s) {
const m_str name = s_name(s);
const Type t = new_type(env->gwion->mp, name, env->gwion->type[et_union]);
- t->size = SZ_INT;
t->nspc = new_nspc(env->gwion->mp, name);
t->info->owner = t->nspc->parent = env->curr;
t->info->owner_class = env->class_def;
return GW_OK;
}
+static inline uint array_ref(const Array_Sub array) {
+ return array && !array->exp;
+}
+
ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) {
Var_Decl_List list = decl->list;
do {
CHECK_BB(isres(env, var->xid, exp_self(decl)->pos))
Type t = decl->type;
CHECK_BB(scan1_defined(env, var))
- if(var->array) {
+ if(var->array) {
if(var->array->exp)
CHECK_BB(scan1_exp(env, var->array->exp))
t = array_type(env, decl->type, var->array->depth);
nspc_add_value(env->curr, var->xid, v);
v->flag |= decl->td->flag;
v->type = t;
- if(var->array && !var->array->exp)
+ if(array_ref(var->array))
SET_FLAG(decl->td, ref);
if(env->class_def) {
if(env->class_def->info->tuple)
ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) {
CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos))
((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl);
+ if(array_ref(decl->td->array))
+ SET_FLAG(decl->td, ref);
CHECK_OB(decl->type)
const m_bool global = GET_FLAG(decl->td, global);
if(global) {
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)))
+ DECL_OB(const Type, t, =(*(Type*)(nspc->info->class_data + i) = known_type(env, l->td)))
if(t->size > sz)
sz = t->size;
l = l->next;
}
- nspc->info->offset = sz;
+ nspc->info->offset = sz + SZ_INT;
return GW_OK;
}
}
ANN m_bool scan2_union_def(const Env env, const Union_Def udef) {
-// if(tmpl_base(udef->tmpl))
-// return GW_OK;
+ if(tmpl_base(udef->tmpl))
+ return GW_OK;
set_tflag(udef->type, tflag_scan2);
return GW_OK;
}
#include "traverse.h"
#include "parse.h"
-ANN static Type option(const Env env, Type_Decl* td) {
+ANN static Type _option(const Env env, Type_Decl* td, const m_uint n) {
struct Type_List_ tl = { .td=td };
- Type_Decl option_td = { .xid=insert_symbol("Option"), .types=&tl };
- UNSET_FLAG(td, optionnal);
- const Type ret = known_type(env, &option_td);
- SET_FLAG(td, optionnal);
+ Type_Decl option_td = { .xid=insert_symbol("Option"), .types=&tl, .pos=td->pos };
+ return !(n-1) ? known_type(env, &option_td) : _option(env, &option_td, n-1);
+}
+
+ANN static Type option(const Env env, Type_Decl* td) {
+ const m_uint option = td->option;
+ td->option = 0;
+ const Type ret = _option(env, td, option);
+ td->option = option;
return ret;
}
if(base->info->ctx && base->info->ctx->error)
ERR_O(td_pos(td), _("type '%s' is invalid"), base->name)
DECL_OO(const Type, t, = scan_type(env, base, td))
- const Type ret = !td->array ? t : array_type(env, t, td->array->depth);
- return !GET_FLAG(td, optionnal) ? ret : option(env, td);
+ const Type ret = !td->option ? t : option(env, td);
+ return !td->array ? ret : array_type(env, ret, td->array->depth);
}
struct td_info {
i++;
i ? i : !i;
++i;
- union { int ui; } u;
- union U:[A] { int ui; };
+ union U { int }
+ union V:[A] { int }
typeof(i);
if(i) i; else i;
for(var int _i; _i < 1; ++_i);
class C {
- union static {
- int i;
- float f;
- };
+ union static { int : float }
}
-union
-{
- int one;
- string two;
-};
+union U { int : string };
<<< one, " ", two >>>;
-union global GlobalUnion {
- int gui;
- float guf;
-};
+union global GlobalUnion { int : float };
<<<"test">>>;
-union U:[A]{
- int i;
- A a;
-};
+union U:[A]{ int : A }
var U:[float] u;
<<< u.a >>>;