From b5dc5a923ff86163319424affd8cfa6bfc063841 Mon Sep 17 00:00:00 2001 From: Joe Zhao Date: Thu, 20 Mar 2014 11:56:20 +0800 Subject: First commit --- simple/simple.rb | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 simple/simple.rb (limited to 'simple') diff --git a/simple/simple.rb b/simple/simple.rb new file mode 100644 index 0000000..a31e001 --- /dev/null +++ b/simple/simple.rb @@ -0,0 +1,196 @@ +#!/usr/bin/ruby + +class Value < Struct.new(:value) + def to_s + value.to_s + end + def inspect + "<#{self}>" + end + def reducible? + false + end +end + +class Number < Value +end + +class Boolean < Value +end + +class Variable < Struct.new(:name) + def to_s + name.to_s + end + + def inspect + "<#{self}>" + end + + def reduce(environment) + environment[name] + end + + def reducible? + true + end +end + +class BiOp < Struct.new(:left, :right) + def inspect + "<#{self}>" + end + def reducible? + true + end +end + +class Add < BiOp + def to_s + "#{left} + #{right}" + end + def reduce(environment) + if left.reducible? + Add.new(left.reduce(environment),right) + elsif right.reducible? + Add.new(left,right.reduce(environment)) + else + Number.new(left.value+right.value) + end + end +end + +class Multiply < BiOp + def to_s + "#{left} * #{right}" + end + def reduce(environment) + if left.reducible? + Add.new(left.reduce(environment),right) + elsif right.reducible? + Add.new(left,right.reduce(environment)) + else + Number.new(left.value*right.value) + end + end +end + +class LessThan < BiOp + def to_s + "#{left} < #{right}" + end + + def reduce(environment) + if left.reducible? + LessThan.new(left.reduce(environment), right) + elsif right.reducible? + LessThan.new(left, right.reduce(environment)) + else + Boolean.new(left.value < right.value) + end + end +end + +class DoNothing + def to_s + 'do-nothing' + end + + def inspect + "<#{self}>" + end + + def ==(other_statement) + other_statement.instance_of?(DoNothing) + end + + def reducible? + false + end +end + +class Assign < Struct.new(:name, :expression) + def to_s + "#{name} = #{expression}" + end + + def inspect + "<#{self}>" + end + + def reducible? + true + end + + def reduce(environment) + if expression.reducible? + [Assign.new(name, expression.reduce(environment)), environment] + else + [DoNothing.new, environment.merge({name => expression })] + end + end +end + +class If < Struct.new(:condition, :consequence, :alternative) + def to_s + "if (#{condition}) { #{consequence} } else { #{alternative} }" + end + + def inspect + "<#{self}>" + end + + def reducible? + true + end + + def reduce(environment) + if condition.reducible? + [If.new(condition.reduce(environment), consequence, alternative), environment] + else + case condition + when Boolean.new(true) + [consequence, environment] + when Boolean.new(false) + [alternative, environment] + end + end + end +end + +class Sequence < Struct.new(:first, :second) + def to_s + "#{first}; #{second}" + end + + def inspect + "<#{self}>" + end + + def reducible? + true + end + + def reduce(environment) + case first + when DoNothing.new + [second,environment] + else + reduced_first, reduced_environment = first.reduce(environment) + [Sequence.new(reduced_first, second), reduced_environment] + end + +class Machine < Struct.new(:statement, :environment) + def step + self.statement, self.environment = statement.reduce(environment) + end + + def run + while statement.reducible? + puts "#{statement}, #{environment}" + step + end + + puts "#{statement}, #{environment}" + end +end -- cgit v1.2.3-70-g09d2