]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve error message
authorfennecdjay <astor.jeremie@wanadoo.fr>
Tue, 9 Apr 2019 09:35:04 +0000 (11:35 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Tue, 9 Apr 2019 09:35:04 +0000 (11:35 +0200)
23 files changed:
ast
include/env.h
include/gwion.h
include/operator.h
include/parse.h
include/type.h
src/emit/emit.c
src/gwion.c
src/lib/func.c
src/lib/import.c
src/lib/instr.c
src/lib/object.c
src/oo/env_utils.c
src/parse/check.c
src/parse/operator.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/type_decl.c
src/parse/type_utils.c
src/plug.c
tests/error/func_code_error.gw
util

diff --git a/ast b/ast
index 5a1fda275fe41169cfe9edae73a7fd95811d24b8..853459cbbf4693c87febaa4be332818cf191a03b 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 5a1fda275fe41169cfe9edae73a7fd95811d24b8
+Subproject commit 853459cbbf4693c87febaa4be332818cf191a03b
index 9934d14313b341229efd4ca14c8d3e8980bd6d94..714b6cd8697258a739e0f021f7a5e0e545970e94 100644 (file)
@@ -50,8 +50,8 @@ ANN Type type_decl_resolve(const Env, const Type_Decl*);
 ANEW ANN m_str tl2str(const Env, const Type_List); // in type_decl.c
 ANN m_bool compat_func(const __restrict__ Func_Def, const __restrict__ Func_Def);
 ANN Type known_type(const Env env, const Type_Decl*);
-ANN m_bool env_access(const Env env, const ae_flag flag);
-ANN m_bool env_storage(const Env env, ae_flag flag);
+ANN m_bool env_access(const Env env, const ae_flag flag, const uint pos);
+ANN m_bool env_storage(const Env env, ae_flag flag, const uint pos);
 ANN void env_add_type(const Env, const Type);
 ANN Type find_type(const Env, ID_List);
 ANN m_bool already_defined(const Env env, const Symbol s, const uint pos);
index 058a46e805b54241486cb3c4d4deaeb89de55862..a557c92a25c383859ecdcb1eb21396dfcd426371 100644 (file)
@@ -17,6 +17,7 @@ struct Gwion_ {
 
 ANN m_bool gwion_ini(const Gwion, struct Arg_*);
 ANN VM* gwion_cpy(const VM*);
-ANN void   gwion_run(const Gwion gwion);
-ANN void   gwion_end(const Gwion gwion);
+ANN void gwion_run(const Gwion gwion);
+ANN void gwion_end(const Gwion gwion);
+ANN void gwion_err(const Gwion gwion, const uint pos, const m_str fmt, ...);
 #endif
index 6980827a57bc3601d0c53340da71ef2685866b21..c34e34f7ae905ce0e29551e809e2d6f581251284 100644 (file)
@@ -9,6 +9,7 @@ struct Op_Import {
   opck ck;
   opem em;
   uintptr_t data;
+  uint pos;
   Operator op;
   m_bool mut;
 };
index c5350fe91b56fb7b90fb6a118a0b900409caecc8..fb68ae88019e0852d31dac4821dc5f394c28b5fd 100644 (file)
@@ -4,6 +4,10 @@
 #include "gwion.h"
 #define insert_symbol(a) insert_symbol(env->gwion->st, (a))
 
+#undef ERR_B
+#define ERR_B(a, b, ...) { gwion_err(env->gwion, (a), (b), ## __VA_ARGS__); return GW_ERROR; }
+#undef ERR_O
+#define ERR_O(a, b, ...) { gwion_err(env->gwion, (a), (b), ## __VA_ARGS__); return NULL; }
 
 #define RET_NSPC(exp)       \
 ++env->scope->depth;        \
index df3b0c97a48ad5b92e78e9bd5a1532def752022b..83f0efd0cb650742eef73c8787190d683286ab29 100644 (file)
@@ -29,7 +29,7 @@ ANN m_str get_type_name(const Env, const m_str, const m_uint);
 ANN Value find_value(const Type, const Symbol);
 ANN Func find_func(const Type, const Symbol);
 ANN m_bool isa(const Type, const Type) __attribute__((pure));
-ANN m_bool isres(const Symbol);
+ANN m_bool isres(const Env, const Symbol, const uint pos);
 ANN Type array_type(const Env, const Type, const m_uint);
 ANN Type find_common_anc(const Type, const Type) __attribute__((pure));
 ANN m_uint id_list_len(ID_List);
index 6f1dafc5d9dfdf430249d87434ec8922fd76e135..e913b22b76929f6ea4b85971357813f3d65d2725 100644 (file)
 #undef insert_symbol
 #define insert_symbol(a) insert_symbol(emit->env->gwion->st, (a))
 
+#undef ERR_B
+#define ERR_B(a, b, ...) { gwion_err(emit->gwion, (a), (b), ## __VA_ARGS__); return GW_ERROR; }
+#undef ERR_O
+#define ERR_O(a, b, ...) { gwion_err(emit->gwion, (a), (b), ## __VA_ARGS__); return NULL; }
+
 typedef struct Local_ {
   m_uint size;
   m_uint offset;
@@ -1511,22 +1516,17 @@ ANN static m_bool emit_VecMember(const Emitter emit, const Exp_Dot* member) {
 }
 
 ANN static m_bool emit_vararg_start(const Emitter emit, const m_uint offset) { GWDEBUG_EXE
-  if(emit->env->func->variadic)
-    ERR_B(0, "vararg.start already used. this is an error")
   emit->env->func->variadic = emit_add_instr(emit, VarargTop);
   emit->env->func->variadic->m_val = offset;
   emit->env->func->variadic->m_val2 = emit_code_size(emit);
   return GW_OK;
 }
 
-ANN static m_bool emit_vararg_end(const Emitter emit, const m_uint offset) { GWDEBUG_EXE
-  if(!emit->env->func->variadic)
-    ERR_B(0, "vararg.start not used before vararg.end. this is an error")
+ANN static void emit_vararg_end(const Emitter emit, const m_uint offset) { GWDEBUG_EXE
   const Instr instr = emit_add_instr(emit, VarargEnd);
   instr->m_val = offset;
   instr->m_val2 = emit->env->func->variadic->m_val2;
   emit->env->func->variadic->m_val2 = emit_code_size(emit);
-  return GW_OK;
 }
 
 ANN static m_bool emit_vararg(const Emitter emit, const Exp_Dot* member) { GWDEBUG_EXE
@@ -1537,10 +1537,18 @@ ANN static m_bool emit_vararg(const Emitter emit, const Exp_Dot* member) { GWDEB
     offset += l->type->size;
     l = l->next;
   }
-  if(!strcmp(str, "start"))
-    return emit_vararg_start(emit, offset);
-  if(!strcmp(str, "end"))
-    return emit_vararg_end(emit, offset);
+  if(!strcmp(str, "start")) {
+    if(emit->env->func->variadic)
+      ERR_B(exp_self(member)->pos, "vararg.start already used. this is an error")
+    emit_vararg_start(emit, offset);
+    return GW_OK;
+  }
+  if(!strcmp(str, "end")) {
+    if(!emit->env->func->variadic)
+      ERR_B(exp_self(member)->pos, "vararg.start not used before vararg.end. this is an error")
+    emit_vararg_end(emit, offset);
+    return GW_OK;
+  }
   const Instr instr = emit_add_instr(emit, VarargMember);
   instr->m_val = offset;
   instr->m_val2 = exp_self(member)->type->size;
@@ -1677,7 +1685,7 @@ ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def) { G
   emit->env->func = func;
   CHECK_BB(emit_func_def_body(emit, func_def))
   if(GET_FLAG(func_def, variadic) && !emit->env->func->variadic)
-    ERR_B(func_def->base->td->xid->pos, "invalid variadic use")
+    ERR_B(func_def->pos, "invalid variadic use")
   emit_func_def_return(emit);
   emit_func_def_code(emit, func);
   emit->env->func = former;
index e25f98e7d4f99459fe9cf98078d510e8eb640001..45f1503fcaa92aedfa776e5c534a9e3d3d5360a3 100644 (file)
@@ -4,6 +4,9 @@
 #include "oo.h"
 #include "vm.h"
 #include "env.h"
+#include "type.h"
+#include "func.h"
+#include "value.h"
 #include "instr.h"
 #include "emit.h"
 #include "engine.h"
@@ -96,3 +99,21 @@ ANN void gwion_end(const Gwion gwion) {
   free_symbols(gwion->st);
   mempool_end(gwion->p);
 }
+
+ANN void gwion_err(const Gwion gwion, const uint pos, const m_str fmt, ...) {
+  const Env env = gwion->env;
+  gw_err("in file: '%s'\n", env->name);
+  if(env->class_def)
+    gw_err("in class: '%s'\n", env->class_def->name);
+  if(env->func) // problem with scan1 FAKE_FUNC
+    gw_err("in function: '%s'\n", env->func->name);
+  if(pos)
+    fprintf(stderr, "line: %u\t", pos);
+  else
+    fprintf(stderr, "\t");
+  va_list arg;
+  va_start(arg, fmt);
+  vfprintf(stderr, fmt, arg);
+  va_end(arg);
+  fprintf(stderr, "\n");
+}
\ No newline at end of file
index 7bdb68c4736794df1c84113e48bc73f738cc99cd..588a8f9106f4b7460cbed0aa8a688ef94299bcb8 100644 (file)
@@ -31,7 +31,7 @@ static OP_CHECK(opck_func_call) {
   Exp e = exp_self(bin);
   e->exp_type = ae_exp_call;
   memcpy(&e->d.exp_call, &call, sizeof(Exp_Call));
-  return check_exp_call1(env, &e->d.exp_call);
+  return check_exp_call1(env, &e->d.exp_call) ?: t_null;
 }
 
 static OP_EMIT(opem_func_assign) {
@@ -71,7 +71,7 @@ ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner,
   }
   if(base || arg)
     ERR_B(exp_self(l)->pos, "argument number does not match for lambda")
-  l->def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, def->base->td, l->name, l->args), l->code, def->flag);
+  l->def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, def->base->td, l->name, l->args), l->code, def->flag, def->pos);
   const m_bool ret = traverse_func_def(env, l->def);
   arg = l->args;
   while(arg) {
index fc2f8db52019ae37a13b595b93f9bcb20a03cc42..b37b151b6aac01286ce69b57ee36a8f0efda14f5 100644 (file)
@@ -433,7 +433,7 @@ ANN static Func_Def make_dll_as_fun(const Env env, DL_Func * dl_fun, ae_flag fla
   }
   name = dl_fun->name;
   arg_list = make_dll_arg_list(env, dl_fun);
-  func_def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, type_decl, insert_symbol(env->gwion->st, name), arg_list), NULL, flag);
+  func_def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, type_decl, insert_symbol(env->gwion->st, name), arg_list), NULL, flag, 0);
   func_def->d.dl_func_ptr = (void*)(m_uint)dl_fun->addr;
   return func_def;
 }
