nendo 0.3.3 → 0.3.4
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/bin/nendo +2 -2
- data/emacs/nendo-mode.el +126 -0
- data/example/KyotoCabinet/kcbench.rb +20 -0
- data/example/KyotoCabinet/kcbench1.nnd +29 -0
- data/example/KyotoCabinet/kcbench2.nnd +30 -0
- data/example/KyotoCabinet/kcbench3.nnd +31 -0
- data/example/export-lisp-functions.rb +20 -0
- data/example/scratch.nnd +8 -17
- data/example/tak_ruby_version.rb +14 -0
- data/lib/debug/syslog.nndc +1 -1
- data/lib/init.nnd +334 -202
- data/lib/init.nndc +5691 -4128
- data/lib/nendo/test.nnd +165 -0
- data/lib/nendo/test.nndc +1635 -0
- data/lib/nendo.rb +248 -37
- data/lib/srfi-1.nnd +15 -24
- data/lib/srfi-1.nndc +1247 -1607
- data/lib/text/html-lite.nnd +1 -1
- data/lib/text/html-lite.nndc +171 -171
- data/lib/text/tree.nndc +2 -2
- data/test/nendo_spec.rb +1281 -981
- data/test/nendo_util.nnd +98 -0
- data/test/srfi-1-test.nnd +28 -0
- data/test/textlib.nnd +24 -0
- metadata +13 -3
data/lib/nendo.rb
CHANGED
@@ -153,6 +153,17 @@ module Nendo
|
|
153
153
|
attr_reader :values
|
154
154
|
end
|
155
155
|
|
156
|
+
class LispRegexp
|
157
|
+
def initialize( str )
|
158
|
+
@exp = str[ 1 ... str.size ]
|
159
|
+
@ignoreCase = (str[0] == 'i')
|
160
|
+
end
|
161
|
+
def escape
|
162
|
+
@exp.gsub( /\\/, "\\\\\\\\" )
|
163
|
+
end
|
164
|
+
attr_reader :ignoreCase
|
165
|
+
end
|
166
|
+
|
156
167
|
class LispKeyword
|
157
168
|
def initialize( str )
|
158
169
|
@key = str.intern
|
@@ -176,6 +187,49 @@ module Nendo
|
|
176
187
|
|
177
188
|
attr_reader :key
|
178
189
|
end
|
190
|
+
|
191
|
+
class SourceInfo
|
192
|
+
def initialize
|
193
|
+
@varname = nil
|
194
|
+
@sourcefile = nil
|
195
|
+
@lineno = nil
|
196
|
+
@source_sexp = Cell.new
|
197
|
+
@expanded_sexp = Cell.new
|
198
|
+
@compiled_str = nil
|
199
|
+
end
|
200
|
+
|
201
|
+
def deepCopy( sexp )
|
202
|
+
Marshal.load(Marshal.dump( sexp ))
|
203
|
+
end
|
204
|
+
|
205
|
+
def setVarname( varname )
|
206
|
+
@varname = varname
|
207
|
+
end
|
208
|
+
|
209
|
+
def setSource( sourcefile, lineno, source_sexp )
|
210
|
+
@sourcefile = sourcefile
|
211
|
+
@lineno = lineno
|
212
|
+
@source_sexp = self.deepCopy( source_sexp )
|
213
|
+
end
|
214
|
+
|
215
|
+
def setExpanded( expanded_sexp )
|
216
|
+
@expanded_sexp = self.deepCopy( expanded_sexp )
|
217
|
+
end
|
218
|
+
|
219
|
+
def setCompiled( compiled_str )
|
220
|
+
@compiled_str = compiled_str
|
221
|
+
end
|
222
|
+
|
223
|
+
def debugPrint
|
224
|
+
printf( "=== sourceInfo === \n" )
|
225
|
+
printf( " varname = %s\n", @varname )
|
226
|
+
printf( " sourcefile = %s\n", @sourcefile )
|
227
|
+
printf( " lineno = %s\n", @lineno)
|
228
|
+
printf( " compiled_str = %s\n", @compiled_str )
|
229
|
+
end
|
230
|
+
|
231
|
+
attr_reader :varname, :sourcefile, :lineno, :source_sexp, :expanded_sexp, :compiled_str
|
232
|
+
end
|
179
233
|
|
180
234
|
class DelayedCallPacket
|
181
235
|
def initialize( _origname, _pred, _args )
|
@@ -261,6 +315,7 @@ module Nendo
|
|
261
315
|
T_LINEFEED = :t_linefeed
|
262
316
|
T_COMMENT = :t_comment
|
263
317
|
T_DEBUG_PRINT = :t_debug_print
|
318
|
+
T_REGEXP = :t_regexp
|
264
319
|
|
265
320
|
# inport is IO class
|
266
321
|
def initialize( inport, sourcefile, debug = false )
|
@@ -362,7 +417,33 @@ module Nendo
|
|
362
417
|
end
|
363
418
|
ret
|
364
419
|
end
|
365
|
-
|
420
|
+
|
421
|
+
def readRegexp()
|
422
|
+
ret = ""
|
423
|
+
while true
|
424
|
+
ch = @chReader.getc
|
425
|
+
#printf( " readRegexp1: [%s]\n", ch )
|
426
|
+
if !ch # eof?
|
427
|
+
break
|
428
|
+
end
|
429
|
+
if ch.chr == "\\" #escape
|
430
|
+
ch2 = @chReader.getc
|
431
|
+
#printf( " readRegexp2: [%s]\n", ch2 )
|
432
|
+
if ch2.chr == '/'
|
433
|
+
ret += ch2.chr # drop escape "\\" char
|
434
|
+
else
|
435
|
+
ret += ch.chr
|
436
|
+
ret += ch2.chr
|
437
|
+
end
|
438
|
+
elsif ch.chr == '/'
|
439
|
+
break
|
440
|
+
else
|
441
|
+
ret += ch.chr
|
442
|
+
end
|
443
|
+
end
|
444
|
+
ret
|
445
|
+
end
|
446
|
+
|
366
447
|
def tokenWithComment
|
367
448
|
skipspace
|
368
449
|
ch = @chReader.getc
|
@@ -401,7 +482,7 @@ module Nendo
|
|
401
482
|
str = ""
|
402
483
|
T_COMMENT
|
403
484
|
when /[#]/
|
404
|
-
nextch = peekchar( /[?!tfbodx(]/ )
|
485
|
+
nextch = peekchar( /[?!tfbodx(\/]/ )
|
405
486
|
case nextch
|
406
487
|
when "?"
|
407
488
|
if peekchar( /[=]/ )
|
@@ -454,6 +535,11 @@ module Nendo
|
|
454
535
|
end
|
455
536
|
str = Integer( str ).to_s
|
456
537
|
T_NUM
|
538
|
+
when "/" # T_REGEXP's str takes "iXXXXX"(igreno case) or " XXXXXX"(case sensitive) value.
|
539
|
+
readwhile( /[\/]/ ) # consume
|
540
|
+
str = readRegexp()
|
541
|
+
str = ((0 < readwhile( /[i]/ ).size) ? "i" : " ") + str
|
542
|
+
T_REGEXP
|
457
543
|
else
|
458
544
|
str += readwhile( /[^ \t\r\n]/ )
|
459
545
|
raise NameError, sprintf( "Error: unknown #xxxx syntax for Nendo %s", str )
|
@@ -526,6 +612,8 @@ module Nendo
|
|
526
612
|
end
|
527
613
|
when T_STRING
|
528
614
|
cur.str
|
615
|
+
when T_REGEXP
|
616
|
+
LispRegexp.new( cur.str )
|
529
617
|
when T_QUOTE
|
530
618
|
:quote
|
531
619
|
when T_QUASIQUOTE
|
@@ -557,7 +645,12 @@ module Nendo
|
|
557
645
|
when T_LINEFEED
|
558
646
|
token # skipEnter
|
559
647
|
when T_EOF
|
560
|
-
|
648
|
+
begin
|
649
|
+
raise RuntimeError, "Error: unbalanced vector's paren(4)"
|
650
|
+
rescue => e
|
651
|
+
e.set_backtrace( [sprintf( "%s:%d", curtoken.sourcefile, curtoken.lineno )] + e.backtrace )
|
652
|
+
raise e
|
653
|
+
end
|
561
654
|
when T_LPAREN, T_LVECTOR
|
562
655
|
arr << sexp()
|
563
656
|
when T_RPAREN
|
@@ -586,7 +679,12 @@ module Nendo
|
|
586
679
|
when T_LINEFEED
|
587
680
|
token # skipEnter
|
588
681
|
when T_EOF
|
589
|
-
|
682
|
+
begin
|
683
|
+
raise RuntimeError, "Error: unbalanced paren(1)"
|
684
|
+
rescue => e
|
685
|
+
e.set_backtrace( [sprintf( "%s:%d", curtoken.sourcefile, curtoken.lineno )] + e.backtrace )
|
686
|
+
raise e
|
687
|
+
end
|
590
688
|
when T_LPAREN, T_LVECTOR
|
591
689
|
cells << Cell.new( sexp() )
|
592
690
|
when T_RPAREN
|
@@ -644,7 +742,12 @@ module Nendo
|
|
644
742
|
token
|
645
743
|
sexp()
|
646
744
|
when T_EOF
|
647
|
-
|
745
|
+
begin
|
746
|
+
raise RuntimeError, "Error: unbalanced paren(2)"
|
747
|
+
rescue => e
|
748
|
+
e.set_backtrace( [sprintf( "%s:%d", curtoken.sourcefile, curtoken.lineno )] + e.backtrace )
|
749
|
+
raise e
|
750
|
+
end
|
648
751
|
when T_LPAREN
|
649
752
|
skipEnter
|
650
753
|
token # consume '('
|
@@ -653,7 +756,13 @@ module Nendo
|
|
653
756
|
token # consume ')'
|
654
757
|
ret
|
655
758
|
when T_RPAREN
|
656
|
-
|
759
|
+
token # consume ')'
|
760
|
+
begin
|
761
|
+
raise RuntimeError, "Error: unbalanced vector's paren(3)"
|
762
|
+
rescue => e
|
763
|
+
e.set_backtrace( [sprintf( "%s:%d", curtoken.sourcefile, curtoken.lineno )] + e.backtrace )
|
764
|
+
raise e
|
765
|
+
end
|
657
766
|
when T_LVECTOR
|
658
767
|
skipEnter
|
659
768
|
token # consume '#('
|
@@ -901,7 +1010,6 @@ module Nendo
|
|
901
1010
|
end
|
902
1011
|
end
|
903
1012
|
def _list( *args) args[0] end
|
904
|
-
def _sort( arg ) arg.to_arr.sort.to_list end
|
905
1013
|
def _reverse( arg ) arg.to_arr.reverse.to_list end
|
906
1014
|
def _uniq( arg ) arg.to_arr.uniq.to_list end
|
907
1015
|
def _range( num, *args )
|
@@ -946,6 +1054,13 @@ module Nendo
|
|
946
1054
|
(Cell == arg.class)
|
947
1055
|
end
|
948
1056
|
end
|
1057
|
+
def __PAMARKlist_QUMARK( arg )
|
1058
|
+
if _pair_QUMARK( arg )
|
1059
|
+
(not arg.lastAtom) and (1 <= arg.to_arr.size) # it means proper list?
|
1060
|
+
else
|
1061
|
+
_null_QUMARK( arg )
|
1062
|
+
end
|
1063
|
+
end
|
949
1064
|
def _integer_QUMARK( arg ) arg.is_a? Integer end
|
950
1065
|
def _number_QUMARK( arg ) arg.is_a? Numeric end
|
951
1066
|
def _string_QUMARK( arg ) String == arg.class end
|
@@ -1000,7 +1115,7 @@ module Nendo
|
|
1000
1115
|
end
|
1001
1116
|
end
|
1002
1117
|
def _require( arg )
|
1003
|
-
|
1118
|
+
require( arg )
|
1004
1119
|
false
|
1005
1120
|
end
|
1006
1121
|
def _read( *args )
|
@@ -1076,11 +1191,9 @@ module Nendo
|
|
1076
1191
|
end
|
1077
1192
|
|
1078
1193
|
def _hash_MIMARKtable_MIMARKget( h, key, *args )
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
if h.has_key?( key )
|
1083
|
-
h[key]
|
1194
|
+
val = h[key]
|
1195
|
+
if val
|
1196
|
+
val
|
1084
1197
|
else
|
1085
1198
|
arr = args[0].to_arr
|
1086
1199
|
if 0 < arr.length
|
@@ -1092,11 +1205,13 @@ module Nendo
|
|
1092
1205
|
end
|
1093
1206
|
|
1094
1207
|
def _hash_MIMARKtable_MIMARKput_EXMARK( h, key, value )
|
1095
|
-
if !((key.is_a? String) or ( key.is_a? Symbol))
|
1096
|
-
raise TypeError, "Error: argument key requires String or Symbol.\n"
|
1097
|
-
end
|
1098
1208
|
h[key] = value
|
1099
1209
|
end
|
1210
|
+
|
1211
|
+
def _hash_MIMARKtable_MIMARKexist_QUMARK( h, key )
|
1212
|
+
# don't use h.has_key(k), because has_key method undefined on some database bindings. (e.g. KyotoCabinet)
|
1213
|
+
h[key] ? true : false
|
1214
|
+
end
|
1100
1215
|
|
1101
1216
|
# backtrace expects this format "filename:lineno: place message ". e.g. "init.nnd:10: in aaa macro.".
|
1102
1217
|
def _raise( exception, message, backtrace )
|
@@ -1120,6 +1235,7 @@ module Nendo
|
|
1120
1235
|
end
|
1121
1236
|
v[index] = value
|
1122
1237
|
end
|
1238
|
+
|
1123
1239
|
end
|
1124
1240
|
|
1125
1241
|
|
@@ -1130,10 +1246,12 @@ module Nendo
|
|
1130
1246
|
EXEC_TYPE_ANONYMOUS = 2
|
1131
1247
|
EXEC_TYPE_TAILCALL = 3
|
1132
1248
|
|
1133
|
-
def initialize( debug = false )
|
1249
|
+
def initialize( core, debug = false )
|
1250
|
+
@core = core
|
1134
1251
|
@indent = " "
|
1135
1252
|
@binding = binding
|
1136
1253
|
@debug = debug
|
1254
|
+
@trace_debug = false
|
1137
1255
|
@char_table_lisp_to_ruby = {
|
1138
1256
|
# list (! $ % & * + - . / : < = > ? @ ^ _ ~)
|
1139
1257
|
'!' => '_EXMARK',
|
@@ -1165,7 +1283,7 @@ module Nendo
|
|
1165
1283
|
x.to_s.match( /^_/ )
|
1166
1284
|
}.map { |name|
|
1167
1285
|
[
|
1168
|
-
defMethodStr( name ),
|
1286
|
+
defMethodStr( name, false ),
|
1169
1287
|
sprintf( "@%s = self.method( :%s ).to_proc", name, name ),
|
1170
1288
|
sprintf( "@global_lisp_binding['%s'] = self.method( :%s_METHOD ).to_proc", name, name ),
|
1171
1289
|
].join( " ; " )
|
@@ -1175,13 +1293,17 @@ module Nendo
|
|
1175
1293
|
# reset gensym counter
|
1176
1294
|
@gensym_counter = 0
|
1177
1295
|
|
1296
|
+
# call depth counter
|
1297
|
+
@call_depth = 0
|
1298
|
+
|
1178
1299
|
# init optimize level
|
1179
1300
|
@optimize_level = 1
|
1180
1301
|
|
1181
1302
|
# compiled ruby code
|
1182
1303
|
# { 'filename1' => [ 'code1' 'code2' ... ],
|
1183
1304
|
# 'filename2' => [ 'code1' 'code2' ... ], ... }
|
1184
|
-
@compiled_code
|
1305
|
+
@compiled_code = Hash.new
|
1306
|
+
@source_info_hash = Hash.new
|
1185
1307
|
|
1186
1308
|
global_lisp_define( toRubySymbol( "%compile-phase-functions" ), Cell.new())
|
1187
1309
|
end
|
@@ -1204,10 +1326,28 @@ module Nendo
|
|
1204
1326
|
@optimize_level
|
1205
1327
|
end
|
1206
1328
|
|
1207
|
-
def
|
1208
|
-
|
1329
|
+
def lispMethodEntry( name, _log )
|
1330
|
+
@call_depth += 1
|
1331
|
+
if @trace_debug and _log
|
1332
|
+
puts " " * @call_depth + "ENTRY: " + name
|
1333
|
+
end
|
1334
|
+
end
|
1335
|
+
def lispMethodExit( name, _log )
|
1336
|
+
if @trace_debug and _log
|
1337
|
+
puts " " * @call_depth + "exit: " + name
|
1338
|
+
end
|
1339
|
+
@call_depth -= 1
|
1209
1340
|
end
|
1210
1341
|
|
1342
|
+
def defMethodStr( name, _log )
|
1343
|
+
[ "def self." + name.to_s + "_METHOD( origname, pred, args ) ",
|
1344
|
+
" lispMethodEntry( origname, " + _log.to_s + " ) ; ",
|
1345
|
+
" ret = callProcedure( origname, pred, args ) ;",
|
1346
|
+
" lispMethodExit( origname, " + _log.to_s + " ) ; ",
|
1347
|
+
" return ret ",
|
1348
|
+
"end " ].join
|
1349
|
+
end
|
1350
|
+
|
1211
1351
|
def _gensym( )
|
1212
1352
|
@gensym_counter += 1
|
1213
1353
|
filename = if @lastSourcefile.is_a? String
|
@@ -1321,14 +1461,14 @@ module Nendo
|
|
1321
1461
|
end
|
1322
1462
|
|
1323
1463
|
def method_missing( name, *args )
|
1324
|
-
sym = toRubySymbol( name )
|
1464
|
+
sym = toRubySymbol( name )
|
1325
1465
|
if @global_lisp_binding[name].is_a? Proc
|
1326
1466
|
@global_lisp_binding[name].call( args[0], args[1], args[2] )
|
1327
1467
|
else
|
1328
1468
|
callProcedure( args[0], args[1], args[2] )
|
1329
1469
|
end
|
1330
1470
|
end
|
1331
|
-
|
1471
|
+
|
1332
1472
|
def delayCall( origname, pred, args )
|
1333
1473
|
case @optimize_level
|
1334
1474
|
when 0 # no optimize
|
@@ -1357,17 +1497,20 @@ module Nendo
|
|
1357
1497
|
}
|
1358
1498
|
end
|
1359
1499
|
|
1360
|
-
def execFunc( funcname, args, sourcefile, lineno, locals, execType )
|
1500
|
+
def execFunc( funcname, args, sourcefile, lineno, locals, sourceInfo, execType )
|
1361
1501
|
case funcname
|
1362
1502
|
when :define, :set! # `define' special form
|
1363
1503
|
ar = args.cdr.map { |x| x.car }
|
1364
1504
|
variable_sym = toRubySymbol( args.car.to_s.sub( /^:/, "" ))
|
1365
1505
|
global_cap = locals.flatten.include?( variable_sym.split( /[.]/ )[0] ) ? nil : "@"
|
1506
|
+
if global_cap and sourceInfo
|
1507
|
+
sourceInfo.setVarname( toLispSymbol( variable_sym ))
|
1508
|
+
end
|
1366
1509
|
[ "begin",
|
1367
1510
|
[
|
1368
1511
|
if global_cap
|
1369
1512
|
[
|
1370
|
-
defMethodStr( variable_sym ),
|
1513
|
+
defMethodStr( variable_sym, true ),
|
1371
1514
|
sprintf( "@global_lisp_binding['%s'] = self.method( :%s_METHOD )", variable_sym, variable_sym )
|
1372
1515
|
]
|
1373
1516
|
else
|
@@ -1471,6 +1614,8 @@ module Nendo
|
|
1471
1614
|
sprintf( "LispMacro.new { %s ", argStr )
|
1472
1615
|
when :lambda
|
1473
1616
|
sprintf( "Proc.new { %s ", argStr )
|
1617
|
+
when :"&block"
|
1618
|
+
sprintf( "&Proc.new { %s ", argStr )
|
1474
1619
|
else
|
1475
1620
|
raise "Error: makeClosure: unknown symbol type " + sym
|
1476
1621
|
end
|
@@ -1552,13 +1697,13 @@ module Nendo
|
|
1552
1697
|
"end"]
|
1553
1698
|
end
|
1554
1699
|
|
1555
|
-
def apply( car, cdr, sourcefile, lineno, locals, execType )
|
1700
|
+
def apply( car, cdr, sourcefile, lineno, locals, sourceInfo, execType )
|
1556
1701
|
cdr.each { |x|
|
1557
1702
|
if Cell == x.class
|
1558
|
-
x.car = translate( x.car, locals )
|
1703
|
+
x.car = translate( x.car, locals, sourceInfo )
|
1559
1704
|
end
|
1560
1705
|
}
|
1561
|
-
execFunc( car, cdr, sourcefile, lineno, locals, execType )
|
1706
|
+
execFunc( car, cdr, sourcefile, lineno, locals, sourceInfo, execType )
|
1562
1707
|
end
|
1563
1708
|
|
1564
1709
|
def genQuote( sexp, str = "" )
|
@@ -1638,7 +1783,7 @@ module Nendo
|
|
1638
1783
|
# (let ((c 3))
|
1639
1784
|
# (print (+ a b c))))
|
1640
1785
|
# => locals must be [["_a" "_b"]["_c"]] value.
|
1641
|
-
def translate( sexp, locals )
|
1786
|
+
def translate( sexp, locals, sourceInfo = nil )
|
1642
1787
|
case sexp
|
1643
1788
|
when Cell
|
1644
1789
|
if :quote == sexp.car
|
@@ -1648,13 +1793,15 @@ module Nendo
|
|
1648
1793
|
elsif sexp.isNull
|
1649
1794
|
[ "Cell.new()" ]
|
1650
1795
|
elsif Cell == sexp.car.class
|
1651
|
-
self.apply( translate( sexp.car, locals ), sexp.cdr, sexp.car.car.sourcefile, sexp.car.car.lineno, locals, EXEC_TYPE_ANONYMOUS )
|
1796
|
+
self.apply( translate( sexp.car, locals, sourceInfo ), sexp.cdr, sexp.car.car.sourcefile, sexp.car.car.lineno, locals, sourceInfo, EXEC_TYPE_ANONYMOUS )
|
1652
1797
|
elsif :begin == sexp.car
|
1653
1798
|
self.makeBegin( sexp.cdr, locals )
|
1654
1799
|
elsif :lambda == sexp.car
|
1655
1800
|
self.makeClosure( :lambda, sexp.cdr, locals )
|
1656
1801
|
elsif :macro == sexp.car
|
1657
1802
|
self.makeClosure( :macro, sexp.cdr, locals )
|
1803
|
+
elsif :"&block" == sexp.car
|
1804
|
+
self.makeClosure( :"&block", sexp.cdr, locals )
|
1658
1805
|
elsif :if == sexp.car
|
1659
1806
|
self.makeIf( sexp.cdr, locals )
|
1660
1807
|
elsif :let == sexp.car
|
@@ -1664,12 +1811,12 @@ module Nendo
|
|
1664
1811
|
elsif :"%tailcall" == sexp.car
|
1665
1812
|
if sexp.cdr.car.is_a? Cell
|
1666
1813
|
sexp = sexp.cdr.car
|
1667
|
-
self.apply( sexp.car, sexp.cdr, sexp.car.sourcefile, sexp.car.lineno, locals, EXEC_TYPE_TAILCALL )
|
1814
|
+
self.apply( sexp.car, sexp.cdr, sexp.car.sourcefile, sexp.car.lineno, locals, sourceInfo, EXEC_TYPE_TAILCALL )
|
1668
1815
|
else
|
1669
1816
|
raise RuntimeError, "Error: special form tailcall expects function call expression."
|
1670
1817
|
end
|
1671
1818
|
else
|
1672
|
-
self.apply( sexp.car, sexp.cdr, sexp.car.sourcefile, sexp.car.lineno, locals, EXEC_TYPE_NORMAL )
|
1819
|
+
self.apply( sexp.car, sexp.cdr, sexp.car.sourcefile, sexp.car.lineno, locals, sourceInfo, EXEC_TYPE_NORMAL )
|
1673
1820
|
end
|
1674
1821
|
when Array
|
1675
1822
|
raise RuntimeError, "Error: can't eval unquoted vector."
|
@@ -1683,6 +1830,12 @@ module Nendo
|
|
1683
1830
|
sexp.to_s
|
1684
1831
|
when String, LispString
|
1685
1832
|
sprintf( "\"%s\"", LispString.escape( sexp ))
|
1833
|
+
when LispRegexp
|
1834
|
+
if sexp.ignoreCase
|
1835
|
+
sprintf( "Regexp.new( \"%s\", Regexp::IGNORECASE)", sexp.escape )
|
1836
|
+
else
|
1837
|
+
sprintf( "Regexp.new( \"%s\")", sexp.escape )
|
1838
|
+
end
|
1686
1839
|
when LispKeyword
|
1687
1840
|
sprintf( "LispKeyword.new( \"%s\" )", sexp.key )
|
1688
1841
|
when Nil
|
@@ -1716,7 +1869,7 @@ module Nendo
|
|
1716
1869
|
when Cell
|
1717
1870
|
if :quote == sexp.car or :quasiquote == sexp.car
|
1718
1871
|
sexp
|
1719
|
-
elsif :define == sexp.car or :set! == sexp.car or :lambda == sexp.car or :macro == sexp.car
|
1872
|
+
elsif :define == sexp.car or :set! == sexp.car or :lambda == sexp.car or :macro == sexp.car or :"&block" == sexp.car
|
1720
1873
|
sexp.cdr.car = Cell.new( :quote, Cell.new( sexp.cdr.car ))
|
1721
1874
|
sexp.cdr.cdr = quotingPhase( sexp.cdr.cdr )
|
1722
1875
|
sexp
|
@@ -1822,8 +1975,10 @@ module Nendo
|
|
1822
1975
|
end
|
1823
1976
|
|
1824
1977
|
def lispEval( sexp, sourcefile, lineno )
|
1978
|
+
sourceInfo = SourceInfo.new
|
1825
1979
|
@lastSourcefile = sourcefile
|
1826
1980
|
@lastLineno = lineno
|
1981
|
+
sourceInfo.setSource( sourcefile, lineno, sexp )
|
1827
1982
|
sexp = macroExpandPhase( sexp )
|
1828
1983
|
sexp = quotingPhase( sexp )
|
1829
1984
|
if @debug
|
@@ -1838,13 +1993,18 @@ module Nendo
|
|
1838
1993
|
printf( "\n compiled=<<< %s >>>\n", (Printer.new())._print(sexp))
|
1839
1994
|
end
|
1840
1995
|
end
|
1996
|
+
sourceInfo.setExpanded( sexp )
|
1841
1997
|
|
1842
|
-
arr = [ "trampCall( ", translate( sexp, [] ), " )" ]
|
1998
|
+
arr = [ "trampCall( ", translate( sexp, [], sourceInfo ), " )" ]
|
1843
1999
|
rubyExp = ppRubyExp( 0, arr ).flatten.join
|
2000
|
+
sourceInfo.setCompiled( rubyExp )
|
1844
2001
|
if not @compiled_code.has_key?( sourcefile )
|
1845
2002
|
@compiled_code[ sourcefile ] = Array.new
|
1846
2003
|
end
|
1847
2004
|
@compiled_code[ sourcefile ] << rubyExp
|
2005
|
+
if sourceInfo.varname
|
2006
|
+
@source_info_hash[ sourceInfo.varname ] = sourceInfo
|
2007
|
+
end
|
1848
2008
|
printf( " rubyExp=<<<\n%s\n>>>\n", rubyExp ) if @debug
|
1849
2009
|
eval( rubyExp, @binding, @lastSourcefile, @lastLineno )
|
1850
2010
|
end
|
@@ -1903,12 +2063,60 @@ module Nendo
|
|
1903
2063
|
def _disable_MIMARKidebug()
|
1904
2064
|
@debug = false
|
1905
2065
|
end
|
2066
|
+
def _enable_MIMARKtrace()
|
2067
|
+
@trace_debug = true
|
2068
|
+
end
|
2069
|
+
def _disable_MIMARKtrace()
|
2070
|
+
@trace_debug = false
|
2071
|
+
end
|
1906
2072
|
def _set_MIMARKoptimize_MIMARKlevel(level)
|
1907
2073
|
self.setOptimizeLevel( level )
|
1908
2074
|
end
|
1909
2075
|
def _get_MIMARKoptimize_MIMARKlevel()
|
1910
2076
|
self.getOptimizeLevel
|
1911
2077
|
end
|
2078
|
+
|
2079
|
+
def _get_MIMARKsource_MIMARKinfo( varname )
|
2080
|
+
info = @source_info_hash[ varname.to_s ]
|
2081
|
+
if info
|
2082
|
+
[
|
2083
|
+
Cell.new( "varname", info.varname ),
|
2084
|
+
Cell.new( "sourcefile", info.sourcefile ),
|
2085
|
+
Cell.new( "lineno", info.lineno ),
|
2086
|
+
Cell.new( "source", info.source_sexp ),
|
2087
|
+
Cell.new( "expanded", info.expanded_sexp ),
|
2088
|
+
Cell.new( "compiled_str", info.compiled_str ) ].to_list
|
2089
|
+
else
|
2090
|
+
raise NameError, sprintf( "Error: not found variable [%s]. \n", varname.to_s )
|
2091
|
+
end
|
2092
|
+
end
|
2093
|
+
|
2094
|
+
def __PAMARKexport_MIMARKto_MIMARKruby( origname, pred )
|
2095
|
+
if toRubySymbol( origname ) != ("_" + origname)
|
2096
|
+
raise ArgumentError, "Error: %export-to-ruby requires function name in ruby method naming rule."
|
2097
|
+
end
|
2098
|
+
if not _procedure_QUMARK( pred )
|
2099
|
+
raise ArgumentError, "Error: %export-to-ruby requires 'pred' as a Proc instance."
|
2100
|
+
end
|
2101
|
+
if 0 > pred.arity
|
2102
|
+
raise ArgumentError, "Error: %export-to-ruby requires only a function that have fixed length argument."
|
2103
|
+
end
|
2104
|
+
if self.methods.include?( origname.intern ) or @core.methods.include?( origname.intern )
|
2105
|
+
raise RuntimeError, "Error: %export-to-ruby: Nendo::Core." + origname + " method was already deifned."
|
2106
|
+
end
|
2107
|
+
|
2108
|
+
argsStr = (1..(pred.arity)).map { |n| "arg" + n.to_s }.join( "," )
|
2109
|
+
str = [ "def self." + origname + "(" + argsStr + ")",
|
2110
|
+
sprintf( " trampCall( callProcedure( '%s', @_%s, [ " + argsStr + " ].to_list )) ",
|
2111
|
+
origname, origname ),
|
2112
|
+
"end ;",
|
2113
|
+
"def @core." + origname + "(" + argsStr + ")",
|
2114
|
+
" @evaluator." + origname + "(" + argsStr + ") ",
|
2115
|
+
"end"
|
2116
|
+
].join
|
2117
|
+
eval( str, @binding )
|
2118
|
+
true
|
2119
|
+
end
|
1912
2120
|
end
|
1913
2121
|
|
1914
2122
|
class Printer
|
@@ -1964,6 +2172,8 @@ module Nendo
|
|
1964
2172
|
else
|
1965
2173
|
sexp.to_s
|
1966
2174
|
end
|
2175
|
+
when Regexp
|
2176
|
+
"#/" + sexp.source + "/" + (sexp.casefold? ? "i" : "")
|
1967
2177
|
when LispKeyword
|
1968
2178
|
":" + sexp.key.to_s
|
1969
2179
|
when Nil
|
@@ -1987,7 +2197,7 @@ module Nendo
|
|
1987
2197
|
class Core
|
1988
2198
|
def initialize( debug_evaluator = false, debug_printer = false )
|
1989
2199
|
@debug_evaluator = debug_evaluator
|
1990
|
-
@evaluator = Evaluator.new( debug_evaluator )
|
2200
|
+
@evaluator = Evaluator.new( self, debug_evaluator )
|
1991
2201
|
@debug_printer = debug_printer
|
1992
2202
|
end
|
1993
2203
|
|
@@ -2002,6 +2212,7 @@ module Nendo
|
|
2002
2212
|
end
|
2003
2213
|
unless done
|
2004
2214
|
@evaluator._load( File.dirname(__FILE__) + "/init.nnd" )
|
2215
|
+
@evaluator._load( File.dirname(__FILE__) + "/init.nnd" ) # for %tailcall compile for init.nnd
|
2005
2216
|
end
|
2006
2217
|
end
|
2007
2218
|
|
@@ -2057,7 +2268,7 @@ module Nendo
|
|
2057
2268
|
end
|
2058
2269
|
end
|
2059
2270
|
|
2060
|
-
def
|
2271
|
+
def evalStr( str )
|
2061
2272
|
printer = Printer.new( @debug_printer )
|
2062
2273
|
sio = StringIO.open( str )
|
2063
2274
|
reader = Reader.new( sio, "(string)", false )
|
@@ -2095,7 +2306,7 @@ end
|
|
2095
2306
|
class Array
|
2096
2307
|
def to_list( lastAtom = false, value = Nendo::Nil.new )
|
2097
2308
|
if 0 == self.length
|
2098
|
-
Nendo::
|
2309
|
+
Nendo::Cell.new()
|
2099
2310
|
else
|
2100
2311
|
cells = self.map { |x|
|
2101
2312
|
Nendo::Cell.new( x )
|
data/lib/srfi-1.nnd
CHANGED
@@ -790,12 +790,7 @@
|
|
790
790
|
'())))
|
791
791
|
|
792
792
|
;; Fast path.
|
793
|
-
(
|
794
|
-
(if (null-list? lis) lis
|
795
|
-
(let ((tail (recur (cdr lis))))
|
796
|
-
(cond ((f (car lis)) => (lambda (x) (cons x tail)))
|
797
|
-
(else tail)))))))
|
798
|
-
|
793
|
+
(%filter-map f lis1)))
|
799
794
|
|
800
795
|
;;; Map F across lists, guaranteeing to go left-to-right.
|
801
796
|
;;; NOTE: Some implementations of R5RS MAP are compliant with this spec;
|
@@ -812,18 +807,12 @@
|
|
812
807
|
'())))
|
813
808
|
|
814
809
|
;; Fast path.
|
815
|
-
(
|
816
|
-
(if (null-list? lis) lis
|
817
|
-
(let ((tail (cdr lis))
|
818
|
-
(x (f (car lis)))) ; Do head first,
|
819
|
-
(cons x (recur tail))))))) ; then tail.
|
820
|
-
|
810
|
+
(%map f lis1)))
|
821
811
|
|
822
812
|
;;; We extend MAP to handle arguments of unequal length.
|
823
813
|
(define map map-in-order)
|
824
814
|
(define for-each map-in-order)
|
825
815
|
|
826
|
-
|
827
816
|
;;; filter, remove, partition
|
828
817
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
829
818
|
;;; FILTER, REMOVE, PARTITION and their destructive counterparts do not
|
@@ -832,17 +821,19 @@
|
|
832
821
|
;; This FILTER shares the longest tail of L that has no deleted elements.
|
833
822
|
;; If Scheme had multi-continuation calls, they could be made more efficient.
|
834
823
|
|
835
|
-
(define (filter pred lis) ; Sleazing with EQ? makes this
|
836
|
-
(check-arg procedure? pred filter) ; one faster.
|
837
|
-
(let recur ((lis lis))
|
838
|
-
(if (null-list? lis) lis ; Use NOT-PAIR? to handle dotted lists.
|
839
|
-
(let ((head (car lis))
|
840
|
-
(tail (cdr lis)))
|
841
|
-
(if (pred head)
|
842
|
-
(let ((new-tail (recur tail))) ; Replicate the RECUR call so
|
843
|
-
(if (eq? tail new-tail) lis
|
844
|
-
(cons head new-tail)))
|
845
|
-
(recur tail)))))) ; this one can be a tail call.
|
824
|
+
;;(define (filter pred lis) ; Sleazing with EQ? makes this
|
825
|
+
;; (check-arg procedure? pred filter) ; one faster.
|
826
|
+
;; (let recur ((lis lis))
|
827
|
+
;; (if (null-list? lis) lis ; Use NOT-PAIR? to handle dotted lists.
|
828
|
+
;; (let ((head (car lis))
|
829
|
+
;; (tail (cdr lis)))
|
830
|
+
;; (if (pred head)
|
831
|
+
;; (let ((new-tail (recur tail))) ; Replicate the RECUR call so
|
832
|
+
;; (if (eq? tail new-tail) lis
|
833
|
+
;; (cons head new-tail)))
|
834
|
+
;; (recur tail)))))) ; this one can be a tail call.
|
835
|
+
|
836
|
+
(define filter %filter)
|
846
837
|
|
847
838
|
|
848
839
|
;;; Another version that shares longest tail.
|