From: Jérémie Astor Date: Tue, 6 Apr 2021 21:41:20 +0000 (+0200) Subject: :art: Fix foreach bug X-Git-Tag: nightly~763 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=71b8e41cdfcdb960895d393c5c74aa00df09df5d;p=gwion.git :art: Fix foreach bug --- diff --git a/src/emit/emit.c b/src/emit/emit.c index 82bf7488..9167df53 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -118,6 +118,17 @@ ANN /*static */Instr emit_kind(Emitter emit, const m_uint size, const uint addr, return instr; } +ANN static m_bool emit_class_def(const Emitter, const Class_Def); +ANN /*static */m_bool emit_cdef(const Emitter, const Type); + +ANN static inline m_bool ensure_emit(const Emitter emit, const Type t) { + if(tflag(t, tflag_emit) || !(tflag(t, tflag_cdef) || tflag(t, tflag_udef))) + return GW_OK;//clean callers + struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef, + .scope=emit->env->scope->depth, .flag=tflag_emit }; + return envset_run(&es, t); +} + ANN static void emit_struct_ctor(const Emitter emit, const Type type, const m_uint offset) { emit->code->frame->curr_offset += SZ_INT; const Instr instr = emit_add_instr(emit, RegPushMem4); @@ -834,17 +845,6 @@ ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl, return GW_OK; } -ANN static m_bool emit_class_def(const Emitter, const Class_Def); -ANN static m_bool emit_cdef(const Emitter, const Type); - -ANN static inline m_bool ensure_emit(const Emitter emit, const Type t) { - if(tflag(t, tflag_emit) || !(tflag(t, tflag_cdef) || tflag(t, tflag_udef))) - return GW_OK;//clean callers - struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef, - .scope=emit->env->scope->depth, .flag=tflag_emit }; - return envset_run(&es, t); -} - ANN static void set_late(const Gwion gwion, const Exp_Decl *decl, const Var_Decl var) { const Value v = var->value; const uint array_ref = (decl->td->array && !decl->td->array->exp) || (var->array && !var->array->exp); @@ -2298,6 +2298,7 @@ ANN static inline m_bool emit_ast_inner(const Emitter emit, Ast ast) { } ANN static m_bool emit_extend_def(const Emitter emit, const Extend_Def xdef) { + CHECK_BB(ensure_emit(emit, xdef->t)) CHECK_BB(extend_push(emit->env, xdef->t)) const m_bool ret = emit_ast_inner(emit, xdef->body); extend_pop(emit->env, xdef->t); diff --git a/src/parse/check.c b/src/parse/check.c index 37d91b10..d40451af 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -162,20 +162,37 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) { return ret > 0 ? decl->list->self->value->type : NULL; } -ANN static m_bool prim_array_inner(const Env env, Type type, const Exp e) { +ANN static m_bool prim_array_inner(const Env env, Type type, const Exp e, + const loc_t loc) { const Type common = find_common_anc(e->type, type); if(common) return GW_OK; - if(check_implicit(env, e, type) < 0) - ERR_B(e->pos, _("array init [...] contains incompatible types ...")) - return GW_OK; + if(check_implicit(env, e, type) > 0) + return GW_OK; + + char fst[16 + strlen(type->name)]; + sprintf(fst, "expected `{+/}%s{0}`", type->name); + gwerr_basic(_("literal contains incompatible types"), fst, NULL, + env->name, loc, 0); + // suggested fix: rewrite int 2 as float 2.0" + char sec[12 + strlen(e->type->name)]; + sprintf(sec, "got `{+/}%s{0}`", e->type->name); + gwerr_secondary(sec, env->name, e->pos); + + return GW_ERROR; } ANN static inline Type prim_array_match(const Env env, Exp e) { const Type type = e->type; - do CHECK_BO(prim_array_inner(env, type, e)) + bool err = false; + const loc_t loc = e->pos; + do if(prim_array_inner(env, type, e, loc) < 0) + err = true; while((e = e->next)); - return array_type(env, array_base(type), type->array_depth + 1); + if(!err) + return array_type(env, array_base(type), type->array_depth + 1); + env->context->error = true; + return NULL; } ANN static Type check_prim_array(const Env env, const Array_Sub *data) { @@ -184,7 +201,7 @@ ANN static Type check_prim_array(const Env env, const Array_Sub *data) { if(!e) ERR_O(prim_pos(data), _("must provide values/expressions for array [...]")) CHECK_OO(check_exp(env, e)) - return (array->type = prim_array_match(env, e)); + return array->type = prim_array_match(env, e); } ANN static m_bool check_range(const Env env, Range *range) { @@ -336,8 +353,43 @@ ANN static Type check_prim_hack(const Env env, const Exp *data) { return env->gwion->type[et_gack]; } +ANN static Type check_prim_map(const Env env, const Exp *data) { + CHECK_OO(check_exp(env, *data)) + if(env->func) // really? + unset_fflag(env->func, fflag_pure); + bool err = false; + Exp key = *data; + Exp val = key->next; + const Type type_key = key->type; + const Type type_val = val->type; + const loc_t loc_key = (*data)->pos; + const loc_t loc_val = (*data)->next->pos; + do { + val = key->next; + if(prim_array_inner(env, type_key, key, loc_key) < 0) + err = true; + if(prim_array_inner(env, type_val, val, loc_val) < 0) + err = true; + } while((key = val->next)); + if(!err) { + Type_Decl *td_key = type2td(env->gwion, type_key, loc_key); + Type_Decl *td_val = type2td(env->gwion, type_val, loc_val); + struct Type_List_ tl_val = { .td=td_val }; + struct Type_List_ tl_key = { .td=td_key, .next=&tl_val }; + Type_Decl td = { .xid=insert_symbol("Map"), .types=&tl_key }; + const Type t = known_type(env, &td); + free_type_decl(env->gwion->mp, td_key); + free_type_decl(env->gwion->mp, td_val); + ensure_traverse(env, t); + prim_exp(data)->type = t; + return t; + } + env->context->error = true; + return NULL; +} + #define describe_prim_xxx(name, type) \ -ANN static Type check##_prim_##name(const Env env NUSED, const union prim_data* data NUSED) {\ +ANN static Type check_prim_##name(const Env env NUSED, const union prim_data* data NUSED) {\ return type; \ } describe_prim_xxx(num, env->gwion->type[et_int]) @@ -345,9 +397,6 @@ describe_prim_xxx(char, env->gwion->type[et_char]) describe_prim_xxx(float, env->gwion->type[et_float]) describe_prim_xxx(nil, env->gwion->type[et_void]) -#define check_prim_complex check_prim_vec -#define check_prim_polar check_prim_vec -#define check_prim_char check_prim_char DECL_PRIM_FUNC(check, Type, Env); ANN static Type check_prim(const Env env, Exp_Primary *prim) { @@ -983,7 +1032,6 @@ ANN static inline Type foreach_type(const Env env, const Exp exp) { DECL_OO(const Type, t, = array_base(base)) const m_uint depth = base->array_depth - 1; return depth ? array_type(env, t, depth) : t; - } ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) { @@ -1335,6 +1383,7 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { } ANN static m_bool check_extend_def(const Env env, const Extend_Def xdef) { + CHECK_BB(ensure_check(env, xdef->t)) CHECK_BB(extend_push(env, xdef->t)) const m_bool ret = check_ast(env, xdef->body); extend_pop(env, xdef->t); diff --git a/src/parse/did_you_mean.c b/src/parse/did_you_mean.c index 63819fad..83d58718 100644 --- a/src/parse/did_you_mean.c +++ b/src/parse/did_you_mean.c @@ -53,7 +53,7 @@ ANN static void ressembles(const Nspc nspc, const char* name, bool *const done) #undef did_you_mean_nspc ANN void did_you_mean_nspc(Nspc nspc, const char* name) { CHECK_LEN(name) - bool done; + bool done = false; do ressembles(nspc, name, &done); while((nspc = nspc->parent)); } @@ -61,7 +61,7 @@ ANN void did_you_mean_nspc(Nspc nspc, const char* name) { #undef did_you_mean_type ANN void did_you_mean_type(Type type, const char* name) { CHECK_LEN(name) - bool done; + bool done = false; do ressembles(type->nspc, name, &done); while((type = type->info->parent) && type->nspc); } diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 77e7cdbe..683cda1e 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -595,6 +595,7 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) { } ANN static m_bool scan1_extend_def(const Env env, const Extend_Def xdef) { + CHECK_BB(ensure_scan1(env, xdef->t)) CHECK_BB(extend_push(env, xdef->t)) const m_bool ret = scan1_ast(env, xdef->body); extend_pop(env, xdef->t); diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 3cd0aeb4..1cdc281a 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -529,6 +529,7 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def fdef) { ANN static m_bool scan2_extend_def(const Env env, const Extend_Def xdef) { + CHECK_BB(ensure_scan2(env, xdef->t)) CHECK_BB(extend_push(env, xdef->t)) const m_bool ret = scan2_ast(env, xdef->body); extend_pop(env, xdef->t); diff --git a/src/parse/template.c b/src/parse/template.c index e9f1f629..b4190139 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -111,7 +111,8 @@ ANN Type scan_type(const Env env, const Type t, Type_Decl* td) { if(td->next) { Type_Decl *next = td->next; td->next = NULL; - const Type owner = known_type(env, td); + const Type maybe_array = known_type(env, td); + const Type owner = array_base(maybe_array); td->next = next; CHECK_OO(owner) if(!owner->nspc) @@ -120,11 +121,15 @@ ANN Type scan_type(const Env env, const Type t, Type_Decl* td) { .scope=env->scope->depth, .flag=tflag_none }; envset_push(&es, owner, owner->nspc); (void)env_push(env, owner, owner->nspc);// TODO: is this needed? - const Type ret = scan_type(env, t, td->next); +// const Type ret = scan_type(env, t, td->next); +printf("known %s\n", owner->name); + const Type ret = known_type(env, td->next); env_pop(env, es.scope); if(es.run) envset_pop(&es, owner); - return ret; + if(!td->array) + return ret; + return array_type(env, ret, td->array->depth); } return !t->array_depth ? _scan_type(env, t, td) : t; } diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index 935875e9..712ad571 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -29,13 +29,17 @@ ANN static inline Type ref(const Env env, Type_Decl* td) { } ANN static Type resolve(const Env env, Type_Decl* td) { + Type_Decl *last = td; + while(last->next) + last = last->next; + Array_Sub array = last->array; DECL_OO(const Type, base, = find_type(env, td)) if(base->info->ctx && base->info->ctx->error) ERR_O(td->pos, _("type '%s' is invalid"), base->name) DECL_OO(const Type, type, = scan_type(env, base, td)) const Type t = !td->ref ? type : ref(env, td); const Type ret = !td->option ? t : option(env, td); - return !td->array ? ret: array_type(env, ret, td->array->depth); + return !array ? ret: array_type(env, ret, array->depth); } ANN static inline void* type_unknown(const Env env, const Type_Decl* td) {