Module: Lisp
- Defined in:
- lib/lisp.rb,
lib/lisp/repl.rb,
lib/lisp/version.rb
Constant Summary collapse
- VERSION =
"1.0.2"
Class Method Summary collapse
- .eval(string) ⇒ Object
- .evaluator(token) ⇒ Object
- .execute(exp, scope = global) ⇒ Object
- .global ⇒ Object
- .input ⇒ Object
- .parse(tokens, tree = []) ⇒ Object
- .repl ⇒ Object
- .tokenize(string) ⇒ Object
Class Method Details
.eval(string) ⇒ Object
6 7 8 |
# File 'lib/lisp.rb', line 6 def self.eval(string) execute(parse(tokenize(string))) end |
.evaluator(token) ⇒ Object
31 32 33 34 35 36 37 38 |
# File 'lib/lisp.rb', line 31 def self.evaluator(token) case token when /\d/ token.to_f else token.to_sym end end |
.execute(exp, scope = global) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/lisp.rb', line 40 def self.execute(exp, scope = global) 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 func, *args = exp.map { |exp| execute(exp, scope) } func.call(*args) end end |
.global ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/lisp.rb', line 61 def self.global @scope ||= begin operators = [:==, :"!=", :"<", :"<=", :">", :">=", :+, :-, :*, :/] operators.inject({}) do |scope, operator| scope.merge(operator => lambda { |*args| args.inject(&operator) }) end end end |
.input ⇒ Object
19 20 21 |
# File 'lib/lisp/repl.rb', line 19 def self.input Coolline.new end |
.parse(tokens, tree = []) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/lisp.rb', line 14 def self.parse(tokens, tree = []) raise "unexpected: eof" if tokens.size.zero? token = tokens.shift case token when "(" while tokens[0] != ")" do tree.push parse(tokens) end tokens.shift tree when ")" raise "unexpected: )" else evaluator(token) end end |
.repl ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/lisp/repl.rb', line 5 def self.repl trap("SIGINT") { throw :exit } puts "ctrl-c to exit" catch(:exit) do loop do puts begin eval input.readline rescue Exception => e e. end end end end |
.tokenize(string) ⇒ Object
10 11 12 |
# File 'lib/lisp.rb', line 10 def self.tokenize(string) string.gsub("("," ( ").gsub(")"," ) ").split end |