git @ Cat's Eye Technologies Robin / 078fd74
Convert almost everything to use new import syntax. catseye 13 years ago
36 changed file(s) with 595 addition(s) and 572 deletion(s). Raw diff Collapse all Expand all
8282
8383 > loadModules mc Null = do
8484 > return (mc, Env.empty)
85 > loadModules mc (Pair (Symbol name) (Pair version (Pair qualifiers rest))) = do
86 > let (rest', qualified) = case qualifiers of
87 > (Symbol _) -> ((Pair qualifiers rest), False)
88 > _ -> (rest, True)
89 > loadModuleBySpec mc name version qualified rest'
90 > loadModules mc (Pair (Symbol name) (Pair version rest)) = do
91 > loadModuleBySpec mc name version False rest
92
93 > loadModuleBySpec mc name version qualified rest = do
85 > loadModules mc (Pair (Pair (Symbol name) (Pair version qualifiers)) rest) = do
86 > let qualified = case qualifiers of
87 > (Pair (Symbol "*") Null) -> False
88 > Null -> True
9489 > (major, minor) <- parseVersion version
9590 > (mc', nextEnv) <- loadModules mc rest
9691 > (mc'', thisEnv) <- loadModule mc' (name, major, minor) qualified
9792 > return (mc'', Env.union nextEnv thisEnv)
9893
99 > parseVersion (Pair (Number major) (Number minor)) = do
94 > parseVersion (Pair (Number major) (Pair (Number minor) Null)) = do
10095 > case (denominator major, denominator minor) of
10196 > (1, 1) -> return (numerator major, numerator minor)
10297 > _ -> error "version number components can't be fractions"
2121 > legalSymbolic = (char '*' <|> char '-' <|> char '/' <|>
2222 > char '+' <|> char '<' <|> char '>' <|>
2323 > char '<' <|> char '=' <|> char '?' <|>
24 > char '_' <|> char '!' <|> char '$')
24 > char '_' <|> char '!' <|> char '$' <|>
25 > char ':')
2526
2627 > symbol = do
2728 > c <- (letter <|> legalSymbolic)
2121 The `VERSION` gives the version of the Robin semantics in use. It has
2222 the syntax:
2323
24 (NAT . NAT)
24 (NAT NAT)
2525
2626 ...where `NAT` is a natural number (an integer not less than zero.)
2727 More on versions later; the only version of Robin that currently
28 exists is 0.1 (aka `(0 . 1)`), so we'll use that.
28 exists is 0.1 (aka `(0 1)`), so we'll use that.
2929
3030 The list of `MODULE-SPEC`s may be empty. So, without further ado,
3131 here is one of the simplest Robin programs one can write:
3232
33 | (robin (0 . 1) () #t)
33 | (robin (0 1) () #t)
3434 = #t
3535
3636 Versioning
5858 An implementation might, obviously, provide or not provide any
5959 particular version of the language.
6060
61 | (robin (0 . 781) () #t)
62 ? robin: unsupported language version (0 . 781)
61 | (robin (0 781) () #t)
62 ? unsupported language version (0 781)
6363
6464 The Robin semantics brought in by the version number in the `robin`
6565 form include things like datatypes and evaluation rules, and are not
101101 Here is an example of importing a module (but not doing anything
102102 with it.)
103103
104 | (robin (0 . 1) (core (0 . 1)) #t)
104 | (robin (0 1) ((core (0 1))) #t)
105105 = #t
106106
107107 A particular version of a module might, naturally, not be available.
109109 (TODO: The particular error message produced here may differ. Falderal
110110 needs a forigiving-error-message option.)
111111
112 | (robin (0 . 1) (small (0 . 781)) #t)
113 ? robin: module/small_0_781.robin: openFile: does not exist (No such file or directory)
112 | (robin (0 1) ((small (0 781))) #t)
113 ? module/small_0_781.robin: openFile: does not exist (No such file or directory)
114114
115115 And a particular module might, naturally, not even be available.
116116
117 | (robin (0 . 1) (gzgptzgztxxky (1 . 0)) #t)
118 ? robin: module/gzgptzgztxxky_1_0.robin: openFile: does not exist (No such file or directory)
117 | (robin (0 1) ((gzgptzgztxxky (1 0))) #t)
118 ? module/gzgptzgztxxky_1_0.robin: openFile: does not exist (No such file or directory)
119119
120120 And a particular version of a module may rely on a particular version
121121 of the fundamental semantics, so some combinations may not make sense.
122122 For example, if `small` 3.0 relies on Robin 2.0, this will fail
123123 (with a more appropriate error message like "Robin 2.0 required"):
124124
125 | (robin (1 . 0) (small (3 . 0)) #t)
126 ? robin: unsupported language version (1 . 0)
125 | (robin (1 0) ((small (3 0))) #t)
126 ? unsupported language version (1 . 0)
127
128 By default, identifiers are imported qualified.
129
130 | (robin (0 1) ((core (0 1)))
131 | (core:number? 3/5))
132 = #t
133
134 | (robin (0 1) ((core (0 1)))
135 | (number? 3/5))
136 ? undefined identifier number?
137
138 The `*` qualifier imports a module unqualified.
139
140 | (robin (0 1) ((core (0 1) *))
141 | (number? 3/5))
142 = #t
143
144 | (robin (0 1) ((core (0 1) *))
145 | (core:number? 3/5))
146 ? undefined identifier core:number?
127147
128148 Intrinsic Data Types
129149 --------------------
165185 module for this purpose, as it is the most straightforward way to create
166186 a literal symbol in a Robin program.
167187
168 | (robin (0 . 1) (small (0 . 1))
169 | (literal hello))
188 | (robin (0 1) ((small (0 1) *))
189 | (small:literal hello))
170190 = hello
171191
172192 A Robin program is not expected to be able to generate new symbols
201221
202222 For example, 5 is a rational number:
203223
204 | (robin (0 . 1) () 5)
224 | (robin (0 1) () 5)
205225 = 5
206226
207227 The literal syntax for rational numbers allows one to use `/` to
208228 denote a fraction:
209229
210 | (robin (0 . 1) () 4/5)
230 | (robin (0 1) () 4/5)
211231 = 4/5
212232
213233 Rational numbers always evaluate to themselves.
250270 Macros are represented as the S-expression expansion of their
251271 implementation, except in the case of built-in macros.
252272
253 | (robin (0 . 1) (core (0 . 1))
254 | (macro (self args env) args))
273 | (robin (0 1) ((core (0 1)))
274 | (core:macro (self args env) args))
255275 = (macro (self args env) args)
256276
257277 A built-in macro is represented thusly. (TODO: this representation
258278 has problems; see section on pairs below.)
259279
260 | (robin (0 . 1) (core (0 . 1))
261 | pair)
280 | (robin (0 1) ((core (0 1)))
281 | core:pair)
262282 = (builtin pair)
263283
264284 One upshot of built-in macros is that *all* intrinsic Robin functionality,
265285 even things that in Scheme are special forms, can be passed around as
266286 values.
267287
268 | (robin (0 . 1) (core (0 . 1))
288 | (robin (0 1) ((core (0 1) *))
269289 | (pair if head))
270290 = ((builtin if) . (builtin head))
271291
279299
280300 TODO: write more about this.
281301
282 | (robin (0 . 1) (small (0 . 1))
283 | (literal (7 . 8)))
302 | (robin (0 1) ((small (0 1)))
303 | (small:literal (7 . 8)))
284304 = (7 . 8)
285305
286306 Representations of some types (like built-in macros) look funny because they
287307 don't follow the rules for depicting pairs with a dot and lists without --
288308 effectively, the parens are "fake" on these things.
289309
290 | (robin (0 . 1) (core (0 . 1))
310 | (robin (0 1) ((core (0 1) *))
291311 | (pair #f boolean?))
292312 = (#f . (builtin boolean?))
293313
313333 Unlike Scheme, you do not need to quote `()`; it evaluates to itself
314334 rather than indicating an illegal empty application.
315335
316 | (robin (0 . 1) () ())
336 | (robin (0 1) () ())
317337 = ()
318338
319339 ### Alists ###
339359 specifying literal strings. The characters of the string are given
340360 between pairs of single quotes.
341361
342 | (robin (0 . 1) (small (0 . 1))
362 | (robin (0 1) ((small (0 1) *))
343363 | (literal ''Hello''))
344364 = (72 101 108 108 111)
345365
346366 A single single quote may appear in string literals of this kind.
347367
348 | (robin (0 . 1) (small (0 . 1))
368 | (robin (0 1) ((small (0 1) *))
349369 | (literal ''He'llo''))
350370 = (72 101 39 108 108 111)
351371
354374 match the sentinel given between the trailing single quote pair. The
355375 sentinel may consist of any text not containing a single quote.
356376
357 | (robin (0 . 1) (small (0 . 1))
377 | (robin (0 1) ((small (0 1) *))
358378 | (literal 'X'Hello'X'))
359379 = (72 101 108 108 111)
360380
361 | (robin (0 . 1) (small (0 . 1))
381 | (robin (0 1) ((small (0 1) *))
362382 | (literal '...@('Hello'...@('))
363383 = (72 101 108 108 111)
364384
365 | (robin (0 . 1) (small (0 . 1))
385 | (robin (0 1) ((small (0 1) *))
366386 | (literal 'X'Hello'Y'))
367387 ? (line 3, column 1):
368388 ? unexpected end of input
370390
371391 A sentinelized literal like this may embed a pair of single quotes.
372392
373 | (robin (0 . 1) (small (0 . 1))
393 | (robin (0 1) ((small (0 1) *))
374394 | (literal 'X'Hel''lo'X'))
375395 = (72 101 108 39 39 108 111)
376396
377397 By choosing different sentinels, string literals may contain any other
378398 string literal.
379399
380 | (robin (0 . 1) (small (0 . 1))
400 | (robin (0 1) ((small (0 1) *))
381401 | (literal 'X'Hel'Y'bye'Y'lo'X'))
382402 = (72 101 108 39 89 39 98 121 101 39 89 39 108 111)
383403
385405 (Functions to convert escape sequences commonly found in other languages
386406 may one day be available in a standard module.)
387407
388 | (robin (0 . 1) (small (0 . 1))
408 | (robin (0 1) ((small (0 1) *))
389409 | (literal ''Hello\nworld''))
390410 = (72 101 108 108 111 92 110 119 111 114 108 100)
391411
392412 All characters which appear in the source text between the delimiters
393413 of the string literal are literally included in the string.
394414
395 | (robin (0 . 1) (small (0 . 1))
415 | (robin (0 1) ((small (0 1) *))
396416 | (literal ''Hello
397417 | world''))
398418 = (72 101 108 108 111 10 119 111 114 108 100)
399419
400420 Adjacent string literals are not automatically concatenated.
401421
402 | (robin (0 . 1) (small (0 . 1))
422 | (robin (0 1) ((small (0 1) *))
403423 | (literal (''Hello'' ''world'')))
404424 = ((72 101 108 108 111) (119 111 114 108 100))
405425
406426 A string literal may appear in the tail of an improper list.
407427
408 | (robin (0 . 1) (small (0 . 1))
428 | (robin (0 1) ((small (0 1) *))
409429 | (literal (a b c . ''123'')))
410430 = (a b c 49 50 51)
411431
415435 Any S-expression preceded by a `;` symbol is a comment. It will still
416436 be parsed, but it will be ignored.
417437
418 | (robin (0 . 1) (core (0 . 1))
438 | (robin (0 1) ((core (0 1) *))
419439 | ;(this program produces a pair of booleans)
420440 | (pair #f #f))
421441 = (#f . #f)
423443 Because S-expressions may nest, and because comments may appear
424444 inside S-expressions, comments may nest.
425445
426 | (robin (0 . 1) (core (0 . 1))
446 | (robin (0 1) ((core (0 1) *))
427447 | ;(this program produces
428448 | ;(what you might call)
429449 | a pair of booleans)
432452
433453 Comments are still parsed. A syntax error in a comment is an error.
434454
435 | (robin (0 . 1) (core (0 . 1))
455 | (robin (0 1) ((core (0 1) *))
436456 | ;(this program produces
437457 | #k
438458 | a pair of booleans)
443463
444464 Any number of comments may appear together.
445465
446 | (robin (0 . 1) (core (0 . 1))
466 | (robin (0 1) ((core (0 1) *))
447467 | (pair ;what ;on ;earth #f #f))
448468 = (#f . #f)
449469
450470 Comments may appear before a closing parenthesis.
451471
452 | (robin (0 . 1) (core (0 . 1))
472 | (robin (0 1) ((core (0 1) *))
453473 | (pair #f #f ;foo))
454474 = (#f . #f)
455475
456 | (robin (0 . 1) (core (0 . 1))
476 | (robin (0 1) ((core (0 1) *))
457477 | (pair #f #f ;peace ;(on) ;earth))
458478 = (#f . #f)
459479
460480 Comments may appear in the tail of an improper list.
461481
462 | (robin (0 . 1) (small (0 . 1))
482 | (robin (0 1) ((core (0 1) *))
463483 | (literal (a . ;foo b)))
464484 = (a . b)
465485
466 | (robin (0 . 1) (small (0 . 1))
486 | (robin (0 1) ((core (0 1) *))
467487 | (literal (a . ;warp ;factor ;7 b)))
468488 = (a . b)
469489
470 | (robin (0 . 1) (small (0 . 1))
490 | (robin (0 1) ((core (0 1) *))
471491 | (literal (a . b ;foo)))
472492 = (a . b)
473493
474 | (robin (0 . 1) (small (0 . 1))
494 | (robin (0 1) ((core (0 1) *))
475495 | (literal (a . b ;warp ;factor ;7)))
476496 = (a . b)
477497
478498 Comments may appear in an empty list.
479499
480 | (robin (0 . 1) ()
500 | (robin (0 1) ()
481501 | ( ;hi ;there))
482502 = ()
483503
484504 Comments need not be preceded by spaces.
485505
486 | (robin (0 . 1) ()
506 | (robin (0 1) ()
487507 | (;north;by;north;west))
488508 = ()
489509
490510 To put truly arbitrary text in a comment, the string sugar syntax may be
491511 used.
492512
493 | (robin (0 . 1) (core (0 . 1))
513 | (robin (0 1) ((core (0 1) *))
494514 | ;''This program, it produces a pair of booleans. #k ?''
495515 | (pair #f #f))
496516 = (#f . #f)
117117 test program which simply imports all of those modules; if any of them
118118 fail static analysis, an exception will be thrown at import time:
119119
120 (robin (0 . 1) (foo (0 . 1) bar (0 . 1) baz (0 . 1))
120 (robin (0 1) ((foo (0 1) *) (bar (0 1) *) (baz (0 1) *))
121121 #t)
122122
123123 There is also room here for optimization. If static analysis for a module
99
1010 ### `+` ###
1111
12 | (robin (0 . 1) (arith (0 . 1))
12 | (robin (0 1) ((arith (0 1) *))
1313 | (+ 14 23))
1414 = 37
1515
1616 ### `-` ###
1717
18 | (robin (0 . 1) (arith (0 . 1))
18 | (robin (0 1) ((arith (0 1) *))
1919 | (- 23 10))
2020 = 13
2121
2222 ### `*` ###
2323
24 | (robin (0 . 1) (arith (0 . 1))
24 | (robin (0 1) ((arith (0 1) *))
2525 | (* 23 10))
2626 = 230
2727
2828 ### `/` ###
2929
30 | (robin (0 . 1) (arith (0 . 1))
30 | (robin (0 1) ((arith (0 1) *))
3131 | (/ 33 11))
3232 = 3
3333
3434 ### `abs` ###
3535
36 | (robin (0 . 1) (arith (0 . 1))
36 | (robin (0 1) ((arith (0 1) *))
3737 | (abs 5))
3838 = 5
3939
40 | (robin (0 . 1) (arith (0 . 1))
40 | (robin (0 1) ((arith (0 1) *))
4141 | (abs (- 0 5)))
4242 = 5
4343
44 | (robin (0 . 1) (arith (0 . 1))
44 | (robin (0 1) ((arith (0 1) *))
4545 | (abs 0))
4646 = 0
4747
4848 ### `frac` ###
4949
50 | (robin (0 . 1) (arith (0 . 1))
50 | (robin (0 1) ((arith (0 1) *))
5151 | (frac 6/5))
5252 = 1/5
5353
54 | (robin (0 . 1) (arith (0 . 1))
54 | (robin (0 1) ((arith (0 1) *))
5555 | (frac (- 0 6/5)))
5656 = 1/5
5757
58 | (robin (0 . 1) (arith (0 . 1))
58 | (robin (0 1) ((arith (0 1) *))
5959 | (frac 8))
6060 = 0
6161
6262 ### `integer?` ###
6363
64 | (robin (0 . 1) (arith (0 . 1))
64 | (robin (0 1) ((arith (0 1) *))
6565 | (integer? 6/5))
6666 = #f
6767
68 | (robin (0 . 1) (arith (0 . 1))
68 | (robin (0 1) ((arith (0 1) *))
6969 | (integer? 8))
7070 = #t
7171
72 | (robin (0 . 1) (arith (0 . 1))
72 | (robin (0 1) ((arith (0 1) *))
7373 | (integer? 0))
7474 = #t
7575
76 | (robin (0 . 1) (arith (0 . 1))
76 | (robin (0 1) ((arith (0 1) *))
7777 | (integer? (- 0 8)))
7878 = #t
7979
8080 ### `div` ###
8181
82 | (robin (0 . 1) (arith (0 . 1))
82 | (robin (0 1) ((arith (0 1) *))
8383 | (div 100 3))
8484 = 33
8585
86 | (robin (0 . 1) (arith (0 . 1))
86 | (robin (0 1) ((arith (0 1) *))
8787 | (div (- 0 100) 3))
8888 = -34
8989
90 | (robin (0 . 1) (arith (0 . 1))
90 | (robin (0 1) ((arith (0 1) *))
9191 | (div 100 (- 0 3)))
9292 = -34
9393
94 | (robin (0 . 1) (arith (0 . 1))
94 | (robin (0 1) ((arith (0 1) *))
9595 | (div 1001/10 3))
9696 = 33
9797
98 | (robin (0 . 1) (arith (0 . 1))
98 | (robin (0 1) ((arith (0 1) *))
9999 | (div 100 10/3))
100100 = 33
101101
102 | (robin (0 . 1) (arith (0 . 1))
102 | (robin (0 1) ((arith (0 1) *))
103103 | (div 10 0))
104104 ? uncaught exception: (division-by-zero . 10)
105105
106106 ### `rem` ###
107107
108 | (robin (0 . 1) (arith (0 . 1))
108 | (robin (0 1) ((arith (0 1) *))
109109 | (rem 12 3))
110110 = 0
111111
112 | (robin (0 . 1) (arith (0 . 1))
112 | (robin (0 1) ((arith (0 1) *))
113113 | (rem 11 3))
114114 = 2
115115
116 | (robin (0 . 1) (arith (0 . 1))
116 | (robin (0 1) ((arith (0 1) *))
117117 | (rem 10 3))
118118 = 1
119119
120 | (robin (0 . 1) (arith (0 . 1))
120 | (robin (0 1) ((arith (0 1) *))
121121 | (rem 9 3))
122122 = 0
123123
124 | (robin (0 . 1) (arith (0 . 1))
124 | (robin (0 1) ((arith (0 1) *))
125125 | (rem (- 0 10) 3))
126126 = 2
127127
128 | (robin (0 . 1) (arith (0 . 1))
128 | (robin (0 1) ((arith (0 1) *))
129129 | (rem 10 (- 0 3)))
130130 = -2
131131
132 | (robin (0 . 1) (arith (0 . 1))
132 | (robin (0 1) ((arith (0 1) *))
133133 | (rem 10 0))
134134 ? uncaught exception: (division-by-zero . 10)
135135
136136 ### `>` ###
137137
138 | (robin (0 . 1) (arith (0 . 1))
138 | (robin (0 1) ((arith (0 1) *))
139139 | (> 6 4))
140140 = #t
141141
142 | (robin (0 . 1) (arith (0 . 1))
142 | (robin (0 1) ((arith (0 1) *))
143143 | (> 6 8))
144144 = #f
145145
146 | (robin (0 . 1) (arith (0 . 1))
146 | (robin (0 1) ((arith (0 1) *))
147147 | (> 6 6))
148148 = #f
149149
150150 ### `<` ###
151151
152 | (robin (0 . 1) (arith (0 . 1))
152 | (robin (0 1) ((arith (0 1) *))
153153 | (< 6 4))
154154 = #f
155155
156 | (robin (0 . 1) (arith (0 . 1))
156 | (robin (0 1) ((arith (0 1) *))
157157 | (< 6 8))
158158 = #t
159159
160 | (robin (0 . 1) (arith (0 . 1))
160 | (robin (0 1) ((arith (0 1) *))
161161 | (< 6 6))
162162 = #f
163163
164164 ### `>=` ###
165165
166 | (robin (0 . 1) (arith (0 . 1))
166 | (robin (0 1) ((arith (0 1) *))
167167 | (>= 6 4))
168168 = #t
169169
170 | (robin (0 . 1) (arith (0 . 1))
170 | (robin (0 1) ((arith (0 1) *))
171171 | (>= 6 8))
172172 = #f
173173
174 | (robin (0 . 1) (arith (0 . 1))
174 | (robin (0 1) ((arith (0 1) *))
175175 | (>= 6 6))
176176 = #t
177177
178178 ### `<=` ###
179179
180 | (robin (0 . 1) (arith (0 . 1))
180 | (robin (0 1) ((arith (0 1) *))
181181 | (<= 6 4))
182182 = #f
183183
184 | (robin (0 . 1) (arith (0 . 1))
184 | (robin (0 1) ((arith (0 1) *))
185185 | (<= 6 8))
186186 = #t
187187
188 | (robin (0 . 1) (arith (0 . 1))
188 | (robin (0 1) ((arith (0 1) *))
189189 | (<= 6 6))
190190 = #t
191191
192192 ### `natural?` ###
193193
194 | (robin (0 . 1) (arith (0 . 1))
194 | (robin (0 1) ((arith (0 1) *))
195195 | (natural? 6/5))
196196 = #f
197197
198 | (robin (0 . 1) (arith (0 . 1))
198 | (robin (0 1) ((arith (0 1) *))
199199 | (natural? 8))
200200 = #t
201201
202 | (robin (0 . 1) (arith (0 . 1))
202 | (robin (0 1) ((arith (0 1) *))
203203 | (natural? 0))
204204 = #t
205205
206 | (robin (0 . 1) (arith (0 . 1))
206 | (robin (0 1) ((arith (0 1) *))
207207 | (natural? (- 0 8)))
208208 = #f
99
1010 ### `assert` ###
1111
12 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
12 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
1313 | (assert (equal? 5 5) 7))
1414 = 7
1515
16 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
16 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
1717 | (assert (equal? 5 6) 7))
1818 ? uncaught exception: (assertion-failed equal? 5 6)
1919
2020 ### `assert-boolean` ###
2121
22 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
22 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
2323 | (assert-boolean #f 4))
2424 = 4
2525
26 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
26 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
2727 | (assert-boolean 4 #f))
2828 ? uncaught exception: (expected-boolean . 4)
2929
3030 ### `assert-number` ###
3131
32 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
32 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
3333 | (assert-number 4 #f))
3434 = #f
3535
36 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
36 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
3737 | (assert-number #f 4))
3838 ? uncaught exception: (expected-number . #f)
3939
4040 ### `assert-symbol` ###
4141
42 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
42 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
4343 | (assert-symbol (literal captain) (literal tennille)))
4444 = tennille
4545
46 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
46 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
4747 | (assert-symbol 7 (literal what)))
4848 ? uncaught exception: (expected-symbol . 7)
4949
5050 ### `assert-pair` ###
5151
52 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
52 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
5353 | (assert-pair (pair 1 2) #t))
5454 = #t
5555
56 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
56 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
5757 | (assert-pair #t (pair 1 2)))
5858 ? uncaught exception: (expected-pair . #t)
5959
6060 ### `assert-macro` ###
6161
62 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
62 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
6363 | (assert-macro literal (literal it-is)))
6464 = it-is
6565
66 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
66 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
6767 | (assert-macro (macro (self args env) args) (literal it-is)))
6868 = it-is
6969
70 | (robin (0 . 1) (small (0 . 1) assert (0 . 1))
70 | (robin (0 1) ((small (0 1) *) (assert (0 1) *))
7171 | (assert-macro 7 (literal what)))
7272 ? uncaught exception: (expected-macro . 7)
99
1010 ### `and` ###
1111
12 | (robin (0 . 1) (boolean (0 . 1))
12 | (robin (0 1) ((boolean (0 1) *))
1313 | (and #t #t))
1414 = #t
1515
16 | (robin (0 . 1) (boolean (0 . 1))
16 | (robin (0 1) ((boolean (0 1) *))
1717 | (and #t #f))
1818 = #f
1919
20 | (robin (0 . 1) (boolean (0 . 1))
20 | (robin (0 1) ((boolean (0 1) *))
2121 | (and #f #t))
2222 = #f
2323
24 | (robin (0 . 1) (boolean (0 . 1))
24 | (robin (0 1) ((boolean (0 1) *))
2525 | (and #f #f))
2626 = #f
2727
2828 `and` can take any number of arguments.
2929
30 | (robin (0 . 1) (boolean (0 . 1))
30 | (robin (0 1) ((boolean (0 1) *))
3131 | (and))
3232 = #t
3333
34 | (robin (0 . 1) (boolean (0 . 1))
34 | (robin (0 1) ((boolean (0 1) *))
3535 | (and #f))
3636 = #f
3737
38 | (robin (0 . 1) (boolean (0 . 1))
38 | (robin (0 1) ((boolean (0 1) *))
3939 | (and #t #t #t #t #t))
4040 = #t
4141
42 | (robin (0 . 1) (boolean (0 . 1))
42 | (robin (0 1) ((boolean (0 1) *))
4343 | (and #t #t #t #f))
4444 = #f
4545
4949
5050 ### `or` ###
5151
52 | (robin (0 . 1) (boolean (0 . 1))
52 | (robin (0 1) ((boolean (0 1) *))
5353 | (or #t #t))
5454 = #t
5555
56 | (robin (0 . 1) (boolean (0 . 1))
56 | (robin (0 1) ((boolean (0 1) *))
5757 | (or #t #f))
5858 = #t
5959
60 | (robin (0 . 1) (boolean (0 . 1))
60 | (robin (0 1) ((boolean (0 1) *))
6161 | (or #f #t))
6262 = #t
6363
64 | (robin (0 . 1) (boolean (0 . 1))
64 | (robin (0 1) ((boolean (0 1) *))
6565 | (or #f #f))
6666 = #f
6767
6868 `or` can take any number of arguments.
6969
70 | (robin (0 . 1) (boolean (0 . 1))
70 | (robin (0 1) ((boolean (0 1) *))
7171 | (or))
7272 = #f
7373
74 | (robin (0 . 1) (boolean (0 . 1))
74 | (robin (0 1) ((boolean (0 1) *))
7575 | (or #t))
7676 = #t
7777
78 | (robin (0 . 1) (boolean (0 . 1))
78 | (robin (0 1) ((boolean (0 1) *))
7979 | (or #f #f #f #f #f))
8080 = #f
8181
82 | (robin (0 . 1) (boolean (0 . 1))
82 | (robin (0 1) ((boolean (0 1) *))
8383 | (or #f #f #f #t))
8484 = #t
8585
8989
9090 ### `not` ###
9191
92 | (robin (0 . 1) (boolean (0 . 1))
92 | (robin (0 1) ((boolean (0 1) *))
9393 | (not #t))
9494 = #f
9595
96 | (robin (0 . 1) (boolean (0 . 1))
96 | (robin (0 1) ((boolean (0 1) *))
9797 | (not #f))
9898 = #t
9999
100 | (robin (0 . 1) (boolean (0 . 1))
100 | (robin (0 1) ((boolean (0 1) *))
101101 | (not #t #f))
102102 ? uncaught exception: (illegal-arguments #f)
103103
104104 ### `xor` ###
105105
106 | (robin (0 . 1) (boolean (0 . 1))
106 | (robin (0 1) ((boolean (0 1) *))
107107 | (xor #t #t))
108108 = #f
109109
110 | (robin (0 . 1) (boolean (0 . 1))
110 | (robin (0 1) ((boolean (0 1) *))
111111 | (xor #t #f))
112112 = #t
113113
114 | (robin (0 . 1) (boolean (0 . 1))
114 | (robin (0 1) ((boolean (0 1) *))
115115 | (xor #f #t))
116116 = #t
117117
118 | (robin (0 . 1) (boolean (0 . 1))
118 | (robin (0 1) ((boolean (0 1) *))
119119 | (xor #f #f))
120120 = #f
121121
122122 This test demonstrates that these functions really do evaluate their
123123 arguments.
124124
125 | (robin (0 . 1) (boolean (0 . 1))
125 | (robin (0 1) ((boolean (0 1) *))
126126 | (and (or (xor (and #t #t) #f) #f) #t))
127127 = #t
3939
4040 `myself` expects exactly zero arguments.
4141
42 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
42 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
4343 | (myself 123))
4444 ? uncaught exception: (illegal-arguments 123)
4545
4848 `pid?` evaluates its argument, then evaluates to `#t` if that value
4949 is a process identifier, `#f` otherwise.
5050
51 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
51 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
5252 | (pid? (literal b)))
5353 = #f
5454
55 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
55 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
5656 | (pid? (myself)))
5757 = #t
5858
5959 The argument to `pid?` may naturally be of any type, but there
6060 must be exactly one argument.
6161
62 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
62 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
6363 | (pid?))
6464 ? uncaught exception: (illegal-arguments)
6565
66 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
66 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
6767 | (pid? 200 500))
6868 ? uncaught exception: (illegal-arguments 200 500)
6969
7575 proceeds to evaluate its third argument, in the current process, with
7676 that new binding.
7777
78 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
78 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
7979 | (spawn! worker (literal ok)
8080 | (pid? worker)))
8181 = #t
8282
83 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
83 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
8484 | (spawn! worker (literal ok)
8585 | (equal? (myself) worker)))
8686 = #f
8787
8888 `spawn!` takes exactly three arguments.
8989
90 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
90 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
9191 | (spawn!))
9292 ? uncaught exception: (illegal-arguments)
9393
94 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
94 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
9595 | (spawn! cheesecake))
9696 ? uncaught exception: (illegal-arguments cheesecake)
9797
98 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
98 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
9999 | (spawn! (fun (x) 0) (fun (x) 1)))
100100 ? uncaught exception: (illegal-arguments (fun (x) 0) (fun (x) 1))
101101
102 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
102 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
103103 | (spawn! (fun (x) 0) (fun (x) 1)
104104 | (fun (x) 2) (fun (x) 3)))
105105 ? uncaught exception: (illegal-arguments (fun (x) 0) (fun (x) 1) (fun (x) 2) (fun (x) 3))
106106
107107 The first argument to `spawn!` must be a symbol.
108108
109 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
109 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
110110 | (spawn! #f (literal ok) 123))
111111 ? uncaught exception: (illegal-arguments #f (literal ok) 123)
112112
117117 the process identified by the pid, then evaluates its third argument
118118 and itself evaluates to that.
119119
120 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
120 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
121121 | (spawn! worker (literal ok)
122122 | (send! worker (literal spam) (literal ok))))
123123 = ok
124124
125125 `send!` expects its first argument to be a pid.
126126
127 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
127 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
128128 | (send! (literal eggs) (literal spam) (literal ok)))
129129 ? uncaught exception: (expected-pid . eggs)
130130
131131 `send!` expects exactly three arguments.
132132
133 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
133 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
134134 | (spawn! worker (literal ok)
135135 | (send! worker worker)))
136136 ? uncaught exception: (illegal-arguments worker worker)
137137
138 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
138 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
139139 | (spawn! worker (literal ok)
140140 | (send! worker worker worker worker)))
141141 ? uncaught exception: (illegal-arguments worker worker worker worker)
147147 its first argument to the value so received, and evaluates its second
148148 argument, and itself evaluates to that.
149149
150 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
150 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
151151 | (bind parent (myself)
152152 | (spawn! worker (send! parent (literal lettuce) (literal ok))
153153 | (recv! message (pair message message)))))
157157 is a case of illegal arguments, as the identifier is not an expression
158158 that must evaluate to a certain type.)
159159
160 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
160 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
161161 | (bind parent (myself)
162162 | (spawn! worker (send! parent (literal lettuce) (literal ok))
163163 | (recv! (pair 7 8) 9))))
165165
166166 `recv!` expects exactly two arguments.
167167
168 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
168 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
169169 | (bind parent (myself)
170170 | (spawn! worker (send! parent (literal lettuce) (literal ok))
171171 | (recv! message))))
172172 ? uncaught exception: (illegal-arguments message)
173173
174 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
174 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
175175 | (bind parent (myself)
176176 | (spawn! worker (send! parent (literal lettuce) (literal ok))
177177 | (recv! message message message))))
181181
182182 A process we spawned can send our message back to us.
183183
184 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
184 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
185185 | (bind parent (myself)
186186 | (spawn! worker (recv! message (send! parent message 123))
187187 | (send! worker (literal whoopie)
190190
191191 A process we spawned can receive multiple messages.
192192
193 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
193 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
194194 | (bind parent (myself)
195195 | (spawn! worker
196196 | (recv! message1
204204 A process we spawned will terminate while waiting for a message, if the
205205 main process terminates.
206206
207 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
207 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
208208 | (bind parent (myself)
209209 | (spawn! worker
210210 | (recv! message1
216216
217217 A spawned process can spawn processes of its own.
218218
219 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
219 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
220220 | (bind parent (myself)
221221 | (spawn! worker
222222 | (bind subparent (myself)
229229 A process can send messages to any process it knows about, not just
230230 its parent.
231231
232 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
232 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
233233 | (bind parent (myself)
234234 | (spawn! worker
235235 | (spawn! subworker
241241 send!s a message to this effect to the process that spawn!ed it,
242242 immediately before terminating.
243243
244 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
244 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
245245 | (bind parent (myself)
246246 | (spawn! worker
247247 | (bind x (head ())
254254 `msgs?` evaluates to `#t` if the current process has one or more messages
255255 waiting in its queue, `#f` otherwise.
256256
257 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
257 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
258258 | (msgs?))
259259 = #f
260260
261261 X Note: it's hard to write this test without a race condition...
262262 X
263 X | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
263 X | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
264264 X | (bind parent (myself)
265265 X | (spawn! (send! parent (literal lettuce) (literal ok)) worker
266266 X | (msgs?))))
268268
269269 `msgs?` expects exactly zero arguments.
270270
271 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
271 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
272272 | (msgs? #t))
273273 ? uncaught exception: (illegal-arguments #t)
274274
277277 `call!` combines `send!` and `recv!` to accomplish synchronous communication
278278 with another process.
279279
280 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
280 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
281281 | (spawn! worker
282282 | (recv! message
283283 | (let ((sender (head message))
294294 not finish. Note: this is an awful test, because an implementation
295295 may in fact hang instead of doing what our implementation does.
296296
297 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
297 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
298298 | (bind parent (myself) (spawn! worker
299299 | (recv! message
300300 | (let ((sender (head message))
307307 | (pair (literal reply-was) reply)))))
308308 ? thread blocked indefinitely in an MVar operation
309309
310 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
310 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
311311 | (bind parent (myself) (spawn! worker
312312 | (recv! message
313313 | (let ((send!er (head message))
325325 behavior or what (it's an exception message from any process,
326326 currently!) but... we'll see.
327327
328 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
328 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
329329 | (spawn! worker
330330 | (recv! message
331331 | (let ((send!er (head message))
338338
339339 `call!` expects its first argument to be a pid.
340340
341 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
341 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
342342 | (call! (literal worker) this-tag (literal this-payload) reply
343343 | (pair (literal reply-was) reply)))
344344 ? uncaught exception: (expected-pid . worker)
345345
346346 `call!` expects its second argument to be a symbol.
347347
348 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
348 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
349349 | (call! (myself) #f (literal this-payload) reply
350350 | (pair (literal reply-was) reply)))
351351 ? uncaught exception: (illegal-arguments (myself) #f (literal this-payload) reply (pair (literal reply-was) reply))
352352
353353 `call!` expects its fourth argument to be an identifier.
354354
355 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
355 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
356356 | (call! (myself) this-tag (literal this-payload) #f
357357 | (pair (literal reply-was) reply)))
358358 ? uncaught exception: (illegal-arguments (myself) this-tag (literal this-payload) #f (pair (literal reply-was) reply))
365365 the appropriate branch, sends a reply message to the pid that `call!`ed it,
366366 and evaluates the tail of the branch.
367367
368 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
368 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
369369 | (spawn! worker
370370 | (respond!
371371 | (donkey (x) (literal kong) (literal ok))
375375
376376 The payload of the `call!` is available in the bound variable.
377377
378 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
378 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
379379 | (spawn! worker
380380 | (respond!
381381 | (donkey (x) (literal kong) (literal ok))
385385
386386 `respond!` respond!s to only one message.
387387
388 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
388 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
389389 | (spawn! worker
390390 | (respond!
391391 | (donkey (x) (literal kong) (literal ok))
396396
397397 Typicall!y, to write a server, you would use it in a loop.
398398
399 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
399 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
400400 | (bind work-fun (fun (self)
401401 | (respond!
402402 | (donkey (x) (literal kong) (self self))
411411
412412 `respond!` evaluates to the appropriate tail.
413413
414 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1))
414 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *))
415415 | (bind parent (myself) (spawn! worker
416416 | (call! parent take 71 reply (literal ok))
417417 | (respond!
1515 `pair` evaluates both of its arguments, then evaluates to a pair which
1616 contains both of those values, in the same order.
1717
18 | (robin (0 . 1) (core (0 . 1))
18 | (robin (0 1) ((core (0 1) *))
1919 | (pair #t #f))
2020 = (#t . #f)
2121
22 | (robin (0 . 1) (core (0 . 1))
22 | (robin (0 1) ((core (0 1) *))
2323 | (pair #t (pair #f ())))
2424 = (#t #f)
2525
2626 Arguments to `pair` can be any type, but fewer than or more than
2727 two arguments will raise an exception.
2828
29 | (robin (0 . 1) (core (0 . 1))
29 | (robin (0 1) ((core (0 1) *))
3030 | (pair #t))
3131 ? uncaught exception: (illegal-arguments #t)
3232
33 | (robin (0 . 1) (core (0 . 1))
33 | (robin (0 1) ((core (0 1) *))
3434 | (pair #f #t #f))
3535 ? uncaught exception: (illegal-arguments #f #t #f)
3636
4141 `head` evaluates its argument to a pair, and evaluates to the first element
4242 of that pair.
4343
44 | (robin (0 . 1) (core (0 . 1))
44 | (robin (0 1) ((core (0 1) *))
4545 | (head (pair #t #f)))
4646 = #t
4747
4848 `head` expects its argument to be a pair.
4949
50 | (robin (0 . 1) (core (0 . 1))
50 | (robin (0 1) ((core (0 1) *))
5151 | (head #f))
5252 ? uncaught exception: (expected-pair . #f)
5353
5454 `head` expects exactly one argument.
5555
56 | (robin (0 . 1) (core (0 . 1))
56 | (robin (0 1) ((core (0 1) *))
5757 | (head (pair #t #f) (pair #f #t)))
5858 ? uncaught exception: (illegal-arguments (pair #t #f) (pair #f #t))
5959
60 | (robin (0 . 1) (core (0 . 1))
60 | (robin (0 1) ((core (0 1) *))
6161 | (head))
6262 ? uncaught exception: (illegal-arguments)
6363
6868 `tail` evaluates its argument to a pair, and evaluates to the second element
6969 of that pair.
7070
71 | (robin (0 . 1) (core (0 . 1))
71 | (robin (0 1) ((core (0 1) *))
7272 | (tail (pair #t #f)))
7373 = #f
7474
7575 `tail` expects its argument to be a pair.
7676
77 | (robin (0 . 1) (core (0 . 1))
77 | (robin (0 1) ((core (0 1) *))
7878 | (tail #f))
7979 ? uncaught exception: (expected-pair . #f)
8080
8181 `tail` expects exactly one argument.
8282
83 | (robin (0 . 1) (core (0 . 1))
83 | (robin (0 1) ((core (0 1) *))
8484 | (tail (pair #t #f) (pair #f #t)))
8585 ? uncaught exception: (illegal-arguments (pair #t #f) (pair #f #t))
8686
87 | (robin (0 . 1) (core (0 . 1))
87 | (robin (0 1) ((core (0 1) *))
8888 | (tail))
8989 ? uncaught exception: (illegal-arguments)
9090
9797 is `#f` it evaluates, and evaluates to, its third argument. In all cases,
9898 at most two arguments are evaluated.
9999
100 | (robin (0 . 1) (core (0 . 1))
100 | (robin (0 1) ((core (0 1) *))
101101 | (if #t 7 9))
102102 = 7
103103
104 | (robin (0 . 1) (core (0 . 1))
104 | (robin (0 1) ((core (0 1) *))
105105 | (if #f 7 9))
106106 = 9
107107
108108 The second and third arguments can be arbitrary expressions, but `if`
109109 expects its first argument to be a boolean.
110110
111 | (robin (0 . 1) (core (0 . 1))
111 | (robin (0 1) ((core (0 1) *))
112112 | (if 5 7 9))
113113 ? uncaught exception: (expected-boolean . 5)
114114
115115 `if` expects exactly three arguments.
116116
117 | (robin (0 . 1) (core (0 . 1))
117 | (robin (0 1) ((core (0 1) *))
118118 | (if #t 7))
119119 ? uncaught exception: (illegal-arguments #t 7)
120120
121 | (robin (0 . 1) (core (0 . 1))
121 | (robin (0 1) ((core (0 1) *))
122122 | (if #t 7 8 9))
123123 ? uncaught exception: (illegal-arguments #t 7 8 9)
124124
125125 The identifiers named in the branch which is not evaluated need not be
126126 properly bound to values in the environment.
127127
128 | (robin (0 . 1) (core (0 . 1))
128 | (robin (0 1) ((core (0 1) *))
129129 | (if #t 1 (pair fred ethel)))
130130 = 1
131131
136136
137137 `equal?` works on symbols.
138138
139 | (robin (0 . 1) (core (0 . 1))
139 | (robin (0 1) ((core (0 1) *))
140140 | (equal?
141141 | ((macro (s a e) (head a)) this-symbol)
142142 | ((macro (s a e) (head a)) this-symbol)))
143143 = #t
144144
145 | (robin (0 . 1) (core (0 . 1))
145 | (robin (0 1) ((core (0 1) *))
146146 | (equal?
147147 | ((macro (s a e) (head a)) this-symbol)
148148 | ((macro (s a e) (head a)) that-symbol)))
150150
151151 `equal?` works on lists.
152152
153 | (robin (0 . 1) (core (0 . 1))
153 | (robin (0 1) ((core (0 1) *))
154154 | (equal? (pair 1 (pair 2 (pair 3 ())))
155155 | (pair 1 (pair 2 (pair 3 ())))))
156156 = #t
157157
158158 Two values of different types are never equal.
159159
160 | (robin (0 . 1) (core (0 . 1))
160 | (robin (0 1) ((core (0 1) *))
161161 | (equal? #t
162162 | (pair ((macro (self args env) (head args)) a) ())))
163163 = #f
164164
165 | (robin (0 . 1) (core (0 . 1))
165 | (robin (0 1) ((core (0 1) *))
166166 | (equal? #f
167167 | ()))
168168 = #f
170170 Arguments to `equal?` can be any type, but fewer than or more than
171171 two arguments will raise an exception.
172172
173 | (robin (0 . 1) (core (0 . 1))
173 | (robin (0 1) ((core (0 1) *))
174174 | (equal? 7))
175175 ? uncaught exception: (illegal-arguments 7)
176176
177 | (robin (0 . 1) (core (0 . 1))
177 | (robin (0 1) ((core (0 1) *))
178178 | (equal? 7 8 9))
179179 ? uncaught exception: (illegal-arguments 7 8 9)
180180
183183 `pair?` evaluates its argument, then evaluates to `#t` if it is a pair,
184184 `#f` otherwise.
185185
186 | (robin (0 . 1) (core (0 . 1))
186 | (robin (0 1) ((core (0 1) *))
187187 | (pair? ((macro (self args env) (head args)) (a . b))))
188188 = #t
189189
190 | (robin (0 . 1) (core (0 . 1))
190 | (robin (0 1) ((core (0 1) *))
191191 | (pair? ((macro (self args env) (head args)) (a b c d e f))))
192192 = #t
193193
194 | (robin (0 . 1) (core (0 . 1))
194 | (robin (0 1) ((core (0 1) *))
195195 | (pair? (pair 4 5)))
196196 = #t
197197
198198 Symbols are not pairs.
199199
200 | (robin (0 . 1) (core (0 . 1))
200 | (robin (0 1) ((core (0 1) *))
201201 | (pair? ((macro (self args env) (head args)) b)))
202202 = #f
203203
204204 The argument to `pair?` may (naturally) be any type, but there must be
205205 exactly one argument.
206206
207 | (robin (0 . 1) (core (0 . 1))
207 | (robin (0 1) ((core (0 1) *))
208208 | (pair? (pair 4 5) (pair 6 7)))
209209 ? uncaught exception: (illegal-arguments (pair 4 5) (pair 6 7))
210210
213213 `macro?` evaluates its argument, then evaluates to `#t` if it is a macro
214214 (either built-in or user-defined), or `#f` if it is not.
215215
216 | (robin (0 . 1) (core (0 . 1))
216 | (robin (0 1) ((core (0 1) *))
217217 | (macro? (macro (self args env) args)))
218218 = #t
219219
220 | (robin (0 . 1) (core (0 . 1))
220 | (robin (0 1) ((core (0 1) *))
221221 | (macro? macro))
222222 = #t
223223
224 | (robin (0 . 1) (core (0 . 1))
224 | (robin (0 1) ((core (0 1) *))
225225 | (macro? ((macro (self args env) (head args)) macro)))
226226 = #f
227227
228 | (robin (0 . 1) (core (0 . 1))
228 | (robin (0 1) ((core (0 1) *))
229229 | (macro? 4/5))
230230 = #f
231231
232232 The argument to `macro?` may (naturally) be any type, but there must be
233233 exactly one argument.
234234
235 | (robin (0 . 1) (core (0 . 1))
235 | (robin (0 1) ((core (0 1) *))
236236 | (macro? macro macro))
237237 ? uncaught exception: (illegal-arguments macro macro)
238238
241241 `symbol?` evaluates its argument, then evaluates to `#t` if it is a symbol,
242242 `#f` otherwise.
243243
244 | (robin (0 . 1) (core (0 . 1))
244 | (robin (0 1) ((core (0 1) *))
245245 | (symbol? ((macro (s a e) (head a)) this-symbol)))
246246 = #t
247247
248248 Pairs are not symbols.
249249
250 | (robin (0 . 1) (core (0 . 1))
250 | (robin (0 1) ((core (0 1) *))
251251 | (symbol? (pair 1 2)))
252252 = #f
253253
254254 The argument to `symbol?` may (naturally) be any type, but there must be
255255 exactly one argument.
256256
257 | (robin (0 . 1) (core (0 . 1))
257 | (robin (0 1) ((core (0 1) *))
258258 | (symbol? 77 88))
259259 ? uncaught exception: (illegal-arguments 77 88)
260260
263263 `boolean?` evaluates its argument, then evaluates to `#t` if it is a
264264 boolean value, `#f` otherwise.
265265
266 | (robin (0 . 1) (core (0 . 1))
266 | (robin (0 1) ((core (0 1) *))
267267 | (boolean? #t))
268268 = #t
269269
270 | (robin (0 . 1) (core (0 . 1))
270 | (robin (0 1) ((core (0 1) *))
271271 | (boolean? #f))
272272 = #t
273273
274 | (robin (0 . 1) (core (0 . 1))
274 | (robin (0 1) ((core (0 1) *))
275275 | (boolean? ()))
276276 = #f
277277
278278 The argument to `symbol?` may (naturally) be any type, but there must be
279279 exactly one argument.
280280
281 | (robin (0 . 1) (core (0 . 1))
281 | (robin (0 1) ((core (0 1) *))
282282 | (boolean? #t #f))
283283 ? uncaught exception: (illegal-arguments #t #f)
284284
287287 `number?` evaluates its argument, then evaluates to `#t` if it is a
288288 rational number, `#f` otherwise.
289289
290 | (robin (0 . 1) (core (0 . 1))
290 | (robin (0 1) ((core (0 1) *))
291291 | (number? 5/7))
292292 = #t
293293
294 | (robin (0 . 1) (core (0 . 1))
294 | (robin (0 1) ((core (0 1) *))
295295 | (number? 0))
296296 = #t
297297
298 | (robin (0 . 1) (core (0 . 1))
298 | (robin (0 1) ((core (0 1) *))
299299 | (number? ()))
300300 = #f
301301
302 | (robin (0 . 1) (core (0 . 1))
302 | (robin (0 1) ((core (0 1) *))
303303 | (number? #t))
304304 = #f
305305
306306 The argument to `number?` may (naturally) be any type, but there must be
307307 exactly one argument.
308308
309 | (robin (0 . 1) (core (0 . 1))
309 | (robin (0 1) ((core (0 1) *))
310310 | (number? 6 4))
311311 ? uncaught exception: (illegal-arguments 6 4)
312312
316316 evaluates its second argument to a rational number, then evaluates
317317 to the difference between the first and second numbers.
318318
319 | (robin (0 . 1) (core (0 . 1))
319 | (robin (0 1) ((core (0 1) *))
320320 | (subtract 6 4))
321321 = 2
322322
323 | (robin (0 . 1) (core (0 . 1))
323 | (robin (0 1) ((core (0 1) *))
324324 | (subtract 16/15 1/5))
325325 = 13/15
326326
327 | (robin (0 . 1) (core (0 . 1))
327 | (robin (0 1) ((core (0 1) *))
328328 | (subtract 1000 8000))
329329 = -7000
330330
331331 Addition may be accomplished by negating the second argument.
332332
333 | (robin (0 . 1) (core (0 . 1))
333 | (robin (0 1) ((core (0 1) *))
334334 | (subtract 999 (subtract 0 999)))
335335 = 1998
336336
337337 `subtract` expects both of its arguments to be numbers.
338338
339 | (robin (0 . 1) (core (0 . 1))
339 | (robin (0 1) ((core (0 1) *))
340340 | (subtract #f 100))
341341 ? uncaught exception: (expected-number . #f)
342342
343 | (robin (0 . 1) (core (0 . 1))
343 | (robin (0 1) ((core (0 1) *))
344344 | (subtract 100 ()))
345345 ? uncaught exception: (expected-number)
346346
347347 `subtract` expects exactly two arguments.
348348
349 | (robin (0 . 1) (core (0 . 1))
349 | (robin (0 1) ((core (0 1) *))
350350 | (subtract 100 200 300))
351351 ? uncaught exception: (illegal-arguments 100 200 300)
352352
353 | (robin (0 . 1) (core (0 . 1))
353 | (robin (0 1) ((core (0 1) *))
354354 | (subtract))
355355 ? uncaught exception: (illegal-arguments)
356356
360360 evaluates its second argument to a rational number, then evaluates
361361 to the ratio between the first and second numbers.
362362
363 | (robin (0 . 1) (core (0 . 1))
363 | (robin (0 1) ((core (0 1) *))
364364 | (divide 99 11))
365365 = 9
366366
367 | (robin (0 . 1) (core (0 . 1))
367 | (robin (0 1) ((core (0 1) *))
368368 | (divide 6 4))
369369 = 3/2
370370
371 | (robin (0 . 1) (core (0 . 1))
371 | (robin (0 1) ((core (0 1) *))
372372 | (divide 4 (subtract 0 5)))
373373 = -4/5
374374
377377 Addition may be accomplished by taking the reciprocal of the second
378378 argument.
379379
380 | (robin (0 . 1) (core (0 . 1))
380 | (robin (0 1) ((core (0 1) *))
381381 | (divide 123 0))
382382 ? uncaught exception: (division-by-zero . 123)
383383
384384 Addition may be accomplished by taking the reciprocal of the second
385385 argument.
386386
387 | (robin (0 . 1) (core (0 . 1))
387 | (robin (0 1) ((core (0 1) *))
388388 | (divide 7 (divide 1 7)))
389389 = 49
390390
391391 `divide` expects both of its arguments to be numbers.
392392
393 | (robin (0 . 1) (core (0 . 1))
393 | (robin (0 1) ((core (0 1) *))
394394 | (divide #f 100))
395395 ? uncaught exception: (expected-number . #f)
396396
397 | (robin (0 . 1) (core (0 . 1))
397 | (robin (0 1) ((core (0 1) *))
398398 | (divide 100 ()))
399399 ? uncaught exception: (expected-number)
400400
401401 `divide` expects exactly two arguments.
402402
403 | (robin (0 . 1) (core (0 . 1))
403 | (robin (0 1) ((core (0 1) *))
404404 | (divide 100 200 300))
405405 ? uncaught exception: (illegal-arguments 100 200 300)
406406
407 | (robin (0 . 1) (core (0 . 1))
407 | (robin (0 1) ((core (0 1) *))
408408 | (divide))
409409 ? uncaught exception: (illegal-arguments)
410410
413413 `floor` evaluates its sole argument to a rational number, then
414414 evaluates to the nearest whole number not larger than that rational.
415415
416 | (robin (0 . 1) (core (0 . 1))
416 | (robin (0 1) ((core (0 1) *))
417417 | (floor 26/5))
418418 = 5
419419
420 | (robin (0 . 1) (core (0 . 1))
420 | (robin (0 1) ((core (0 1) *))
421421 | (floor 5))
422422 = 5
423423
424 | (robin (0 . 1) (core (0 . 1))
424 | (robin (0 1) ((core (0 1) *))
425425 | (floor (subtract 0 1/2)))
426426 = -1
427427
428 | (robin (0 . 1) (core (0 . 1))
428 | (robin (0 1) ((core (0 1) *))
429429 | (floor 100 200 300))
430430 ? uncaught exception: (illegal-arguments 100 200 300)
431431
432 | (robin (0 . 1) (core (0 . 1))
432 | (robin (0 1) ((core (0 1) *))
433433 | (floor))
434434 ? uncaught exception: (illegal-arguments)
435435
439439 evaluates to 0 if that number is 0, 1 if that number is positive, or
440440 -1 if that number is negative.
441441
442 | (robin (0 . 1) (core (0 . 1))
442 | (robin (0 1) ((core (0 1) *))
443443 | (sign 26/5))
444444 = 1
445445
446 | (robin (0 . 1) (core (0 . 1))
446 | (robin (0 1) ((core (0 1) *))
447447 | (sign 0))
448448 = 0
449449
450 | (robin (0 . 1) (core (0 . 1))
450 | (robin (0 1) ((core (0 1) *))
451451 | (sign (subtract 0 200)))
452452 = -1
453453
454 | (robin (0 . 1) (core (0 . 1))
454 | (robin (0 1) ((core (0 1) *))
455455 | (sign 100 200 300))
456456 ? uncaught exception: (illegal-arguments 100 200 300)
457457
458 | (robin (0 . 1) (core (0 . 1))
458 | (robin (0 1) ((core (0 1) *))
459459 | (sign))
460460 ? uncaught exception: (illegal-arguments)
461461
469469 sake of purity, that dependency should be removed (but the tests
470470 will look awful.)
471471
472 | (robin (0 . 1) (small (0 . 1))
472 | (robin (0 1) ((small (0 1) *))
473473 | (eval (env) (literal (pair (literal a) (literal b)))))
474474 = (a . b)
475475
476 | (robin (0 . 1) (small (0 . 1))
476 | (robin (0 1) ((small (0 1) *))
477477 | (eval () (literal (pair (literal a) (literal b)))))
478478 ? uncaught exception: (unbound-identifier . pair)
479479
480 | (robin (0 . 1) (small (0 . 1))
480 | (robin (0 1) ((small (0 1) *))
481481 | (bind bindings (pair
482482 | (pair (literal same) equal?)
483483 | (pair (pair (literal x) #f) (literal ())))
488488 alist passed to `eval`, the one closer to the front of the alist takes
489489 precedence.
490490
491 | (robin (0 . 1) (small (0 . 1))
491 | (robin (0 1) ((small (0 1) *))
492492 | (bind bindings (pair
493493 | (pair (literal foo) (literal yes))
494494 | (pair (pair (literal foo) (literal no))
500500 environment, however, subsequent evaluation will fail when it
501501 tries to look up things in that environment.
502502
503 | (robin (0 . 1) (small (0 . 1))
503 | (robin (0 1) ((small (0 1) *))
504504 | (eval 103 (literal (pair (literal a) (literal b)))))
505505 ? uncaught exception: (expected-pair . 103)
506506
507507 Evaluation expects the contents of the list which makes up the
508508 environment to be pairs.
509509
510 | (robin (0 . 1) (small (0 . 1))
510 | (robin (0 1) ((small (0 1) *))
511511 | (eval (pair #f ()) (literal (pair (literal a) (literal b)))))
512512 ? uncaught exception: (expected-pair . #f)
513513
514514 Evaluation expects the head of each pair in the list which makes up the
515515 environment to be a symbol.
516516
517 | (robin (0 . 1) (small (0 . 1))
517 | (robin (0 1) ((small (0 1) *))
518518 | (eval (pair (pair 7 #f) ()) (literal (pair (literal a) (literal b)))))
519519 ? uncaught exception: (expected-symbol . 7)
520520
521521 `eval` expects exactly two arguments.
522522
523 | (robin (0 . 1) (core (0 . 1))
523 | (robin (0 1) ((core (0 1) *))
524524 | (eval))
525525 ? uncaught exception: (illegal-arguments)
526526
527 | (robin (0 . 1) (core (0 . 1))
527 | (robin (0 1) ((core (0 1) *))
528528 | (eval 4 5 6))
529529 ? uncaught exception: (illegal-arguments 4 5 6)
530530
548548 `literal`, in fact, can be defined as a macro, and it is one of the
549549 simplest possible macros that can be written:
550550
551 | (robin (0 . 1) (core (0 . 1))
551 | (robin (0 1) ((core (0 1) *))
552552 | ((macro (self args env) (head args)) (why hello there)))
553553 = (why hello there)
554554
556556 macro is defined will still be in force when the macro is applied,
557557 even if they are no longer lexically in scope.
558558
559 | (robin (0 . 1) (small (0 . 1))
559 | (robin (0 1) ((small (0 1) *))
560560 | ((let
561561 | ((a (literal these-are))
562562 | (m (macro (self args env) (pair a args))))
565565
566566 Macros can return macros.
567567
568 | (robin (0 . 1) (small (0 . 1))
568 | (robin (0 1) ((small (0 1) *))
569569 | (let
570570 | ((mk (macro (self argsa env)
571571 | (macro (self argsb env)
576576
577577 Arguments to macros shadow any other bindings in effect.
578578
579 | (robin (0 . 1) (small (0 . 1))
579 | (robin (0 1) ((small (0 1) *))
580580 | (let
581581 | ((args (literal a))
582582 | (b (macro (self args env) (pair args args))))
591591 sake of purity, that dependency should be removed (but the tests
592592 will look awful.)
593593
594 | (robin (0 . 1) (small (0 . 1))
594 | (robin (0 1) ((small (0 1) *))
595595 | (bind qqq
596596 | (macro (self args env)
597597 | (if (equal? args ())
601601 | (bind b 1 (bind d 4 (qqq b c d)))))
602602 = (0 . 0)
603603
604 | (robin (0 . 1) (small (0 . 1))
604 | (robin (0 1) ((small (0 1) *))
605605 | (bind qqq
606606 | (macro (self args env)
607607 | (if (equal? args ())
613613
614614 Your recursive `macro` application doesn't have to be tail-recursive.
615615
616 | (robin (0 . 1) (small (0 . 1))
616 | (robin (0 1) ((small (0 1) *))
617617 | (bind make-env
618618 | (macro (self args env)
619619 | (if (equal? args ())
626626
627627 `macro` expects exactly two arguments.
628628
629 | (robin (0 . 1) (core (0 . 1))
629 | (robin (0 1) ((core (0 1) *))
630630 | ((macro (self args env)) (why hello there)))
631631 ? uncaught exception: (illegal-arguments (self args env))
632632
633 | (robin (0 . 1) (core (0 . 1))
633 | (robin (0 1) ((core (0 1) *))
634634 | ((macro (self args env) pair pair) (why hello there)))
635635 ? uncaught exception: (illegal-arguments (self args env) pair pair)
636636
637637 `macro` expects its first argument to be a list of exactly three
638638 symbols.
639639
640 | (robin (0 . 1) (core (0 . 1))
640 | (robin (0 1) ((core (0 1) *))
641641 | ((macro 100 pair) (why hello there)))
642642 ? uncaught exception: (illegal-arguments 100 pair)
643643
644 | (robin (0 . 1) (core (0 . 1))
644 | (robin (0 1) ((core (0 1) *))
645645 | ((macro (self args) pair) (why hello there)))
646646 ? uncaught exception: (illegal-arguments (self args) pair)
647647
648 | (robin (0 . 1) (core (0 . 1))
648 | (robin (0 1) ((core (0 1) *))
649649 | ((macro (self args env foo) pair) (why hello there)))
650650 ? uncaught exception: (illegal-arguments (self args env foo) pair)
651651
652 | (robin (0 . 1) (core (0 . 1))
652 | (robin (0 1) ((core (0 1) *))
653653 | ((macro (self args 99) pair) (why hello there)))
654654 ? uncaught exception: (illegal-arguments (self args 99) pair)
655655
666666 refers to the exception that triggered it, but this is not a strict
667667 requirement.
668668
669 | (robin (0 . 1) (core (0 . 1))
669 | (robin (0 1) ((core (0 1) *))
670670 | (raise 999999))
671671 ? uncaught exception: 999999
672672
673673 `raise`'s single argument may be any kind of value, but `raise` expects
674674 exactly one argument.
675675
676 | (robin (0 . 1) (core (0 . 1))
676 | (robin (0 1) ((core (0 1) *))
677677 | (raise))
678678 ? uncaught exception: (illegal-arguments)
679679
680 | (robin (0 . 1) (core (0 . 1))
680 | (robin (0 1) ((core (0 1) *))
681681 | (raise 2 3 4))
682682 ? uncaught exception: (illegal-arguments 2 3 4)
683683
685685
686686 `with` attaches metadata to a value.
687687
688 | (robin (0 . 1) (core (0 . 1))
688 | (robin (0 1) ((core (0 1) *))
689689 | (with #t 5))
690690 = 5
691691
692692 Passing values with metadata attached shouldn't break any of the core
693693 macros.
694694
695 | (robin (0 . 1) (core (0 . 1))
695 | (robin (0 1) ((core (0 1) *))
696696 | (head (with #t (pair 1 2))))
697697 = 1
698698
699 | (robin (0 . 1) (core (0 . 1))
699 | (robin (0 1) ((core (0 1) *))
700700 | (tail (with #t (pair 1 2))))
701701 = 2
702702
703 | (robin (0 . 1) (core (0 . 1))
703 | (robin (0 1) ((core (0 1) *))
704704 | (pair (with #t 1) (with #t 2)))
705705 = (1 . 2)
706706
707 | (robin (0 . 1) (core (0 . 1))
707 | (robin (0 1) ((core (0 1) *))
708708 | (pair (with #t 1) (with #t 2)))
709709 = (1 . 2)
710710
711 | (robin (0 . 1) (core (0 . 1))
711 | (robin (0 1) ((core (0 1) *))
712712 | (if (with #t #t) (with #t 2) (with #t 3)))
713713 = 2
714714
715 | (robin (0 . 1) (core (0 . 1))
715 | (robin (0 1) ((core (0 1) *))
716716 | (if (with 777 #f) (with #t 2) (with #t 3)))
717717 = 3
718718
719 | (robin (0 . 1) (core (0 . 1))
719 | (robin (0 1) ((core (0 1) *))
720720 | (equal? (with #t 4) (with #t 4)))
721721 = #t
722722
723 | (robin (0 . 1) (core (0 . 1))
723 | (robin (0 1) ((core (0 1) *))
724724 | (pair? (with #t (pair 2 3))))
725725 = #t
726726
727 | (robin (0 . 1) (core (0 . 1))
727 | (robin (0 1) ((core (0 1) *))
728728 | (number? (with #t 3)))
729729 = #t
730730
731 | (robin (0 . 1) (small (0 . 1))
731 | (robin (0 1) ((small (0 1) *))
732732 | (symbol? (with #t (literal x))))
733733 = #t
734734
735 | (robin (0 . 1) (core (0 . 1))
735 | (robin (0 1) ((core (0 1) *))
736736 | (macro? (with #t (macro (self args env) args))))
737737 = #t
738738
739 | (robin (0 . 1) (core (0 . 1))
739 | (robin (0 1) ((core (0 1) *))
740740 | (boolean? (with #t #t)))
741741 = #t
742742
743 | (robin (0 . 1) (core (0 . 1))
743 | (robin (0 1) ((core (0 1) *))
744744 | ((with #t (macro (self args env) args)) foo bar baz))
745745 = (foo bar baz)
746746
747 | (robin (0 . 1) (core (0 . 1))
747 | (robin (0 1) ((core (0 1) *))
748748 | (subtract (with #t 0) (with #f 5)))
749749 = -5
750750
751 | (robin (0 . 1) (core (0 . 1))
751 | (robin (0 1) ((core (0 1) *))
752752 | (divide (with #t 1) (with #f 5)))
753753 = 1/5
754754
755 | (robin (0 . 1) (core (0 . 1))
755 | (robin (0 1) ((core (0 1) *))
756756 | (sign (with #t 1)))
757757 = 1
758758
759 | (robin (0 . 1) (core (0 . 1))
759 | (robin (0 1) ((core (0 1) *))
760760 | (floor (with #t 3/2)))
761761 = 1
762762
763763 Testing for equality ignores metadata.
764764
765 | (robin (0 . 1) (core (0 . 1))
765 | (robin (0 1) ((core (0 1) *))
766766 | (equal? (with #t 4) 4))
767767 = #t
768768
769 | (robin (0 . 1) (core (0 . 1))
769 | (robin (0 1) ((core (0 1) *))
770770 | (equal? 4 (with #t 4)))
771771 = #t
772772
773 | (robin (0 . 1) (core (0 . 1))
773 | (robin (0 1) ((core (0 1) *))
774774 | (equal? (with #t 4) (with #f 4)))
775775 = #t
776776
777 | (robin (0 . 1) (core (0 . 1))
777 | (robin (0 1) ((core (0 1) *))
778778 | (equal? (with #t 4) (with #t 5)))
779779 = #f
780780
782782
783783 `has?` checks if a value has a given metadata.
784784
785 | (robin (0 . 1) (core (0 . 1))
785 | (robin (0 1) ((core (0 1) *))
786786 | (has? #t 4))
787787 = #f
788788
789 | (robin (0 . 1) (core (0 . 1))
789 | (robin (0 1) ((core (0 1) *))
790790 | (has? #t (with #t 4)))
791791 = #t
792792
793 | (robin (0 . 1) (core (0 . 1))
793 | (robin (0 1) ((core (0 1) *))
794794 | (has? #t (head (pair (with #t 4) 5))))
795795 = #t
796796
797797 Binding retains metatdata.
798798
799 | (robin (0 . 1) (small (0 . 1))
799 | (robin (0 1) ((small (0 1) *))
800800 | (bind q (with (literal gee) 77)
801801 | (has? (literal gee) q)))
802802 = #t
803803
804804 Metadata is retained in macros.
805805
806 | (robin (0 . 1) (small (0 . 1))
806 | (robin (0 1) ((small (0 1) *))
807807 | (bind whee
808808 | (macro (self args env)
809809 | (pair (head (head env))
3939 be written to the standard output, and an `ok` message sent back to the
4040 sending process as a confirmation.
4141
42 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
42 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
4343 | (call! crude-output write (literal hello-world) reply reply))
4444 = hello-world
4545 = ok
5353 implementation need not write the result of the main process to the
5454 standard output.
5555
56 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
56 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
5757 | (call! crude-output write (literal hello-world) reply 0))
5858 = hello-world
5959
6161 message will be formatted as a textual S-expression, and written out on
6262 its own line.
6363
64 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
64 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
6565 | (call! crude-output write (literal hello) x
6666 | (call! crude-output write (literal (world 1 2 3)) y
6767 | 0)))
9090 `crude-input` can be subscribed to, and the subscriber will receive
9191 messages when input occurs.
9292
93 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
93 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
9494 | (call! crude-input subscribe () x
9595 | (recv! entered
9696 | (pair (literal i-got) entered))))
100100
101101 Arbitrary S-expressions may occur on each line; they are parsed.
102102
103 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
103 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
104104 | (call! crude-input subscribe () x
105105 | (recv! entered
106106 | (pair (literal i-got) entered))))
110110
111111 Multiple lines of text may be input, and multiple messages will be sent.
112112
113 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
113 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
114114 | (bind input-loop
115115 | (fun (self)
116116 | (recv! entered
129129 If an S-expression on a given line cannot be parsed, no message will be
130130 sent.
131131
132 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
132 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
133133 | (bind input-loop
134134 | (fun (self)
135135 | (recv! entered
2727 of capabilities. Each capability is (for now) a symbol, which refers to
2828 a required capability of the device.
2929
30 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) device (0 . 1))
30 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (device (0 1) *))
3131 | (acquire! (console (ascii colour addressable)
3232 | foo ())
3333 | (pair (pid? console) (pid? foo))))
4343 the device that it will no longer be used by this process. Subsequent
4444 messages sent to the device pid from this process will be ignored.
4545
46 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) device (0 . 1))
46 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (device (0 1) *))
4747 | (acquire! (console (ascii colour addressable))
4848 | (release! console
4949 | 123)))
1616 `env?` evaluates its single argument, and evaluates to `#t` if
1717 and only if it is a well-formed binding alist.
1818
19 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
19 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
2020 | (env? (literal ((a . 1) (b . 2) (c . 3)))))
2121 = #t
2222
23 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
23 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
2424 | (env? (literal ((a . 1) (999 . 2) (c . 3)))))
2525 = #f
2626
27 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
27 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
2828 | (env? (literal ((a . 1) (b . 2) . c))))
2929 = #f
3030
31 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
31 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
3232 | (env? 7))
3333 = #f
3434
35 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
35 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
3636 | (env? (env)))
3737 = #t
3838
4141 `unbind` removes the given identifier from the environment and evaluates its
4242 second argument in that reduced environment.
4343
44 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
44 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
4545 | (unbind if (if #t (literal x) (literal y))))
4646 ? uncaught exception: (unbound-identifier . if)
4747
4848 If the identifier doesn't exist in the environment, no change is made to
4949 the environment.
5050
51 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
51 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
5252 | (unbind yog-sothoth (if #t (literal x) (literal y))))
5353 = x
5454
5656 identifier has several definitions that are shadowed, none of them will be
5757 in effect.
5858
59 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
59 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
6060 | (let ((x 7))
6161 | (let ((x 8))
6262 | (unbind x
6969 its second argument in an environment where all bindings *except* those
7070 for the listed identifiers have been unbound.
7171
72 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
72 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
7373 | (sandbox (pair tail)
7474 | (tail (pair 8 9))))
7575 = 9
7676
77 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
77 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
7878 | (sandbox (pair tail)
7979 | (head (pair 8 9))))
8080 ? uncaught exception: (unbound-identifier . head)
9494 Note: the order of the bindings in the binding alist isn't guaranteed;
9595 these tests should be rewritten to search the resulting alist.
9696
97 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
97 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
9898 | (let ((a 1) (b 2))
9999 | (export a b)))
100100 = ((b . 2) (a . 1))
101101
102 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
102 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
103103 | (export pair tail))
104104 = ((tail . (builtin tail)) (pair . (builtin pair)))
105105
109109 for the given identifier; previously shadowed bindings, if any exist,
110110 will be visible instead.
111111
112 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
112 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
113113 | (unshadow yog-sothoth (if #t (literal x) (literal y))))
114114 = x
115115
116 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
116 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
117117 | (unshadow if (if #t (literal x) (literal y))))
118118 ? uncaught exception: (unbound-identifier . if)
119119
120 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
120 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
121121 | (bind if (literal what)
122122 | (unshadow if (if #t (literal x) (literal y)))))
123123 = x
124124
125 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
125 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
126126 | (bind q 400
127127 | (unshadow q q)))
128128 ? uncaught exception: (unbound-identifier . q)
129129
130 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
130 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
131131 | (bind q 200
132132 | (bind q 400
133133 | (unshadow q q))))
134134 = 200
135135
136 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
136 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
137137 | (bind q 100
138138 | (bind q 200
139139 | (bind q 400
140140 | (unshadow q (unshadow q q))))))
141141 = 100
142142
143 | (robin (0 . 1) (small (0 . 1) env (0 . 1))
143 | (robin (0 1) ((small (0 1) *) (env (0 1) *))
144144 | (let ((q 100)
145145 | (q 200)
146146 | (q 400))
158158 this module re-exports the macro `env` from `core`, and `bind` and `let`
159159 from `small`.
160160
161 | (robin (0 . 1) (env (0 . 1))
161 | (robin (0 1) ((env (0 1) *))
162162 | (env? (env)))
163163 = #t
164164
165 | (robin (0 . 1) (env (0 . 1))
165 | (robin (0 1) ((env (0 1) *))
166166 | (bind a 1 a))
167167 = 1
168168
169 | (robin (0 . 1) (env (0 . 1))
169 | (robin (0 1) ((env (0 1) *))
170170 | (let ((a 7) (b a)) b))
171171 = 7
2525 first argument of `catch`, and the second argument of `catch` is
2626 evaluated in that new environment.
2727
28 | (robin (0 . 1) (small (0 . 1) exception (0 . 1))
28 | (robin (0 1) ((pure (0 1) *) (exception (0 1) *))
2929 | (catch error (pair error #f)
3030 | (raise (literal (nasty-value . 999999)))))
3131 = ((nasty-value . 999999) . #f)
3232
3333 `catch` can catch exceptions raised by core macros.
3434
35 | (robin (0 . 1) (small (0 . 1) exception (0 . 1))
35 | (robin (0 1) ((pure (0 1) *) (exception (0 1) *))
3636 | (catch error (pair error 5)
3737 | (head #f)))
3838 = ((expected-pair . #f) . 5)
3939
4040 The innermost `catch` will catch the exception.
4141
42 | (robin (0 . 1) (small (0 . 1) exception (0 . 1))
42 | (robin (0 1) ((pure (0 1) *) (exception (0 1) *))
4343 | (catch error (pair error 5)
4444 | (catch error (pair error 9)
4545 | (head #f))))
4848 An exception raised from within an exception handler is
4949 caught by the next innermost exception handler.
5050
51 | (robin (0 . 1) (small (0 . 1) exception (0 . 1))
51 | (robin (0 1) ((pure (0 1) *) (exception (0 1) *))
5252 | (catch error (pair error 5)
5353 | (catch error (pair error 9)
5454 | (catch error (raise (pair error error))
5757
5858 `catch` expects its first argument to be an identifier.
5959
60 | (robin (0 . 1) (small (0 . 1) exception (0 . 1))
60 | (robin (0 1) ((pure (0 1) *) (exception (0 1) *))
6161 | (catch #f 23 (head #f)))
6262 ? uncaught exception: (illegal-arguments #f 23 (head #f))
6363
6464 `catch` expects exactly three arguments.
6565
66 | (robin (0 . 1) (small (0 . 1) exception (0 . 1))
66 | (robin (0 1) ((pure (0 1) *) (exception (0 1) *))
6767 | (catch error error))
6868 ? uncaught exception: (illegal-arguments error error)
6969
70 | (robin (0 . 1) (small (0 . 1) exception (0 . 1))
70 | (robin (0 1) ((pure (0 1) *) (exception (0 1) *))
7171 | (catch error error (head #f) 23))
7272 ? uncaught exception: (illegal-arguments error error (head #f) 23)
7373
7676 Because it would be reasonable to find it here by categorization, this
7777 module re-exports the macro `raise` from `core`.
7878
79 | (robin (0 . 1) (exception (0 . 1))
79 | (robin (0 1) ((exception (0 1) *))
8080 | (catch error error (raise 799)))
8181 = 799
1515 `list` is a macro which evaluates each of its arguments, and evaluates to a
1616 (proper) list containing each of the results, in the same order.
1717
18 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
18 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
1919 | (list 1 2 3 4 5))
2020 = (1 2 3 4 5)
2121
22 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
22 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
2323 | (list (pair 2 3) (pair 6 7)))
2424 = ((2 . 3) (6 . 7))
2525
26 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
26 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
2727 | (list 1 2 3 4 . 5))
2828 ? uncaught exception: (expected-pair . 5)
2929
3030 `list` need not have any arguments at all; the result is the empty list.
3131
32 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
32 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
3333 | (list))
3434 = ()
3535
3838 `empty?` evaluates its single argument, and evaluates to `#t` if that value
3939 is the empty list, `#f` otherwise.
4040
41 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
41 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
4242 | (empty? (literal symbol)))
4343 = #f
4444
45 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
45 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
4646 | (empty? ()))
4747 = #t
4848
49 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
49 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
5050 | (empty? (list 1 2 3)))
5151 = #f
5252
5555 `list?` evaluates its single argument, and evaluates to `#t` if that value
5656 is a proper list, `#f` otherwise.
5757
58 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
58 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
5959 | (list? (literal symbol)))
6060 = #f
6161
62 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
62 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
6363 | (list? ()))
6464 = #t
6565
66 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
66 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
6767 | (list? (literal (a b c))))
6868 = #t
6969
70 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
70 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
7171 | (list? (pair 1 2)))
7272 = #f
7373
74 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
74 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
7575 | (list? (literal (a b c . d))))
7676 = #f
7777
8282 the macro to each element of the given list. The macro is generally assumed
8383 to be a one-argument function.
8484
85 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
85 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
8686 | (map (fun (x) (list x)) (literal (three dog night))))
8787 = ((three) (dog) (night))
8888
89 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
89 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
9090 | (map (fun (x) (list x)) (literal (three dog . night))))
9191 ? uncaught exception: (expected-pair . night)
9292
9494 very productive. (Also, it exposes the implementation of `map`, so this
9595 is not a very good test.)
9696
97 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
97 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
9898 | (map (macro (self args env) args) (literal (three dog night))))
9999 = (((head li)) ((head li)) ((head li)))
100100
110110 the second argument. `fold` evaluates to the result of the the final
111111 application of the function.
112112
113 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
113 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
114114 | (fold (fun (x a) x) () (literal (three dog night))))
115115 = night
116116
117 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
117 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
118118 | (fold (fun (x a) a) 541 (literal (archie moffam))))
119119 = 541
120120
121 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
121 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
122122 | (fold (fun (x a) (pair a x)) () (literal (three dog night))))
123123 = (((() . three) . dog) . night)
124124
125 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
125 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
126126 | (fold (fun (x a) a) 1/2 (literal (three dog . night))))
127127 ? uncaught exception: (expected-pair . night)
128128
129 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
129 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
130130 | (fold 1/2 (fun (x a) a) (literal (three dog night))))
131131 ? uncaught exception: (inapplicable-object . 1/2)
132132
136136 is the same as the given list in every respect except that the order of
137137 the elements is reversed.
138138
139 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
139 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
140140 | (reverse (literal (1 2 3 4 5))))
141141 = (5 4 3 2 1)
142142
148148 to a list which contains all the elements of the given list, in the same
149149 order, which satisfy the predicate.
150150
151 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
151 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
152152 | (filter (fun (x) (symbol? x)) (literal (1 two #f 3 () four 5 six))))
153153 = (two four six)
154154
155 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
155 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
156156 | (filter (fun (x) (symbol? x)) (literal (1 two #f 3 () four 5 . six))))
157157 ? uncaught exception: (expected-pair . six)
158158
159 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
159 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
160160 | (filter (fun (x) x) (literal (#t #t #f banana #t #f))))
161161 ? uncaught exception: (expected-boolean . banana)
162162
168168 a list which contains exactly one element, which will be the first
169169 element from the list which satisfies the predicate.
170170
171 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
171 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
172172 | (find (fun (x) (symbol? x)) ()))
173173 = ()
174174
175 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
175 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
176176 | (find (fun (x) (symbol? x)) (list 1 2 3)))
177177 = ()
178178
179 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
179 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
180180 | (find (fun (x) #t) (list 1 2 3)))
181181 = (1)
182182
183 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
183 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
184184 | (find (fun (x) (symbol? x)) (literal (1 two #f 3 () four 5 six))))
185185 = (two)
186186
193193 second argument to obtain a list. It then evaluates to `#t` if the value
194194 is `equal?` to some element of the list, `#f` otherwise.
195195
196 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
196 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
197197 | (elem? (literal p) (literal (a p e))))
198198 = #t
199199
200 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
200 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
201201 | (elem? (literal p) (literal (a r k))))
202202 = #f
203203
204 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
204 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
205205 | (elem? 7 ()))
206206 = #f
207207
208 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
208 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
209209 | (elem? 7 (list 5 (list 6 7) 8)))
210210 = #f
211211
212 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
212 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
213213 | (elem? (literal two) (literal (two four . six))))
214214 = #t
215215
216 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
216 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
217217 | (elem? (literal eight) (literal (two four . six))))
218218 ? uncaught exception: (expected-pair . six)
219219
226226 `append` evaluates both of its arguments to lists. It then
227227 evaluates to a list which is the concatenation of these lists.
228228
229 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
229 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
230230 | (append (list 1 2 3) (list 4 5 6)))
231231 = (1 2 3 4 5 6)
232232
233 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
233 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
234234 | (append () ()))
235235 = ()
236236
237237 The second list may be improper, but the first may not be.
238238
239 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
239 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
240240 | (append (list 1 2 3) (literal (4 5 . 6))))
241241 = (1 2 3 4 5 . 6)
242242
243 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
243 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
244244 | (append (literal (1 2 . 3)) (literal (4 5 6))))
245245 ? uncaught exception: (expected-pair . 3)
246246
251251 (the number of pairs, not counting nested pairs and not counting the
252252 empty list at the very tail.)
253253
254 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
254 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
255255 | (length ()))
256256 = 0
257257
258 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
258 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
259259 | (length (list 1 2 #t #f 3)))
260260 = 5
261261
262 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
262 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
263263 | (length (literal (1 2 #t #f . 3))))
264264 ? uncaught exception: (expected-pair . 3)
265265
266 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
266 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
267267 | (length (literal whatnot)))
268268 ? uncaught exception: (expected-pair . whatnot)
269269
274274 list at the index given by the natural number. The index is 0-based;
275275 0 refers to the element at the head of the list.
276276
277 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
277 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
278278 | (index 0 (literal (the girl from ipanema))))
279279 = the
280280
281 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
281 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
282282 | (index 2 (literal (the girl from ipanema))))
283283 = from
284284
285 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
285 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
286286 | (bind last (fun (li) (index (subtract (length li) 1) li))
287287 | (last (literal (the girl from ipanema)))))
288288 = ipanema
289289
290290 Attempting to index beyond the end of the list will raise an exception.
291291
292 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
292 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
293293 | (index 7 (literal (the girl from ipanema))))
294294 ? uncaught exception: (expected-pair)
295295
296296 `index` expects its first argument to be a number.
297297
298 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
298 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
299299 | (index (literal goofy) (list 1 2 3 4 5)))
300300 ? uncaught exception: (expected-number . goofy)
301301
302302 `index` expects its second argument to be a list.
303303
304 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
304 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
305305 | (index 8 (literal whatnot)))
306306 ? uncaught exception: (expected-pair . whatnot)
307307
311311 second argument to obtain a list. It then evaluates to the longest prefix
312312 of the list whose elements all satisfy the predicate.
313313
314 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
314 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
315315 | (take-while (fun (x) (symbol? x)) (literal (one two 3 4 five 6 seven))))
316316 = (one two)
317317
318 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
318 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
319319 | (take-while (fun (x) (symbol? x)) (literal (1 2 3 4 five six))))
320320 = ()
321321
322 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
322 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
323323 | (take-while (fun (x) (number? x)) (literal (1 2 3 4 5 6))))
324324 = (1 2 3 4 5 6)
325325
326 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
326 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
327327 | (take-while (fun (x) (number? x)) (literal (1 2 3 #f 5 . 6))))
328328 = (1 2 3)
329329
330 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
330 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
331331 | (take-while (fun (x) (number? x)) (literal (1 2 3 4 5 . #f))))
332332 ? uncaught exception: (expected-pair . #f)
333333
334 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
334 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
335335 | (take-while (fun (x) (symbol? x)) ()))
336336 = ()
337337
338 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
338 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
339339 | (take-while (fun (x) (symbol? x)) #f))
340340 ? uncaught exception: (expected-pair . #f)
341341
346346 given list, starting at the first element which does not satisfy the
347347 predicate.
348348
349 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
349 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
350350 | (drop-while (fun (x) (symbol? x)) (literal (one two 3 4 five 6 seven))))
351351 = (3 4 five 6 seven)
352352
353 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
353 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
354354 | (drop-while (fun (x) (symbol? x)) (literal (1 2 3 4 5 6))))
355355 = (1 2 3 4 5 6)
356356
357 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
357 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
358358 | (drop-while (fun (x) (number? x)) (literal (1 2 3 4 5 6))))
359359 = ()
360360
361 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
361 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
362362 | (drop-while (fun (x) (symbol? x)) (literal (one two 3 4 five 6 . seven))))
363363 = (3 4 five 6 . seven)
364364
365 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
365 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
366366 | (drop-while (fun (x) (symbol? x)) (literal (one two . three))))
367367 ? uncaught exception: (expected-pair . three)
368368
369 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
369 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
370370 | (drop-while (fun (x) (symbol? x)) ()))
371371 = ()
372372
373 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
373 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
374374 | (drop-while (fun (x) (symbol? x)) #f))
375375 ? uncaught exception: (expected-pair . #f)
376376
380380 considered to be a desired length, and its second argument to obtain a list.
381381 It then evaluates to the prefix of the given list of the desired length.
382382
383 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
383 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
384384 | (first 0 (list 1 2 3 4 5)))
385385 = ()
386386
387 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
387 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
388388 | (first 3 (list 1 2 3 4 5)))
389389 = (1 2 3)
390390
391 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
391 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
392392 | (first 6 (list 1 2 3 4 5)))
393393 ? uncaught exception: (expected-pair)
394394
395 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
395 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
396396 | (first 6 (list 1 2 3 4 5 . 6)))
397397 ? uncaught exception: (expected-pair . 6)
398398
399 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
399 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
400400 | (first 1 (literal foo)))
401401 ? uncaught exception: (expected-pair . foo)
402402
403 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
403 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
404404 | (first 0 (literal foo)))
405405 = ()
406406
411411 list. It then evaluates to the suffix of the given list starting at the
412412 desired position. The position 0 indicates the beginning of the list.
413413
414 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
414 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
415415 | (rest 0 (list 1 2 3 4 5)))
416416 = (1 2 3 4 5)
417417
418 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
418 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
419419 | (rest 3 (list 1 2 3 4 5)))
420420 = (4 5)
421421
422 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
422 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
423423 | (rest 5 (list 1 2 3 4 5)))
424424 = ()
425425
426 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
426 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
427427 | (rest 6 (list 1 2 3 4 5)))
428428 ? uncaught exception: (expected-pair)
429429
430 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
430 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
431431 | (rest 6 (list 1 2 3 4 5 . 6)))
432432 ? uncaught exception: (expected-pair . 6)
433433
434 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
434 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
435435 | (rest 1 (literal foo)))
436436 ? uncaught exception: (expected-pair . foo)
437437
438 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
438 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
439439 | (rest 0 (literal foo)))
440440 = foo
441441
446446 list. It then evaluates to the suffix of the given list of the desired
447447 length.
448448
449 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
449 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
450450 | (last 0 (list 1 2 3 4 5)))
451451 = ()
452452
453 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
453 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
454454 | (head (last 1 (list 1 2 3 4 5))))
455455 = 5
456456
457 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
457 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
458458 | (last 3 (list 1 2 3 4 5)))
459459 = (3 4 5)
460460
461 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
461 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
462462 | (last 6 (list 1 2 3 4 5)))
463463 ? uncaught exception: (expected-pair)
464464
465 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
465 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
466466 | (last 6 (list 1 2 3 4 5 . 6)))
467467 ? uncaught exception: (expected-pair . 6)
468468
469 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
469 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
470470 | (last 1 (literal foo)))
471471 ? uncaught exception: (expected-pair . foo)
472472
473473 Unlike `first`, `last` does care if it's not a list, even when the count
474474 is zero.
475475
476 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
476 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
477477 | (last 0 (literal foo)))
478478 ? uncaught exception: (expected-pair . foo)
479479
485485 or the head of A is `equal?` to the head of B and the tail of A is a
486486 prefix of the tail of B.
487487
488 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
488 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
489489 | (prefix? (list 1 2 3) (list 1 2 3 4 5 6)))
490490 = #t
491491
492 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
492 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
493493 | (prefix? (list 1 2 5) (list 1 2 3 4 5 6)))
494494 = #f
495495
496 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
496 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
497497 | (prefix? () (list 1 2 3 4 5 6)))
498498 = #t
499499
500 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
500 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
501501 | (prefix? () (literal schpritz)))
502502 = #t
503503
504 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
504 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
505505 | (prefix? (list 1 2 3) (list 1 2 3)))
506506 = #t
507507
508 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
508 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
509509 | (prefix? (list 1 2 3 4) (list 1 2 3)))
510510 = #f
511511
512 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
512 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
513513 | (prefix? (literal (1 2 3)) (literal (1 2 3 4 5 . 6))))
514514 = #t
515515
516 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
516 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
517517 | (prefix? (literal (1 2 3 4 8)) (literal (1 2 3 4 5 . 6))))
518518 = #f
519519
520 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
520 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
521521 | (prefix? (literal (1 2 . 3)) (literal (1 2 . 3))))
522522 ? uncaught exception: (expected-pair . 3)
523523
524 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
524 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
525525 | (prefix? (literal (1 2 4 8)) (literal (1 2 . 3))))
526526 ? uncaught exception: (expected-pair . 3)
527527
535535 is applied recursively to any elements in sublists which are themselves
536536 sublists.
537537
538 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
538 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
539539 | (flatten ()))
540540 = ()
541541
542 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
542 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
543543 | (flatten (list 1 2 3)))
544544 = (1 2 3)
545545
546 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
546 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
547547 | (flatten (list 1 (list 2 3 4) 5)))
548548 = (1 2 3 4 5)
549549
550 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
550 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
551551 | (flatten (list 1 (list 2 3 (list 4 4 4)) 5)))
552552 = (1 2 3 4 4 4 5)
553553
554 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
554 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
555555 | (flatten (list 1 () 5)))
556556 = (1 5)
557557
558 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
558 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
559559 | (flatten (list 1 (pair 2 3) 4)))
560560 = (1 (2 . 3) 4)
561561
562 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
562 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
563563 | (flatten (list 1 (literal (2 3 . 4)) 5)))
564564 = (1 (2 3 . 4) 5)
565565
566 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
566 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
567567 | (flatten (literal (1 2 . 3))))
568568 ? uncaught exception: (expected-pair . 3)
569569
570570 ### `lookup` ###
571571
572 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
572 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
573573 | (lookup (literal b) (literal ((a . 1) (b . 2) (c . 3)))))
574574 = (2)
575575
576 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
576 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
577577 | (lookup (literal a) (literal ((a . 1) (a . 2) (a . 3)))))
578578 = (1)
579579
580 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
580 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
581581 | (lookup (literal r) (literal ((a . 1) (b . 2) (c . 3)))))
582582 = ()
583583
584 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
584 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
585585 | (lookup (literal q) ()))
586586 = ()
587587
588 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
588 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
589589 | (lookup (literal q) 55))
590590 ? uncaught exception: (expected-pair . 55)
591591
592 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
592 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
593593 | (lookup (literal q) (literal ((a . 7) 99 (q . 4)))))
594594 ? uncaught exception: (expected-pair . 99)
595595
596596 ### `extend` ###
597597
598 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
598 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
599599 | (extend (literal b) 6 (literal ((a . 1) (b .2) (c .3)))))
600600 = ((b . 6) (a . 1) (b . 2) (c . 3))
601601
602602 The following should be true for any identifier i and alist x.
603603
604 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
604 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
605605 | (let ((i (literal a))
606606 | (x (literal ((f . 5) (g . 7)))))
607607 | (lookup i (extend i 1 x))))
608608 = (1)
609609
610 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
610 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
611611 | (extend (literal b) 6 81))
612612 = ((b . 6) . 81)
613613
614614 ### `delete` ###
615615
616 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
616 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
617617 | (delete (literal b) (literal ((a . 1) (b . 2) (c . 3)))))
618618 = ((a . 1) (c . 3))
619619
620 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
620 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
621621 | (delete (literal b) (literal ((a . 1) (b . 2) (c . 3) (b . 4)))))
622622 = ((a . 1) (c . 3))
623623
624 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
624 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
625625 | (delete (literal r) (literal ((a . 1) (b . 2) (c . 3)))))
626626 = ((a . 1) (b . 2) (c . 3))
627627
628628 The following should be true for any identifier i and alist x.
629629
630 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
630 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
631631 | (let ((i (literal a))
632632 | (x (literal ((a . 5) (b . 7)))))
633633 | (lookup i (delete i x))))
634634 = ()
635635
636 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
636 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
637637 | (delete (literal q) 55))
638638 ? uncaught exception: (expected-pair . 55)
639639
640 | (robin (0 . 1) (small (0 . 1) list (0 . 1))
640 | (robin (0 1) ((small (0 1) *) (list (0 1) *))
641641 | (delete (literal q) (literal ((a . 7) 99 (q . 4)))))
642642 ? uncaught exception: (expected-pair . 99)
1414 is not loaded twice.
1515
1616 | ----- module a 0.1
17 | (robin (0 . 1) (small (0 . 1) random (0 . 1))
17 | (robin (0 1) ((small (0 1) *) (random (0 1) *))
1818 | (pair (pair (literal random-a) random) ()))
1919 | ----- module b 0.1
20 | (robin (0 . 1) (small (0 . 1) random (0 . 1))
20 | (robin (0 1) ((small (0 1) *) (random (0 1) *))
2121 | (pair (pair (literal random-b) random) ()))
2222 | ----- main
23 | (robin (0 . 1) (core (0 . 1) a (0 . 1) b (0 . 1))
23 | (robin (0 1) ((core (0 1) *) (a (0 1) *) (b (0 1) *))
2424 | (equal? random-a random-b))
2525 = #t
2626
2828 loop.
2929
3030 | ----- module a 0.1
31 | (robin (0 . 1) (small (0 . 1) b (0 . 1))
31 | (robin (0 1) ((small (0 1) *) (b (0 1) *))
3232 | (pair (pair (literal literal-a) literal-b) ()))
3333 | ----- module b 0.1
34 | (robin (0 . 1) (small (0 . 1) a (0 . 1))
34 | (robin (0 1) ((small (0 1) *) (a (0 1) *))
3535 | (pair (pair (literal literal-b) literal-a) ()))
3636 | ----- main
37 | (robin (0 . 1) (core (0 . 1) a (0 . 1))
37 | (robin (0 1) ((core (0 1) *) (a (0 1) *))
3838 | (equal? literal-a literal-b))
3939 ? robin: circular reference in module a
4040
41 -> Tests for shell command "bin/robin %(test-file)"
41 -> Functionality "Interpret Robin Program" is implemented by
42 -> shell command "bin/robin %(test-file)"
43
44 -> Tests for functionality "Interpret Robin Program"
4245
4346 `and` is short-circuiting.
4447
45 | (robin (0 . 1) (small (0 . 1) boolean (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
48 | (robin (0 1) ((small (0 1) *) (boolean (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
4649 | (let ((true
4750 | (fun () (call! crude-output write (literal t) reply #t)))
4851 | (false
5457
5558 `or` is short-circuiting.
5659
57 | (robin (0 . 1) (small (0 . 1) boolean (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
60 | (robin (0 1) ((small (0 1) *) (boolean (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
5861 | (let ((true
5962 | (fun () (call! crude-output write (literal t) reply #t)))
6063 | (false
3232 but marked with `pure` in the metadata (except `eval` where this is far
3333 from a guarantee.)
3434
35 | (robin (0 . 1) (pure (0 . 1))
35 | (robin (0 1) ((pure (0 1) *))
3636 | (has? (literal pure) head))
3737 = #t
3838
39 | (robin (0 . 1) (pure (0 . 1))
39 | (robin (0 1) ((pure (0 1) *))
4040 | (has? (literal pure) tail))
4141 = #t
4242
43 | (robin (0 . 1) (pure (0 . 1))
43 | (robin (0 1) ((pure (0 1) *))
4444 | (has? (literal pure) pair))
4545 = #t
4646
47 | (robin (0 . 1) (pure (0 . 1))
47 | (robin (0 1) ((pure (0 1) *))
4848 | (has? (literal pure) if))
4949 = #t
5050
51 | (robin (0 . 1) (pure (0 . 1))
51 | (robin (0 1) ((pure (0 1) *))
5252 | (has? (literal pure) macro))
5353 = #t
5454
55 | (robin (0 . 1) (pure (0 . 1))
55 | (robin (0 1) ((pure (0 1) *))
5656 | (has? (literal pure) fun))
5757 = #t
5858
7979 of symbols which are the formal parameters of the function. The third
8080 argument is a literal term which is the body of the function.
8181
82 | (robin (0 . 1) (pure (0 . 1))
82 | (robin (0 1) ((pure (0 1) *))
8383 | (pure-expr? (env) () (literal 4)))
8484 = #t
8585
86 | (robin (0 . 1) (pure (0 . 1))
86 | (robin (0 1) ((pure (0 1) *))
8787 | (pure-expr? (env) () (literal (subtract 4 5))))
8888 = #t
8989
90 | (robin (0 . 1) (pure (0 . 1))
90 | (robin (0 1) ((pure (0 1) *))
9191 | (pure-expr? (env) (literal (a b)) (literal (subtract a b))))
9292 = #t
9393
94 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
94 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
9595 | (pure-expr? (env) (literal (a b)) (literal (send! (myself) 3))))
9696 = #f
9797
9898 An otherwise pure function which simply binds something that it does not use
9999 is still pure.
100100
101 | (robin (0 . 1) (pure (0 . 1))
101 | (robin (0 1) ((pure (0 1) *))
102102 | (pure-expr? (env) (literal (x)) (literal
103103 | (bind y 23 x))))
104104 = #t
106106 An otherwise pure function which binds some pure values to names is still
107107 pure.
108108
109 | (robin (0 . 1) (pure (0 . 1))
109 | (robin (0 1) ((pure (0 1) *))
110110 | (pure-expr? (env) (literal (x)) (literal
111111 | (bind y (subtract x 23) (bind r 5 (subtract y r))))))
112112 = #t
113113
114114 A function which evaluates to a pure built-in function is pure.
115115
116 | (robin (0 . 1) (pure (0 . 1))
116 | (robin (0 1) ((pure (0 1) *))
117117 | (pure-expr? (env) (literal (foo)) (literal head)))
118118 = #t
119119
120120 A function which evaluates to a pure function is pure.
121121
122 | (robin (0 . 1) (pure (0 . 1))
122 | (robin (0 1) ((pure (0 1) *))
123123 | (pure-expr? (env) (literal (foo)) (literal (fun (x) x))))
124124 = #t
125125
127127 the impure function is determined entirely by the parameters to the pure
128128 function.
129129
130 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
130 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
131131 | (pure-expr? (env) () (literal
132132 | (fun (x) (send! x 3)))))
133133 = #t
134134
135135 Even if it uses a closed-over identifier.
136136
137 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
137 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
138138 | (pure-expr? (env) (literal (pid)) (literal
139139 | (fun (x) (send! pid x)))))
140140 = #t
141141
142142 Even if it evaluates to multiple functions.
143143
144 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
144 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
145145 | (pure-expr? (env) (literal (pid)) (literal
146146 | (pair (fun () pid)
147147 | (fun (x) (send! pid x))))))
150150 An otherwise pure function which calls a pure function that it defines
151151 within itself is pure.
152152
153 | (robin (0 . 1) (pure (0 . 1))
153 | (robin (0 1) ((pure (0 1) *))
154154 | (pure-expr? (env) (literal (x)) (literal
155155 | ((fun (y) y) 123))))
156156 = #t
157157
158158 (Unless of course, one of its actual arguments is not.)
159159
160 | (robin (0 . 1) (pure (0 . 1))
160 | (robin (0 1) ((pure (0 1) *))
161161 | (pure-expr? (env) (literal (x)) (literal
162162 | ((fun (y) y) (send! x 14)))))
163163 = #f
164164
165165 Even if it uses closed-over identifiers.
166166
167 | (robin (0 . 1) (pure (0 . 1))
167 | (robin (0 1) ((pure (0 1) *))
168168 | (pure-expr? (env) (literal (x)) (literal
169169 | ((fun (y) x) 123))))
170170 = #t
171171
172172 Even if it was bound to a name first.
173173
174 | (robin (0 . 1) (pure (0 . 1))
174 | (robin (0 1) ((pure (0 1) *))
175175 | (pure-expr? (env) (literal (x)) (literal
176176 | (bind y (fun (z) z)
177177 | (y 123)))))
179179
180180 Even if it was bound to a name first, and uses closed-over identifiers.
181181
182 | (robin (0 . 1) (pure (0 . 1))
182 | (robin (0 1) ((pure (0 1) *))
183183 | (pure-expr? (env) (literal (x)) (literal
184184 | (bind y (fun (z) (pair x z))
185185 | (y 123)))))
188188 An otherwise pure function which calls an impure function that it defines
189189 within itself is not pure.
190190
191 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
191 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
192192 | (pure-expr? (env) (literal (pid)) (literal
193193 | ((fun (j) (send! j 3)) pid))))
194194 = #f
195195
196196 Even if that impure function was bound to a name first.
197197
198 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
198 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
199199 | (pure-expr? (env) (literal (pid)) (literal
200200 | (bind zap! (fun (j) (send! j 3))
201201 | (zap! pid)))))
204204 If we bind a name to an impure expression, the function is not pure, even
205205 if it doesn't use the name.
206206
207 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
207 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
208208 | (pure-expr? (env) (literal (pid)) (literal
209209 | (bind n (send! pid 3) pid))))
210210 = #f
212212 A function which applies one of its arguments is not pure, because its
213213 argument might not be pure.
214214
215 | (robin (0 . 1) (pure (0 . 1))
215 | (robin (0 1) ((pure (0 1) *))
216216 | (pure-expr? (env) (literal (x)) (literal
217217 | (x 123))))
218218 = #f
221221
222222 TBW
223223
224 | (robin (0 . 1) (pure (0 . 1))
224 | (robin (0 1) ((pure (0 1) *))
225225 | (pure-fun-defn? (env) (literal
226226 | (fun (a) a))))
227227 = #t
228228
229229 We don't do macros yet.
230230
231 | (robin (0 . 1) (pure (0 . 1))
231 | (robin (0 1) ((pure (0 1) *))
232232 | (pure-fun-defn? (env) (literal
233233 | (macro (self args env) args))))
234234 = #f
235235
236 | (robin (0 . 1) (pure (0 . 1))
236 | (robin (0 1) ((pure (0 1) *))
237237 | (pure-fun-defn? (env) (literal
238238 | head)))
239239 = #t
240240
241 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
241 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
242242 | (pure-fun-defn? (env) (literal
243243 | (fun (a) (send! a a)))))
244244 = #f
245245
246 | (robin (0 . 1) (pure (0 . 1) concurrency (0 . 1))
246 | (robin (0 1) ((pure (0 1) *) (concurrency (0 1) *))
247247 | (pure-fun-defn? (env) (literal
248248 | send!)))
249249 = #f
251251 This is actually pure, but too complex for us to analyze right now,
252252 so we pessimistically say no.
253253
254 | (robin (0 . 1) (pure (0 . 1))
254 | (robin (0 1) ((pure (0 1) *))
255255 | (pure-fun-defn? (env) (literal
256256 | ((head (pair fun ())) (a) a))))
257257 = #f
1212
1313 -> Tests for functionality "Interpret Robin Program"
1414
15 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) arith (0 . 1) random (0 . 1))
15 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (arith (0 1) *) (random (0 1) *))
1616 | (call! random range (pair 1 (pair 6 ())) value
1717 | (< value 7)))
1818 = #t
1919
20 | (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) arith (0 . 1) random (0 . 1))
20 | (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (arith (0 1) *) (random (0 1) *))
2121 | (call! random range (pair 1 (pair 6 ())) value
2222 | (>= value 1)))
2323 = #t
3636 which evaluates to the literal content of its sole argument, which can be
3737 any S-expression.
3838
39 | (robin (0 . 1) (small (0 . 1))
39 | (robin (0 1) ((small (0 1) *))
4040 | (literal symbol))
4141 = symbol
4242
43 | (robin (0 . 1) (small (0 . 1))
43 | (robin (0 1) ((small (0 1) *))
4444 | (literal (a . pair)))
4545 = (a . pair)
4646
47 | (robin (0 . 1) (small (0 . 1))
47 | (robin (0 1) ((small (0 1) *))
4848 | (literal (hello world)))
4949 = (hello world)
5050
5454
5555 You can define functions with `fun`. They can be anonymous.
5656
57 | (robin (0 . 1) (small (0 . 1))
57 | (robin (0 1) ((small (0 1) *))
5858 | ((fun (a) a) (literal whee)))
5959 = whee
6060
6262 function is defined will still be in force when the function is applied,
6363 even if they are no longer lexically in scope.
6464
65 | (robin (0 . 1) (small (0 . 1))
65 | (robin (0 1) ((small (0 1) *))
6666 | ((let
6767 | ((a (literal (hi)))
6868 | (f (fun (x) (pair x a))))
7171
7272 Functions can take functions.
7373
74 | (robin (0 . 1) (small (0 . 1))
74 | (robin (0 1) ((small (0 1) *))
7575 | (let
7676 | ((apply (fun (x) (x (literal a)))))
7777 | (apply (fun (r) (pair r (literal ()))))))
7979
8080 Functions can return functions.
8181
82 | (robin (0 . 1) (small (0 . 1))
82 | (robin (0 1) ((small (0 1) *))
8383 | (let
8484 | ((mk (fun (x) (fun (y) (pair y x))))
8585 | (mk2 (mk (literal (vindaloo)))))
8888
8989 Arguments to functions shadow any other bindings in effect.
9090
91 | (robin (0 . 1) (small (0 . 1))
91 | (robin (0 1) ((small (0 1) *))
9292 | (let
9393 | ((a (literal a))
9494 | (b (fun (a) (pair a a))))
9797
9898 A function may have no arguments at all.
9999
100 | (robin (0 . 1) (small (0 . 1))
100 | (robin (0 1) ((small (0 1) *))
101101 | ((fun () 7)))
102102 = 7
103103
109109 expression, and makes that binding available in another expression which
110110 it evaluates.
111111
112 | (robin (0 . 1) (small (0 . 1))
112 | (robin (0 1) ((small (0 1) *))
113113 | (bind x (literal hello)
114114 | (pair x x)))
115115 = (hello . hello)
116116
117 | (robin (0 . 1) (small (0 . 1))
117 | (robin (0 1) ((small (0 1) *))
118118 | (bind dup (fun (x) (pair x x))
119119 | (dup (literal g))))
120120 = (g . g)
121121
122 | (robin (0 . 1) (small (0 . 1))
122 | (robin (0 1) ((small (0 1) *))
123123 | (bind dup (fun (x) (pair x x))
124124 | (dup (dup (literal g)))))
125125 = ((g . g) g . g)
126126
127 | (robin (0 . 1) (small (0 . 1))
127 | (robin (0 1) ((small (0 1) *))
128128 | (bind smoosh (fun (x y) (pair y x))
129129 | (smoosh #t #f)))
130130 = (#f . #t)
131131
132 | (robin (0 . 1) (small (0 . 1))
132 | (robin (0 1) ((small (0 1) *))
133133 | (bind find (fun (self alist key)
134134 | (if (equal? alist (literal ())) (literal ())
135135 | (if (equal? key (head (head alist)))
147147
148148 An identifier can be bound to a symbol.
149149
150 | (robin (0 . 1) (small (0 . 1))
150 | (robin (0 1) ((small (0 1) *))
151151 | (let ((a (literal hello))) a))
152152 = hello
153153
154154 `let` can appear in the binding expression in a `let`.
155155
156 | (robin (0 . 1) (small (0 . 1))
156 | (robin (0 1) ((small (0 1) *))
157157 | (let ((a (let ((b (literal c))) b))) a))
158158 = c
159159
160160 `let` can bind a symbol to a function value.
161161
162 | (robin (0 . 1) (small (0 . 1))
162 | (robin (0 1) ((small (0 1) *))
163163 | (let ((a (fun (x y) (pair x y))))
164164 | (a (literal foo) (literal ()))))
165165 = (foo)
167167 Bindings established in a `let` remain in effect when evaluating
168168 the arguments things in the body of the `let`.
169169
170 | (robin (0 . 1) (small (0 . 1))
170 | (robin (0 1) ((small (0 1) *))
171171 | (let ((dup (fun (x) (pair x x))))
172172 | (dup (dup (literal g)))))
173173 = ((g . g) g . g)
175175 Bindings established in a binding in a `let` can be seen in
176176 subsequent bindings in the same `let`.
177177
178 | (robin (0 . 1) (small (0 . 1))
178 | (robin (0 1) ((small (0 1) *))
179179 | (let ((a (literal hello)) (b (pair a (literal ())))) b))
180180 = (hello)
181181
182182 Shadowing happens.
183183
184 | (robin (0 . 1) (small (0 . 1))
184 | (robin (0 1) ((small (0 1) *))
185185 | (let ((a (literal hello))) (let ((a (literal goodbye))) a)))
186186 = goodbye
187187
188188 `let` can have an empty list of bindings.
189189
190 | (robin (0 . 1) (small (0 . 1))
190 | (robin (0 1) ((small (0 1) *))
191191 | (let () (literal hi)))
192192 = hi
193193
203203 condition in the final test must be the literal symbol `else`; the
204204 corresponding expression will be evaluated if all other tests failed.
205205
206 | (robin (0 . 1) (small (0 . 1))
206 | (robin (0 1) ((small (0 1) *))
207207 | (choose (#t (literal hi)) (else (literal lo))))
208208 = hi
209209
210 | (robin (0 . 1) (small (0 . 1))
210 | (robin (0 1) ((small (0 1) *))
211211 | (choose (#f (literal hi)) (#t (literal med)) (else (literal lo))))
212212 = med
213213
214 | (robin (0 . 1) (small (0 . 1))
214 | (robin (0 1) ((small (0 1) *))
215215 | (choose (#f (literal hi)) (#f (literal med)) (else (literal lo))))
216216 = lo
217217
218218 `choose` can have zero tests before the `else`.
219219
220 | (robin (0 . 1) (small (0 . 1))
220 | (robin (0 1) ((small (0 1) *))
221221 | (choose (else (literal woo))))
222222 = woo
223223
228228 `env` evaluates to all the bindings in effect at the point of execution
229229 where this form is encountered, as an alist.
230230
231 | (robin (0 . 1) (small (0 . 1))
231 | (robin (0 1) ((small (0 1) *))
232232 | (bind find (fun (self alist key)
233233 | (if (equal? alist (literal ())) (literal ())
234234 | (if (equal? key (head (head alist)))
1717 value (even those deeply nested within subpairs) have been replaced with the
1818 second value.
1919
20 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
20 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
2121 | (subst 4 5 4))
2222 = 5
2323
24 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
24 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
2525 | (subst 4 5 (literal (1 2 3 4 5))))
2626 = (1 2 3 5 5)
2727
28 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
28 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
2929 | (subst 4 5 (literal (one two three four five))))
3030 = (one two three four five)
3131
32 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
32 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
3333 | (subst 4 5 (literal (4 1 4 1 4))))
3434 = (5 1 5 1 5)
3535
36 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
36 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
3737 | (subst 4 5 (literal (1 4 (1 4 (4 1) 4) 4))))
3838 = (1 5 (1 5 (5 1) 5) 5)
3939
40 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
40 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
4141 | (subst 4 () (literal (1 2 3 4))))
4242 = (1 2 3 ())
4343
44 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
44 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
4545 | (subst 4 () (literal (1 2 3 . 4))))
4646 = (1 2 3)
4747
48 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
48 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
4949 | (subst (literal (turkey and cheese)) (literal (pastrami and rye))
5050 | (pair (literal (turkey and bacon)) (literal (turkey and cheese)))))
5151 = ((turkey and bacon) pastrami and rye)
5252
5353 ### `subst-many` ###
5454
55 | (robin (0 . 1) (small (0 . 1) term (0 . 1))
55 | (robin (0 1) ((small (0 1) *) (term (0 1) *))
5656 | (subst-many (literal ((p . 100) (q . 200)))
5757 | (literal (a d (r p q) q (p (z q) p p) p z q)))))
5858 = (a d (r 100 200) 200 (100 (z 200) 100 100) 100 z 200)
0 (robin (0 . 1) (small (0 . 1)
1 arith (0 . 1)
2 list (0 . 1)
3 concurrency (0 . 1)
4 console (0 . 1))
0 (robin (0 1) ((small (0 1) *)
1 (arith (0 1) *)
2 (list (0 1) *)
3 (concurrency (0 1) *)
4 (console (0 1) *))
55 (let (
66 (loop! (fun (self x)
77 (if (equal? x 10000)
0 (robin (0 . 1) (small (0 . 1))
0 (robin (0 1) ((small (0 1) *))
11 (literal hello-world))
0 (robin (0 . 1) (small (0 . 1)
1 list (0 . 1)
2 boolean (0 . 1)
3 concurrency (0 . 1)
4 arith (0 . 1)
5 random (0 . 1)
6 crude-io (0 . 1)
7 term (0 . 1))
0 (robin (0 1) ((small (0 1) *)
1 (list (0 1) *)
2 (boolean (0 1) *)
3 (concurrency (0 1) *)
4 (arith (0 1) *)
5 (random (0 1) *)
6 (crude-io (0 1) *)
7 (term (0 1) *))
88 ;''Beginnings of an implementation of Hunt the Wumpus.
99 The !'s aren't quite consistent in this yet.''
1010 (let
0 (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
0 (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
11 (call! crude-input subscribe () x
22 (recv! entered
33 (pair (literal i-got) entered))))
0 (robin (0 . 1) (small (0 . 1) concurrency (0 . 1) crude-io (0 . 1))
0 (robin (0 1) ((small (0 1) *) (concurrency (0 1) *) (crude-io (0 1) *))
11 (bind input-loop
22 (fun (self)
33 (recv! entered
0 (robin (0 . 1) (pure (0 . 1))
0 (robin (0 1) ((pure (0 1) *))
11 (pure? (env) (literal (foo)) (literal (macro (self args env) foo))))
0 (robin (0 . 1) (small (0 . 1) list (0 . 1) concurrency (0 . 1) crude-io (0 . 1) random (0 . 1))
0 (robin (0 1) ((small (0 1) *)
1 (list (0 1) *)
2 (concurrency (0 1) *)
3 (crude-io (0 1) *)
4 (random (0 1) *))
15 (bind output-loop
26 (fun (self n)
37 (if (equal? n 0)
0 (robin (0 . 1) (small (0 . 1)
1 exception (0 . 1)
2 concurrency (0 . 1)
3 crude-io (0 . 1)
4 env (0 . 1))
0 (robin (0 1) ((small (0 1) *)
1 (exception (0 1) *)
2 (concurrency (0 1) *)
3 (crude-io (0 1) *)
4 (env (0 1) *))
55 (let (
66 (restricted-env
77 (export pair head tail if equal? pair? macro? symbol? boolean?
0 (robin (0 . 1) (small (0 . 1) env (0 . 1))
0 (robin (0 1) ((small (0 1) *) (env (0 1) *))
11 (let (
22 (- (fun (a b)
33 (subtract a b)))
0 (robin (0 . 1) (small (0 . 1) env (0 . 1) arith (0 . 1))
0 (robin (0 1) ((small (0 1) *) (env (0 1) *) (arith (0 1) *))
11 (let (
22 (assert (macro (self args env)
33 (let ((expr (head args))
0 (robin (0 . 1) (small (0 . 1) env (0 . 1))
0 (robin (0 1) ((small (0 1) *) (env (0 1) *))
11 (let (
22 (and (macro (self args env)
33 (if (equal? args ())
0 (robin (0 . 1) (small (0 . 1) list (0 . 1))
0 (robin (0 1) ((small (0 1) *) (list (0 1) *))
11 (let (
22 (env? (fun (li)
33 (bind env?-r (fun (self li)
0 (robin (0 . 1) (small (0 . 1))
0 (robin (0 1) ((small (0 1) *))
11 (let (
22 (empty? (fun (li)
33 (equal? li ())))
0 (robin (0 . 1) (small (0 . 1) list (0 . 1) env (0 . 1))
0 (robin (0 1) ((small (0 1) *) (list (0 1) *) (env (0 1) *))
11 ;''This is an EXPERIMENTAL module for EXPERIMENTING with
22 static analysis in Robin using metadata on values.''
33 (let (
0 (robin (0 . 1) (core (0 . 1))
0 (robin (0 1) ((core (0 1) *))
11 (eval
22 (pair
33 (pair ((macro (self args env) (head args)) literal) (macro (self args env) (head args)))
0 (robin (0 . 1) (small (0 . 1) list (0 . 1))
0 (robin (0 1) ((small (0 1) *) (list (0 1) *))
11 (let (
22 (subst (fun (src dest sexp)
33 (bind subst-r (fun (self src dest sexp)
2727 -c "Interpret Bundled Robin Program" \
2828 -c "Interpret Robin Program without output" \
2929 -f 'Interpret Robin Program:shell command "bin\\robin.exe %(test-file)"' \
30 -f 'Interpret Bundled Robin Program:shell command "python bin\\unbundle_modules.py %(test-file)"' \
30 -f 'Interpret Bundled Robin Program:shell command "c:\\Python27\\python.exe bin\\unbundle_modules.py %(test-file)"' \
3131 -f 'Interpret Robin Program without output:shell command "bin\\robin.exe -n %(test-file)"' \
3232 ${FILES}
3333 rm -f results*