A categorical programming language
修订版 | fa414c8aa7290f4490cfa29532906f6e59145fe0 (tree) |
---|---|
时间 | 2022-03-02 14:52:37 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Remove old CHICKEN stub and OCaml frame.
We won't be reusing this code, it hasn't been called in a while, and
it's time for cammy-build to retire, at least for now.
@@ -2,12 +2,16 @@ import os | ||
2 | 2 | import os.path |
3 | 3 | import sys |
4 | 4 | |
5 | +from rpython.rlib.listsort import make_timsort_class | |
6 | + | |
5 | 7 | from cammylib.arrows import BuildProblem |
6 | 8 | from cammylib.hive import Hive, MissingAtom |
7 | 9 | from cammylib.parser import parse |
8 | 10 | from cammylib.types import ConstraintStore, TypeExtractor, UnificationFailed |
9 | 11 | |
10 | 12 | |
13 | +SortFileNames = make_timsort_class() | |
14 | + | |
11 | 15 | def codeblock(code): |
12 | 16 | return "```\n" + code + "\n```" |
13 | 17 |
@@ -19,6 +23,7 @@ def main(argv): | ||
19 | 23 | prefix = len(hivepath) |
20 | 24 | doc = [] |
21 | 25 | for dirpath, dirnames, filenames in os.walk(hivepath): |
26 | + SortFileNames(filenames).sort() | |
22 | 27 | section = dirpath[prefix:] or "Top level" |
23 | 28 | doc.append("# " + section) |
24 | 29 |
@@ -1,40 +0,0 @@ | ||
1 | -#!@bash@/bin/bash | |
2 | - | |
3 | -# set -x | |
4 | -set -eu -o pipefail | |
5 | - | |
6 | -export CHICKEN_REPOSITORY_PATH=@CHICKEN_REPOSITORY_PATH@ | |
7 | -export CHICKEN_INCLUDE_PATH=@CHICKEN_INCLUDE_PATH@ | |
8 | - | |
9 | -frame="@frame@/bin/frame" | |
10 | -jelly="@jelly@/bin/jelly" | |
11 | -movelist="@movelist@/bin/movelist" | |
12 | - | |
13 | -# Configure a temporary directory. | |
14 | -tmpdir=$(mktemp -d) | |
15 | - | |
16 | -# Get the compilation mode, hive, and program to compile. | |
17 | -mode="$1" | |
18 | -printf "Compilation mode: %s\n" "$mode" | |
19 | -hive="$2" | |
20 | -input="$3" | |
21 | - | |
22 | -fullname=$(basename -- $input) | |
23 | -name="${fullname%.*}" | |
24 | - | |
25 | -# Pull from the frame and clarify the jelly. | |
26 | -<$input $frame $hive | $jelly >"$tmpdir/program.cammy" | |
27 | -# cat "$tmpdir/program.cammy" | |
28 | - | |
29 | -# Typecheck with movelist. | |
30 | -ty=$($movelist type-check <"$tmpdir/program.cammy") | |
31 | -printf "Type: %s\n" "$ty" | |
32 | - | |
33 | -# Compute the final piece. | |
34 | -sed -i -e 's,case,cammy-case,g' -e 's,cons,cammy-cons,g' -e 's,map,cammy-map,g' "$tmpdir/program.cammy" | |
35 | -cat stub.scm <(printf '(cammy-%s' "$1") "$tmpdir/program.cammy" <(echo "'$ty)") >"$tmpdir/$name.scm" | |
36 | -# Compile with Chicken. | |
37 | -@chicken@/bin/csc -static -O3 -o "$name" "$tmpdir/$name.scm" | |
38 | - | |
39 | -# Clean up temporary files. | |
40 | -rm -r "$tmpdir" |
@@ -1,7 +1,6 @@ | ||
1 | 1 | { nixpkgs ? import <nixpkgs> {} }: |
2 | 2 | let |
3 | 3 | inherit (nixpkgs) pkgs; |
4 | - frame = import ./frame { inherit nixpkgs; }; | |
5 | 4 | jelly = (import jelly/Cargo.nix { pkgs = nixpkgs; }).rootCrate.build; |
6 | 5 | movelist = import ./movelist { inherit nixpkgs; }; |
7 | 6 | cammy-draw = import ./cammy-rpy/draw.nix { inherit nixpkgs jelly; }; |
@@ -25,18 +24,11 @@ in pkgs.stdenv.mkDerivation { | ||
25 | 24 | buildInputs = [ pkgs.makeWrapper ]; |
26 | 25 | |
27 | 26 | inherit (pkgs) bash chicken python3; |
28 | - inherit CHICKEN_REPOSITORY_PATH CHICKEN_INCLUDE_PATH frame jelly movelist; | |
27 | + inherit CHICKEN_REPOSITORY_PATH CHICKEN_INCLUDE_PATH jelly movelist; | |
29 | 28 | |
30 | 29 | installPhase = '' |
31 | 30 | mkdir -p $out/bin/ |
32 | 31 | |
33 | - substitute $src/cammy.sh $out/bin/cammy-build \ | |
34 | - --subst-var bash \ | |
35 | - --subst-var chicken \ | |
36 | - --subst-var CHICKEN_REPOSITORY_PATH --subst-var CHICKEN_INCLUDE_PATH \ | |
37 | - --subst-var frame --subst-var jelly --subst-var movelist | |
38 | - chmod +x $out/bin/cammy-build | |
39 | - | |
40 | 32 | # To be removed |
41 | 33 | makeWrapper ${movelist}/bin/movelist $out/bin/cammy-movelist |
42 | 34 |
@@ -1 +0,0 @@ | ||
1 | -profile=compact |
@@ -1,13 +0,0 @@ | ||
1 | -{ nixpkgs ? import <nixpkgs> {} }: | |
2 | -let | |
3 | - inherit (nixpkgs.pkgs.ocamlPackages) buildDunePackage sexplib; | |
4 | -in buildDunePackage { | |
5 | - pname = "frame"; | |
6 | - version = "0.0.1"; | |
7 | - | |
8 | - useDune2 = true; | |
9 | - | |
10 | - buildInputs = [ sexplib ]; | |
11 | - | |
12 | - src = ./.; | |
13 | -} |
@@ -1,5 +0,0 @@ | ||
1 | -(executable | |
2 | - (name frame) | |
3 | - (libraries sexplib) | |
4 | - (public_name frame) | |
5 | - (package frame)) |
@@ -1,3 +0,0 @@ | ||
1 | -(lang dune 2.8) | |
2 | -(name frame) | |
3 | -(package (name frame) (synopsis "Recursively expand Cammy programs")) |
@@ -1,76 +0,0 @@ | ||
1 | -open Sexplib.Sexp | |
2 | -module PrimitiveFilter = Set.Make (String) | |
3 | -module CodeCache = Map.Make (String) | |
4 | - | |
5 | -let primitives = | |
6 | - "id comp ignore fst snd pair left right case curry uncurry \ | |
7 | - zero succ pr nil cons fold t f not conj disj either \ | |
8 | - f-zero f-one f-pi \ | |
9 | - f-sign f-floor f-negate f-recip f-lt f-add f-mul f-sqrt f-sin f-cos f-atan2" | |
10 | - | |
11 | -let filter = | |
12 | - List.fold_left | |
13 | - (Fun.flip PrimitiveFilter.add) | |
14 | - PrimitiveFilter.empty | |
15 | - (String.split_on_char ' ' primitives) | |
16 | - | |
17 | -let which_arg s = | |
18 | - let len = String.length s in | |
19 | - if len == 0 || s.[0] != '@' then None | |
20 | - else int_of_string_opt (String.sub s 1 (len - 1)) | |
21 | - | |
22 | -let rec arity_of expr = | |
23 | - match expr with | |
24 | - | Atom a -> Option.fold ~none:0 ~some:(fun x -> x + 1) (which_arg a) | |
25 | - | List l -> List.fold_left max 0 (List.rev_map arity_of l) | |
26 | - | |
27 | -let is_primitive s = | |
28 | - Option.is_some (which_arg s) || PrimitiveFilter.mem s filter | |
29 | - | |
30 | -let cache = ref CodeCache.empty | |
31 | -let basepath = Sys.argv.(1) | |
32 | - | |
33 | -let rec apply_functor args expr = | |
34 | - match expr with | |
35 | - | Atom a -> Option.fold ~none:expr ~some:(List.nth args) (which_arg a) | |
36 | - | List l -> List (List.hd l :: List.map (apply_functor args) (List.tl l)) | |
37 | - | |
38 | -let rec replace_code node = | |
39 | - match node with Atom a -> do_atom a | List l -> do_list l | |
40 | - | |
41 | -and lookup s = | |
42 | - match CodeCache.find_opt s !cache with | |
43 | - | Some pair -> pair | |
44 | - | None -> | |
45 | - let fullpath = Filename.concat basepath s ^ ".cammy" in | |
46 | - (* Printf.eprintf "Loading %s...\n" s ; *) | |
47 | - let expr = replace_code (load_sexp fullpath) in | |
48 | - let arity = arity_of expr in | |
49 | - cache := CodeCache.add s (expr, arity) !cache ; | |
50 | - (* Printf.eprintf "Loaded %s, arity %d\n" s arity ; *) | |
51 | - (expr, arity) | |
52 | - | |
53 | -and do_atom s = | |
54 | - if is_primitive s then Atom s | |
55 | - else | |
56 | - let expr, arity = lookup s in | |
57 | - if arity != 0 then failwith ("Functor " ^ s ^ " is not nullary") else expr | |
58 | - | |
59 | -and do_list l = | |
60 | - let tail = List.map replace_code (List.tl l) in | |
61 | - let head = List.hd l in | |
62 | - match head with | |
63 | - | Atom a -> | |
64 | - if is_primitive a then List (head :: tail) | |
65 | - else | |
66 | - let expr, arity = lookup a in | |
67 | - if arity != List.length tail then | |
68 | - failwith ("Functor " ^ a ^ " misapplied") | |
69 | - else apply_functor tail expr | |
70 | - | List l -> failwith "Functor heads cannot be lists!" | |
71 | - | |
72 | -let tree = input_sexp stdin | |
73 | - | |
74 | -let () = | |
75 | - output stdout (replace_code tree) ; | |
76 | - print_newline () |
@@ -1 +1,3 @@ | ||
1 | 1 | (f/addpair f-one f/9) |
2 | + | |
3 | +Ten. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp f/10 f/cube) |
2 | + | |
3 | +One thousand. |
@@ -1 +1,3 @@ | ||
1 | 1 | (f/addpair f-one f-one) |
2 | + | |
3 | +Two. |
@@ -1 +1,3 @@ | ||
1 | 1 | (f/addpair f-one f/2) |
2 | + | |
3 | +Three. |
@@ -1 +1,3 @@ | ||
1 | 1 | (f/addpair f/2 f/2) |
2 | + | |
3 | +Four. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp f/3 f/sqr) |
2 | + | |
3 | +Nine. |
@@ -2,3 +2,5 @@ | ||
2 | 2 | (pair (comp (comp f-sign either) (case (fun/name id) (fun/name f-negate))) |
3 | 3 | id) |
4 | 4 | fun/app) |
5 | + | |
6 | +The absolute value of a floating-point number. |
@@ -1 +1,3 @@ | ||
1 | 1 | (v2/map2 f-add) |
2 | + | |
3 | +Addition of two-dimensional vectors. |
@@ -1 +1,3 @@ | ||
1 | 1 | (v3/map2 f-add) |
2 | + | |
3 | +Addition of three-dimensional vectors. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (pair @0 @1) f-add) |
2 | + | |
3 | +Apply addition to a pair of arrows. |
@@ -1,2 +1,5 @@ | ||
1 | 1 | (comp (comp (f/error @0) f/sqr) |
2 | 2 | (f/ltpair id (fun/const (comp f/1000 f-recip)))) |
3 | + | |
4 | +Whether the given functor is approximately equal to the input floating-point | |
5 | +value at the input parameter. The absolute tolerance is one millionth. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (comp (pair id fun/dup) (pair fst (comp snd f-mul))) f-mul) |
2 | + | |
3 | +The cube of a floating-point number. |
@@ -1 +1,10 @@ | ||
1 | 1 | (comp (pair fst (comp snd f-recip)) f-mul) |
2 | + | |
3 | +Divide two floating-point numbers. Division by zero yields: | |
4 | + | |
5 | +* $\infty$ for positive dividends | |
6 | +* $-\infty$ for negative dividends | |
7 | +* $\pm 0$ for zero dividends | |
8 | + | |
9 | +Signs are respected; the result is negative when exactly one input is | |
10 | +negative, and positive otherwise. |
@@ -1 +1,3 @@ | ||
1 | 1 | (f/mulpair @0 (comp @1 f-recip)) |
2 | + | |
3 | +Apply division to a pair of arrows. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (pair @0 @1) f/dot2) |
2 | + | |
3 | +Apply the dot product to a pair of arrows. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (v3/map2 f-mul) (v3/fold f-add)) |
2 | + | |
3 | +The dot product of two three-dimensional vectors. |
@@ -1 +1,4 @@ | ||
1 | 1 | (f/addpair (comp fst @0) (comp snd f-negate)) |
2 | + | |
3 | +The error between the output value of the given arrow at the input value and | |
4 | +the expected input value. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp f/sub3 v3/norm) |
2 | + | |
3 | +The Euclidean distance between two three-dimensional vectors. |
@@ -1 +1,3 @@ | ||
1 | 1 | (f/subpair id (comp f-floor (case id (fun/const f-zero)))) |
2 | + | |
3 | +The fractional component of a floating-point number. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp f/2 f-recip) |
2 | + | |
3 | +One half. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (pair @0 @1) f-lt) |
2 | + | |
3 | +Whether one arrow is less than another at an input value. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (pair f-lt id) bool/pick) |
2 | + | |
3 | +The minimum of two floating-point numbers. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (pair @0 @1) f/min) |
2 | + | |
3 | +The minimum of two arrows at an input value. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (pair @0 @1) f-mul) |
2 | + | |
3 | +Apply multiplication to a pair of arrows. |
@@ -1,2 +1,4 @@ | ||
1 | 1 | (pair (comp fst f-negate) |
2 | 2 | (pair (comp (comp snd fst) f-negate) (comp (comp snd snd) f-negate))) |
3 | + | |
4 | +Negate a three-dimensional vector. |
@@ -1 +1,3 @@ | ||
1 | 1 | (f/mulpair id id) |
2 | + | |
3 | +The square of a floating-point number. |
@@ -1 +1,4 @@ | ||
1 | 1 | (comp f-sqrt (case id f-zero)) |
2 | + | |
3 | +The square root of a floating-point number, clamped to zero for negative | |
4 | +inputs. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (pair fst (comp snd f-negate)) f-add) |
2 | + | |
3 | +Subtraction of floating-point numbers. |
@@ -1 +1,3 @@ | ||
1 | 1 | (comp (pair fst (comp snd (v3/map f-negate))) f/add3) |
2 | + | |
3 | +Subtraction of two three-dimensional vectors. |
@@ -1 +1,3 @@ | ||
1 | 1 | (f/addpair @0 (comp @1 f-negate)) |
2 | + | |
3 | +Apply subtraction to a pair of arrows. |
@@ -1 +1,3 @@ | ||
1 | 1 | (fold f-zero f-add) |
2 | + | |
3 | +An uncompensated sum of a list of floating-point numbers. |
@@ -10,13 +10,8 @@ in pkgs.stdenv.mkDerivation { | ||
10 | 10 | buildInputs = with pkgs; [ |
11 | 11 | # debugging native code |
12 | 12 | gdb checksec |
13 | - # debugging stub.scm | |
14 | - chicken rlwrap ] ++ | |
15 | - (with eggs; [ srfi-144 srfi-160 srfi-189 stb-image-write ]) ++ [ | |
16 | 13 | # maintaining movelist/ |
17 | 14 | egg2nix |
18 | - # maintaining frame/ | |
19 | - ocamlformat | |
20 | 15 | # maintaining cammy-rpy/ |
21 | 16 | pythonPackages.pyflakes |
22 | 17 | # developing cammy-weave |
@@ -1,162 +0,0 @@ | ||
1 | -(import (srfi 6) (srfi 144) (srfi 160 u8) (srfi 189)) | |
2 | -(import (chicken condition) (chicken format) (chicken process-context) (chicken string)) | |
3 | -(import (matchable)) | |
4 | -(import (stb-image-write)) | |
5 | - | |
6 | -(define id (lambda (x) x)) | |
7 | -(define (comp f g) (lambda (x) (g (f x)))) | |
8 | - | |
9 | -(define ignore (lambda (x) '())) | |
10 | -(define fst (lambda (x) (car x))) | |
11 | -(define snd (lambda (x) (cdr x))) | |
12 | -(define (pair f g) (lambda (x) (cons (f x) (g x)))) | |
13 | -(define dup (lambda (x) (cons x x))) | |
14 | - | |
15 | -(define swap (lambda (x) (cons (cdr x) (car x)))) | |
16 | - | |
17 | -; left and right are exactly as in SRFI 189 | |
18 | -(define (cammy-case f g) (lambda (x) (either-ref x f g))) | |
19 | - | |
20 | -(define (curry f) (lambda (x) (lambda (y) (f (cons x y))))) | |
21 | -(define (uncurry f) (lambda (xy) ((f (car xy)) (cdr xy)))) | |
22 | -(define (name f) (lambda (x) f)) | |
23 | - | |
24 | -(define t (lambda (x) #t)) | |
25 | -(define f (lambda (x) #f)) | |
26 | -(define conj (lambda (xy) (and (car xy) (cdr xy)))) | |
27 | -(define disj (lambda (xy) (or (car xy) (cdr xy)))) | |
28 | -(define either (lambda (b) (if b (left '()) (right '())))) | |
29 | - | |
30 | -(define zero (lambda (x) 0)) | |
31 | -(define succ (lambda (x) (+ x 1))) | |
32 | -(define (pr x f) (lambda (n) (if (zero? n) (x '()) (f ((pr x f) (- n 1)))))) | |
33 | - | |
34 | -(define nil (lambda (x) '())) | |
35 | -(define cammy-cons (lambda (xy) (cons (car xy) (cdr xy)))) | |
36 | -(define (cammy-map f) (lambda (l) (map f l))) | |
37 | -(define (fold x f) | |
38 | - (lambda (l) (if (null? l) (x '()) (f (cons (car l) ((fold x f) (cdr l))))))) | |
39 | - | |
40 | -(define f-zero (lambda (x) (flonum 0.0))) | |
41 | -(define f-one (lambda (x) (flonum 1.0))) | |
42 | -(define f-sign (lambda (x) (eqv? (flsign-bit x) 0))) | |
43 | -(define (f-negate x) (fl- x)) | |
44 | -(define (f-recip x) (fl/ x)) | |
45 | -(define (f-lt xy) (fl<? (car xy) (cdr xy))) | |
46 | -(define (f-add xy) (fl+ (car xy) (cdr xy))) | |
47 | -(define (f-mul xy) (fl* (car xy) (cdr xy))) | |
48 | -(define (f-sqrt x) (if (eqv? 0 (flsign-bit x)) (left (flsqrt x)) (right '()))) | |
49 | - | |
50 | -(define (read-string s) (read (open-input-string s))) | |
51 | -(define (arg-error arg why) | |
52 | - (signal (condition (list 'exn 'message (sprintf "Invalid argument ~A: ~A" arg why))))) | |
53 | -(define (arg-unit args) (cons '() args)) | |
54 | -(define (arg-bool args) | |
55 | - (let ((x (car args))) | |
56 | - (if (boolean? x) (cons x (cdr args)) (arg-error x "not bool")))) | |
57 | -(define (arg-nat args) | |
58 | - (let ((x (car args))) | |
59 | - (if (>= x 0) (cons x (cdr args)) (arg-error x "not a natural number")))) | |
60 | -(define (arg-fp args) | |
61 | - (let ((x (car args))) | |
62 | - (if (flonum? x) (cons x (cdr args)) | |
63 | - (arg-error x "not a floating-point number")))) | |
64 | -(define (arg-list p) | |
65 | - (lambda (args) | |
66 | - (let ((x (car args))) | |
67 | - (cons x (cdr args))))) | |
68 | -(define (arg-pair p1 p2) | |
69 | - (lambda (args1) | |
70 | - (let* ((pair1 (p1 args1)) (x (car pair1)) (args2 (cdr pair1)) | |
71 | - (pair2 (p2 args2)) (y (car pair2)) (args3 (cdr pair2))) | |
72 | - (cons (cons x y) args3)))) | |
73 | - | |
74 | -(define (argv) (map read-string (command-line-arguments))) | |
75 | - | |
76 | -(define (parse-args parser) | |
77 | - (parser (argv))) | |
78 | - | |
79 | -(define ty-parse (match-lambda | |
80 | - ['1 arg-unit] | |
81 | - ['N arg-nat] | |
82 | - ['F arg-fp] | |
83 | - [('list x) (arg-list (ty-parse x))] | |
84 | - [('pair x y) (arg-pair (ty-parse x) (ty-parse y))])) | |
85 | - | |
86 | -; Run a program once using argv for parameters. | |
87 | -(define (cammy-oneshot program ty) | |
88 | - (let* | |
89 | - ((input (car (parse-args (ty-parse (car ty))))) | |
90 | - (rv (program input))) | |
91 | - (begin (display rv) (newline)))) | |
92 | - | |
93 | - | |
94 | -(define (scale bot top) | |
95 | - (let ((d (- top bot))) | |
96 | - (lambda (x) (+ bot (* d x))))) | |
97 | - | |
98 | -(define (viewport window width height) | |
99 | - (let* | |
100 | - ((aspect (/ width height)) | |
101 | - (iw (/ width)) | |
102 | - (ih (/ height)) | |
103 | - (dw (* 0.5 iw)) | |
104 | - (dh (* 0.5 ih)) | |
105 | - (sw (scale (car window) (car (cdr (cdr window))))) | |
106 | - (sh (scale (car (cdr window)) (car (cdr (cdr (cdr window))))))) | |
107 | - (lambda (i) | |
108 | - (let ((w (modulo i width)) (h (/ i width))) | |
109 | - (cons (sw (+ dw (* iw w))) (sh (+ dh (* ih h)))))))) | |
110 | - | |
111 | -(define f-sum (fold f-zero f-add)) | |
112 | -(define (f-average xs) (/ (f-sum xs) (length xs))) | |
113 | - | |
114 | -(define ((multisample radius program) p) | |
115 | - (let* | |
116 | - ((px (car p)) | |
117 | - (py (cdr p)) | |
118 | - (c0 (program p)) | |
119 | - (c1 (program (cons (+ px radius) py))) | |
120 | - (c2 (program (cons (- px radius) py))) | |
121 | - (c3 (program (cons px (+ py radius)))) | |
122 | - (c4 (program (cons px (- py radius)))) | |
123 | - (l (list c0 c1 c2 c3 c4)) | |
124 | - (red (f-average (map car l))) | |
125 | - (blue (f-average (map (comp cdr car) l))) | |
126 | - (green (f-average (map (comp cdr cdr) l)))) | |
127 | - (cons red (cons blue green)))) | |
128 | - | |
129 | -(define (finish-channel c) | |
130 | - (inexact->exact (round (* 255 (max 0.0 (min 1.0 c)))))) | |
131 | - | |
132 | -(define ((draw-pixel program vp) i) | |
133 | - (let* | |
134 | - ((color (program (vp i))) | |
135 | - (r (car color)) | |
136 | - (g (car (cdr color))) | |
137 | - (b (cdr (cdr color)))) | |
138 | - (list->u8vector (map finish-channel (list r g b))))) | |
139 | - | |
140 | -(define (draw-png program filename window width height) | |
141 | - (let* | |
142 | - ((vp (viewport window width height)) | |
143 | - (size (* width height)) | |
144 | - (radius 0.000001) | |
145 | - (channels 3) | |
146 | - (drawable (draw-pixel (multisample radius program) vp)) | |
147 | - ; (drawable (draw-pixel program vp)) | |
148 | - (pixels | |
149 | - (do ((buf (make-u8vector (* size channels))) | |
150 | - (i 0 (+ i 1))) | |
151 | - ((eqv? i size) buf) | |
152 | - (u8vector-copy! buf (* i channels) (drawable i))))) | |
153 | - (with-output-to-file filename | |
154 | - (lambda () (write-png pixels width height | |
155 | - channels))))) | |
156 | - | |
157 | -; Run a program repeatedly and draw the results. | |
158 | -(define (cammy-draw program ty) | |
159 | - (match (command-line-arguments) | |
160 | - [(window width height filename) | |
161 | - (draw-png program filename (read-string window) (read-string width) | |
162 | - (read-string height))])) |