--- /dev/null
+#ifndef __AST_DATA
+#define __AST_DATA
+
+typedef struct DataTable_* DataTable;
+ANN DataTable new_datatable(MemPool p, size_t sz);
+ANN void datatable_reset(DataTable);
+ANN void free_datatable(DataTable);
+
+ANN struct Type_* dataget_type (DataTable, void*);
+//ANN Type dataget_cast (Data, void*);
+//ANN Value dataget_val (Data, void*);
+//ANN Func dataget_func (Data, void*);
+//ANN Nspc dataget_nspc (Data, void*);
+//ANN Vector dataget_vec (Data, void*);
+//ANN Instr dataget_instr (Data, void*);
+
+ANN void dataset_type (DataTable, void*, struct Type_*);
+//ANN void dataset_cast (Data, void*);
+//ANN void dataset_val (Data, void*);
+//ANN void dataset_func (Data, void*);
+//ANN void dataset_nspc (Data, void*);
+//ANN void dataset_vec (Data, void*);
+//ANN void dataset_instr (Data, void*);
+#endif
eDotMember2,
eDotMember3,
eDotMember4,
+ eUnionCheck,
eUnionMember,
eUnionMember2,
eUnionMember3,
#define DotMember2 (f_instr)eDotMember2
#define DotMember3 (f_instr)eDotMember3
#define DotMember4 (f_instr)eDotMember4
+#define UnionCheck (f_instr)eUnionCheck
#define UnionMember (f_instr)eUnionMember
#define UnionMember2 (f_instr)eUnionMember2
#define UnionMember3 (f_instr)eUnionMember3
DotMember2
DotMember3
DotMember4
+UnionCheck
UnionMember
UnionMember2
UnionMember3
return exp->val ? emit_exp(emit, exp->val) : GW_OK;
}
+ANN static inline m_bool emit_exp1(const Emitter emit, const Exp e) {
+ const Exp next = e->next;
+ e->next = NULL;
+ const m_bool ret = emit_exp(emit, e);
+ e->next = next;
+ return ret;
+}
+
ANN static m_bool emit_case_head(const Emitter emit, const Exp base,
const Exp e, const Symbol op, const Vector v) {
- CHECK_BB(emit_exp(emit, base))
- CHECK_BB(emit_exp_pop_next(emit, e))
- const m_int size = -exp_size(e);
- emit_exp_addref(emit, base, -exp_totalsize(base) + size);
- emit_exp_addref1(emit, e, size);
+ CHECK_BB(emit_exp1(emit, base))
+ emit_exp_addref1(emit, base, -exp_size(base));
+ CHECK_BB(emit_exp1(emit, e))
+ emit_exp_addref1(emit, e, -exp_size(e));
const Exp_Binary bin = { .lhs=base, .rhs=e, .op=op };
struct Exp_ ebin = { .d={.exp_binary=bin}, };
struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type,
ANN static m_bool case_value(const Emitter emit, const Exp base, const Exp e) {
const Value v = e->d.prim.value;
+printf("base->type %s\n", base->type->name);
v->from->offset = emit_local(emit, base->type);
- CHECK_BB(emit_exp(emit, base))
- emit_exp_addref(emit, base, -exp_totalsize(base));
- regpop(emit, base->type->size);
const Instr instr = emit_add_instr(emit, Reg2Mem4);
instr->m_val = v->from->offset;
instr->m_val2 = base->type->size;
return GW_OK;
}
+// should be in src/lib/union.c
+static const f_instr unionmember[] = { UnionMember, UnionMember2, UnionMember3, UnionMember4 };
#define CASE_PASS (Symbol)1
-ANN static Symbol case_op(const Emitter emit, const Exp base, const Exp e) {
+ANN static Symbol case_op(const Emitter emit, const Exp base, const Exp e, const Vector vec, const uint n) {
if(e->exp_type == ae_exp_primary) {
if(e->d.prim.prim_type == ae_prim_id) {
if(e->d.prim.d.var == insert_symbol("_"))
return CASE_PASS;
if(!nspc_lookup_value1(emit->env->curr, e->d.prim.d.var)) {
+ if(!n) {
+ CHECK_BO(emit_exp(emit, base))
+ emit_exp_addref(emit, base, -exp_totalsize(base));
+ regpop(emit, base->type->size);
+ }
CHECK_BO(case_value(emit, base, e))
return CASE_PASS;
}
}
+ } else if(isa(actual_type(emit->gwion, base->type), emit->gwion->type[et_union]) > 0 && e->exp_type == ae_exp_call) {
+ const Exp func = e->d.exp_call.func;
+ if(func->d.prim.prim_type == ae_prim_id) {
+ const Map map = &actual_type(emit->gwion, base->type)->nspc->info->value->map;
+ for(m_uint i = 0; i < map_size(map); ++i) {
+ if(VKEY(map, i) == (m_uint)func->d.prim.d.var) {
+ const Value v = (Value)VVAL(map, i);
+ if(v) {
+ if(!n)
+ CHECK_BO(emit_exp(emit, base))
+ else
+ regpush(emit, SZ_INT);
+ const Instr check = emit_add_instr(emit, UnionCheck);
+ check->m_val2 = i;
+ vector_add(vec, (m_uint)check);
+ const Instr instr = emit_kind(emit, v->type->size, 0 /*emit_addr*/, unionmember);
+ instr->m_val = i;
+ regpop(emit, v->type->size);
+ case_op(emit, e->d.exp_call.args, e->d.exp_call.args, vec, i + 1);
+ return CASE_PASS;
+ }
+ }
+ }
+ }
}
- return insert_symbol("==");
+ if(!n)
+ return insert_symbol("==");
+ regpush(emit, SZ_INT);
+ CHECK_BO(emit_exp(emit, e))
+ const Exp_Binary bin = { .lhs=base, .rhs=e, .op=insert_symbol("==") };
+ struct Exp_ ebin = { .d={.exp_binary=bin}, };
+ struct Op_Import opi = { .op=insert_symbol("=="), .lhs=base->type, .rhs=e->type,
+ .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary };
+ CHECK_BO(op_emit(emit, &opi))
+ const Instr instr = emit_add_instr(emit, BranchEqInt);
+ vector_add(vec, (vtype)instr);
}
ANN static m_bool _emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt,
- const Vector v) {
+ const Vector v, struct Match_ *const match) {
Exp e = stmt->cond;
const Map map = &emit->env->scope->match->map;
for(m_uint i = 0; i < map_size(map) && e; e = e->next, ++i) {
const Exp base = (Exp)VKEY(map, i);
- const Symbol op = case_op(emit, base, e);
+ const Symbol op = case_op(emit, base, e, v, 0);
if(op != CASE_PASS)
CHECK_BB(emit_case_head(emit, base, e, op, v))
+else puts("pass");
}
CHECK_BB(emit_case_body(emit, stmt))
return GW_OK;
}
-ANN static m_bool emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt) {
+ANN static m_bool emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt,
+ struct Match_ *match) {
emit_push_scope(emit);
struct Vector_ v;
vector_init(&v);
- const m_bool ret = _emit_stmt_match_case(emit, stmt, &v);
+ const m_bool ret = _emit_stmt_match_case(emit, stmt, &v, match);
emit_pop_scope(emit);
for(m_uint i = 0; i < vector_size(&v); ++i) {
const Instr instr = (Instr)vector_at(&v, i);
return ret;
}
-ANN static inline void match_unvec(struct Match_ *const match , const m_uint pc) {
+ANN static inline void match_unvec(struct Match_ *const match, const m_uint pc) {
const Vector vec = &match->vec;
for(m_uint i = 0; i < vector_size(vec); ++i) {
const Instr instr = (Instr)VPTR(vec, i);
vector_release(vec);
}
-ANN static m_bool emit_stmt_cases(const Emitter emit, Stmt_List list) {
- do CHECK_BB(emit_stmt_match_case(emit, &list->stmt->d.stmt_match))
+ANN static m_bool emit_stmt_cases(const Emitter emit, Stmt_List list, struct Match_ *match) {
+ do CHECK_BB(emit_stmt_match_case(emit, &list->stmt->d.stmt_match, match))
while((list = list->next));
return GW_OK;
}
CHECK_BB(emit_stmt(emit, stmt->where, 1))
MATCH_INI(emit->env->scope)
vector_init(&m.vec);
- const m_bool ret = emit_stmt_cases(emit, stmt->list);
+ const m_bool ret = emit_stmt_cases(emit, stmt->list, &m);
match_unvec(&m, emit_code_size(emit));
MATCH_END(emit->env->scope)
return ret;
GWI_BB(import_string(gwi))
GWI_BB(import_shred(gwi))
GWI_BB(import_modules(gwi))
- GWI_BB(import_union(gwi))
GWI_BB(import_foreach(gwi))
GWI_BB(gwi_oper_ini(gwi, "@Class", "@Class", "int"))
GWI_BB(gwi_oper_end(gwi, ">", instr_class_gt))
GWI_BB(gwi_oper_end(gwi, "<=", instr_class_le))
GWI_BB(gwi_oper_end(gwi, "<", instr_class_lt))
-
+/*
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_emi(gwi, opem_object_dot))
GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
+ GWI_BB(import_union(gwi))
return GW_OK;
}
const Value v = (Value)VVAL(map, i);
const uint emit_addr = exp_getvar(exp_self(member));
const Instr instr = emit_kind(emit, v->type->size, emit_addr, unionmember);
- instr->m_val = i + 1;
+ instr->m_val = i;// + 1;
instr->m_val2 = v->type->size;
return GW_OK;
}
e->exp_type = ae_exp_binary;
e->d.exp_binary.lhs = cpy_exp(env->gwion->mp, exp_func);
e->d.exp_binary.lhs->d.exp_dot.xid = insert_symbol(env->gwion->st, "@index");
- e->d.exp_binary.rhs = new_prim_int(env->gwion->mp, i+1, e->pos);
+// e->d.exp_binary.rhs = new_prim_int(env->gwion->mp, i+1, e->pos);
+ e->d.exp_binary.rhs = new_prim_int(env->gwion->mp, i, e->pos);
free_exp(env->gwion->mp, exp_func);
free_exp(env->gwion->mp, exp_args);
e->d.exp_binary.op = insert_symbol(env->gwion->st, "==");
*(m_uint*)RETURN = *(m_uint*)MEM(SZ_INT) == *(m_uint*)o->data;
}
+static OP_CHECK(opck_union_ctor) {
+ Exp_Call *call = (Exp_Call*)data;
+ const Exp name = call->args;
+ if(!name || !name->next || name->next->next)
+ ERR_N(name->pos, "Union constructor takes two arguments, "
+ "'id' and 'value'")
+ if(name->exp_type != ae_exp_primary ||
+ name->d.prim.prim_type != ae_prim_id)
+ return NULL;
+ const Exp val = name->next;
+ const Type base = actual_type(env->gwion, call->func->type);
+ const Map map = &base->nspc->info->value->map;
+ for(m_uint i = 0; i < map_size(map); ++i) {
+ if(VKEY(map, i) == (m_uint)name->d.prim.d.var) {
+ const Value v = (Value)VVAL(map, i);
+ name->d.prim.prim_type = ae_prim_num;
+ name->d.prim.d.num = i;
+ name->type = env->gwion->type[et_int];
+ DECL_ON(const Type, t, = check_exp(env, val))
+ if(isa(t, v->type) < 0) {
+ ERR_N(val->pos, "Invalid type '%s' for '%s', should be '%s'",
+ t->name, v->name, v->type->name)
+ }
+ return base;
+ }
+ }
+ return NULL;
+}
+
+static INSTR(UnionCtor) {
+ POP_REG(shred, instr->m_val2);
+ POP_REG(shred, SZ_INT);
+ const Type t = *(Type*)REG(-SZ_INT*2);
+ const m_uint index = *(m_uint*)REG(-SZ_INT);
+ const M_Object o = *(M_Object*)REG(-SZ_INT) = new_object(shred->info->vm->gwion->mp, NULL, (Type)instr->m_val);
+ *(m_uint*)o->data = index;// + 1;
+ memcpy(o->data + SZ_INT, REG(0), instr->m_val2);
+}
+
+static OP_EMIT(opem_union_ctor) {
+ Exp_Call *call = (Exp_Call*)data;
+ const Type base = actual_type(emit->gwion, call->func->type);
+ const Instr instr = emit_add_instr(emit, UnionCtor);
+ instr->m_val = base;
+ instr->m_val2 = call->args->next->type->size;
+ return GW_OK;
+}
+
ANN GWION_IMPORT(union) {
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_func_arg(gwi, "int", "member"))
GWI_BB(gwi_func_end(gwi, union_is, ae_flag_none))
GWI_BB(gwi_class_end(gwi))
+
+ GWI_BB(gwi_oper_ini(gwi, NULL, "@Union", NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_union_ctor))
+ GWI_BB(gwi_oper_emi(gwi, opem_union_ctor))
+ GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
+
const Func f = (Func)vector_front(&t_union->nspc->info->vtable);
const struct Op_Func opfunc = { .ck=opck_union_is };
const struct Op_Import opi = { .rhs=f->value_ref->type,
if(!ret)
return exp_self(exp)->type;
const Type t = actual_type(env->gwion, exp->func->type);
- if(isa(t, env->gwion->type[et_function]) < 0) {
- // use func flag?
+ if(isa(t, env->gwion->type[et_function]) < 0) { // use func flag?
struct Op_Import opi = { .op=insert_symbol("@ctor"), .rhs=actual_type(env->gwion, exp->func->type),
.data=(uintptr_t)exp, .pos=exp_self(exp)->pos, .op_type=op_exp };
const Type t = op_check(env, &opi);
-// exp_self(exp)->info->nspc = t ? t->info->owner : NULL;
return t;
}
if(t == env->gwion->type[et_lambda])
return stmt->val ? check_exp(env, stmt->val) ? 1 : -1 : 1;
}
-ANN static Value match_value(const Env env, const Exp_Primary* prim, const m_uint i) {
+ANN static Value match_value(const Env env, const Type base, const Exp_Primary* prim, const m_uint i) {
const Symbol sym = prim->d.var;
- const Value v = new_value(env->gwion->mp,
- ((Exp)VKEY(&env->scope->match->map, i))->type, s_name(sym));
+ const Value v = new_value(env->gwion->mp, base, s_name(sym));
set_vflag(v, vflag_valid);
nspc_add_value(env->curr, sym, v);
VVAL(&env->scope->match->map, i) = (vtype)v;
return v;
}
-ANN static Symbol case_op(const Env env, const Exp e, const m_uint i) {
+ANN static Symbol case_op(const Env env, const Type base, const Exp e, const m_uint i) {
if(e->exp_type == ae_exp_primary) {
if(e->d.prim.prim_type == ae_prim_id) {
if(e->d.prim.d.var == insert_symbol("_"))
return NULL;
if(!nspc_lookup_value1(env->curr, e->d.prim.d.var)) {
- e->d.prim.value = match_value(env, &e->d.prim, i);
+ e->d.prim.value = match_value(env, base, &e->d.prim, i);
+ return NULL;
+ }
+ }
+ } else if(isa(actual_type(env->gwion, base), env->gwion->type[et_union]) > 0 && e->exp_type == ae_exp_call) {
+ const Exp func = e->d.exp_call.func;
+ if(func->d.prim.prim_type == ae_prim_id) {
+ const Value v= find_value(actual_type(env->gwion, base), func->d.prim.d.var);
+ if(v) {
+ if(!i)
+ e->type = v->type;
+ case_op(env, v->type, e->d.exp_call.args, i);
+ e->d.exp_call.args->type = v->type;
return NULL;
}
}
if(!e)
ERR_B(last->pos, _("no enough to match"))
last = e;
- const Symbol op = case_op(env, e, i);
+ const Exp base = (Exp)VKEY(&env->scope->match->map, i);
+ const Symbol op = case_op(env, base->type, e, i);
if(op) {
- const Exp base = (Exp)VKEY(&env->scope->match->map, i);
- CHECK_OB(check_exp(env, e))
+ const Exp next = e->next;
+ e->next = NULL;
+ const Type t = check_exp(env, e);
+ e->next = next;
+ CHECK_OB(t)
Exp_Binary bin = { .lhs=base, .rhs=e, .op=op };
struct Exp_ ebin = { .d={.exp_binary=bin} };
struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type,
.data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary };
CHECK_OB(op_check(env, &opi))
-// e->info->nspc= info.nspc;
- return GW_OK;
}
}
if(e)
map_release(map);
}
+static m_str type_name(const Type t) {
+ return t ? t == OP_ANY_TYPE ? "any" : t->name : "";
+}
+
static m_bool op_match(const restrict Type t, const restrict Type mo) {
if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE)
return GW_OK;
return create;
}
-static m_str type_name(const Type t) {
- return t ? t == OP_ANY_TYPE ? "any" : t->name : "";
-}
-
ANN static m_bool _op_exist(const struct OpChecker* ock, const Nspc n) {
const Vector v = (Vector)map_get(&n->info->op_map, (vtype)ock->opi->op);
if(!v || !operator_find2(v, ock->opi->lhs, ock->opi->rhs))
t->info->tuple = new_tupleform(env->gwion->mp, NULL); // ???
add_type(env, env->curr, t);
mk_class(env, t);
- SET_FLAG(t, final);
+ SET_FLAG(t, final | ae_flag_abstract);
return t;
}
if(t->size > sz)
sz = t->size;
} while((l = l->next));
-udef->type->nspc->info->offset = SZ_INT +sz;
+ udef->type->nspc->info->offset = SZ_INT +sz;
return GW_OK;
}
&&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid,
&&newobj, &&addref, &&addrefaddr, &&objassign, &&assign, &&remref,
&&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr,
- &&unionint, &&unionfloat, &&unionother, &&unionaddr,
+ &&unioncheck, &&unionint, &&unionfloat, &&unionother, &&unionaddr,
&&staticint, &&staticfloat, &&staticother,
&&upvalueint, &&upvaluefloat, &&upvalueother, &&upvalueaddr,
&&dotfunc, &&dotstaticfunc,
continue;\
}
+unioncheck:
+{
+ if(*(m_uint*)(*(M_Object*)(reg-SZ_INT))->data != VAL2) {
+ reg -= SZ_INT;
+ PC_DISPATCH(VAL);
+ }
+ DISPATCH()
+}
unionint:
{
UNION_CHECK