A categorical programming language
修订版 | 7f8b03a3d558edae73e0bc5bf258e9a097bb54e2 (tree) |
---|---|
时间 | 2021-08-10 14:34:36 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Parse lists of nats.
Generalized lists of lists will need something recursive.
@@ -1,4 +1,4 @@ | ||
1 | -To update Cargo dependencies: | |
1 | +To update Cargo dependencies for jelly: | |
2 | 2 | |
3 | 3 | * $ cargo metadata |
4 | 4 | * $ crate2nix generate |
@@ -56,3 +56,23 @@ Combinators with (*) are provided by OCaml by default; the others are in a | ||
56 | 56 | stub module. Type-checking is achieved by copying the combinators into |
57 | 57 | an OCaml expression; compilation is achieved by copying the combinators into |
58 | 58 | a CHICKEN Scheme expression. |
59 | + | |
60 | +In terms of the "principal programming paradigms" | |
61 | +https://www.info.ucl.ac.be/~pvr/paradigmsDIAGRAMeng101.pdf, Cammy is a | |
62 | +"functional programming" language; it possesses the ability to encode | |
63 | +arbitrary functions via topos theory. Later improvements may shift Cammy to | |
64 | +the "monotonic dataflow programming", "multi-agent dataflow programming", or | |
65 | +"event-loop programming" paradigms. | |
66 | + | |
67 | +In terms of the common taxonomy of type systems, exhibited for tutorial at | |
68 | +https://www.cs.uaf.edu/users/chappell/public_html/class/2018_spr/cs331/docs/types_primer.html, | |
69 | +Cammy's current toolchain implements a static, implicit, structural, sound | |
70 | +type system. For a classic example, the program (comp dup apply), sometimes | |
71 | +called the "Turing bird", will be rejected by the toolchain as ill-typed. | |
72 | + | |
73 | +In terms of the taxonomy of desugaring systems | |
74 | +https://cs.brown.edu/research/pubs/theses/phd/2018/pombrio.justin.pdf, Cammy | |
75 | +does not implement desugaring. Any nullary sugar can be implemented as plain | |
76 | +Cammy programs. Every algebraic equality in Cammy's combinators corresponds to | |
77 | +a desugaring rule in the toolchain, but those equalities are not taxonomically | |
78 | +syntactic sugar. |
@@ -9,6 +9,12 @@ parsers = { | ||
9 | 9 | "nat * nat": "string->int", |
10 | 10 | } |
11 | 11 | |
12 | +def get_parser(ty): | |
13 | + if ty.endswith(" list"): | |
14 | + return "(string->listof {})".format(get_parser(ty[:-5])) | |
15 | + else: | |
16 | + return parsers[ty] | |
17 | + | |
12 | 18 | with open(sys.argv[-1], "r", encoding="utf-8") as handle: |
13 | 19 | line = handle.readlines()[-2] |
14 | 20 |
@@ -25,11 +31,11 @@ with open(sys.argv[-2], "r", encoding="utf-8") as handle: | ||
25 | 31 | |
26 | 32 | print(""" |
27 | 33 | (import (chicken process-context)) |
28 | -(define parsers (map eval '({}))) | |
34 | +(define parsers (list {})) | |
29 | 35 | (define parsed-args (zip-app parsers (command-line-arguments))) |
30 | 36 | (begin |
31 | 37 | (display (fold-left program (lambda (x f) (f x)) parsed-args)) |
32 | 38 | (newline)) |
33 | 39 | """.format( |
34 | - " ".join(parsers[ty] for ty in tys), | |
40 | + " ".join(get_parser(ty) for ty in tys), | |
35 | 41 | )) |
@@ -0,0 +1 @@ | ||
1 | +(fold zero (uncurry nat/add)) |
@@ -1,4 +1,5 @@ | ||
1 | 1 | (import (chicken condition)) |
2 | +(import (chicken string)) | |
2 | 3 | |
3 | 4 | (define id (lambda (x) x)) |
4 | 5 | (define (comp f g) (lambda (x) (g (f x)))) |
@@ -30,14 +31,23 @@ | ||
30 | 31 | (define (fold x f) |
31 | 32 | (lambda (l) (if (null? l) (x '()) (f (cons (car l) ((fold x f) (cdr l))))))) |
32 | 33 | |
34 | +(define (parse-error message) (signal (condition (list 'exn 'message message)))) | |
33 | 35 | (define (string->unit s) '()) |
34 | 36 | (define (string->boolean s) (equal? s "true")) |
35 | 37 | (define (string->nat s) |
36 | 38 | (let ((i (string->number s))) |
37 | - (if (< i 0) (signal (condition '(exn message "nats must be positive"))) | |
39 | + (if (< i 0) (parse-error "nats must be positive") | |
38 | 40 | i))) |
39 | 41 | (define (string->int s) |
40 | 42 | (let ((i (string->number s))) (if (< i 0) (cons 0 (abs i)) (cons i 0)))) |
43 | +(define (string->listof p) (lambda (s) | |
44 | + (let ((len (string-length s))) | |
45 | + (if (not (equal? #\( (string-ref s 0))) | |
46 | + (parse-error "list must start with (")) | |
47 | + (if (not (equal? #\) (string-ref s (- len 1)))) | |
48 | + (parse-error "list must end with )")) | |
49 | + (map p (string-split (substring s 1 (- len 1))))))) | |
50 | + | |
41 | 51 | (define (fold-left kn kc l) (if (null? l) kn (kc (car l) (fold-left kn kc (cdr l))))) |
42 | 52 | (define (zip-app fs xs) |
43 | 53 | (if (null? fs) '() |