nendo 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/test/syntax_spec.rb CHANGED
@@ -2,24 +2,24 @@
2
2
  # -*- encoding: utf-8 -*-
3
3
  #
4
4
  # syntax_spec.rb - "RSpec file for nendo language (syntax part)"
5
- #
5
+ #
6
6
  # Copyright (c) 2009-2010 Kiyoka Nishiyama <kiyoka@sumibi.org>
7
- #
7
+ #
8
8
  # Redistribution and use in source and binary forms, with or without
9
9
  # modification, are permitted provided that the following conditions
10
10
  # are met:
11
- #
11
+ #
12
12
  # 1. Redistributions of source code must retain the above copyright
13
13
  # notice, this list of conditions and the following disclaimer.
14
- #
14
+ #
15
15
  # 2. Redistributions in binary form must reproduce the above copyright
16
16
  # notice, this list of conditions and the following disclaimer in the
17
17
  # documentation and/or other materials provided with the distribution.
18
- #
18
+ #
19
19
  # 3. Neither the name of the authors nor the names of its contributors
20
20
  # may be used to endorse or promote products derived from this
21
21
  # software without specific prior written permission.
22
- #
22
+ #
23
23
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
24
  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
25
  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -31,7 +31,7 @@
31
31
  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
32
  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
33
  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
- #
34
+ #
35
35
  require 'nendo'
36
36
  include Nendo
37
37
 
@@ -52,8 +52,8 @@ describe Nendo, "when read the core syntax keyword " do
52
52
  @nendo.evalStr( "(eq? a macro)" ).should == '#t'
53
53
  @nendo.evalStr( "(define a &block)" ).should match( /Nendo::LispCoreSyntax/ )
54
54
  @nendo.evalStr( "(eq? a &block)" ).should == '#t'
55
- @nendo.evalStr( "(define a let)" ).should match( /Nendo::LispCoreSyntax/ )
56
- @nendo.evalStr( "(eq? a let)" ).should == '#t'
55
+ @nendo.evalStr( "(define a %let)" ).should match( /Nendo::LispCoreSyntax/ )
56
+ @nendo.evalStr( "(eq? a %let)" ).should == '#t'
57
57
  @nendo.evalStr( "(define a letrec)" ).should match( /Nendo::LispCoreSyntax/ )
58
58
  @nendo.evalStr( "(eq? a letrec)" ).should == '#t'
59
59
  @nendo.evalStr( "(define a set!)" ).should match( /Nendo::LispCoreSyntax/ )
@@ -62,6 +62,55 @@ describe Nendo, "when read the core syntax keyword " do
62
62
  end
63
63
 
64
64
 
