A categorical programming language
修订版 | cd87073975ed14b10dc277904b2d8dc732f7fb2e (tree) |
---|---|
时间 | 2023-01-13 17:49:17 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Get new REPL to extract complete terms.
We're gonna hack a bit on new REPL, I guess.
@@ -1,49 +1,88 @@ | ||
1 | 1 | #!/usr/bin/env nix-shell |
2 | -#! nix-shell -i python -p python3Packages.requests python3Packages.click-repl | |
2 | +#! nix-shell -i python -p python3Packages.requests | |
3 | 3 | |
4 | +import readline | |
5 | +import sys | |
4 | 6 | from textwrap import dedent |
5 | 7 | |
6 | -import click | |
7 | -import click_repl | |
8 | - | |
9 | 8 | import requests |
10 | 9 | |
11 | -@click.group() | |
12 | -def cli(): | |
13 | - pass | |
14 | - | |
15 | 10 | def getJSON(url): |
16 | 11 | try: |
17 | 12 | return requests.get(url).json() |
18 | 13 | except requests.exceptions.JSONDecodeError: |
19 | - click.echo("Server response was not JSON") | |
14 | + print("Server response was not JSON") | |
15 | + raise | |
16 | + | |
17 | +def fetchDippers(base): return getJSON(base + "/dippers") | |
18 | + | |
19 | +class Extractor: | |
20 | + def __init__(self, base): | |
21 | + # XXX should this cache be sparse? | |
22 | + self.cache = {} | |
23 | + self.base = base | |
24 | + | |
25 | + def extractExpr(self, expr): | |
26 | + if expr not in self.cache: | |
27 | + self.cache[expr] = getJSON(base + "/extract/" + str(expr)) | |
28 | + return self.cache[expr] | |
20 | 29 | |
21 | -@cli.command() | |
22 | -def size(): | |
23 | - dippers = getJSON("http://localhost:5000/dippers") | |
24 | - if dippers: | |
25 | - click.echo("got dippers") | |
26 | - click.echo(len(dippers)) | |
30 | + def fullyExtract(self, expr): | |
31 | + if isinstance(expr, int): return self.fullyExtract(self.extractExpr(expr)) | |
32 | + elif isinstance(expr, list): | |
33 | + return [expr[0]] + [self.fullyExtract(ex) for ex in expr[1:]] | |
34 | + else: return expr | |
27 | 35 | |
28 | 36 | def sexpify(expr): |
29 | 37 | if isinstance(expr, list): |
30 | 38 | return "(" + " ".join(sexpify(x) for x in expr) + ")" |
31 | 39 | else: return expr |
32 | 40 | |
33 | -@cli.command() | |
34 | -@click.argument("name") | |
35 | -def show(name): | |
36 | - obj = getJSON("http://localhost:5000/dip/" + name) | |
37 | - if obj: | |
38 | - trail = obj["trail"].strip() | |
39 | - expr = sexpify(obj["expr"]) | |
40 | - click.echo(dedent(""" | |
41 | - Name: {name} | |
42 | - Trail: {trail} | |
43 | - Dipped form: {expr} | |
44 | - """).strip().format(name=name, trail=trail, expr=expr)) | |
45 | - | |
46 | -click_repl.register_repl(cli) | |
41 | +def fetchDipper(base, name): | |
42 | + return getJSON(base + "/dip/" + name) | |
43 | + | |
44 | +class DipperCompleter: | |
45 | + def __init__(self, dippers): | |
46 | + self.cache = {} | |
47 | + self.dippers = dippers | |
48 | + | |
49 | + def complete(self, text, state): | |
50 | + if text not in self.cache: | |
51 | + self.cache[text] = [d for d in self.dippers if d.startswith(text)] | |
52 | + if state < len(self.cache[text]): return self.cache[text][state] | |
53 | + | |
54 | +def repl(base): | |
55 | + print("Starting REPL with honey base", base) | |
56 | + extractor = Extractor(base) | |
57 | + done = False | |
58 | + while not done: | |
59 | + try: | |
60 | + line = input("> ") | |
61 | + except EOFError: | |
62 | + print("\nSee you later~") | |
63 | + done = True | |
64 | + else: | |
65 | + if line.startswith(":"): | |
66 | + print("I think it's a command") | |
67 | + else: | |
68 | + print("I think it's a sugared Cammy expression") | |
69 | + if line.startswith("("): | |
70 | + print("I think it's an application") | |
71 | + else: | |
72 | + print("I'm gonna guess that it's a dip!") | |
73 | + obj = fetchDipper(base, line) | |
74 | + trail = obj.get("trail", "").strip() | |
75 | + if trail: print("Trail:", trail) | |
76 | + term = extractor.fullyExtract(obj["expr"]) | |
77 | + print("Term:", sexpify(term)) | |
78 | + | |
79 | +def installCompletion(dippers): | |
80 | + readline.parse_and_bind("tab: complete") | |
81 | + readline.set_completer(DipperCompleter(dippers).complete) | |
82 | + readline.set_completer_delims("() ") | |
47 | 83 | |
48 | 84 | if __name__ == "__main__": |
49 | - cli() | |
85 | + base = sys.argv[-1] | |
86 | + dippers = fetchDippers(base) | |
87 | + installCompletion(dippers) | |
88 | + repl(base) |