nendo 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/nendo.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- encoding: utf-8 -*-
3
3
  #
4
- # Nendo: "Principle of Least Surprise (for Rubyist)"
4
+ # Nendo: "Nendo is a diarect of Lisp."
5
5
  #
6
6
  #
7
7
  #
@@ -26,6 +26,13 @@ class Nil
26
26
  end
27
27
 
28
28
  class LispString < String
29
+ def LispString.escape( str )
30
+ if str.is_a? String
31
+ str.gsub( /["]/, "\\\"" )
32
+ else
33
+ raise TypeError
34
+ end
35
+ end
29
36
  end
30
37
 
31
38
  class LispMacro < Proc
@@ -192,6 +199,7 @@ class Reader
192
199
  T_DOT = :t_dot
193
200
  T_LINEFEED = :t_linefeed
194
201
  T_COMMENT = :t_comment
202
+ T_DEBUG_PRINT = :t_debug_print
195
203
 
196
204
  # inport is IO class
197
205
  def initialize( inport, sourcefile, debug = false )
@@ -239,6 +247,32 @@ class Reader
239
247
  ret
240
248
  end
241
249
 
250
+ def readstring()
251
+ ret = ""
252
+ while true
253
+ ch = @chReader.getc
254
+ #printf( " readstring: [%s]\n", ch )
255
+ if !ch # eof?
256
+ break
257
+ end
258
+ if ch.chr.match( /[\\]/ )
259
+ ch2 = @chReader.getc
260
+ if ch2.chr == "\"" # \" reduce to "
261
+ ret += "\""
262
+ else
263
+ ret += ch.chr
264
+ ret += ch2.chr
265
+ end
266
+ elsif ch.chr.match( /[^"]/ )
267
+ ret += ch.chr
268
+ else
269
+ @chReader.ungetc( ch )
270
+ break
271
+ end
272
+ end
273
+ ret
274
+ end
275
+
242
276
  def tokenWithComment
243
277
  skipspace
244
278
  ch = @chReader.getc
@@ -276,12 +310,28 @@ class Reader
276
310
  readwhile( /[^\r\n]/ )
277
311
  str = ""
278
312
  T_COMMENT
279
- when /[#!]/
280
- readwhile( /[^\r\n]/ )
281
- str = ""
282
- T_COMMENT
313
+ when /[#]/
314
+ keyword = readwhile( /[?=!tf]/ )
315
+ case keyword
316
+ when /[?=]/
317
+ str = ""
318
+ T_DEBUG_PRINT
319
+ when /[!]/
320
+ readwhile( /[^\r\n]/ )
321
+ str = ""
322
+ T_COMMENT
323
+ when "t"
324
+ str = "true"
325
+ T_SYMBOL
326
+ when "f"
327
+ str = "false"
328
+ T_SYMBOL
329
+ else
330
+ str += readwhile( /[^ \t\r\n]/ )
331
+ raise NameError, sprintf( "Error: unknown #xxxx syntax for Nendo %s", str )
332
+ end
283
333
  when /[_a-zA-Z]/ # symbol
284
- str += readwhile( /[_a-zA-Z0-9!?*.-]/ ).gsub( /[-]/, '_' )
334
+ str += readwhile( /[_a-zA-Z0-9!?*.:-]/ ).gsub( /[-]/, '_' )
285
335
  T_SYMBOL
286
336
  when /[*\/=!<>&|%]/ # symbol
287
337
  str += readwhile( /[+*\/=!<>&|?%-]/ )
@@ -301,11 +351,12 @@ class Reader
301
351
  str += readwhile( /[0-9.]/ )
302
352
  T_NUM
303
353
  when /["]/ # String
304
- str = LispString.new( readwhile( /[^"]/ )) ; readwhile( /["]/ )
354
+ str = LispString.new( readstring() )
355
+ readwhile( /["]/ )
305
356
  T_STRING
306
357
  else
307
358
  str += readwhile( /[^ \t\r\n]/ )
308
- raise NameError, sprintf( "unknown token for Nendo [%s]", str )
359
+ raise NameError, sprintf( "Error: unknown token for Nendo [%s]", str )
309
360
  end
310
361
  printf( " token: [%s] : %s (%s:L%d:C%d)\n", str, kind.to_s, @chReader.sourcefile, @chReader.lineno, @chReader.column ) if @debug
311
362
  @curtoken = Token.new( kind, str, @chReader.sourcefile, @chReader.lineno, @chReader.column )
@@ -364,6 +415,8 @@ class Reader
364
415
  :dot_operator
365
416
  when T_FEEDTO
366
417
  :feedto
418
+ when T_DEBUG_PRINT
419
+ "debug-print".intern
367
420
  else
368
421
  raise "Error: Unknown token in atom()"
369
422
  end
@@ -396,7 +449,7 @@ class Reader
396
449
  token
397
450
  lastAtom = sexp()
398
451
  end
399
- when T_QUOTE , T_QUASIQUOTE , T_UNQUOTE , T_UNQUOTE_SPLICING
452
+ when T_QUOTE , T_QUASIQUOTE , T_UNQUOTE , T_UNQUOTE_SPLICING, T_DEBUG_PRINT
400
453
  cells << Cell.new( sexp() )
401
454
  else
402
455
  if lastAtom
@@ -454,6 +507,12 @@ class Reader
454
507
  when T_QUOTE , T_QUASIQUOTE , T_UNQUOTE , T_UNQUOTE_SPLICING
455
508
  _atom = atom() ## "quote" symbol
456
509
  Cell.new( _atom, Cell.new( sexp() ))
510
+ when T_DEBUG_PRINT
511
+ file = curtoken.sourcefile
512
+ lineno = curtoken.lineno
513
+ _atom = atom() ## "debug-print" symbol
514
+ child = sexp()
515
+ [_atom, child, LispString.new( file ), lineno, Cell.new( :quote, Cell.new( child )) ].to_list
457
516
  else
458
517
  atom()
459
518
  end
@@ -651,6 +710,8 @@ module BuiltinFunctions
651
710
  end
652
711
  end
653
712
  def _to_s( arg ) arg.to_s end
713
+ def _to_i( arg ) arg.to_i end
714
+ def _nil_QMARK( arg ) arg.nil? end
654
715
  def _to_list( arg )
655
716
  case arg
656
717
  when Array
@@ -665,7 +726,10 @@ module BuiltinFunctions
665
726
  def _string_join( lst, delim )
666
727
  lst.to_a.map{ |x| x.car }.join( delim )
667
728
  end
668
- def _require( arg ) Kernel::require( arg ) end
729
+ def _require( arg )
730
+ Kernel::require( arg )
731
+ false
732
+ end
669
733
  def _read( *args )
670
734
  lst = args[0].to_arr
671
735
  io = if 0 == lst.length
@@ -685,6 +749,18 @@ module BuiltinFunctions
685
749
  end until s[2]
686
750
  ret
687
751
  end
752
+
753
+ def _apply1( first, arg )
754
+ callProcedure( "(apply1 genereate func)", first, arg )
755
+ end
756
+
757
+ def _global_variables
758
+ self.instance_variables.select { |x|
759
+ x.match( /^[@]_[a-zA-Z]/ )
760
+ }.map{ |name|
761
+ self.toLispSymbol( name[1..-1] ).intern
762
+ }.to_list
763
+ end
688
764
  end
689
765
 
690
766
 
@@ -692,6 +768,7 @@ end
692
768
  class Evaluator
693
769
  include BuiltinFunctions
694
770
  def initialize( debug = false )
771
+ @indent = " "
695
772
  @binding = binding
696
773
  @debug = debug
697
774
  @alias = {'+' => 'plus',
@@ -715,7 +792,7 @@ class Evaluator
715
792
 
716
793
  # initialize global symbols
717
794
  rubyExp = @sym.keys.map { |name|
718
- sprintf( "%s = @sym[ '%s' ] ", name, name )
795
+ sprintf( "@%s = @sym[ '%s' ] ", name, name )
719
796
  }.join( " ; " )
720
797
  eval( rubyExp, @binding )
721
798
 
@@ -723,12 +800,15 @@ class Evaluator
723
800
  rubyExp = self.methods.select { |x|
724
801
  x.to_s.match( /^_/ )
725
802
  }.map { |name|
726
- sprintf( "%s = self.method( :%s ).to_proc", name, name )
803
+ sprintf( "@%s = self.method( :%s ).to_proc", name, name )
727
804
  }.join( " ; " )
728
805
  eval( rubyExp, @binding )
729
806
 
730
807
  # reset gensym counter
731
808
  @gensym_counter = 0
809
+
810
+ # compiled ruby code
811
+ @compiled_code = []
732
812
  end
733
813
 
734
814
  def _gensym( )
@@ -753,8 +833,8 @@ class Evaluator
753
833
  if 0 == name.length
754
834
  ""
755
835
  else
756
- arr = name.split( /[.]/ )
757
- arr[0] = arr[0].gsub( /[*]/, '_AMARK' ).gsub( /[?]/, '_QMARK' ).gsub( /[!]/, '_EMARK' ).gsub( /[-]/, '_' ).gsub( /["]/, '' )
836
+ arr = name.gsub( /["]/, '' ).split( /[.]/ )
837
+ arr[0] = arr[0].gsub( /[*]/, '_AMARK' ).gsub( /[?]/, '_QMARK' ).gsub( /[!]/, '_EMARK' ).gsub( /[-]/, '_' )
758
838
  if arr[0].match( /^[A-Z]/ )
759
839
  # nothing to do
760
840
  elsif arr[0] == ""
@@ -772,26 +852,27 @@ class Evaluator
772
852
 
773
853
  def toLispSymbol( name )
774
854
  name = name.to_s if Symbol == name.class
775
- raise ArgumentError if not ('_' == name[0])
855
+ raise ArgumentError, sprintf( "Error: `%s' is not a lisp symbol", name ) if not ('_' == name[0])
776
856
  name = name[1..-1]
777
857
  name.gsub( /_AMARK/, '*' ).gsub( /_QMARK/, '?' ).gsub( /_EMARK/, '!' )
778
858
  end
779
859
 
780
860
  def toRubyArgument( origname, pred, args )
861
+ argument_error_message = sprintf( "Error: wrong number of arguments for closure `%s'", origname )
781
862
  num = pred.arity
782
863
  if 0 == num
783
- raise ArgumentError, sprintf( "at function `%s'", origname ) if 0 != args.length
864
+ raise ArgumentError, argument_error_message if 0 != args.length
784
865
  []
785
866
  elsif 0 < num
786
867
  if args.isNull
787
868
  [ Nil.new ]
788
869
  else
789
- raise ArgumentError, sprintf( "at function `%s'", origname ) if num != args.length
870
+ raise ArgumentError, argument_error_message if num != args.length
790
871
  args.map { |x| x.car }
791
872
  end
792
873
  else
793
874
  num = num.abs( )-1
794
- raise ArgumentError, sprintf( "at function `%s'", origname ) if num > args.length
875
+ raise ArgumentError, argument_error_message if num > args.length
795
876
  params = []
796
877
  rest = []
797
878
  args.each_with_index { |x,i|
@@ -819,130 +900,193 @@ class Evaluator
819
900
  pred.call( *rubyArgument )
820
901
  end
821
902
 
822
- def execFunc( funcname, args, sourcefile, lineno, lambda_flag )
903
+ # for code generation of Ruby's argument values
904
+ # in case: str = ","
905
+ # [1,"2",3] => [
906
+ # [ 1, ","]
907
+ # ["2", ","]
908
+ # [ 3 ]
909
+ # ]
910
+ def separateWith( arr, str )
911
+ seps = []
912
+ (arr.length-1).times {|n| seps << str }
913
+ arr.zip( seps ).map{ |x|
914
+ x.select { |elem| elem }
915
+ }
916
+ end
917
+
918
+ def execFunc( funcname, args, sourcefile, lineno, locals, lambda_flag )
823
919
  case funcname
824
- when :set! # `set!' special form
825
- sprintf( "%s = %s", toRubySymbol( args.car.to_s.sub( /^:/, "" )), toRubyValue( args.cdr.car ))
920
+ when :define, :set! # `define' special form
921
+ ar = args.cdr.map { |x| x.car }
922
+ variable_sym = toRubySymbol( args.car.to_s.sub( /^:/, "" ))
923
+ global_cap = locals.flatten.include?( variable_sym ) ? nil : "@"
924
+ [ sprintf( "%s%s = ", global_cap, variable_sym ), ar ]
826
925
  when :error
827
926
  sprintf( 'begin raise RuntimeError, %s ; rescue => __e ; __e.set_backtrace( ["%s:%d"] + __e.backtrace ) ; raise __e ; end ', toRubyValue( args.car ), sourcefile, lineno )
828
927
  else
829
928
  if (not lambda_flag) and isRubyInterface( funcname )
830
929
  # Ruby method
831
930
  # 1) convert arguments
832
- argStr = args.map { |x| toRubyValue( x.car ) }.join( "," )
931
+ translatedArr = args.map { |x| x.car }
833
932
  # 2) generate caller code part
834
- sprintf( "%s( %s )", toRubySymbol( funcname ), argStr )
933
+ lispSymbolReference( toRubySymbol( funcname ), locals, translatedArr, sourcefile, lineno )
835
934
  else
836
935
  # Nendo function
837
- argStr = args.map { |x| toRubyValue( x.car ) }.join( " ,Cell.new(" )
838
- argStr += args.map { |x| "" }.join( ")" )
936
+ if 0 == args.length
937
+ arr = [ "Cell.new(" ]
938
+ else
939
+ arr = separateWith( args.map.with_index { |x,i| x.car }, ",Cell.new(" )
940
+ arr[0].unshift( "Cell.new(" )
941
+ end
839
942
  if lambda_flag
840
- "anonymouse"
841
- sprintf( "callProcedure( 'anonymouse', %s, Cell.new( %s ))", funcname, argStr )
943
+ [sprintf( "callProcedure( 'anonymouse', " ),
944
+ [ funcname ] + [ "," ],
945
+ arr,
946
+ sprintf( " )" ) + arr.map { |n| ")" }.join]
842
947
  else
843
948
  origname = funcname.to_s
844
949
  funcname = funcname.to_s
845
950
  funcname = @alias[ funcname ] if @alias[ funcname ]
846
- sprintf( "callProcedure( '%s', %s, Cell.new( %s ))", origname, toRubySymbol( funcname ), argStr )
951
+ sym = toRubySymbol( funcname )
952
+ [sprintf( "callProcedure( '%s',", origname ),
953
+ [lispSymbolReference( sym, locals, nil, sourcefile, lineno )] + [","],
954
+ arr,
955
+ sprintf( " )" ) + arr.map { |n| ")" }.join]
847
956
  end
848
957
  end
849
958
  end
850
959
  end
851
960
 
852
- def makeBegin( args )
961
+ def makeBegin( args, locals )
853
962
  ar = args.map { |e|
854
- translate( e.car )
963
+ translate( e.car, locals )
855
964
  }
856
- "begin " + ar.join( ";" ) + " end"
965
+ ["begin", ar, "end"]
857
966
  end
858
967
 
968
+ # returns [ argsyms[], string ]
859
969
  def toRubyParameter( argform )
860
970
  argsyms = []
971
+ locals = []
861
972
  rest = nil
862
973
  if Symbol == argform.class
863
974
  rest = argform
864
975
  else
865
976
  argsyms = argform.map { |x| toRubySymbol( x.car ) }
977
+ locals = argsyms.clone
866
978
  rest = argform.lastAtom
867
979
  end
868
980
  if rest
869
981
  rest = toRubySymbol( rest )
982
+ locals << rest
870
983
  argsyms << "*__rest__"
871
- sprintf( "|%s| %s = __rest__[0] ; ", argsyms.join( "," ), rest )
984
+ [ locals, sprintf( "|%s| %s = __rest__[0] ; ", argsyms.join( "," ), rest ) ]
872
985
  else
873
- sprintf( "|%s|", argsyms.join( "," ))
986
+ [ locals, sprintf( "|%s|", argsyms.join( "," )) ]
874
987
  end
875
988
  end
876
989
 
877
- def makeClosure( sym, args )
990
+ def makeClosure( sym, args, locals )
878
991
  first = args.car
879
992
  if args.car.car == :quote
880
993
  first = args.car.cdr.car
881
994
  end
882
995
  rest = args.cdr
883
- argStr = toRubyParameter( first )
996
+ ( _locals, argStr ) = toRubyParameter( first )
884
997
  str = case sym
885
998
  when :macro
886
999
  sprintf( "LispMacro.new { %s ", argStr )
887
1000
  when :lambda
888
- sprintf( " Proc.new { %s ", argStr )
1001
+ sprintf( "Proc.new { %s ", argStr )
889
1002
  else
890
1003
  raise "Error: makeClosure: unknown symbol type " + sym
891
1004
  end
892
1005
  ar = rest.map { |e|
893
- translate( e.car )
1006
+ translate( e.car, locals.clone + [_locals])
894
1007
  }
895
- str += ar.join( ";" ) + "}"
1008
+ [ str, ar, "}" ]
896
1009
  end
897
1010
 
898
- def makeIf( args )
899
- _condition = translate( args.car )
900
- _then = translate( args.cdr.car )
1011
+ def makeIf( args, locals )
1012
+ _condition = translate( args.car, locals )
1013
+ _then = translate( args.cdr.car, locals )
901
1014
  _else = nil
902
1015
  if 2 < args.length
903
- _else = translate( args.cdr.cdr.car )
1016
+ _else = translate( args.cdr.cdr.car, locals )
904
1017
  end
905
1018
  if _else
906
- str = sprintf( "if ( %s ) then %s else %s end ", _condition, _then, _else )
1019
+ ["if ( ", _condition, " ) then",
1020
+ [ _then ],
1021
+ "else",
1022
+ [ _else ],
1023
+ "end"]
907
1024
  else
908
- str = sprintf( "if ( %s ) then %s end ", _condition, _then )
1025
+ ["if ( ", _condition, " ) then",
1026
+ [ _then ],
1027
+ "end"]
909
1028
  end
910
1029
  end
911
1030
 
912
- def makeLet( args )
1031
+ def makeLet( args, locals )
913
1032
  _name = "___lambda"
914
- str = ""
915
1033
  argvals = []
1034
+ rest = args.cdr
916
1035
  if args.car.is_a? Nil
917
1036
  # nothing to do
918
- str = sprintf( "begin %s = lambda { || ", _name )
919
- rest = args.cdr
1037
+ lambda_head = sprintf( "%s = lambda { || ", _name )
1038
+ else
1039
+ argsyms = args.car.map { |x|
1040
+ toRubySymbol( x.car.car.cdr.car.to_s )
1041
+ }
1042
+ argvals = args.car.map.with_index { |x,i|
1043
+ translate( x.car.cdr.car, locals )
1044
+ }
1045
+ lambda_head = sprintf( "%s = lambda { |%s| ", _name, argsyms.join( "," ))
1046
+ end
1047
+ ["begin",
1048
+ [lambda_head,
1049
+ rest.map { |e| translate( e.car, locals.clone + [argsyms] ) },
1050
+ sprintf( "} ; %s.call(", _name ),
1051
+ separateWith( argvals, "," ),
1052
+ sprintf( " )")],
1053
+ "end"]
1054
+ end
1055
+
1056
+ def makeLetrec( args, locals )
1057
+ _name = "___lambda"
1058
+ argvals = []
1059
+ argsyms = []
1060
+ rest = args.cdr
1061
+ if args.car.is_a? Nil
1062
+ # nothing to do
1063
+ lambda_head = sprintf( "%s = lambda { || ", _name )
920
1064
  else
921
- if :quote == args.car.car
922
- _name = args.car.cdr.car.to_s
923
- args = args.cdr
924
- end
925
- rest = args.cdr
926
1065
  argsyms = args.car.map { |x|
927
1066
  toRubySymbol( x.car.car.cdr.car.to_s )
928
1067
  }
929
1068
  argvals = args.car.map { |x|
930
- translate( x.car.cdr.car )
1069
+ translate( x.car.cdr.car, locals.clone + [argsyms] )
931
1070
  }
932
- str = sprintf( "begin %s = lambda { |%s| ", _name, argsyms.join( "," ))
1071
+ lambda_head = sprintf( "%s = lambda { |%s| ", _name, argsyms.join( "," ))
933
1072
  end
934
- ar = rest.map { |e| translate( e.car ) }
935
- str += ar.join( ";" ) + "} ; "
936
- str += sprintf( "%s.call( %s ) end ", _name, argvals.join( "," ))
1073
+ ["begin",
1074
+ [lambda_head,
1075
+ argsyms.zip( argvals ).map { |x| [ x[0], " = ", x[1] ] },
1076
+ rest.map { |e| translate( e.car, locals.clone + [argsyms] ) },
1077
+ sprintf( "} ; %s.call(", _name ),
1078
+ argsyms.map { |x| "nil" }.join( "," ),
1079
+ sprintf( " )")],
1080
+ "end"]
937
1081
  end
938
1082
 
939
- def apply( car, cdr, sourcefile, lineno, lambda_flag = false )
1083
+ def apply( car, cdr, sourcefile, lineno, locals, lambda_flag = false )
940
1084
  cdr.each { |x|
941
1085
  if Cell == x.class
942
- x.car = translate( x.car )
1086
+ x.car = translate( x.car, locals )
943
1087
  end
944
1088
  }
945
- execFunc( car, cdr, sourcefile, lineno, lambda_flag )
1089
+ execFunc( car, cdr, sourcefile, lineno, locals, lambda_flag )
946
1090
  end
947
1091
 
948
1092
  def genQuote( sexp, str = "" )
@@ -954,7 +1098,7 @@ class Evaluator
954
1098
  else
955
1099
  arr = sexp.map { |x| genQuote( x.car ) }
956
1100
  str += "Cell.new("
957
- str += arr.join( " ,Cell.new(" )
1101
+ str += arr.join( ",Cell.new(" )
958
1102
  lastAtom = sexp.lastAtom
959
1103
  str += "," + genQuote( lastAtom ) if lastAtom
960
1104
  str += arr.map{ |e| ")" }.join
@@ -962,7 +1106,7 @@ class Evaluator
962
1106
  when Symbol
963
1107
  str += sprintf( ":\"%s\"", sexp.to_s )
964
1108
  when String
965
- str += sprintf( "\"%s\"", sexp )
1109
+ str += sprintf( "\"%s\"", LispString.escape( sexp ))
966
1110
  when TrueClass, FalseClass, NilClass # reserved symbols
967
1111
  str += toRubyValue( sexp )
968
1112
  else
@@ -971,35 +1115,72 @@ class Evaluator
971
1115
  str
972
1116
  end
973
1117
 
974
- def translate( sexp )
975
- str = ""
1118
+ def lispSymbolReference( sym, locals, translatedArr, sourcefile, lineno )
1119
+ variable_sym = sym.split( /[.]/ )[0]
1120
+ global_cap = if variable_sym.match( /^[A-Z]/ )
1121
+ nil
1122
+ else
1123
+ locals.flatten.include?( variable_sym ) ? nil : "@"
1124
+ end
1125
+ expression = if translatedArr
1126
+ [sprintf( "%s%s(", global_cap, sym ),
1127
+ separateWith( translatedArr, "," ),
1128
+ sprintf( " )" )]
1129
+ else
1130
+ [sprintf( "%s%s", global_cap, sym )]
1131
+ end
1132
+ if global_cap
1133
+ ["begin",
1134
+ [sprintf( 'if (self.instance_variables.include?(:@%s)) then', variable_sym ),
1135
+ expression,
1136
+ sprintf( 'else raise NameError.new( "Error: undefined variable %s", "%s" ) end', variable_sym, variable_sym ),
1137
+ sprintf( 'rescue => __e ; __e.set_backtrace( ["%s:%d"] + __e.backtrace ) ; raise __e', sourcefile, lineno )],
1138
+ "end"]
1139
+ else
1140
+ ["begin",
1141
+ [expression,
1142
+ sprintf( 'rescue => __e ; __e.set_backtrace( ["%s:%d"] + __e.backtrace ) ; raise __e', sourcefile, lineno )],
1143
+ "end"]
1144
+ end
1145
+ end
1146
+
1147
+ # Lisp->Ruby translater
1148
+ # - locals is array of closure's local variable list
1149
+ # when S-expression is
1150
+ # (let ((a 1)
1151
+ # (b 2))
1152
+ # (let ((c 3))
1153
+ # (print (+ a b c))))
1154
+ # => locals must be [["_a" "_b"]["_c"]] value.
1155
+ def translate( sexp, locals )
976
1156
  case sexp
977
1157
  when Cell
978
1158
  if :quote == sexp.car
979
1159
  genQuote( sexp.cdr.car )
980
1160
  elsif sexp.isDotted
981
- print "Error: can't eval dotted pair"
982
- raise NameError
1161
+ raise NameError, "Error: can't eval dotted pair."
983
1162
  elsif sexp.isNull
984
- str += "Cell.new()"
1163
+ [ "Cell.new()" ]
985
1164
  elsif Cell == sexp.car.class
986
1165
  if :lambda == sexp.car.car
987
- str += self.apply( translate( sexp.car ), sexp.cdr, sexp.car.car.sourcefile, sexp.car.car.lineno, true )
1166
+ self.apply( translate( sexp.car, locals ), sexp.cdr, sexp.car.car.sourcefile, sexp.car.car.lineno, locals, true )
988
1167
  else
989
- str += translate( sexp.car )
1168
+ translate( sexp.car, locals )
990
1169
  end
991
1170
  elsif :begin == sexp.car
992
- str += self.makeBegin( sexp.cdr )
1171
+ self.makeBegin( sexp.cdr, locals )
993
1172
  elsif :lambda == sexp.car
994
- str += self.makeClosure( :lambda, sexp.cdr )
1173
+ self.makeClosure( :lambda, sexp.cdr, locals )
995
1174
  elsif :macro == sexp.car
996
- str += self.makeClosure( :macro, sexp.cdr )
1175
+ self.makeClosure( :macro, sexp.cdr, locals )
997
1176
  elsif :if == sexp.car
998
- str += self.makeIf( sexp.cdr )
1177
+ self.makeIf( sexp.cdr, locals )
999
1178
  elsif :let == sexp.car
1000
- str += self.makeLet( sexp.cdr )
1179
+ self.makeLet( sexp.cdr, locals )
1180
+ elsif :letrec == sexp.car
1181
+ self.makeLetrec( sexp.cdr, locals )
1001
1182
  else
1002
- str += self.apply( sexp.car, sexp.cdr, sexp.car.sourcefile, sexp.car.lineno )
1183
+ self.apply( sexp.car, sexp.cdr, sexp.car.sourcefile, sexp.car.lineno, locals )
1003
1184
  end
1004
1185
  else
1005
1186
  case sexp
@@ -1007,17 +1188,17 @@ class Evaluator
1007
1188
  sym = sexp.to_s
1008
1189
  sym = @alias[ sym ] if @alias[ sym ]
1009
1190
  sym = toRubySymbol( sym )
1010
- str += sprintf( 'begin %s ; rescue NameError => __e ; __e.set_backtrace( ["%s:%d"] + __e.backtrace ) ; raise __e ; end', sym, sexp.sourcefile, sexp.lineno )
1191
+ lispSymbolReference( sym, locals, nil, sexp.sourcefile, sexp.lineno )
1011
1192
  when Fixnum
1012
- str += sexp.to_s
1013
- when LispString
1014
- str += sprintf( "\"%s\"", sexp )
1193
+ sexp.to_s
1194
+ when String
1195
+ sprintf( "\"%s\"", LispString.escape( sexp ))
1015
1196
  when Nil
1016
- str += "Nil.new"
1197
+ "Nil.new"
1017
1198
  when TrueClass, FalseClass, NilClass # reserved symbols
1018
- str += toRubyValue( sexp )
1199
+ toRubyValue( sexp )
1019
1200
  else
1020
- str += sexp.to_s
1201
+ sexp.to_s
1021
1202
  end
1022
1203
  end
1023
1204
  end
@@ -1043,19 +1224,33 @@ class Evaluator
1043
1224
  when Cell
1044
1225
  if :quote == sexp.car or :quasiquote == sexp.car
1045
1226
  sexp
1046
- elsif :set! == sexp.car or :lambda == sexp.car or :macro == sexp.car
1227
+ elsif :define == sexp.car or :set! == sexp.car or :lambda == sexp.car or :macro == sexp.car
1047
1228
  sexp.cdr.car = Cell.new( :quote, Cell.new( sexp.cdr.car ))
1048
1229
  sexp.cdr.cdr = quoting( sexp.cdr.cdr )
1049
1230
  sexp
1050
1231
  elsif :let == sexp.car
1232
+ if _null_QMARK( sexp.cdr )
1233
+ # do nothing
1234
+ p "kiyoka1"
1235
+ else
1236
+ case sexp.cdr.car
1237
+ when Cell # let
1238
+ sexp.cdr = Cell.new( letArgumentList( sexp.cdr.car ),
1239
+ quoting( sexp.cdr.cdr ))
1240
+ when Symbol # named let
1241
+ sexp.cdr.car = Cell.new( :quote, Cell.new( sexp.cdr.car ))
1242
+ sexp.cdr.cdr = Cell.new( letArgumentList( sexp.cdr.cdr.car ),
1243
+ quoting( sexp.cdr.cdr.cdr ))
1244
+ end
1245
+ end
1246
+ sexp
1247
+ elsif :letrec == sexp.car
1051
1248
  case sexp.cdr.car
1052
- when Cell # let
1249
+ when Cell # letrec
1053
1250
  sexp.cdr = Cell.new( letArgumentList( sexp.cdr.car ),
1054
- quoting( sexp.cdr.cdr ))
1055
- when Symbol # named let
1056
- sexp.cdr.car = Cell.new( :quote, Cell.new( sexp.cdr.car ))
1057
- sexp.cdr.cdr = Cell.new( letArgumentList( sexp.cdr.cdr.car ),
1058
- quoting( sexp.cdr.cdr.cdr ))
1251
+ quoting( sexp.cdr.cdr ))
1252
+ when Symbol # named letrec is illegal
1253
+ raise SyntaxError, "Error: named letrec is not a illegal form"
1059
1254
  end
1060
1255
  sexp
1061
1256
  else
@@ -1066,7 +1261,19 @@ class Evaluator
1066
1261
  end
1067
1262
  end
1068
1263
 
1069
- def macroexpand_1( sexp )
1264
+ def macroexpand_1_check( sexp )
1265
+ if not @expand_flag
1266
+ sexp
1267
+ else
1268
+ newSexp = macroexpand_1_sub( sexp )
1269
+ if not _equal_QMARK( newSexp, sexp )
1270
+ @expand_flag = false
1271
+ end
1272
+ newSexp
1273
+ end
1274
+ end
1275
+
1276
+ def macroexpand_1_sub( sexp )
1070
1277
  case sexp
1071
1278
  when Cell
1072
1279
  if :quote == sexp.car
@@ -1075,22 +1282,35 @@ class Evaluator
1075
1282
  sym = sexp.car.to_s
1076
1283
  sym = @alias[ sym ] if @alias[ sym ]
1077
1284
  sym = toRubySymbol( sym )
1078
- if isRubyInterface( sym )
1079
- arr = sexp.map { |x| macroexpand_1( x.car ) }
1080
- arr.to_list( sexp.lastAtom )
1081
- elsif sexp.car.class == Symbol and eval( sprintf( "(defined? %s and LispMacro == %s.class)", sym,sym ), @binding )
1082
- eval( sprintf( "@_macro = %s", sym ), @binding )
1083
- callProcedure( sym, @_macro, sexp.cdr )
1285
+ newSexp = sexp
1286
+ if isRubyInterface( sym )
1287
+ # do nothing
1288
+ elsif sexp.car.class == Symbol and eval( sprintf( "(defined? @%s and LispMacro == @%s.class)", sym,sym ), @binding )
1289
+ eval( sprintf( "@__macro = @%s", sym ), @binding )
1290
+ newSexp = callProcedure( sym, @__macro, sexp.cdr )
1291
+ end
1292
+ if _equal_QMARK( newSexp, sexp )
1293
+ sexp.map { |x|
1294
+ if x.car.is_a? Cell
1295
+ macroexpand_1_check( x.car )
1296
+ else
1297
+ x.car
1298
+ end
1299
+ }.to_list( sexp.lastAtom )
1084
1300
  else
1085
- arr = sexp.map { |x| macroexpand_1( x.car ) }
1086
- arr.to_list( sexp.lastAtom )
1301
+ newSexp
1087
1302
  end
1088
1303
  end
1089
1304
  else
1090
1305
  sexp
1091
1306
  end
1092
1307
  end
1093
-
1308
+
1309
+ def macroexpand_1( sexp )
1310
+ @expand_flag = true
1311
+ macroexpand_1_check( sexp )
1312
+ end
1313
+
1094
1314
  def lispCompile( sexp )
1095
1315
  converge = true
1096
1316
  begin
@@ -1100,6 +1320,22 @@ class Evaluator
1100
1320
  end until converge
1101
1321
  sexp
1102
1322
  end
1323
+
1324
+ def ppRubyExp( level, exp )
1325
+ indent = @indent * level
1326
+ exp.map { |x|
1327
+ if Array == x.class
1328
+ ppRubyExp( level+1, x )
1329
+ else
1330
+ str = sprintf( "%s", x )
1331
+ if str.match( /^[,]/ ) or str.match( /^ = / )
1332
+ sprintf( "%s%s", indent, str )
1333
+ else
1334
+ sprintf( "\n%s%s", indent, str )
1335
+ end
1336
+ end
1337
+ }
1338
+ end
1103
1339
 
1104
1340
  def lispEval( sexp, sourcefile, lineno )
1105
1341
  sexp = lispCompile( sexp )
@@ -1107,8 +1343,10 @@ class Evaluator
1107
1343
  if @debug
1108
1344
  printf( "\n quoting=<<< %s >>>\n", (Printer.new())._print(sexp))
1109
1345
  end
1110
- rubyExp = translate( sexp );
1111
- printf( " rubyExp=<<< %s >>>\n", rubyExp ) if @debug
1346
+ arr = [ translate( sexp, [] ) ]
1347
+ rubyExp = ppRubyExp( 0, arr ).flatten.join
1348
+ @compiled_code << rubyExp
1349
+ printf( " rubyExp=<<<\n%s\n>>>\n", rubyExp ) if @debug
1112
1350
  eval( rubyExp, @binding, sourcefile, lineno );
1113
1351
  end
1114
1352
 
@@ -1129,13 +1367,27 @@ class Evaluator
1129
1367
  }
1130
1368
  end
1131
1369
 
1370
+ def _loadCompiledCode( filename )
1371
+ open( filename ) { |f|
1372
+ rubyExp = f.read
1373
+ eval( rubyExp, @binding )
1374
+ }
1375
+ end
1376
+
1377
+ def _get_compiled_code()
1378
+ @compiled_code.to_list
1379
+ end
1380
+
1132
1381
  def _eval( sexp )
1133
1382
  self.lispEval( sexp, "dynamic S-expression ( no source )", 1 )
1134
1383
  end
1135
1384
 
1136
- def _enable_debug()
1385
+ def _enable_idebug()
1137
1386
  @debug = true
1138
1387
  end
1388
+ def _disable_idebug()
1389
+ @debug = false
1390
+ end
1139
1391
  end
1140
1392
 
1141
1393
  class Printer
@@ -1180,7 +1432,7 @@ class Printer
1180
1432
  end
1181
1433
  when String
1182
1434
  if readable
1183
- sprintf( "\"%s\"", sexp.to_s )
1435
+ sprintf( "\"%s\"", LispString.escape( sexp.to_s ))
1184
1436
  else
1185
1437
  sexp.to_s
1186
1438
  end
@@ -1209,8 +1461,18 @@ class Nendo
1209
1461
  @debug_printer = debug_printer
1210
1462
  end
1211
1463
 
1212
- def loadInitFile
1213
- @evaluator._load( File.dirname(__FILE__) + "/init.nnd" )
1464
+ def loadInitFile( use_compiled = true )
1465
+ done = false
1466
+ if use_compiled
1467
+ compiled_file = File.dirname(__FILE__) + "/init.nndc"
1468
+ if File.exist?( compiled_file )
1469
+ @evaluator._loadCompiledCode( compiled_file )
1470
+ done = true
1471
+ end
1472
+ end
1473
+ unless done
1474
+ @evaluator._load( File.dirname(__FILE__) + "/init.nnd" )
1475
+ end
1214
1476
  end
1215
1477
 
1216
1478
  def load( path )
@@ -1238,8 +1500,8 @@ class Nendo
1238
1500
  if s[1] # EOF?
1239
1501
  break
1240
1502
  elsif Nil != s[0].class
1241
- printf( "\n readExp=<<< %s >>>\n", printer._print(s[0]) ) if @debug_evaluator
1242
- print printer._print( @evaluator.lispEval( s[0], reader.sourcefile, lineno ))
1503
+ printf( "\n readExp=<<< %s >>>\n", printer._write(s[0]) ) if @debug_evaluator
1504
+ print printer._write( @evaluator.lispEval( s[0], reader.sourcefile, lineno ))
1243
1505
  print "\n" + "nendo> "
1244
1506
  end
1245
1507
  rescue => e
@@ -1261,8 +1523,8 @@ class Nendo
1261
1523
  if s[1] # EOF?
1262
1524
  break
1263
1525
  elsif Nil != s[0].class
1264
- printf( "\n readExp=<<< %s >>>\n", printer._print(s[0]) ) if @debug_evaluator
1265
- result = printer._print( @evaluator.lispEval( s[0], reader.sourcefile, lineno ))
1526
+ printf( "\n readExp=<<< %s >>>\n", printer._write(s[0]) ) if @debug_evaluator
1527
+ result = printer._write( @evaluator.lispEval( s[0], reader.sourcefile, lineno ))
1266
1528
  end
1267
1529
  end
1268
1530
  result