65
+ describe Nendo, "when use lib functions for let-syntax " do
66
+ before do
67
+ @nendo = Nendo::Core.new()
68
+ end
69
+ it "should" do
70
+ @nendo.evaluator.write_to_string(
71
+ @nendo.evaluator.__wrapNestedLet( 1000,
72
+ [[ :a, Cell.new( 2 ) ]]
73
+ )).should == "(%let ((a 2)) 1000)"
74
+ @nendo.evaluator.write_to_string(
75
+ @nendo.evaluator.__wrapNestedLet( 1000,
76
+ [[ :a, Cell.new( 2 ) ], [ :b, Cell.new( 3 ) ]]
77
+ )).should == "(%let ((a 2)) (%let ((b 3)) 1000))"
78
+ @nendo.evaluator.write_to_string(
79
+ @nendo.evaluator.__wrapNestedLet( Cell.new( :"+", Cell.new( :a, Cell.new( :b ))),
80
+ [[ :a, Cell.new( 2 ) ], [ :b, Cell.new( 3 ) ]]
81
+ )).should == "(%let ((a 2)) (%let ((b 3)) (+ a b)))"
82
+
83
+ @nendo.evalStr( "(strip-syntax-quote 'abc)" ).should == "abc"
84
+ @nendo.evalStr( "(strip-syntax-quote '())" ).should == "()"
85
+ @nendo.evalStr( "(strip-syntax-quote '(a (b) ((c))))" ).should == "(a (b) ((c)))"
86
+ @nendo.evalStr( "(strip-syntax-quote '(syntax-quote abc))" ).should == "(quote abc)"
87
+ @nendo.evalStr( "(strip-syntax-quote '(syntax-quote (syntax-quote abc)))" ).should == "(quote (quote abc))"
88
+
89
+ @nendo.evalStr( "(strip-let-syntax-keyword 'abc)" ).should == "abc"
90
+ @nendo.evalStr( <<EOS
91
+ (strip-let-syntax-keyword
92
+ '(let-syntax ((nil!
93
+ (syntax-rules ()
94
+ ((_ x)
95
+ (set! x '())))))
96
+ (nil! aa)))
97
+ EOS
98
+ ).should == "(begin (nil! aa))"
99
+
100
+ @nendo.evalStr( <<EOS
101
+ (strip-let-syntax-keyword
102
+ '(let ()
103
+ (let-syntax ((a (syntax-rules () ((_ ?x) (+ ?x 8))))
104
+ (b (syntax-rules () ((_ ?x) (- ?x 8)))))
105
+ (let-syntax ((a (syntax-rules () ((_ ?y) (b 2))))
106
+ (b (syntax-rules () ((_ ?y) (a 3)))))
107
+ (list (a 7) (b 8))))))
108
+ EOS
109
+ ).should == "(let () (begin (begin (list (a 7) (b 8)))))"
110
+ end
111
+ end
112
+
113
+
65
114
  describe Nendo, "when use identifier checker " do
66
115
  before do
67
116
  @nendo = Nendo::Core.new()
@@ -90,13 +139,16 @@ describe Nendo, "when call make-syntactic-closure " do
90
139
  @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'print )" ).should == 'print'
91
140
  @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'if )" ).should == 'if'
92
141
  @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'lambda )" ).should == 'lambda'
93
- @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'aaaa )" ).should match( /_gensym_/ )
94
- @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'tmp )" ).should match( /_gensym_/ )
95
- @nendo.evalStr( "(define name (make-syntactic-closure (global-variables) '() 'tmp ))" ).should match( /_gensym_/ )
96
- @nendo.evalStr( "name" ).should match( /_gensym_/ )
97
- @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'new_global_var)" ).should match( /_gensym_/ )
142
+ @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'aaaa )" ).should match( /SyntacticClosure.aaaa:_aaaa_/ )
143
+ @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'tmp )" ).should match( /SyntacticClosure.tmp:_tmp_/ )
144
+ @nendo.evalStr( "(define name (make-syntactic-closure (global-variables) '() 'tmp ))" ).should match( /SyntacticClosure.tmp:_tmp_/ )
145
+ @nendo.evalStr( "name" ).should match( /SyntacticClosure.tmp:_tmp_/ )
146
+ @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'new_global_var)" ).should match( /SyntacticClosure.new_global_var:_new_global_var_/ )
98
147
  @nendo.evalStr( "(define new_global_var 10)" ).should == '10'
99
148
  @nendo.evalStr( "(make-syntactic-closure (global-variables) '() 'new_global_var)" ).should == 'new_global_var'
149
+
150
+ @nendo.evalStr( "(strip-syntactic-closures name)" ).should match( /_tmp_/ )
151
+ @nendo.evalStr( "(strip-syntactic-closures (list name name))" ).should match( /[(]_tmp_/ )
100
152
  end
101
153
  end
102
154
 
@@ -124,33 +176,108 @@ describe Nendo, "when use er-macro-transformer " do
124
176
  @nendo.loadInitFile
125
177
  end
126
178
  it "should" do
127
- @nendo.evalStr( " " +
128
- "(define-syntax my-or" +
129
- " (er-macro-transformer" +
130
- " (lambda (expr rename compare)" +
131
- " (cond ((null? (cdr expr)) #f)" +
132
- " ((null? (cddr expr)) (cadr expr))" +
133
- " (else" +
134
- " (list (rename 'let) (list (list (rename 'tmp) (cadr expr)))" +
135
- " (list (rename 'if) (rename 'tmp)" +
136
- " (rename 'tmp)" +
137
- " (cons (rename 'my-or) (cddr expr)))))))))" +
138
- "my-or" ).should match( /Nendo::LispSyntax/ )
179
+
180
+ @nendo.evalStr( <<EOS
181
+ (define-syntax test-of-identifier1?
182
+ (er-macro-transformer
183
+ (lambda (expr rename compare)
184
+ (cons (rename 'list)
185
+ (list (identifier? 'rename)
186
+ (identifier? 'sym))))))
187
+ test-of-identifier1?
188
+ EOS
189
+ ).should match( /Nendo::LispSyntax/ )
190
+
191
+ @nendo.evalStr( "(test-of-identifier1? 1)" ).should == '(#t #t)'
192
+
193
+ @nendo.evalStr( <<EOS
194
+ (define-syntax test-of-identifier2?
195
+ (er-macro-transformer
196
+ (lambda (expr rename compare)
197
+ (identifier? (cadr expr)))))
198
+
199
+ (let ((a 1)
200
+ (b 2)
201
+ (c 3))
202
+ (let ((b a))
203
+ (list
204
+ a
205
+ b
206
+ c
207
+ (test-of-identifier2? a)
208
+ (test-of-identifier2? b)
209
+ (test-of-identifier2? c)
210
+ (test-of-identifier2? d)
211
+ (test-of-identifier2? 'e))))
212
+ EOS
213
+ ).should == '(1 1 3 #t #t #t #t #f)'
214
+
215
+ @nendo.evalStr( <<EOS
216
+ (define-syntax test-of-rename
217
+ (er-macro-transformer
218
+ (lambda (expr rename compare)
219
+ (list (rename 'quote)
220
+ (rename 'sym)))))
221
+ test-of-rename
222
+ EOS
223
+ ).should match( /Nendo::LispSyntax/ )
224
+ @nendo.evalStr( "(test-of-rename 2)" ).should == 'sym'
225
+
226
+ @nendo.evalStr( <<EOS
227
+ (define-syntax test-of-identifier=?
228
+ (er-macro-transformer
229
+ (lambda (expr rename compare)
230
+ (let ((_compare (rename 'compare)))
231
+ (compare
232
+ (cadr expr)
233
+ (caddr expr))))))
234
+ (let ((a 1)
235
+ (b 2)
236
+ (c 3))
237
+ (let ((b a))
238
+ (list
239
+ a
240
+ b
241
+ c
242
+ (test-of-identifier=? a a)
243
+ (test-of-identifier=? b b)
244
+ (test-of-identifier=? c c)
245
+ (test-of-identifier=? a b)
246
+ (test-of-identifier=? a c))))
247
+ EOS
248
+ ).should == '(1 1 3 #t #t #t #f #f)'
249
+
250
+ @nendo.evalStr( <<EOS
251
+ (define-syntax my-or
252
+ (er-macro-transformer
253
+ (lambda (expr rename compare)
254
+ (cond ((null? (cdr expr)) #f)
255
+ ((null? (cddr expr)) (cadr expr))
256
+ (else
257
+ (list (rename 'let) (list (list (rename 'tmp) (cadr expr)))
258
+ (list (rename 'if) (rename 'tmp)
259
+ (rename 'tmp)
260
+ (cons (rename 'my-or) (cddr expr)))))))))
261
+ my-or
262
+ EOS
263
+ ).should match( /Nendo::LispSyntax/ )
139
264
  @nendo.evalStr( "(my-or 1 2)" ).should == '1'
140
265
  @nendo.evalStr( "(my-or #f 100 200)" ).should == '100'
141
266
  @nendo.evalStr( "(my-or #f #f #f #f 500)" ).should == '500'
142
267
  @nendo.evalStr( "(my-or #f #f #f #f #f)" ).should == '#f'
143
268
 
144
- @nendo.evalStr( " " +
145
- "(define-syntax my-and" +
146
- " (er-macro-transformer" +
147
- " (lambda (expr rename compare)" +
148
- " (cond ((null? (cdr expr)))" +
149
- " ((null? (cddr expr)) (cadr expr))" +
150
- " (else (list (rename 'if) (cadr expr)" +
151
- " (cons (rename 'my-and) (cddr expr))" +
152
- " #f))))))" +
153
- "my-and" ).should match( /Nendo::LispSyntax/ )
269
+ @nendo.evalStr( <<EOS
270
+ (define-syntax my-and
271
+ (er-macro-transformer
272
+ (lambda (expr rename compare)
273
+ (cond ((null? (cdr expr)))
274
+ ((null? (cddr expr)) (cadr expr))
275
+ (else (list (rename 'if) (cadr expr)
276
+ (cons (rename 'my-and) (cddr expr))
277
+ #f))))))
278
+ my-and
279
+ EOS
280
+ ).should match( /Nendo::LispSyntax/ )
154
281
  @nendo.evalStr( "(my-and 1 2)" ).should == '2'
155
282
  @nendo.evalStr( "(my-and 1 2 3 4)" ).should == '4'
156
283
  @nendo.evalStr( "(my-and #t #t #t #t 500)" ).should == '500'
@@ -166,26 +293,30 @@ describe Nendo, "when use syntax-rules " do
166
293
  @nendo.loadInitFile
167
294
  end
168
295
  it "should" do
169
- @nendo.evalStr( " " +
170
- "(define-syntax nil!" +
171
- " (syntax-rules ()" +
172
- " ((_ x)" +
173
- " (set! x '()))))" +
174
- "nil!" ).should match( /Nendo::LispSyntax/ )
296
+ @nendo.evalStr( <<EOS
297
+ (define-syntax nil!
298
+ (syntax-rules ()
299
+ ((_ x)
300
+ (set! x '()))))
301
+ nil!
302
+ EOS
303
+ ).should match( /Nendo::LispSyntax/ )
175
304
  @nendo.evalStr( "(define a 1) a" ).should == '1'
176
305
  @nendo.evalStr( "(nil! a) a" ).should == '()'
177
306
  @nendo.evalStr( "(set! a 2) a" ).should == '2'
178
307
  @nendo.evalStr( "(nil! a) a" ).should == '()'
179
- @nendo.evalStr( " " +
180
- "(define-syntax test-syntax" +
181
- " (syntax-rules ()" +
182
- " ((_ a)" +
183
- " (list a))" +
184
- " ((_ a b)" +
185
- " (list a (list b)))" +
186
- " ((_ a b c ...)" +
187
- " (list a (list b (list c ...))))))" +
188
- "test-syntax" ).should match( /Nendo::LispSyntax/ )
308
+ @nendo.evalStr( <<EOS
309
+ (define-syntax test-syntax
310
+ (syntax-rules ()
311
+ ((_ a)
312
+ (list a))
313
+ ((_ a b)
314
+ (list a (list b)))
315
+ ((_ a b c ...)
316
+ (list a (list b (list c ...))))))
317
+ test-syntax
318
+ EOS
319
+ ).should match( /Nendo::LispSyntax/ )
189
320
  @nendo.evalStr( "(test-syntax 1)" ).should == '(1)'
190
321
  @nendo.evalStr( "(test-syntax 1 2)" ).should == '(1 (2))'
191
322
  @nendo.evalStr( "(test-syntax 1 2 3)" ).should == '(1 (2 (3)))'
@@ -196,5 +327,383 @@ describe Nendo, "when use syntax-rules " do
196
327
  @nendo.evalStr( "(test-syntax 'a \"B\")" ).should == '(a ("B"))'
197
328
  @nendo.evalStr( "(test-syntax 'a \"B\" 'C)" ).should == '(a ("B" (C)))'
198
329
  @nendo.evalStr( "(test-syntax 'a \"B\" 'C \"d\")" ).should == '(a ("B" (C "d")))'
330
+ lambda { @nendo.evalStr( <<EOS
331
+ (define-syntax dummy-syntax
332
+ (syntax-rules))
333
+ EOS
334
+ ) }.should raise_error( RuntimeError, /syntax-rules.+\(1\)/ )
335
+ lambda { @nendo.evalStr( <<EOS
336
+ (define-syntax dummy-syntax
337
+ (syntax-rules eee))
338
+ EOS
339
+ ) }.should raise_error( RuntimeError, /syntax-rules.+\(2\)/ )
340
+
341
+ lambda { @nendo.evalStr( <<EOS
342
+ (define-syntax dummy-syntax
343
+ (syntax-rules
344
+ ((_ arg1)
345
+ arg1)))
346
+ EOS
347
+ ) }.should raise_error( RuntimeError, /syntax-rules.+\(3\)/ )
348
+
349
+ @nendo.evalStr( <<EOS
350
+ (define this-is-var 1)
351
+ (define-syntax dummy-syntax
352
+ (syntax-rules ()
353
+ ((_ arg1)
354
+ this-is-var)))
355
+ (macroexpand
356
+ '(dummy-syntax 100))
357
+ EOS
358
+ ).should == "this-is-var"
359
+
360
+ @nendo.evalStr( <<EOS
361
+ (define-syntax dummy-syntax
362
+ (syntax-rules ()
363
+ ((_ arg1)
364
+ 'this-is-symbol)))
365
+ (macroexpand
366
+ '(dummy-syntax 100))
367
+ EOS
368
+ ).should match( /quote #<SyntacticClosure.this-is-symbol:_this/ )
369
+
370
+ @nendo.evalStr( <<EOS
371
+ (define-syntax dummy-syntax
372
+ (syntax-rules ()
373
+ ((_ arg1)
374
+ 'this-is-symbol)))
375
+ (dummy-syntax 100)
376
+ EOS
377
+ ).should == "this-is-symbol"
378
+
199
379
  end
200
380
  end
381
+
382
+ describe Nendo, "When use let-syntax" do
383
+ before do
384
+ @nendo = Nendo::Core.new()
385
+ @nendo.loadInitFile
386
+ end
387
+ it "should" do
388
+
389
+ @nendo.evalStr( <<EOS
390
+ (macroexpand
391
+ '(let-syntax ((nil!
392
+ (syntax-rules ()
393
+ ((_ x)
394
+ (set! x '())))))
395
+ (nil! aa)))
396
+ EOS
397
+ ).should == "(begin (set! aa (quote ())))"
398
+
399
+ @nendo.evalStr( <<EOS
400
+ (macroexpand
401
+ '(let-syntax ((dummy-syntax
402
+ (syntax-rules ()
403
+ ((_ x)
404
+ 'this-is-symbol))))
405
+ (dummy-syntax 100)))
406
+ EOS
407
+ ).should match( /begin [(]quote #<SyntacticClosure.this-is-symbol:/ )
408
+
409
+ @nendo.evalStr( <<EOS
410
+ (macroexpand
411
+ '(let-syntax ((dummy-syntax
412
+ (syntax-rules ()
413
+ ((_ x)
414
+ (begin "this is debug line"
415
+ #?.)))))
416
+ (dummy-syntax 100)))
417
+ EOS
418
+ ).should == "(begin (begin \"this is debug line\" \"(string):6\"))"
419
+
420
+ @nendo.evalStr( <<EOS
421
+ (define aa 100)
422
+ (let-syntax ((nil!
423
+ (syntax-rules ()
424
+ ((_ x)
425
+ (set! x '())))))
426
+ (nil! aa))
427
+ aa
428
+ EOS
429
+ ).should == "()"
430
+
431
+ @nendo.evalStr( <<EOS
432
+ (let ()
433
+ (let-syntax ()
434
+ (define internal-def 'ok)
435
+ internal-def))
436
+ EOS
437
+ ).should == "ok"
438
+
439
+ @nendo.evalStr( <<EOS
440
+ '"internal-def2"
441
+ (let ()
442
+ (let-syntax ()
443
+ (define internal-def 'ok)
444
+ internal-def))
445
+ EOS
446
+ ).should == "ok"
447
+
448
+ @nendo.evalStr( <<EOS
449
+ (let-syntax
450
+ ((foo (syntax-rules ()
451
+ ((foo args ... penultimate ultimate)
452
+ (list ultimate penultimate args ...)))))
453
+ (foo 1 2 3 4 5))
454
+ EOS
455
+ ).should == "(5 4 1 2 3)"
456
+
457
+ lambda { @nendo.evalStr( <<EOS
458
+ (let-syntax ((a (+ 1 2)))
459
+ (a))
460
+ EOS
461
+ ) }.should raise_error( SyntaxError, /syntax-rules/ )
462
+
463
+ lambda { @nendo.evalStr( <<EOS
464
+ (let-syntax ((a 100))
465
+ (a))
466
+ EOS
467
+ ) }.should raise_error( SyntaxError, /syntax-rules/ )
468
+
469
+ lambda { @nendo.evalStr( <<EOS
470
+ (let-syntax ((a (syntax-rules-dummy () 1))
471
+ (b (syntax-rules () 2)))
472
+ (list (a) (b)))
473
+ EOS
474
+ ) }.should raise_error( SyntaxError, /syntax-rules/ )
475
+
476
+ @nendo.evalStr( <<EOS
477
+ (let-syntax ()
478
+ (list 1 2))
479
+ EOS
480
+ ).should == "(1 2)"
481
+
482
+ @nendo.evalStr( <<EOS
483
+ (let ()
484
+ (let-syntax ((a (syntax-rules () ((_ ?x) (+ ?x 8))))
485
+ (b (syntax-rules () ((_ ?x) (- ?x 8)))))
486
+ (list (a 7) (b 8))))
487
+ EOS
488
+ ).should == "(15 0)"
489
+
490
+ @nendo.evalStr( <<EOS
491
+ (let ()
492
+ (let-syntax ((a (syntax-rules () ((_ ?x) (+ ?x 8))))
493
+ (b (syntax-rules () ((_ ?x) (- ?x 8)))))
494
+ (let-syntax ((aa (syntax-rules () ((_ ?x) (b 2))))
495
+ (bb (syntax-rules () ((_ ?x) (a 3)))))
496
+ (list (aa 7) (bb 8)))))
497
+ EOS
498
+ ).should == "(-6 11)"
499
+
500
+ @nendo.evalStr( <<EOS
501
+ (let ()
502
+ (let-syntax ((a (syntax-rules () ((_ ?x) (+ ?x 8))))
503
+ (b (syntax-rules () ((_ ?x) (- ?x 8)))))
504
+ (let-syntax ((a (syntax-rules () ((_ ?y) (b 2))))
505
+ (b (syntax-rules () ((_ ?y) (a 3)))))
506
+ (list (a 7) (b 8)))))
507
+ EOS
508
+ ).should == "(-6 11)"
509
+ end
510
+ end
511
+
512
+
513
+ describe Nendo, "When use let-syntax in lexical scope " do
514
+ before do
515
+ @nendo = Nendo::Core.new()
516
+ @nendo.loadInitFile
517
+ end
518
+ it "should" do
519
+
520
+ @nendo.evalStr( <<EOS
521
+ (let ((... 2))
522
+ (let-syntax ((s (syntax-rules ()
523
+ ((_ x ...) 'bad)
524
+ ((_ . r) 'ok))))
525
+ (s a b c)))
526
+ EOS
527
+ ).should == "ok"
528
+
529
+ @nendo.evalStr( <<EOS
530
+ (let ((x 'outer))
531
+ (let-syntax ((m (syntax-rules () ((m) x))))
532
+ (let ((x 'inner))
533
+ (m))))
534
+ EOS
535
+ ).should == "outer"
536
+
537
+ @nendo.evalStr( <<EOS
538
+ (let ((x 'outer1))
539
+ (let ((y 'outer2))
540
+ (let ((z 'outer3))
541
+ (let-syntax ((m (syntax-rules () ((m) (list x y z)))))
542
+ (let ((x 'inner1))
543
+ (let ((y 'inner2))
544
+ (let ((z 'inner3))
545
+ (m))))))))
546
+ EOS
547
+ ).should == "(outer1 outer2 outer3)"
548
+
549
+ @nendo.evalStr( <<EOS
550
+ (let ((x 'outer))
551
+ (let-syntax ((with-x
552
+ (syntax-rules ()
553
+ ((_ y expr)
554
+ (let-syntax ((y (syntax-rules () ((_) x))))
555
+ expr)))))
556
+ (let ((x 'inner))
557
+ (with-x z (z)))))
558
+ EOS
559
+ ).should == "outer"
560
+
561
+ pending( "nested let fails on limitation of Nendo's let-syntax." )
562
+
563
+ @nendo.evalStr( <<EOS
564
+ (define z 'top-level-1)
565
+ (let ((x 'outer1))
566
+ (let ((y x))
567
+ (let ((z y))
568
+ (let-syntax ((m (syntax-rules () ((m) z))))
569
+ (let ((x 'inner1))
570
+ (let ((y x))
571
+ (let ((z y))
572
+ (m))))))))
573
+ EOS
574
+ ).should == "outer1"
575
+
576
+ end
577
+ end
578
+
579
+ describe Nendo, "When use complex let-syntax" do
580
+ before do
581
+ @nendo = Nendo::Core.new()
582
+ @nendo.loadInitFile
583
+ end
584
+ it "should" do
585
+
586
+ @nendo.evalStr( <<EOS
587
+ (define-syntax %cut
588
+ (syntax-rules (<> <...>)
589
+ ((%cut e? params args)
590
+ (lambda params args))
591
+ ((%cut e? (params ...) (args ...) <> . rest)
592
+ (%cut e? (params ... tmp) (args ... tmp) . rest))
593
+ ((%cut e? (params ...) (args ...) <...>)
594
+ (%cut e? (params ... . tmp) (apply args ... tmp)))
595
+ ((%cut e? (params ...) (args ...) <...> . rest)
596
+ (error "cut: non-terminal <...>"))
597
+ ((%cut #t (params ...) (args ...) x . rest)
598
+ (let ((tmp x)) (%cut #t (params ...) (args ... tmp) . rest)))
599
+ ((%cut #f (params ...) (args ...) x . rest)
600
+ (%cut #t (params ...) (args ... x) . rest))))
601
+ EOS
602
+ ).should match( /Nendo::LispSyntax/ )
603
+
604
+ @nendo.evalStr( <<EOS
605
+ (define-syntax cut
606
+ (syntax-rules () ((cut args ...) (%cut #f () () args ...))))
607
+ EOS
608
+ ).should match( /Nendo::LispSyntax/ )
609
+
610
+ @nendo.evalStr( <<EOS
611
+ (define rassq (cut rassoc <> <> eq?))
612
+ EOS
613
+ ).should match( /Proc/ )
614
+
615
+ @nendo.evalStr( <<EOS
616
+ ((cut list 1 <> 3 <>) 2 4)
617
+ EOS
618
+ ).should == "(1 2 3 4)"
619
+
620
+ @nendo.evalStr( <<EOS
621
+ (define-syntax match-check-ellipse
622
+ (syntax-rules ()
623
+ ((match-check-ellipse (a . b) success-k failure-k) failure-k)
624
+ ((match-check-ellipse #(a ...) success-k failure-k) failure-k)
625
+ ;; matching an atom
626
+ ((match-check-ellipse id success-k failure-k)
627
+ (let-syntax ((ellipse? (syntax-rules ()
628
+ ((ellipse? (foo id) sk fk) sk)
629
+ ((ellipse? other sk fk) fk))))
630
+ (ellipse? (a b c) success-k failure-k)))))
631
+ EOS
632
+ ).should match( /Nendo::LispSyntax/ )
633
+
634
+ @nendo.evalStr( <<EOS
635
+ (match-check-ellipse (aa bb) (+ #?. " ellipse") (+ #?. " non-ellipse"))
636
+ EOS
637
+ ).should == '"(string):1 non-ellipse"'
638
+
639
+ @nendo.evalStr( <<EOS
640
+ (match-check-ellipse xxx (+ #?. " ellipse") (+ #?. " non-ellipse"))
641
+ EOS
642
+ ).should == '"(string):1 non-ellipse"'
643
+
644
+ @nendo.evalStr( <<EOS
645
+ (match-check-ellipse ... (+ #?. " ellipse") (+ #?. " non-ellipse"))
646
+ EOS
647
+ ).should == '"(string):1 ellipse"'
648
+
649
+ @nendo.evalStr( <<EOS
650
+ (define-syntax dummy-syntax
651
+ (syntax-rules ()
652
+ ((_ arg)
653
+ (match-check-ellipse arg (result-str "ellipse") (result-str "non-ellipse")))))
654
+ (define-syntax result-str
655
+ (syntax-rules ()
656
+ ((_ arg-str)
657
+ (+ #?. " " arg-str))))
658
+ (dummy-syntax xxx)
659
+ EOS
660
+ ).should == '"(string):8 non-ellipse"'
661
+
662
+ @nendo.evalStr( <<EOS
663
+ (match-check-ellipse ... (match-check-ellipse xxx 'tt 'tf) (match-check-ellipse xxx 'ft 'ff))
664
+ EOS
665
+ ).should == 'tf'
666
+
667
+ @nendo.evalStr( <<EOS
668
+ (match-check-ellipse yyy (match-check-ellipse xxx 'tt 'tf) (match-check-ellipse xxx 'ft 'ff))
669
+ EOS
670
+ ).should == 'ff'
671
+
672
+ @nendo.evalStr( <<EOS
673
+ (define-syntax match-check-identifier
674
+ (syntax-rules ()
675
+ ;; fast-case failures, lists and vectors are not identifiers
676
+ ((_ (x . y) success-k failure-k) failure-k)
677
+ ((_ #(x ...) success-k failure-k) failure-k)
678
+ ;; x is an atom
679
+ ((_ x success-k failure-k)
680
+ (let-syntax
681
+ ((sym?
682
+ (syntax-rules ()
683
+ ((sym? x sk fk) sk)
684
+ ;; otherwise x is a non-symbol datum
685
+ ((sym? y sk fk) (begin #?. fk)))))
686
+ (sym? abracadabra success-k failure-k)))))
687
+ EOS
688
+ ).should match( /Nendo::LispSyntax/ )
689
+
690
+ @nendo.evalStr( <<EOS
691
+ (match-check-identifier (aa bb) "id" "non-id")
692
+ EOS
693
+ ).should == '"non-id"'
694
+
695
+ @nendo.evalStr( <<EOS
696
+ (match-check-identifier xx "id" "non-id")
697
+ EOS
698
+ ).should == '"id"'
699
+
700
+ @nendo.evalStr( <<EOS
701
+ (let ([yy (match-check-identifier xx "id" "non-id")])
702
+ yy)
703
+ EOS
704
+ ).should == '"id"'
705
+
706
+ end
707
+ end
708
+
709
+