diff --git a/lib/virtual/compiler.rb b/lib/bosl/compiler.rb similarity index 78% rename from lib/virtual/compiler.rb rename to lib/bosl/compiler.rb index 60a09094..bea82d45 100644 --- a/lib/virtual/compiler.rb +++ b/lib/bosl/compiler.rb @@ -1,4 +1,4 @@ -module Virtual +module Bosl module Compiler # Compiling is the conversion of the AST into 2 things: @@ -14,19 +14,14 @@ module Virtual # may be unknown Unknown value. # # The Compiler.compile uses a visitor patter to dispatch according to the class name of - # the expression. So a NameExpression is delegated to compile_name etc. + # the expression. So a NameExpression is delegated to Virtual::Set.new etc. # This makes the dispatch extensible, ie Expressions may be added by external code, # as long as matching compile methods are supplied too. # def self.compile expression , method - exp_name = expression.class.name.split("::").last.sub("Expression","").downcase - #puts "Expression #{exp_name}" - begin - self.send "compile_#{exp_name}".to_sym , expression, method - rescue NoMethodError => e - puts "No compile method found for " + exp_name + " #{e}" - raise e - end + exp_name = expression.type + puts "Expression #{expression.to_sexp}" + self.send "compile_#{exp_name}".to_sym , expression, method end end diff --git a/lib/virtual/compiler/README.md b/lib/bosl/compiler/README.md similarity index 100% rename from lib/virtual/compiler/README.md rename to lib/bosl/compiler/README.md diff --git a/lib/virtual/compiler/basic_expressions.rb b/lib/bosl/compiler/basic_expressions.rb similarity index 66% rename from lib/virtual/compiler/basic_expressions.rb rename to lib/bosl/compiler/basic_expressions.rb index 45d24d18..1de04629 100644 --- a/lib/virtual/compiler/basic_expressions.rb +++ b/lib/bosl/compiler/basic_expressions.rb @@ -1,4 +1,4 @@ -module Virtual +module Bosl # collection of the simple ones, int and strings and such module Compiler @@ -12,36 +12,36 @@ module Virtual # But in the future (in the one that holds great things) we optimize those unneccesay moves away # attr_reader :value - def self.compile_integer expression , method - int = expression.value - to = Return.new(Integer , int) - method.source.add_code Set.new( int , to ) + def self.compile_int expression , method + int = *expression + to = Virtual::Return.new(Integer , int) + method.source.add_code Virtual::Set.new( int , to ) to end def self.compile_true expression , method - to = Return.new(Reference , true ) - method.source.add_code Set.new( true , to ) + to = Virtual::Return.new(Reference , true ) + method.source.add_code Virtual::Set.new( true , to ) to end def self.compile_false expression , method - to = Return.new(Reference , false) - method.source.add_code Set.new( false , to ) + to = Virtual::Return.new(Reference , false) + method.source.add_code Virtual::Set.new( false , to ) to end def self.compile_nil expression , method - to = Return.new(Reference , nil) - method.source.add_code Set.new( nil , to ) + to = Virtual::Return.new(Reference , nil) + method.source.add_code Virtual::Set.new( nil , to ) to end def self.compile_modulename expression , method clazz = Parfait::Space.object_space.get_class_by_name expression.name raise "compile_modulename #{clazz}.#{name}" unless clazz - to = Return.new(Reference , clazz ) - method.source.add_code Set.new( clazz , to ) + to = Virtual::Return.new(Reference , clazz ) + method.source.add_code Virtual::Set.new( clazz , to ) to end @@ -49,9 +49,9 @@ module Virtual def self.compile_string expression , method # Clearly a TODO here to implement strings rather than reusing symbols value = expression.string.to_sym - to = Return.new(Reference , value) + to = Virtual::Return.new(Reference , value) method.source.constants << value - method.source.add_code Set.new( value , to ) + method.source.add_code Virtual::Set.new( value , to ) to end @@ -64,17 +64,17 @@ module Virtual raise "oh noo, nil from where #{expression.right.inspect}" unless r index = method.has_arg(expression.left.name.to_sym) if index - method.source.add_code Set.new(ArgSlot.new(index , r.type , r ) , Return.new) + method.source.add_code Virtual::Set.new(ArgSlot.new(index , r.type , r ) , Virtual::Return.new) else index = method.ensure_local(expression.left.name.to_sym) - method.source.add_code Set.new(FrameSlot.new(index , r.type , r ) , Return.new) + method.source.add_code Virtual::Set.new(FrameSlot.new(index , r.type , r ) , Virtual::Return.new) end r end def self.compile_variable expression, method method.source.add_code InstanceGet.new(expression.name) - Return.new( Unknown ) + Virtual::Return.new( Unknown ) end end end diff --git a/lib/virtual/compiler/callsite_expression.rb b/lib/bosl/compiler/callsite_expression.rb similarity index 54% rename from lib/virtual/compiler/callsite_expression.rb rename to lib/bosl/compiler/callsite_expression.rb index 480cae22..36c9dbeb 100644 --- a/lib/virtual/compiler/callsite_expression.rb +++ b/lib/bosl/compiler/callsite_expression.rb @@ -1,33 +1,36 @@ -module Virtual +module Bosl module Compiler # operators are really function calls # call_site - attr_reader :name, :args , :receiver - def self.compile_callsite expession , method - me = Compiler.compile( expession.receiver , method ) + def self.compile_call expession , method + name , arguments , receiver = *expession + name = name.to_a.first + + me = Compiler.compile( receiver.to_a.first , method ) ## need two step process, compile and save to frame # then move from frame to new message - method.source.add_code NewMessage.new - method.source.add_code Set.new( me , NewSelf.new(me.type)) - method.source.add_code Set.new( expession.name.to_sym , NewMessageName.new()) + method.source.add_code Virtual::NewMessage.new + method.source.add_code Virtual::Set.new( me , Virtual::NewSelf.new(me.type)) + method.source.add_code Virtual::Set.new( name.to_sym , Virtual::NewMessageName.new()) compiled_args = [] - expession.args.each_with_index do |arg , i| + arguments.to_a.each_with_index do |arg , i| #compile in the running method, ie before passing control val = Compiler.compile( arg , method) # move the compiled value to it's slot in the new message # + 1 as this is a ruby 0-start , but 0 is the last message ivar. # so the next free is +1 - to = NewArgSlot.new(i + 1 ,val.type , val) + to = Virtual::NewArgSlot.new(i + 1 ,val.type , val) # (doing this immediately, not after the loop, so if it's a return it won't get overwritten) - method.source.add_code Set.new( val , to ) + method.source.add_code Virtual::Set.new( val , to ) compiled_args << to end - method.source.add_code MessageSend.new(expession.name , me , compiled_args) #and pass control + method.source.add_code Virtual::MessageSend.new(name , me , compiled_args) #and pass control # the effect of the method is that the NewMessage Return slot will be filled, return it # (this is what is moved _inside_ above loop for such expressions that are calls (or constants)) - Return.new( method.source.return_type ) + Virtual::Return.new( method.source.return_type ) end end end diff --git a/lib/virtual/compiler/compound_expressions.rb b/lib/bosl/compiler/compound_expressions.rb similarity index 94% rename from lib/virtual/compiler/compound_expressions.rb rename to lib/bosl/compiler/compound_expressions.rb index 45f81d77..c0fcdaf9 100644 --- a/lib/virtual/compiler/compound_expressions.rb +++ b/lib/bosl/compiler/compound_expressions.rb @@ -1,4 +1,4 @@ -module Virtual +module Bosl module Compiler # attr_reader :values diff --git a/lib/virtual/compiler/expression_list.rb b/lib/bosl/compiler/expression_list.rb similarity index 54% rename from lib/virtual/compiler/expression_list.rb rename to lib/bosl/compiler/expression_list.rb index 12b0d7ac..759a3470 100644 --- a/lib/virtual/compiler/expression_list.rb +++ b/lib/bosl/compiler/expression_list.rb @@ -1,8 +1,8 @@ -module Virtual +module Bosl module Compiler # list - attr_reader :expressions - def self.compile_list expession , method - expession.expressions.collect do |part| + def self.compile_expressions expession , method + expession.children.collect do |part| Compiler.compile( part , method ) end end diff --git a/lib/virtual/compiler/function_expression.rb b/lib/bosl/compiler/function_expression.rb similarity index 63% rename from lib/virtual/compiler/function_expression.rb rename to lib/bosl/compiler/function_expression.rb index 4bc81cc7..a3299ce9 100644 --- a/lib/virtual/compiler/function_expression.rb +++ b/lib/bosl/compiler/function_expression.rb @@ -1,12 +1,15 @@ -module Virtual +module Bosl module Compiler # function attr_reader :name, :params, :body , :receiver def self.compile_function expression, method - args = expression.params.collect do |p| - raise "error, argument must be a identifier, not #{p}" unless p.is_a? Ast::NameExpression - p.name + return_type , name , parameters, kids = *expression + name = name.to_a.first + args = parameters.to_a.collect do |p| + raise "error, argument must be a identifier, not #{p}" unless p.type == :field + p[2] end - if expression.receiver + + if expression[:receiver] # compiler will always return slot. with known value or not r = Compiler.compile(expression.receiver, method ) if( r.value.is_a? Parfait::Class ) @@ -15,21 +18,20 @@ module Virtual raise "unimplemented case in function #{r}" end else - r = Self.new() + r = Virtual::Self.new() class_name = method.for_class.name end - new_method = MethodSource.create_method(class_name, expression.name , args ) + new_method = Virtual::MethodSource.create_method(class_name, name , args ) new_method.source.receiver = r new_method.for_class.add_instance_method new_method #frame = frame.new_frame - return_type = nil - expression.body.each do |ex| + kids.to_a.each do |ex| return_type = Compiler.compile(ex,new_method ) - raise return_type.inspect if return_type.is_a? Instruction + raise return_type.inspect if return_type.is_a? Virtual::Instruction end new_method.source.return_type = return_type - Return.new(return_type) + Virtual::Return.new(return_type) end end end diff --git a/lib/virtual/compiler/if_expression.rb b/lib/bosl/compiler/if_expression.rb similarity index 99% rename from lib/virtual/compiler/if_expression.rb rename to lib/bosl/compiler/if_expression.rb index f3e53a39..8561ccdb 100644 --- a/lib/virtual/compiler/if_expression.rb +++ b/lib/bosl/compiler/if_expression.rb @@ -1,4 +1,4 @@ -module Virtual +module Bosl module Compiler # if - attr_reader :cond, :if_true, :if_false diff --git a/lib/virtual/compiler/module_expression.rb b/lib/bosl/compiler/module_expression.rb similarity index 98% rename from lib/virtual/compiler/module_expression.rb rename to lib/bosl/compiler/module_expression.rb index c9781ac9..aa6b0ded 100644 --- a/lib/virtual/compiler/module_expression.rb +++ b/lib/bosl/compiler/module_expression.rb @@ -1,4 +1,4 @@ -module Virtual +module Bosl module Compiler # module attr_reader :name ,:expressions def self.compile_module expression , context diff --git a/lib/bosl/compiler/name_expression.rb b/lib/bosl/compiler/name_expression.rb new file mode 100644 index 00000000..404ac3a8 --- /dev/null +++ b/lib/bosl/compiler/name_expression.rb @@ -0,0 +1,23 @@ +module Bosl + module Compiler + + # attr_reader :name + # compiling name needs to check if it's a variable and if so resolve it + # otherwise it's a method without args and a send is issued. + # whichever way this goes the result is stored in the return slot (as all compiles) + def self.compile_name expression , method + name = expression.to_a.first + return Virtual::Self.new( Reference.new(method.for_class)) if name == :self + # either an argument, so it's stored in message + ret = Virtual::Return.new + if( index = method.has_arg(name)) + method.source.add_code Virtual::Set.new( Virtual::ArgSlot.new(index ) , ret) + else # or a local so it is in the frame + index = method.ensure_local( name ) + method.source.add_code Virtual::Set.new(Virtual::FrameSlot.new(index ) , ret ) + end + return ret + end + + end #module +end diff --git a/lib/bosl/compiler/operator_expressions.rb b/lib/bosl/compiler/operator_expressions.rb new file mode 100644 index 00000000..f9da2d80 --- /dev/null +++ b/lib/bosl/compiler/operator_expressions.rb @@ -0,0 +1,20 @@ +module Bosl + module Compiler +# operator attr_reader :operator, :left, :right + def self.compile_operator expression, method + call = Ast::CallSiteExpression.new(expression.operator , [expression.right] , expression.left ) + Compiler.compile(call, method) + end + + def self.compile_assign expression, method + puts "assign" + puts expression.inspect + name , value = *expression + name = name.to_a.first + v = self.compile(value , method ) + index = method.ensure_local( name ) + method.source.add_code Virtual::Set.new(Virtual::FrameSlot.new(index ) , v ) + end + + end +end diff --git a/lib/virtual/compiler/return_expression.rb b/lib/bosl/compiler/return_expression.rb similarity index 61% rename from lib/virtual/compiler/return_expression.rb rename to lib/bosl/compiler/return_expression.rb index 9e22677a..48591d55 100644 --- a/lib/virtual/compiler/return_expression.rb +++ b/lib/bosl/compiler/return_expression.rb @@ -1,9 +1,9 @@ -module Virtual +module Bosl module Compiler # return attr_reader :expression def self.compile_return expression, method - return Compiler.compile(expression.expression , method) + return Compiler.compile(expression.to_a.first , method) end end end diff --git a/lib/virtual/compiler/while_expression.rb b/lib/bosl/compiler/while_expression.rb similarity index 98% rename from lib/virtual/compiler/while_expression.rb rename to lib/bosl/compiler/while_expression.rb index fe530f0d..e2e4b361 100644 --- a/lib/virtual/compiler/while_expression.rb +++ b/lib/bosl/compiler/while_expression.rb @@ -1,4 +1,4 @@ -module Virtual +module Bosl module Compiler # while- attr_reader :condition, :body diff --git a/lib/virtual.rb b/lib/virtual.rb index aafaf2af..59e68477 100644 --- a/lib/virtual.rb +++ b/lib/virtual.rb @@ -5,7 +5,7 @@ require "virtual/positioned" require "virtual/padding" require "virtual/parfait_adapter" -require "virtual/compiler" +require "bosl/compiler" require "virtual/instruction" require "virtual/method_source" require "virtual/slots/slot" diff --git a/lib/virtual/compiler/name_expression.rb b/lib/virtual/compiler/name_expression.rb deleted file mode 100644 index cf68d2e2..00000000 --- a/lib/virtual/compiler/name_expression.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Virtual - module Compiler - - # attr_reader :name - # compiling name needs to check if it's a variable and if so resolve it - # otherwise it's a method without args and a send is issued. - # whichever way this goes the result is stored in the return slot (as all compiles) - def self.compile_name expression , method - return Self.new( Reference.new(method.for_class)) if expression.name == :self - name = expression.name.to_sym - if method.has_var(name) - # either an argument, so it's stored in message - ret = Return.new - if( index = method.has_arg(name)) - method.source.add_code Set.new( ArgSlot.new(index ) , ret) - else # or a local so it is in the frame - index = method.ensure_local( name ) - method.source.add_code Set.new(FrameSlot.new(index ) , ret ) - end - return ret - else - call = Ast::CallSiteExpression.new(expression.name , [] ) #receiver self is implicit - Compiler.compile(call, method) - end - end - - end #module -end diff --git a/lib/virtual/compiler/operator_expressions.rb b/lib/virtual/compiler/operator_expressions.rb deleted file mode 100644 index 6f16297f..00000000 --- a/lib/virtual/compiler/operator_expressions.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Virtual - module Compiler -# operator attr_reader :operator, :left, :right - def self.compile_operator expression, method - call = Ast::CallSiteExpression.new(expression.operator , [expression.right] , expression.left ) - Compiler.compile(call, method) - end - end -end diff --git a/lib/virtual/machine.rb b/lib/virtual/machine.rb index 19736996..994c978c 100644 --- a/lib/virtual/machine.rb +++ b/lib/virtual/machine.rb @@ -135,7 +135,7 @@ module Virtual syntax = @parser.parse_with_debug(bytes) parts = Parser::Transform.new.apply(syntax) #puts parts.to_s - Compiler.compile( parts , @space.get_main ) + Bosl::Compiler.compile( parts , @space.get_main ) end private diff --git a/test/fragments/test_foo.rb b/test/fragments/test_foo.rb index 689a2da2..e8e921bc 100644 --- a/test/fragments/test_foo.rb +++ b/test/fragments/test_foo.rb @@ -5,8 +5,9 @@ class TestFoo < MiniTest::Test def test_foo2 @string_input = <