return l;
}
-ANN void emit_local_exp(const Emitter emit, const Exp e) {
+ANN m_uint emit_local_exp(const Emitter emit, const Exp e) {
Local *const l = emit_localx(emit, e->type);
if(e->ref)
e->ref->data = l;
+ return l->offset;
}
ANN m_uint emit_localn(const Emitter emit, const Type t) {
emit_regmove(emit, t->size - SZ_INT);
}
-ANN static void emit_struct_decl_finish(const Emitter emit, const Type t,
- const bool emit_addr) {
- emit->code->frame->curr_offset += t->size + SZ_INT;
- emit_ext_ctor(emit, t);
- if (!emit_addr) decl_expand(emit, t);
- emit->code->frame->curr_offset -= t->size + SZ_INT;
+ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *decl, const Type t) {
+ if(!exp_self(decl)->data)
+ return emit_local(emit, t);
+ const Local *l = exp_self(decl)->data;
+ exp_self(decl)->data = (void*)-1;
+ return l->offset;
+}
+
+ANN static m_bool struct_finish(const Emitter emit, const Exp_Decl *decl) {
+ const Type t = decl->type;
+ const bool emit_addr = exp_getvar(exp_self(decl));
+ if (decl->args) {
+ const Instr instr = (Instr)vector_back(&emit->code->instr);
+ CHECK_BB(emit_exp(emit, decl->args));
+ if (emit_addr) {
+ emit_regmove(emit, -t->size);
+ vector_add(&emit->code->instr, (m_uint)instr);
+ }
+ return GW_OK;
+ }
+ if(tflag(t, tflag_ctor)) {
+ emit_ext_ctor(emit, t);
+ if (!emit_addr) decl_expand(emit, t);
+ }
+ return GW_OK;
}
ANN static m_bool emit_exp_decl_static(const Emitter emit, const Exp_Decl *decl,
if (isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
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);
+ if (tflag(v->type, tflag_struct)) CHECK_BB(struct_finish(emit, decl));
if (isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
emit_object_addref(emit, 0, emit_addr);
}
}
-ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *decl, const Type t) {
- if(!exp_self(decl)->data)
- return emit_local(emit, t);
- const Local *l = exp_self(decl)->data;
- exp_self(decl)->data = (void*)-1;
- return l->offset;
-}
-
ANN static m_bool emit_exp_decl_non_static(const Emitter emit,
const Exp_Decl *decl,
const Var_Decl *var_decl,
}
if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
emit_object_addref(emit, 0, emit_addr);
- } else if (struct_ctor(v))
- emit_struct_decl_finish(emit, v->type, emit_addr);
+ } else if (tflag(v->type, tflag_struct)) {
+// if (!emit_var)
+// decl->vd.value->from->offset = decl_non_static_offset(emit, decl, type);
+ CHECK_BB(struct_finish(emit, decl));
+ }
return GW_OK;
}
const Instr assign = emit_add_instr(emit, Assign);
assign->m_val = emit_var;
(void)emit_object_addref(emit, -SZ_INT, emit_var);
- } else if (struct_ctor(v)) {
- emit_struct_decl_finish(emit, v->type, emit_addr);
+ } else if (tflag(v->type, tflag_struct)) {
+ struct_finish(emit, decl);
(void)emit_struct_addref(emit, v->type, -v->type->size, emit_addr);
}
return GW_OK;
const Vector vec = &v->type->nspc->vtable;
for(m_uint i = 0; i < vector_size(vec); i++) {
const Func f = (Func)vector_at(vec, i);
- if(!strcmp(s_name(f->def->base->xid), "new")) {
+ if(is_new(f->def)) {
gw_err(_("maybe use a constructor?\n"));
break;
}
}
#endif
-ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *exp_call) {
+
+ANN static inline bool is_new_struct(const Func f, const Type t) {
+ return is_new(f->def) && tflag(t, tflag_struct);
+}
+
+ANN static m_bool emit_new_struct(const Emitter emit,const Exp_Call *call) {
+ const Exp self = exp_self(call);
+ const Type t = self->type;
+ const m_int offset = self->ref ? emit->code->frame->curr_offset - t->size: emit_local(emit, t);
+ const Instr back = self->ref ? (Instr)vector_pop(&emit->code->instr) : NULL;
+ CHECK_BB(emit_func_args(emit, call));
+ if(back)
+ vector_add(&emit->code->instr, (m_uint)back);
+ else if(tflag(t, tflag_ctor)) {
+ const Instr instr = emit_add_instr(emit, RegPushMem4);
+ instr->m_val = offset;
+ }
+ if(tflag(t, tflag_ctor)) emit_ext_ctor(emit, t);
+ else if(!back) {
+ emit_regmove(emit, -SZ_INT + t->size);
+ const Instr instr = emit_add_instr(emit, RegPushMem4);
+ instr->m_val = offset;
+ }
+ emit_add_instr(emit, NoOp);
+ return GW_OK;
+}
+
+ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *call) {
#ifdef GWION_INLINE
- const Func _f = is_inlinable(emit, exp_call);
+ const Func _f = is_inlinable(emit, call);
if(_f) {
const Func base = emit->env->func;
emit->env->func = _f;
const m_uint scope = emit_push(emit, _f->value_ref->from->owner_class, _f->value_ref->from->owner);
- const m_bool ret = emit_inline(emit, _f, exp_call);
+ const m_bool ret = emit_inline(emit, _f, call);
emit_pop(emit, scope);
emit->env->func = base;
return ret;
}
#endif
- // skip when recursing
- const Type t = actual_type(emit->gwion, exp_call->func->type);
- const Func f = t->info->func;
- if (strstr(emit->code->name, "ork~") ||
- (f != emit->env->func || (f && f->value_ref->from->owner_class)))
- CHECK_BB(prepare_call(emit, exp_call));
- else
- CHECK_BB(emit_func_args(emit, exp_call));
- if (is_func(emit->gwion, t)) // is_callable needs type
- CHECK_BB(emit_exp_call1(emit, t->info->func,
- is_static_call(emit->gwion, exp_call->func)));
- else {
+ const Type t = call->func->type;
+
+ if(unlikely(!is_func(emit->gwion, t))) {
+ const Type t = actual_type(emit->gwion, call->func->type);
struct Op_Import opi = {.op = insert_symbol("@ctor"),
.rhs = t,
- .data = (uintptr_t)exp_call,
- .pos = exp_self(exp_call)->pos};
+ .data = (uintptr_t)call,
+ .pos = exp_self(call)->pos};
CHECK_BB(op_emit(emit, &opi));
}
+
+ const Func f = t->info->func;
+ if(unlikely(is_new_struct(f, exp_self(call)->type)))
+ emit_new_struct(emit, call);
+ else if (strstr(emit->code->name, "ork~") || // skip when recursing
+ (f != emit->env->func || (f && f->value_ref->from->owner_class)))
+ CHECK_BB(prepare_call(emit, call));
+ else CHECK_BB(emit_func_args(emit, call));
+ CHECK_BB(emit_exp_call1(emit, f, is_static_call(emit->gwion, call->func)));
return GW_OK;
}
tflag(e->type, tflag_struct))
emit_regmove(emit, -SZ_INT);
}
-// if(isa(e->type, emit->gwion->type[et_object]) > 0)
-// emit_local_exp(emit, e);
return GW_OK;
}
ANN static void call_finish(const Emitter emit, const Func f,
const bool is_static) {
const m_uint offset = emit_code_offset(emit);
- if (f != emit->env->func || !is_static || strcmp(s_name(f->def->base->xid), "new"))
+ if (f != emit->env->func || !is_static || !is_new(f->def))
emit_setimm(emit, offset, 0);
const Instr instr = emit_call(emit, f, is_static);
instr->m_val = f->def->base->ret_type->size;
ANN static inline VM_Code _emit_func_def_code(const Emitter emit,
const Func func) {
- if(!strcmp(s_name(func->def->base->xid), "new"))
- emit_add_instr(emit, RegPushMem);
+ if(is_new(func->def)) {
+ const Type t = func->value_ref->from->owner_class;
+ if(!tflag(t, tflag_struct))
+ emit_add_instr(emit, RegPushMem);
+ else {
+ const Instr instr = emit_add_instr(emit, RegPushMemDeref);
+ instr->m_val2 = t->size;
+ }
+ }
return !fbflag(func->def->base, fbflag_internal) ? finalyze(emit, FuncReturn)
: emit_internal(emit, func);
}
return GW_OK;
}
if ((vflag(func->value_ref, vflag_builtin) &&
- safe_tflag(emit->env->class_def, tflag_tmpl)) || (fdef->base->tmpl && !strcmp(s_name(f->base->xid), "new"))) {
+ safe_tflag(emit->env->class_def, tflag_tmpl)) || (fdef->base->tmpl && is_new(f))) {
const Func base =
nspc_lookup_func1(func->value_ref->from->owner, f->base->xid);
builtin_func(emit->gwion, func, (f_xfun)base->code->native_func);
ANN Type check_exp_decl(const Env env, Exp_Decl *const decl) {
if (decl->td->array && decl->td->array->exp)
CHECK_OO(check_exp(env, decl->td->array->exp));
-// if (decl->args && !decl->args->type) { // for some reason this can be parsed twice
if (decl->args) {
const Exp e = new_exp_unary2(env->gwion->mp, insert_symbol("new"), cpy_type_decl(env->gwion->mp, decl->td), decl->args, decl->td->pos);
CHECK_OO(check_exp(env, e));
decl->args = e;
+ e->ref = exp_self(decl);
}
if (decl->td->xid == insert_symbol("auto")) { // should be better
CHECK_BO(scan1_exp(env, exp_self(decl)));
}
ANN Type _check_exp_call1(const Env env, Exp_Call *const exp) {
- /* const */Type t = exp->func->type;
+ Type t = exp->func->type;
if (!is_func(env->gwion, t)) { // use func flag?
if(isa(exp->func->type, env->gwion->type[et_closure]) > 0)
t = closure_def(t)->base->func->value_ref->type;
- else {
+ else if(is_class(env->gwion, t) && tflag(t->info->base_type, tflag_struct)) {
+ const Value v = nspc_lookup_value0(t->info->base_type->nspc, insert_symbol("new"));
+ if(v) t = exp->func->type = v->type;
+ else return NULL;
+ } else {
struct Op_Import opi = {.op = insert_symbol("@ctor"),
.rhs = actual_type(env->gwion, exp->func->type),
.data = (uintptr_t)exp,
if (t == env->gwion->type[et_op]) return check_op_call(env, exp);
if (!t->info->func) // TODO: effects?
return check_lambda_call(env, exp);
-/*
- if (fflag(t->info->func, fflag_ftmpl)) {
- const Value value = t->info->func->value_ref;
- if (value->from->owner_class)
- CHECK_BO(ensure_traverse(env, value->from->owner_class));
- }
-*/
if (exp->args) {
CHECK_OO(check_exp(env, exp->args));
Exp e = exp->args;
return check_exp_call_template(env, (Exp_Call *)exp); // TODO: effects?
const Func func = find_func_match(env, t->info->func, exp);
if (func) {
-/*
- if (func != env->func && func->def && !fflag(func, fflag_valid)) {
- if(func->value_ref->from->owner_class)
- CHECK_BO(ensure_check(env, func->value_ref->from->owner_class));
- else {
- const m_uint scope = env_push(env, NULL, func->value_ref->from->owner);
- const m_bool ret = check_func_def(env, func->def);
- env_pop(env, scope);
- CHECK_BO(ret);
- }
- }
-*/
exp->func->type = func->value_ref->type;
call_add_effect(env, func, exp->func->pos);
-// used in new. why???
- return func->def->base->ret_type != env->gwion->type[et_auto] ?
- func->def->base->ret_type : exp->func->d.exp_dot.base->type;
+ if(func->def->base->ret_type != env->gwion->type[et_auto])
+ return func->def->base->ret_type;
+ if(tflag(func->value_ref->from->owner_class, tflag_struct))
+ return func->value_ref->from->owner_class;
+ return exp->func->d.exp_dot.base->type;
}
if(exp->func->exp_type == ae_exp_lambda) {
const Type tt = partial_type(env, exp);
ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
DECL_BO(const m_bool, ret, = func_check(env, exp));
if (!ret) return exp_self(exp)->type;
- const Type t = exp->func->type;
+// const Type t = actual_type(env->gwion, exp->func->type);
+/* const */Type t = exp->func->type;
CHECK_OO(check_static(env, exp->func));
const Type _ret = _check_exp_call1(env, exp);
if(_ret) return _ret;
if(t) return t;
}
}
- function_alternative(env, t, exp->args, exp->func->pos);
+//puts(t->name);
+// if(!is_func(env->gwion, t)) {
+// if(is_class(env->gwion, t)) {
+// const Value v = nspc_lookup_value0(t->info->base_type->nspc, insert_symbol("new"));
+// if(v) t = v->type;
+// }
+// else
+// }
+//exit(3);
+ if(is_func(env->gwion, exp->func->type))
+ function_alternative(env, exp->func->type, exp->args, exp->func->pos);
return NULL;
}
}
// check for closure and b ring it back
if (!is_func(env->gwion, t)) return check_exp_call1(env, exp);
- if(strcmp("new", s_name(t->info->func->def->base->xid)))
+ if(!is_new(t->info->func->def))
return check_exp_call_tmpl(env, exp, t);
}
return check_exp_call1(env, exp);
stmt_func_xxx(each, Stmt_Each, env_inline_mult(env, 1.5), do_stmt_each(env, stmt))
ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) {
- if (!strcmp(s_name(env->func->def->base->xid), "new")) {
+ if (is_new(env->func->def)) {
if(stmt->val)
ERR_B(stmt_self(stmt)->pos,
_("'return' statement inside constructor function should have no expression"))