A categorical programming language
修订版 | 3ee4ecc4571ee60e563341963a49c9a7f8c64652 (tree) |
---|---|
时间 | 2021-08-11 02:02:54 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Redo and simplify argument handling.
Lists of lists should no longer be off the menu.
@@ -2,18 +2,17 @@ | ||
2 | 2 | |
3 | 3 | import sys |
4 | 4 | |
5 | -parsers = { | |
6 | - "unit": "string->unit", | |
7 | - "bool": "string->boolean", | |
8 | - "nat": "string->nat", | |
9 | - "nat * nat": "string->int", | |
5 | +aliases = { | |
6 | + "nat * nat": "int", | |
10 | 7 | } |
11 | 8 | |
12 | 9 | def get_parser(ty): |
13 | 10 | if ty.endswith(" list"): |
14 | - return "(string->listof {})".format(get_parser(ty[:-5])) | |
11 | + return "(arg-list {})".format(get_parser(ty[:-5])) | |
12 | + elif ty in aliases: | |
13 | + return get_parser(aliases[ty]) | |
15 | 14 | else: |
16 | - return parsers[ty] | |
15 | + return "arg-" + ty | |
17 | 16 | |
18 | 17 | with open(sys.argv[-1], "r", encoding="utf-8") as handle: |
19 | 18 | line = handle.readlines()[-2] |
@@ -32,7 +31,9 @@ with open(sys.argv[-2], "r", encoding="utf-8") as handle: | ||
32 | 31 | print(""" |
33 | 32 | (import (chicken process-context)) |
34 | 33 | (define parsers (list {})) |
35 | -(define parsed-args (zip-app parsers (command-line-arguments))) | |
34 | +(define parsed-args | |
35 | + (map (lambda (arg p) (p (read-string arg))) | |
36 | + (command-line-arguments) parsers)) | |
36 | 37 | (begin |
37 | 38 | (display (fold-left program (lambda (x f) (f x)) parsed-args)) |
38 | 39 | (newline)) |
@@ -1,4 +1,6 @@ | ||
1 | +(import (srfi 6)) | |
1 | 2 | (import (chicken condition)) |
3 | +(import (chicken format)) | |
2 | 4 | (import (chicken string)) |
3 | 5 | |
4 | 6 | (define id (lambda (x) x)) |
@@ -31,24 +33,14 @@ | ||
31 | 33 | (define (fold x f) |
32 | 34 | (lambda (l) (if (null? l) (x '()) (f (cons (car l) ((fold x f) (cdr l))))))) |
33 | 35 | |
34 | -(define (parse-error message) (signal (condition (list 'exn 'message message)))) | |
35 | -(define (string->unit s) '()) | |
36 | -(define (string->boolean s) (equal? s "true")) | |
37 | -(define (string->nat s) | |
38 | - (let ((i (string->number s))) | |
39 | - (if (< i 0) (parse-error "nats must be positive") | |
40 | - i))) | |
41 | -(define (string->int s) | |
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))))))) | |
36 | +(define (read-string s) (read (open-input-string s))) | |
37 | +(define (arg-error arg why) | |
38 | + (signal (condition (list 'exn 'message (sprintf "Invalid argument ~A: ~A" arg why))))) | |
39 | +(define (arg-unit x) '()) | |
40 | +(define (arg-bool x) (if (boolean? x) x (arg-error x "not bool"))) | |
41 | +(define (arg-nat x) (if (> x 0) x (arg-error x "not a natural number"))) | |
42 | +(define (arg-int x) | |
43 | + (if (number? x) (if (> x 0) (cons x 0) (cons 0 (abs x))) (arg-error x "not an integer"))) | |
44 | +(define (arg-list p) (lambda (x) (map p x))) | |
50 | 45 | |
51 | 46 | (define (fold-left kn kc l) (if (null? l) kn (kc (car l) (fold-left kn kc (cdr l))))) |
52 | -(define (zip-app fs xs) | |
53 | - (if (null? fs) '() | |
54 | - (cons ((car fs) (car xs)) (zip-app (cdr fs) (cdr xs))))) |