Skip to content

Commit d74203b

Browse files
committed
Implement some of the special forms
1 parent 1e6b584 commit d74203b

File tree

1 file changed

+67
-10
lines changed

1 file changed

+67
-10
lines changed

ports-r/scheme.rb

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,81 @@
11
require_relative "parser"
22

33
module Scheme
4-
GLOBAL_ENV = {
4+
class Environment
5+
def initialize(params, args, outer_environment = nil)
6+
@outer_environment = outer_environment
7+
8+
@env = params.zip(args).to_h
9+
end
10+
11+
def [](key)
12+
@env[key]
13+
end
14+
15+
def []=(key, value)
16+
@env[key] = value
17+
end
18+
19+
def find(key)
20+
if @env.key?(key)
21+
self
22+
elsif !@outer_environment.nil?
23+
@outer_environment.find(key)
24+
else
25+
raise "Lookup error for #{key}"
26+
end
27+
end
28+
end
29+
30+
class Procedure
31+
def initialize(params, body, environment)
32+
@params = params
33+
@body = body
34+
@environment = environment
35+
end
36+
37+
def call(*args)
38+
Scheme.evaluate(@body, Environment.new(@params, args, @environment))
39+
end
40+
end
41+
42+
GLOBAL_DICT = {
543
:+ => proc { |a, b| a + b },
6-
:* => proc { |a, b| a * b }
7-
}
44+
:* => proc { |a, b| a * b },
45+
:- => proc { |a, b| a - b },
46+
:/ => proc { |a, b| a / b },
47+
:> => proc { |a, b| a > b },
48+
:< => proc { |a, b| a < b }
49+
}.entries.transpose
50+
GLOBAL_ENV = Environment.new(GLOBAL_DICT[0], GLOBAL_DICT[1])
851

9-
def evaluate(tokens)
52+
def evaluate(tokens, environment = GLOBAL_ENV)
1053
if tokens.is_a?(String)
1154
tokens
1255
elsif tokens.is_a?(Numeric)
1356
tokens
1457
elsif tokens.is_a?(Array)
15-
token = tokens.shift
16-
procedure = evaluate(token)
17-
procedure.call(
18-
*(tokens.map { |t| evaluate(t) })
19-
)
58+
case tokens.first
59+
when :if
60+
condition = evaluate(tokens[1], environment)
61+
branch = condition ? tokens[2] : tokens[3]
62+
evaluate(branch, environment)
63+
when :define
64+
environment[tokens[1]] = evaluate(tokens[2], environment)
65+
nil
66+
when :quote
67+
tokens[1]
68+
when :lambda
69+
Procedure.new(tokens[1], tokens[2], environment)
70+
else
71+
token = tokens.first
72+
procedure = evaluate(token, environment)
73+
procedure.call(
74+
*(tokens[1..].map { |t| evaluate(t, environment) })
75+
)
76+
end
2077
elsif tokens.is_a?(Symbol)
21-
GLOBAL_ENV[tokens]
78+
environment.find(tokens)[tokens]
2279
end
2380
end
2481

0 commit comments

Comments
 (0)