Skip to content

Commit 69f0600

Browse files
committed
better error messages and decimal constants
1 parent c249d3b commit 69f0600

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

src/kdrag/parsers/microlean.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
For example \\alpha will tab autocomplete to α.
99
"""
1010

11+
import difflib
1112
import lark
1213
import kdrag.smt as smt
1314
from lark import Tree
@@ -62,7 +63,7 @@
6263
theorem : "theorem" NAME ":" expr ":=" "grind"
6364
6465
NAME: /[a-zA-Z_][a-zA-Z0-9_']*/
65-
NUMBER: /-?\d+/
66+
NUMBER: /-?\d+(\.\d+)?/
6667
%import common.WS
6768
%ignore WS
6869
COMMENT: "--" /[^\n]*/
@@ -82,7 +83,25 @@ def __getitem__(self, key):
8283
elif key in self.globals:
8384
return self.globals[key]
8485
else:
85-
raise KeyError(key)
86+
# Suggest a close name in error
87+
names = list(self.locals) + list(self.globals)
88+
dotted = []
89+
for name, value in self.globals.items():
90+
if name.startswith("_"):
91+
continue
92+
try:
93+
attrs = dir(value)
94+
except Exception:
95+
continue
96+
for attr in attrs:
97+
if attr.startswith("_"):
98+
continue
99+
dotted.append(f"{name}.{attr}")
100+
hints = difflib.get_close_matches(str(key), names + dotted, n=3, cutoff=0.6)
101+
msg = f"Unknown name {key!s}"
102+
if hints:
103+
msg += f". Did you mean: {', '.join(hints)}?"
104+
raise NameError(msg)
86105

87106
def __setitem__(self, key, value):
88107
self.locals[key] = value
@@ -166,7 +185,10 @@ def expr(tree, env: Env) -> smt.ExprRef:
166185
match tree:
167186
# TODO: obviously this is not well typed.
168187
case Tree("num", [n]):
169-
return int(n) # type: ignore
188+
text = str(n)
189+
if "." in text:
190+
return smt.RealVal(text)
191+
return int(text)
170192
case Tree("const", [name, *attrs]):
171193
res = env[name] # type: ignore
172194
for attr in attrs:

tests/test_parsers.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import kdrag.solvers.prolog as prolog
33
import kdrag.parsers.tptp as tptp
44
import kdrag.parsers.smtlib as smtlib
5+
import kdrag.parsers.microlean as microlean
6+
import kdrag.theories.real.seq as seq
57
import lark
68
import kdrag.smt as smt
79

@@ -33,3 +35,18 @@ def test_smtlib():
3335
(get-model)
3436
"""
3537
t = smtlib.parser.parse(ex1)
38+
39+
40+
def test_microlean_did_you_mean():
41+
ex1 = "has_lim (fun (n : Int) => n) 0"
42+
try:
43+
microlean.parse(ex1, {"seq": seq})
44+
except NameError as exc:
45+
assert "seq.has_lim" in str(exc)
46+
else:
47+
raise AssertionError("Expected NameError with suggestion")
48+
49+
50+
def test_microlean_decimal_is_real():
51+
t = microlean.parse("1.0", {})
52+
assert t.eq(smt.RealVal("1.0"))

0 commit comments

Comments
 (0)