fflag_tmpl = 1 << 3,
fflag_valid = 1 << 4,
fflag_emit = 1 << 5,
- fflag_return = 1 << 6,
} __attribute__((packed));
struct Func_ {
Func next;
m_str name;
float inline_mult;
- uint16_t weight;
- uint16_t memoize;
+ uint16_t weight; // used to mark gack use in scan1
+ uint16_t memoize; // used to mark return in scan1
uint16_t ref;
uint16_t vt_index;
ae_flag flag;
}
if (vflag(v, vflag_builtin) || vflag(v, vflag_direct))
return emit_symbol_builtin(emit, data);
- if(is_func(emit->gwion, v->type) && !is_fptr(emit->gwion, v->type)) {
+ if(is_func(emit->gwion, v->type) && !is_fptr(emit->gwion, v->type)) { // is_func
const Func f = v->type->info->func;
if(f->code)
regpushi(emit, (m_uint)f->code);
if (exp_call->args) CHECK_BB(emit_exp(emit, exp_call->args));
const Type t = actual_type(emit->gwion, exp_call->func->type);
if (is_func(emit->gwion, t) &&
- fbflag(t->info->func->def->base, fbflag_variadic))
+ fbflag(t->info->func->def->base, fbflag_variadic)) // is_callable
emit_func_arg_vararg(emit, exp_call);
return GW_OK;
}
ANN static inline Func is_inlinable(const Emitter emit,
const Exp_Call *exp_call) {
const Type ftype = exp_call->func->type;
- if (!is_func(emit->gwion, ftype) || is_fptr(emit->gwion, ftype) ||
+ if (!is_func(emit->gwion, ftype) || is_fptr(emit->gwion, ftype) || // is_fptr
!ftype->info->func->code || ftype->info->func->code->builtin)
return false;
const Func f = ftype->info->func;
CHECK_BB(prepare_call(emit, exp_call));
else
CHECK_BB(emit_func_args(emit, exp_call));
- if (is_func(emit->gwion, t))
+ 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)));
else {
const Instr instr = emit_add_instr(emit, Reg2RegAddr);
instr->m_val = -SZ_INT;
} else {
- if (!is_func(emit->gwion, exp_call->func->type) &&
+ if (!is_func(emit->gwion, exp_call->func->type) && // is_callable
tflag(e->type, tflag_struct))
regpop(emit, SZ_INT);
}
}
ANN static m_bool emit_type_def(const Emitter emit, const Type_Def tdef) {
- if (tdef->when) CHECK_BB(emit_func_def(emit, tdef->when_def));
+ if (tdef->when_def) CHECK_BB(emit_func_def(emit, tdef->when_def));
if (!is_fptr(emit->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) {
if(!tflag(tdef->type->info->parent, tflag_emit))
for(m_uint i = 0; i < map_size(m); i++) {
const Value value = (Value)map_at(m, i);
if(!vflag(value, vflag_member)) continue;
- if(is_func(gwion, value->type) && !is_fptr(gwion, value->type)) continue;
+ if(is_func(gwion, value->type) && !is_fptr(gwion, value->type)) continue; // is_func
vector_add(v, (m_uint)value);
}
}
OP_EMIT(opem_object_dot);
static ID_CHECK(idck_predicate) {
- set_fflag(env->func, fflag_return);
return exp_self(prim)->type;
}
if (!is_class(env->gwion, info->lhs->value_ref->type)) {
if (!(info->lhs = nspc_lookup_func1(nspc, sym))) {
const Value v = nspc_lookup_value1(nspc, insert_symbol(c));
- if (!is_func(env->gwion, v->type)) return NULL;
+ if (!is_func(env->gwion, v->type)) return NULL; // is_callable
info->lhs = v->type->info->func;
}
} else {
}
const Value v = nspc_lookup_value1(env->curr, member->xid);
if (v && member->is_call) {
- if (is_func(env->gwion, v->type) && (!v->from->owner_class || isa(the_base, v->from->owner_class) > 0))
+ if (is_func(env->gwion, v->type) && (!v->from->owner_class || isa(the_base, v->from->owner_class) > 0)) // is_callable needs type
return v->type;
if (is_class(env->gwion, v->type)) {
DECL_OO(const Type, parent, = class_type(env, member, v->type));
}
if (!is_class(emit->gwion, member->base->type) &&
(vflag(value, vflag_member) ||
- (is_func(emit->gwion, exp_self(member)->type) &&
+ (is_func(emit->gwion, exp_self(member)->type) && // is_func
!is_fptr(emit->gwion, exp_self(member)->type)))) {
if (!tflag(t_base, tflag_struct) && vflag(value, vflag_member))
CHECK_BB(emit_exp(emit, member->base));
}
- if (is_func(emit->gwion, exp_self(member)->type) &&
+ if (is_func(emit->gwion, exp_self(member)->type) && // is_func
!is_fptr(emit->gwion, exp_self(member)->type))
emit_member_func(emit, member);
else if (vflag(value, vflag_member)) {
const Exp_Dot *member = (Exp_Dot *)data;
const Map map = &member->base->type->nspc->info->value->map;
CHECK_BB(emit_exp(emit, member->base));
- if (is_func(emit->gwion, exp_self(member)->type)) {
+ if (is_func(emit->gwion, exp_self(member)->type)) { // is_callable? can only be a func
const Instr instr = emit_add_instr(emit, RegPushImm);
const Func f =
(Func)vector_front(&member->base->type->info->parent->nspc->vtable);
_("non-global variable '%s' used from global function/class."),
s_name(var))
} else if(env->func && fbflag(env->func->def->base, fbflag_locale)) {
- if(!is_func(env->gwion, value->type) && value->from->owner && !from_global_nspc(env, value->from->owner))
+ if(!is_func(env->gwion, value->type) && value->from->owner && !from_global_nspc(env, value->from->owner)) // is_callable
ERR_O(prim_pos(data), _("invalid variable access from locale definition"));
}
return value;
ANN static Type check_prim_perform(const Env env, const Symbol *data) {
env_add_effect(env, *data, prim_pos(data));
env_weight(env, 1);
- if (env->func && env->scope->depth == 1) // so ops no dot set scope->depth ?
- set_fflag(env->func, fflag_return);
return env->gwion->type[et_void];
}
}
ANN static inline Type type_list_base(const Gwion gwion, const Type type) {
- return !(is_func(gwion, type) && !is_fptr(gwion, type)) ?
+ return !(is_func(gwion, type) && !is_fptr(gwion, type)) ? // is_func
type : type_list_base_func(type);
}
ANN Func ufcs(const Env env, const Func up, Exp_Call *const call) {
const Value v = nspc_lookup_value1(env->curr, up->def->base->xid);
- if (v && is_func(env->gwion, v->type) && !v->from->owner_class)
+ if (v && is_func(env->gwion, v->type) && !v->from->owner_class) // is_callable
return call2ufcs(env, call, v);
return NULL;
}
"site. did you meant to use `@=>`?"))
const Type t = actual_type(env->gwion, exp->func->type);
if(!is_fptr(env->gwion, t)) {
- if (is_func(env->gwion, t) && exp->func->exp_type == ae_exp_dot &&
+ if (is_func(env->gwion, t) && exp->func->exp_type == ae_exp_dot && // is_callable
!t->info->value->from->owner_class) {
if (exp->args) CHECK_OB(check_exp(env, exp->args));
return call2ufcs(env, exp, t->info->func->value_ref) ? GW_OK : GW_ERROR;
set_fbflag(fb, fbflag_op);
const Exp helper = new_prim_id(env->gwion->mp, insert_symbol("@predicate"),
tdef->when->pos);
- const Exp when = cpy_exp(env->gwion->mp, tdef->when);
+ const Exp when = tdef->when;
+ tdef->when = NULL;
when->next = helper;
- Stmt_List body = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 1);
+ Stmt_List body = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 2);
mp_vector_set(body, struct Stmt_, 0,
((struct Stmt_) {
.stmt_type = ae_stmt_exp, .d = { .stmt_exp = { .val = when }},
.pos = when->pos
}));
+ mp_vector_set(body, struct Stmt_, 1,
+ ((struct Stmt_) {
+ .stmt_type = ae_stmt_exp,
+ .pos = when->pos
+ }));
const Stmt code = new_stmt_code(env->gwion->mp, body, when->pos);
const Func_Def fdef = new_func_def(env->gwion->mp, fb, code);
- if(traverse_func_def(env, fdef) < 0) {
- free_mp_vector(env->gwion->mp, sizeof(struct Stmt_), body);
- return GW_ERROR;
- }
+ tdef->when_def = fdef;
+ CHECK_BB(traverse_func_def(env, fdef));
if (isa(when->type, env->gwion->type[et_bool]) < 0) {
- free_mp_vector(env->gwion->mp, sizeof(struct Stmt_), body);
char explain[strlen(when->type->name) + 20];
sprintf(explain, "found `{/+}%s{0}`", when->type->name);
gwerr_basic("Invalid `{/+}when{0}` predicate expression type", explain,
env_set_error(env);
return GW_ERROR;
}
- /*
- // enable static checking
- const Func f = fdef->base->func;
- const struct Op_Func opfunc = { .ck=opck_predicate };
- const struct Op_Import opi = { .rhs=f->value_ref->type,
- .func=&opfunc, .data=(uintptr_t)f, .pos=tdef->pos,
- .op=insert_symbol("@func_check") }; CHECK_BB(add_op(env->gwion, &opi));
- */
// we handle the return after, so that we don't get *cant' use implicit
// casting while defining it*
- const Exp ret_id =
- new_prim_id(env->gwion->mp, insert_symbol("self"), when->pos);
+ const Exp ret_id = new_prim_id(env->gwion->mp, insert_symbol("self"), when->pos);
ret_id->d.prim.value = new_value(env, tdef->type, "self", tdef->pos);
struct Stmt_ ret = {
.stmt_type = ae_stmt_return, .d = { .stmt_exp = { .val = ret_id }},
.pos = when->pos
};
- mp_vector_add(env->gwion->mp, &fdef->d.code->d.stmt_code.stmt_list, struct Stmt_, ret);
- ret_id->type = tdef->type;
- tdef->when_def = fdef;
- }
- if (!is_fptr(env->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) {
- if(!tflag(tdef->type->info->parent, tflag_check))
- return check_class_def(env, tdef->type->info->parent->info->cdef);
+ mp_vector_set(fdef->d.code->d.stmt_code.stmt_list, struct Stmt_, 1, ret);
+ ret_id->type = tdef->type;
}
-
- return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef)
- ? check_class_def(env, tdef->type->info->cdef)
- : GW_OK;
+ return GW_OK;
}
ANN static Type check_exp_lambda(const Env env, const Exp_If *exp_if NUSED) {
return env->gwion->type[et_lambda];
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 (!env->func)
- ERR_B(stmt_self(stmt)->pos,
- _("'return' statement found outside function definition"))
- if (env->scope->depth == 1) // so ops no dot set scope->depth ?
- set_fflag(env->func, fflag_return);
if (!strcmp(s_name(env->func->def->base->xid), "new")) {
if(stmt->val)
ERR_B(stmt_self(stmt)->pos,
CHECK_BB(check_stmt_code(env, &fdef->d.code->d.stmt_code));
env->scope->depth++;
}
- // check fdef->base->td for `new`
- if (fdef->base->td && fdef->base->ret_type &&
- fdef->base->ret_type != env->gwion->type[et_void] && fdef->d.code &&
- !fflag(fdef->base->func, fflag_return))
- ERR_B(fdef->base->td->pos,
- _("missing return statement in a non void function"));
return GW_OK;
}
const Func_Def request) {
const Value v = nspc_lookup_value0(t->nspc, request->base->xid);
if (v) {
- if (!is_func(env->gwion, v->type) || is_fptr(env->gwion, v->type)) {
+ if (!is_func(env->gwion, v->type) || is_fptr(env->gwion, v->type)) { // is_fptr
gwerr_basic("is not a function", NULL, NULL, v->from->filename,
v->from->loc, 0);
return false;
gwerr_basic(_("no match found for operator"), "expected duration", "did you try converting to `dur`?", env->name, opi->pos, 0);
env->context->error = true;
} else if (strcmp(op, "@implicit")) {
- if (opi->rhs && opi->lhs && is_func(env->gwion, opi->rhs)) {
+ if (opi->rhs && opi->lhs && is_func(env->gwion, opi->rhs)) { // is_callable
const size_t len = strlen(op);
if (len > 2 && !strcmp(op + len - 2, "=>"))
return chuck_rewrite(env, opi, op, len);
context_global(env);
env_push_global(env);
}
- if (!is_func(env->gwion, base)) {
+ if (!is_func(env->gwion, base)) { // is_callable
if (!tdef->ext->types && (!tdef->ext->array || !tdef->ext->array->exp)) {
typedef_simple(env, tdef, base);
} else
#define scan1_stmt_until scan1_stmt_flow
#define scan1_stmt_continue dummy_func
#define scan1_stmt_break dummy_func
-#define scan1_stmt_return scan1_stmt_exp
#define scan1_stmt_retry dummy_func
+ANN static m_bool scan1_stmt_return(const Env env, const Stmt_Exp stmt) {
+ if (!env->func)
+ ERR_B(stmt_self(stmt)->pos,
+ _("'return' statement found outside function definition"))
+ if (env->scope->depth <= 2) env->func->memoize = 1;
+ if(stmt->val) scan1_exp(env, stmt->val);
+ return GW_OK;
+}
+
ANN static m_bool scan1_stmt_pp(const Env env, const Stmt_PP stmt) {
if (stmt->pp_type == ae_pp_include) env->name = stmt->data;
return GW_OK;
const Func_Def fdef) {
const Value v = nspc_lookup_value1(env->curr, fdef->base->xid);
if (!v) return GW_OK;
- if (is_func(env->gwion, actual_type(env->gwion, v->type))) return GW_OK;
+ if (is_func(env->gwion, actual_type(env->gwion, v->type))) return GW_OK; // is_callable
if ((!env->class_def || !GET_FLAG(env->class_def, final)) &&
!nspc_lookup_value0(env->curr, fdef->base->xid))
ERR_B(fdef->base->pos,
--env->scope->depth;
env->func = former;
if (global) env_pop(env, scope);
+ if ((strcmp(s_name(fdef->base->xid), "@implicit") || fbflag(fdef->base, fbflag_internal)) && !fdef->builtin && fdef->base->ret_type &&
+ fdef->base->ret_type != env->gwion->type[et_void] && fdef->d.code &&
+ !fake.memoize)
+ ERR_B(fdef->base->td->pos,
+ _("missing return statement in a non void function %u"), fake.memoize);
if (fdef->base->xid == insert_symbol("@gack") && !fake.weight) {
gwerr_basic(_("`@gack` operator does not print anything"), NULL,
_("use `<<<` `>>>` in the function"), env->name, fdef->base->pos, 0);
ANN static m_bool scan2_func_def_overload(const Env env, const Func_Def f,
const Value overload) {
const m_bool fptr = is_fptr(env->gwion, overload->type);
- if (!is_func(env->gwion, overload->type) ||
+ if (!is_func(env->gwion, overload->type) || // is_fptr
is_fptr(env->gwion, overload->type)) {
if (!fbflag(f->base, fbflag_internal))
ERR_B(f->base->pos,
}
static ANN Type maybe_func(const Env env, const Type t, const Type_Decl *td) {
- if (is_func(env->gwion, t) && t->info->func->def->base->tmpl)
+ if (is_func(env->gwion, t) && t->info->func->def->base->tmpl) // is_callable needs type
return scan_func(env, t, td);
ERR_O(td->pos,
_("type '%s' is not template. You should not provide template types"),
}
ANN static Type _scan_type(const Env env, const Type t, Type_Decl *td) {
- if (tflag(t, tflag_tmpl) && !is_func(env->gwion, t)) {
+ if (tflag(t, tflag_tmpl) && !is_func(env->gwion, t)) { // is_callable
if (tflag(t, tflag_ntmpl) && !td->types) return t;
if(!td->types) {
const Type new_type = nspc_lookup_type1(env->curr, td->xid);
}
class D extends C {
- fun int test() {}
+ fun int test() { return 42;}
}