nendo 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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