nendo 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
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
- raise RuntimeError, "Error: unbalanced vector's paren(4)"
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
- raise RuntimeError, "Error: unbalanced paren(1)"
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
- raise RuntimeError, "Error: unbalanced paren(2)"
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
- raise RuntimeError, "Error: unbalanced paren(3)"
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
- Kernel::require( arg )
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
- if !((key.is_a? String) or ( key.is_a? Symbol))
1080
- raise TypeError, "Error: argument key requires String or Symbol.\n"
1081
- end
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 = Hash.new
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 defMethodStr( name )
1208
- sprintf( "def self.%s_METHOD( origname, pred, args ) callProcedure( origname, pred, args ) end", name )
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 replStr( str )
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::Nil.new
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
- (let recur ((lis lis1))
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
- (let recur ((lis lis1))
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.