@@ -447,7 +447,7 @@ ANN m_int gwi_func_end(const Gwi gwi, const ae_flag flag) {
   Func_Def def = import_fun(gwi->gwion->env, &gwi->func, flag);
   CHECK_OB(def)
   if(gwi->templater.n) {
-    def = new_func_def(gwi->gwion->p, new_func_base(gwi->gwion->p, NULL, NULL, NULL), NULL, 0);
+    def = new_func_def(gwi->gwion->p, new_func_base(gwi->gwion->p, NULL, NULL, NULL), NULL, 0, 0);
     const ID_List list = templater_def(gwi->gwion->st, &gwi->templater);
     def->tmpl = new_tmpl_list(gwi->gwion->p, list, -1);
     SET_FLAG(def, template);
@@ -480,7 +480,7 @@ ANN2(1,2) static int import_op(const Env env, const DL_Oper* op,
   const Type rhs = op->rhs ? get_type(env, op->rhs) : NULL;
   const Type ret = get_type(env, op->ret);
   const struct Op_Import opi = { lhs, rhs, ret,
-    op->ck, op->em, (uintptr_t)f, op->op, op->mut };
+    op->ck, op->em, (uintptr_t)f, 0, op->op, op->mut };
   return env_add_op(env, &opi);
 }
 
index 957cdd681cd532a80f1e0f3db42a3062e5dc3931..ed8ed6706501f5fd9d89b5344591a9d665dc5f78 100644 (file)
@@ -70,7 +70,7 @@ ANN static Func_Def from_base(const Env env, const struct dottmpl_ *dt, const Ty
   CHECK_OO(v)
   const Func_Def base = v->d.func_ref->def;
   const Func_Def def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, base->base->td, insert_symbol(env->gwion->st, v->name),
-            base->base->args), base->d.code, base->flag);
+            base->base->args), base->d.code, base->flag, base->pos);
   def->tmpl = new_tmpl_list(env->gwion->p, base->tmpl->list, dt->overload);
   SET_FLAG(def, template);
   return def;
