From: Jérémie Astor Date: Mon, 16 May 2022 15:54:21 +0000 (+0200) Subject: Squashed commit of the following: X-Git-Tag: nightly~270 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=f3ce04e2e7299925048a014a4ba6f8a25a68b783;p=gwion.git Squashed commit of the following: commit 66de1087b9e3bdcf3c92ea0776717f99eab5cf00 Author: Jérémie Astor Date: Mon May 16 17:47:44 2022 +0200 :art: Fix STK commit ac2dd499de7518877a899e04c19ad026f5dffead Author: Jérémie Astor Date: Mon May 16 10:00:20 2022 +0200 :art: Remove @internal commit db23a57694366d5a4fff3017eaeb1846e967e73c Author: Jérémie Astor Date: Mon May 16 00:52:03 2022 +0200 :wrench: Test ctor commit d2e474f11071f5d1f08b6df2b9cd6199b8ba3ca5 Author: Jérémie Astor Date: Mon May 16 00:51:36 2022 +0200 :art: Improve Evdev commit 3fa05203d33996069d7a0696156ea49a3b68ca07 Author: Jérémie Astor Date: Sun May 15 20:50:09 2022 +0200 :art: Improve return handling commit fc66a973244c84d6c38aedc1ae749c4a3c7baf74 Author: Jérémie Astor Date: Sun May 15 20:28:10 2022 +0200 :bug: Fix uncurry commit 38445380d1e0428e738784e7990db3c1180d79a9 Author: Jérémie Astor Date: Sun May 15 18:44:33 2022 +0200 :art: Improve gack not printing error commit 94cfcdeb81452b4406442a674e625bd530bdc997 Author: Jérémie Astor Date: Sun May 15 18:44:02 2022 +0200 clean commit 2acff6c9b459b413a5a08b9ce4e652f2bcfd71cf Author: Jérémie Astor Date: Sun May 15 16:16:53 2022 +0200 :art: error if @gack does not print anything commit 2098cc4b6620b2b782ab1d44385b9b126f10f26d Author: Jérémie Astor Date: Sat May 14 15:43:31 2022 +0200 :art: Use is_func commit 8488df8795458f2a9ab038cfceef6ed76f0b57dd Author: Jérémie Astor Date: Sat May 14 01:21:37 2022 +0200 :wrench: Improve git recursive warning commit 1b80ef7f6950d1a8c9b692f9d75a4ca3392793d3 Merge: b4fff0a1 5f203eb7 Author: Jérémie Astor Date: Sat May 14 01:20:23 2022 +0200 Merge branch 'master' into dev commit b4fff0a1fd2ccb60e5debac63d1c6f165c6b1aa7 Author: Jérémie Astor Date: Sat May 14 01:20:16 2022 +0200 Revert ":wrench: Fix Makefile for CMD" This reverts commit 63e807d3b83d771749304fff3c40df13a39b9e51. commit 63e807d3b83d771749304fff3c40df13a39b9e51 Author: Jérémie Astor Date: Fri May 13 20:49:29 2022 +0200 :wrench: Fix Makefile for CMD commit d4cd99fd262216cc56b7e3c625c93d425ca95935 Author: Jérémie Astor Date: Fri May 13 17:48:13 2022 +0200 :bug: Fix perform in recursive funcs commit 7dbaa330e23648be41f3bea296306d9236ac3479 Author: Jérémie Astor Date: Fri May 13 16:37:56 2022 +0200 :art: test chuck_rewrite commit 87e4ce72d5777c42ce2430d0af933cbbd7ca7489 Author: Jérémie Astor Date: Fri May 13 16:37:42 2022 +0200 :art: Improve local error commit 8da844a7def70f62b612d5aaf9e053a97d9ef5c5 Author: Jérémie Astor Date: Fri May 13 15:57:11 2022 +0200 :art: Uncurry commit 220747ee19587f72b3e88ef4b3149ca197f818f5 Author: Jérémie Astor Date: Fri May 13 15:56:43 2022 +0200 :art: improve enum gack commit 700c827f79fdada656444055061175ed7157ac72 Author: Jérémie Astor Date: Fri May 13 11:04:19 2022 +0200 :bug: Fix constant fold code commit 2c68d7bc3bfe1d937f1113fab8c32e271bb93eec Author: Jérémie Astor Date: Thu May 12 22:46:12 2022 +0200 :art: Update BMI again commit 13857cef34584c99850385529ed7dfae5c915330 Author: Jérémie Astor Date: Thu May 12 22:12:25 2022 +0200 :bug: Add # and b to locales commit 1bc571823dd89b98d9ef31b42aab8337a0e93051 Author: Jérémie Astor Date: Thu May 12 22:09:09 2022 +0200 :bug fix partial ambiguity commit dfbd2753b29346712327075fac2579804ac52a6d Author: Jérémie Astor Date: Thu May 12 21:43:34 2022 +0200 :art: More on BMI commit 452ead875cbc8110dc6e138c37727e22fd31fd4c Author: Jérémie Astor Date: Thu May 12 20:56:58 2022 +0200 :bug: Fix locale exp lexing commit 670e633d00d849f9bdad39a40e104e573752cfdf Author: Jérémie Astor Date: Thu May 12 20:56:12 2022 +0200 :bug: Fix builtin static item access commit b812ca6f259c7b54036857d031def6da8eb2bac3 Author: Jérémie Astor Date: Thu May 12 20:55:36 2022 +0200 :bug: Use full path in ref_type commit 8dc08c4408c718478820d5125847af391ac76648 Author: Jérémie Astor Date: Wed May 11 20:34:39 2022 +0200 :wrench: Make install target more POSIX compliant commit 79d2c30999068ebe50aa322bbb6a5eaca5c4e3cd Author: Jérémie Astor Date: Wed May 11 20:33:53 2022 +0200 :bug: Abort compilation on locale error commit 1e347817dc39c6a4df44aa5cf888819a554360b0 Author: Jérémie Astor Date: Wed May 11 20:32:51 2022 +0200 :bug: Fix signature's storage commit 05ce38003f130daed1cf7c9eb297e8ae64f70751 Author: Jérémie Astor Date: Wed May 11 20:29:34 2022 +0200 :art: Allow complex => rewrites. Thanks Mort :) commit 50cd3d1e7ff9a947b77bbb5367fd3f01027f3058 Author: Jérémie Astor Date: Wed May 11 20:18:35 2022 +0200 :art: Use constructors for SinOsc yet mark the type as non abstract to allow var SinOsc foo and new SinOsc commit 71da7adff210a9323ee8e1e516f775b1a5c3b5f9 Author: Jérémie Astor Date: Tue May 10 21:06:24 2022 +0200 :art: Update soundpipe commit 375fc2720a064801856a82d6339e05bca466b5d1 Author: Jérémie Astor Date: Tue May 10 17:04:21 2022 +0200 :bug: fix char usage commit ec01b6ed6e57f62dc99ab4b3ebb2f7820a54d49c Author: Jérémie Astor Date: Mon May 9 14:04:37 2022 +0200 :art: Improve vm cleaning and fptr type check commit e03c0c19094c810a195b923cc9cd4880717eb815 Author: Jérémie Astor Date: Fri May 6 13:35:54 2022 +0200 :art: Improve resolve security --- diff --git a/Makefile b/Makefile index 62047ffe..8d979e21 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ GWION_PACKAGE=gwion -ifeq (,$(wildcard util/config.mk.orig)) +ifeq (,$(wildcard util/Makefile)) $(warning "missing git submodules, please run:") $(error "git submodules update --init --recursive") endif diff --git a/include/env/func.h b/include/env/func.h index 42230c69..db728f35 100644 --- a/include/env/func.h +++ b/include/env/func.h @@ -8,7 +8,6 @@ enum fflag { fflag_tmpl = 1 << 3, fflag_valid = 1 << 4, fflag_emit = 1 << 5, - fflag_return = 1 << 6, } __attribute__((packed)); struct Func_ { @@ -18,8 +17,8 @@ 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; diff --git a/plug b/plug index 5a583451..c9d54806 160000 --- a/plug +++ b/plug @@ -1 +1 @@ -Subproject commit 5a583451cd50f26867cf18c9bd309e3cc0f523d2 +Subproject commit c9d548067f33207ba9b92eda3b9699498752ba65 diff --git a/src/emit/emit.c b/src/emit/emit.c index 312497ef..e77094ff 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -541,7 +541,7 @@ ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) { } 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); @@ -932,9 +932,8 @@ ANN static m_bool emit_prim_locale(const Emitter emit, const Symbol *id) { vm_run(emit->gwion->vm); emit->gwion->vm->bbq->is_running = true; const m_float ret = *(m_float*)shred->reg; - if(ret == -1.0) { + if(ret == -1.0) ERR_B(prim_pos(id), "error in locale"); - } const Instr instr = emit_add_instr(emit, RegPushImm2); instr->f = ret; return GW_OK; @@ -1221,7 +1220,7 @@ ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call *exp_call) { 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; } @@ -1267,7 +1266,7 @@ ANN static inline bool member_inlinable(const Emitter emit, const Func f, const 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; @@ -1372,7 +1371,7 @@ ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *exp_call) { 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 { @@ -1397,7 +1396,7 @@ ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call *exp_call) { 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); } @@ -2565,7 +2564,7 @@ ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) { } 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)) diff --git a/src/lib/deep_equal.c b/src/lib/deep_equal.c index a71cfeaf..28d1ccbb 100644 --- a/src/lib/deep_equal.c +++ b/src/lib/deep_equal.c @@ -48,7 +48,7 @@ static void type_get_member(const Gwion gwion, const Type t, const Vector v) { 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(isa(value->type, gwion->type[et_function]) > 0 && !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); } } diff --git a/src/lib/engine.c b/src/lib/engine.c index 49c5afa8..894f68b7 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -43,7 +43,6 @@ OP_CHECK(opck_object_dot); OP_EMIT(opem_object_dot); static ID_CHECK(idck_predicate) { - set_fflag(env->func, fflag_return); return exp_self(prim)->type; } @@ -141,10 +140,6 @@ ANN static m_bool import_core_libs(const Gwi gwi) { /*set_tflag(t_lambda, tflag_infer);*/ GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda)) - gwidoc(gwi, "type for internal pointer data."); - GWI_BB(gwi_typedef_ini(gwi, "int", "@internal")) - GWI_BB(gwi_typedef_end(gwi, ae_flag_none)) - GWI_BB(import_object_op(gwi)) GWI_BB(import_values(gwi)) GWI_BB(import_union(gwi)) diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index c6992f6d..6e4b50e3 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -28,8 +28,8 @@ ANN static Exp uncurry(const Env env, const Exp_Binary *bin) { args->next = NULL; if(tmp) tmp = (tmp->next = cpy_exp(env->gwion->mp, args)); else base = (tmp = cpy_exp(env->gwion->mp, args)); - args->next = next; - } else { + args->next = next; + } else { if(!lhs) { free_exp(env->gwion->mp, base); return NULL; @@ -62,8 +62,8 @@ static OP_CHECK(opck_func_call) { if(!strncmp(bin->rhs->type->name, "partial:", 8)) { const Stmt stmt = mp_vector_at(bin->rhs->type->info->func->def->d.code->d.stmt_code.stmt_list, struct Stmt_, 0); const Exp_Call *call = &stmt->d.stmt_exp.val->d.exp_call; - const Exp args = uncurry(env, bin); - if(args) return mk_call(env, exp_self(bin), call->func, args); + DECL_ON(const Exp, args, = uncurry(env, bin)); + return mk_call(env, exp_self(bin), call->func, args); } return mk_call(env, exp_self(bin), bin->rhs, bin->lhs); } @@ -249,7 +249,7 @@ ANN static Type fptr_type(const Env env, struct FptrInfo *info) { 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 { diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 984bf45b..d748b5e4 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -197,7 +197,7 @@ OP_CHECK(opck_object_dot) { } 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)); @@ -255,12 +255,12 @@ OP_EMIT(opem_object_dot) { } 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)) { diff --git a/src/lib/union.c b/src/lib/union.c index 369c331d..a3cf314e 100644 --- a/src/lib/union.c +++ b/src/lib/union.c @@ -32,7 +32,7 @@ static OP_EMIT(opem_union_dot) { 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); diff --git a/src/parse/check.c b/src/parse/check.c index 978ba4c6..f3cb165f 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -311,7 +311,7 @@ ANN static Value check_non_res_value(const Env env, const Symbol *data) { _("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; @@ -357,7 +357,7 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) { const Value v = check_non_res_value(env, data); if (!v || !vflag(v, vflag_valid) || (v->from->ctx && v->from->ctx->error)) { const m_str name = s_name(*data); - if (!isalpha(*name) && *name != '_') { /* && *name != '@' ???*/ + if (!isalpha(*name) && *name != '_') { prim_self(data)->value = env->gwion->type[et_op]->info->value; return env->gwion->type[et_op]; } @@ -402,8 +402,6 @@ ANN static Type check_prim_id(const Env env, const Symbol *data) { 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]; } @@ -481,7 +479,7 @@ ANN static inline Type type_list_base_func(const Type type) { } 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); } @@ -549,7 +547,7 @@ ANN static Func call2ufcs(const Env env, Exp_Call *call, const Value v) { 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; } @@ -813,7 +811,7 @@ ANN m_bool func_check(const Env env, Exp_Call *const exp) { "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; @@ -1081,22 +1079,25 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) { 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, @@ -1107,35 +1108,18 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) { 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]; @@ -1303,11 +1287,6 @@ stmt_func_xxx(loop, Stmt_Loop, env_inline_mult(env, 1.5); check_idx(env, stmt->i 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, @@ -1686,12 +1665,6 @@ ANN m_bool check_fdef(const Env env, const Func_Def fdef) { 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; } diff --git a/src/parse/check_traits.c b/src/parse/check_traits.c index aba6c009..2c0dad3a 100644 --- a/src/parse/check_traits.c +++ b/src/parse/check_traits.c @@ -61,7 +61,7 @@ ANN static bool request_fun(const Env env, const Type t, 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; diff --git a/src/parse/operator.c b/src/parse/operator.c index 5179dd44..8f94d9fc 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -356,7 +356,7 @@ ANN Type op_check(const Env env, struct Op_Import *opi) { 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); diff --git a/src/parse/partial.c b/src/parse/partial.c index 9979a787..039cbbf2 100644 --- a/src/parse/partial.c +++ b/src/parse/partial.c @@ -49,7 +49,11 @@ ANN static Exp partial_exp(const Env env, Exp e, const uint i) { if(is_hole(env, e) || is_typed_hole(env, e)) { char c[256]; sprintf(c, "@%u", i); - return new_prim_id(env->gwion->mp, insert_symbol(c), e->pos); + const Exp exp = new_prim_id(env->gwion->mp, insert_symbol(c), e->pos); + exp->type = e->type; + exp->d.prim.value = new_value(env, e->type, c, e->pos); + valid_value(env, insert_symbol(c), exp->d.prim.value); + return exp; } const Exp next = e->next; e->next = NULL; @@ -212,11 +216,13 @@ ANN Type partial_type(const Env env, Exp_Call *const call) { } ERR_O(call->func->pos, _("no match found for partial application")); } + nspc_push_value(env->gwion->mp, env->curr); Func_Base *const fbase = partial_base(env, f->def->base, call->args, call->func->pos); const Stmt code = partial_code(env, call->func, call->args); const Exp exp = exp_self(call); exp->d.exp_lambda.def = new_func_def(env->gwion->mp, fbase, code); exp->exp_type = ae_exp_lambda; CHECK_OO(traverse_func_def(env, exp->d.exp_lambda.def)); + nspc_pop_value(env->gwion->mp, env->curr); return exp->d.exp_lambda.def->base->func->value_ref->type; } diff --git a/src/parse/scan0.c b/src/parse/scan0.c index c237c607..275966ca 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -187,7 +187,7 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) { 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 diff --git a/src/parse/scan1.c b/src/parse/scan1.c index b6c232c8..8438427f 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -182,8 +182,12 @@ ANN static m_bool scan1_range(const Env env, Range *range) { } ANN static inline m_bool scan1_prim(const Env env, const Exp_Primary *prim) { - if (prim->prim_type == ae_prim_hack || prim->prim_type == ae_prim_dict || prim->prim_type == ae_prim_interp) + if (prim->prim_type == ae_prim_dict || prim->prim_type == ae_prim_interp) return scan1_exp(env, prim->d.exp); + if (prim->prim_type == ae_prim_hack) { + if(env->func) env->func->weight = 1; // mark function has having gack + return scan1_exp(env, prim->d.exp); + } if (prim->prim_type == ae_prim_array && prim->d.array->exp) return scan1_exp(env, prim->d.array->exp); if (prim->prim_type == ae_prim_range) return scan1_range(env, prim->d.range); @@ -532,9 +536,17 @@ ANN m_bool scan1_union_def(const Env env, const Union_Def udef) { #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; @@ -654,7 +666,7 @@ ANN static inline m_bool scan1_fdef_defined(const Env env, 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, @@ -680,6 +692,17 @@ ANN static m_bool _scan1_func_def(const Env env, const Func_Def fdef) { --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); + env->context->error = true; + return GW_ERROR; + } return ret; } diff --git a/src/parse/scan2.c b/src/parse/scan2.c index e45c28a2..a68f0131 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -301,7 +301,7 @@ ANN static m_bool scan2_stmt_list(const Env env, Stmt_List l) { 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, diff --git a/src/parse/template.c b/src/parse/template.c index 1a9121f1..c3f25aaf 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -114,7 +114,7 @@ static ANN Type scan_func(const Env env, const Type t, const Type_Decl *td) { } 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"), @@ -122,7 +122,7 @@ static ANN Type maybe_func(const Env env, const Type t, const Type_Decl *td) { } 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); diff --git a/tests/ctor/ctor_return.gw b/tests/ctor/ctor_return.gw new file mode 100644 index 00000000..dc95d371 --- /dev/null +++ b/tests/ctor/ctor_return.gw @@ -0,0 +1,3 @@ +class C { + operator new() { return this; } +} diff --git a/tests/error/name_conflict.gw b/tests/error/name_conflict.gw index ea409add..b2c29453 100644 --- a/tests/error/name_conflict.gw +++ b/tests/error/name_conflict.gw @@ -4,5 +4,5 @@ class C { } class D extends C { - fun int test() {} + fun int test() { return 42;} }