git @ Cat's Eye Technologies Robin / d73329a
Checkpoint removing `self`. list, choose, remainder need rewriting. Chris Pressey 4 years ago
39 changed file(s) with 180 addition(s) and 188 deletion(s). Raw diff Collapse all Expand all
6161 Such a form is parsed as a conventional string data type (see
6262 the "String" section in the Robin Expression Language for details.)
6363
64 | (define literal (macro (s a e) (head a)))
64 | (define literal (macro (a e) (head a)))
6565 | (display
6666 | (literal ''Hello''))
6767 = (72 101 108 108 111)
6868
6969 A single single quote may appear in string literals of this kind.
7070
71 | (define literal (macro (s a e) (head a)))
71 | (define literal (macro (a e) (head a)))
7272 | (display
7373 | (literal ''He'llo''))
7474 = (72 101 39 108 108 111)
7878 match the sentinel given between the trailing single quote pair. The
7979 sentinel may consist of any text not containing a single quote.
8080
81 | (define literal (macro (s a e) (head a)))
81 | (define literal (macro (a e) (head a)))
8282 | (display
8383 | (literal 'X'Hello'X'))
8484 = (72 101 108 108 111)
8585
86 | (define literal (macro (s a e) (head a)))
86 | (define literal (macro (a e) (head a)))
8787 | (display
8888 | (literal '...('Hello'...('))
8989 = (72 101 108 108 111)
9090
91 | (define literal (macro (s a e) (head a)))
91 | (define literal (macro (a e) (head a)))
9292 | (display
9393 | (literal 'X'Hello'Y'))
9494 ? unexpected end of input
9595
9696 A sentinelized literal like this may embed a pair of single quotes.
9797
98 | (define literal (macro (s a e) (head a)))
98 | (define literal (macro (a e) (head a)))
9999 | (display
100100 | (literal 'X'Hel''lo'X'))
101101 = (72 101 108 39 39 108 111)
103103 By choosing different sentinels, string literals may contain any other
104104 string literal.
105105
106 | (define literal (macro (s a e) (head a)))
106 | (define literal (macro (a e) (head a)))
107107 | (display
108108 | (literal 'X'Hel'Y'bye'Y'lo'X'))
109109 = (72 101 108 39 89 39 98 121 101 39 89 39 108 111)
112112 (Functions to convert escape sequences commonly found in other languages
113113 may one day be available in a standard module.)
114114
115 | (define literal (macro (s a e) (head a)))
115 | (define literal (macro (a e) (head a)))
116116 | (display
117117 | (literal ''Hello\nworld''))
118118 = (72 101 108 108 111 92 110 119 111 114 108 100)
120120 All characters which appear in the source text between the delimiters
121121 of the string literal are literally included in the string.
122122
123 | (define literal (macro (s a e) (head a)))
123 | (define literal (macro (a e) (head a)))
124124 | (display
125125 | (literal ''Hello
126126 | world''))
128128
129129 Adjacent string literals are not automatically concatenated.
130130
131 | (define literal (macro (s a e) (head a)))
131 | (define literal (macro (a e) (head a)))
132132 | (display
133133 | (literal (''Hello'' ''world'')))
134134 = ((72 101 108 108 111) (119 111 114 108 100))
258258 covered yet: a macro. We'll just go ahead and show the example, and
259259 will explain macros later.
260260
261 | ((macro (s a e) (head a)) hello)
261 | ((macro (a e) (head a)) hello)
262262 = hello
263263
264264 A Robin implementation is not expected to be able to generate new symbols
332332 binds each of those values to a formal parameter of the function, then
333333 evaluates the body of the function in that new environment, a macro:
334334
335 * binds the macro value itself to the first formal parameter of the
336 macro (by convention called `self`) — this is to facilitate writing
337 recursive macros;
338335 * binds the literal tail of the list of the macro application to
339336 the second formal parameter of the macro (by convention called `args`);
340337 * binds a binding alist representing the environment in effect at the
349346 Macros are represented as the S-expression expansion of their
350347 implementation.
351348
352 | (macro (self args env) args)
353 = (macro (self args env) args)
349 | (macro (args env) args)
350 = (macro (args env) args)
354351
355352 Macros can be applied, and that is the typical use of them.
356353
357 | ((macro (self args env) args) 1)
354 | ((macro (args env) args) 1)
358355 = (1)
359356
360357 ### Lists ###
380377
381378 Non-empty lists do not evaluate to themselves; rather, they represent a macro
382379 application. However, the `literal` macro (whose definition is
383 `(macro (s a e) (head a))`) may be used to obtain a literal list.
384
385 | ((macro (s a e) (head a)) (7 8)))
380 `(macro (a e) (head a))`) may be used to obtain a literal list.
381
382 | ((macro (a e) (head a)) (7 8)))
386383 = (7 8)
387384
388385 Lists cannot be directly applied, but since a list itself represents an
672669 is perhaps not the best example.)
673670
674671 | (define true #t)
675 | (define true ((macro (self args env) #t)))
672 | (define true ((macro (args env) #t)))
676673 | (display true)
677674 = #t
678675
825822 the integer 0, and the state is set to 0 after each event is reacted to.
826823
827824 | (reactor (line-terminal) 0
828 | (macro (self args env)
825 | (macro (args env)
829826 | (bind event (head args)
830827 | (bind event-type (head event)
831828 | (if (equal? event-type (literal init))
845842 Thus we can construct a simple `cat` program:
846843
847844 | (reactor (line-terminal) 0
848 | (macro (self args env)
845 | (macro (args env)
849846 | (bind event (head args)
850847 | (bind event-type (head event)
851848 | (bind event-payload (head (tail event))
880877 A reactor can issue multiple commands in its response to an event.
881878
882879 | (reactor (line-terminal) 0
883 | (macro (self args env)
880 | (macro (args env)
884881 | (bind event (head args)
885882 | (bind event-type (head event)
886883 | (bind event-payload (head (tail event))
900897 message of some kind, but it should otherwise ignore it and keep going.
901898
902899 | (reactor (line-terminal) 0
903 | (macro (self args env)
900 | (macro (args env)
904901 | (bind event (head args)
905902 | (bind event-type (head event)
906903 | (bind event-payload (head (tail event))
924921 but this is not a strict requirement.
925922
926923 | (reactor (line-terminal) 0
927 | (macro (self args env)
924 | (macro (args env)
928925 | (bind event (head args)
929926 | (bind event-type (head event)
930927 | (bind event-payload (head (tail event))
943940
944941 Reactors can keep state.
945942
946 | (define inc (macro (self args env)
943 | (define inc (macro (args env)
947944 | (subtract (eval env (head args)) (subtract 0 1))))
948945 | (reactor (line-terminal) 65
949 | (macro (self args env)
946 | (macro (args env)
950947 | (bind state (head (tail args))
951948 | (bind event (head args)
952949 | (bind event-type (head event)
964961 Multiple reactors can be instantiated, will react to the same events.
965962 Note that reactors react in the *opposite* order they were installed.
966963
967 | (define inc (macro (self args env)
964 | (define inc (macro (args env)
968965 | (subtract (eval env (head args)) (subtract 0 1))))
969966 | (reactor (line-terminal) 65
970 | (macro (self args env)
967 | (macro (args env)
971968 | (bind state (head (tail args))
972969 | (bind event (head args)
973970 | (bind event-type (head event)
976973 | (list (inc state) (list (literal writeln) (list state)))
977974 | (list state))))))))
978975 | (reactor (line-terminal) 0
979 | (macro (self args env)
976 | (macro (args env)
980977 | (bind event (head args)
981978 | (bind event-type (head event)
982979 | (bind event-payload (head (tail event))
996993
997994 A reactor can stop by issuing a `stop` command.
998995
999 | (define inc (macro (self args env)
996 | (define inc (macro (args env)
1000997 | (subtract (eval env (head args)) (subtract 0 1))))
1001998 | (reactor (line-terminal) 65
1002 | (macro (self args env)
999 | (macro (args env)
10031000 | (bind state (head (tail args))
10041001 | (bind event (head args)
10051002 | (bind event-type (head event)
10201017
10211018 Stopping one reactor does not stop others.
10221019
1023 | (define inc (macro (self args env)
1020 | (define inc (macro (args env)
10241021 | (subtract (eval env (head args)) (subtract 0 1))))
10251022 | (reactor (line-terminal) 65
1026 | (macro (self args env)
1023 | (macro (args env)
10271024 | (bind state (head (tail args))
10281025 | (bind event (head args)
10291026 | (bind event-type (head event)
10341031 | (list (inc state) (list (literal writeln) event-payload)))
10351032 | (list state))))))))
10361033 | (reactor (line-terminal) 65
1037 | (macro (self args env)
1034 | (macro (args env)
10381035 | (bind state (head (tail args))
10391036 | (bind event (head args)
10401037 | (bind event-type (head event)
00 (require fun)
11 (require empty?)
22
3 (define command (macro (self args env)
3 (define command (macro (args env)
44 (list (head args) (eval env (head (tail args))))))
55
6 (reactor (line-terminal) (list 0 0) (macro (self args env)
6 (reactor (line-terminal) (list 0 0) (macro (args env)
77 (let ((event (head args))
88 (event-type (head event))
99 (event-payload (head (tail event)))
00 (require bind)
11
22 (reactor (line-terminal) 0
3 (macro (self args env)
3 (macro (args env)
44 (bind event (head args)
55 (bind event-type (head event)
66 (bind event-payload (head (tail event))
44 (require itoa)
55
66 (reactor (line-terminal) 0
7 (macro (self args env)
7 (macro (args env)
88 (bind event (head args)
99 (bind event-type (head event)
1010 (bind event-payload (head (tail event))
1515 (if (equal? prev-state 256)
1616 0
1717 prev-state))
18 (bind prompt (macro (self args env)
18 (bind prompt (macro (args env)
1919 (bind show (eval env (head args))
2020 (bind state (eval env (head (tail args)))
2121 (if show
11 (require literal)
22
33 (reactor (line-terminal) 0
4 (macro (self args env)
4 (macro (args env)
55 (bind event (head args)
66 (bind event-type (head event)
77 (if (equal? event-type (literal init))
33 (require let) (require choose) (require itoa) (require abs) (require remainder)
44
55 (reactor (line-terminal random-u16-source) 0
6 (macro (self args env)
6 (macro (args env)
77 (let ((event (head args))
88 (event-type (head event))
99 (event-payload (head (tail event))))
7070 makeMacroEnv :: Env -> Expr -> Expr -> Env
7171 makeMacroEnv env actuals m@(Macro closedEnv argList _) =
7272 let
73 (List [(Symbol argSelf), (Symbol argFormal),
74 (Symbol envFormal)]) = argList
75 newEnv = insert argSelf m closedEnv
76 newEnv' = insert argFormal actuals newEnv
73 (List [(Symbol argFormal), (Symbol envFormal)]) = argList
74 newEnv' = insert argFormal actuals closedEnv
7775 newEnv'' = insert envFormal env newEnv'
7876 in
7977 newEnv''
7878 eval_ env other cc = errMsg "illegal-arguments" other
7979
8080 macro :: Evaluable
81 macro env (List [args@(List [(Symbol selfS), (Symbol argsS), (Symbol envS)]), body]) cc =
81 macro env (List [args@(List [(Symbol argsS), (Symbol envS)]), body]) cc =
8282 cc $ Macro env args body
8383 macro env other cc = errMsg "illegal-arguments" other
8484
2626
2727 '<<SPEC'
2828
29 (define abs (macro (self args env)
29 (define abs (macro (args env)
3030 (bind-args (a) args env
3131 (if (equal? (sign a) 1) a (subtract 0 a)))))
2525
2626 '<<SPEC'
2727
28 (define add (macro (self args env)
28 (define add (macro (args env)
2929 (bind-args (a b) args env
3030 (subtract a (subtract 0 b)))))
4141
4242 '<<SPEC'
4343
44 (define and (macro (self args env)
44 (define and (macro (args env)
4545 (if (equal? (tail (tail args)) ())
4646 (if (eval env (head args))
4747 (if (eval env (head (tail args))) #t #f)
4444 become clear here: typically you would just pass the macro's `args` and
4545 `env` to those arguments.
4646
47 | (bind add (macro (self args env)
47 | (bind add (macro (args env)
4848 | (bind-args (a b) args env
4949 | (subtract a (subtract 0 b))))
5050 | (add 4 (add 5 6)))
5151 = 15
5252
53 | (bind add (macro (self args env)
53 | (bind add (macro (args env)
5454 | (bind-args (a b) args env
5555 | (subtract a (subtract 0 b))))
5656 | (bind r 7
5757 | (add r r)))
5858 = 14
5959
60 | (bind add (macro (self args env)
60 | (bind add (macro (args env)
6161 | (bind-args (a b) args env
6262 | (subtract a (subtract 0 b))))
6363 | (add (subtract 0 0)))
6464 ? abort (illegal-arguments ((subtract 0 0)))
6565
66 | (bind add (macro (self args env)
66 | (bind add (macro (args env)
6767 | (bind-args (a b) args env
6868 | (subtract a (subtract 0 b))))
6969 | (add 9 9 9))
7070 ? abort (illegal-arguments (9 9 9))
7171
72 | (bind add (macro (self args env)
72 | (bind add (macro (args env)
7373 | (bind-args (a b) args env
7474 | (subtract a (subtract 0 b))))
7575 | (add 1 n))
7878 '<<SPEC'
7979
8080 (define bind-args
81 (macro (self args env)
81 (macro (args env)
8282 (let (
8383 (id-list (head args))
8484 (orig-val-list (eval env (head (tail args))))
8585 (given-env (eval env (head (tail (tail args)))))
8686 (expr (head (tail (tail (tail args)))))
87 (bind-args-r (macro (self args env)
87 (bind-args-r (macro (args env)
8888 (let (
89 (id-list (eval env (head args)))
90 (val-list (eval env (head (tail args))))
91 (env-acc (eval env (head (tail (tail args)))))
89 (self (eval env (head args)))
90 (id-list (eval env (head (tail args))))
91 (val-list (eval env (head (tail (tail args)))))
92 (env-acc (eval env (head (tail (tail (tail args))))))
9293 )
9394 (if (equal? id-list ())
9495 (if (equal? val-list ())
105106 env-acc))
106107 error (abort error))))))))
107108 (recover
108 (bind-args-r id-list orig-val-list env)
109 (bind-args-r bind-args-r id-list orig-val-list env)
109110 new-env (eval new-env expr)
110111 error (abort error)))))
99 | (list x x))
1010 = (hello hello)
1111
12 | (bind dup (macro (self args env)
12 | (bind dup (macro (args env)
1313 | (list (head args) (head args)))
1414 | (dup g))
1515 = (g g)
1616
17 | (bind dup (macro (self args env)
17 | (bind dup (macro (args env)
1818 | (bind x (eval env (head args))
1919 | (list x x)))
2020 | (dup (literal g)))
2121 = (g g)
2222
23 | (bind dup (macro (self args env)
23 | (bind dup (macro (args env)
2424 | (bind x (eval env (head args))
2525 | (list x x)))
2626 | (dup (dup (literal g))))
2727 = ((g g) (g g))
2828
29 | (bind find (macro (self args env)
30 | (bind-args (alist key) args env
31 | (if (equal? alist (literal ())) (literal ())
32 | (if (equal? key (head (head alist)))
33 | (head alist)
34 | (self (tail alist) key)))))
35 | (find (literal ((c d) (e f) (a b))) (literal a)))
36 = (a b)
29 /| (bind find (macro (self args env)
30 /| (bind-args (alist key) args env
31 /| (if (equal? alist (literal ())) (literal ())
32 /| (if (equal? key (head (head alist)))
33 /| (head alist)
34 /| (self (tail alist) key)))))
35 /| (find (literal ((c d) (e f) (a b))) (literal a)))
36 /= (a b)
3737
3838 `bind` expects exactly three arguments, or else an abort value will be produced.
3939
5151
5252 '<<SPEC'
5353
54 (define bind (macro (self args env)
54 (define bind (macro (args env)
5555 (eval
5656 (prepend
5757 (prepend (head args) (prepend (eval env (head (tail args)))
2424
2525 '<<SPEC'
2626
27 (define boolean? (macro (self args env)
27 (define boolean? (macro (args env)
2828 (bind-args (b) args env
2929 (if (equal? b #t)
3030 #t
2929
3030 '<<SPEC'
3131
32 (define bound? (macro (self args env)
32 (define bound? (macro (args env)
3333 (if (equal? args ())
3434 (abort (list (literal illegal-arguments) args))
3535 (if (equal? (tail args) ())
4040
4141 '<<SPEC'
4242
43 (define choose (macro (self args env)
43 (define choose (macro (args env)
4444 (bind branch (head args)
4545 (bind test (head branch)
4646 (bind then (head (tail branch))
4545
4646 '<<SPEC'
4747
48 (define divide (macro (self args env)
48 (define divide (macro (args env)
4949 (bind divide-r-pos (fun (self n d acc) ;(d is positive)
5050 (if (gt? d n)
5151 acc
44 `env` evaluates to all the bindings in effect at the point of execution
55 where this form is encountered, as an alist.
66
7 | (bind find (macro (self args env)
8 | (bind-args (alist key) args env
9 | (if (equal? alist (literal ())) (literal ())
10 | (if (equal? key (head (head alist)))
11 | (head alist)
12 | (self (tail alist) key)))))
13 | (prepend
14 | (find (env) (literal symbol?)) (find (env) (literal prepend))))
15 = ((symbol? symbol?) prepend prepend)
7 /| (bind find (macro (self args env)
8 /| (bind-args (alist key) args env
9 /| (if (equal? alist (literal ())) (literal ())
10 /| (if (equal? key (head (head alist)))
11 /| (head alist)
12 /| (self (tail alist) key)))))
13 /| (prepend
14 /| (find (env) (literal symbol?)) (find (env) (literal prepend))))
15 /= ((symbol? symbol?) prepend prepend)
1616
1717 `env` expects no arguments. Any arguments supplied will be simply ignored
1818 and discarded, without being evaluated.
1919
20 | (bind find (macro (self args env)
21 | (bind-args (alist key) args env
22 | (if (equal? alist (literal ())) (literal ())
23 | (if (equal? key (head (head alist)))
24 | (head alist)
25 | (self (tail alist) key)))))
26 | (prepend
27 | (find (env find) (literal symbol?))
28 | (find (env (goofah whatever)) (literal prepend))))
29 = ((symbol? symbol?) prepend prepend)
20 /| (bind find (macro (self args env)
21 /| (bind-args (alist key) args env
22 /| (if (equal? alist (literal ())) (literal ())
23 /| (if (equal? key (head (head alist)))
24 /| (head alist)
25 /| (self (tail alist) key)))))
26 /| (prepend
27 /| (find (env find) (literal symbol?))
28 /| (find (env (goofah whatever)) (literal prepend))))
29 /= ((symbol? symbol?) prepend prepend)
3030
3131 '<<SPEC'
3232
33 (define env (macro (self args env) env))
33 (define env (macro (args env) env))
3535 '<<SPEC'
3636
3737 (define export
38 (macro (self args env)
38 (macro (args env)
3939 (filter (fun (binding) (elem? (head binding) args)) env)))
8282
8383 '<<SPEC'
8484
85 (define fun (macro (self args env)
86 (bind extend-with-args (macro (self args env)
87 (bind-args (env-to-extend formals actuals env-for-actuals) args env
85 (define fun (macro (args env)
86 (bind extend-with-args (macro (args env)
87 (bind-args (self env-to-extend formals actuals env-for-actuals) args env
8888 (if (equal? formals ())
8989 (if (equal? actuals ())
9090 env-to-extend
100100 (binding (list formal evaled-actual))
101101 (extended-env (prepend binding env-to-extend))
102102 )
103 (self extended-env rest-formals rest-actuals env-for-actuals))))))
104 (macro (iself iargs ienv)
103 (self self extended-env rest-formals rest-actuals env-for-actuals))))))
104 (macro (iargs ienv)
105105 (recover (extend-with-args env (head args) iargs ienv)
106106 extended-env (eval extended-env (head (tail args)))
107107 error (abort error))))))
5252
5353 '<<SPEC'
5454
55 (define gt? (macro (self args env)
56 (bind cmp-same-sign? (macro (self args env)
55 (define gt? (macro (args env)
56 (bind cmp-same-sign? (macro (args env)
5757 (bind-args (a b c) args env
5858 (equal? (sign (subtract a b)) c)))
5959 (bind-args (a b) args env
3737
3838 '<<SPEC'
3939
40 (define gte? (macro (self args env)
40 (define gte? (macro (args env)
4141 (bind-args (a b) args env
4242 (if (equal? a b) #t (gt? a b)))))
2424
2525 '<<SPEC'
2626
27 (define itoa (macro (self args env)
28 (bind itoa-r (macro (self args env)
29 (bind-args (val) args env
27 (define itoa (macro (args env)
28 (bind itoa-r (macro (args env)
29 (bind-args (self val) args env
3030 (if (equal? val 0)
3131 ()
3232 (let ((digit (remainder val 10))
3333 (rest (divide val 10)))
34 (prepend (add 48 digit) (self rest))))))
34 (prepend (add 48 digit) (self self rest))))))
3535 (bind-args (val) args env
3636 (if (equal? val 0)
3737 (list 48)
3838 (if (lt? val 0)
39 (prepend 45 (reverse (itoa-r (subtract 0 val))))
40 (reverse (itoa-r val))))))))
39 (prepend 45 (reverse (itoa-r itoa-r (subtract 0 val))))
40 (reverse (itoa-r itoa-r val))))))))
1515
1616 `let` can bind a symbol to a macro.
1717
18 | (let ((a (macro (self args env)
18 | (let ((a (macro (args env)
1919 | (let ((x (eval env (head args)))
2020 | (y (eval env (head (tail args)))))
2121 | (prepend y x)))))
2525 Bindings established in a `let` remain in effect when evaluating
2626 the arguments things in the body of the `let`.
2727
28 | (let ((dup (macro (self args env)
28 | (let ((dup (macro (args env)
2929 | (bind x (eval env (head args))
3030 | (list x x)))))
3131 | (dup (dup (literal g))))
9696
9797 '<<SPEC'
9898
99 (define let (macro (self args env)
99 (define let (macro (args env)
100100 (bind bindings (head args)
101101 (if (equal? bindings ())
102102 (eval env (head (tail args)))
2222
2323 '<<SPEC'
2424
25 (define list (macro (self args env)
25 (define list (macro (args env)
2626 (if (equal? args ())
2727 ()
2828 (prepend (eval env (head args))
5252
5353 '<<SPEC'
5454
55 (define lt? (macro (self args env)
56 (bind cmp-same-sign? (macro (self args env)
55 (define lt? (macro (args env)
56 (bind cmp-same-sign? (macro (args env)
5757 (bind-args (a b c) args env
5858 (equal? (sign (subtract a b)) c)))
5959 (bind-args (a b) args env
3737
3838 '<<SPEC'
3939
40 (define lte? (macro (self args env)
40 (define lte? (macro (args env)
4141 (bind-args (a b) args env
4242 (if (equal? a b) #t (lt? a b)))))
66 `macro?` evaluates its argument, then evaluates to `#t` if it is a macro,
77 or `#f` if it is not.
88
9 | (macro? (macro (self args env) args))
9 | (macro? (macro (args env) args))
1010 = #t
1111
1212 Intrinsic macros are macros.
1616
1717 Literal symbols are not macros, even if they're the name of one.
1818
19 | (macro? ((macro (self args env) (head args)) macro))
19 | (macro? ((macro (args env) (head args)) macro))
2020 = #f
2121
2222 Numbers are not macros.
99 value.
1010
1111 When this macro value is evaluated, the first formal argument will
12 be bound to the macro itself, the second will be bound to the
13 literal, unevaluated list of arguments passed to the macro, and the
14 third will be bound to an alist representing the environment in
15 effect at the point the macro value is evaluated.
12 be bound to the literal, unevaluated list of arguments passed to the
13 macro, and the second will be bound to an alist representing the
14 environment in effect at the point the macro value is evaluated.
1615
17 These formals are conventionally called `self`, `args`, and `env`,
16 These formals are conventionally called `args` and `env`,
1817 but different names can be chosen in the `macro` definition, for
1918 instance to avoid shadowing.
2019
2120 `literal`, in fact, can be defined as a macro, and it is one of the
2221 simplest possible macros that can be written:
2322
24 | ((macro (self args env) (head args)) (why hello there))
23 | ((macro (args env) (head args)) (why hello there))
2524 = (why hello there)
2625
2726 Another facility that can be defined simply by a macro is `env`:
2827
29 (define env (macro (s a e) e))
28 (define env (macro (a e) e))
3029
3130 These tests are written against the "small" library, which defines
3231 both of these symbols (and a few others such as `bind` and `let`).
3837
3938 | ((let
4039 | ((a (literal these-are))
41 | (m (macro (self args env) (prepend a args))))
40 | (m (macro (args env) (prepend a args))))
4241 | m) my args)
4342 = (these-are my args)
4443
4544 Macros can return macros.
4645
4746 | (let
48 | ((mk (macro (self argsa env)
49 | (macro (self argsb env)
47 | ((mk (macro (argsa env)
48 | (macro (argsb env)
5049 | (prepend (head argsb) argsa))))
5150 | (mk2 (mk vindaloo)))
5251 | (mk2 chicken))
5655
5756 | (let
5857 | ((args (literal a))
59 | (b (macro (self args env) (prepend args args))))
58 | (b (macro (args env) (prepend args args))))
6059 | (b 7))
6160 = ((7) 7)
6261
63 `self` is there to let you write recursive macros. The following
64 example demonstrates this; it evaluates `(prepend b d)` in an environment
65 where all the identifiers you list after `qqq` have been bound to 0.
62 /`self` is there to let you write recursive macros. The following
63 /example demonstrates this; it evaluates `(prepend b d)` in an environment
64 /where all the identifiers you list after `qqq` have been bound to 0.
65 /
66 / | (bind qqq
67 / | (macro (self args env)
68 / | (if (equal? args ())
69 / | (eval env (literal (prepend b (prepend d ()))))
70 / | (eval (prepend (prepend (head args) (prepend 0 ())) env)
71 / | (prepend self (tail args)))))
72 / | (bind b 1 (bind d 4 (qqq b c d))))
73 / = (0 0)
74 /
75 / | (bind qqq
76 / | (macro (self args env)
77 / | (if (equal? args ())
78 / | (eval env (literal (prepend b (prepend d ()))))
79 / | (eval (prepend (prepend (head args) (prepend 0 ())) env)
80 / | (prepend self (tail args)))))
81 / | (bind b 1 (bind d 4 (qqq x y z))))
82 / = (1 4)
6683
67 | (bind qqq
68 | (macro (self args env)
69 | (if (equal? args ())
70 | (eval env (literal (prepend b (prepend d ()))))
71 | (eval (prepend (prepend (head args) (prepend 0 ())) env)
72 | (prepend self (tail args)))))
73 | (bind b 1 (bind d 4 (qqq b c d))))
74 = (0 0)
75
76 | (bind qqq
77 | (macro (self args env)
78 | (if (equal? args ())
79 | (eval env (literal (prepend b (prepend d ()))))
80 | (eval (prepend (prepend (head args) (prepend 0 ())) env)
81 | (prepend self (tail args)))))
82 | (bind b 1 (bind d 4 (qqq x y z))))
83 = (1 4)
84
85 A recursive `macro` application doesn't have to be tail-recursive.
86
87 | (bind make-env
88 | (macro (self args env)
89 | (if (equal? args ())
90 | ()
91 | (prepend (prepend (head args)
92 | (prepend (eval env (head args)) ()))
93 | (eval env
94 | (prepend self (tail args))))))
95 | (bind b 1 (bind d 4 (make-env b d macro))))
96 = ((b 1) (d 4) (macro macro))
84 /A recursive `macro` application doesn't have to be tail-recursive.
85 /
86 / | (bind make-env
87 / | (macro (self args env)
88 / | (if (equal? args ())
89 / | ()
90 / | (prepend (prepend (head args)
91 / | (prepend (eval env (head args)) ()))
92 / | (eval env
93 / | (prepend self (tail args))))))
94 / | (bind b 1 (bind d 4 (make-env b d macro))))
95 / = ((b 1) (d 4) (macro macro))
9796
9897 `macro` expects exactly two arguments.
9998
100 | ((macro (self args env)) (why hello there))
101 ? abort (illegal-arguments ((self args env)))
99 | ((macro (args env)) (why hello there))
100 ? abort (illegal-arguments ((args env)))
102101
103 | ((macro (self args env) prepend prepend) (why hello there))
104 ? abort (illegal-arguments ((self args env) prepend prepend))
102 | ((macro (args env) prepend prepend) (why hello there))
103 ? abort (illegal-arguments ((args env) prepend prepend))
105104
106 `macro` expects its first argument to be a list of exactly three
105 `macro` expects its first argument to be a list of exactly two
107106 symbols.
108107
109108 | ((macro 100 prepend) (why hello there))
110109 ? abort (illegal-arguments (100 prepend))
111110
112 | ((macro (self args) prepend) (why hello there))
113 ? abort (illegal-arguments ((self args) prepend))
111 | ((macro (args) prepend) (why hello there))
112 ? abort (illegal-arguments ((args) prepend))
114113
115 | ((macro (self args env foo) prepend) (why hello there))
116 ? abort (illegal-arguments ((self args env foo) prepend))
117
118 | ((macro (self args 99) prepend) (why hello there))
119 ? abort (illegal-arguments ((self args 99) prepend))
114 | ((macro (args env foo) prepend) (why hello there))
115 ? abort (illegal-arguments ((args env foo) prepend))
120116
121117 '<<SPEC'
122118
1313 very productive. (Also, it exposes the implementation of `map`, so this
1414 is not a very good test.)
1515
16 | (map (macro (self args env) args) (literal (three dog night)))
16 | (map (macro (args env) args) (literal (three dog night)))
1717 = (((head li)) ((head li)) ((head li)))
1818
1919 '<<SPEC'
3434
3535 '<<SPEC'
3636
37 (define multiply (macro (self args env)
37 (define multiply (macro (args env)
3838 (bind multiply-r (fun (self a b) ;(b must be positive)
3939 (if (equal? b 1)
4040 a
2525
2626 '<<SPEC'
2727
28 (define not (macro (self args env)
28 (define not (macro (args env)
2929 (bind-args (a) args env
3030 (if a #f #t))))
4141
4242 '<<SPEC'
4343
44 (define or (macro (self args env)
44 (define or (macro (args env)
4545 (if (equal? (tail (tail args)) ())
4646 (if (eval env (head args))
4747 #t
3232 in the context of a `recover`, it will still be recovered.
3333
3434 | (recover
35 | ((macro (self args env) (abort (literal (nasty-value 1111)))) joe)
35 | ((macro (args env) (abort (literal (nasty-value 1111)))) joe)
3636 | value (list value #t)
3737 | error (list error #f))
3838 = ((nasty-value 1111) #f)
4646
4747 '<<SPEC'
4848
49 (define remainder (macro (self args env)
49 (define remainder (macro (args env)
5050 (bind remainder-r-pos (fun (self n d acc) ;(d is positive)
5151 (if (gt? d n)
5252 n
1616 '<<SPEC'
1717
1818 (define sandbox
19 (macro (self args env)
19 (macro (args env)
2020 (eval (filter (fun (binding) (elem? (head binding) (head args))) env)
2121 (head (tail args)))))
2626 '<<SPEC'
2727
2828 (define unbind
29 (macro (self args env)
29 (macro (args env)
3030 (eval (filter (fun (binding) (if (equal? (head binding) (head args)) #f #t)) env)
3131 (head (tail args)))))
4444 '<<SPEC'
4545
4646 (define unshadow
47 (macro (self args env)
47 (macro (args env)
4848 (bind remove-binding-r (fun (self id li)
4949 (if (empty? li)
5050 li
4040
4141 '<<SPEC'
4242
43 (define xor (macro (self args env)
43 (define xor (macro (args env)
4444 (bind-args (a b) args env
4545 (or (and a (not b)) (and (not a) b)))))