lib/lisp.rb in lisp-1.0.1 vs lib/lisp.rb in lisp-1.0.2
- old
+ new
@@ -1,26 +1,10 @@
-#!/usr/bin/env ruby
-
require "bundler/setup"
require "lisp/version"
-require "lisp/scope"
+require "lisp/repl"
module Lisp
- def self.repl
- puts "ctrl-c to exit"
- catch(:exit) do
- loop do
- print "> "
- puts begin
- eval gets
- rescue Exception => e
- e.message
- end
- end
- end
- end
-
def self.eval(string)
execute(parse(tokenize(string)))
end
def self.tokenize(string)
@@ -52,43 +36,34 @@
token.to_sym
end
end
def self.execute(exp, scope = global)
- case exp
- when Array
- case exp[0]
- when :define
- _, var, exp = exp
- scope[var] = execute(exp, scope)
- when :lambda
- _, params, exp = exp
- lambda { |*args| execute(exp, Scope.new(params, args, scope)) }
- when :if
- _, test, conseq, alt = exp
- exp = execute(test, scope) ? conseq : alt
- execute(exp, scope)
- else
- func, *args = exp.map { |exp| execute(exp, scope) }
- func.call(*args)
- end
- when Symbol
- scope[exp]
+ return scope[exp] if exp.is_a? Symbol
+ return exp unless exp.is_a? Array
+
+ case exp[0]
+ when :define
+ _, var, exp = exp
+ scope[var] = execute(exp, scope)
+ when :lambda
+ _, params, exp = exp
+ lambda { |*args| execute(exp, scope.merge(Hash[params.zip(args)])) }
+ when :if
+ _, test, conseq, alt = exp
+ exp = execute(test, scope) ? conseq : alt
+ execute(exp, scope)
else
- exp
+ func, *args = exp.map { |exp| execute(exp, scope) }
+ func.call(*args)
end
end
def self.global
@scope ||= begin
- methods = [:==, :"!=", :"<", :"<=", :">", :">=", :+, :-, :*, :/]
- methods.inject(Scope.new) do |scope, method|
- scope.merge(method => lambda { |*args| args.inject(&method) })
+ operators = [:==, :"!=", :"<", :"<=", :">", :">=", :+, :-, :*, :/]
+ operators.inject({}) do |scope, operator|
+ scope.merge(operator => lambda { |*args| args.inject(&operator) })
end
end
end
-end
-
-if __FILE__ == $0
- trap("SIGINT") { throw :exit }
- Lisp.repl
end