index e74bc2a6152bba1c7be273ea0ce759d1d675e142..ccfb0e02e028294f596ac9b089b2f00973e3797d 100644 (file)
@@ -15,7 +15,7 @@
 #include "operator.h"
 
 ANN void exception(const VM_Shred shred, const m_str c) {
-  err_msg(0, "%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]",
+  gw_err("%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]",
           c, shred->tick->xid, shred->info->name, shred->pc - 1);
   vm_shred_exit(shred);
 }
index 27651ba7af8b4147484292e7b3174762e7b5d963..5f2be4df055a0580448dd38c64d1a898782851a8 100644 (file)
@@ -20,21 +20,21 @@ ANN Nspc env_nspc(const Env env) {
 }
 
 #define GET(a,b) ((a) & (b)) == (b)
-ANN m_bool env_access(const Env env, const ae_flag flag) {
+ANN m_bool env_access(const Env env, const ae_flag flag, const uint pos) {
   if(env->scope->depth) {
    if(GET(flag, ae_flag_global))
-      ERR_B(0, "'global' can only be used at %s scope.",
+      ERR_B(pos, "'global' can only be used at %s scope.",
           GET(flag, ae_flag_global) && !env->class_def ?
            "file" : "class")
   }
   if((GET(flag, ae_flag_static) || GET(flag, ae_flag_private) ||
       GET(flag, ae_flag_protect)) && (!env->class_def || env->scope->depth))
-      ERR_B(0, "static/private/protect can only be used at class scope.")
+      ERR_B(pos, "static/private/protect can only be used at class scope.")
   return GW_OK;
 }
 
-ANN m_bool env_storage(const Env env, ae_flag flag) {
-  CHECK_BB(env_access(env, flag))
+ANN m_bool env_storage(const Env env, ae_flag flag, const uint pos) {
+  CHECK_BB(env_access(env, flag, pos))
   return !(env->class_def && GET(flag, ae_flag_global)) ? GW_OK :GW_ERROR;
 }
 
index 12cdc22a60531f668042e7120e228d2f32bd9789..c06ba982fc5e9a52c8c68fee6e8744f9471ede05 100644 (file)
 #include "operator.h"
 #include "switch.h"
 
-#define OP_RET(a, b)\
-  const Type op_ret = op_check(env, &opi);\
-  if(!op_ret)\
-    ERR_O(exp_self(a)->pos, "in %s expression", b)\
-  return op_ret;
-
 ANN static Type   check_exp(const Env env, Exp exp);
 ANN static m_bool check_stmt_list(const Env env, Stmt_List list);
 ANN m_bool check_class_def(const Env env, const Class_Def class_def);
@@ -140,7 +134,7 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) { GWDEBUG_EXE
   return decl->type;
 }
 
-ANN static m_bool prim_array_inner(const Type t, Type type, const Exp e) {
+ANN static m_bool prim_array_inner(const Env env, const Type t, Type type, const Exp e) {
   const Type common = find_common_anc(t, type);
   if(common)
     return GW_OK;
@@ -148,12 +142,12 @@ ANN static m_bool prim_array_inner(const Type t, Type type, const Exp e) {
       e->cast_to = type;
       return GW_OK;
   }
-  return err_msg(e->pos, "array init [...] contains incompatible types ...");
+  ERR_B(e->pos, "array init [...] contains incompatible types ...")
 }
 
 ANN static inline Type prim_array_match(const Env env, Exp e) {
   const Type type = e->type;
-  do CHECK_BO(prim_array_inner(e->type, type, e))
+  do CHECK_BO(prim_array_inner(env, e->type, type, e))
   while((e = e->next));
   return array_type(env, type->array_depth ? array_base(type) : type, type->array_depth + 1);
 }
@@ -186,7 +180,7 @@ ANN static Value check_non_res_value(const Env env, const Exp_Primary* primary)
 ANN static Type prim_id_non_res(const Env env, const Exp_Primary* primary) {
   const Value v = check_non_res_value(env, primary);
   if(!v || !GET_FLAG(v, checked)) {
-    err_msg(exp_self(primary)->pos,
+    gwion_err(env->gwion, exp_self(primary)->pos,
           "variable %s not legit at this point.", s_name(primary->d.var));
     did_you_mean(env->gwion->st, s_name(primary->d.var));
     return NULL;
@@ -353,7 +347,7 @@ ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t,
       }
       if(implicit) {
         const struct Implicit imp = { e, t };
-        struct Op_Import opi = { .op=op_impl, .lhs=e->type, .rhs=t, .data=(m_uint)&imp };
+        struct Op_Import opi = { .op=op_impl, .lhs=e->type, .rhs=t, .data=(m_uint)&imp, .pos=e->pos };
       return op_check(env, &opi) ? 1 : -1;
     }
   }
@@ -436,7 +430,7 @@ ANN static Func _find_template_match(const Env env, const Value v, const Exp_Cal
         continue;
       base = value->d.func_ref->def;
       def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, base->base->td, insert_symbol(v->name),
-                base->base->args), base->d.code, base->flag);
+                base->base->args), base->d.code, base->flag, base->pos);
       def->tmpl = new_tmpl_list(env->gwion->p, base->tmpl->list, (m_int)i);
       SET_FLAG(def, template);
     }
@@ -476,8 +470,7 @@ ANN Func find_template_match(const Env env, const Value value, const Exp_Call* e
      t = t->parent;
   }
   assert(exp_self(exp));
-  err_msg(exp_self(exp)->pos, "arguments do not match for template call");
-  return NULL;
+  ERR_O(exp_self(exp)->pos, "arguments do not match for template call")
 }
 
 ANN static void print_current_args(Exp e) {
@@ -493,8 +486,8 @@ ANN static void print_arg(Arg_List e) {
   while((e = e->next) && gw_err(","));
 }
 
-ANN2(1) static void* function_alternative(const Type f, const Exp args){
-  err_msg(args ? args->pos : 0, "argument type(s) do not match for function. should be :");
+ANN2(1) static void* function_alternative(const Env env, const Type f, const Exp args, const uint pos){
+  gwion_err(env->gwion, pos, "argument type(s) do not match for function. should be :");
   Func up = f->d.func;
   do {
     gw_err("(%s)\t", up->name);
@@ -584,7 +577,7 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
   }
   if(arg || e)
     ERR_O(exp_self(exp)->pos, "argument number does not match for lambda")
-  l->def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, NULL, l->name, l->args), l->code, 0);
+  l->def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, NULL, l->name, l->args), l->code, 0, exp_self(exp)->pos);
   CHECK_BO(traverse_func_def(env, l->def))
   if(env->class_def)
     SET_FLAG(l->def, member);
