: emit_struct_addref(emit, t, size, emit_var);
}
-ANN static inline bool is_static_call(const Emitter emit, const Exp e) {
- if (e->exp_type != ae_exp_dot) return true;
- const Exp_Dot *member = &e->d.exp_dot;
- return GET_FLAG(e->type, final) ||
- GET_FLAG(member->base->type, final) ||
- is_class(emit->gwion, member->base->type) ||
-// GET_FLAG(e->type->info->func, static) ||
- member->base->exp_type == ae_exp_cast;
-}
-
ANN Instr emit_kind(Emitter, const m_uint size, const bool addr,
const f_instr func[]);
ANN Instr emit_regpushimm(Emitter, const m_uint, const bool);
}
ANN m_bool abstract_array(const Env env, const Array_Sub array);
+
+ANN static inline bool is_static_call(const Gwion gwion, const Exp e) {
+ if (e->exp_type != ae_exp_dot) return true;
+ const Exp_Dot *member = &e->d.exp_dot;
+ if(unlikely(!strcmp(s_name(member->xid), "new"))) return true;
+ return GET_FLAG(e->type, final) ||
+ GET_FLAG(member->base->type, final) ||
+ is_class(gwion, member->base->type) ||
+ member->base->exp_type == ae_exp_cast;
+}
#endif
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, exp_call->func)));
+ is_static_call(emit->gwion, exp_call->func)));
else {
struct Op_Import opi = {.op = insert_symbol("@ctor"),
.rhs = t,
const m_uint offset = emit_code_offset(emit);
if (f != emit->env->func || !is_static || strcmp(s_name(f->def->base->xid), "new"))
regseti(emit, offset);
- const bool _is_static = !strcmp(s_name(f->def->base->xid), "new") ? true : is_static;
- const Instr instr = emit_call(emit, f, _is_static);
+ const Instr instr = emit_call(emit, f, is_static);
instr->m_val = f->def->base->ret_type->size;
instr->m_val2 = offset;
}
#include "vm.h"
#include "gwion.h"
-#define MAX(a, b) (a >= b ? a : b)
ANN void free_value(Value a, Gwion gwion) {
const Type t = a->type;
if (t->size > SZ_INT && !vflag(a, vflag_func) && a->d.ptr)
struct Exp_ rexp = MK_DOT(emit, ds->rhs->tmp, rhs);
struct Exp_ temp = MK_BIN(lexp, rexp, ds->bin);
temp.type=emit->gwion->type[et_bool];
- if(tflag(lexp.type, tflag_struct))
- exp_setvar(&lexp, true);
- if(tflag(rexp.type, tflag_struct))
- exp_setvar(&rexp, true);
if(emit_exp(emit, &temp) < 0) return false;
vector_add(&ds->acc, (m_uint)emit_add_instr(emit, BranchEqInt));
}
+
#include "gwion_util.h"
#include "gwion_ast.h"
#include "gwion_env.h"
instr->m_val = (m_uint)f;
return;
}
- } else if (is_static_call(emit, exp_self(member))) {
+ } else if (is_static_call(emit->gwion, exp_self(member))) {
if (member->is_call && f == emit->env->func && strcmp(s_name(f->def->base->xid), "new")) return;
const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : SetFunc);
func_i->m_val = (m_uint)f->code ?: (m_uint)f;
return;
} else {
if (tflag(member->base->type, tflag_struct)) {
- if (!GET_FLAG(f->def->base, static)) {
- exp_setvar(member->base, 1);
- emit_exp(emit, member->base);
- }
const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : SetFunc);
func_i->m_val = (m_uint)f->code ?: (m_uint)f;
return;
_("keyword 'this' must be associated with object instance..."));
const Value value = get_value(env, member, the_base);
if (!value) {
-/*
- if(env->class_def != the_base && tflag(the_base, tflag_cdef) && !tflag(the_base, tflag_check))
- CHECK_BN(ensure_traverse(env, the_base));
- return check_exp(env, exp_self(member));
- }
-*/
const Value v = nspc_lookup_value1(env->curr, member->xid);
if(v) {
if (member->is_call) {
return v->type;
if (is_class(env->gwion, v->type)) {
DECL_OO(const Type, parent, = class_type(env, member, v->type));
- // allow only direct parent or smth?
- // mark the function as ctor_ok
if (isa(the_base, parent) > 0 && parent->nspc) {
const Symbol sym = insert_symbol(env->gwion->st, "new");
+ if(!env->func || env->func->def->base->xid != sym)
+ ERR_N(exp_self(member)->pos, "calling a parent constructor is only allowed in `new` definition");
+ // is this
+ if(member->base->exp_type != ae_exp_primary ||
+ member->base->d.prim.prim_type != ae_prim_id ||
+ strcmp(s_name(member->base->d.prim.d.var), "this"))
+ ERR_N(exp_self(member)->pos, "calling a parent constructor is only allowed with `this`");
+ SET_FLAG(env->func, const); // mark the function as ctor_ok
const Value ret = nspc_lookup_value1(parent->nspc, sym);
member->xid = sym;
- if(ret)
- return ret->type;
+ if(ret) return ret->type;
}
}
} else if(is_class(env->gwion, v->type) && the_base == v->type->info->base_type)
ERR_N(exp_self(member)->pos,
_("cannot access member '%s.%s' without object instance..."),
the_base->name, str);
-// if current function is a constructor
if (GET_FLAG(value, const)) exp_setmeta(exp_self(member), 1);
exp_self(member)->acquire = 1;
return value->type;
OP_EMIT(opem_object_dot) {
const Exp_Dot *member = (Exp_Dot *)data;
-// const Type t_base = actual_type(emit->gwion, member->base->type);
const Type t_base = member_type(emit->gwion, member->base->type);
const Value value = find_value(t_base, member->xid);
if(!tflag(t_base, tflag_emit) /*&& emit->env->class_def != t_base*/) {
instr->m_val = (m_uint)value->type;
return GW_OK;
}
+ if (tflag(t_base, tflag_struct) && !GET_FLAG(value, static)) {
+ exp_setvar(member->base, true);
+ CHECK_BB(emit_exp(emit, member->base));
+ }
if (!is_class(emit->gwion, member->base->type) &&
(vflag(value, vflag_member) ||
(is_func(emit->gwion, exp_self(member)->type)))) {
- if (!tflag(t_base, tflag_struct) && vflag(value, vflag_member))
+ if (!tflag(t_base, tflag_struct))
CHECK_BB(emit_exp(emit, member->base));
}
- if (is_func(emit->gwion, exp_self(member)->type) && // is_func
+ if (is_func(emit->gwion, exp_self(member)->type) &&
!fflag(exp_self(member)->type->info->func, fflag_fptr))
emit_member_func(emit, member);
else if (vflag(value, vflag_member)) {
if (!tflag(t_base, tflag_struct))
emit_member(emit, value, exp_getvar(exp_self(member)));
- else {
- exp_setvar(member->base, 1);
- CHECK_BB(emit_exp(emit, member->base));
+ else
emit_struct_data(emit, value, exp_getvar(exp_self(member)));
- }
} else if (GET_FLAG(value, static))
emit_dot_static_import_data(emit, value, exp_getvar(exp_self(member)));
else { // member type
CHECK_BO(envset_pushv(&es, t->info->value));
const bool local = !owner && !tmpl_global(env, td->types) && from_global_nspc(env, env->curr);
if(local && env->context) env_push(env, NULL, env->context->nspc);
- // these context and env command may fit better somewhere else
-// const m_str env_filename = env->name;
-// const m_str ctx_filename = env->context->name;
-// env->name = t->info->value->from->filename;
-// env->context->name = t->info->value->from->ctx->name;
const Type ret = _scan_class(env, &info);
-// env->name = env_filename;
-// env->context->name = ctx_filename;
if(local && env->context)env_pop(env, es.scope);
envset_pop(&es, owner);
return ret;
return NULL;
}
+ANN static Type check_static(const Env env, const Exp e) {
+ const Type t = e->type;
+ if(unlikely(!is_func(env->gwion, t)) ||
+ !t->info->func ||
+ !GET_FLAG(t->info->func->def->base, abstract) ||
+ !is_static_call(env->gwion, e)) return t;
+ env_err(env, e->pos, "making a static call to an abstract function");
+ env->context->error = false;
+ gwerr_secondary_from("declared here", t->info->value->from);
+ env->context->error = true;
+ return NULL;
+}
+
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;
+ CHECK_OO(check_static(env, exp->func));
const Type _ret = _check_exp_call1(env, exp);
if(_ret) return _ret;
if(isa(exp->func->type, env->gwion->type[et_closure]) > 0) {
return ret;
}
+ANN m_bool check_new(const Env env, const Func_Def fdef) {
+ if(!fdef->builtin && !GET_FLAG(fdef->base->func, const) &&
+ GET_FLAG(env->class_def->info->parent, abstract)) {
+ // we can probably do simpler, but this may require fixing new@ index
+ const Value v = nspc_lookup_value0(env->class_def->info->parent->nspc, fdef->base->xid);
+ if(v) {
+ Func f = v->d.func_ref;
+ while(f) {
+ if(compat_func(fdef, f->def)) break;
+ f = f->next;
+ }
+ if(f && GET_FLAG(f, abstract)) ERR_B(fdef->base->pos, "What what?");
+ }
+ }
+ return GW_OK;
+}
+
ANN m_bool check_func_def(const Env env, const Func_Def fdef) {
const uint16_t depth = env->scope->depth;
env->scope->depth = 0;
const m_bool ret = _check_func_def(env, fdef);
env->scope->depth = depth;
+ // we need to find matching parent and see if abstract
+ if(!strcmp(s_name(fdef->base->xid), "new"))
+ CHECK_BB(check_new(env, fdef));
return ret;
}
!(tflag(cdef->base.type, tflag_cdef) || tflag(cdef->base.type, tflag_udef)))
ERR_B(pos, _("cannot extend primitive type '%s'"), parent->name)
if (type_ref(parent)) ERR_B(pos, _("can't use ref type in class extend"))
+ if (GET_FLAG(parent, abstract)) SET_FLAG(cdef->base.type, abstract);
return GW_OK;
}
reg += VAL2;
DISPATCH()
dotfunc:
- *(VM_Code *)(reg + (m_uint)VAL2) =
+ *(VM_Code *)(reg + IVAL2) =
((Func)(*(M_Object *)(reg - SZ_INT))->type_ref->nspc->vtable.ptr[OFFSET + VAL])->code;
DISPATCH()
gacktype : {
m_str str = *(m_str *)(reg - SZ_INT);
if (!VAL) {
gw_out("%s\n", str);
-fflush(stdout);
-}
- else
+ fflush(stdout);
+ } else
*(M_Object *)(reg - SZ_INT) = new_string(vm->gwion, str);
if (str) mp_free2(vm->gwion->mp, strlen(str), str);
DISPATCH();