Class: Iode::Interpreter
- Inherits:
-
Object
- Object
- Iode::Interpreter
- Defined in:
- lib/iode/interpreter.rb
Overview
Iode interpreter, providing the central #eval function.
Instance Method Summary collapse
-
#apply(fn, args) ⇒ Object
Apply a function to its arguments.
-
#car(list) ⇒ Object
Get the head (car) of a list.
-
#cdr(list) ⇒ Array
Get the tail (cdr) of a list.
-
#eval(sexp) ⇒ Object
Given an iode data structure, execute it.
-
#initialize(scope = Scope.new) ⇒ Interpreter
constructor
Create a new Interpreter with a given Scope.
-
#lambda(argnames, *sexps) ⇒ Proc
Create a new lambda for Iode.
-
#progn(*sexps) ⇒ Object
Create an explicit progn block.
Constructor Details
#initialize(scope = Scope.new) ⇒ Interpreter
Create a new Interpreter with a given Scope.
24 25 26 |
# File 'lib/iode/interpreter.rb', line 24 def initialize(scope = Scope.new) @env = scope end |
Instance Method Details
#apply(fn, args) ⇒ Object
Apply a function to its arguments.
96 97 98 99 100 101 102 |
# File 'lib/iode/interpreter.rb', line 96 def apply(fn, args) if fn.respond_to?(:call) fn.call(*args) else raise "Cannot apply non-function `#{fn}`" end end |
#car(list) ⇒ Object
Get the head (car) of a list.
35 36 37 38 |
# File 'lib/iode/interpreter.rb', line 35 def car(list) v, *_ = list v end |
#cdr(list) ⇒ Array
Get the tail (cdr) of a list.
47 48 49 50 |
# File 'lib/iode/interpreter.rb', line 47 def cdr(list) _, *v = list v end |
#eval(sexp) ⇒ Object
Given an iode data structure, execute it.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/iode/interpreter.rb', line 111 def eval(sexp) case sexp when Array case car(sexp) when nil nil when :quote car(cdr(sexp)) when :if if eval(car(cdr(sexp))) eval(car(cdr(cdr(sexp)))) else eval(car(cdr(cdr(cdr(sexp))))) end when :progn progn(*cdr(sexp)) when :set! @env[car(cdr(sexp))] = eval(car(cdr(cdr(sexp)))) when :def @env.define(car(cdr(sexp)), eval(car(cdr(cdr(sexp))))) when :lambda lambda(car(cdr(sexp)), *cdr(cdr(sexp))) else apply(eval(car(sexp)), cdr(sexp).map(&method(:eval))) end when Symbol @env[sexp] else sexp end end |
#lambda(argnames, *sexps) ⇒ Proc
Create a new lambda for Iode.
These lambdas act as closures in their environment.
78 79 80 81 82 83 84 |
# File 'lib/iode/interpreter.rb', line 78 def lambda(argnames, *sexps) Proc.new do |*args| Interpreter.new( @env.push_scope(Hash[argnames.zip(args)]) ).progn(*sexps) end end |
#progn(*sexps) ⇒ Object
Create an explicit progn block.
A progn encapsulates a list of S-Expressions to be evaluated in sequence. The last evaluated S-Expression becomes the value of the progn.
62 63 64 |
# File 'lib/iode/interpreter.rb', line 62 def progn(*sexps) sexps.inject(nil){|_,s| eval(s)} end |