]> Nishi Git Mirror - gwion.git/commitdiff
:art: libprettyerr and contracts
authorJérémie Astor <fennecdjay@gmail.com>
Sun, 14 Mar 2021 15:58:21 +0000 (16:58 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Sun, 14 Mar 2021 15:58:21 +0000 (16:58 +0100)
15 files changed:
Makefile
ast
src/clean.c
src/emit/emit.c
src/gwion.c
src/import/import_tdef.c
src/lib/engine.c
src/lib/object.c
src/lib/ref.c
src/parse/check.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
tests/error/func_code_error.gw
tests/error/stray.gw

index 15ae537eefa8b7cc2a24fc5550ee6ca4710bba60..0a9ee058fa6fdd633c92cd21e47e2c8d7f8fbe8d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,6 +22,7 @@ test_dir += examples
 
 
 CFLAGS += -Iutil/include -Iast/include -Ilibcmdapp/src -D_GNU_SOURCE
+CFLAGS += -Iast/libprettyerr/src
 
 # add commit hash to version for now
 CFLAGS += -DGWION_VERSION=\"$(shell git log -n1 --format="%h")\"
@@ -47,8 +48,8 @@ endif
 
 CFLAGS += -DGWION_BUILTIN
 
-_GWLIBS = util/libgwion_util.a ast/libgwion_ast.a libcmdapp/libcmdapp.a lib${PRG}.a util/libtermcolor/libtermcolor.a
-GWLIBS = lib${PRG}.a libcmdapp/libcmdapp.a ast/libgwion_ast.a util/libgwion_util.a util/libtermcolor/libtermcolor.a
+_GWLIBS = util/libgwion_util.a ast/libgwion_ast.a libcmdapp/libcmdapp.a lib${PRG}.a util/libtermcolor/libtermcolor.a ast/libprettyerr/libprettyerr.a
+GWLIBS = lib${PRG}.a libcmdapp/libcmdapp.a ast/libgwion_ast.a ast/libprettyerr/libprettyerr.a util/libgwion_util.a util/libtermcolor/libtermcolor.a
 _LDFLAGS = ${GWLIBS} ${LDFLAGS}
 
 all: options-show ${_GWLIBS} src/main.o
@@ -76,6 +77,9 @@ ast/libgwion_ast.a:
 libcmdapp/libcmdapp.a:
        @+${MAKE} -s -C libcmdapp static
 
+ast/libprettyerr/libprettyerr.a:
+       @+CFLAGS=-I${PWD}/util/libtermcolor/src ${MAKE} -s -C ast/libprettyerr static
+
 ast: ast/libgwion_ast.a
        @(info build ast)
 
diff --git a/ast b/ast
index a6f47836656ec77d15a9ad1914b05779692bdaba..d5f0d5d1df9b07c116da954771d566af9aa2ad10 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit a6f47836656ec77d15a9ad1914b05779692bdaba
+Subproject commit d5f0d5d1df9b07c116da954771d566af9aa2ad10
index 148e412a3eb18ac7b34fb643a929a6cbf30309d8..72ddac6f82d6193886bd3cf0528be36b1e916dac 100644 (file)
@@ -332,6 +332,11 @@ ANN static void clean_fptr_def(Clean *a, Fptr_Def b) {
 ANN static void clean_type_def(Clean *a, Type_Def b) {
   if(b->ext)
     clean_type_decl(a, b->ext);
+  if(b->when) {
+    clean_exp(a, b->when);
+    if(b->when_def)
+      clean_func_def(a, b->when_def);
+  }
   if(b->tmpl)
     clean_tmpl(a, b->tmpl);
 }
index e618d20b3fd88c03071bee541e03607456e08ac5..52a4cb215b175e812bd789300a7740bb882213ba 100644 (file)
@@ -1504,7 +1504,8 @@ ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) {
       CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to))
     if(isa(e->type, emit->gwion->type[et_object]) > 0 &&
         (e->cast_to ? isa(e->cast_to, emit->gwion->type[et_object]) > 0 : 1) &&
-         e->exp_type == ae_exp_decl && GET_FLAG(e->d.exp_decl.td, late) && exp_getuse(e) && !exp_getvar(e)) {
+         e->exp_type == ae_exp_decl && GET_FLAG(e->d.exp_decl.td, late) && exp_getuse(e) && !exp_getvar(e) && GET_FLAG(e->d.exp_decl.list->self->value, late)) {
+//         e->exp_type == ae_exp_decl && !exp_getvar(e)) {
       const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
       instr->m_val = -SZ_INT;
     }
