compiler: give suggestions in diagnostics for unbound variable.

This uses the Jaro-Winkler edit distance, which seemed like the best
fit for identifiers, even though it is intended for people's names.
This commit is contained in:
whitequark 2015-11-15 23:09:40 +03:00
parent 9670939ca6
commit c8cfa7c7bd
2 changed files with 27 additions and 5 deletions

View File

@ -11,6 +11,8 @@ from collections import OrderedDict, defaultdict
from pythonparser import ast, algorithm, source, diagnostic, parse_buffer
from pythonparser import lexer as source_lexer, parser as source_parser
from Levenshtein import jaro_winkler
from ..language import core as language_core
from . import types, builtins, asttyped, prelude
from .transforms import ASTTypedRewriter, Inferencer, IntMonomorphizer
@ -225,10 +227,29 @@ class StitchingASTTypedRewriter(ASTTypedRewriter):
if node.id in self.host_environment:
return self.quote(self.host_environment[node.id], node.loc)
else:
suggestion = self._most_similar_ident(node.id)
if suggestion is not None:
diag = diagnostic.Diagnostic("fatal",
"name '{name}' is not bound to anything", {"name":node.id},
"name '{name}' is not bound to anything; did you mean '{suggestion}'?",
{"name": node.id, "suggestion": suggestion},
node.loc)
self.engine.process(diag)
else:
diag = diagnostic.Diagnostic("fatal",
"name '{name}' is not bound to anything", {"name": node.id},
node.loc)
self.engine.process(diag)
def _most_similar_ident(self, id):
names = set()
names.update(self.host_environment.keys())
for typing_env in reversed(self.env_stack):
names.update(typing_env.keys())
sorted_names = sorted(names, key=lambda other: jaro_winkler(id, other), reverse=True)
if len(sorted_names) > 0:
if jaro_winkler(id, sorted_names[0]) > 0.0:
return sorted_names[0]
class StitchingInferencer(Inferencer):
def __init__(self, engine, value_map, quote):

View File

@ -27,7 +27,8 @@ requirements = [
"sphinx", "sphinx-argparse", "pyserial", "numpy", "scipy",
"python-dateutil", "prettytable", "h5py", "pydaqmx", "pyelftools",
"quamash", "pyqtgraph", "pygit2", "aiohttp",
"llvmlite_artiq", "pythonparser", "lit", "OutputCheck",
"llvmlite_artiq", "pythonparser", "python-Levenshtein",
"lit", "OutputCheck",
]
scripts = [