A categorical programming language
修订版 | debfeb9fc404cbe7a3355ab74f243bbc07286966 (tree) |
---|---|
时间 | 2022-03-16 15:19:40 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Add refactoring tool for renaming expressions.
@@ -15,14 +15,14 @@ class Hive(object): | ||
15 | 15 | |
16 | 16 | def __init__(self, hivepath): |
17 | 17 | self.hivepath = hivepath |
18 | + # Values are tuples: original sexp, expanded sexp, trail | |
18 | 19 | self.exprs = {} |
19 | 20 | self.dag = {} |
20 | 21 | |
21 | 22 | def load(self, atom): |
22 | 23 | if atom in self.exprs: |
23 | - return self.exprs[atom] | |
24 | + return self.exprs[atom][1] | |
24 | 25 | |
25 | - # print("Loading", atom) | |
26 | 26 | filename = atom + ".cammy" |
27 | 27 | fullpath = os.path.join(self.hivepath, filename) |
28 | 28 | try: |
@@ -31,9 +31,8 @@ class Hive(object): | ||
31 | 31 | symbols = {} |
32 | 32 | sexp.symbols(symbols) |
33 | 33 | self.dag[atom] = symbols |
34 | - sexp = sexp.canonicalize(self) | |
35 | - self.exprs[atom] = sexp | |
36 | - # print("Loaded", atom, sexp) | |
37 | - return sexp | |
34 | + expanded = sexp.canonicalize(self) | |
35 | + self.exprs[atom] = sexp, expanded, trail | |
36 | + return expanded | |
38 | 37 | except IOError: |
39 | 38 | raise MissingAtom(atom) |
@@ -33,6 +33,9 @@ class Atom(SExp): | ||
33 | 33 | def substitute(self, args): |
34 | 34 | return self |
35 | 35 | |
36 | + def replaceAtom(self, s, t): | |
37 | + return Atom(t) if self.symbol == s else self | |
38 | + | |
36 | 39 | def canonicalize(self, hive): |
37 | 40 | if self.symbol in BASIS_ATOMS: |
38 | 41 | return self |
@@ -77,6 +80,10 @@ class Functor(SExp): | ||
77 | 80 | return Functor(self.constructor, |
78 | 81 | [arg.substitute(args) for arg in self.arguments]) |
79 | 82 | |
83 | + def replaceAtom(self, s, t): | |
84 | + return Functor(self.constructor, | |
85 | + [arg.replaceAtom(s, t) for arg in self.arguments]) | |
86 | + | |
80 | 87 | def canonicalize(self, hive): |
81 | 88 | args = [arg.canonicalize(hive) for arg in self.arguments] |
82 | 89 | if self.constructor in BASIS_FUNCTORS: |
@@ -134,6 +141,9 @@ class Hole(SExp): | ||
134 | 141 | def substitute(self, args): |
135 | 142 | return args[self.index] |
136 | 143 | |
144 | + def replaceAtom(self, s, t): | |
145 | + return self | |
146 | + | |
137 | 147 | def canonicalize(self, hive): |
138 | 148 | return self |
139 | 149 |
@@ -0,0 +1,5 @@ | ||
1 | +let | |
2 | + makeBuilder = import ./builder.nix; | |
3 | +in | |
4 | + makeBuilder ./rename.py "cammy-rename" false | |
5 | + |
@@ -0,0 +1,59 @@ | ||
1 | +import os | |
2 | +import sys | |
3 | + | |
4 | +from cammylib.hive import Hive | |
5 | +from cammylib.sexp import BASIS_ATOMS, BASIS_FUNCTORS | |
6 | + | |
7 | +def comb(dag): | |
8 | + rv = {} | |
9 | + for k, v in dag.iteritems(): | |
10 | + rv[k] = [x for x in v | |
11 | + if x not in BASIS_ATOMS and x not in BASIS_FUNCTORS] | |
12 | + return rv | |
13 | + | |
14 | +def atomPath(hivepath, atom): | |
15 | + return os.path.join(hivepath, atom + ".cammy") | |
16 | + | |
17 | +def main(argv): | |
18 | + hivepath = argv[-3] | |
19 | + satom = argv[-2] | |
20 | + tatom = argv[-1] | |
21 | + hive = Hive(hivepath) | |
22 | + prefix = len(hivepath) | |
23 | + for dirpath, dirnames, filenames in os.walk(hivepath): | |
24 | + for filename in filenames: | |
25 | + if not filename.endswith(".cammy"): | |
26 | + continue | |
27 | + fullpath = os.path.join(dirpath, filename) | |
28 | + suffix = len(fullpath) - 6 | |
29 | + assert suffix >= 0, "proven by .endswith() check above" | |
30 | + atom = fullpath[prefix:suffix] | |
31 | + hive.load(atom) | |
32 | + graph = comb(hive.dag) | |
33 | + write = True | |
34 | + if tatom in graph: | |
35 | + print "There is already an expression %s in the hive; doing nothing." % tatom | |
36 | + return 1 | |
37 | + callers = [k for k in graph if satom in graph[k]] | |
38 | + for caller in callers: | |
39 | + print "Changing expression %s" % caller | |
40 | + sexp, _, trail = hive.exprs[caller] | |
41 | + sexp = sexp.replaceAtom(satom, tatom) | |
42 | + text = sexp.asStr() + "\n\n" + trail.strip() + "\n" | |
43 | + if write: | |
44 | + path = atomPath(hivepath, caller) | |
45 | + with open(path, "w") as handle: | |
46 | + handle.write(text) | |
47 | + else: | |
48 | + print "Would have written:", text | |
49 | + if write: | |
50 | + print "Renaming %s to %s" % (satom, tatom) | |
51 | + os.rename(atomPath(hivepath, satom), atomPath(hivepath, tatom)) | |
52 | + return 0 | |
53 | + | |
54 | +def target(driver, *args): | |
55 | + driver.exe_name = "cammy-rename" | |
56 | + return main, None | |
57 | + | |
58 | +if __name__ == "__main__": | |
59 | + main(sys.argv) |
@@ -7,6 +7,7 @@ let | ||
7 | 7 | cammy-draw = import ./cammy-rpy/draw.nix { inherit nixpkgs jelly; }; |
8 | 8 | cammy-frame = import ./cammy-rpy/frame.nix { inherit nixpkgs jelly; }; |
9 | 9 | cammy-repl = import ./cammy-rpy/repl.nix { inherit nixpkgs jelly; }; |
10 | + cammy-rename = import ./cammy-rpy/rename.nix { inherit nixpkgs jelly; }; | |
10 | 11 | cammy-weave = import ./cammy-rpy/weave.nix { inherit nixpkgs jelly; }; |
11 | 12 | in pkgs.stdenv.mkDerivation { |
12 | 13 | name = "cammy"; |
@@ -30,6 +31,7 @@ in pkgs.stdenv.mkDerivation { | ||
30 | 31 | makeWrapper ${cammy-draw}/bin/cammy-draw $out/bin/cammy-draw |
31 | 32 | makeWrapper ${cammy-frame}/bin/cammy-frame $out/bin/cammy-frame |
32 | 33 | makeWrapper ${cammy-repl}/bin/cammy-repl $out/bin/cammy-repl |
34 | + makeWrapper ${cammy-rename}/bin/cammy-rename $out/bin/cammy-rename | |
33 | 35 | makeWrapper ${cammy-weave}/bin/cammy-weave $out/bin/cammy-weave |
34 | 36 | ''; |
35 | 37 | } |
@@ -1,12 +1,4 @@ | ||
1 | -(comp | |
2 | - (pair | |
3 | - (f/addpair | |
4 | - (f/divpair | |
5 | - (comp fun/swap f-atan2) | |
6 | - (fun/const (f/mulpair f-pi f/2))) | |
7 | - (fun/const (comp f/2 f-recip))) | |
8 | - (f/mulpair v2/norm (fun/const f/2))) | |
9 | - hv2rgb) | |
1 | +(comp (pair (f/addpair (f/divpair (comp pair/swap f-atan2) (fun/const (f/mulpair f-pi f/2))) (fun/const (comp f/2 f-recip))) (f/mulpair v2/norm (fun/const f/2))) hv2rgb) | |
10 | 2 | |
11 | 3 | Map a complex number to a color. The magnitude is mapped to luminance and the |
12 | 4 | angle is mapped to hue. |
@@ -1,6 +1,3 @@ | ||
1 | -(comp | |
2 | - (comp fun/swap fun/distribl) | |
3 | - (case (comp fun/swap left) (comp fun/swap right))) | |
1 | +(comp (comp pair/swap fun/distribl) (case (comp pair/swap left) (comp pair/swap right))) | |
4 | 2 | |
5 | 3 | Distribute to the right. |
6 | - |
@@ -1,3 +1,3 @@ | ||
1 | -(curry (comp fun/swap (uncurry @0))) | |
1 | +(curry (comp pair/swap (uncurry @0))) | |
2 | 2 | |
3 | 3 | Swap the order in which arguments are applied onto a curried arrow. |
@@ -1 +0,0 @@ | ||
1 | -(pair snd fst) |
@@ -0,0 +1,7 @@ | ||
1 | +(pair snd fst) | |
2 | + | |
3 | +Swap the first and second components of a pair. | |
4 | + | |
5 | +Swapping twice in a row is equivalent to the identity arrow. | |
6 | + | |
7 | +This expression is the smallest with its type signature. |
@@ -1,3 +1,3 @@ | ||
1 | -(curry (comp fun/swap bool/pick)) | |
1 | +(curry (comp pair/swap bool/pick)) | |
2 | 2 | |
3 | 3 | Convert a pair to a square. |