nendo 0.1.0 → 0.2.0

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