@@ -1862,6 +1863,8 @@ 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))
   return (!is_fptr(emit->gwion, tdef->type) && tdef->type->info->cdef) ?
     emit_class_def(emit, tdef->type->info->cdef) : GW_OK;
 }
index 48e2f180e0bcc97228af600639621121cf0b0f57..a360c8199f5b0f9d57c8eb0a34ce5c6f2e8fb400 100644 (file)
@@ -140,18 +140,21 @@ ANN void gwion_end(const Gwion gwion) {
 
 ANN static void env_header(const Env env) {
   if(env->class_def)
-    gw_err(_("in class: '%s'\n"), env->class_def->name);
-  if(env->func)
-    gw_err(_("in function: '%s'\n"), env->func->name);
+    gwerr_secondary("in class:", env->name, env->class_def->info->cdef->pos);
+  if(env->func && env->func != (Func)1 && env->func->def)
+    gwerr_secondary("in function:", env->name, env->func->def->pos);
 }
 
 ANN static void env_xxx(const Env env, const loc_t pos, const m_str fmt, va_list arg) {
 #ifndef __FUZZING__
+  va_list tmpa;
+  va_copy(tmpa, arg);
+  const int size = vsnprintf(NULL, 0, fmt, tmpa);
+  va_end(tmpa);
+  char c[size + 1];
+  vsprintf(c, fmt, arg);
+  gwerr_basic(c, NULL, NULL, env->name, pos, 0);
   env_header(env);
-  loc_header(pos, env->name);
-  vfprintf(stderr, fmt, arg);
-  fprintf(stderr, "\n");
-  loc_err(pos, env->name);
 #endif
 }
 
index f0712a1643e1bce8362771b88fd404b4b751287a..9df5ea6d2122eb50633c99d8038e51869a3696fa 100644 (file)
@@ -27,7 +27,7 @@ ANN Type gwi_typedef_end(const Gwi gwi, const ae_flag flag) {
   CHECK_BO(ck_ok(gwi, ck_tdef))
   Type_Decl *td = gwi->ck->td;
   td->flag |= flag;
-  const Type_Def tdef = new_type_def(gwi->gwion->mp, td, gwi->ck->sym);
+  const Type_Def tdef = new_type_def(gwi->gwion->mp, td, gwi->ck->sym, gwi->loc);
   if(gwi->ck->tmpl)
     tdef->tmpl = gwi_tmpl(gwi);
   gwi->ck->td = NULL;
index 14b2a7fe43f857b16eade7f4f81c3928303c5d65..1d26b25b834d8d74df908d3397275bc6b8c6e5ec 100644 (file)
@@ -73,6 +73,11 @@ static OP_CHECK(opck_basic_ctor) {
   ERR_N(exp_self(call)->pos, _("can't call a non-callable value"))
 }
 
+static INSTR(PredicateCheck) {
+  if(!*(m_uint*)REG(-SZ_INT))
+    Except(shred, "predicate failed");
+}
+
 ANN static m_bool import_core_libs(const Gwi gwi) {
   const Type t_class = gwi_mk_type(gwi, "@Class", SZ_INT, NULL);
   set_tflag(t_class, tflag_infer);
@@ -108,6 +113,9 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   struct SpecialId_ spid = { .type=t_now, .exec=RegPushNow, .is_const=1 };
   gwi_specialid(gwi, "now", &spid);
 
+  struct SpecialId_ predicate = { .type=t_void, .exec=PredicateCheck, .is_const=1 };
+  gwi_specialid(gwi, "@predicate", &predicate);
+
   const Type t_compound = gwi_mk_type(gwi, "@Compound", SZ_INT, NULL);
   GWI_BB(gwi_gack(gwi, t_compound, gack_compound))
   GWI_BB(gwi_set_global_type(gwi, t_compound, et_compound))
index afd7dffc19f30b543aea4619c57545b44b792d65..f8e48f264874783dc3b2b8e2ddfc3c324b75a68b 100644 (file)
@@ -20,7 +20,7 @@
 
 #undef insert_symbol
 ANN void exception(const VM_Shred shred, const m_str c) {
-  gw_err("%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]\n",
+  gw_err("{+}%s{0}: shred[{-}id=%" UINT_F "{0}:%s], PC=[{-}%" UINT_F "{0}]\n",
           c, shred->tick->xid, shred->info->name, shred->pc - 1);
   vm_shred_exit(shred);
 }
index c3702df6e2d3132815220422b93462b3247cf846..237266de3d5addd5a3bcc74d239222aaed48953e 100644 (file)
@@ -21,7 +21,8 @@ static m_bool ref_access(const Env env, const Exp e) {
   const m_str access = exp_access(e);
   if(!access)
     return GW_OK;
-  ERR_B(e->pos, _("operand is %s"), access);
+  env_err(env, e->pos, _("operand is %s"), access );
+  return GW_ERROR;
 }
 
 static OP_CHECK(opck_implicit_similar) {
index 977842ec48d39ac5aa0b20ba9ecf41582de9e8a9..c8b6643ab4ac1f97ae89a983ef9a9c421c0d99b9 100644 (file)
@@ -861,6 +861,41 @@ ANN static Type check_exp_dot(const Env env, Exp_Dot* member) {
 }
 
 ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
+  if(tdef->when) {
+    const Var_Decl decl = new_var_decl(env->gwion->mp, insert_symbol("self"), NULL, tdef->when->pos);
+    const Arg_List args = new_arg_list(env->gwion->mp, cpy_type_decl(env->gwion->mp, tdef->ext), decl, NULL);
+    Func_Base *fb = new_func_base(env->gwion->mp, type2td(env->gwion, tdef->type, tdef->when->pos),
+      insert_symbol("@implicit"), args, ae_flag_none);
+    set_fbflag(fb, fbflag_op);
+    const Exp helper = new_prim_id(env->gwion->mp, insert_symbol("@predicate"), tdef->when->pos);
+    tdef->when->next = helper;
+    const Stmt stmt = new_stmt_exp(env->gwion->mp, ae_stmt_exp, cpy_exp(env->gwion->mp, tdef->when), tdef->when->pos);// copy exp
+    const Stmt_List body = new_stmt_list(env->gwion->mp, stmt, NULL);//ret_list);
+    const Stmt code = new_stmt_code(env->gwion->mp, body, tdef->when->pos);
+    const Func_Def fdef = new_func_def(env->gwion->mp, fb, code, tdef->when->pos);
+    CHECK_BB(traverse_func_def(env, fdef))
+    const Exp predicate = stmt->d.stmt_exp.val;
+    if(isa(predicate->type, env->gwion->type[et_bool]) < 0) {
+      char explain[strlen(predicate->type->name) + 7];
+      sprintf(explain, "found `{/+}%s{0}`", predicate->type->name);
+      gwerr_basic("Invalid `{/+}when{0}` predicate expression type", explain, "use `{/+}bool{0}`",
+        env->name, tdef->when->pos, 0);
+      char from[strlen(tdef->type->name) + 39];
+      sprintf(from, "in `{/+}%s{0}` definition", tdef->type->name);
+      gwerr_secondary(from, env->name, tdef->pos);
+      if(env->context)
+        env->context->error++;
+      return GW_ERROR;
+    }
+    // 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"), tdef->when->pos);
+    ret_id->d.prim.value = new_value(env->gwion->mp, tdef->type, "self");
+    const Stmt ret = new_stmt_exp(env->gwion->mp, ae_stmt_return, ret_id, tdef->when->pos);
+    const Stmt_List ret_list = new_stmt_list(env->gwion->mp, ret, NULL);
+    ret_id->type = tdef->type;
+    body->next = ret_list;
+    tdef->when_def = fdef;
+  }
   return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ?
      check_class_def(env, tdef->type->info->cdef) : GW_OK;
 }
@@ -931,7 +966,7 @@ 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)"
-          "...(e.g., 'for(; true;){ /*...*/ }')"))
+          "...(e.g., 'for(; true;){{ /*...*/ }')"))
   return GW_OK;
 }
 
