A categorical programming language
修订版 | 0bc7131ef99cb227b2b358ba4379526e8d2fa711 (tree) |
---|---|
时间 | 2022-03-02 11:00:55 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Add :! command to REPL for evaluating elements.
I should probably add typechecking, because it also will try to evaluate
non-elements.
@@ -36,3 +36,14 @@ The environment for developing the Cammy toolchain is contained within | ||
36 | 36 | To update eggs for the shell environment: |
37 | 37 | |
38 | 38 | $ egg2nix eggs.scm > eggs.nix |
39 | + | |
40 | +# Hive Documentation | |
41 | + | |
42 | +The toolchain can generate documentation for hives. To generate PDF | |
43 | +documentation: | |
44 | + | |
45 | + $ cammy-weave hive/ | pandoc -o doc.pdf | |
46 | + | |
47 | +And to generate HTML documentation: | |
48 | + | |
49 | + $ cammy-weave hive/ | pandoc --mathml -o doc.html |
@@ -34,22 +34,19 @@ class Element(object): | ||
34 | 34 | |
35 | 35 | class T(Element): |
36 | 36 | _immutable_ = True |
37 | + def asStr(self): return "*" | |
37 | 38 | |
38 | 39 | class B(Element): |
39 | 40 | _immutable_ = True |
40 | - def __init__(self, b): | |
41 | - self._b = b | |
42 | - | |
43 | - def b(self): | |
44 | - return self._b | |
41 | + def __init__(self, b): self._b = b | |
42 | + def b(self): return self._b | |
43 | + def asStr(self): return "true" if self._b else "false" | |
45 | 44 | |
46 | 45 | class N(Element): |
47 | 46 | _immutable_ = True |
48 | - def __init__(self, bi): | |
49 | - self._bi = bi | |
50 | - | |
51 | - def n(self): | |
52 | - return self._bi | |
47 | + def __init__(self, bi): self._bi = bi | |
48 | + def n(self): return self._bi | |
49 | + def asStr(self): return self._bi.str() | |
53 | 50 | |
54 | 51 | class F(Element): |
55 | 52 | _immutable_ = True |
@@ -62,6 +59,8 @@ class F(Element): | ||
62 | 59 | def f(self): |
63 | 60 | return self._f |
64 | 61 | |
62 | + def asStr(self): return str(self._f) | |
63 | + | |
65 | 64 | class P(Element): |
66 | 65 | _immutable_ = True |
67 | 66 |
@@ -75,6 +74,8 @@ class P(Element): | ||
75 | 74 | def second(self): |
76 | 75 | return self._y |
77 | 76 | |
77 | + def asStr(self): return "(%s, %s)" % (self._x.asStr(), self._y.asStr()) | |
78 | + | |
78 | 79 | class L(Element): |
79 | 80 | _immutable_ = True |
80 | 81 |
@@ -84,6 +85,9 @@ class L(Element): | ||
84 | 85 | def tagged(self, f, g): |
85 | 86 | return f.run(self._x) |
86 | 87 | |
88 | + def asStr(self): | |
89 | + return "L(%s)" % self._x.asStr() | |
90 | + | |
87 | 91 | class R(Element): |
88 | 92 | _immutable_ = True |
89 | 93 |
@@ -93,6 +97,9 @@ class R(Element): | ||
93 | 97 | def tagged(self, f, g): |
94 | 98 | return g.run(self._x) |
95 | 99 | |
100 | + def asStr(self): | |
101 | + return "R(%s)" % self._x.asStr() | |
102 | + | |
96 | 103 | class H(Element): |
97 | 104 | _immutable_ = True |
98 | 105 | def __init__(self, f, x): |
@@ -100,6 +107,8 @@ class H(Element): | ||
100 | 107 | self._x = x |
101 | 108 | def apply(self, y): |
102 | 109 | return self._f.run(P(self._x, y)) |
110 | + def asStr(self): | |
111 | + return "%s @ %s" % (self._f, self._x.asStr()) | |
103 | 112 | |
104 | 113 | class Xs(Element): |
105 | 114 | _immutable_ = True |
@@ -107,6 +116,8 @@ class Xs(Element): | ||
107 | 116 | def __init__(self, xs): |
108 | 117 | self.xs = xs |
109 | 118 | def l(self): return self.xs |
119 | + def asStr(self): | |
120 | + return "[%s]" % ", ".join([x.asStr() for x in self.xs]) | |
110 | 121 | |
111 | 122 | class Arrow(object): |
112 | 123 | _immutable_ = True |
@@ -1,11 +1,10 @@ | ||
1 | 1 | # Inspired by https://www.pypy.org/posts/2018/11/guest-post-implementing-calculator-repl-6271483514675006846.html |
2 | 2 | |
3 | -import os | |
4 | 3 | import sys |
5 | 4 | |
6 | 5 | from rpython.rlib.rfile import create_stdio |
7 | 6 | |
8 | -from cammylib.arrows import BuildProblem | |
7 | +from cammylib.arrows import BuildProblem, T | |
9 | 8 | from cammylib.hive import Hive, MissingAtom |
10 | 9 | from cammylib.jelly import jellify |
11 | 10 | from cammylib.parser import parse |
@@ -13,10 +12,15 @@ from cammylib.types import ConstraintStore, TypeExtractor, UnificationFailed | ||
13 | 12 | |
14 | 13 | LINE_BUFFER_LENGTH = 1024 |
15 | 14 | |
16 | -def command(code, line): | |
17 | - if code == "e": | |
18 | - # Edit a file | |
19 | - os.system("$EDITOR") | |
15 | +def command(hive, code, line): | |
16 | + # XXX code e: Edit a file | |
17 | + # os.system("$EDITOR") | |
18 | + if code == "!": | |
19 | + sexp, trail = parse(line) | |
20 | + sexp = sexp.canonicalize(hive) | |
21 | + sexp = jellify(sexp) | |
22 | + arrow = sexp.buildArrow() | |
23 | + print arrow.run(T()).asStr() | |
20 | 24 | |
21 | 25 | def repl(hive, stdin, stdout): |
22 | 26 | while True: |
@@ -28,7 +32,8 @@ def repl(hive, stdin, stdout): | ||
28 | 32 | if line.startswith(":"): |
29 | 33 | if len(line) < 2: |
30 | 34 | print "Not a full command" |
31 | - command(line[1], line[3:]) | |
35 | + command(hive, line[1], line[3:]) | |
36 | + continue | |
32 | 37 | sexp, trail = parse(line) |
33 | 38 | print "Got:", line |
34 | 39 | print "S-expression:", sexp.asStr() |
@@ -1,12 +0,0 @@ | ||
1 | -#!@bash@/bin/bash | |
2 | - | |
3 | -# set -x | |
4 | -set -eu -o pipefail | |
5 | - | |
6 | -frame="@frame@/bin/frame" | |
7 | -jelly="@jelly@/bin/jelly" | |
8 | - | |
9 | -hive="$1" | |
10 | - | |
11 | -# Do it all. | |
12 | -exec $frame $hive | $jelly |
@@ -1,32 +0,0 @@ | ||
1 | -#!@python3@/bin/python3 | |
2 | - | |
3 | -import sys | |
4 | - | |
5 | -def offset_list(s): | |
6 | - count = 0 | |
7 | - for i, c in enumerate(s): | |
8 | - if c == '(': | |
9 | - count += 1 | |
10 | - elif c == ')': | |
11 | - count -= 1 | |
12 | - if not count: | |
13 | - return i + 1 | |
14 | - raise Exception("Runaway Cammy expression has %d unclosed parentheses" % count) | |
15 | - | |
16 | -def offset_atom(s): | |
17 | - for i, c in enumerate(s): | |
18 | - if c == ' ' or c == '\n': | |
19 | - return i | |
20 | - return len(s) | |
21 | - | |
22 | -def untangle(s): | |
23 | - offset = offset_list(s) if s.startswith('(') else offset_atom(s) | |
24 | - return s[:offset], s[offset:].strip() | |
25 | - | |
26 | -if __name__ == "__main__": | |
27 | - expr, doc = untangle(sys.stdin.read()) | |
28 | - command = sys.argv[1] | |
29 | - if command == "strip": | |
30 | - print(expr) | |
31 | - else: | |
32 | - raise Exception("Unknown command %s" % command) |
@@ -37,17 +37,13 @@ in pkgs.stdenv.mkDerivation { | ||
37 | 37 | --subst-var frame --subst-var jelly --subst-var movelist |
38 | 38 | chmod +x $out/bin/cammy-build |
39 | 39 | |
40 | - substitute $src/cammy-simplify.sh $out/bin/cammy-simplify \ | |
41 | - --subst-var bash \ | |
42 | - --subst-var frame --subst-var jelly --subst-var movelist | |
43 | - chmod +x $out/bin/cammy-simplify | |
44 | - | |
45 | - substitute $src/cammy-weave.py $out/bin/cammy-weave \ | |
46 | - --subst-var python3 | |
47 | - chmod +x $out/bin/cammy-weave | |
48 | - | |
40 | + # To be removed | |
49 | 41 | makeWrapper ${movelist}/bin/movelist $out/bin/cammy-movelist |
50 | 42 | |
43 | + # jelly | |
44 | + makeWrapper ${jelly}/bin/jelly $out/bin/cammy-jelly | |
45 | + | |
46 | + # RPython tools | |
51 | 47 | makeWrapper ${cammy-draw}/bin/cammy-draw $out/bin/cammy-draw |
52 | 48 | makeWrapper ${cammy-frame}/bin/cammy-frame $out/bin/cammy-frame |
53 | 49 | makeWrapper ${cammy-repl}/bin/cammy-repl $out/bin/cammy-repl |
@@ -1,3 +1,5 @@ | ||
1 | 1 | (f/addpair |
2 | 2 | (f/mulpair (comp fst fst) (comp snd fst)) |
3 | 3 | (f/mulpair (comp fst snd) (comp snd snd))) |
4 | + | |
5 | +The dot product of two two-dimensional vectors. |
@@ -0,0 +1 @@ | ||
1 | +(comp (pair @0 @1) f/dot2) |
@@ -0,0 +1,11 @@ | ||
1 | +(pair (comp fst @0) (comp snd @1)) | |
2 | + | |
3 | +Compose two arrows in parallel, acting on pairs of values. | |
4 | + | |
5 | +In categorical jargon, the [tensor | |
6 | +product](https://ncatlab.org/nlab/show/tensor+product) is a functor from pairs | |
7 | +of arrows to arrows: | |
8 | + | |
9 | +$$ | |
10 | +\bigotimes : C \times C \to C | |
11 | +$$ |
@@ -0,0 +1,5 @@ | ||
1 | +(pair | |
2 | + (pair f-one f-zero) | |
3 | + (pair f-zero f-one)) | |
4 | + | |
5 | +An identity matrix. |
@@ -0,0 +1,7 @@ | ||
1 | +(comp | |
2 | + (fun/tensor id mat2/trans) | |
3 | + (pair | |
4 | + (mat2/vecpair fst (comp snd fst)) | |
5 | + (mat2/vecpair fst (comp snd snd)))) | |
6 | + | |
7 | +Multiply two matrices. |
@@ -0,0 +1,5 @@ | ||
1 | +(pair | |
2 | + (pair (comp fst fst) (comp snd fst)) | |
3 | + (pair (comp fst snd) (comp snd snd))) | |
4 | + | |
5 | +Transpose a matrix. |
@@ -0,0 +1,5 @@ | ||
1 | +(pair | |
2 | + (f/dot2pair (comp fst fst) snd) | |
3 | + (f/dot2pair (comp fst snd) snd)) | |
4 | + | |
5 | +Apply a matrix to a column vector. |
@@ -0,0 +1 @@ | ||
1 | +(comp (pair @0 @1) mat2/vec) |
@@ -1 +1,3 @@ | ||
1 | 1 | (pr t not) |
2 | + | |
3 | +Whether a natural number is even. Zero is even. |
@@ -0,0 +1,3 @@ | ||
1 | +(comp nat/is_even not) | |
2 | + | |
3 | +Whether a natural number is odd. |
@@ -4,14 +4,13 @@ | ||
4 | 4 | - cammy-weave $HIVE: document a hive |
5 | 5 | * cammy-tangle $HIVE: take an expression on stdin, return framed optimized |
6 | 6 | expression on stdout |
7 | - * cammy-frame $HIVE | jelly | |
7 | + - cammy-frame $HIVE | cammy-jelly | |
8 | 8 | - cammy-draw ...: take an expression and canvas params, make a PNG |
9 | 9 | - cammy-frame $HIVE: take an expression on stdin, return framed expression |
10 | 10 | on stdout |
11 | - * cammy-jelly $EXPR: print an optimized expression on stdout | |
12 | - * $EXPR is a path! | |
13 | - * This is wholly due to RPython issues | |
14 | - * When $EXPR is "-", read from stdin | |
11 | + - cammy-jelly: print an optimized expression on stdout | |
12 | + - cammy-djinn $TY $TY: synthesize a function with the given signature | |
13 | + - uses last bit of movelist code | |
15 | 14 | * REPL improvements |
16 | 15 | * allow mid-functor newlines |
17 | 16 | * jellification |
@@ -30,18 +29,16 @@ | ||
30 | 29 | * list/append : [X] × [X] → [X] |
31 | 30 | * rat |
32 | 31 | * refactoring from the bikeshed: ignore -> ! |
33 | -* Typechecker needs to handle holes | |
34 | -* Typechecker should handle polymorphism better | |
35 | -* Typechecker errors are inscrutable | |
36 | -* Trigonometric functions | |
37 | - * f-atan2 added, need f-sin and f-cos? | |
38 | - * Optimizations for odd/even functions? | |
32 | + * Might not be important since fun/const is the only user! | |
39 | 33 | * Transcendental and other constants |
40 | 34 | * Euler's constant e |
41 | 35 | * Euler's constant gamma |
42 | 36 | * Remove movelist djinn, maybe? |
43 | 37 | * Double-negation monad for CPS? |
38 | + * Cont is available but not fully developed | |
39 | + * monads/cont/join, monads/cont/bind, etc. | |
44 | 40 | * fun/name should always start from 1 |
41 | + * Requires changing some callers | |
45 | 42 | * Prove that nat/add is smallest with its behavior |
46 | 43 | * Streams |
47 | 44 | * Monad: X → [N, X] |
@@ -58,3 +55,4 @@ | ||
58 | 55 | * Moore transducers: [Q × S, Q] -> [Q × S, Q] |
59 | 56 | * Mealy machines: For state type Q, input type S, and output type L, Q × S -> Q × L |
60 | 57 | * Jets |
58 | +* f/dot2pair |