From c411ac5df8e6a11c80b4f637b9ca90a4ef69117f Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Thu, 24 Apr 2014 17:38:06 +0300 Subject: [PATCH] removed the structs (code smell) --- lib/crystal.rb | 2 ++ lib/vm/compiler.rb | 2 +- lib/vm/nodes.rb | 38 +++++++++++++++++++++++++++++++++----- lib/vm/transform.rb | 14 +++++++------- test/test_nodes.rb | 30 +++++++++++++++--------------- test/test_transform.rb | 28 ++++++++++++++-------------- 6 files changed, 72 insertions(+), 42 deletions(-) diff --git a/lib/crystal.rb b/lib/crystal.rb index 600c1e88..3cd55220 100644 --- a/lib/crystal.rb +++ b/lib/crystal.rb @@ -6,4 +6,6 @@ require "asm/stack_instruction" require "asm/arm_assembler" require "elf/object_writer" require 'vm/parser' +require 'vm/nodes' +require 'vm/transform' diff --git a/lib/vm/compiler.rb b/lib/vm/compiler.rb index 55113a94..777f36aa 100644 --- a/lib/vm/compiler.rb +++ b/lib/vm/compiler.rb @@ -54,7 +54,7 @@ module Vm end def split_functions(tree) - first_expr = tree.index { |t| ! t.is_a?(Function) } + first_expr = tree.index { |t| ! t.is_a?(FunctionExpression) } funcs = first_expr ? tree[0...first_expr] : tree exprs = first_expr ? tree[first_expr..-1] : [] diff --git a/lib/vm/nodes.rb b/lib/vm/nodes.rb index 500f3aec..b0bbafc0 100644 --- a/lib/vm/nodes.rb +++ b/lib/vm/nodes.rb @@ -1,11 +1,27 @@ module Vm - class Number < Struct.new :value + + class Expression + # evey Expression has a eval function that returns a value + def eval + raise "abstract" + end + end + + class NumberExpression < Expression + attr_reader :value + def initialize val + @value = val + end def eval(context, builder) builder.mov "r0" , value end end - class Name < Struct.new :name + class NameExpression < Expression + attr_reader :name + def initialize name + @name = name + end def eval(context, builder) param_names = context[:params] || [] position = param_names.index(name) @@ -15,7 +31,11 @@ module Vm end end - class Funcall < Struct.new :name, :args + class FuncallExpression < Expression + attr_reader :name, :args + def initialize name, args + @name , @args = name , args + end def eval(context, builder) args.each { |a| a.eval(context, builder) } types = [builder.int] * (args.length + 1) @@ -23,7 +43,11 @@ module Vm end end - class Conditional < Struct.new :cond, :if_true, :if_false + class ConditionalExpression < Expression + attr_reader :cond, :if_true, :if_false + def initialize cond, if_true, if_false + @cond, @if_true, @if_false = cond, if_true, if_false + end def eval(context, builder) cond.eval context, builder @@ -39,7 +63,11 @@ module Vm end end - class Function < Struct.new :name, :params, :body + class FunctionExpression < Expression + attr_reader :name, :params, :body + def initialize name, params, body + @name, @params, @body = name, params, body + end def eval(context, builder) param_names = [params].flatten.map(&:name) context[:params] = param_names diff --git a/lib/vm/transform.rb b/lib/vm/transform.rb index 81024f02..314a139f 100644 --- a/lib/vm/transform.rb +++ b/lib/vm/transform.rb @@ -3,31 +3,31 @@ require 'vm/nodes' module Vm class Transform < Parslet::Transform - rule(:number => simple(:value)) { Number.new(value.to_i) } - rule(:name => simple(:name)) { Name.new(name.to_s) } + rule(:number => simple(:value)) { NumberExpression.new(value.to_i) } + rule(:name => simple(:name)) { NameExpression.new(name.to_s) } rule(:arg => simple(:arg)) { arg } rule(:args => sequence(:args)) { args } rule(:funcall => simple(:funcall), - :args => simple(:args)) { Funcall.new(funcall.name, [args]) } + :args => simple(:args)) { FuncallExpression.new(funcall.name, [args]) } rule(:funcall => simple(:funcall), - :args => sequence(:args)) { Funcall.new(funcall.name, args) } + :args => sequence(:args)) { FuncallExpression.new(funcall.name, args) } rule(:cond => simple(:cond), :if_true => {:body => simple(:if_true)}, - :if_false => {:body => simple(:if_false)}) { Conditional.new(cond, if_true, if_false) } + :if_false => {:body => simple(:if_false)}) { ConditionalExpression.new(cond, if_true, if_false) } rule(:param => simple(:param)) { param } rule(:params => sequence(:params)) { params } rule(:func => simple(:func), :params => simple(:name), - :body => simple(:body)) { Function.new(func.name, [name], body) } + :body => simple(:body)) { FunctionExpression.new(func.name, [name], body) } rule(:func => simple(:func), :params => sequence(:params), - :body => simple(:body)) { Function.new(func.name, params, body) } + :body => simple(:body)) { FunctionExpression.new(func.name, params, body) } end end diff --git a/test/test_nodes.rb b/test/test_nodes.rb index d7fa992c..6c960142 100644 --- a/test/test_nodes.rb +++ b/test/test_nodes.rb @@ -1,15 +1,15 @@ -$: << File.expand_path(File.dirname(__FILE__) + '/../lib') -$: << File.expand_path(File.dirname(__FILE__)) - -require 'minitest/autorun' +require_relative "helper" require 'minitest/spec' -require 'vm/nodes' include Vm class FakeBuilder attr_reader :result + Asm::InstructionTools::REGISTERS.each do |reg , number| + define_method(reg) { Asm::Register.new(reg , number) } + end + def initialize @result = '' end @@ -36,7 +36,7 @@ describe 'Nodes' do end it 'emits a number' do - input = Vm::Number.new 42 + input = Vm::NumberExpression.new 42 expected = < '42'} - expected = Vm::Number.new(42) + expected = Vm::NumberExpression.new(42) @transform.apply(input).must_equal expected end it 'transforms a name' do input = {:name => 'foo'} - expected = Vm::Name.new('foo') + expected = Vm::NameExpression.new('foo') @transform.apply(input).must_equal expected end @@ -26,8 +26,8 @@ describe Transform do it 'transforms an argument list' do input = {:args => [{:arg => {:number => '42'}}, {:arg => {:name => 'foo'}}]} - expected = [Vm::Number.new(42), - Vm::Name.new('foo')] + expected = [Vm::NumberExpression.new(42), + Vm::NameExpression.new('foo')] @transform.apply(input).must_equal expected end @@ -35,7 +35,7 @@ describe Transform do it 'transforms a single-argument function call' do input = {:funcall => {:name => 'foo'}, :args => [{:arg => {:number => '42'}}]} - expected = Vm::Funcall.new 'foo', [Vm::Number.new(42)] + expected = Vm::FuncallExpression.new 'foo', [Vm::NumberExpression.new(42)] @transform.apply(input).must_equal expected end @@ -44,8 +44,8 @@ describe Transform do input = {:funcall => {:name => 'baz'}, :args => [{:arg => {:number => '42'}}, {:arg => {:name => 'foo'}}]} - expected = Vm::Funcall.new 'baz', [Vm::Number.new(42), - Vm::Name.new('foo')] + expected = Vm::FuncallExpression.new 'baz', [Vm::NumberExpression.new(42), + Vm::NameExpression.new('foo')] @transform.apply(input).must_equal expected end @@ -54,10 +54,10 @@ describe Transform do input = {:cond => {:number => '0'}, :if_true => {:body => {:number => '42'}}, :if_false => {:body => {:number => '667'}}} - expected = Vm::Conditional.new \ - Vm::Number.new(0), - Vm::Number.new(42), - Vm::Number.new(667) + expected = Vm::ConditionalExpression.new \ + Vm::NumberExpression.new(0), + Vm::NumberExpression.new(42), + Vm::NumberExpression.new(667) @transform.apply(input).must_equal expected end @@ -66,10 +66,10 @@ describe Transform do input = {:func => {:name => 'foo'}, :params => {:param => {:name => 'x'}}, :body => {:number => '5'}} - expected = Vm::Function.new \ + expected = Vm::FunctionExpression.new \ 'foo', - [Vm::Name.new('x')], - Vm::Number.new(5) + [Vm::NameExpression.new('x')], + Vm::NumberExpression.new(5) @transform.apply(input).must_equal expected end