Skip to content

Instantly share code, notes, and snippets.

@justincampbell
Created January 22, 2015 14:47
Show Gist options
  • Save justincampbell/e6cba19ead5d5ea1554d to your computer and use it in GitHub Desktop.
Save justincampbell/e6cba19ead5d5ea1554d to your computer and use it in GitHub Desktop.
module Guillemets
def inspect; "<<#{self}>>"; end
end
Value = Struct.new(:value) do
include Guillemets
def reducible?; false; end
end
Operation = Struct.new(:left, :right) do
include Guillemets
def self.operator(symbol = nil); @operator ||= symbol end
def operator; self.class.operator; end
def reducible?; true; end
def to_s; "#{left} #{operator} #{right}"; end
def reduce
if left.reducible?
self.class.new(left.reduce, right)
elsif right.reducible?
self.class.new(left, right.reduce)
else
Number.new(left.value.send(operator, right.value))
end
end
end
class Number < Value
def to_s; "#{value}"; end
end
class Add < Operation
operator :+
end
class Multiply < Operation
operator :*
end
Machine = Struct.new(:expression) do
def step
self.expression = expression.reduce # => <<2 + 3 * 4>>, <<2 + 12>>, <<14>>
end
def run
step while expression.reducible?
expression
end
end
expression = Add.new(
Multiply.new(Number.new(1), Number.new(2)),
Multiply.new(Number.new(3), Number.new(4))
) # => <<1 * 2 + 3 * 4>>
machine = Machine.new(expression)
machine.run # => <<14>>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment