main
1require "spec_helper"
2
3class Machine < Struct.new(:expression, :environment)
4 def step
5 self.expression = expression.reduce(environment)
6 end
7
8 def run
9 while expression.reducible?
10 puts expression
11 step
12 end
13 puts expression
14 end
15end
16
17class Number < Struct.new(:value)
18 def reducible?
19 false
20 end
21
22 def to_s
23 value.to_s
24 end
25
26 def inspect
27 "<<#{self}>>"
28 end
29end
30
31class Add < Struct.new(:left, :right)
32 def reducible?
33 true
34 end
35
36 def reduce(environment)
37 if left.reducible?
38 Add.new(left.reduce(environment), right)
39 elsif right.reducible?
40 Add.new(left, right.reduce(environment))
41 else
42 Number.new(left.value + right.value)
43 end
44 end
45
46 def to_s
47 "(#{left} + #{right})"
48 end
49
50 def inspect
51 "<<#{self}>>"
52 end
53end
54
55class Multiply < Struct.new(:left, :right)
56 def reducible?
57 true
58 end
59
60 def reduce(environment)
61 if left.reducible?
62 Multiple.new(left.reduce(environment), right)
63 elsif right.reducible?
64 Multiple.new(left, right.reduce(environment))
65 else
66 Number.new(left.value * right.value)
67 end
68 end
69
70 def to_s
71 "(#{left} * #{right})"
72 end
73
74 def inspect
75 "<<#{self}>>"
76 end
77end
78
79class Boolean < Struct.new(:value)
80 def to_s
81 value.to_s
82 end
83
84 def inspect
85 "<<#{self}>>"
86 end
87
88 def reducible?
89 false
90 end
91end
92
93class LessThan < Struct.new(:left, :right)
94 def to_s
95 "#{left} < #{right}"
96 end
97
98 def inspect
99 "<<#{self}>>"
100 end
101
102 def reducible?
103 true
104 end
105
106 def reduce(environment)
107 if left.reducible?
108 LessThan.new(left.reduce(environment), right)
109 elsif right.reducible?
110 LessThan.new(left, right.reduce(environment))
111 else
112 Boolean.new(left.value < right.value)
113 end
114 end
115end
116
117class Variable < Struct.new(:name)
118 def to_s
119 name.to_s
120 end
121
122 def inspect
123 "<<#{self}>>"
124 end
125
126 def reducible?
127 true
128 end
129
130 def reduce(environment)
131 environment[name]
132 end
133end
134
135describe "expressions" do
136 it "can do math" do
137 machine = Machine.new(Add.new(Multiply.new(Number.new(1), Number.new(2)), Multiply.new(Number.new(3), Number.new(4))))
138 result = machine.run
139 puts result
140 end
141
142 it "can check less than" do
143 puts Machine.new(LessThan.new(Number.new(5), Add.new(Number.new(2), Number.new(2)))).run
144 end
145
146 it "can assign variables" do
147 environment = { x: Number.new(3), y: Number.new(4) }
148 puts Machine.new(Add.new(Variable.new(:x), Variable.new(:y)), environment).run
149 end
150end