]> Nishi Git Mirror - gwion.git/commitdiff
:art: Fix foreach bug
authorJérémie Astor <fennecdjay@gmail.com>
Tue, 6 Apr 2021 21:41:20 +0000 (23:41 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Tue, 6 Apr 2021 21:41:20 +0000 (23:41 +0200)
src/emit/emit.c
src/parse/check.c
src/parse/did_you_mean.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/template.c
src/parse/type_decl.c

index 82bf748802c32aae1eb5aef939750e8a5e614ba1..9167df53132d313b8dbb997baac6cc8fb359944e 100644 (file)
@@ -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);
index 37d91b1054d9cf29c0e211e79711f70c059b1fec..d40451af55ada68906eaa62f5515b151d01f8fd3 100644 (file)
@@ -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);
index 63819fad27dd15776f1ef87a8c4047ebd63a861d..83d58718d69cd717e2f47ef82521983ae76703f3 100644 (file)
@@ -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);
 }
index 77e7cdbe6f04426452d0fc3dd57da9d4a509f8be..683cda1ee8c6341159cc3a8de491c5e4898b623f 100644 (file)
@@ -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);
index 3cd0aeb405398ba512bf0544bf94822d9a4de39c..1cdc281af3dd2fc4e7310381eab7622d1b83b9b5 100644 (file)
@@ -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);
index e9f1f6292048e3c6ff8e0b0ed45479814641423b..b4190139813859f6c89b532d92922b5759522c40 100644 (file)
@@ -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;
 }
index 935875e935ed3871264f2036dab89d18f2145088..712ad571937d0da42ee65686ff758567eff74106 100644 (file)
@@ -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) {