index 134c642548dafa486feae36a2c6facf05de496fd..606b66c6400a634f408be31dd836023deb3c7db3 100644 (file)
@@ -162,7 +162,7 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) {
       CHECK_BB(typedef_complex(env, tdef, base))
   } else
     typedef_fptr(env, tdef, base);
-  if(!tdef->distinct)
+  if(!tdef->distinct && !tdef->when)
     scan0_implicit_similar(env, tdef->type, base);
   set_tflag(tdef->type, tflag_typedef);
   return GW_OK;
index d1e5411d0efba25387ab8211a70716c672e86813..6c209490b28ee7239775a7435fe31511a40b4612 100644 (file)
@@ -403,6 +403,8 @@ ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
 ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
   if(!tdef->type)
     tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
+  if(tdef->when)
+    CHECK_BB(scan1_exp(env, tdef->when))
   return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ?
     scan1_cdef(env, tdef->type) : GW_OK;
 }
@@ -533,7 +535,7 @@ ANN static m_bool scan1_fdef_args(const Env env, Arg_List list) {
   do {
     Nspc nspc = env->curr;
     do if(nspc_lookup_value0(nspc, list->var_decl->xid))
-       ERR_B(list->var_decl->pos, _("argument '%s' shadows a previuosly defined variable"),
+       ERR_B(list->var_decl->pos, _("argument '%s' shadows a previously defined variable"),
             s_name(list->var_decl->xid))
     while((nspc = nspc->parent));
   } while((list = list->next));
index 837e50914c6c5083b8128e4eb041783d832e3abe..ea0a5cc9e5f9cb3bf824f7ab51d44182e06aa4a5 100644 (file)
@@ -89,8 +89,12 @@ ANN m_bool scan2_fptr_def(const Env env NUSED, const Fptr_Def fptr) {
   return GW_OK;
 }
 
+ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f);
 ANN m_bool scan2_type_def(const Env env, const Type_Def tdef) {
-  if(!tdef->type->info->cdef) return GW_OK;
+  if(tdef->when)
+    CHECK_BB(scan2_exp(env, tdef->when))
+  if(!tdef->type->info->cdef)
+    return GW_OK;
   return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ?
     scan2_class_def(env, tdef->type->info->cdef) : GW_OK;
 }
index 229933d43bcedd9f8bbd9c93f9223d6ff23319d6..11262c4b7463d944ec987a032d45618522fba029 100644 (file)
@@ -1,2 +1,6 @@
 #! [contains] in function:
-fun void test() { <<< b >>>; }
+class C {
+  fun void test() {
+    <<< b >>>;
+  }
+}
index ca84fac1ffcd512ff91fb35b5342b0f3e5c197ad..aac695b534dc2a0a1a1e074d2f84dbff7058434b 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains somewhere] stray in program
-**µ
+1**µ