lib/lisp.rb in lisp-1.5.0 vs lib/lisp.rb in lisp-1.5.1

- old
+ new

@@ -1,76 +1,8 @@ -$:.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(__FILE__) require "lisp/version" +require "lisp/interpreter" require "lisp/repl" module Lisp - def self.eval string - execute parse tokenize string - end - - def self.tokenize string - string.gsub("("," ( ").gsub(")"," ) ").split - end - - def self.parse tokens, tree = [] - raise "unexpected: eof" if tokens.size.zero? - - case token = tokens.shift - when "(" - while tokens[0] != ")" do - tree.push parse tokens - end - tokens.shift - tree - when ")" - raise "unexpected: )" - else - atom token - end - end - - def self.atom token - case token - when /\d/ - token.to_f % 1 > 0 ? token.to_f : token.to_i - else - token.to_sym - end - end - - def self.execute expression, scope = global - return scope.fetch(expression) { |var| raise "#{var} is undefined" } if expression.is_a? Symbol - return expression unless expression.is_a? Array - - case expression[0] - when :define - _, var, expression = expression - scope[var] = execute expression, scope - when :lambda - _, params, expression = expression - lambda { |*args| execute expression, scope.merge(Hash[params.zip(args)]) } - when :if - _, test, consequent, alternative = expression - expression = if execute test, scope then consequent else alternative end - execute expression, scope - when :set! - _, var, expression = expression - if scope.has_key?(var) then scope[var] = execute expression, scope else raise "#{var} is undefined" end - when :begin - _, *expression = expression - expression.map { |expression| execute expression, scope }.last - else - function, *args = expression.map { |expression| execute expression, scope } - function.call *args - end - end - - def self.global - @scope ||= begin - operators = [:==, :"!=", :"<", :"<=", :">", :">=", :+, :-, :*, :/] - operators.inject({}) do |scope, operator| - scope.merge operator => lambda { |*args| args.inject &operator } - end - end - end end