#ifndef __IMPORT_UNION
#define __IMPORT_UNION
-ANN2(1) m_int gwi_union_ini(const Gwi gwi, const m_str type, const m_str name);
-ANN m_int gwi_union_add(const Gwi gwi, const __restrict__ m_str type, const __restrict__ m_str name);
+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, const __restrict__ m_str name);
ANN Type gwi_union_end(const Gwi gwi, const ae_flag flag);
ANN void ck_clean_udef(MemPool, ImportCK*);
RET_NSPC(exp) \
}
-ANN m_uint union_push(const Env, const Union_Def);
-ANN void union_pop(const Env, const Union_Def, const m_uint);
-ANN void union_flag(const Union_Def, const enum tflag);
ANN m_bool check_stmt(const Env env, const Stmt stmt);
typedef m_bool (*_exp_func)(const void*, const void*);
--- /dev/null
+#ifndef _TMPL_INFO
+#define _TMPL_INFO
+struct tmpl_info {
+ Symbol name;
+ ID_List list;
+ const Type_Decl* td;
+ Type ret;
+ Type base;
+ struct Vector_ type;
+ struct Vector_ size;
+ uint8_t index;
+};
+#endif
}
}
-
ANN static inline m_uint exp_size(const Exp e) {
if(exp_getvar(e))
return SZ_INT;
return GW_OK;
}
-ANN void emit_union_offset(Decl_List l, const m_uint o) {
- do {
- Var_Decl_List v = l->self->d.exp_decl.list;
- do v->self->value->from->offset = o;
- while((v = v->next));
- } while((l = l->next));
-}
-
-ANN static inline void union_allocdata(MemPool mp, const Union_Def udef) {
- const Nspc nspc = (udef->xid ? udef->value->type : udef->type)->nspc;
- nspc_allocdata(mp, nspc);
- nspc->info->offset = udef->s;
-}
-
-ANN static m_bool emit_union_def(const Emitter emit, const Union_Def udef) {
+ANN static m_bool emit_union_def(const Emitter emit NUSED, const Union_Def udef) {
if(tmpl_base(udef->tmpl))
return GW_OK;
- Decl_List l = udef->l;
- m_uint scope = emit->env->scope->depth;
- const m_bool global = GET_FLAG(udef, global);
- if(udef->xid) {
- union_allocdata(emit->gwion->mp, udef);
- Type_Decl *type_decl = new_type_decl(emit->gwion->mp,
- udef->xid, loc_cpy(emit->gwion->mp, udef->pos));
- type_decl->flag = udef->flag;
- const Var_Decl var_decl = new_var_decl(emit->gwion->mp, udef->xid, NULL, loc_cpy(emit->gwion->mp, udef->pos));
- const Var_Decl_List var_decl_list = new_var_decl_list(emit->gwion->mp, var_decl, NULL);
- const Exp exp = new_exp_decl(emit->gwion->mp, type_decl, var_decl_list, loc_cpy(emit->gwion->mp, udef->pos));
- exp->d.exp_decl.type = udef->value->type;
- var_decl->value = udef->value;
- const m_bool ret = emit_exp_decl(emit, &exp->d.exp_decl);
- free_exp(emit->gwion->mp, exp);
- CHECK_BB(ret)
- if(global) {
- const M_Object o = new_object(emit->gwion->mp, NULL, udef->value->type);
- udef->value->d.ptr = (m_uint*)o;
- set_vflag(udef->value, vflag_builtin);
- }
- scope = emit_push_type(emit, udef->value->type);
- } else if(udef->type_xid) {
- union_allocdata(emit->gwion->mp, udef);
- scope = emit_push_type(emit, udef->type);
- } else if(global) {
- // TODO: use mpool allocation
- void* ptr = (void*)xcalloc(1, udef->s);
- l = udef->l;
- udef->value->d.ptr = ptr;
- udef->value->vflag |= (vflag_enum | vflag_freeme);
- do {
- Var_Decl_List list = l->self->d.exp_decl.list;
- list->self->value->d.ptr = ptr;
- set_vflag(list->self->value, vflag_direct);// xcalloc
- } while((l = l->next));
- udef->l->self->d.exp_decl.list->self->value->vflag |= (vflag_enum | vflag_freeme);
- }
- if(udef->xid)
- regpop(emit, SZ_INT);
- emit_union_offset(udef->l, udef->o);
- if(udef->xid || udef->type_xid || global)
- emit_pop(emit, scope);
- union_flag(udef, tflag_emit);
+ set_tflag(udef->type, tflag_emit);
return GW_OK;
}
ANN static Type _get_type(const Gwi gwi, const m_str s) {
if(s == (m_str)OP_ANY_TYPE)
return OP_ANY_TYPE;
+ // str2type
Type_Decl *td = gwi_str2decl(gwi, s);
const Type t = known_type(gwi->gwion->env, td);
free_type_decl(gwi->gwion->mp, td);
return NULL;
}
-ANN2(1) m_int gwi_union_ini(const Gwi gwi, const m_str type, const m_str name) {
+ANN m_int gwi_union_ini(const Gwi gwi, const m_str name) {
CHECK_BB(ck_ini(gwi, ck_udef))
- if(name)
- CHECK_OB((gwi->ck->xid = gwi_str2sym(gwi, name)))
- gwi->ck->name = type;
- if(type)
- CHECK_BB(check_typename_def(gwi, gwi->ck))
+ gwi->ck->name = name;
+ CHECK_BB(check_typename_def(gwi, gwi->ck))
return GW_OK;
}
ANN static Type union_type(const Gwi gwi, const Union_Def udef) {
CHECK_BO(scan0_union_def(gwi->gwion->env, udef))
CHECK_BO(traverse_union_def(gwi->gwion->env, udef))
- if(!udef->tmpl)
- emit_union_offset(udef->l, udef->o);
- if(gwi->gwion->env->class_def && !GET_FLAG(udef, static))
- gwi->gwion->env->class_def->nspc->info->offset =
- udef->o + udef->s;
- if(udef->xid || !udef->type_xid) {
- set_vflag(udef->value, vflag_builtin);
- const M_Object o = new_object(gwi->gwion->mp, NULL, udef->value->type);
- udef->value->d.ptr = (m_uint*)o;
- return udef->value->type;
- }
+// if(!udef->tmpl)
+// emit_union_offset(udef->l, udef->o);
+// if(gwi->gwion->env->class_def && !GET_FLAG(udef, static))
+// gwi->gwion->env->class_def->nspc->info->offset =
+// udef->o + udef->s;
+// set_vflag(udef->value, vflag_builtin);
+// const M_Object o = new_object(gwi->gwion->mp, NULL, udef->value->type);
+// udef->value->d.ptr = (m_uint*)o;
return udef->type;
}
CHECK_BO(ck_ok(gwi, ck_udef))
if(!gwi->ck->list)
GWI_ERR_O(_("union is empty"));
- if(gwi->ck->tmpl && gwi->ck->xid)
- GWI_ERR_O(_("Template union type can't declare instance at declaration"));
const Union_Def udef = new_union_def(gwi->gwion->mp, gwi->ck->list, loc(gwi));
gwi->ck->list = NULL;
udef->flag = flag;
- udef->xid = gwi->ck->xid;
- udef->type_xid = gwi->ck->sym;
+ udef->xid = gwi->ck->sym;
if(gwi->ck->tmpl) {
udef->tmpl = gwi_tmpl(gwi);
gwi->ck->tmpl = NULL;
ERR_N(exp_self(call)->pos, _("can't call a non-callable value"))
}
+static OP_CHECK(opck_dot_union) {
+ Exp_Dot *dot = (Exp_Dot*)data;
+ const Value v = nspc_lookup_value0(dot->t_base->nspc, dot->xid);
+ if(!v)
+ ERR_N(exp_self(dot)->pos, _("'%s' is not legit in '%s'\n"), s_name(dot->xid), dot->t_base->name)
+ return v->type;
+}
+
+static INSTR(UnionSet) {
+ const M_Object o = *(M_Object*)REG(-SZ_INT);
+ *(m_uint*)(o->data) = instr->m_val2;
+ memset(o->data + SZ_INT, 0, instr->m_val); // needed only for object!
+ *(void**)REG(-instr->m_val) = &*(m_bit**)(o->data + SZ_INT);
+}
+
+static INSTR(UnionGet) {
+ const M_Object o = *(M_Object*)REG(-SZ_INT);
+ if(*(m_uint*)(o->data) != instr->m_val2)
+ Except(shred, "invalid union access");
+ POP_REG(shred, SZ_INT - instr->m_val);
+ memcpy(REG(-instr->m_val), o->data + SZ_INT, instr->m_val);
+}
+
+static OP_EMIT(opem_dot_union) {
+ Exp_Dot *dot = (Exp_Dot*)data;
+ CHECK_BO(emit_exp(emit, dot->base))
+ const uint emit_var = exp_getvar(exp_self(dot));
+ const Value v = nspc_lookup_value0(dot->t_base->nspc, dot->xid);
+ const Instr instr = emit_add_instr(emit, !emit_var ? UnionGet : UnionSet);
+ instr->m_val = !emit_var ? v->type->size : SZ_INT;
+ instr->m_val2 = v->from->offset;
+ return instr;
+}
+
+DTOR(UnionDtor) {
+ const m_uint idx = *(m_uint*)o->data;
+ if(idx) {
+ const Type t = (Type)vector_at(&o->type_ref->info->tuple->contains, idx - 1);
+ if(isa(t, shred->info->vm->gwion->type[et_compound]) > 0)
+ compound_release(shred, t, *(m_bit**)(o->data + SZ_INT));
+ }
+}
+
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_class, et_class))
- GWI_BB(gwi_gack(gwi, t_class, gack_class)) // not working yet
- 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, t_class, gack_class))
+
const Type t_undefined = gwi_mk_type(gwi, "@Undefined", SZ_INT, NULL);
GWI_BB(gwi_set_global_type(gwi, t_undefined, et_undefined))
const Type t_auto = gwi_mk_type(gwi, "auto", SZ_INT, NULL);
const Type t_compound = gwi_mk_type(gwi, "@Compound", 0, NULL);
GWI_BB(gwi_gack(gwi, t_compound, gack_compound))
GWI_BB(gwi_set_global_type(gwi, t_compound, et_compound))
+
GWI_BB(import_object(gwi))
+
+ const Type t_union = gwi_class_ini(gwi, "@Union", "Object");
+ gwi_class_xtor(gwi, NULL, UnionDtor);
+ GWI_BB(gwi_item_ini(gwi, "int", "@index"))
+ GWI_BB(gwi_item_end(gwi, ae_flag_none, NULL))
+ GWI_BB(gwi_class_end(gwi))
+ GWI_BB(gwi_gack(gwi, t_union, gack_compound))
+ gwi->gwion->type[et_union] = t_union;
+
GWI_BB(import_prim(gwi))
const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
GWI_BB(gwi_gack(gwi, t_function, gack_function))
GWI_BB(import_object_op(gwi))
GWI_BB(import_values(gwi))
-// TODO: check me
- const Type t_union = gwi_class_ini(gwi, "@Union", NULL);
- gwi->gwion->type[et_union] = t_union;
- GWI_BB(gwi_class_end(gwi))
-
GWI_BB(import_array(gwi))
GWI_BB(import_event(gwi))
GWI_BB(import_ugen(gwi))
GWI_BB(gwi_oper_add(gwi, opck_new))
GWI_BB(gwi_oper_emi(gwi, opem_new))
GWI_BB(gwi_oper_end(gwi, "new", NULL))
-// GWI_BB(import_prim(gwi))
GWI_BB(import_vararg(gwi))
GWI_BB(import_string(gwi))
GWI_BB(import_shred(gwi))
GWI_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL))
GWI_BB(gwi_oper_add(gwi, opck_basic_ctor))
GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
+
+ GWI_BB(gwi_oper_ini(gwi, "@Compound", (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_oper_ini(gwi, "@Class", (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_oper_ini(gwi, "@Union", (m_str)OP_ANY_TYPE, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_dot_union))
+ GWI_BB(gwi_oper_emi(gwi, opem_dot_union))
+ GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
+
+ GWI_BB(gwi_union_ini(gwi, "Option:[A]"))
+ GWI_BB(gwi_union_add(gwi, "A", "@val"))
+ GWI_BB(gwi_union_end(gwi, ae_flag_none))
+
return GW_OK;
}
MemPool p = shred->info->mp;
Type t = o->type_ref;
do {
- if(!t->nspc || is_special(t))
+ if(!t->nspc || is_special(t) || tflag(t, tflag_udef))
continue;
struct scope_iter iter = { t->nspc->info->value, 0, 0 };\
Value v;
#include "template.h"
#include "parse.h"
#include "specialid.h"
-
#include "gwi.h"
+#include "tmpl_info.h"
#undef insert_symbol
return unary->exp->info->type;
}
-ANN /*static*/ Type scan_class(const Env env, const Type t, const Type_Decl* td);
+ANN /*static*/ Type scan_class(const Env env, const Type t, const Type_Decl * td);
static Type opck_object_scan(const Env env, const struct TemplateScan *ts) {
if(ts->td->types)
const m_str str = s_name(member->xid);
const m_bool base_static = is_class(env->gwion, member->t_base);
const Type the_base = base_static ? member->t_base->info->base_type : member->t_base;
- if(!the_base->nspc)
- ERR_N(member->base->pos,
- _("type '%s' does not have members - invalid use in dot expression of %s"),
- the_base->name, str)
+// if(!the_base->nspc)
+// ERR_N(member->base->pos,
+// _("type '%s' does not have members - invalid use in dot expression of %s"),
+// the_base->name, str)
if(member->xid == insert_symbol(env->gwion->st, "this") && base_static)
ERR_N(exp_self(member)->pos,
_("keyword 'this' must be associated with object instance..."))
if(!tflag(t_base, tflag_struct))
emit_member(emit, value, exp_getvar(exp_self(member)));
else {
-// exp_setvar(member->base, exp_getvar(exp_self(member)));
exp_setvar(member->base, 1);
CHECK_BO(emit_exp(emit, member->base))
emit_struct_data(emit, value, exp_getvar(exp_self(member)));
return (Instr)GW_OK;
}
-struct tmpl_info {
- Symbol name;
- ID_List list;
- Type_List call;
- Type ret;
- Type base;
- struct Vector_ type;
- struct Vector_ size;
- uint8_t index;
-};
-
-ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
- vector_add(&info->type, (vtype)t);
- const size_t len = strlen(t->name);
- vector_add(&info->size, len);
- return len;
-}
-
-ANN static ssize_t template_size(const Env env, struct tmpl_info* info) {
- ID_List base = info->list; // ???
- Type_List call = info->call;
- size_t size = 0;
- do {
- DECL_OB(const Type, t, = known_type(env, call->td))
- size += tmpl_set(info, t);
- } while((call = call->next) && (base = base->next) && ++size);
-// } while((call = call->next) && ++size);
- size += tmpl_set(info, info->base);
- return size + 4;
-}
-
-ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) {
- const Type t = (Type)vector_at(&info->type, info->index);
- strcpy(str, t->name);
- return str += vector_at(&info->size, info->index);
-}
-
-ANN static void template_name(struct tmpl_info* info, m_str s) {
- m_str str = s;
- const m_uint size = info->index = vector_size(&info->type) -1;
- str = tmpl_get(info, str);
- *str++ = ':';
- *str++ = '[';
- for(info->index = 0; info->index < size; ++info->index) {
- str = tmpl_get(info, str);
- if(info->index < size - 1)
- *str++ = ',';
- else {
- *str++ = ']';
- }
- }
- *str = '\0';
-}
-
-ANEW ANN static Symbol template_id(const Env env, struct tmpl_info* info) {
- vector_init(&info->type);
- vector_init(&info->size);
- ssize_t sz = template_size(env, info);
- char name[sz];
- if(sz > GW_ERROR)
- template_name(info, name);
- vector_release(&info->type);
- vector_release(&info->size);
- return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL;
-}
-
-ANN static m_bool template_match(ID_List base, Type_List call) {
- while((call = call->next) && (base = base->next));
- return !call ? GW_OK : GW_ERROR;
-}
-
-ANN static Type tmpl_exists(const Env env, const Symbol name) {
- if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name))
- return env->class_def;
- return nspc_lookup_type1(env->curr, name);
-}
-
ANN static m_bool scantmpl_class_def(const Env env, struct tmpl_info *info) {
const Class_Def c = info->base->info->cdef;
const Class_Def cdef = new_class_def(env->gwion->mp, c->flag, info->name, c->base.ext ? cpy_type_decl(env->gwion->mp, c->base.ext) : NULL,
c->body ?cpy_ast(env->gwion->mp, c->body) : NULL,
loc_cpy(env->gwion->mp, c->pos));
cdef->cflag = c->cflag;
- cdef->base.tmpl = mk_tmpl(env, c->base.tmpl, info->call);
+ cdef->base.tmpl = mk_tmpl(env, c->base.tmpl, info->td->types);
const m_bool ret = scan0_class_def(env, cdef);
if((info->ret = cdef->base.type)) {
info->ret->info->cdef = cdef;
return ret;
}
+ANN static OP_CHECK(opck_option_get) {
+ Exp_Binary *bin = (Exp_Binary*)data;
+ exp_setvar(bin->rhs, 1);
+ return bin->rhs->info->type;
+}
+
+static INSTR(OptionCheck) {
+ const M_Object o = *(M_Object*)REG(-SZ_INT*2);
+ if(*(m_uint*)(o->data) != 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(&*(m_bit*)REG(-instr->m_val), o->data + SZ_INT, instr->m_val);
+}
+
+ANN static OP_EMIT(opem_option_get) {
+ Exp_Binary *bin = (Exp_Binary*)data;
+ const Instr instr = emit_add_instr(emit, OptionCheck);
+ instr->m_val = bin->rhs->info->type->size;
+ instr->m_val2 = 1;
+ return instr;
+}
+
+ANN static OP_CHECK(opck_option_set) {
+ Exp_Binary *bin = (Exp_Binary*)data;
+ CHECK_NN(opck_rassign(env, data, mut)) // check those two lines
+ exp_setvar(bin->rhs, 0);
+ const Value v = nspc_lookup_value0(bin->rhs->info->type->nspc, insert_symbol(env->gwion->st, "@val"));
+ return v->type;
+}
+
+static INSTR(OptionSet) {
+ M_Object o = *(M_Object*)REG(-SZ_INT);
+ *(m_uint*)(o->data) = instr->m_val2;
+ *(m_bit**)(o->data + SZ_INT) = *(void**)REG(-instr->m_val);
+}
+
+ANN static OP_EMIT(opem_option_set) {
+ Exp_Binary *bin = (Exp_Binary*)data;
+ const Value v = nspc_lookup_value0(bin->rhs->info->type->nspc, insert_symbol(emit->gwion->st, "@val"));
+ const Instr set = emit_add_instr(emit, OptionSet);
+ set->m_val = SZ_INT + v->type->size;
+ set->m_val2 = 1;
+ const Instr pop = emit_add_instr(emit, RegPop);
+ pop->m_val = SZ_INT;
+ return set;
+}
+
+ANN static OP_CHECK(opck_option_setn) {
+ Exp_Binary *bin = (Exp_Binary*)data;
+ CHECK_NN(opck_rassign(env, data, mut))
+ exp_setvar(bin->rhs, 1);
+ return env->gwion->type[et_void];
+}
+
+ANN static OP_EMIT(opem_option_setn) {
+ Exp_Binary *bin = (Exp_Binary*)data;
+ const Instr instr = emit_add_instr(emit, OptionSet);
+ instr->m_val = bin->rhs->info->type->nspc->info->offset;
+ const Instr pop2 = emit_add_instr(emit, RegPop);
+ pop2->m_val = SZ_INT * 2;
+ return instr;
+}
+
+ANN static OP_EMIT(opem_option_not) {
+ Exp_Unary *unary = (Exp_Unary*)data;
+ const Instr pop = emit_add_instr(emit, RegPop);
+ pop->m_val = unary->exp->info->type->nspc->info->offset - sizeof(uint16_t)*2;
+ const Instr set = emit_add_instr(emit, Reg2Reg);
+ set->m_val = -sizeof(uint16_t)*2;
+ set->m_val2 = unary->exp->info->type->nspc->info->offset - sizeof(uint16_t)*2;
+ return emit_add_instr(emit, IntNot);
+}
+
+ANN static OP_EMIT(opem_option_cond) {
+ Exp exp = (Exp)data;
+ const Instr set = emit_add_instr(emit, Reg2Reg);
+ set->m_val = -exp->info->type->size;
+ set->m_val2 = -sizeof(uint16_t)*2;
+ const Instr pop2 = emit_add_instr(emit, RegPop);
+ pop2->m_val = exp->info->type->nspc->info->offset - sizeof(uint16_t)*2;
+ const Instr instr = emit_add_instr(emit, BranchEqInt);
+ return instr;
+}
+
+ANN static OP_EMIT(opem_option_uncond) {
+ Exp exp = (Exp)data;
+ const Instr set = emit_add_instr(emit, Reg2Reg);
+ set->m_val = -exp->info->type->size;
+ set->m_val2 = -sizeof(uint16_t)*2;
+ const Instr pop2 = emit_add_instr(emit, RegPop);
+ pop2->m_val = exp->info->type->size - sizeof(uint16_t)*2;
+ const Instr instr = emit_add_instr(emit, BranchNeqInt);
+ return instr;
+}
+
+
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_decl_list(env->gwion->mp, u->l),
loc_cpy(env->gwion->mp, u->pos));
- udef->type_xid = info->name;
- udef->tmpl = mk_tmpl(env, u->tmpl, info->call);
+ udef->xid = info->name;
+ udef->tmpl = mk_tmpl(env, u->tmpl, info->td->types);
if(GET_FLAG(info->base, global))
SET_FLAG(udef, global);
const m_bool ret = scan0_union_def(env, udef);
if(udef->type) {
+ if(!strcmp(info->base->name, "Option")) {
+ const Type base = known_type(env, info->td->types->td);
+ const m_uint scope = env_push(env, udef->type->info->parent->info->owner_class, udef->type->info->parent->info->owner);
+ const struct Op_Func opfunc0 = { .ck=opck_option_get, .em=opem_option_get };
+ struct Op_Import opi0 = { .lhs=udef->type, .rhs=base, .ret=base,
+ .op=insert_symbol(env->gwion->st, "?=>"), .pos=info->td->pos, .func=&opfunc0 };
+ CHECK_BB(add_op(env->gwion, &opi0))
+ const struct Op_Func opfunc1 = { .ck=opck_option_set, .em=opem_option_set };
+ struct Op_Import opi1 = { .lhs=base, .rhs=udef->type, .ret=udef->type, .func=&opfunc1,
+ .op=insert_symbol(env->gwion->st, "@=>"), .pos=info->td->pos };
+ CHECK_BB(add_op(env->gwion, &opi1))
+ const struct Op_Func opfunc2 = { .ck=opck_option_setn, .em=opem_option_setn };
+ struct Op_Import opi2 = { .lhs=env->gwion->type[et_null], .rhs=udef->type, .ret=udef->type, .func=&opfunc2,
+ .op=insert_symbol(env->gwion->st, "@=>"), .pos=info->td->pos };
+ CHECK_BB(add_op(env->gwion, &opi2))
+ const struct Op_Func opfunc3 = { .em=opem_option_not };
+ struct Op_Import opi3 = { .rhs=udef->type, .ret=env->gwion->type[et_bool], .func=&opfunc3,
+ .op=insert_symbol(env->gwion->st, "!"), .pos=info->td->pos };
+ CHECK_BB(add_op(env->gwion, &opi3))
+ const struct Op_Func opfunc4 = { .em=opem_option_cond };
+ struct Op_Import opi4 = { .rhs=udef->type, .ret=env->gwion->type[et_bool], .func=&opfunc4,
+ .op=insert_symbol(env->gwion->st, "@conditionnal"), .pos=info->td->pos };
+ CHECK_BB(add_op(env->gwion, &opi4))
+ const struct Op_Func opfunc5 = { .em=opem_option_uncond };
+ struct Op_Import opi5 = { .rhs=udef->type, .ret=env->gwion->type[et_bool], .func=&opfunc5,
+ .op=insert_symbol(env->gwion->st, "@unconditionnal"), .pos=info->td->pos };
+ CHECK_BB(add_op(env->gwion, &opi5))
+ env_pop(env, scope);
+ }
udef->type->info->udef = udef;// mark as udef
info->ret = udef->type;
set_tflag(info->ret, tflag_udef);
return info->ret;
}
-ANN Type scan_class(const Env env, const Type t, const Type_Decl* td) {
- if(template_match(t->info->cdef->base.tmpl->list, td->types) < 0) // invalid template
- ERR_O(td->pos, _("invalid template types number"))
- struct tmpl_info info = { .base=t, .call=td->types, .list=t->info->cdef->base.tmpl->list };
- DECL_OO(const Symbol, name, = info.name = template_id(env, &info))
- const Type exists = tmpl_exists(env, name);
+ANN Type tmpl_exists(const Env env, struct tmpl_info *const info);
+ANN Type scan_class(const Env env, const Type t, const Type_Decl *td) {
+ struct tmpl_info info = { .base=t, .td=td, .list=t->info->cdef->base.tmpl->list };
+ const Type exists = tmpl_exists(env, &info);
if(exists)
- return exists;
+ return exists != env->gwion->type[et_null] ? exists : NULL;
struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan0_cdef,
.scope=env->scope->depth, .flag=tflag_scan0 };
CHECK_BO(envset_push(&es, t->info->owner_class, t->info->ctx ? t->info->ctx->nspc : env->curr))
GWI_BB(gwi_oper_emi(gwi, opem_object_cast))
GWI_BB(gwi_oper_end(gwi, "$", NULL))
GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool"))
- GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
+ GWI_BB(gwi_oper_add(gwi, opck_unary_meta2)) // this is suspicious
GWI_BB(gwi_oper_add(gwi, opck_object_not))
GWI_BB(gwi_oper_end(gwi, "!", IntNot))
GWI_BB(gwi_oper_ini(gwi, "@Compound", NULL, NULL))
GWI_BB(gwi_gack(gwi, t_bool, gack_bool))
gwi->gwion->type[et_bool] = t_bool;
GWI_BB(gwi_oper_ini(gwi, NULL, "int", "bool"))
- GWI_BB(gwi_oper_add(gwi, opck_unary_meta)) // should return bool
+ GWI_BB(gwi_oper_add(gwi, opck_unary_meta))
GWI_BB(gwi_oper_end(gwi, "!", IntNot))
struct SpecialId_ spid = { .type=t_bool, .exec=RegPushMaybe, .is_const=1 };
gwi_specialid(gwi, "maybe", &spid);
GWI_BB(gwi_oper_ini(gwi, "float", "dur", "dur"))
GWI_BB(gwi_oper_end(gwi, "::", FloatTimes))
GWI_BB(gwi_oper_ini(gwi, NULL, "float", "bool"))
- GWI_BB(gwi_oper_add(gwi, opck_unary_meta2)) // should return bool
+ GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
GWI_BB(gwi_oper_end(gwi, "!", float_not))
return GW_OK;
}
--- /dev/null
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "object.h"
+#include "operator.h"
+#include "traverse.h"
+#include "parse.h"
+#include "tmpl_info.h"
+
+ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) {
+ const Type t = (Type)vector_at(&info->type, info->index);
+ strcpy(str, t->name);
+ return str += vector_at(&info->size, info->index);
+}
+
+ANN static void template_name(struct tmpl_info* info, m_str s) {
+ m_str str = s;
+ const m_uint size = info->index = vector_size(&info->type) -1;
+ str = tmpl_get(info, str);
+ *str++ = ':';
+ *str++ = '[';
+ for(info->index = 0; info->index < size; ++info->index) {
+ str = tmpl_get(info, str);
+ if(info->index < size - 1)
+ *str++ = ',';
+ else
+ *str++ = ']';
+ }
+ *str = '\0';
+}
+
+ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
+ vector_add(&info->type, (vtype)t);
+ const size_t len = strlen(t->name);
+ vector_add(&info->size, len);
+ return len;
+}
+
+ANN static ssize_t template_size(const Env env, struct tmpl_info* info) {
+ ID_List base = info->list; // ???
+ Type_List call = info->td->types;
+ size_t size = 0;
+ do {
+ DECL_OB(const Type, t, = known_type(env, call->td))
+ size += tmpl_set(info, t);
+ } while((call = call->next) && (base = base->next) && ++size);
+ size += tmpl_set(info, info->base);
+ return size + 4;
+}
+
+ANEW ANN static Symbol template_id(const Env env, struct tmpl_info *const info) {
+ vector_init(&info->type);
+ vector_init(&info->size);
+ ssize_t sz = template_size(env, info);
+ char name[sz];
+ if(sz > GW_ERROR)
+ template_name(info, name);
+ vector_release(&info->type);
+ vector_release(&info->size);
+ return sz > GW_ERROR ? insert_symbol(name) : NULL;
+}
+
+ANN static m_bool template_match(ID_List base, Type_List call) {
+ while((call = call->next) && (base = base->next));
+ return !call ? GW_OK : GW_ERROR;
+}
+
+ANN static Type _tmpl_exists(const Env env, const Symbol name) {
+ if(env->class_def && name == insert_symbol(env->class_def->name))
+ return env->class_def;
+ return nspc_lookup_type1(env->curr, name);
+}
+
+ANN Type tmpl_exists(const Env env, struct tmpl_info *const info) {
+ if(template_match(info->list, info->td->types) < 0) // invalid template
+ ERR_N(info->td->pos, _("invalid template types number"))
+ DECL_ON(const Symbol, name, = info->name = template_id(env, info))
+ return _tmpl_exists(env, name);
+}
ANN m_bool check_union_decl(const Env env, const Union_Def udef) {
Decl_List l = udef->l;
+ m_uint sz = 0, idx = 0;
do {
CHECK_OB(check_exp(env, l->self))
Var_Decl_List list = l->self->d.exp_decl.list;
+ list->self->value->from->offset = ++idx;
do set_vflag(list->self->value, vflag_union);
- while((list = list->next));
- if(l->self->info->type->size > udef->s)
- udef->s = l->self->info->type->size;
+ while((list = list->next)); // disallow multiple values here.
+ if(l->self->info->type->size > sz)
+ sz = l->self->info->type->size;
} while((l = l->next));
+ udef->type->nspc->info->offset = sz + SZ_INT;
return GW_OK;
}
-ANN void check_udef(const Env env, const Union_Def udef) {
- if(udef->xid) {
- if(env->class_def)
- (!GET_FLAG(udef, static) ? decl_member : decl_static)(env, udef->value);
- else if(env->class_def) {
- if(!GET_FLAG(udef, static))
- udef->o = env->class_def->nspc->info->offset;
- else {
- udef->o = env->class_def->nspc->info->class_data_size;
- env->class_def->nspc->info->class_data_size += SZ_INT;
- }
- }
- }
-}
-
ANN m_bool check_union_def(const Env env, const Union_Def udef) {
if(tmpl_base(udef->tmpl)) // there's a func for this
return GW_OK;
- check_udef(env, udef);
- const m_uint scope = union_push(env, udef);
+ const m_uint scope = env_push_type(env, udef->type);
const m_bool ret = check_union_decl(env, udef);
- if(!udef->xid && !udef->type_xid && env->class_def && !GET_FLAG(udef, static))
- env->class_def->nspc->info->offset = udef->o + udef->s;
- union_pop(env, udef, scope);
- union_flag(udef, tflag_check);
+ env_pop(env, scope);
+ set_tflag(udef->type, tflag_check);
return ret;
}
return GW_OK;
}
-ANN static Type union_type(const Env env, const Symbol s, const m_bool add) {
+ANN static Type union_type(const Env env, const Symbol s) {
const m_str name = s_name(s);
- const Type t = type_copy(env->gwion->mp, env->gwion->type[et_union]);
- t->name = name;
+ 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;
- t->info->parent = env->gwion->type[et_union];
t->info->tuple = new_tupleform(env->gwion->mp, NULL);
add_type(env, env->curr, t);
- if(add)
- mk_class(env, t);
+ mk_class(env, t);
+ SET_FLAG(t, final);
return t;
}
set_tflag(u->type, tflag_tmpl);
set_tflag(u->type, tflag_udef);
}
- if(GET_FLAG(udef, global))
- SET_FLAG(udef->type, global);
-}
-
-ANN static Value union_value(const Env env, const Type t, const Symbol sym) {
- const Value v = new_value(env->gwion->mp, t, s_name(sym));
- valuefrom(env, v->from);
- nspc_add_value(env->curr, sym, v);
- set_vflag(v, vflag_union);
- return v;
+// if(GET_FLAG(udef, global))
+// SET_FLAG(udef->type, global);
}
ANN m_bool scan0_union_def(const Env env, const Union_Def udef) {
env_push_global(env);
if(GET_FLAG(udef, global))
context_global(env);
- if(udef->xid) {
- CHECK_BB(scan0_defined(env, udef->xid, udef->pos))
- const Symbol sym = udef->type_xid ?: scan0_sym(env, "union", udef->pos);
- const Type t = union_type(env, sym, !!udef->type_xid);
- udef->value = union_value(env, t, udef->xid);
- udef->value->flag |= udef->flag;
- SET_ACCESS(udef, t);
- if(env->class_def && !GET_FLAG(udef, static))
- set_vflag(udef->value, vflag_member);
- } else if(udef->type_xid) {
- CHECK_BB(scan0_defined(env, udef->type_xid, udef->pos))
- udef->type = union_type(env, udef->type_xid, 1);
- SET_ACCESS(udef, udef->type);
- } else {
- const Symbol sym = scan0_sym(env, "union", udef->pos);
- CHECK_BB(scan0_defined(env, sym, udef->pos))
- const Type t = union_type(env, sym, 1);
- SET_ACCESS(udef, t);
- udef->value = union_value(env, t, sym);
- udef->value->flag |= udef->flag;
- }
+ CHECK_BB(scan0_defined(env, udef->xid, udef->pos))
+ udef->type = union_type(env, udef->xid);
+ SET_ACCESS(udef, udef->type);
if(udef->tmpl)
union_tmpl(env, udef);
if(GET_FLAG(udef, global))
env_pop(env, scope);
- union_flag(udef, tflag_scan0);
+ set_tflag(udef->type, tflag_scan0);
return GW_OK;
}
scan1_cdef(env, tdef->type) : GW_OK;
}
-ANN static m_bool scan1_union_def_action(const Env env, const Union_Def udef,
- const Decl_List l) {
- const Exp_Decl decl = l->self->d.exp_decl;
- decl.td->flag |= udef->flag;
- const m_bool global = GET_FLAG(udef, global);
- if(global)
- UNSET_FLAG(decl.td, global);
- else if(GET_FLAG(udef, static))
- SET_FLAG(decl.td, static);
- CHECK_BB(scan1_exp(env, l->self))
-
- Var_Decl_List list = decl.list;
- do value_addref(list->self->value);
- while((list = list->next));
-
- if(global)
- SET_FLAG(decl.td, global);
- return GW_OK;
-}
-
-ANN static inline m_bool scan1_union_def_inner_loop(const Env env, const Union_Def udef, Decl_List l) {
- do CHECK_BB(scan1_union_def_action(env, udef, l))
+ANN static inline m_bool scan1_union_def_inner_loop(const Env env, Decl_List l) {
+ do CHECK_BB(scan1_exp(env, l->self))
while((l = l->next));
return GW_OK;
}
ANN static m_bool scan1_union_def_inner(const Env env, const Union_Def udef) {
if(udef->tmpl && udef->tmpl->call)
CHECK_BB(template_push_types(env, udef->tmpl))
- const m_bool ret = scan1_union_def_inner_loop(env, udef, udef->l);
+ const m_bool ret = scan1_union_def_inner_loop(env, udef->l);
if(udef->tmpl && udef->tmpl->call)
nspc_pop_type(env->gwion->mp, env->curr);
return ret;
ANN m_bool scan1_union_def(const Env env, const Union_Def udef) {
if(tmpl_base(udef->tmpl))
return GW_OK;
- const m_uint scope = union_push(env, udef);
- if(udef->xid || udef->type_xid) {
- UNSET_FLAG(udef, private);
- UNSET_FLAG(udef, protect);
- }
+ const m_uint scope = env_push_type(env, udef->type);
const m_bool ret = scan1_union_def_inner(env, udef);
- union_pop(env, udef, scope);
- union_flag(udef, tflag_scan1);
+ env_pop(env, scope);
+ set_tflag(udef->type, tflag_scan1);
return ret;
}
return GW_OK;
}
-ANN static m_bool scan2_union_decl(const Env env, const Decl_List list) {
- Decl_List l = list;
- do CHECK_BB(scan2_exp_decl(env, &l->self->d.exp_decl))
-// do CHECK_BB(scan2_exp(env, l->self))
+ANN static m_bool scan2_union_decl(const Env env, Decl_List l) {
+ do CHECK_BB(scan2_exp(env, l->self))
while((l = l->next));
return GW_OK;
}
ANN m_bool scan2_union_def(const Env env, const Union_Def udef) {
if(tmpl_base(udef->tmpl))
return GW_OK;
- const m_uint scope = union_push(env, udef);
+ const m_uint scope = env_push_type(env, udef->type);
const m_bool ret = scan2_union_decl(env, udef->l);
- union_pop(env, udef, scope);
- union_flag(udef, tflag_scan2);
+ env_pop(env, scope);
+ set_tflag(udef->type, tflag_scan2);
return ret;
}
+++ /dev/null
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "gwion_env.h"
-
-ANN m_uint union_push(const Env env, const Union_Def udef) {
- const Type type = udef->xid ? udef->value->type : udef->type_xid ?
- udef->type : NULL;
- return type ? env_push_type(env, type) : GET_FLAG(udef, global) ?
- env_push_global(env) : env->scope->depth;
-}
-
-ANN void union_pop(const Env env, const Union_Def udef, const m_uint scope) {
- if(udef->xid || udef->type_xid || GET_FLAG(udef, global))
- env_pop(env, scope);
-}
-
-ANN void union_flag(const Union_Def udef, const enum tflag flag) {
- const Type type = udef->xid || !udef->type_xid ?
- udef->value->type : udef->type;
- type->tflag |= flag;
-}
#include "gwion.h"
#include "operator.h"
-struct tmpl_info {
- const Class_Def cdef;
- Type_List call;
- struct Vector_ type;
- struct Vector_ size;
- uint8_t index;
-};
-
ANN static m_bool push_types(const Env env, const Tmpl *tmpl) {
ID_List list = tmpl->list;
Type_List call = tmpl->call;
+++ /dev/null
-#! [contains] can only be used at class scope.
-union private { int i; } u;
+++ /dev/null
-#! [contains] can only be used at class scope.
-union private static { int i; } u;
+++ /dev/null
-#! [contains] can only be used at class scope.
-union static { int i; } u;
+++ /dev/null
-#! [contains] does not have members - invalid use in dot expression
-var int i;
-i.nothing;
-
--- /dev/null
+#! [contains] expression is known to be nonnull
+nonnull Object o;
+<<< (!o) >>>;
#! [contains] must be defined with empty
-union {
+union U {
int i;
int array[4];
};
#! [contains] can only be used at class scope.
-union static { int i; };
+union static U { int i; };
#! [contains] can only be used at class scope.
-union private static { int i; };
+union private static U { int i; };
#! [contains] can only be used at class scope.
-union private { int i; };
+union private U { int i; };
#! [contains] unknown_type
-union
+union U
{
unknown_type unknown_variable;
};
#include "gwi.h"
GWION_IMPORT(checker) {
- GWI_BB(gwi_union_ini(gwi, NULL, NULL))
+ GWI_BB(gwi_union_ini(gwi, "U"))
GWI_BB(gwi_union_add(gwi, "int", "|array[2][3]"))
return GW_OK;
}
#include "import.h"
GWION_IMPORT(empty_union_test) {
- GWI_BB(gwi_union_ini(gwi, NULL, NULL))
+ GWI_BB(gwi_union_ini(gwi, "U"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
}
#include "import.h"
GWION_IMPORT(union_test) {
- GWI_BB(gwi_union_ini(gwi, NULL, NULL))
+ GWI_BB(gwi_union_ini(gwi, "U"))
GWI_BB(gwi_union_add(gwi,"float", "f"))
GWI_BB(gwi_union_add(gwi,"int", "i"))
GWI_OB(gwi_union_end(gwi, 0))
#include "import.h"
GWION_IMPORT(union_test) {
- GWI_BB(gwi_union_ini(gwi, NULL, NULL))
+ GWI_BB(gwi_union_ini(gwi, "U"))
GWI_BB(gwi_union_add(gwi,"Float", "f"))
GWI_BB(gwi_union_add(gwi,"int", "i"))
GWI_OB(gwi_union_end(gwi, 0))
GWION_IMPORT(union_member) {
GWI_OB(gwi_class_ini(gwi, "UnionMember", NULL))
- GWI_BB(gwi_union_ini(gwi, "U", NULL))
+ GWI_BB(gwi_union_ini(gwi, "U"))
GWI_BB(gwi_union_add(gwi,"float", "f"))
GWI_BB(gwi_union_add(gwi,"int[]", "i"))
GWI_OB(gwi_union_end(gwi, ae_flag_none))
#include "import.h"
GWION_IMPORT(union_test) {
- GWI_BB(gwi_union_ini(gwi, NULL, "my_union"))
+ GWI_BB(gwi_union_ini(gwi, "my_union"))
GWI_BB(gwi_union_add(gwi,"float", "f"))
GWI_BB(gwi_union_add(gwi,"int", "i"))
GWI_OB(gwi_union_end(gwi, 0))
#include "import.h"
GWION_IMPORT(union_test) {
- GWI_BB(gwi_union_ini(gwi, "U:[A]", NULL))
+ GWI_BB(gwi_union_ini(gwi, "U:[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"))
#include "import.h"
GWION_IMPORT(union_test) {
- GWI_BB(gwi_union_ini(gwi, "U:[A]", "My"))
+ GWI_BB(gwi_union_ini(gwi, "U:[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"))
#include "import.h"
GWION_IMPORT(union_test) {
- GWI_BB(gwi_union_ini(gwi, "U:[A]", NULL))
+ GWI_BB(gwi_union_ini(gwi, "U:[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]", NULL))
+ GWI_BB(gwi_union_ini(gwi, "U:[A]"))
GWI_OB(gwi_union_end(gwi, 0))
return GW_OK;
}
#include "import.h"
GWION_IMPORT(union_test) {
- GWI_BB(gwi_union_ini(gwi, "U:[A]", "Test"))
+ GWI_BB(gwi_union_ini(gwi, "U:[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"))