diff --git a/lib/ast/basic_expressions.rb b/lib/ast/basic_expressions.rb index 252e5284..fc78ad37 100644 --- a/lib/ast/basic_expressions.rb +++ b/lib/ast/basic_expressions.rb @@ -34,7 +34,7 @@ module Ast # otherwise it's a method without args and a send is ussued. # this makes the namespace static, ie when eval and co are implemented method needs recompilation def compile frame , method - return Virtual::SelfReference.new() if name == :self + return Virtual::Self.new( Virtual::Mystery.new ) if name == :self if method.has_var(name) frame.compile_get(method , name ) else @@ -75,6 +75,7 @@ module Ast class VariableExpression < NameExpression def compile frame ,method method.add Virtual::ObjectGet.new(name) + Virtual::Return.new( Virtual::Mystery.new ) end end end \ No newline at end of file diff --git a/lib/ast/call_site_expression.rb b/lib/ast/call_site_expression.rb index 6b0ae3ba..001ce17c 100644 --- a/lib/ast/call_site_expression.rb +++ b/lib/ast/call_site_expression.rb @@ -6,7 +6,7 @@ module Ast @@counter = 0 def compile frame , method with = args.collect{|a| a.compile(frame , method)} - frame.compile_send( method , @name , with ) + frame.compile_send( method , name , with ) end def scratch diff --git a/lib/ast/operator_expressions.rb b/lib/ast/operator_expressions.rb index 77ac3802..a9b05798 100644 --- a/lib/ast/operator_expressions.rb +++ b/lib/ast/operator_expressions.rb @@ -2,12 +2,10 @@ module Ast class OperatorExpression < Expression # attr_reader :operator, :left, :right def compile frame , method - tmp = method.get_tmp - ass = AssignmentExpression.new( tmp , left ) - l = ass.compile(frame , method) - call = CallSiteExpression.new( operator , [right] , l) + call = CallSiteExpression.new( operator , [right] , left ) call.compile(frame , method) end + def scratch into = context.function puts "compiling operator #{to_s}" diff --git a/lib/virtual/constants.rb b/lib/virtual/constants.rb index a17808cf..8aea60fa 100644 --- a/lib/virtual/constants.rb +++ b/lib/virtual/constants.rb @@ -3,10 +3,13 @@ module Virtual class Constant < ::Virtual::Value end class TrueValue < Constant + def attributes ; [] ; end end class FalseValue < Constant + def attributes ; [] ; end end class NilValue < Constant + def attributes ; [] ; end end # another abstract "marker" class (so we can check for it) @@ -19,7 +22,7 @@ module Virtual @integer = int end attr_reader :integer - def attributes + def attributes [:integer] end def inspect diff --git a/lib/virtual/frame.rb b/lib/virtual/frame.rb index e34616a7..a3248065 100644 --- a/lib/virtual/frame.rb +++ b/lib/virtual/frame.rb @@ -30,14 +30,17 @@ module Virtual # def compile_get method , name method.add FrameGet.new(name) + method.get_var(name) end def compile_send method , name , with = [] method.add FrameSend.new(name , with ) + Return.new( method.return_type ) end def compile_set method , name , val method.add FrameSet.new(name , val ) + method.get_var(name) end end end diff --git a/lib/virtual/instruction.rb b/lib/virtual/instruction.rb index 14a08e92..e4323ec7 100644 --- a/lib/virtual/instruction.rb +++ b/lib/virtual/instruction.rb @@ -18,9 +18,6 @@ module Virtual def initialize nex = nil @next = nex end - def type - Reference - end end # the first instruction we need is to stop. Off course in a real machine this would be a syscall, but that is just diff --git a/lib/virtual/method.rb b/lib/virtual/method.rb index 0862a589..2f41705b 100644 --- a/lib/virtual/method.rb +++ b/lib/virtual/method.rb @@ -17,7 +17,7 @@ module Virtual def attributes [:name , :args , :receiver , :return_type , :start] end - def initialize name , args , receiver = Virtual::SelfReference.new , return_type = Virtual::Reference , start = MethodEnter.new + def initialize name , args , receiver = Virtual::SelfReference.new , return_type = Virtual::Mystery , start = MethodEnter.new @name = name.to_sym @args = args @locals = [] @@ -34,7 +34,6 @@ module Virtual raise instruction.inspect unless instruction.is_a? Instruction @current.next = instruction @current = instruction - instruction.type end # determine whether this method has a variable by the given name @@ -46,7 +45,8 @@ module Virtual var = @tmps.find {|a| a == name } unless var var end - + alias :get_var :has_var + def get_tmp name = "__tmp__#{@tmps.length}" @tmps << name diff --git a/lib/virtual/type.rb b/lib/virtual/type.rb index 07f91e07..8f7352b3 100644 --- a/lib/virtual/type.rb +++ b/lib/virtual/type.rb @@ -48,7 +48,9 @@ module Virtual class Mystery < Type def initialize end - + def attributes + [] + end def as type type.new end diff --git a/lib/virtual/value.rb b/lib/virtual/value.rb index f50fa88b..096251a6 100644 --- a/lib/virtual/value.rb +++ b/lib/virtual/value.rb @@ -9,15 +9,65 @@ module Virtual def == other other.class == self.class end - def inspect - self.class.name + ".new()" - end def type - raise "abstract called" + raise "abstract called for #{self.class}" + end + def attributes + raise "abstract called for #{self.class}" + end + def == other + return false unless other.class == self.class + attributes.each do |a| + left = send(a) + right = other.send(a) + return false unless left.class == right.class + return false unless left == right + end + return true + end + def inspect + self.class.name + ".new(" + attributes.collect{|a| send(a).inspect }.join(",")+ ")" end private def initialize end end - + + class Variable < Value + + def initialize name , type + @name = name + @type = type + end + attr_accessor :name , :type + def attributes + [:name , :type] + end + end + # The subclasses are not strictly speaking neccessary at this def point + # i just don't want to destroy the information for later optimizations + # + # All variables are stored in frames and quite possibly in order arg,local,tmp + class Return < Variable + def initialize type + super(:return , type) + end + def attributes + [:type] + end + end + class Self < Variable + def initialize type + super(:self , type) + end + def attributes + [:type] + end + end + class Argument < Variable + end + class Local < Variable + end + class Temp < Variable + end end \ No newline at end of file diff --git a/test/virtual/test_basic.rb b/test/virtual/test_basic.rb index 154f3264..9d4e6d42 100644 --- a/test/virtual/test_basic.rb +++ b/test/virtual/test_basic.rb @@ -27,19 +27,19 @@ class TestBasic < MiniTest::Test def test_name @string_input = 'foo ' - @output = [Virtual::Reference] + @output = [Virtual::Return.new(Virtual::Mystery)] check end def test_self @string_input = 'self ' - @output = [Virtual::SelfReference.new()] + @output = [Virtual::Self.new(Virtual::Mystery.new())] check end def test_instance_variable @string_input = '@foo_bar ' - @output = [Virtual::Reference] + @output = [Virtual::Return.new( Virtual::Mystery.new())] check end diff --git a/test/virtual/test_methods.rb b/test/virtual/test_methods.rb index e5df4993..cda99ea2 100644 --- a/test/virtual/test_methods.rb +++ b/test/virtual/test_methods.rb @@ -9,7 +9,7 @@ def foo(x) 5 end HERE - @output = [Virtual::Method.new(:foo,[Ast::NameExpression.new(:x)],Virtual::SelfReference.new(),Virtual::IntegerConstant.new(5),Virtual::MethodEnter.new(nil))] + @output = [Virtual::Method.new(:foo,[Ast::NameExpression.new(:x)],Virtual::SelfReference.new(nil),Virtual::IntegerConstant.new(5),Virtual::MethodEnter.new(nil))] check end @@ -19,7 +19,7 @@ def String.length(x) @length end HERE - @output = [Virtual::Method.new(:length,[Ast::NameExpression.new(:x)],Boot::BootClass.new(:String,:Object),Virtual::Reference,Virtual::MethodEnter.new(Virtual::ObjectGet.new(:length)))] + @output = [Virtual::Method.new(:length,[Ast::NameExpression.new(:x)],Boot::BootClass.new(:String,:Object),Virtual::Return.new( Virtual::Mystery.new()),Virtual::MethodEnter.new(Virtual::ObjectGet.new(:length)))] check end @@ -30,7 +30,7 @@ def foo(x) 2 + 5 end HERE - @output = [Virtual::Method.new(:foo,[Ast::NameExpression.new(:x)],Virtual::SelfReference.new(),Virtual::Reference,Virtual::MethodEnter.new(Virtual::FrameSet.new(:abba,Virtual::IntegerConstant.new(5))))] + @output = [Virtual::Method.new(:foo,[Ast::NameExpression.new(:x)],Virtual::SelfReference.new(nil),Virtual::Return.new( Virtual::Mystery),Virtual::MethodEnter.new(Virtual::FrameSet.new(:abba,Virtual::IntegerConstant.new(5))))] check end