@@ -606,7 +599,7 @@ ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
     return check_exp_call_template(env, exp);
   const Func func = find_func_match(env, exp->func->type->d.func, exp->args);
   return (exp_self(exp)->d.exp_call.m_func = func) ?
-    func->def->base->ret_type : function_alternative(exp->func->type, exp->args);
+    func->def->base->ret_type : function_alternative(env, exp->func->type, exp->args, exp_self(exp)->pos);
 }
 
 ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) { GWDEBUG_EXE
@@ -615,22 +608,22 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) { GWDEBUG
     bin->rhs->type = bin->rhs->d.exp_decl.type = bin->lhs->type;
   CHECK_OO(check_exp(env, bin->rhs))
   struct Op_Import opi = { .op=bin->op, .lhs=bin->lhs->type,
-    .rhs=bin->rhs->type, .data=(uintptr_t)bin };
-  OP_RET(bin, "binary")
+    .rhs=bin->rhs->type, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos };
+  return op_check(env, &opi);
 }
 
 ANN static Type check_exp_cast(const Env env, const Exp_Cast* cast) { GWDEBUG_EXE
   const Type t = check_exp(env, cast->exp);
   CHECK_OO(t)
   CHECK_OO((exp_self(cast)->type = cast->td->xid ? known_type(env, cast->td) : check_td(env, cast->td)))
-  struct Op_Import opi = { .op=op_cast, .lhs=t, .rhs=exp_self(cast)->type, .data=(uintptr_t)cast };
-  OP_RET(cast, "cast")
+  struct Op_Import opi = { .op=op_cast, .lhs=t, .rhs=exp_self(cast)->type, .data=(uintptr_t)cast, .pos=exp_self(cast)->pos };
+  return op_check(env, &opi);
 }
 
 ANN static Type check_exp_post(const Env env, const Exp_Postfix* post) { GWDEBUG_EXE
-  struct Op_Import opi = { .op=post->op, .lhs=check_exp(env, post->exp), .data=(uintptr_t)post };
+  struct Op_Import opi = { .op=post->op, .lhs=check_exp(env, post->exp), .data=(uintptr_t)post, .pos=exp_self(post)->pos };
   CHECK_OO(opi.lhs)
-  OP_RET(post, "postfix");
+  return op_check(env, &opi);
 }
 
 ANN static Type check_exp_call(const Env env, Exp_Call* exp) { GWDEBUG_EXE
@@ -653,10 +646,10 @@ ANN static Type check_exp_call(const Env env, Exp_Call* exp) { GWDEBUG_EXE
 
 ANN static Type check_exp_unary(const Env env, const Exp_Unary* unary) { GWDEBUG_EXE
   struct Op_Import opi = { .op=unary->op, .rhs=unary->exp ? check_exp(env, unary->exp) : NULL,
-    .data=(uintptr_t)unary };
+    .data=(uintptr_t)unary, .pos=exp_self(unary)->pos };
   if(unary->exp && !opi.rhs)
     return NULL;
-  OP_RET(unary, "unary")
+  return op_check(env, &opi);
 }
 
 ANN static Type check_exp_if(const Env env, const Exp_If* exp_if) { GWDEBUG_EXE
@@ -755,7 +748,7 @@ ANN static m_bool check_stmt_code(const Env env, const Stmt_Code stmt) { GWDEBUG
   return GW_OK;
 }
 
-ANN static m_bool check_flow(const Exp exp, const m_str orig) { GWDEBUG_EXE
+ANN static m_bool check_flow(const Env env, const Exp exp, const m_str orig) { GWDEBUG_EXE
   if(isa(exp->type, t_object) > 0 || isa(exp->type, t_int) > 0 || isa(exp->type, t_float) > 0 ||
      isa(exp->type, t_dur) > 0 || isa(exp->type, t_time)  > 0)
     return GW_OK;
@@ -776,7 +769,7 @@ ANN static m_bool check_conts(const Env env, const Stmt a, const Stmt b) { GWDEB
   return GW_OK;
 }
 
-ANN static inline m_bool for_empty(const Stmt_For stmt) {
+ANN static inline m_bool for_empty(const Env env, const Stmt_For stmt) {
   if(!stmt->c2 || !stmt->c2->d.stmt_exp.val)
     ERR_B(stmt_self(stmt)->pos, "empty for loop condition...",
           "...(note: explicitly use 'true' if it's the intent)",
@@ -826,7 +819,7 @@ ANN static m_bool do_stmt_auto(const Env env, const Stmt_Auto stmt) { GWDEBUG_EX
   return check_conts(env, stmt_self(stmt), stmt->body);
 }
 
-ANN static m_bool cond_type(const Exp e) {
+ANN static m_bool cond_type(const Env env, const Exp e) {
   const Type t = e->type;
   if(isa(t, t_int) > 0)
     return GW_OK;
@@ -838,25 +831,25 @@ ANN static m_bool cond_type(const Exp e) {
 }
 #define stmt_func_xxx(name, type, prolog, exp) describe_stmt_func(check, name, type, prolog, exp)
 stmt_func_xxx(if, Stmt_If,, !(!check_exp(env, stmt->cond) ||
-  check_flow(stmt->cond, "if") < 0   ||
+  check_flow(env, stmt->cond, "if") < 0   ||
   check_stmt(env, stmt->if_body) < 0 ||
   (stmt->else_body && check_stmt(env, stmt->else_body) < 0)) ? 1 : -1)
 stmt_func_xxx(flow, Stmt_Flow,,
   !(!check_exp(env, stmt->cond) ||
-    check_flow(stmt->cond, stmt_self(stmt)->stmt_type == ae_stmt_while ? "while" : "until") < 0 ||
+    check_flow(env, stmt->cond, stmt_self(stmt)->stmt_type == ae_stmt_while ? "while" : "until") < 0 ||
     check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
 stmt_func_xxx(for, Stmt_For,, !(
-  for_empty(stmt) < 0 ||
+  for_empty(env, stmt) < 0 ||
   check_stmt(env, stmt->c1) < 0 ||
   check_stmt(env, stmt->c2) < 0 ||
-  check_flow(stmt->c2->d.stmt_exp.val, "for") < 0 ||
+  check_flow(env, stmt->c2->d.stmt_exp.val, "for") < 0 ||
   (stmt->c3 && !check_exp(env, stmt->c3)) ||
   check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
 stmt_func_xxx(loop, Stmt_Loop,, !(!check_exp(env, stmt->cond) ||
-  cond_type(stmt->cond) < 0 ||
+  cond_type(env, stmt->cond) < 0 ||
   check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
 stmt_func_xxx(switch, Stmt_Switch,, !(!check_exp(env, stmt->val) ||
-  cond_type(stmt->val) < 0 || !switch_add(env, stmt) ||
+  cond_type(env, stmt->val) < 0 || !switch_add(env, stmt) ||
   check_breaks(env, stmt_self(stmt), stmt->stmt) < 0 || !switch_pop(env)) ? 1 : -1)
 stmt_func_xxx(auto, Stmt_Auto,, do_stmt_auto(env, stmt))
 
@@ -981,12 +974,12 @@ ANN static m_bool check_stmt_list(const Env env, Stmt_List l) { GWDEBUG_EXE
   return GW_OK;
 }
 
-ANN static m_bool check_signature_match(const Func_Def f, const Func parent) { GWDEBUG_EXE
+ANN static m_bool check_signature_match(const Env env, const Func_Def f, const Func parent) { GWDEBUG_EXE
   if(GET_FLAG(parent->def, static) != GET_FLAG(f, static)) {
     const m_str c_name  = f->base->func->value_ref->owner_class->name;
     const m_str p_name = parent->value_ref->owner_class->name;
     const m_str f_name = s_name(f->base->xid);
-    ERR_B(f->base->td->xid->pos,
+    ERR_B(td_pos(f->base->td),
           "function '%s.%s' ressembles '%s.%s' but cannot override...\n"
           "\t...(reason: '%s.%s' is declared as 'static')",
           c_name, f_name, p_name, c_name,
@@ -1000,7 +993,7 @@ ANN static m_bool parent_match_actual(const Env env, const restrict Func_Def f,
   Func parent_func = func;
   do {
     if(compat_func(f, parent_func->def) > 0) {
-      CHECK_BB(check_signature_match(f, parent_func))
+      CHECK_BB(check_signature_match(env, f, parent_func))
       if(!f->tmpl) {
         f->base->func->vt_index = parent_func->vt_index;
         vector_set(&env->curr->info->vtable, f->base->func->vt_index, (vtype)f->base->func);
@@ -1056,7 +1049,7 @@ ANN static m_bool check_func_overload(const Env env, const Func_Def f) {
     for(m_uint j = i + 1; f1 && j <= v->offset; ++j) {
       const Func f2 = get_overload(env, f, j);
       if(f2 && compat_func(f1->def, f2->def) > 0)
-        ERR_B(f2->def->base->td->xid->pos, "global function '%s' already defined"
+        ERR_B(td_pos(f2->def->base->td), "global function '%s' already defined"
           " for those arguments", s_name(f->base->xid))
     }
   }
@@ -1068,7 +1061,7 @@ ANN static m_bool check_func_def_override(const Env env, const Func_Def f) { GWD
   if(env->class_def && env->class_def->parent) {
     const Value override = find_value(env->class_def->parent, f->base->xid);
     if(override && override->owner_class && isa(override->type, t_function) < 0)
-      ERR_B(f->base->td->xid->pos,
+      ERR_B(f->pos,
             "function name '%s' conflicts with previously defined value...\n"
             "\tfrom super class '%s'...",
             s_name(f->base->xid), override->owner_class->name)
@@ -1091,7 +1084,7 @@ ANN static void operator_func(const Func f) {
   const Type l = is_unary ? NULL : a->type;
   const Type r = is_unary ? a->type : a->next ? a->next->type : NULL;
   const Operator op = name2op(s_name(f->def->base->xid));
-  struct Op_Import opi = { .op=op, .lhs=l, .rhs=r, .data=(m_uint)f };
+  struct Op_Import opi = { .op=op, .lhs=l, .rhs=r, .data=(m_uint)f, .pos=f->def->pos };
   operator_set_func(&opi);
 }
 
@@ -1120,8 +1113,7 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
   if(ret > 0) {
     const Value variadic = GET_FLAG(f, variadic) ? set_variadic(env) : NULL;
     if(!GET_FLAG(f, builtin) && check_stmt_code(env, &f->d.code->d.stmt_code) < 0)
-      ret = err_msg(f->base->td ? f->base->td->xid->pos : 0, "...in function '%s'", 
-         s_name(f->base->xid));
+      ret = GW_ERROR;
     if(variadic)
       REM_REF(variadic, env->gwion)
     if(GET_FLAG(f, builtin))
index 9e4c13d8d358adf8b33dfadbba098d44047e2d34..bfc20339d5faf8863e35a74af95fc1ffca13e1ec 100644 (file)
@@ -79,16 +79,23 @@ ANN2(1) static M_Operator* operator_find(const Vector v, const restrict Type lhs
 }
 
 ANN m_bool add_op(const Gwion gwion, const Nspc nspc, const struct Op_Import* opi) {
-  Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
   M_Operator* mo;
+  Nspc n = nspc;
+  do {
+    if(!n->info->op_map.ptr)
+      continue;
+    const Vector v = (Vector)map_get(&n->info->op_map, (vtype)opi->op);
+    if(v && (mo = operator_find(v, opi->lhs, opi->rhs)))
+      ERR_B(opi->pos, "operator '%s', for type '%s' and '%s' already imported",
+            op2str(opi->op), opi->lhs ? opi->lhs->name : NULL,
+            opi->rhs ? opi->rhs->name : NULL)
+  } while((n = n->parent));
+  Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
   if(!v) {
     v = new_vector(gwion->p);
     map_set(&nspc->info->op_map, (vtype)opi->op, (vtype)v);
   }
-  if((mo = operator_find(v, opi->lhs, opi->rhs)))
-    CHECK_BB((err_msg(0, "operator '%s', for type '%s' and '%s' already imported",
-            op2str(opi->op), opi->lhs ? opi->lhs->name : NULL,
-            opi->rhs ? opi->rhs->name : NULL)))
+// new mo
   mo = mp_alloc(gwion->p, M_Operator);
   mo->lhs       = opi->lhs;
   mo->rhs       = opi->rhs;
@@ -97,7 +104,9 @@ ANN m_bool add_op(const Gwion gwion, const Nspc nspc, const struct Op_Import* op
   mo->ck     = opi->ck;
   mo->em     = opi->em;
   mo->mut     = opi->mut;
+// add
   vector_add(v, (vtype)mo);
+// mo_type_ref
   if(opi->lhs && opi->lhs != OP_ANY_TYPE)
     ADD_REF(opi->lhs)
   if(opi->rhs && opi->rhs != OP_ANY_TYPE)
@@ -141,13 +150,14 @@ static m_str type_name(const Type t) {
 }
 
 ANN Type op_check(const Env env, struct Op_Import* opi) {
+  Type ret = NULL;
   Nspc nspc = env->curr;
   do {
     if(nspc->info->op_map.ptr) {
       Type l = opi->lhs;
       do {
         struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data };
-        Type ret = op_check_inner(env, &nspc->info->op_map, &opi2);
+        ret = op_check_inner(env, &nspc->info->op_map, &opi2);
         if(ret) {
           if(ret == t_null)
             break;
@@ -159,10 +169,9 @@ ANN Type op_check(const Env env, struct Op_Import* opi) {
     }
     nspc = nspc->parent;
   } while(nspc);
-  if(opi->op != op_impl)
-  (void)err_msg(0, "%s %s %s: no match found for operator",
+  if(opi->op == op_cast || (ret != t_null && opi->op != op_impl))
+    err_msg(opi->pos, "%s %s %s: no match found for operator",
     type_name(opi->lhs), op2str(opi->op), type_name(opi->rhs));
-
   return NULL;
 }
 
index 80a294066d7bc56336d09f87f5ee96d1546f9e42..f79f05c0c6cd016342336aecd3ef3044cc9ab8f7 100644 (file)
@@ -29,8 +29,8 @@ ANN static inline m_bool scan0_defined(const Env env, const Symbol s, const uint
 }
 
 ANN m_bool scan0_stmt_fptr(const Env env, const Stmt_Fptr stmt) { GWDEBUG_EXE
-  CHECK_BB(env_access(env, stmt->base->td->flag))
-  CHECK_BB(scan0_defined(env, stmt->base->xid, stmt->base->td->xid->pos));
+  CHECK_BB(env_access(env, stmt->base->td->flag, stmt_self(stmt)->pos))
+  CHECK_BB(scan0_defined(env, stmt->base->xid, td_pos(stmt->base->td)));
   const m_str name = s_name(stmt->base->xid);
   const Type t = new_type(env->gwion->p, t_fptr->xid, name, t_fptr);
   t->owner = !(!env->class_def && GET_FLAG(stmt->base->td, global)) ?
@@ -44,7 +44,7 @@ ANN m_bool scan0_stmt_fptr(const Env env, const Stmt_Fptr stmt) { GWDEBUG_EXE
 }
 
 ANN static m_bool scan0_stmt_type(const Env env, const Stmt_Type stmt) { GWDEBUG_EXE
-  CHECK_BB(env_access(env, stmt->ext->flag))
+  CHECK_BB(env_access(env, stmt->ext->flag, stmt_self(stmt)->pos))
   const Type base = known_type(env, stmt->ext);
   CHECK_OB(base)
   CHECK_BB(scan0_defined(env, stmt->xid, stmt->ext->xid->pos))
@@ -70,7 +70,7 @@ ANN static m_bool scan0_stmt_type(const Env env, const Stmt_Type stmt) { GWDEBUG
 }
 
 ANN m_bool scan0_stmt_enum(const Env env, const Stmt_Enum stmt) { GWDEBUG_EXE
-  CHECK_BB(env_storage(env, stmt->flag))
+  CHECK_BB(env_storage(env, stmt->flag, stmt_self(stmt)->pos))
   if(stmt->xid) {
     const Value v = nspc_lookup_value1(env->curr, stmt->xid);
     if(v)
@@ -108,7 +108,7 @@ ANN static Type union_type(const Env env, const Nspc nspc, const Symbol s, const
 }
 
 ANN static m_bool scan0_stmt_union(const Env env, const Stmt_Union stmt) { GWDEBUG_EXE
-  CHECK_BB(env_storage(env, stmt->flag))
+  CHECK_BB(env_storage(env, stmt->flag, stmt_self(stmt)->pos))
   if(stmt->xid) {
     CHECK_BB(scan0_defined(env, stmt->xid, stmt_self(stmt)->pos))
     const Nspc nspc = !GET_FLAG(stmt, global) ?
@@ -151,13 +151,13 @@ ANN static m_bool scan0_Stmt_List(const Env env, Stmt_List l) { GWDEBUG_EXE
 }
 
 ANN static m_bool scan0_class_def_pre(const Env env, const Class_Def class_def) { GWDEBUG_EXE
-  CHECK_BB(env_storage(env, class_def->flag))
+  CHECK_BB(env_storage(env, class_def->flag, class_def->pos))
   if(GET_FLAG(class_def, global)) {
     vector_add(&env->scope->nspc_stack, (vtype)env->curr);
     env->curr = env->global_nspc;
   }
   CHECK_BB(scan0_defined(env, class_def->base.xid, class_def->pos)) // test for type ?
-  CHECK_BB(isres(class_def->base.xid))
+  CHECK_BB(isres(env, class_def->base.xid, class_def->pos))
   return GW_OK;
 }
 
index 01a11933b511d676ced48f7f3be86aee3875eeca..e5efda19f510b89720c0b9c791a59065484b9065 100644 (file)
@@ -9,7 +9,7 @@
 #include "vm.h"
 #include "parse.h"
 
-#define FAKE_FUNC ((Func)1)
+//#define FAKE_FUNC ((Func)1)
 
 ANN m_bool scan0_class_def(const Env env, const Class_Def class_def);
 ANN /* static */ m_bool scan1_exp(const Env env, Exp exp);
@@ -50,7 +50,7 @@ ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) {
 }
 
 ANN m_bool scan1_exp_decl(const Env env, Exp_Decl* decl) { GWDEBUG_EXE
-  CHECK_BB(env_storage(env, decl->td->flag))
+  CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos))
   Var_Decl_List list = decl->list;
   ((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl);
   CHECK_OB(decl->type)
@@ -63,7 +63,7 @@ ANN m_bool scan1_exp_decl(const Env env, Exp_Decl* decl) { GWDEBUG_EXE
     Type t = decl->type;
     const Var_Decl var = list->self;
     const Value former = nspc_lookup_value0(env->curr, var->xid);
-    CHECK_BB(isres(var->xid))
+    CHECK_BB(isres(env, var->xid, exp_self(decl)->pos))
     if(!decl->td->exp && decl->td->xid->xid != insert_symbol("auto") &&
         former && (!env->class_def || // cuold be better
         (!GET_FLAG(env->class_def, template) || !GET_FLAG(env->class_def, scan1))))
@@ -203,7 +203,7 @@ ANN static m_bool scan1_args(const Env env, Arg_List list) { GWDEBUG_EXE
   do {
     const Var_Decl var = list->var_decl;
     if(var->xid)
-      CHECK_BB(isres(var->xid))
+      CHECK_BB(isres(env, var->xid, var->pos))
     if(list->td)
       CHECK_OB((list->type = void_type(env, list->td, var->pos)))
   } while((list = list->next));
@@ -273,14 +273,16 @@ ANN static m_bool scan1_stmt_list(const Env env, Stmt_List l) { GWDEBUG_EXE
 }
 
 ANN m_bool scan1_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
-  CHECK_BB(env_storage(env, f->flag))
+  if(f->base->td)
+    CHECK_BB(env_storage(env, f->flag, td_pos(f->base->td)))
   if(tmpl_list_base(f->tmpl))
     return GW_OK;
   const Func former = env->func;
-  env->func = FAKE_FUNC;
+  struct Func_ fake = { .name=s_name(f->base->xid) };
+  env->func = &fake;
   ++env->scope->depth;
   if(GET_FLAG(f, dtor) && !env->class_def)
-    ERR_B(f->base->td->xid->pos, "dtor must be in class def!!")
+    ERR_B(td_pos(f->base->td), "dtor must be in class def!!")
   if(f->base->td)
     CHECK_OB((f->base->ret_type = known_type(env, f->base->td)))
   if(f->base->args)
@@ -297,8 +299,7 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
 DECL_SECTION_FUNC(scan1)
 
 ANN static m_bool scan1_class_parent(const Env env, const Class_Def class_def) {
-  const uint pos = class_def->base.ext->xid ? class_def->base.ext->xid->pos :
-    class_def->base.ext->exp->pos;
+  const uint pos = td_pos(class_def->base.ext);
   if(class_def->base.ext->array)
     CHECK_BB(scan1_exp(env, class_def->base.ext->array->exp))
   const Type parent = class_def->base.type->parent = known_type(env, class_def->base.ext);
index e544d2f364ef768eb5256d5ea09a7f32c7182e79..b53811c07d16e4a9ea713ce6033ff361acecbb6b 100644 (file)
@@ -90,7 +90,8 @@ ANN static Value scan2_func_assign(const Env env, const Func_Def d,
 }
 
 ANN m_bool scan2_stmt_fptr(const Env env, const Stmt_Fptr ptr) { GWDEBUG_EXE
-  const Func_Def def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, ptr->base->td, ptr->base->xid, ptr->base->args), NULL, ptr->base->td->flag);
+  const Func_Def def = new_func_def(env->gwion->p, new_func_base(env->gwion->p, ptr->base->td, ptr->base->xid, ptr->base->args),
+    NULL,ptr->base->td->flag, stmt_self(ptr)->pos);
   def->base->ret_type = ptr->base->ret_type;
   ptr->base->func = new_func(env->gwion->p, s_name(ptr->base->xid), def);
   ptr->value->d.func_ref = ptr->base->func;
@@ -156,7 +157,7 @@ ANN static inline m_bool scan2_exp_array(const Env env, const Exp_Array* array)
 }
 
 
-ANN static m_bool multi_decl(const Exp e, const Operator op) {
+ANN static m_bool multi_decl(const Env env, const Exp e, const Operator op) {
   if(e->exp_type == ae_exp_decl) {
     if(e->d.exp_decl.list->next)
       ERR_B(e->pos, "cant '%s' from/to a multi-variable declaration.", op2str(op))
@@ -168,8 +169,8 @@ ANN static m_bool multi_decl(const Exp e, const Operator op) {
 ANN static inline m_bool scan2_exp_binary(const Env env, const Exp_Binary* bin) { GWDEBUG_EXE
   CHECK_BB(scan2_exp(env, bin->lhs))
   CHECK_BB(scan2_exp(env, bin->rhs))
-  CHECK_BB(multi_decl(bin->lhs, bin->op))
-  return multi_decl(bin->rhs, bin->op);
+  CHECK_BB(multi_decl(env, bin->lhs, bin->op))
+  return multi_decl(env, bin->rhs, bin->op);
 }
 
 ANN static inline m_bool scan2_exp_cast(const Env env, const Exp_Cast* cast) { GWDEBUG_EXE
@@ -302,13 +303,13 @@ ANN static m_bool scan2_stmt_list(const Env env, Stmt_List list) { GWDEBUG_EXE
   return GW_OK;
 }
 
-ANN static m_bool scan2_func_def_overload(const Func_Def f, const Value overload) { GWDEBUG_EXE
+ANN static m_bool scan2_func_def_overload(const Env env, const Func_Def f, const Value overload) { GWDEBUG_EXE
   const m_bool base = tmpl_list_base(f->tmpl);
   const m_bool tmpl = GET_FLAG(overload, template);
   if(isa(overload->type, t_function) < 0)
-    ERR_B(f->base->td->xid->pos, "function name '%s' is already used by another value", overload->name)
+    ERR_B(f->pos, "function name '%s' is already used by another value", overload->name)
   if((!tmpl && base) || (tmpl && !base && !GET_FLAG(f, template)))
-    ERR_B(f->base->td->xid->pos, "must overload template function with template")
+    ERR_B(f->pos, "must overload template function with template")
   return GW_OK;
 }
 
@@ -407,7 +408,7 @@ ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f) { GWDEBUG_E
     f->base->args->var_decl->value->type;
   const Type r = GET_FLAG(f, unary) ? f->base->args->var_decl->value->type :
     f->base->args->next ? f->base->args->next->var_decl->value->type : NULL;
-  struct Op_Import opi = { .op=op, .lhs=l, .rhs=r, .ret=f->base->ret_type };
+  struct Op_Import opi = { .op=op, .lhs=l, .rhs=r, .ret=f->base->ret_type, .pos=f->pos };
   CHECK_BB(env_add_op(env, &opi))
   if(env->class_def) {
     if(env->class_def == l)
@@ -489,7 +490,7 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
   const Value overload = nspc_lookup_value0(env->curr, f->base->xid);
   m_str func_name = s_name(f->base->xid);
   if(overload)
-    CHECK_BB(scan2_func_def_overload(f, overload))
+    CHECK_BB(scan2_func_def_overload(env, f, overload))
   if(tmpl_list_base(f->tmpl))
     return scan2_func_def_template(env, f, overload);
   if(!f->tmpl) {
index 9bbc9598111047a448905a24b354146664837d3d..47ee97702034e0b40ac2462796f3544d2c5725c0 100644 (file)
@@ -80,7 +80,7 @@ ANN static inline void* type_unknown(const Env env, const ID_List id) {
   return NULL;
 }
 
-ANN static Type prim_ref(const Type t, const Type_Decl* td) {
+ANN static inline Type prim_ref(const Env env, const Type t, const Type_Decl* td) {
   if(GET_FLAG(td, ref) && isa(t, t_object) < 0 && isa(t, t_class) < 0)
     ERR_O(td->xid->pos, "primitive types cannot be used as reference (@)...\n")
   return t;
@@ -90,5 +90,5 @@ ANN Type known_type(const Env env, const Type_Decl* td) {
   if(!td->xid)
     return t_undefined;
   const Type t = type_decl_resolve(env, td);
-  return t ? prim_ref(t, td) : type_unknown(env, td->xid);
+  return t ? prim_ref(env, t, td) : type_unknown(env, td->xid);
 }
index e9f832e105420e778edf64fca011760897a65adf..10f1fa56e0f3f02b1ea4fc4687b8c64633f2fe00 100644 (file)
@@ -9,10 +9,10 @@
 #include "vm.h"
 #include "parse.h"
 
-ANN m_bool isres(const Symbol xid) {
+ANN m_bool isres(const Env env, const Symbol xid, const uint pos) {
   const m_str s = s_name(xid);
   if(!strcmp(s, "this") || !strcmp(s, "vararg") || !name2op(s))
-    ERR_B(0, "%s is reserved.", s_name(xid));
+    ERR_B(pos, "%s is reserved.", s_name(xid));
   return GW_OK;
 }
 
index ef2f0c9583f325575fa11ce0468b9ed5f7406242..6bd3af2208f014fcb2f5faaeb06831503f8cefcc 100644 (file)
@@ -66,7 +66,7 @@ ANN static void plug_get(MemPool p, PlugInfo* pi, const m_str c) {
       map_set(&pi->drv, (vtype)str(), (vtype)drv);
     }
   } else
-    err_msg(0, "error in %s.", DLERROR());
+    gw_err("error in %s.", DLERROR());
 }
 
 ANN PlugInfo* new_plug(MemPool p, const Vector list) {
index a61ecc82a09a033566d35cd68eef5905d1c2c412..81c1df2e399234b5e574b9647b119bd83b4f5baf 100644 (file)
@@ -1,2 +1,2 @@
-// [contains] in function 'test'
+// [contains] in function:
 function void test() { <<<b>>>; }
diff --git a/util b/util
index 48ce5516794eb7deefa558bbb2229ff3f827ce74..cb9e371b894ede91c4c0830e1ee494dd50483c02 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 48ce5516794eb7deefa558bbb2229ff3f827ce74
+Subproject commit cb9e371b894ede91c4c0830e1ee494dd50483c02