Show
Ignore:
Timestamp:
03/18/09 12:35:31 (6 years ago)
Author:
kiyoka
Message:

Added Printer class and Nil class.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lang/ruby/RedLisp/trunk/redlisp.rb

    r31286 r31335  
    11#!/usr/bin/env ruby 
    22# 
    3 # Lisp Of Least Surprise (for Rubyist) 
     3# RedLisp 
     4#   "Principle of Least Surprise (for Rubyist)" 
    45# 
    56# 
     
    78require 'pp' 
    89 
     10class Nil 
     11end 
     12 
    913class Cell 
    1014  include Enumerable 
    1115 
    12   NIL=:nil 
    13   def initialize( car = NIL, cdr = NIL ) 
     16  def initialize( car = Nil.new, cdr = Nil.new ) 
    1417    @car = car 
    1518    @cdr = cdr 
     
    2023    it = self 
    2124    begin 
    22       yield it.car 
     25      yield it 
    2326      it = it.cdr 
    24     end while NIL != it 
    25   end 
     27    end while Nil != it.class 
     28  end 
     29 
     30  def length 
     31    count = 0 
     32    p = self 
     33    begin 
     34      p = p.car 
     35      count += 1 
     36    end while Nil != it.class 
     37  end 
     38 
     39  def isDotted 
     40    ((Cell != @cdr.class) and (Nil != @cdr.class)) 
     41  end 
     42     
    2643end 
    2744 
     
    129146      case tok.type 
    130147      when T_EOF 
    131         print "Error: unbalanced paren(2)" 
    132         break 
     148        print "Error: unbalanced paren(2)\n" 
     149        raise ExceptionParen 
    133150      when T_LPAREN 
    134151        cells << Cell.new( list( token )) 
     
    147164          end 
    148165        elsif tok.type == T_QUOTE 
    149           cells << Cell.new( atom( tok ), sexp( token )) 
     166          cells << Cell.new( Cell.new( atom( tok ), Cell.new( sexp( token )))) 
    150167          tok = curtoken 
    151168        else 
     
    177194      list( token ) 
    178195    when T_RPAREN 
    179       print "Error: unbalanced paren(1)" 
     196      print "Error: unbalanced paren(1)\n" 
     197      raise ExceptionParen 
    180198    when T_QUOTE 
    181       Cell.new( atom( tok ), list( token )) 
     199      Cell.new( Cell.new( tom( tok ), Cell.new( sexp( token )))) 
    182200    else 
    183201      atom( tok ) 
     
    185203  end 
    186204 
    187   def read 
     205  def _read 
    188206    sexp( token ) 
    189207  end 
     
    191209 
    192210 
    193  
    194211class Evaluator  
     212  def initialize 
     213    @sym = { 
     214      '+' => getIFunc( '+' ), 
     215      '-' => getIFunc( '-' ), 
     216      '*' => getIFunc( '*' ), 
     217      '/' => getIFunc( '/' ), 
     218      '%' => getIFunc( '%' ), 
     219 
     220      'car'    => getIFunc( 'car' ), 
     221      'cdr'    => getIFunc( 'cdr' ), 
     222    } 
     223  end 
     224 
     225  def argCheck( args ) 
     226    if 0 == args.length 
     227      nil 
     228    else 
     229      args.each { |x| 
     230        if x.class != Fixnum 
     231          print "Error: + - * / % operator got illegal argument. " 
     232          return nil 
     233        end 
     234      } 
     235    end 
     236  end 
     237     
     238  def getIFunc( name ) 
     239    case name 
     240    when '+' 
     241      lambda {|args|  
     242        argCheck( args ) 
     243        args.inject(0) {|x,y| x + y} 
     244      } 
     245    when '-' 
     246      lambda {|args| 
     247        argCheck( args ) 
     248        if 1 == args.length  
     249          - args[0] 
     250        else 
     251          args[1..-1].inject(args[0]) {|x,y| x - y} 
     252        end 
     253      } 
     254    when '*' 
     255      lambda {|args| 
     256        argCheck( args ) 
     257        args.inject(1) {|x,y| x * y} 
     258      } 
     259    when '/' 
     260      lambda {|args| 
     261        argCheck( args ) 
     262        if 1 == args.length  
     263          1 / args[0] 
     264        else 
     265          args[1..-1].inject(args[0]) {|x,y| x / y} 
     266        end 
     267      } 
     268    when '%' 
     269      lambda {|args| 
     270        argCheck( args ) 
     271        if 1 == args.length  
     272          1 % args[0] 
     273        else 
     274          args[1..-1].inject(args[0]) {|x,y| x % y} 
     275        end 
     276      } 
     277    when 'car' 
     278      lambda {|args| 
     279        p "function car():", args.car 
     280        if Cell == args.class 
     281          args.car.car 
     282        else 
     283          print "Error: car argument error\n" 
     284          raise ExceptionArgument 
     285        end 
     286      } 
     287    when 'cdr' 
     288      lambda {|args| 
     289        p "function cdr():", args.car 
     290        if Cell == args.class 
     291          args.car.cdr 
     292        else 
     293          print "Error: car argument error\n" 
     294          raise ExceptionArgument 
     295        end 
     296      } 
     297    end 
     298  end 
    195299 
    196300  def execFunc( funcname, args ) 
    197     case funcname 
    198     when /[+*\/-]/ 
    199       args.each { |x| 
    200         if x.class.to_s != "Fixnum" 
    201           print "Error: + - * / operator got illegal argument. " 
    202           return nil 
    203         end 
    204       } 
    205       case funcname 
    206       when "+" 
    207         args.inject(0) {|x,y| x + y} 
    208       when "-" 
    209         args[1..-1].inject(args[0]) {|x,y| x - y} 
    210       when "*" 
    211         args.inject(1) {|x,y| x * y} 
    212       when "/" 
    213         args[1..-1].inject(args[0]) {|x,y| x / y} 
    214       end 
     301    printf( "execFunc( %s, %s )\n", funcname, "xxx" ) 
     302    pp args 
     303    if @sym[ funcname ]  
     304      @sym[ funcname ].call( args ) 
     305    else 
     306      printf( "Error: no such function %s\n", funcname ) 
     307      raise ExceptionNoSymbol 
    215308    end 
    216309  end 
    217310 
    218311  def apply( car, cdr ) 
    219     execFunc( car, 
    220               cdr.map { |x| 
    221                 self.eval( x ) 
    222               } ) 
    223   end 
    224  
    225   def eval( sexp ) 
     312    p "apply() car.class.to_s: " + car.class.to_s + ":" + car 
     313    ptr = cdr 
     314    while Nil != ptr.class 
     315      print "ptr.car: " 
     316      pp ptr.car 
     317      ptr.car = _eval( ptr.car ) 
     318      ptr = ptr.cdr 
     319    end 
     320    execFunc( car, cdr ) 
     321  end 
     322 
     323  def _eval( sexp ) 
    226324    case sexp.class.to_s 
    227325    when "Cell" 
    228       case sexp.car  
    229       when "quote" 
    230         sexp.cdr 
     326      if "quote" == sexp.car 
     327        sexp.cdr.car 
     328      elsif sexp.isDotted 
     329        print "Error: can't eval dotted pair" 
     330        raise ExceptionNoSymbol         
     331      elsif Cell == sexp.car.class 
     332        _eval( sexp.car ) 
    231333      else 
    232334        self.apply( sexp.car, sexp.cdr ) 
     
    235337      sexp 
    236338    end 
     339  end 
     340end 
     341 
     342 
     343class Printer 
     344  def _print( sexp, str = "" ) 
     345    case sexp.class.to_s 
     346    when "Cell" 
     347      str += "(" 
     348      str += _print( sexp.car ) 
     349      ptr = sexp.cdr 
     350      while Nil != ptr.class 
     351        str += _print( ptr.car ) 
     352        ptr = ptr.cdr 
     353      end 
     354      str += ")" 
     355    else 
     356      str += sprintf( "%s ", sexp ) 
     357    end 
     358    str 
    237359  end 
    238360end 
     
    248370  def repl 
    249371    while true 
    250       @printer.print( @evaluator.eval( @reader.read )) 
     372      @printer._print( @evaluator._eval( @reader._read )) 
    251373    end 
    252374  end 
     
    259381  reader = Reader.new( sio ) 
    260382  p "--- " + sexp + " --- is " 
    261   pp reader.read 
     383  pp reader._read 
    262384end 
    263385 
    264386#test  
    265 def readerEvaluatorTest( sexp ) 
     387def readerPrinterTest( sexp ) 
    266388  sio = StringIO.open( sexp ) 
    267389  reader = Reader.new( sio ) 
    268   p "--- " + sexp + " --- is " 
    269   s = reader.read 
    270   pp s 
     390  print "--- " + sexp + " --- is       \n" 
     391  s = reader._read 
     392  printer = Printer.new 
     393  print "--- " + sexp + " --- prints   \n" 
     394  printf( "   %s\n\n", printer._print( s )) 
     395end 
     396 
     397#test  
     398def replTest( sexp ) 
     399  sio = StringIO.open( sexp ) 
     400  reader = Reader.new( sio ) 
     401  print "--- " + sexp + " --- is       \n" 
     402  s = reader._read 
     403  printer = Printer.new 
     404  print "--- " + sexp + " --- prints   \n" 
     405  printf( "   %s\n", printer._print( s )) 
    271406  evaluator = Evaluator.new 
    272   p "--- " + sexp + " --- evals " 
    273   pp evaluator.eval( s ) 
    274 end 
    275  
    276 readerEvaluatorTest( " + " ) 
    277 readerEvaluatorTest( " 123 " ) 
    278 readerEvaluatorTest( " (+ 1 2 3 4 ) " ) 
    279 readerEvaluatorTest( " (* 1 2 3 4 ) " ) 
    280 readerEvaluatorTest( " (- 10 5 1 ) " ) 
    281 readerEvaluatorTest( " (/ 10 4 2 ) " ) 
    282 readerEvaluatorTest( " (+ (+ 1 2) (+ 3 4 )) " ) 
    283 readerEvaluatorTest( " (- (* 3 3) (* 2 2 )) " ) 
    284 #readerEvaluatorTest( " ( 1 . 2 ) " ) 
    285 #readerEvaluatorTest( " ( 1 ) " ) 
    286 #readerEvaluatorTest( " (car '(1 . 2)) " ) 
    287 #readerEvaluatorTest( " (cdr '(1 . 2)) " ) 
    288 #readerEvaluatorTest( " '( 1 2 3 '4 ) " ) 
    289 #readerTest( " (( 1 )) " ) 
    290 #readerTest( " ( 1 2 ( 3 4 )) " ) 
    291 #readerTest( " ( " ) 
    292 #readerTest( " ) " ) 
     407  print "--- " + sexp + " --- evals    \n" 
     408  printf( "   %s\n", printer._print( evaluator._eval( s ))) 
     409end 
     410 
     411replTest( " + " ) 
     412replTest( " 123 " ) 
     413replTest( " (car '(a b c)) " ) 
     414replTest( " (cdr '(a b c)) " ) 
     415#replTest( " (+ 1 2 3 4 ) " ) 
     416#replTest( " (* 1 2 3 4 ) " ) 
     417#replTest( " (- 10 5 1 ) " ) 
     418#replTest( " (/ 10 4 2 ) " ) 
     419#replTest( " (+ (+ 1 2) (+ 3 4 )) " ) 
     420#replTest( " (- (* 3 3) (* 2 2 )) " ) 
     421#replTest( " ( 1 . 2 ) " ) 
     422#replTest( " ( 1 ) " ) 
     423#replTest( " (car '(1 . 2)) " ) 
     424#replTest( " (cdr '(1 . 2)) " ) 
     425#replTest( " '( 1 2 3 '4 ) " ) 
     426#replTest( " (( 1 )) " ) 
     427#replTest( " ( 1 2 ( 3 4 )) " ) 
     428#replTest( " ( " ) 
     429#replTest( " ) " ) 
    293430 
    294431