nendo 0.5.4 → 0.6.0

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/lib/nendo.rb CHANGED
@@ -2,24 +2,24 @@
2
2
  # -*- encoding: utf-8 -*-
3
3
  #
4
4
  # nendo.rb - "language core of nendo"
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,2842 +31,15 @@
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
- #
35
- # $Id:
36
34
  #
37
- module Nendo
38
- require 'stringio'
39
- require 'digest/sha1'
40
- require 'pp'
41
-
42
- class Nil
43
- include Enumerable
44
- def each() end
45
- def to_arr() [] end
46
- def length() 0 end
47
- def isNull() true end
48
- def isDotted() false end
49
- def lastAtom() false end
50
- def getLastAtom()
51
- raise RuntimeError, "Error: Nil#getLastAtom method: this cell is not dotted list."
52
- end
53
- def to_s() "" end
54
- def car()
55
- raise "Error: Nil#car method: pair required, but got ()"
56
- end
57
- def cdr()
58
- raise "Error: Nil#cdr method: pair required, but got ()"
59
- end
60
- end
61
-
62
- class LispString < String
63
- def LispString.escape( str )
64
- if str.is_a? String
65
- str.gsub( /\\/, "\\\\\\\\" ).gsub( /["]/, "\\\"" ).gsub( /[\r]/, "\\r" ).gsub( /[\t]/, "\\t" )
66
- else
67
- raise TypeError
68
- end
69
- end
70
- end
71
-
72
- class LispMacro < Proc
73
- end
74
-
75
- class LispSyntax < Proc
76
- end
77
-
78
- class LispCoreSyntax
79
- def initialize( syntaxName )
80
- @syntaxName = syntaxName
81
- end
82
- attr_reader :syntaxName
83
- end
84
-
85
-
86
- class Cell
87
- include Enumerable
88
-
89
- def initialize( car = Nil.new, cdr = Nil.new )
90
- @car = car
91
- @cdr = cdr
92
- end
93
- attr_accessor :car, :cdr
94
-
95
- def each # Supporting iterator
96
- h = {}
97
- if not isNull
98
- it = self
99
- while Nil != it.class
100
- h[ it.hash ] = true
101
- # printf( "%s : %s\n", it.car, it.hash )
102
- yield it
103
- if it.cdr.is_a? Cell
104
- it = it.cdr
105
- if h.has_key?( it.hash )
106
- # found circular-list.
107
- it = Nil.new
108
- end
109
- else
110
- it = Nil.new
111
- end
112
- end
113
- end
114
- end
115
-
116
- def length() self.to_arr.length end
117
- def size() self.length end # alias of length
118
-
119
- def isDotted
120
- ((Cell != @cdr.class) and (Nil != @cdr.class))
121
- end
122
-
123
- def isNull
124
- ((Nil == @car.class) and (Nil == @cdr.class))
125
- end
126
-
127
- def lastCell
128
- lastOne = self
129
- self.each { |x| lastOne = x }
130
- lastOne
131
- end
132
-
133
- def lastAtom
134
- lastOne = self.lastCell
135
- lastOne.isDotted
136
- end
137
-
138
- def getLastAtom
139
- if self.lastAtom
140
- self.lastCell.cdr
141
- else
142
- Nendo::Nil.new
143
- end
144
- end
145
-
146
- def to_arr
147
- if isNull
148
- []
149
- else
150
- self.map {|x| x.car}
151
- end
152
- end
153
-
154
- def first
155
- self.car
156
- end
157
-
158
- def second
159
- self.cdr.car
160
- end
161
-
162
- def third
163
- self.cdr.cdr.car
164
- end
165
-
166
- alias :cdar :second
167
- alias :cddar :third
168
- end
169
-
170
- class LispValues
171
- def initialize( arr )
172
- if 1 == arr.size
173
- raise ArgumentError, "Error: LispValues object expects 0 or 2+ length of array"
174
- else
175
- @values = arr
176
- end
177
- end
178
- attr_reader :values
179
- end
180
-
181
- class LispRegexp
182
- def initialize( str )
183
- @exp = str[ 1 ... str.size ]
184
- @ignoreCase = (str[0] == 'i')
185
- end
186
- def to_s
187
- sprintf( "|%s|", @exp ) + (@ignoreCase ? "i" : "")
188
- end
189
- def escape
190
- @exp.gsub( /\\/, "\\\\\\\\" )
191
- end
192
- attr_reader :ignoreCase
193
- end
194
-
195
- class LispKeyword
196
- def initialize( str )
197
- @key = str.intern
198
- end
199
-
200
- def ==(other)
201
- if other.is_a? LispKeyword
202
- self.key == other.key
203
- else
204
- false
205
- end
206
- end
207
-
208
- def ===(other)
209
- self.==(other)
210
- end
211
-
212
- def to_s
213
- self.key.to_s
214
- end
215
-
216
- attr_reader :key
217
- end
218
-
219
- class NendoTestError
220
- def initialize( type = RuntimeError )
221
- @type = type
222
- end
223
-
224
- def to_s
225
- type.to_s
226
- end
227
- attr_accessor :type
228
- end
229
-
230
- class SyntacticClosure
231
- def initialize( originalSymbol, renamedSymbol )
232
- @originalSymbol = originalSymbol
233
- @renamedSymbol = renamedSymbol
234
- end
235
-
236
- def to_s
237
- @renamedSymbol.to_s
238
- end
239
-
240
- def intern
241
- @renamedSymbol
242
- end
243
-
244
- def sourcefile() "dynamic S-expression ( no source )" end
245
- def lineno() 1 end
246
-
247
- attr_reader :originalSymbol, :renamedSymbol
248
- end
249
-
250
- class SourceInfo
251
- def initialize
252
- @varname = nil
253
- @sourcefile = nil
254
- @lineno = nil
255
- @source_sexp = Cell.new
256
- @expanded_sexp = Cell.new
257
- @compiled_str = nil
258
- end
259
-
260
- def deepCopy( sexp )
261
- Marshal.load(Marshal.dump( sexp ))
262
- end
263
-
264
- def setVarname( varname )
265
- @varname = varname
266
- end
267
-
268
- def setSource( sourcefile, lineno, source_sexp )
269
- @sourcefile = sourcefile
270
- @lineno = lineno
271
- @source_sexp = self.deepCopy( source_sexp )
272
- end
273
-
274
- def setExpanded( expanded_sexp )
275
- @expanded_sexp = self.deepCopy( expanded_sexp )
276
- end
277
-
278
- def setCompiled( compiled_str )
279
- @compiled_str = compiled_str
280
- end
281
-
282
- def debugPrint
283
- printf( "=== sourceInfo === \n" )
284
- printf( " varname = %s\n", @varname )
285
- printf( " sourcefile = %s\n", @sourcefile )
286
- printf( " lineno = %s\n", @lineno)
287
- printf( " compiled_str = %s\n", @compiled_str )
288
- end
289
-
290
- attr_reader :varname, :sourcefile, :lineno, :source_sexp, :expanded_sexp, :compiled_str
291
- end
292
-
293
- class DelayedCallPacket
294
- def initialize( _rubysym, _origname, _pred, _args )
295
- @rubysym = _rubysym
296
- @origname = _origname
297
- @pred = _pred
298
- @args = _args
299
- end
300
- attr_reader :rubysym, :origname, :pred, :args
301
- end
302
-
303
- class Token
304
- def initialize( kind, str, sourcefile, lineno = nil, column = nil )
305
- @kind = kind
306
- @str = str
307
- @sourcefile = sourcefile
308
- @lineno = lineno
309
- @column = column
310
- end
311
- attr_accessor :kind, :str, :sourcefile, :lineno, :column
312
- end
313
-
314
-
315
- class CharReader
316
- def initialize( inport, sourcefile )
317
- @inport = inport
318
- @sourcefile = sourcefile
319
- self.reset
320
- end
321
-
322
- def reset
323
- @lineno = 1
324
- @column = 1
325
- end
326
-
327
- def getc
328
- @undo_lineno = @lineno
329
- @undo_column = @column
330
- ch = @inport.getc
331
- if nil != ch
332
- if ch.chr.match( /[\r\n]/ )
333
- @lineno += 1
334
- end
335
- @column += 1
336
- end
337
- ch
338
- end
339
-
340
- def ungetc( ch )
341
- @lineno = @undo_lineno
342
- @column = @undo_column
343
- @inport.ungetc( ch )
344
- end
345
-
346
- def sourcefile
347
- @sourcefile
348
- end
349
-
350
- def lineno
351
- @lineno
352
- end
353
-
354
- def column
355
- @column
356
- end
357
- end
358
-
359
- class Reader
360
- ## tokens
361
- T_EOF = :t_eof
362
- T_LPAREN = :t_lparen
363
- T_RPAREN = :t_rparen
364
- T_LVECTOR = :t_lvector
365
- T_SYMBOL = :t_symbol
366
- T_KEYWORD = :t_keyword
367
- T_NUM = :t_num
368
- T_STRING = :t_string
369
- T_QUOTE = :t_quote
370
- T_QUASIQUOTE = :t_quasiquote
371
- T_UNQUOTE = :t_unquote
372
- T_UNQUOTE_SPLICING = :t_unquote_splicing
373
- T_FEEDTO = :t_feedto
374
- T_DOT = :t_dot
375
- T_LINEFEED = :t_linefeed
376
- T_COMMENT = :t_comment
377
- T_DEBUG_PRINT = :t_debug_print
378
- T_MACRO_DEBUG_PRINT = :t_macro_debug_print
379
- T_REGEXP = :t_regexp
380
-
381
- # inport is IO class
382
- def initialize( inport, sourcefile, debug = false )
383
- @inport = inport
384
- @sourcefile = sourcefile
385
- @chReader = nil
386
- @curtoken = nil
387
- @debug = debug
388
- end
389
-
390
- def reset
391
- @chReader.reset if @chReader
392
- end
393
-
394
- def sourcefile
395
- @sourcefile
396
- end
397
-
398
- def lineno
399
- if @chReader
400
- @chReader.lineno
401
- else
402
- 1
403
- end
404
- end
405
-
406
- def skipspace
407
- begin
408
- ch = @chReader.getc
409
- break if nil == ch # non eof?
410
- #printf( " skipspace: [%02x]\n", ch ) if @debug
411
- end while ch.chr.match( /[ \t]/ )
412
- @chReader.ungetc( ch ) if nil != ch
413
- end
414
-
415
- def readwhile( exp, oneshot = false )
416
- ret = ""
417
- while true
418
- ch = @chReader.getc
419
- #printf( " readwhile: [%02x]\n", ch ) if @debug
420
- if !ch # eof?
421
- break
422
- end
423
- if ch.chr.match( exp )
424
- ret += ch.chr
425
- else
426
- @chReader.ungetc( ch )
427
- break
428
- end
429
- if oneshot then break end
430
- end
431
- ret
432
- end
433
-
434
- def peekchar( exp )
435
- ch = @chReader.getc
436
- #printf( " peekchar: [%02x]\n", ch ) if @debug
437
- if !ch # eof?
438
- return nil
439
- end
440
- if ch.chr.match( exp )
441
- ch.chr
442
- else
443
- @chReader.ungetc( ch )
444
- nil
445
- end
446
- end
447
-
448
- def readstring()
449
- ret = ""
450
- while true
451
- ch = @chReader.getc
452
- #printf( " readstring: [%s]\n", ch )
453
- if !ch # eof?
454
- break
455
- end
456
- if ch.chr == "\\"
457
- ch2 = @chReader.getc
458
- ret += case ch2.chr
459
- when '"' # \" reduce to "
460
- '"'
461
- when '\\' # \\ reduce to \
462
- "\\"
463
- when 'n'
464
- "\n"
465
- when 'r'
466
- "\r"
467
- when 't'
468
- "\t"
469
- else
470
- ""
471
- end
472
- elsif ch.chr != '"'
473
- ret += ch.chr
474
- else
475
- @chReader.ungetc( ch )
476
- break
477
- end
478
- end
479
- ret
480
- end
481
-
482
- def readRegexp()
483
- ret = ""
484
- while true
485
- ch = @chReader.getc
486
- #printf( " readRegexp1: [%s]\n", ch )
487
- if !ch # eof?
488
- break
489
- end
490
- if ch.chr == "\\" #escape
491
- ch2 = @chReader.getc
492
- #printf( " readRegexp2: [%s]\n", ch2 )
493
- ret += "\\" + ch2.chr
494
- elsif ch.chr == '/'
495
- break
496
- else
497
- ret += ch.chr
498
- end
499
- end
500
- ret
501
- end
502
-
503
- def tokenWithComment
504
- skipspace
505
- ch = @chReader.getc
506
- if nil == ch # eof?
507
- @curtoken = Token.new( T_EOF, "", @chReader.sourcefile, @chReader.lineno, @chReader.column )
508
- else
509
- str = ch.chr
510
- kind =
511
- case str
512
- when /[\']/
513
- T_QUOTE
514
- when /[\`]/
515
- T_QUASIQUOTE
516
- when /[,]/
517
- str += readwhile( /[@]/, true )
518
- if 1 == str.length
519
- T_UNQUOTE
520
- else
521
- T_UNQUOTE_SPLICING
522
- end
523
- when '(', '['
524
- T_LPAREN
525
- when ')', ']'
526
- T_RPAREN
527
- when '.'
528
- str += readwhile( /[_a-zA-Z0-9!?.]/ )
529
- if 1 == str.length
530
- T_DOT
531
- else
532
- T_SYMBOL
533
- end
534
- when /[\r\n]/
535
- T_LINEFEED
536
- when /;/
537
- readwhile( /[^\r\n]/ )
538
- str = ""
539
- T_COMMENT
540
- when /[#]/
541
- nextch = peekchar( /[?!tfbodx(\/]/ )
542
- case nextch
543
- when "?"
544
- if peekchar( /[=]/ )
545
- str = ""
546
- T_DEBUG_PRINT
547
- elsif peekchar( /[.]/ )
548
- str = ""
549
- T_MACRO_DEBUG_PRINT
550
- else
551
- str += readwhile( /[^ \t\r\n]/ )
552
- raise NameError, sprintf( "Error: unknown #xxxx syntax for Nendo %s", str )
553
- end
554
- when "!"
555
- readwhile( /[^\r\n]/ )
556
- str = ""
557
- T_COMMENT
558
- when "("
559
- str = ""
560
- T_LVECTOR
561
- when "t"
562
- str = "true"
563
- T_SYMBOL
564
- when "f"
565
- str = "false"
566
- T_SYMBOL
567
- when "b","o","d","x"
568
- str = readwhile( /[0-9a-zA-Z]/ )
569
- case nextch
570
- when "b"
571
- if str.match( /^[0-1]+$/ )
572
- str = "0b" + str
573
- else
574
- raise RuntimeError, sprintf( "Error: illegal #b number for Nendo #b%s", str )
575
- end
576
- when "o"
577
- if str.match( /^[0-7]+$/ )
578
- str = "0o" + str
579
- else
580
- raise RuntimeError, sprintf( "Error: illegal #o number for Nendo #o%s", str )
581
- end
582
- when "d"
583
- if str.match( /^[0-9]+$/ )
584
- str = "0d" + str
585
- else
586
- raise RuntimeError, sprintf( "Error: illegal #d number for Nendo #d%s", str )
587
- end
588
- when "x"
589
- if str.match( /^[0-9a-fA-F]+$/ )
590
- str = "0x" + str
591
- else
592
- raise RuntimeError, sprintf( "Error: illegal #x number for Nendo #x%s", str )
593
- end
594
- end
595
- str = Integer( str ).to_s
596
- T_NUM
597
- when "/" # T_REGEXP's str takes "iXXXXX"(igreno case) or " XXXXXX"(case sensitive) value.
598
- readwhile( /[\/]/ ) # consume
599
- str = readRegexp()
600
- str = ((0 < readwhile( /[i]/ ).size) ? "i" : " ") + str
601
- T_REGEXP
602
- else
603
- str += readwhile( /[^ \t\r\n]/ )
604
- raise NameError, sprintf( "Error: unknown #xxxx syntax for Nendo %s", str )
605
- end
606
- when /[_a-zA-Z!$%&*+\/:<=>?@^~-]/ # symbol
607
- str += readwhile( /[0-9._a-zA-Z!$%&*+\/:<=>?@^~-]/ )
608
- if str.match( /^[=][>]$/ )
609
- T_FEEDTO
610
- elsif str.match( /^[+-][0-9.]+$/ )
611
- T_NUM
612
- elsif str.match( /^[:]/ )
613
- str = str[1..-1]
614
- T_KEYWORD
615
- else
616
- T_SYMBOL
617
- end
618
- when /[0-9]/ # Numeric
619
- str += readwhile( /[0-9.]/ )
620
- T_NUM
621
- when /["]/ # String
622
- str = LispString.new( readstring() )
623
- readwhile( /["]/ )
624
- T_STRING
625
- else
626
- str += readwhile( /[^ \t\r\n]/ )
627
- raise NameError, sprintf( "Error: unknown token for Nendo [%s]", str )
628
- end
629
- printf( " token: [%s] : %s (%s:L%d:C%d)\n", str, kind.to_s, @chReader.sourcefile, @chReader.lineno, @chReader.column ) if @debug
630
- @curtoken = Token.new( kind, str, @chReader.sourcefile, @chReader.lineno, @chReader.column )
631
- end
632
- end
633
-
634
- def token
635
- begin
636
- tokenWithComment
637
- end while T_COMMENT == curtoken.kind
638
- curtoken
639
- end
640
-
641
- def curtoken
642
- if !@curtoken
643
- self.token
644
- end
645
- @curtoken
646
- end
647
-
648
- def atom
649
- cur = curtoken
650
- printf( " NonT: [%s] : [%s]\n", "atom", cur.str ) if @debug
651
- token
652
- case cur.kind
653
- when T_SYMBOL
654
- sym = cur.str.intern
655
- sym.setLispToken( cur )
656
- case sym
657
- when :true
658
- true
659
- when :false
660
- false
661
- when :nil
662
- nil
663
- else
664
- sym
665
- end
666
- when T_NUM
667
- if cur.str.match( /[.]/ ) # floating point
668
- cur.str.to_f
669
- else
670
- cur.str.to_i
671
- end
672
- when T_STRING
673
- cur.str
674
- when T_REGEXP
675
- LispRegexp.new( cur.str )
676
- when T_QUOTE
677
- :quote
678
- when T_QUASIQUOTE
679
- :quasiquote
680
- when T_UNQUOTE
681
- :unquote
682
- when T_UNQUOTE_SPLICING
683
- :"unquote-splicing"
684
- when T_DOT
685
- :"dot-operator"
686
- when T_FEEDTO
687
- :feedto
688
- when T_DEBUG_PRINT
689
- "debug-print".intern
690
- when T_MACRO_DEBUG_PRINT
691
- LispString.new( sprintf( "%s:%d", cur.sourcefile, cur.lineno ))
692
- when T_KEYWORD
693
- LispKeyword.new( cur.str )
694
- else
695
- raise "Error: Unknown token in atom()"
696
- end
697
- end
698
-
699
- # vector := sexp
700
- # | atom ... atom
701
- def vector
702
- printf( " NonT: [%s]\n", "vector" ) if @debug
703
- arr = []
704
- while true
705
- case curtoken.kind
706
- when T_LINEFEED
707
- token # skipEnter
708
- when T_EOF
709
- begin
710
- raise RuntimeError, "Error: unbalanced vector's paren(4)"
711
- rescue => e
712
- e.set_backtrace( [sprintf( "%s:%d", curtoken.sourcefile, curtoken.lineno )] + e.backtrace )
713
- raise e
714
- end
715
- when T_LPAREN, T_LVECTOR
716
- arr << sexp()
717
- when T_RPAREN
718
- break
719
- when T_QUOTE , T_QUASIQUOTE , T_UNQUOTE , T_UNQUOTE_SPLICING, T_DEBUG_PRINT
720
- arr << sexp()
721
- when T_DOT
722
- raise RuntimeError, "Error: illegal list."
723
- else
724
- arr << atom()
725
- end
726
- end
727
- arr
728
- end
729
-
730
- # list := sexp
731
- # | atom ... atom
732
- # | atom ... . atom
733
- def list
734
- printf( " NonT: [%s]\n", "list" ) if @debug
735
- dotted = false
736
- cells = []
737
- lastAtom = Nil.new
738
- while true
739
- case curtoken.kind
740
- when T_LINEFEED
741
- token # skipEnter
742
- when T_EOF
743
- begin
744
- raise RuntimeError, "Error: unbalanced paren(1)"
745
- rescue => e
746
- e.set_backtrace( [sprintf( "%s:%d", curtoken.sourcefile, curtoken.lineno )] + e.backtrace )
747
- raise e
748
- end
749
- when T_LPAREN, T_LVECTOR
750
- cells << Cell.new( sexp() )
751
- when T_RPAREN
752
- break
753
- when T_DOT
754
- if 0 == cells.length
755
- # (. symbol1 symbol2 ... ) form
756
- cells << Cell.new( atom() )
757
- else
758
- # ( symbol1 ... symbol2 . symbol3 ) form
759
- token
760
- lastAtom = sexp()
761
- if lastAtom.is_a? Cell and lastAtom.isNull
762
- lastAtom = Nil.new # the null list "()" could not be a lastAtom.
763
- end
764
- end
765
- when T_QUOTE , T_QUASIQUOTE , T_UNQUOTE , T_UNQUOTE_SPLICING, T_DEBUG_PRINT
766
- cells << Cell.new( sexp() )
767
- else
768
- if not lastAtom.is_a? Nil
769
- raise "Error : illegal dotted pair syntax."
770
- else
771
- cells << Cell.new( atom() )
772
- end
773
- end
774
- end
775
- ## setup list
776
- if 0 == cells.size
777
- Cell.new() # null list
778
- elsif 1 == cells.size
779
- cells.first.cdr = lastAtom
780
- cells.first
781
- elsif 1 < cells.size
782
- ptr = cells.pop
783
- ptr.cdr = lastAtom
784
- cells.reverse.each { |x|
785
- x.cdr = ptr
786
- ptr = x
787
- }
788
- cells.first
789
- end
790
- end
791
-
792
- def skipEnter
793
- while T_LINEFEED == curtoken.kind
794
- token
795
- end
796
- end
797
-
798
- # sexp := ( list ) | | #( vector ) | 'sexp | `sexp | atom
799
- def sexp
800
- printf( " NonT: [%s]\n", "sexp" ) if @debug
801
- case curtoken.kind
802
- when T_LINEFEED
803
- token
804
- sexp()
805
- when T_EOF
806
- begin
807
- raise RuntimeError, "Error: unbalanced paren(2)"
808
- rescue => e
809
- e.set_backtrace( [sprintf( "%s:%d", curtoken.sourcefile, curtoken.lineno )] + e.backtrace )
810
- raise e
811
- end
812
- when T_LPAREN
813
- skipEnter
814
- token # consume '('
815
- ret = list()
816
- skipEnter
817
- token # consume ')'
818
- ret
819
- when T_RPAREN
820
- token # consume ')'
821
- begin
822
- raise RuntimeError, "Error: unbalanced vector's paren(3)"
823
- rescue => e
824
- e.set_backtrace( [sprintf( "%s:%d", curtoken.sourcefile, curtoken.lineno )] + e.backtrace )
825
- raise e
826
- end
827
- when T_LVECTOR
828
- skipEnter
829
- token # consume '#('
830
- ret = vector()
831
- skipEnter
832
- token # consume ')'
833
- ret
834
- when T_QUOTE , T_QUASIQUOTE , T_UNQUOTE , T_UNQUOTE_SPLICING
835
- _atom = atom() ## "quote" symbol
836
- Cell.new( _atom, Cell.new( sexp() ))
837
- when T_DEBUG_PRINT
838
- file = curtoken.sourcefile
839
- lineno = curtoken.lineno
840
- _atom = atom() ## "debug-print" symbol
841
- child = sexp()
842
- [_atom, child, LispString.new( file ), lineno, Cell.new( :quote, Cell.new( child )) ].to_list
843
- else
844
- atom()
845
- end
846
- end
847
-
848
- # return value is [ S-expression-tree, eof-flag, valid-sexp-flag ]
849
- def _read
850
- @chReader = CharReader.new( @inport, @sourcefile ) unless @chReader
851
- case curtoken.kind
852
- when T_EOF
853
- [ Nil.new, true, false ]
854
- when T_LINEFEED
855
- token
856
- [ Nil.new, false, false ]
857
- else
858
- [ sexp(), false, true ]
859
- end
860
- end
861
- end
862
-
863
-
864
- # built-in functions
865
- module BuiltinFunctions
866
- def __assertFlat( *args )
867
- if 0 == args.length
868
- raise ArgumentError, "Error: + - * / % operator got illegal argument. "
869
- else
870
- args.each { |x|
871
- if Cell == x.class or Nil == x.class
872
- raise ArgumentError, "Error: + - * / % operator got illegal argument. "
873
- end
874
- }
875
- end
876
- end
877
-
878
- def __assertList( funcname, arg )
879
- if Cell != arg.class
880
- raise ArgumentError, "Error: %s expects a list argument.\n"
881
- end
882
- end
883
-
884
- def _equal_QUMARK( a, b )
885
- if a.is_a? String and b.is_a? String
886
- a === b
887
- elsif a.class != b.class
888
- false
889
- elsif a.is_a? Cell
890
- _equal_QUMARK( a.car, b.car ) and _equal_QUMARK( a.cdr, b.cdr )
891
- elsif _null_QUMARK( a ) and _null_QUMARK( b )
892
- true
893
- elsif a.is_a? Proc
894
- a == b
895
- else
896
- (a === b)
897
- end
898
- end
899
-
900
- def __PLMARK_ARGS0( ) 0 end
901
- def __PLMARK_ARGS1( a ) a end
902
- def __PLMARK_ARGS2( a, b ) a + b end
903
- def __PLMARK_ARGS3( a, b, c ) a + b + c end
904
-
905
- def __PLMARK( *args )
906
- arr = args[0].to_arr
907
- case args[0].length
908
- when 0
909
- 0
910
- else
911
- __assertFlat( arr )
912
- arr.each { |x|
913
- if not (_number_QUMARK(x) or _string_QUMARK(x))
914
- ##arr.each { |v| STDERR.printf( "__PLMARK: %s\n", v ) }
915
- raise TypeError, sprintf( "Error: arg %s is [%s] type",x ,x.class )
916
- end
917
- }
918
- case args[0].length
919
- when 1
920
- args[0].car
921
- else
922
- arr[1..-1].inject(arr[0]){|x,y| x+y}
923
- end
924
- end
925
- end
926
-
927
- def __ASMARK_ARGS0( ) 1 end
928
- def __ASMARK_ARGS1( a ) a end
929
- def __ASMARK_ARGS2( a, b ) a * b end
930
- def __ASMARK_ARGS3( a, b, c ) a * b * c end
931
-
932
- def __ASMARK( *args )
933
- arr = args[0].to_arr
934
- case args[0].length
935
- when 0
936
- 1
937
- else
938
- __assertFlat( arr )
939
- arr.each { |x|
940
- if not _number_QUMARK(x)
941
- raise TypeError
942
- end
943
- }
944
- case args[0].length
945
- when 1
946
- args[0].car
947
- else
948
- arr[1..-1].inject(arr[0]){|x,y| x*y}
949
- end
950
- end
951
- end
952
-
953
- def __MIMARK_ARGS0( ) 0 end
954
- def __MIMARK_ARGS1( a ) -a end
955
- def __MIMARK_ARGS2( a, b ) a - b end
956
- def __MIMARK_ARGS3( a, b, c ) a - b - c end
957
-
958
- def __MIMARK( first, *rest )
959
- raise TypeError if not _number_QUMARK(first)
960
- rest = rest[0].to_arr
961
- __assertFlat( rest )
962
- if 0 == rest.length
963
- - first
964
- else
965
- rest.inject(first){|x,y| x-y}
966
- end
967
- end
968
-
969
- def __SLMARK( first, *rest )
970
- raise TypeError if not _number_QUMARK(first)
971
- rest = rest[0].to_arr
972
- __assertFlat( rest )
973
- if 0 == rest.length
974
- 1 / first
975
- else
976
- rest.inject(first){|x,y| x/y}
977
- end
978
- end
979
-
980
- def __PAMARK( first, *rest )
981
- _modulo( first, *rest )
982
- end
983
-
984
- def _quotient( first, second )
985
- raise TypeError if not _number_QUMARK(first)
986
- raise TypeError if not _number_QUMARK(second)
987
- (first / second.to_f).to_i
988
- end
989
-
990
- def _remainder( first, second )
991
- raise TypeError if not _number_QUMARK(first)
992
- raise TypeError if not _number_QUMARK(second)
993
- first - _quotient( first, second ) * second
994
- end
995
-
996
- def _modulo( first, *rest )
997
- raise TypeError if not _number_QUMARK(first)
998
- rest = rest[0].to_arr
999
- __assertFlat( rest )
1000
- if 0 == rest.length
1001
- 1 % first
1002
- else
1003
- rest.inject(first){|x,y| x%y}
1004
- end
1005
- end
1006
-
1007
- def _not( arg )
1008
- arg = false if Nil == arg.class
1009
- not arg
1010
- end
1011
-
1012
- def _cons( first, second )
1013
- if first.is_a? Nil
1014
- first = Cell.new
1015
- end
1016
- if second.is_a? Cell
1017
- if second.isNull
1018
- Cell.new( first )
1019
- else
1020
- Cell.new( first, second )
1021
- end
1022
- else
1023
- Cell.new( first, second )
1024
- end
1025
- end
1026
-
1027
- def _set_MIMARKcar_EXMARK( cell, arg )
1028
- if cell.is_a? Cell
1029
- cell.car = arg
1030
- cell
1031
- else
1032
- raise TypeError
1033
- end
1034
- end
1035
-
1036
- def _set_MIMARKcdr_EXMARK( cell, arg )
1037
- arg = if arg.is_a? Cell
1038
- _null_QUMARK( arg ) ? Nil.new : arg
1039
- else
1040
- arg
1041
- end
1042
- if cell.is_a? Cell
1043
- cell.cdr = arg
1044
- cell
1045
- else
1046
- raise TypeError
1047
- end
1048
- end
1049
-
1050
- def _exit( *args )
1051
- if 0 == args[0].length
1052
- Kernel::exit(0)
1053
- else
1054
- arr = args[0].to_arr
1055
- Kernel::exit(arr[0])
1056
- end
1057
- end
1058
-
1059
- def _print( format, *rest )
1060
- print( format, *(rest[0].to_arr) )
1061
- end
1062
-
1063
- def _printf( format, *rest )
1064
- Kernel::printf( format, *(rest[0].to_arr) )
1065
- end
1066
-
1067
- def _sprintf( format, *rest )
1068
- Kernel::sprintf( format, *(rest[0].to_arr) )
1069
- end
1070
-
1071
- def _null_QUMARK( arg )
1072
- if Nil == arg.class
1073
- true
1074
- elsif Cell == arg.class
1075
- arg.isNull
1076
- else
1077
- false
1078
- end
1079
- end
1080
- def _length( arg )
1081
- if _null_QUMARK( arg )
1082
- 0
1083
- elsif arg.is_a? Cell
1084
- arg.length
1085
- else
1086
- raise TypeError
1087
- end
1088
- end
1089
- def _list( *args) args[0] end
1090
- def _reverse( arg ) arg.to_arr.reverse.to_list end
1091
- def _uniq( arg ) arg.to_arr.uniq.to_list end
1092
- def _range( num, *args )
1093
- arr = args[0].to_arr
1094
- if 0 < arr.length
1095
- if arr[0].is_a? Fixnum
1096
- (0..num-1).to_a.map { |x| x + arr[0] }.to_list
1097
- else
1098
- raise TypeError, "Error range's start expects number."
1099
- end
1100
- else
1101
- (0..num-1).to_a.to_list
1102
- end
1103
- end
1104
- def __EQMARK( a,b ) a == b end
1105
- def __GTMARK( a,b ) a > b end
1106
- def __GTMARK_EQMARK( a,b ) a >= b end
1107
- def __LTMARK( a,b ) a < b end
1108
- def __LTMARK_EQMARK( a,b ) a <= b end
1109
- def _eq_QUMARK( a,b ) a == b end
1110
- def _gt_QUMARK( a,b ) a > b end
1111
- def _ge_QUMARK( a,b ) a >= b end
1112
- def _lt_QUMARK( a,b ) a < b end
1113
- def _le_QUMARK( a,b ) a <= b end
1114
- def _eqv_QUMARK( a,b ) a === b end
1115
- def _car( cell ) cell.car end
1116
- def _cdr( cell )
1117
- if cell.cdr.is_a? Nil
1118
- Cell.new
1119
- else
1120
- cell.cdr
1121
- end
1122
- end
1123
- def _write( arg ) printer = Printer.new ; print printer._write( arg ) ; arg end
1124
- def _write_MIMARKto_MIMARKstring( arg ) printer = Printer.new ; printer._write( arg ) end
1125
- alias write_to_string _write_MIMARKto_MIMARKstring
1126
- def _display( arg ) printer = Printer.new ; print printer._print( arg ) ; arg end
1127
- def _print( arg ) self._display( arg ) ; self._newline() ; arg end
1128
- def _newline( ) print "\n" end
1129
- def _procedure_QUMARK( arg ) ((Proc == arg.class) or (Method == arg.class)) end
1130
- def _macro_QUMARK( arg ) (LispMacro == arg.class) end
1131
- def _symbol_QUMARK( arg ) (arg.is_a? Symbol or arg.is_a? SyntacticClosure) end
1132
- def _keyword_QUMARK( arg ) (arg.is_a? LispKeyword) end
1133
- def _syntax_QUMARK( arg ) (arg.is_a? LispSyntax) end
1134
- def _core_MIMARKsyntax_QUMARK( arg )
1135
- if arg.is_a? LispCoreSyntax
1136
- arg.syntaxName
1137
- else
1138
- nil
1139
- end
1140
- end
1141
- def _pair_QUMARK( arg )
1142
- if _null_QUMARK( arg )
1143
- false
1144
- else
1145
- (Cell == arg.class)
1146
- end
1147
- end
1148
- def __PAMARKlist_QUMARK( arg )
1149
- if _pair_QUMARK( arg )
1150
- (not arg.lastAtom) and (1 <= arg.to_arr.size) # it means proper list?
1151
- else
1152
- _null_QUMARK( arg )
1153
- end
1154
- end
1155
- def _integer_QUMARK( arg ) arg.is_a? Integer end
1156
- def _number_QUMARK( arg ) arg.is_a? Numeric end
1157
- def _string_QUMARK( arg ) arg.is_a? String end
1158
- def _macroexpand_MIMARK1( arg )
1159
- if _pair_QUMARK( arg )
1160
- macroexpandInit( 1 )
1161
- macroexpandEngine( arg, [], [] )
1162
- else
1163
- arg
1164
- end
1165
- end
1166
- def _to_s( arg ) _to_MIMARKs( arg ) end
1167
- def _to_MIMARKs( arg ) arg.to_s end
1168
- def _to_i( arg ) _to_MIMARKi( arg ) end
1169
- def _to_MIMARKi( arg ) arg.to_i end
1170
- def _nil_QUMARK( arg ) arg.nil? end
1171
- def _to_list( arg ) _to_MIMARKlist( arg ) end
1172
- def _to_MIMARKlist( arg )
1173
- case arg
1174
- when Array
1175
- arg.to_list
1176
- when Cell
1177
- arg
1178
- else
1179
- raise TypeError
1180
- end
1181
- end
1182
- def _to_arr( arg ) _to_MIMARKarr( arg ) end
1183
- def _to_MIMARKarr( arg )
1184
- case arg
1185
- when Cell
1186
- arg.to_arr
1187
- when Array
1188
- arg
1189
- else
1190
- raise TypeError
1191
- end
1192
- end
1193
- def _intern( arg ) arg.intern end
1194
- def _string_MIMARK_GTMARKsymbol( arg ) arg.intern end
1195
- def _symbol_MIMARK_GTMARKstring( arg ) arg.to_s end
1196
- def _string_MIMARKjoin( lst, *args )
1197
- arr = args[0].to_arr
1198
- if 0 < arr.length
1199
- if not arr[0].is_a? String
1200
- raise TypeError, "Error: string-join's expects delimitter as String."
1201
- else
1202
- lst.to_a.map{ |x| x.car }.join( arr[0] )
1203
- end
1204
- else
1205
- lst.to_a.map{ |x| x.car }.join
1206
- end
1207
- end
1208
- def _require( arg )
1209
- require( arg )
1210
- false
1211
- end
1212
- def _read_MIMARKfrom_MIMARKstring( str )
1213
- if not str.is_a? String
1214
- raise TypeError, "Error: read-from-string expects sexp as String."
1215
- else
1216
- sio = StringIO.open( str )
1217
- reader = Reader.new( sio, "(string)", false )
1218
- s = reader._read
1219
- s[0]
1220
- end
1221
- end
1222
- def _read( *args )
1223
- lst = args[0].to_arr
1224
- io = if 0 == lst.length
1225
- STDIN
1226
- else
1227
- lst[0]
1228
- end
1229
- reader = Reader.new( io, "STDIN", false )
1230
- ret = nil
1231
- begin
1232
- s = reader._read
1233
- ret = s[0]
1234
- if s[1] # EOF?
1235
- ret = Cell.new
1236
- break
1237
- end
1238
- end until s[2]
1239
- ret
1240
- end
1241
-
1242
- def _apply1( first, arg )
1243
- trampCall( callProcedure( nil, "(apply1 genereate func)", first, arg.to_arr ))
1244
- end
1245
-
1246
- def _global_MIMARKvariables
1247
- self.instance_variables.select { |x|
1248
- x.match( /^[@]_[_a-zA-Z]/ )
1249
- }.map{ |name|
1250
- self.toLispSymbol( name[1..-1] ).intern
1251
- }.to_list
1252
- end
1253
-
1254
- def _make_MIMARKvalues( lst )
1255
- if _pair_QUMARK( lst )
1256
- LispValues.new( lst.to_arr )
1257
- elsif _null_QUMARK( lst )
1258
- LispValues.new( [] )
1259
- else
1260
- raise ArgumentError, "Error: make-values expects a list argument."
1261
- end
1262
- end
1263
-
1264
- def _values_QUMARK( arg ) arg.is_a? LispValues end
1265
-
1266
- def _values_MIMARKvalues( arg )
1267
- if _values_QUMARK( arg )
1268
- arg.values.to_list
1269
- else
1270
- raise TypeError, "Error: values-values expects only LispValues object."
1271
- end
1272
- end
1273
-
1274
- def _make_MIMARKkeyword( arg )
1275
- if _symbol_QUMARK( arg ) or _string_QUMARK( arg )
1276
- LispKeyword.new( arg.to_s )
1277
- else
1278
- raise TypeError, "Error: make-keyword expects symbol or string object."
1279
- end
1280
- end
1281
-
1282
- def _keyword_MIMARK_GTMARKstring( arg )
1283
- if _keyword_QUMARK( arg )
1284
- arg.key.to_s
1285
- else
1286
- raise TypeError, "Error: keyword->string expects only keyword object."
1287
- end
1288
- end
1289
-
1290
- def _hash_MIMARKtable_MIMARKget( h, key, *args )
1291
- if h.has_key?(key)
1292
- h[key]
1293
- else
1294
- arr = args[0].to_arr
1295
- if 0 < arr.length
1296
- arr[0]
1297
- else
1298
- raise RuntimeError, sprintf( "Error: in hash-table-get() key [%s] was not exist.\n", key )
1299
- end
1300
- end
1301
- end
1302
-
1303
- def _hash_MIMARKtable_MIMARKput_EXMARK( h, key, value )
1304
- h[key] = value
1305
- end
1306
-
1307
- def _hash_MIMARKtable_MIMARKexist_QUMARK( h, key )
1308
- # don't use h.has_key(k), because has_key method undefined on some database bindings. (e.g. KyotoCabinet)
1309
- h[key] ? true : false
1310
- end
1311
-
1312
- # backtrace expects this format "filename:lineno: place message ". e.g. "init.nnd:10: in aaa macro.".
1313
- def __PAMARKraise( exception, message, backtrace )
1314
- raise exception, message, [ backtrace ]
1315
- end
1316
-
1317
- def __ASMARKLINE_ASMARK()
1318
- @lastLineno
1319
- end
1320
-
1321
- def __ASMARKFILE_ASMARK()
1322
- @lastSourcefile
1323
- end
1324
-
1325
- def _vector_MIMARKset_EXMARK( v, index, value )
1326
- if !(v.is_a? Array)
1327
- raise TypeError, "Error: vector-set! requires Array as argument v(Lisp's vector).\n"
1328
- end
1329
- if (index < 0) or (v.size <= index)
1330
- raise ArgumentError, "Error: vector-set! requires index between 0 and (size-1) number.\n"
1331
- end
1332
- v[index] = value
1333
- end
1334
-
1335
- end
1336
-
1337
-
1338
- # Translate S expression to Ruby expression and Evaluation
1339
- class Evaluator
1340
- include BuiltinFunctions
1341
- EXEC_TYPE_NORMAL = 1
1342
- EXEC_TYPE_ANONYMOUS = 2
1343
- EXEC_TYPE_TAILCALL = 3
1344
-
1345
- def initialize( core, debug = false )
1346
- @core = core
1347
- @indent = " "
1348
- @binding = binding
1349
- @debug = debug
1350
- @trace_debug = false
1351
- @lexicalVars = []
1352
- @syntaxHash = {}
1353
- @optimize_level = 2
1354
- @backtrace = {}
1355
- @backtrace_counter = 1;
1356
- @displayErrorsFlag = true;
1357
- @char_table_lisp_to_ruby = {
1358
- # list (! $ % & * + - . / : < = > ? @ ^ _ ~ ...)
1359
- '!' => '_EXMARK',
1360
- '$' => '_DOMARK',
1361
- '%' => '_PAMARK',
1362
- '&' => '_ANMARK',
1363
- '*' => '_ASMARK',
1364
- '+' => '_PLMARK',
1365
- '-' => '_MIMARK',
1366
- # '.'
1367
- '/' => '_SLMARK',
1368
- ':' => '_COMARK',
1369
- '<' => '_LTMARK',
1370
- '=' => '_EQMARK',
1371
- '>' => '_GTMARK',
1372
- '?' => '_QUMARK',
1373
- '@' => '_ATMARK',
1374
- '^' => '_NKMARK',
1375
- # '_'
1376
- '~' => '_CHMARK',
1377
- '...' => '_DOTDOTDOT',
1378
- }
1379
- @char_table_ruby_to_lisp = @char_table_lisp_to_ruby.invert
1380
-
1381
- @core_syntax_list = [ :quote, :"syntax-quote", :if , :begin , :lambda , :macro , :"&block" , :"%let" , :letrec , :define, :set!, :error, :"%syntax", :"define-syntax", :"let-syntax", :"%guard" ]
1382
- @core_syntax_hash = Hash.new
1383
- @core_syntax_list.each { |x|
1384
- renamed = ("/nendo/core/" + x.to_s).intern
1385
- @core_syntax_hash[ x ] = renamed
1386
- }
1387
-
1388
- # toplevel binding
1389
- @global_lisp_binding = Hash.new
1390
-
1391
- # initialize builtin functions as Proc objects
1392
- rubyExp = self.methods.select { |x|
1393
- x.to_s.match( /^_/ )
1394
- }.map { |name|
1395
- [
1396
- defMethodStr( name, false ),
1397
- sprintf( "@%s = self.method( :%s ).to_proc", name, name ),
1398
- sprintf( "@global_lisp_binding['%s'] = self.method( :%s_METHOD ).to_proc", name, name ),
1399
- ].join( " ; " )
1400
- }.join( " ; " )
1401
- eval( rubyExp, @binding )
1402
-
1403
- # initialize builtin syntax as LispCoreSyntax
1404
- rubyExp = @core_syntax_hash.map { |k,v|
1405
- name1 = toRubySymbol( k )
1406
- name2 = toRubySymbol( v )
1407
- [ sprintf( "@%s = LispCoreSyntax.new( :\"%s\" ) ", name1, k ),
1408
- sprintf( "@global_lisp_binding['%s'] = @%s ", name1, name1 ),
1409
- sprintf( "@%s = @%s ", name2, name1 ),
1410
- sprintf( "@global_lisp_binding['%s'] = @%s ", name1, name2 ) ].join( " ; " )
1411
- }.join( " ; " )
1412
- eval( rubyExp, @binding )
1413
-
1414
- # reset gensym counter
1415
- @gensym_counter = 0
1416
-
1417
- # call depth counter
1418
- @call_depth = 0
1419
- @call_counters = Hash.new
1420
-
1421
- # compiled ruby code
1422
- # { 'filename1' => [ 'code1' 'code2' ... ],
1423
- # 'filename2' => [ 'code1' 'code2' ... ], ... }
1424
- @compiled_code = Hash.new
1425
- @source_info_hash = Hash.new
1426
-
1427
- global_lisp_define( toRubySymbol( "%compile-phase-functions" ), Cell.new())
1428
- load_path = $LOAD_PATH + [ File.dirname(__FILE__) ]
1429
- global_lisp_define( toRubySymbol( "*load-path*" ), load_path.to_list )
1430
- global_lisp_define( toRubySymbol( "*nendo-version*" ), Nendo::Core.version )
1431
- end
1432
-
1433
- def global_lisp_define( rubySymbol, val )
1434
- @___tmp = val
1435
- eval( sprintf( "@%s = @___tmp;", rubySymbol ), @binding )
1436
- eval( sprintf( "@global_lisp_binding['%s'] = @___tmp;", rubySymbol ), @binding )
1437
- end
1438
-
1439
- def setArgv( argv )
1440
- self.global_lisp_define( toRubySymbol( "*argv*"), argv.to_list )
1441
- end
1442
-
1443
- def setOptimizeLevel( level )
1444
- @optimize_level = level
1445
- end
1446
-
1447
- def getOptimizeLevel
1448
- @optimize_level
1449
- end
1450
-
1451
- def setDisplayErrors( flag )
1452
- @displayErrorsFlag = flag
1453
- end
1454
-
1455
- def lispMethodEntry( name, _log )
1456
- @call_depth += 1
1457
- if @trace_debug and _log
1458
- puts " " * @call_depth + "ENTRY: " + name
1459
- end
1460
- end
1461
- def lispMethodExit( name, _log )
1462
- if @trace_debug and _log
1463
- puts " " * @call_depth + "exit: " + name
1464
- end
1465
- @call_depth -= 1
1466
- end
1467
-
1468
- def defMethodStr( name, _log )
1469
- [ "def self." + name.to_s + "_METHOD( origname, pred, args ) ",
1470
- " lispMethodEntry( origname, " + _log.to_s + " ) ; ",
1471
- " ret = callProcedure( '" + name.to_s + "', origname, pred, args ) ;",
1472
- " lispMethodExit( origname, " + _log.to_s + " ) ; ",
1473
- " return ret ",
1474
- "end " ].join
1475
- end
1476
-
1477
- def _gensym( )
1478
- @gensym_counter += 1
1479
- filename = if @lastSourcefile.is_a? String
1480
- Digest::SHA1.hexdigest( @lastSourcefile )
1481
- else
1482
- ""
1483
- end
1484
- sprintf( "__gensym__%s_%d", filename, @gensym_counter ).intern
1485
- end
1486
-
1487
- def forward_gensym_counter( )
1488
- @gensym_counter += 10000
1489
- end
1490
-
1491
- def toRubyValue( val )
1492
- if NilClass == val.class
1493
- "nil"
1494
- elsif TrueClass == val.class
1495
- val.to_s
1496
- elsif FalseClass == val.class
1497
- val.to_s
1498
- else
1499
- val.to_s
1500
- end
1501
- end
1502
-
1503
- def toRubySymbol( name )
1504
- if SyntacticClosure == name.class
1505
- "_" + name.to_s
1506
- else
1507
- name = name.to_s if Symbol == name.class
1508
- if 0 == name.length
1509
- ""
1510
- else
1511
- name.gsub!( Regexp.new( Regexp.escape( '...' )), @char_table_lisp_to_ruby[ '...' ] )
1512
- arr = name.gsub( /["]/, '' ).split( /[.]/ )
1513
- tmp = arr[0]
1514
- tmp.gsub!( /[:][:]/, " " ) # save '::'
1515
- @char_table_lisp_to_ruby.each_pair { |key,val|
1516
- tmp.gsub!( Regexp.new( Regexp.escape( key )), val )
1517
- }
1518
- arr[0] = tmp.gsub( /[ ][ ]/, "::" )
1519
- if arr[0].match( /^[A-Z]/ )
1520
- # nothing to do
1521
- elsif arr[0] == ""
1522
- arr[0] = 'Kernel'
1523
- else
1524
- arr[0] = '_' + arr[0]
1525
- end
1526
- arr.join( "." )
1527
- end
1528
- end
1529
- end
1530
-
1531
- def isRubyInterface( name )
1532
- name.to_s.match( /[.]/ )
1533
- end
1534
-
1535
- def toLispSymbol( name )
1536
- name = name.to_s if Symbol == name.class
1537
- raise ArgumentError, sprintf( "Error: `%s' is not a lisp symbol", name ) if not ('_' == name[0])
1538
- name = name[1..-1]
1539
- @char_table_ruby_to_lisp.each_pair { |key,val|
1540
- name = name.gsub( Regexp.new( key ), val )
1541
- }
1542
- name
1543
- end
1544
-
1545
- def errorMessageOf_toRubyArgument( origname, no, req, got )
1546
- sprintf( "Error: [%s] wrong number of arguments for closure `%s' (requires %d, but got %d)", no, origname, req, got )
1547
- end
1548
-
1549
- def toRubyArgument( origname, pred, args )
1550
- len = args.length
1551
- num = pred.arity
1552
- if 0 == num
1553
- raise ArgumentError, errorMessageOf_toRubyArgument( origname, 1, num, len ) if 0 != len
1554
- []
1555
- elsif 0 < num
1556
- if 0 == len
1557
- raise ArgumentError, errorMessageOf_toRubyArgument( origname, 4, num, len )
1558
- else
1559
- raise ArgumentError, errorMessageOf_toRubyArgument( origname, 2, num, len ) if num != len
1560
- args
1561
- end
1562
- else
1563
- num = num.abs( )-1
1564
- raise ArgumentError, errorMessageOf_toRubyArgument( origname, 3, num, len ) if num > len
1565
- params = []
1566
- rest = []
1567
- args.each_with_index { |x,i|
1568
- if i < num
1569
- params << x
1570
- else
1571
- rest << x
1572
- end
1573
- }
1574
- result = []
1575
- if 0 < params.length
1576
- result = params
1577
- end
1578
- if 0 == rest.length
1579
- result << Cell.new
1580
- else
1581
- result << rest.to_list
1582
- end
1583
- result
1584
- end
1585
- end
1586
-
1587
- def trampCall( result )
1588
- while result.class == DelayedCallPacket
1589
- result = __send__( result.rubysym + "_METHOD", result.origname, result.pred, result.args )
1590
- end
1591
- result
1592
- end
1593
-
1594
- def method_missing( name, *args )
1595
- if @global_lisp_binding[name].is_a? Proc
1596
- @global_lisp_binding[name].call( args[0], args[1], args[2] )
1597
- else
1598
- callProcedure( name, args[0], args[1], args[2] )
1599
- end
1600
- end
1601
-
1602
- def delayCall( rubysym, origname, pred, args )
1603
- case @optimize_level
1604
- when 0 # no optimize
1605
- callProcedure( rubysym, origname, pred, args )
1606
- else # tail call optimization
1607
- DelayedCallPacket.new( rubysym, origname, pred, args )
1608
- end
1609
- end
1610
-
1611
- def callProcedure( rubysym, origname, pred, args )
1612
- if @call_counters.has_key?( origname )
1613
- @call_counters[ origname ] += 1
1614
- else
1615
- @call_counters[ origname ] = 1
1616
- end
1617
- result = pred.call( *toRubyArgument( origname, pred, args ))
1618
-
1619
- @call_counters[ origname ] -= 1
1620
-
1621
- result
1622
- end
1623
-
1624
- # for code generation of Ruby's argument values
1625
- # in case: str = ","
1626
- # [1,"2",3] => [
1627
- # [ 1, ","]
1628
- # ["2", ","]
1629
- # [ 3 ]
1630
- # ]
1631
- def separateWith( arr, str )
1632
- seps = []
1633
- (arr.length-1).times {|n| seps << str }
1634
- arr.zip( seps ).map{ |x|
1635
- x.select { |elem| elem }
1636
- }
1637
- end
1638
-
1639
- def isDefines( sym )
1640
- [ :define, :set!, :"define-syntax", @core_syntax_hash[ :define ], @core_syntax_hash[ :set! ], @core_syntax_hash[ :"define-syntax" ] ].include?( sym )
1641
- end
1642
-
1643
- def embedBacktraceInfo( sourcefile, lineno )
1644
- @backtrace[ sprintf( "%s:%s", sourcefile, lineno ) ] = @backtrace_counter
1645
- @backtrace_counter += 1
1646
- end
1647
-
1648
- def generateEmbedBacktraceInfo( sourcefile, lineno, arr )
1649
- if sourcefile and lineno
1650
- [ "begin",
1651
- [ sprintf( 'embedBacktraceInfo( "%s", %s ); ', sourcefile, lineno ), arr ],
1652
- "end"
1653
- ]
1654
- else
1655
- arr
1656
- end
1657
- end
1658
-
1659
- def optimizedFunc( origname, rubysym, args )
1660
- case origname
1661
- when '+', '-', '*'
1662
- case args.length
1663
- when 0
1664
- [ "#{rubysym}_ARGS0(", ")" ]
1665
- when 1
1666
- [ "#{rubysym}_ARGS1(", args[0], ")" ]
1667
- when 2
1668
- [ "#{rubysym}_ARGS2(", args[0], args[1], ")" ]
1669
- when 3
1670
- [ "#{rubysym}_ARGS3(", args[0], args[1], args[2], ")" ]
1671
- else
1672
- false
1673
- end
1674
- when 'car', 'cdr', 'not', 'length', 'null?', 'reverse', 'uniq',
1675
- 'write', 'write-to-string', 'display', 'print',
1676
- 'procedure?', 'macro?', 'symbol?', 'keyword?', 'syntax?', 'core-syntax?',
1677
- 'pair?', '%list?', 'integer?', 'number?', 'string?', 'macroexpand-1',
1678
- 'to-s', 'to-i', 'nil?', 'to-list', 'to-arr',
1679
- 'intern', 'string->symbol', 'symbol->string', 'read-from-string'
1680
- raise ArgumentError, "Error: #{origname} requires 1 argument. " unless 1 == args.length
1681
- [ "#{rubysym}(", args[0], ")" ]
1682
- when 'cons', '=', ">", ">=", "<", "<=", "eq?", "equal?", 'set-car!', 'set-cdr!'
1683
- raise ArgumentError, "Error: #{origname} requires 2 arguments. " unless 2 == args.length
1684
- [ "#{rubysym}(", args[0], args[1], ")" ]
1685
- else
1686
- false
1687
- end
1688
- end
1689
-
1690
- def execFunc( funcname, args, sourcefile, lineno, locals, sourceInfo, execType )
1691
- if isDefines( funcname )
1692
- ar = args.cdr.map { |x| x.car }
1693
- variable_sym = toRubySymbol( args.car.to_s.sub( /^:/, "" ))
1694
- global_cap = locals.flatten.include?( variable_sym.split( /[.]/ )[0] ) ? nil : "@"
1695
- if global_cap and sourceInfo
1696
- sourceInfo.setVarname( toLispSymbol( variable_sym ))
1697
- end
1698
- [ "begin",
1699
- [
1700
- if global_cap
1701
- [
1702
- defMethodStr( variable_sym, true ),
1703
- sprintf( "@global_lisp_binding['%s'] = self.method( :%s_METHOD )", variable_sym, variable_sym )
1704
- ]
1705
- else
1706
- ""
1707
- end,
1708
- sprintf( "%s%s = ", global_cap, variable_sym ),
1709
- "trampCall(", [ ar ], ")"],
1710
- "end"
1711
- ]
1712
- elsif :error == funcname or @core_syntax_hash[ :error ] == funcname
1713
- arr = if args.length < 2
1714
- args.car
1715
- else
1716
- [ args.car + " ' ' + ",
1717
- "_write_MIMARKto_MIMARKstring(",
1718
- args.cdr.car,
1719
- ")" ]
1720
- end
1721
- [
1722
- 'begin raise RuntimeError, ',
1723
- arr,
1724
- "rescue => __e ",
1725
- sprintf( " __e.set_backtrace( [\"%s:%d\"] + __e.backtrace )", sourcefile, lineno ),
1726
- " raise __e",
1727
- "end "]
1728
- else
1729
- if (EXEC_TYPE_ANONYMOUS != execType) and isRubyInterface( funcname )
1730
- # Ruby method
1731
- # 1) convert arguments
1732
- translatedArr = args.map { |x| x.car }
1733
- # 2) generate caller code part
1734
- lispSymbolReference( toRubySymbol( funcname ), locals, translatedArr, sourcefile, lineno )
1735
- else
1736
- # Nendo function
1737
- arr = separateWith( args.map { |x| x.car }, "," )
1738
- origname = funcname.to_s
1739
- sym = toRubySymbol( origname )
1740
- if EXEC_TYPE_ANONYMOUS == execType
1741
- [sprintf( "trampCall( callProcedure( nil, 'anonymouse', " ),
1742
- [ funcname ] + [ "," ],
1743
- "[", arr, "]",
1744
- " ))"]
1745
- else
1746
- result = false
1747
- if (execType == EXEC_TYPE_NORMAL) and (not locals.flatten.include?( sym ))
1748
- if 1 < @optimize_level
1749
- result = optimizedFunc( origname, sym, arr )
1750
- end
1751
- end
1752
- if result
1753
- generateEmbedBacktraceInfo( sourcefile, lineno, result )
1754
- else
1755
- _call = case execType
1756
- when EXEC_TYPE_NORMAL
1757
- if locals.flatten.include?( sym )
1758
- [ "trampCall( callProcedure( '" + sym + "', ", "))" ] # local function
1759
- else
1760
- [ sprintf( "trampCall( self.%s_METHOD( ", sym ), "))" ] # toplevel function
1761
- end
1762
- when EXEC_TYPE_TAILCALL
1763
- [ sprintf( "delayCall( '%s', ", sym ), ")" ]
1764
- end
1765
-
1766
- temp = [
1767
- sprintf( "%s '%s',", _call[0], origname ),
1768
- [lispSymbolReference( sym, locals, nil, sourcefile, lineno )] + [","],
1769
- "[", arr, "]",
1770
- sprintf( " %s", _call[1] )]
1771
- generateEmbedBacktraceInfo( sourcefile, lineno, temp )
1772
- end
1773
- end
1774
- end
1775
- end
1776
- end
1777
-
1778
- def makeSetVariable( car, cdr, locals, sourceInfo )
1779
- cdr.cdr.each { |x|
1780
- if Cell == x.class
1781
- x.car = translate( x.car, locals, sourceInfo )
1782
- end
1783
- }
1784
- execFunc( car, cdr, car.sourcefile, car.lineno, locals, sourceInfo, EXEC_TYPE_ANONYMOUS )
1785
- end
1786
-
1787
- def makeBegin( args, locals )
1788
- ar = args.map { |e|
1789
- translate( e.car, locals )
1790
- }
1791
- ["begin", ar, "end"]
1792
- end
1793
-
1794
- # returns [ argsyms[], string ]
1795
- def toRubyParameter( argform )
1796
- argsyms = []
1797
- locals = []
1798
- rest = false
1799
- if _symbol_QUMARK( argform )
1800
- rest = argform
1801
- else
1802
- argsyms = argform.map { |x| toRubySymbol( x.car ) }
1803
- locals = argsyms.clone
1804
- if argform.lastAtom
1805
- rest = argform.getLastAtom
1806
- end
1807
- end
1808
- if rest
1809
- rest = toRubySymbol( rest )
1810
- locals << rest
1811
- argsyms << "*__rest__"
1812
- [ locals, sprintf( "|%s| %s = __rest__[0] ; ", argsyms.join( "," ), rest ) ]
1813
- else
1814
- [ locals, sprintf( "|%s|", argsyms.join( "," )) ]
1815
- end
1816
- end
1817
-
1818
- def makeClosure( sym, args, locals )
1819
- first = args.car
1820
- rest = args.cdr
1821
- ( _locals, argStr ) = toRubyParameter( first )
1822
- str = case sym
1823
- when :macro
1824
- sprintf( "LispMacro.new { %s ", argStr )
1825
- when :lambda
1826
- sprintf( "Proc.new { %s ", argStr )
1827
- when :"%syntax"
1828
- sprintf( "LispSyntax.new { %s ", argStr )
1829
- when :"&block"
1830
- sprintf( "&Proc.new { %s ", argStr )
1831
- else
1832
- raise "Error: makeClosure: unknown symbol type " + sym
1833
- end
1834
- ar = rest.map { |e|
1835
- translate( e.car, locals.clone + [_locals])
1836
- }
1837
- [ str, ar, "}" ]
1838
- end
1839
-
1840
- def makeIf( args, locals )
1841
- _condition = translate( args.car, locals )
1842
- _then = translate( args.cdr.car, locals )
1843
- _else = nil
1844
- if 2 < args.length
1845
- _else = translate( args.cdr.cdr.car, locals )
1846
- end
1847
- if _else
1848
- ["if ( ", _condition, " ) then",
1849
- [ _then ],
1850
- "else",
1851
- [ _else ],
1852
- "end"]
1853
- else
1854
- ["if ( ", _condition, " ) then",
1855
- [ _then ],
1856
- "end"]
1857
- end
1858
- end
1859
-
1860
- def makeLet( args, locals )
1861
- _name = "___lambda"
1862
- argvals = []
1863
- rest = args.cdr
1864
- if _null_QUMARK( args.car )
1865
- # nothing to do
1866
- lambda_head = sprintf( "%s = lambda { || ", _name )
1867
- else
1868
- argsyms = args.car.map { |x|
1869
- toRubySymbol( x.car.car.to_s )
1870
- }
1871
- argvals = args.car.map.with_index { |x,i|
1872
- translate( x.car.cdr.car, locals )
1873
- }
1874
- lambda_head = sprintf( "%s = lambda { |%s| ", _name, argsyms.join( "," ))
1875
- end
1876
- ["begin",
1877
- [lambda_head,
1878
- rest.map { |e| translate( e.car, locals.clone + [argsyms] ) },
1879
- sprintf( "} ; %s.call(", _name ),
1880
- separateWith( argvals, "," ),
1881
- sprintf( " )")],
1882
- "end"]
1883
- end
1884
-
1885
- def makeLetrec( args, locals )
1886
- _name = "___lambda"
1887
- argvals = []
1888
- argsyms = []
1889
- rest = args.cdr
1890
- if _null_QUMARK( args.car )
1891
- # nothing to do
1892
- lambda_head = sprintf( "%s = lambda { || ", _name )
1893
- else
1894
- argsyms = args.car.map { |x|
1895
- toRubySymbol( x.car.car.to_s )
1896
- }
1897
- argvals = args.car.map { |x|
1898
- translate( x.car.cdr.car, locals.clone + [argsyms] )
1899
- }
1900
- lambda_head = sprintf( "%s = lambda { |%s| ", _name, argsyms.join( "," ))
1901
- end
1902
- ["begin",
1903
- [lambda_head,
1904
- argsyms.zip( argvals ).map { |x| [ x[0], " = ", x[1] ] },
1905
- rest.map { |e| translate( e.car, locals.clone + [argsyms] ) },
1906
- sprintf( "} ; %s.call(", _name ),
1907
- argsyms.map { |x| "nil" }.join( "," ),
1908
- sprintf( " )")],
1909
- "end"]
1910
- end
1911
-
1912
- def makeGuard( args, locals )
1913
- _var = toRubySymbol( args.car )
1914
- _locals = locals.clone + [_var]
1915
- _case = translate( args.cdr.car, _locals )
1916
- _thunk = translate( args.cdr.cdr.car, _locals )
1917
- ["begin",
1918
- [ _thunk ],
1919
- "rescue => " + _var,
1920
- [ _case ],
1921
- "end" ]
1922
- end
1923
-
1924
- def apply( car, cdr, sourcefile, lineno, locals, sourceInfo, execType )
1925
- cdr.each { |x|
1926
- if Cell == x.class
1927
- x.car = translate( x.car, locals, sourceInfo )
1928
- end
1929
- }
1930
- execFunc( car, cdr, sourcefile, lineno, locals, sourceInfo, execType )
1931
- end
1932
-
1933
- def genQuote( sexp, str = "" )
1934
- origStr = str
1935
- case sexp
1936
- when Cell
1937
- if sexp.isNull
1938
- str += "Cell.new()"
1939
- else
1940
- arr = sexp.map { |x| genQuote( x.car ) }
1941
- str += "Cell.new("
1942
- str += arr.join( ",Cell.new(" )
1943
- str += "," + genQuote( sexp.getLastAtom ) if sexp.lastAtom
1944
- str += arr.map{ |e| ")" }.join
1945
- end
1946
- when Array
1947
- arr = sexp.map { |x| genQuote( x ) }
1948
- str += "[" + arr.join(",") + "]"
1949
- when Symbol
1950
- str += sprintf( ":\"%s\"", sexp.to_s )
1951
- when String, LispString
1952
- str += sprintf( "\"%s\"", LispString.escape( sexp ))
1953
- when LispKeyword
1954
- str += sprintf( "LispKeyword.new( \"%s\" )", sexp.key.to_s )
1955
- when TrueClass, FalseClass, NilClass # reserved symbols
1956
- str += toRubyValue( sexp )
1957
- when SyntacticClosure
1958
- str += sprintf( ":\"%s\"", sexp.originalSymbol.to_s )
1959
- when Nil
1960
- str += "Cell.new()"
1961
- else
1962
- str += sprintf( "%s", sexp )
1963
- end
1964
- str
1965
- end
1966
-
1967
- def trampCallCap( sym )
1968
- if isRubyInterface( sym )
1969
- arr = sym.split( /[.]/ )
1970
- arr[0] = sprintf( "trampCall(%s)", arr[0] )
1971
- arr.join( "." )
1972
- else
1973
- "trampCall(" + sym + ")"
1974
- end
1975
- end
1976
-
1977
- def lispSymbolReference( sym, locals, translatedArr, sourcefile, lineno )
1978
- variable_sym = sym.split( /[.]/ )[0]
1979
- global_cap = if variable_sym.match( /^[A-Z]/ )
1980
- nil
1981
- else
1982
- locals.flatten.include?( variable_sym ) ? nil : "@"
1983
- end
1984
- expression = if translatedArr
1985
- [trampCallCap( sprintf( "%s%s(", global_cap, sym )),
1986
- separateWith( translatedArr, "," ),
1987
- sprintf( " )" )]
1988
- else
1989
- [trampCallCap( sprintf( "%s%s", global_cap, sym ))]
1990
- end
1991
- if global_cap
1992
- ["begin",
1993
- [sprintf( "if @global_lisp_binding.has_key?('%s') then", variable_sym ),
1994
- expression,
1995
- sprintf( 'else raise NameError.new( "Error: undefined variable %s", "%s" ) end', variable_sym, variable_sym ),
1996
- sprintf( 'rescue => __e ; __e.set_backtrace( ["%s:%d"] + __e.backtrace ) ; raise __e', sourcefile, lineno )],
1997
- "end"]
1998
- else
1999
- ["begin",
2000
- [expression,
2001
- sprintf( 'rescue => __e ; __e.set_backtrace( ["%s:%d"] + __e.backtrace ) ; raise __e', sourcefile, lineno )],
2002
- "end"]
2003
- end
2004
- end
2005
-
2006
- # Lisp->Ruby translater
2007
- # - locals is array of closure's local variable list
2008
- # when S-expression is
2009
- # (let ((a 1)
2010
- # (b 2))
2011
- # (let ((c 3))
2012
- # (print (+ a b c))))
2013
- # => locals must be [["_a" "_b"]["_c"]] value.
2014
- def translate( sexp, locals, sourceInfo = nil )
2015
- case sexp
2016
- when Cell
2017
- inv = @core_syntax_hash.invert
2018
- car = if inv.has_key?( sexp.car )
2019
- inv[ sexp.car ]
2020
- else
2021
- sexp.car
2022
- end
2023
- if :quote == car
2024
- genQuote( sexp.second )
2025
- elsif :"syntax-quote" == car
2026
- [ "Cell.new(:\"syntax-quote\", ", genQuote( sexp.cdr ), ")" ]
2027
- elsif sexp.isDotted
2028
- raise NameError, "Error: can't eval dotted pair."
2029
- elsif sexp.isNull
2030
- [ "Cell.new()" ]
2031
- elsif isDefines( car )
2032
- self.makeSetVariable( car, sexp.cdr, locals, sourceInfo )
2033
- elsif :begin == car
2034
- self.makeBegin( sexp.cdr, locals )
2035
- elsif :lambda == car
2036
- self.makeClosure( :lambda, sexp.cdr, locals )
2037
- elsif :macro == car
2038
- self.makeClosure( :macro, sexp.cdr, locals )
2039
- elsif :"%syntax" == car
2040
- self.makeClosure( :"%syntax", sexp.cdr, locals )
2041
- elsif :"&block" == car
2042
- self.makeClosure( :"&block", sexp.cdr, locals )
2043
- elsif :if == car
2044
- self.makeIf( sexp.cdr, locals )
2045
- elsif :"%let" == car
2046
- self.makeLet( sexp.cdr, locals )
2047
- elsif :letrec == car
2048
- self.makeLetrec( sexp.cdr, locals )
2049
- elsif :"%guard" == car
2050
- self.makeGuard( sexp.cdr, locals )
2051
- elsif :"%tailcall" == car
2052
- if sexp.cdr.car.is_a? Cell
2053
- sexp = sexp.cdr.car
2054
- if isDefines( sexp.car )
2055
- translate( sexp, locals, sourceInfo )
2056
- else
2057
- if sexp.car.is_a? Cell
2058
- self.apply( translate( sexp.car, locals, sourceInfo ), sexp.cdr, sexp.car.car.sourcefile, sexp.car.car.lineno, locals, sourceInfo, EXEC_TYPE_ANONYMOUS )
2059
- else
2060
- self.apply( sexp.car, sexp.cdr, sexp.car.sourcefile, sexp.car.lineno, locals, sourceInfo, EXEC_TYPE_TAILCALL )
2061
- end
2062
- end
2063
- else
2064
- raise RuntimeError, "Error: special form tailcall expects function call expression."
2065
- end
2066
- elsif Cell == sexp.car.class
2067
- self.apply( translate( sexp.car, locals, sourceInfo ), sexp.cdr, sexp.car.car.sourcefile, sexp.car.car.lineno, locals, sourceInfo, EXEC_TYPE_ANONYMOUS )
2068
- else
2069
- self.apply( sexp.car, sexp.cdr, sexp.car.sourcefile, sexp.car.lineno, locals, sourceInfo, EXEC_TYPE_NORMAL )
2070
- end
2071
- when Array
2072
- raise RuntimeError, "Error: can't eval unquoted vector."
2073
- else
2074
- case sexp
2075
- when Symbol
2076
- sym = sexp.to_s
2077
- sym = toRubySymbol( sym )
2078
- lispSymbolReference( sym, locals, nil, sexp.sourcefile, sexp.lineno )
2079
- when Fixnum
2080
- sexp.to_s
2081
- when String, LispString
2082
- sprintf( "\"%s\"", LispString.escape( sexp ))
2083
- when LispRegexp
2084
- if sexp.ignoreCase
2085
- sprintf( "Regexp.new( \"%s\", Regexp::IGNORECASE)", sexp.escape )
2086
- else
2087
- sprintf( "Regexp.new( \"%s\")", sexp.escape )
2088
- end
2089
- when LispKeyword
2090
- sprintf( "LispKeyword.new( \"%s\" )", sexp.key )
2091
- when Nil
2092
- "Nil.new"
2093
- when TrueClass, FalseClass, NilClass # reserved symbols
2094
- toRubyValue( sexp )
2095
- when SyntacticClosure
2096
- toRubySymbol( sexp )
2097
- else
2098
- sexp.to_s
2099
- end
2100
- end
2101
- end
2102
-
2103
-
2104
- # warp sexp by lexicalVars
2105
- def __wrapNestedLet( sexp, lexicalVars )
2106
- if 0 == lexicalVars.size
2107
- sexp
2108
- else
2109
- elem = lexicalVars.shift
2110
- Cell.new( :"%let",
2111
- Cell.new(
2112
- Cell.new(
2113
- Cell.new( elem[0], elem[1] )),
2114
- Cell.new( __wrapNestedLet( sexp, lexicalVars ) )))
2115
- end
2116
- end
2117
-
2118
- def __removeSameLexicalScopeVariables( frame )
2119
- frame.select {|x|
2120
- # search same varname and different value
2121
- found = frame.any? {|y|
2122
- x[0] == y[0] and (not _equal_QUMARK( x[1], y[1] ))
2123
- }
2124
- if found
2125
- x
2126
- else
2127
- false
2128
- end
2129
- }
2130
- end
2131
-
2132
- def macroexpandInit( initVal )
2133
- @macroExpandCount = initVal
2134
- end
2135
-
2136
- def macroexpandEngineLoop( sexp, syntaxArray, lexicalVars )
2137
- converge = true
2138
- begin
2139
- newSexp = macroexpandEngine( sexp, syntaxArray, lexicalVars )
2140
- converge = _equal_QUMARK( newSexp, sexp )
2141
- sexp = newSexp
2142
- end until converge or (@macroExpandCount <= 0)
2143
- sexp
2144
- end
2145
-
2146
- def macroexpandEngine( sexp, syntaxArray, lexicalVars )
2147
- if @macroExpandCount <= 0
2148
- sexp
2149
- else
2150
- __macroexpandEngine( sexp, syntaxArray, lexicalVars )
2151
- end
2152
- end
2153
-
2154
- #
2155
- # expand (syntax-rules ...) => (%syntax-rules ...)
2156
- #
2157
- def __expandSyntaxRules( rules, syntaxArray, lexicalVars )
2158
- if :"%syntax-rules" == rules.car
2159
- rules
2160
- else
2161
- ellipse = rules.second
2162
- pattern_body_list = rules.cdr.cdr
2163
-
2164
- lst = []
2165
- lst << :"syntax-rules"
2166
- lst << ellipse
2167
- pattern_body_list.each {|xx|
2168
- pattern_body = xx.car
2169
- pattern = pattern_body.first
2170
- body = pattern_body.second
2171
- new_pattern_body = [ pattern, macroexpandEngine( body, syntaxArray, lexicalVars ) ].to_list
2172
- lst << new_pattern_body
2173
- }
2174
- lst.to_list
2175
- end
2176
- end
2177
-
2178
- # eval (syntax-rules ...) sexp
2179
- #
2180
- # return:
2181
- # (%syntax-rules
2182
- # ((v1 <<@syntaxHash's key1>>)
2183
- # (v2 <<@syntaxHash's key2>>)
2184
- # body))
2185
- #
2186
- # example:
2187
- # (%syntax-rules
2188
- # ((v1 "x = 10 // (+ x v1)")
2189
- # (v2 "y = 20 // (+ y v2)"))
2190
- # (+ v1 v2))
2191
- #
2192
- def __evalSyntaxRules( rules, lexicalVars )
2193
- if :"%syntax-rules" == rules.car
2194
- rules.second
2195
- else
2196
- lexvars = lexicalVars.select { |x|
2197
- if _symbol_MIMARKinclude_QUMARK( rules, x[0].intern )
2198
- x
2199
- elsif lexicalVars.find {|y| _symbol_MIMARKinclude_QUMARK( y[1], x[0].intern ) }
2200
- x
2201
- else
2202
- false
2203
- end
2204
- }
2205
-
2206
- __setupLexicalScopeVariables( lexvars )
2207
- keyStr = lexvars.map {|z|
2208
- z[0].to_s + " / " + write_to_string( z[1] )
2209
- }.join( " / " )
2210
- keyStr += " // " + write_to_string( rules )
2211
- if @syntaxHash.has_key?( keyStr )
2212
- true
2213
- else
2214
- @syntaxHash[ keyStr ] = [ lexvars,
2215
- self.lispEval( rules, "dynamic syntax-rules sexp (no source) ", 1 ) ]
2216
- end
2217
- __setupLexicalScopeVariables( [] )
2218
- keyStr
2219
- end
2220
- end
2221
-
2222
- # args:
2223
- #
2224
- # syntaxArray ... let-syntax's identifiers
2225
- # [
2226
- # [ identifier-name, key of @syntaxHash, sexp of (syntax-rules ...), frame_of_let-syntax ],
2227
- # .
2228
- # .
2229
- # ]
2230
- # lexicalVars ... let's identifiers
2231
- # [
2232
- # [ identifier-name, macroexpandEngine( let's body ) ],
2233
- # ]
2234
- #
2235
- #
2236
- def __macroexpandEngine( sexp, syntaxArray, lexicalVars )
2237
- case sexp
2238
- when Cell
2239
- car = sexp.car
2240
- if :quote == car or :"syntax-quote" == car or @core_syntax_hash[ :quote ] == car or @core_syntax_hash[ :"syntax-quote" ] == car
2241
- sexp
2242
- elsif :"%let" == car or :letrec == car or @core_syntax_hash[ :"%let" ] == car or @core_syntax_hash[ :letrec ] == car
2243
- # catch lexical identifiers of `let' and `letrec'.
2244
- arr = sexp.second.map { |x|
2245
- [ x.car.car, macroexpandEngine( x.car.cdr, syntaxArray, lexicalVars ) ]
2246
- }
2247
- lst = arr.map {|x| Cell.new( x[0], x[1] ) }.to_list
2248
- ret = Cell.new( car,
2249
- Cell.new( lst,
2250
- macroexpandEngine( sexp.cdr.cdr, syntaxArray, lexicalVars + arr )))
2251
- ret
2252
- elsif :"let-syntax" == car
2253
- sexp.second.each {|x|
2254
- if not x.car.second.is_a? Cell
2255
- raise SyntaxError, "Error: let-syntax get only '((name (syntax-rules ...)))' form but got: " + write_to_string( x )
2256
- elsif not ( x.car.second.first == :"syntax-rules" or x.car.second.first == :"%syntax-rules")
2257
- raise SyntaxError, "Error: let-syntax get only '((name (syntax-rules ...)))' form but got: " + write_to_string( x )
2258
- end
2259
- }
2260
- arr_tmp = sexp.second.map { |x|
2261
- [ x.car.first, __expandSyntaxRules( x.car.second, syntaxArray, lexicalVars ) ]
2262
- }
2263
- arr = arr_tmp.map {|x|
2264
- [ x[0], __evalSyntaxRules( x[1], lexicalVars ), x[1], lexicalVars ]
2265
- }
2266
-
2267
- # trial (expand recursively)
2268
- arr_tmp = arr.map { |x|
2269
- [ x[0], __expandSyntaxRules( x[2], syntaxArray + arr, lexicalVars ) ]
2270
- }
2271
- arr = arr_tmp.map {|x|
2272
- [ x[0], __evalSyntaxRules( x[1], lexicalVars ), x[1], lexicalVars ]
2273
- }
2274
-
2275
- # keywords = ((let-syntax-keyword ( let-syntax-body ))
2276
- # (let-syntax-keyword ( let-syntax-body ))
2277
- # ..)
2278
- newKeywords = arr.map { |e|
2279
- [ e[0], [ :"%syntax-rules", e[1]].to_list ].to_list
2280
- }.to_list
2281
-
2282
- ret = Cell.new( :"let-syntax",
2283
- Cell.new( newKeywords, macroexpandEngine( sexp.cdr.cdr, syntaxArray + arr, lexicalVars )))
2284
-
2285
- ret
2286
- else
2287
- sym = toRubySymbol( car.to_s )
2288
- newSexp = sexp
2289
- if isRubyInterface( sym )
2290
- # do nothing
2291
- sexp
2292
- elsif _symbol_QUMARK( car ) and eval( sprintf( "(defined? @%s and LispMacro == @%s.class)", sym,sym ), @binding )
2293
- eval( sprintf( "@__macro = @%s", sym ), @binding )
2294
- newSexp = trampCall( callProcedure( nil, sym, @__macro, sexp.cdr.to_arr ))
2295
- elsif _symbol_QUMARK( car ) and eval( sprintf( "(defined? @%s and LispSyntax == @%s.class)", sym,sym ), @binding )
2296
- # expected input is
2297
- # (syntaxName arg1 arg2 ...)
2298
- # will be transformed
2299
- # (syntaxName (syntaxName arg1 arg2 ...) () (global-variables))
2300
- eval( sprintf( "@__syntax = @%s", sym ), @binding )
2301
- newSexp = trampCall( callProcedure( nil, sym, @__syntax, [ sexp, Cell.new(), _global_MIMARKvariables( ) ] ))
2302
- elsif _symbol_QUMARK( car ) and syntaxArray.map {|arr| arr[0].intern}.include?( car.intern )
2303
- # lexical macro expandeding
2304
- symbol_and_syntaxObj = syntaxArray.reverse.find {|arr| car == arr[0]}
2305
- keys = syntaxArray.reverse.map { |arr| arr[0] }
2306
- if not symbol_and_syntaxObj
2307
- raise "can't find valid syntaxObject"
2308
- end
2309
- vars = symbol_and_syntaxObj[3].map { |arr| arr[0] }
2310
- lexvars = @syntaxHash[ symbol_and_syntaxObj[1] ][0]
2311
- lispSyntax = @syntaxHash[ symbol_and_syntaxObj[1] ][1]
2312
- newSexp = trampCall( callProcedure( nil, symbol_and_syntaxObj[0], lispSyntax, [
2313
- sexp,
2314
- Cell.new(),
2315
- (_global_MIMARKvariables( ).to_arr + keys + vars).to_list ] ))
2316
- newSexp = __wrapNestedLet( newSexp, __removeSameLexicalScopeVariables( lexicalVars + lexvars ))
2317
- end
2318
- if _equal_QUMARK( newSexp, sexp )
2319
- sexp.map { |x|
2320
- if x.car.is_a? Cell
2321
- macroexpandEngine( x.car, syntaxArray, lexicalVars )
2322
- else
2323
- x.car
2324
- end
2325
- }.to_list( sexp.lastAtom, sexp.getLastAtom )
2326
- else
2327
- @macroExpandCount -= 1
2328
- newSexp
2329
- end
2330
- end
2331
- else
2332
- sexp
2333
- end
2334
- end
2335
-
2336
- def macroexpandPhase( sexp )
2337
- macroexpandInit( 100000 )
2338
- _strip_MIMARKlet_MIMARKsyntax_MIMARKkeyword(
2339
- _strip_MIMARKsyntax_MIMARKquote(
2340
- macroexpandEngineLoop( sexp, [], [] )))
2341
- end
2342
-
2343
- def ppRubyExp( level, exp )
2344
- indent = @indent * level
2345
- exp.map { |x|
2346
- if Array == x.class
2347
- ppRubyExp( level+1, x )
2348
- else
2349
- str = sprintf( "%s", x )
2350
- if str.match( /^[,]/ ) or str.match( /^ = / )
2351
- sprintf( "%s%s", indent, str )
2352
- else
2353
- sprintf( "\n%s%s", indent, str )
2354
- end
2355
- end
2356
- }
2357
- end
2358
-
2359
- def displayTopOfCalls( exception )
2360
- if @displayErrorsFlag
2361
- STDERR.puts( "\n <<< Top of calls >>>" )
2362
- strs = []
2363
- @call_counters.each_key { |funcname|
2364
- if 0 < @call_counters[ funcname ]
2365
- strs << sprintf( " %7d : %-20s", @call_counters[ funcname ], funcname )
2366
- end
2367
- }
2368
- strs.sort.reverse.each { |str|
2369
- STDERR.puts( str )
2370
- }
2371
- end
2372
- end
2373
-
2374
- def displayBacktrace( exception )
2375
- if @displayErrorsFlag
2376
- STDERR.puts( "\n <<< Backtrace of Nendo >>>" )
2377
- arr = @backtrace.map { |key,val| [key,val] }.sort_by { |x| x[1] }.reverse
2378
- arr[0...10].each { |x|
2379
- STDERR.printf( " from %s \n", x[0] )
2380
- }
2381
- STDERR.puts( " ...\n\n" )
2382
- end
2383
- end
2384
-
2385
- def lispEval( sexp, sourcefile, lineno )
2386
- begin
2387
- sourceInfo = SourceInfo.new
2388
- @lastSourcefile = sourcefile
2389
- @lastLineno = lineno
2390
- sourceInfo.setSource( sourcefile, lineno, sexp )
2391
-
2392
- # macro expand phase
2393
- sexp = macroexpandPhase( sexp )
2394
- if @debug
2395
- printf( "\n expaneded=<<< %s >>>\n", (Printer.new())._print(sexp))
2396
- end
2397
-
2398
- # compiling phase written
2399
- origsym = "%compile-phase"
2400
- sym = toRubySymbol( origsym )
2401
- if ( eval( sprintf( "(defined? @%s and Proc == @%s.class)", sym,sym ), @binding ))
2402
- eval( sprintf( "@___tmp = @%s", sym ), @binding )
2403
- sexp = trampCall( callProcedure( nil, origsym, @___tmp, [ sexp ]))
2404
- if @debug
2405
- printf( "\n compiled= <<< %s >>>\n", (Printer.new())._print(sexp))
2406
- end
2407
- end
2408
- sourceInfo.setExpanded( sexp )
2409
-
2410
- arr = [ "trampCall( ", translate( sexp, [], sourceInfo ), " )" ]
2411
- rubyExp = ppRubyExp( 0, arr ).flatten.join
2412
- sourceInfo.setCompiled( rubyExp )
2413
- if not @compiled_code.has_key?( sourcefile )
2414
- @compiled_code[ sourcefile ] = Array.new
2415
- end
2416
- @compiled_code[ sourcefile ] << rubyExp
2417
- if sourceInfo.varname
2418
- @source_info_hash[ sourceInfo.varname ] = sourceInfo
2419
- end
2420
- printf( " rubyExp=<<<\n%s\n>>>\n", rubyExp ) if @debug
2421
- eval( rubyExp, @binding, @lastSourcefile, @lastLineno )
2422
- rescue SystemStackError => e
2423
- displayTopOfCalls( e )
2424
- raise e
2425
- rescue => e
2426
- displayBacktrace( e )
2427
- raise e
2428
- end
2429
- end
2430
-
2431
- def __PAMARKload( filename )
2432
- printer = Printer.new( @debug )
2433
- open( filename, "r:utf-8" ) {|f|
2434
- reader = Reader.new( f, filename, false )
2435
- while true
2436
- lineno = reader.lineno
2437
- s = reader._read
2438
- if s[1] # EOF?
2439
- break
2440
- elsif Nil != s[0].class
2441
- printf( "\n readExp=<<< %s >>>\n", printer._print(s[0]) ) if @debug
2442
- self.lispEval( s[0], reader.sourcefile, lineno )
2443
- end
2444
- end
2445
- }
2446
- forward_gensym_counter()
2447
- end
2448
-
2449
- def _load_MIMARKcompiled_MIMARKcode_MIMARKfrom_MIMARKstring( rubyExp )
2450
- eval( rubyExp, @binding )
2451
- forward_gensym_counter()
2452
- end
2453
-
2454
- def __PAMARKload_MIMARKcompiled_MIMARKcode( filename )
2455
- open( filename, "r:utf-8" ) { |f|
2456
- eval( f.read, @binding )
2457
- }
2458
- forward_gensym_counter()
2459
- end
2460
-
2461
- def _clean_MIMARKcompiled_MIMARKcode
2462
- @compiled_code = Hash.new
2463
- end
2464
-
2465
- def _get_MIMARKcompiled_MIMARKcode
2466
- @compiled_code
2467
- ret = Hash.new
2468
- @compiled_code.each_key { |key|
2469
- ret[key] = @compiled_code[key].to_list
2470
- ret[key]
2471
- }
2472
- ret.to_list
2473
- end
2474
-
2475
- def _eval( sexp )
2476
- self.lispEval( sexp, "dynamic S-expression ( no source )", 1 )
2477
- end
2478
-
2479
- def _enable_MIMARKidebug()
2480
- @debug = true
2481
- end
2482
- def _disable_MIMARKidebug()
2483
- @debug = false
2484
- end
2485
- def _enable_MIMARKtrace()
2486
- @trace_debug = true
2487
- end
2488
- def _disable_MIMARKtrace()
2489
- @trace_debug = false
2490
- end
2491
- def _set_MIMARKoptimize_MIMARKlevel(level)
2492
- self.setOptimizeLevel( level )
2493
- end
2494
- def _get_MIMARKoptimize_MIMARKlevel()
2495
- self.getOptimizeLevel
2496
- end
2497
-
2498
- def _get_MIMARKsource_MIMARKinfo( varname )
2499
- info = @source_info_hash[ varname.to_s ]
2500
- if info
2501
- [
2502
- Cell.new( "varname", info.varname ),
2503
- Cell.new( "sourcefile", info.sourcefile ),
2504
- Cell.new( "lineno", info.lineno ),
2505
- Cell.new( "source", info.source_sexp ),
2506
- Cell.new( "expanded", info.expanded_sexp ),
2507
- Cell.new( "compiled_str", info.compiled_str ) ].to_list
2508
- else
2509
- raise NameError, sprintf( "Error: not found variable [%s]. \n", varname.to_s )
2510
- end
2511
- end
2512
-
2513
- def __PAMARKexport_MIMARKto_MIMARKruby( origname, pred )
2514
- if toRubySymbol( origname ) != ("_" + origname)
2515
- raise ArgumentError, "Error: %export-to-ruby requires function name in ruby method naming rule."
2516
- end
2517
- if not _procedure_QUMARK( pred )
2518
- raise ArgumentError, "Error: %export-to-ruby requires 'pred' as a Proc instance."
2519
- end
2520
- if 0 > pred.arity
2521
- raise ArgumentError, "Error: %export-to-ruby requires only a function that have fixed length argument."
2522
- end
2523
- if self.methods.include?( origname.intern ) or @core.methods.include?( origname.intern )
2524
- raise RuntimeError, "Error: %export-to-ruby: Nendo::Core." + origname + " method was already deifned."
2525
- end
2526
-
2527
- argsStr = (1..(pred.arity)).map { |n| "arg" + n.to_s }.join( "," )
2528
- str = [ "def self." + origname + "(" + argsStr + ")",
2529
- sprintf( " trampCall( callProcedure( nil, '%s', @_%s, [ " + argsStr + " ] )) ",
2530
- origname, origname ),
2531
- "end ;",
2532
- "def @core." + origname + "(" + argsStr + ")",
2533
- " @evaluator." + origname + "(" + argsStr + ") ",
2534
- "end"
2535
- ].join
2536
- eval( str, @binding )
2537
- true
2538
- end
2539
-
2540
- def __setupLexicalScopeVariables( lexicalVars )
2541
- @lexicalVars = lexicalVars.clone
2542
- end
2543
-
2544
- def _make_MIMARKsyntactic_MIMARKclosure( mac_env, use_env, identifier )
2545
- if _pair_QUMARK( identifier )
2546
- if :"syntax-quote" == identifier.car
2547
- identifier
2548
- else
2549
- raise TypeError, "make-syntactic-closure requires symbol or (syntax-quote sexp) only. but got: " + write_to_string( identifier )
2550
- end
2551
- elsif _symbol_QUMARK( identifier )
2552
- # pp [ "identifier: ", identifier, "include?=", mac_env.to_arr.include?( identifier.intern ) ]
2553
- # pp [ "mac_env: ", mac_env.to_arr ]
2554
- if mac_env.to_arr.include?( identifier.intern )
2555
- found = @lexicalVars.find { |x| identifier == x[0] }
2556
- if found
2557
- lexvars = @lexicalVars.clone
2558
- __wrapNestedLet( identifier, lexvars )
2559
- else
2560
- identifier
2561
- end
2562
- else
2563
- SyntacticClosure.new( identifier, (toRubySymbol( identifier ) + _gensym( ).to_s).intern )
2564
- end
2565
- else
2566
- raise TypeError, "make-syntactic-closure requires symbol or (syntax-quote sexp) type."
2567
- end
2568
- end
2569
-
2570
- def _strip_MIMARKsyntax_MIMARKquote( sexp )
2571
- case sexp
2572
- when Cell
2573
- if _null_QUMARK( sexp )
2574
- sexp
2575
- else
2576
- car = sexp.car
2577
- if :"syntax-quote" == car or @core_syntax_hash[ :"syntax-quote" ] == car
2578
- Cell.new( :quote, sexp.cdr )
2579
- else
2580
- Cell.new(
2581
- _strip_MIMARKsyntax_MIMARKquote( sexp.car ),
2582
- _strip_MIMARKsyntax_MIMARKquote( sexp.cdr ))
2583
- end
2584
- end
2585
- else
2586
- sexp
2587
- end
2588
- end
2589
-
2590
- def _strip_MIMARKlet_MIMARKsyntax_MIMARKkeyword( sexp )
2591
- case sexp
2592
- when Cell
2593
- if _null_QUMARK( sexp )
2594
- sexp
2595
- else
2596
- car = sexp.car
2597
- if :"quote" == car or @core_syntax_hash[ :"quote" ] == car
2598
- sexp
2599
- elsif :"let-syntax" == car or @core_syntax_hash[ :"let-syntax" ] == car
2600
- Cell.new( :begin,
2601
- _strip_MIMARKlet_MIMARKsyntax_MIMARKkeyword( sexp.cdr.cdr ))
2602
- else
2603
- Cell.new(
2604
- _strip_MIMARKlet_MIMARKsyntax_MIMARKkeyword( sexp.car ),
2605
- _strip_MIMARKlet_MIMARKsyntax_MIMARKkeyword( sexp.cdr ))
2606
- end
2607
- end
2608
- else
2609
- sexp
2610
- end
2611
- end
2612
-
2613
- def _strip_MIMARKsyntactic_MIMARKclosures( sexp )
2614
- case sexp
2615
- when Cell
2616
- if _null_QUMARK( sexp )
2617
- sexp
2618
- else
2619
- Cell.new(
2620
- _strip_MIMARKsyntactic_MIMARKclosures( sexp.car ),
2621
- _strip_MIMARKsyntactic_MIMARKclosures( sexp.cdr ))
2622
- end
2623
- else
2624
- if sexp.is_a? SyntacticClosure
2625
- sexp.intern
2626
- else
2627
- sexp
2628
- end
2629
- end
2630
- end
2631
-
2632
- def _symbol_MIMARKinclude_QUMARK( sexp, sym )
2633
- case sexp
2634
- when Cell
2635
- if _null_QUMARK( sexp )
2636
- false
2637
- else
2638
- _symbol_MIMARKinclude_QUMARK( sexp.car, sym ) or _symbol_MIMARKinclude_QUMARK( sexp.cdr, sym )
2639
- end
2640
- else
2641
- if _symbol_QUMARK( sexp )
2642
- sym.intern == sexp.intern
2643
- else
2644
- false
2645
- end
2646
- end
2647
- end
2648
- end
2649
-
2650
- class Printer
2651
- def initialize( debug = false )
2652
- @debug = debug
2653
- end
2654
-
2655
- def __write( sexp, readable )
2656
- getQuoteKeyword = lambda { |x|
2657
- case x
2658
- when :"dot-operator"
2659
- "."
2660
- else
2661
- false
2662
- end
2663
- }
2664
- case sexp
2665
- when Cell
2666
- arr = sexp.map { |x| __write( x.car, readable ) }
2667
- lastAtom = sexp.lastAtom
2668
- lastAtomStr = lastAtom ? __write( sexp.getLastAtom, readable ) : ""
2669
- keyword = getQuoteKeyword.call( sexp.car )
2670
- if keyword
2671
- keyword + arr[1..-1].join( " " ) + (lastAtom ? " . " + lastAtomStr : "")
2672
- else
2673
- "(" + arr.join( " " ) + (lastAtom ? " . " + lastAtomStr : "") + ")"
2674
- end
2675
- when Array # is a vector in the Nendo world.
2676
- arr = sexp.map { |x| __write( x, readable ) }
2677
- "#(" + arr.join( " " ) + ")"
2678
- when true
2679
- "#t"
2680
- when false
2681
- "#f"
2682
- when Symbol
2683
- keyword = getQuoteKeyword.call( sexp )
2684
- if keyword
2685
- keyword
2686
- else
2687
- sprintf( "%s", sexp.to_s )
2688
- end
2689
- when String, LispString
2690
- if readable
2691
- sprintf( "\"%s\"", LispString.escape( sexp.to_s ))
2692
- else
2693
- sexp.to_s
2694
- end
2695
- when SyntacticClosure
2696
- sprintf( "#<SyntacticClosure[%s:%s]>", sexp.originalSymbol, sexp.renamedSymbol )
2697
- when Regexp
2698
- "#/" + sexp.source + "/" + (sexp.casefold? ? "i" : "")
2699
- when LispKeyword
2700
- ":" + sexp.key.to_s
2701
- when LispCoreSyntax
2702
- "#<Nendo::LispCoreSyntax>"
2703
- when LispMacro
2704
- "#<Nendo::LispMacro>"
2705
- when LispSyntax
2706
- "#<Nendo::LispSyntax>"
2707
- when Nil
2708
- "()"
2709
- when nil
2710
- "nil"
2711
- else
2712
- sprintf( "%s", sexp )
2713
- end
2714
- end
2715
-
2716
- def _print( sexp )
2717
- self.__write( sexp, false )
2718
- end
2719
- def _write( sexp )
2720
- self.__write( sexp, true )
2721
- end
2722
- end
2723
-
2724
-
2725
- class Core
2726
- def initialize( debug_evaluator = false, debug_printer = false )
2727
- @debug_evaluator = debug_evaluator
2728
- @evaluator = Evaluator.new( self, debug_evaluator )
2729
- @debug_printer = debug_printer
2730
- end
2731
-
2732
- def self.version
2733
- "0.5.4" ##NENDO-VERSION
2734
- end
2735
-
2736
- attr_reader :evaluator
2737
-
2738
- def loadInitFile( use_compiled = true )
2739
- done = false
2740
- if use_compiled
2741
- compiled_file = File.dirname(__FILE__) + "/init.nndc"
2742
- if File.exist?( compiled_file )
2743
- @evaluator.__PAMARKload_MIMARKcompiled_MIMARKcode( compiled_file )
2744
- done = true
2745
- end
2746
- end
2747
- unless done
2748
- @evaluator.__PAMARKload( File.dirname(__FILE__) + "/init.nnd" )
2749
- @evaluator.__PAMARKload( File.dirname(__FILE__) + "/init.nnd" ) # for %tailcall compile for init.nnd
2750
- end
2751
- end
2752
-
2753
- def load( path )
2754
- @evaluator.__PAMARKload( path )
2755
- end
2756
-
2757
- def load_compiled_code( path )
2758
- @evaluator.__PAMARKload_MIMARKcompiled_MIMARKcode( path )
2759
- end
2760
-
2761
- def load_compiled_code_from_string( rubyExp )
2762
- @evaluator._load_MIMARKcompiled_MIMARKcode_MIMARKfrom_MIMARKstring( rubyExp )
2763
- end
2764
-
2765
- def setArgv( argv )
2766
- @evaluator.setArgv( argv )
2767
- end
2768
-
2769
- def setOptimizeLevel( level )
2770
- @evaluator.setOptimizeLevel( level )
2771
- end
2772
-
2773
- def setDisplayErrors( flag )
2774
- @evaluator.setDisplayErrors( flag )
2775
- end
2776
-
2777
- def clean_compiled_code
2778
- @evaluator._clean_MIMARKcompiled_MIMARKcode()
2779
- end
2780
-
2781
- def prompt
2782
- STDERR.print "nendo> "
2783
- end
2784
-
2785
- def repl
2786
- printer = Printer.new( @debug_printer )
2787
- reader = Reader.new( STDIN, "(stdin)", false )
2788
- self.prompt
2789
- while true
2790
- begin
2791
- lineno = reader.lineno
2792
- s = reader._read
2793
- if s[1] # EOF?
2794
- break
2795
- elsif not s[0].is_a? Nil
2796
- printf( "\n readExp=<<< %s >>>\n", printer._write(s[0]) ) if @debug_evaluator
2797
- STDERR.print printer._write( @evaluator.lispEval( s[0], reader.sourcefile, lineno )) + "\n"
2798
- self.prompt
2799
- end
2800
- rescue => e
2801
- print e.message + "\n"
2802
- e.backtrace.each { |x| printf( "\tfrom %s\n", x ) }
2803
- print "\n"
2804
- self.prompt
2805
- end
2806
- end
2807
- end
2808
-
2809
- def evalStr( str )
2810
- printer = Printer.new( @debug_printer )
2811
- sio = StringIO.open( str )
2812
- reader = Reader.new( sio, "(string)", false )
2813
- result = nil
2814
- while true
2815
- lineno = reader.lineno
2816
- s = reader._read
2817
- if s[1] # EOF?
2818
- break
2819
- elsif not s[0].is_a? Nil
2820
- printf( "\n readExp=<<< %s >>>\n", printer._write(s[0]) ) if @debug_evaluator
2821
- result = printer._write( @evaluator.lispEval( s[0], reader.sourcefile, lineno ))
2822
- end
2823
- end
2824
- result
2825
- end
2826
- end
2827
- end
2828
-
2829
-
2830
-
2831
-
2832
- class Symbol
2833
- def setLispToken( token )
2834
- @token = token
2835
- end
2836
- def sourcefile
2837
- @token ? @token.sourcefile : ""
2838
- end
2839
- def lineno
2840
- @token ? @token.lineno : 1
2841
- end
2842
- end
2843
-
2844
- class Array
2845
- def to_list( lastAtom = false, value = Nendo::Nil.new )
2846
- if 0 == self.length
2847
- Nendo::Cell.new()
2848
- else
2849
- cells = self.map { |x|
2850
- Nendo::Cell.new( x )
2851
- }
2852
- ptr = cells.pop
2853
- ptr.cdr = value if lastAtom
2854
- cells.reverse.each { |x|
2855
- x.cdr = ptr
2856
- ptr = x
2857
- }
2858
- return ptr
2859
- end
2860
- end
2861
- end
2862
-
2863
- class Hash
2864
- def to_list
2865
- arr = Array.new
2866
- self.each_pair { |key,val|
2867
- arr << Nendo::Cell.new( key, val )
2868
- }
2869
- arr.to_list
2870
- end
2871
- end
35
+ require 'stringio'
36
+ require 'digest/sha1'
37
+ require 'pp'
38
+ require 'ruby/types'
39
+ require 'ruby/reader'
40
+ require 'ruby/builtin_functions'
41
+ require 'ruby/evaluator'
42
+ require 'ruby/printer'
43
+ require 'ruby/core'
44
+ require 'ruby/out_of_module'
2872
45