tflag_float = 1 << 20,
tflag_union = 1 << 21,
tflag_error = 1 << 22,
+ tflag_ref = 1 << 23,
} __attribute__((packed));
struct Type_ {
OP_CHECK(opck_post);
OP_CHECK(opck_rassign);
OP_CHECK(opck_basic_cast);
+OP_CHECK(opck_similar_cast);
OP_CHECK(opck_usr_implicit);
+OP_EMIT(opem_contract_similar);
OP_CHECK(opck_new);
OP_EMIT(opem_new);
}
return GW_OK;
}
- if (!strncmp(v->type->name, "Ref:[", 5) && (!prim_exp(data)->cast_to || strncmp(prim_exp(data)->cast_to->name, "Ref:[", 5))) {
+// if (!strncmp(v->type->name, "Ref:[", 5) && (!prim_exp(data)->cast_to || strncmp(prim_exp(data)->cast_to->name, "Ref:[", 5))) {
+ if (tflag(v->type, tflag_ref) && !safe_tflag(prim_exp(data)->cast_to, tflag_ref)) {
+//puts("here");
if (exp_getvar(exp_self(prim_self(data)))) {
const Instr instr = emit_add_instr(emit, RegPushMem);
instr->m_val = v->from->offset;
: env->gwion->type[et_error];
}
+OP_CHECK(opck_similar_cast) {
+ const Exp_Cast *cast = (Exp_Cast *)data;
+ return exp_self(cast)->type;
+}
+
OP_CHECK(opck_usr_implicit) {
struct Implicit *imp = (struct Implicit *)data;
/*
return imp->t;
}
+//#include "emit.h"
+// contracts only
+OP_EMIT(opem_contract_similar) {
+ const Exp_Cast *cast = (Exp_Cast *)data;
+ const Env env = emit->env;
+ struct Implicit imp = { .t=exp_self(cast)->type, .e=cast->exp};
+ struct Op_Import opi = {
+ .op = insert_symbol("@implicit"), .lhs = cast->exp->type, .rhs = exp_self(cast)->type, .data=(m_uint)&imp };
+ return op_emit(emit, &opi);
+}
+
OP_CHECK(opck_const_rhs) {
const Exp_Binary *bin = (Exp_Binary *)data;
const m_str access = exp_access(bin->rhs);
return GW_ERROR;
}
-static OP_CHECK(opck_implicit_similar) {
+static OP_CHECK(opck_ref_implicit_similar) {
const struct Implicit *imp = (struct Implicit *)data;
CHECK_BN(ref_access(env, imp->e));
exp_setvar(imp->e, 1);
return imp->t;
}
+static inline Type ref_base(Type t) {
+ do if(!tflag(t->info->parent, tflag_ref))
+ return t;
+ while((t = t->info->parent));
+ return NULL;
+}
+
+static OP_EMIT(opem_ref_implicit_similar) {
+ const struct Implicit *imp = (struct Implicit *)data;
+ if(!tflag(imp->t, tflag_contract)) return GW_OK;
+ const Env env = emit->env;
+ const Type base = ref_base(imp->t);
+ struct Op_Import opi = {.op = insert_symbol("@implicit"),
+ .lhs = base,
+ .rhs = imp->t,
+ .data = (m_uint)imp};
+ CHECK_BB(op_emit(emit, &opi));
+ const Instr instr = emit_add_instr(emit, RegMove);
+ instr->m_val = -imp->e->type->size;
+ exp_setvar(imp->e, true);
+ imp->e->cast_to = NULL;
+ return emit_exp(emit, imp->e);
+}
+
static OP_CHECK(opck_implicit_ref) {
const struct Implicit *imp = (struct Implicit *)data;
CHECK_BN(ref_access(env, imp->e));
return imp->t;
}
-static OP_CHECK(opck_cast_similar) {
- const Exp_Cast *cast = (Exp_Cast *)data;
- return exp_self(cast)->type;
+static OP_CHECK(opck_ref_contract_similar) {
+ const struct Implicit *imp = (struct Implicit *)data;
+ CHECK_BN(ref_access(env, imp->e));
+ const Type base = (Type)vector_front(&imp->t->info->tuple->contains);
+ struct Op_Import opi = {.op = insert_symbol("@implicit"),
+ .lhs = imp->e->type,
+ .rhs = base,
+ .data = (m_uint)imp};
+ return op_check(env, &opi);
+}
+
+static OP_EMIT(opem_ref_contract_similar) {
+ const struct Implicit *imp = (struct Implicit *)data;
+ const Env env = emit->env;
+ const Type base = (Type)vector_front(&imp->t->info->tuple->contains);
+ struct Exp_ cast = {.type=base, .d={.exp_cast={.exp=imp->e}}};
+ struct Op_Import opi = {.op = insert_symbol("$"),
+ .lhs = imp->e->type,
+ .rhs = base,
+ .data = (m_uint)&cast};
+ CHECK_BB(op_emit(emit, &opi));
+ const Instr instr = emit_add_instr(emit, RegMove);
+ instr->m_val = -imp->e->type->size;
+ exp_setvar(imp->e, true);
+ imp->e->cast_to = NULL;
+ emit_exp(emit, imp->e);
+ return GW_OK;
}
ANN static void base2ref(Env env, const Type lhs, const Type rhs) {
- struct Op_Func opfunc = {.ck = opck_cast_similar};
+ struct Op_Func opfunc = {.ck = opck_similar_cast};
struct Op_Import opi = {.op = insert_symbol("$"),
.lhs = lhs,
.ret = rhs,
.func = &opfunc,
.data = eNoOp};
add_op(env->gwion, &opi);
- opfunc.ck = opck_implicit_similar;
+ opfunc.ck = opck_ref_implicit_similar;
+ opfunc.em = opem_ref_implicit_similar;
opi.op = insert_symbol("@implicit");
add_op(env->gwion, &opi);
+
+ if(tflag(lhs, tflag_contract)) {
+ opi.lhs = lhs->info->base_type;
+ opfunc.ck = opck_ref_contract_similar;
+ opfunc.em = opem_ref_contract_similar;
+ opi.op = insert_symbol("@implicit");
+ add_op(env->gwion, &opi);
+ }
+
}
ANN static void ref2base(Env env, const Type lhs, const Type rhs) {
set_tflag(t, tflag_scan2);
set_tflag(t, tflag_check);
set_tflag(t, tflag_emit);
+ set_tflag(t, tflag_ref);
const m_uint scope = env_push(env, base->info->value->from->owner_class,
base->info->value->from->owner);
mk_class(env, t, (loc_t) {});
while (e) {
if (!e->type) // investigate
return NULL;
- if (!strncmp(e->type->name, "Ref:[", 5)) {
+// if (!strncmp(e->type->name, "Ref:[", 5)) {
+ if (tflag(e->type, tflag_ref)) {
if(!e->cast_to)e->cast_to = e->type;
}
if (!e1) {
return imp->e->type;
}
-static OP_CHECK(opck_cast_similar) {
+static OP_CHECK(opck_contract_similar) {
const Exp_Cast *cast = (Exp_Cast *)data;
- return exp_self(cast)->type;
+ if(tflag(exp_self(cast)->type, tflag_contract)) {
+ struct Implicit imp = { .t=exp_self(cast)->type, .e=cast->exp};
+ struct Op_Import opi = {
+ .op = insert_symbol("@implicit"), .lhs = cast->exp->type, .rhs = exp_self(cast)->type, .data=(m_uint)&imp };
+ CHECK_NN(op_check(env, &opi));
+ }
+ return opck_similar_cast(env, data);
}
ANN /*static */ void scan0_implicit_similar(const Env env, const Type lhs,
const Type rhs) {
- struct Op_Func opfunc = {.ck = opck_cast_similar};
+ struct Op_Func opfunc = {.ck = opck_similar_cast};
struct Op_Import opi = {
.op = insert_symbol("$"), .lhs = lhs, .rhs = rhs, .func = &opfunc};
add_op(env->gwion, &opi);
ANN static void scan0_explicit_distinct(const Env env, const Type lhs,
const Type rhs) {
- struct Op_Func opfunc = {.ck = opck_cast_similar};
+ struct Op_Func opfunc = {.ck = opck_similar_cast};
+ if(tflag(rhs, tflag_contract)) {
+ opfunc.ck = opck_contract_similar;
+ opfunc.em = opem_contract_similar;
+ }
struct Op_Import opi = {
.op = insert_symbol("$"), .lhs = lhs, .rhs = rhs, .func = &opfunc};
add_op(env->gwion, &opi);
+ opi.lhs = rhs;
+ opi.rhs = lhs;
+ add_op(env->gwion, &opi);
}
ANN static void typedef_simple(const Env env, const Type_Def tdef,
CHECK_BB(typedef_complex(env, tdef, base));
} else
typedef_fptr(env, tdef, base);
+ if (tdef->when) set_tflag(tdef->type, tflag_contract);
if (!tdef->distinct && !tdef->when)
scan0_implicit_similar(env, base, tdef->type);
- if (tdef->distinct) {
- tdef->type->info->parent = base->info->parent;
+ if (tdef->distinct || tdef->when) {
+// tdef->type->info->parent = base->info->parent;
if (base->info->gack)
vmcode_addref(tdef->type->info->gack = base->info->gack);
set_tflag(tdef->type, tflag_distinct);
type_addref(tdef->type); // maybe because of scope_iter in nspc_free_values
} else
set_tflag(tdef->type, tflag_typedef);
+ if(tflag(base, tflag_ref)) {
+ set_tflag(tdef->type, tflag_ref);
+ set_tflag(tdef->type, tflag_infer);
+ }
if (global) env_pop(env, 0);
tdef->type->info->base_type = base;
return GW_OK;