]> Nishi Git Mirror - gwion.git/commitdiff
:art: Add (improved) did_you_mean
authorfennecdjay <astor.jeremie@wanadoo.fr>
Thu, 11 Apr 2019 15:03:37 +0000 (17:03 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Thu, 11 Apr 2019 15:03:37 +0000 (17:03 +0200)
include/nspc.h
src/parse/check.c
src/parse/did_you_mean.c [new file with mode: 0644]
src/parse/type_decl.c
util

index b846659950b076ac69402fc9fe899438ba7382ef..1c318c78c759d657b8558965bdaee2209140382b 100644 (file)
@@ -54,4 +54,6 @@ describe_nspc_func(Value, value)
 describe_nspc_func(Type, type)
 describe_nspc_func(Func, func)
 /* howere there is no need for lookup_func0, push_func, pop_func */
+ANN void did_you_mean_nspc(const Nspc, const char*);
+ANN void did_you_mean_type(const Type, const char*);
 #endif
index f367286c8b7bdd65b5b64fe47ea587a9396fc1d1..27609151663c2d8ae26d80f1004a430ef24c2a50 100644 (file)
@@ -182,7 +182,10 @@ ANN static Type prim_id_non_res(const Env env, const Exp_Primary* primary) {
   if(!v || !GET_FLAG(v, checked)) {
     env_err(env, 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));
+    if(v && v->owner_class)
+      did_you_mean_type(v->owner_class, s_name(primary->d.var));
+    else
+      did_you_mean_nspc(v ? v->owner : env->curr, s_name(primary->d.var));
     return NULL;
   }
   if(env->func && !GET_FLAG(v, const) && v->owner)
@@ -683,9 +686,12 @@ ANN static Type check_exp_dot(const Env env, Exp_Dot* member) { GWDEBUG_EXE
     ERR_O(exp_self(member)->pos,
           "keyword 'this' must be associated with object instance...")
   const Value value = find_value(the_base, member->xid);
-  if(!value)
-    ERR_O(member->base->pos,
-          "class '%s' has no member '%s'", the_base->name, str)
+  if(!value) {
+    env_err(env, member->base->pos,
+          "class '%s' has no member '%s'", the_base->name, str);
+    did_you_mean_type(member->t_base, str);
+    return NULL;
+  }
   if(!env->class_def || isa(env->class_def, value->owner_class) < 0) {
     if(GET_FLAG(value, private))
       ERR_O(exp_self(member)->pos,
diff --git a/src/parse/did_you_mean.c b/src/parse/did_you_mean.c
new file mode 100644 (file)
index 0000000..5be923d
--- /dev/null
@@ -0,0 +1,72 @@
+//#include <stdlib.h>
+#include <string.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "nspc.h"
+#include "value.h"
+#include "env.h"
+#include "type.h"
+
+#ifdef min
+#undef min
+#endif
+
+#define MAX_DISTANCE 2
+#define min2(a, b) ((a) < (b) ? (a) : (b))
+#define min(a, b, c) (min2(min2((a), (b)), (c)))
+
+static m_bool wagner_fisher(const char *s, const char* t) {
+  const size_t m = strlen(s);
+  const size_t n = strlen(t);
+  unsigned int d[m][n];
+  uint i, j;
+  for(i = 0; i < m; ++i)
+    d[i][0] = i;
+  for(i = 0; i < n; ++i)
+    d[0][i] = i;
+  for(j = 1; j < n; ++j) {
+    for(i = 1; i < m; ++i) {
+      if(s[i] == t[j])
+        d[i][j] = d[i-1][j-1];
+      else
+        d[i][j] = min(d[i-1][j] + 1, d[i][j-1] + 1, d[i-1][j-1] + 1);
+      if(d[i][j] > MAX_DISTANCE + 1)
+        return 0;
+    }
+  }
+  return (i && j && d[m-1][n-1] < MAX_DISTANCE);
+}
+
+ANN static void ressembles(const Vector v, const Nspc nspc, const char* name) {
+  struct scope_iter iter = { &nspc->info->value, 0, 0 };
+  Value value;
+  while(scope_iter(&iter, &value) > 0) {
+    if(!strcmp(name, value->name))
+      continue;
+    if(wagner_fisher(name, value->name))
+      vector_add(v, (vtype)value->name);
+  }
+}
+
+ANN void did_you_mean_nspc(Nspc nspc, const char* name) {
+  struct Vector_ v;
+  vector_init(&v);
+  do  ressembles(&v, nspc, name);
+  while((nspc = nspc->parent));
+  for(m_uint i = 0; i < vector_size(&v); ++i)
+    gw_err("\t(did you mean '%s'?)\n", (m_str)vector_at(&v, i));
+  vector_release(&v);
+}
+
+ANN void did_you_mean_type(Type type, const char* name) {
+  Type t = type;
+  struct Vector_ v;
+  vector_init(&v);
+  do ressembles(&v, t->nspc, name);
+  while((t = t->parent));
+  for(m_uint i = 0; i < vector_size(&v); ++i)
+    gw_err("\t(did you mean '%s'?)\n", (m_str)vector_at(&v, i));
+  did_you_mean_nspc(type->nspc, name);
+  vector_release(&v);
+}
index 47ee97702034e0b40ac2462796f3544d2c5725c0..b93a72a6d63dd890f8ac80fe57c42d80ef636c97 100644 (file)
@@ -4,6 +4,7 @@
 #include "gwion_ast.h"
 #include "oo.h"
 #include "env.h"
+#include "nspc.h"
 #include "type.h"
 #include "vm.h"
 #include "parse.h"
@@ -76,7 +77,7 @@ ANN static inline void* type_unknown(const Env env, const ID_List id) {
   char path[id_list_len(id)];
   type_path(path, id);
   err_msg(id->pos, "unknown type '%s'", path);
-  did_you_mean(env->gwion->st, s_name(id->xid));
+  did_you_mean_nspc(env->curr, s_name(id->xid));
   return NULL;
 }
 
diff --git a/util b/util
index adc983bec96f51536b394816048fa7bfe3ccd7c7..ed43d9d14df891ffd3b9ae09ac63ad2c9de4d24e 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit adc983bec96f51536b394816048fa7bfe3ccd7c7
+Subproject commit ed43d9d14df891ffd3b9ae09ac63ad2c9de4d24e