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 +16 -2843
- data/lib/ruby/builtin_functions.rb +510 -0
- data/lib/ruby/core.rb +140 -0
- data/lib/ruby/evaluator.rb +1349 -0
- data/lib/ruby/out_of_module.rb +74 -0
- data/lib/ruby/printer.rb +111 -0
- data/lib/ruby/reader.rb +585 -0
- data/lib/ruby/types.rb +309 -0
- metadata +12 -5
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
|