feat(frontend): accept digits after identifier prefixes
4 files changed, +16 −2
- src/Examples.thy modified +7 −0
- src/Frontend.thy modified +4 −2
- tests/cli.py modified +4 −0
- tests/native.py modified +1 −0
src/Examples.thy modified
| @@ -77,6 +77,13 @@ lemma lexical_shadow: | ||
| 77 | 77 | "reference ''(let x 7 (let x (+ x 2) (* x x)))'' ''1'' ''2'' ''3'' = (True,''81'' @ newline)" |
| 78 | 78 | by eval |
| 79 | 79 | |
| 80 | +lemma numeric_identifier: | |
| 81 | + "reference ''(let x1 7 (let x1 (+ x1 2) (* x1 x1)))'' ''0'' ''0'' ''0'' = (True,''81'' @ newline)" | |
| 82 | + by eval | |
| 83 | + | |
| 84 | +lemma numeric_prefix_rejected: "prepare ''(let 1x 3 1x)'' = None" | |
| 85 | + by eval | |
| 86 | + | |
| 80 | 87 | lemma nested_temporaries: |
| 81 | 88 | "reference ''(+ 10 (let a 3 (+ a (let b 4 (* a b)))))'' ''0'' ''0'' ''0'' = (True,''25'' @ newline)" |
| 82 | 89 | by eval |
src/Frontend.thy modified
| @@ -33,8 +33,10 @@ theorem number_bound: "number s = Some n \<Longrightarrow> n < 2 ^ 64" | ||
| 33 | 33 | by (auto simp: number_def parse_digits_def Let_def split: list.splits if_splits) |
| 34 | 34 | |
| 35 | 35 | definition valid_name :: "string \<Rightarrow> bool" where |
| 36 | - "valid_name s = (s \<noteq> [] \<and> list_all (\<lambda>c. (97 \<le> nat_of_char c \<and> nat_of_char c \<le> 122)) s | |
| 37 | - \<and> s \<noteq> ''let'' \<and> s \<noteq> ''if'')" | |
| 36 | + "valid_name s = (case s of [] \<Rightarrow> False | c # cs \<Rightarrow> | |
| 37 | + 97 \<le> nat_of_char c \<and> nat_of_char c \<le> 122 \<and> | |
| 38 | + list_all (\<lambda>d. (97 \<le> nat_of_char d \<and> nat_of_char d \<le> 122) \<or> | |
| 39 | + (48 \<le> nat_of_char d \<and> nat_of_char d < 58)) cs \<and> s \<noteq> ''let'' \<and> s \<noteq> ''if'')" | |
| 38 | 40 | |
| 39 | 41 | fun lookup :: "string \<Rightarrow> string list \<Rightarrow> nat option" where |
| 40 | 42 | "lookup name [] = None" |
tests/cli.py modified
| @@ -22,6 +22,10 @@ def main(): | ||
| 22 | 22 | assert int(invoke('eval',source,'0','0','0')) == expected, text |
| 23 | 23 | source.write_text('(+ x y)') |
| 24 | 24 | assert int(invoke('eval',source,'0xFF','0x1','0x0')) == 256 |
| 25 | + source.write_text('(let x1 7 (let x1 (+ x1 2) (* x1 x1)))') | |
| 26 | + assert int(invoke('eval',source,'0','0','0')) == 81 | |
| 27 | + source.write_text('(let 1x 3 1x)') | |
| 28 | + invoke(source,binary,ok=False) | |
| 25 | 29 | for text in ['0x','0x10000000000000000','0xfg','0xffextra','-0x1']: |
| 26 | 30 | source.write_text(text) |
| 27 | 31 | binary.write_bytes(b'preserve') |
tests/native.py modified
| @@ -69,6 +69,7 @@ def main(): | ||
| 69 | 69 | cases += [("*", "x", 1), ("*", 1, "x"), ("and", "x", MASK)] |
| 70 | 70 | cases += [("*", "x", 0), ("and", "x", 0), ("shl", 0, "y"), ("shr", 0, "y"), ("or", "x", MASK)] |
| 71 | 71 | cases += [("if", "x", ("+", "y", "t"), ("+", "y", "t"))] |
| 72 | + cases += [("let", "x1", ("+", "x", 1), ("*", "x1", "x1"))] | |
| 72 | 73 | cases += [("let", "a", ("+", "x", 3), ("+", "y", ("let", "b", "t", ("*", "a", "b")))), |
| 73 | 74 | ("let", "x", "y", ("if", "t", ("+", "x", 1), ("-", "x", 1)))] |
| 74 | 75 | cases += [generate(rng, 5, ["x", "y", "t"]) for _ in range(117)] |