diff --git a/lib/parfait.rb b/lib/parfait.rb index abd42f82..e7d82079 100644 --- a/lib/parfait.rb +++ b/lib/parfait.rb @@ -30,7 +30,7 @@ module Parfait def self.object_space Object.object_space end - + class Object # redefine the runtime version def self.new( *args ) diff --git a/lib/parfait/class.rb b/lib/parfait/class.rb index 2f36461b..fa1890a4 100644 --- a/lib/parfait/class.rb +++ b/lib/parfait/class.rb @@ -33,7 +33,7 @@ module Parfait @name = name @super_class_name = superclass @instance_methods = List.new - set_instance_type( instance_type ) + @instance_type = instance_type @meta_class = MetaClass.new( self ) end @@ -65,13 +65,6 @@ module Parfait @instance_type = @instance_type.add_instance_variable( name , type ) end - # setting the type generates all methods for this type - # (or will do, once we store the methods code to do that) - def set_instance_type( type ) - raise "type must be type #{type}" unless type.is_a?(Type) - @instance_type = type - end - # return the super class, but raise exception if either the super class name # or the super classs is nil. # Use only for non Object base class diff --git a/lib/parfait/meta_class.rb b/lib/parfait/meta_class.rb index 670415f8..a7105d78 100644 --- a/lib/parfait/meta_class.rb +++ b/lib/parfait/meta_class.rb @@ -30,7 +30,7 @@ module Parfait super() @clazz = clazz @instance_methods = List.new - set_instance_type( clazz.get_type() ) + @instance_type = Object.object_space.get_type_by_class_name(:Object) end def rxf_reference_name @@ -61,13 +61,6 @@ module Parfait @instance_type = @instance_type.add_instance_variable( name , type ) end - # setting the type generates all methods for this type - # (or will do, once we store the methods code to do that) - def set_instance_type( type ) - raise "type must be type #{type.class}:#{type}" unless type.is_a?(Type) - @instance_type = type - end - # Nil name means no superclass, and so nil returned def super_class return nil diff --git a/lib/parfait/type.rb b/lib/parfait/type.rb index c9b84701..b7e73995 100644 --- a/lib/parfait/type.rb +++ b/lib/parfait/type.rb @@ -190,6 +190,7 @@ module Parfait def add_instance_variable( name , type ) raise "No nil name" unless name raise "No nil type" unless type + return self if @names.index_of(name) hash = to_hash hash[name] = type return Type.for_hash( hash , object_class) diff --git a/lib/risc/parfait_boot.rb b/lib/risc/parfait_boot.rb index a6d47633..e7b08e5c 100644 --- a/lib/risc/parfait_boot.rb +++ b/lib/risc/parfait_boot.rb @@ -3,8 +3,9 @@ module Boot # a ruby object as a placeholder for the parfait Space during boot class Space - attr_reader :classes + attr_reader :classes , :types def initialize + @types = {} @classes = {} end @@ -13,6 +14,9 @@ module Boot raise "No class for #{name}" unless cl cl end + def get_type_by_class_name(name) + @types[name] + end end # another ruby object to shadow the parfait, just during booting. @@ -82,6 +86,7 @@ module Parfait types.each do |name , type| clazz = Boot::Class.new(type) boot_space.classes[name] = clazz + boot_space.types[name] = type end Parfait::Object.set_object_space( boot_space ) end diff --git a/lib/vool/builtin/int_plus.rb b/lib/vool/builtin/int_plus.rb deleted file mode 100644 index e90423b3..00000000 --- a/lib/vool/builtin/int_plus.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Integer < DataObject4 - def +(other) - return X.int_operator( :+ ) - end -end diff --git a/lib/vool/class_expression.rb b/lib/vool/class_expression.rb index 96d31b91..e18b0621 100644 --- a/lib/vool/class_expression.rb +++ b/lib/vool/class_expression.rb @@ -45,11 +45,6 @@ module Vool Mom::MomCollection.new(method_compilers) end - def each(&block) - block.call(self) - @body.each(&block) if @body - end - # This creates the Parfait class. But doesn not handle reopening yet, so only new classes # Creating the class involves creating the instance_type (or an initial version) # which means knowing all used names. So we go through the code looking for @@ -60,24 +55,37 @@ module Vool #FIXME super class check with "sup" #existing class, don't overwrite type (parfait only?) else - create_new_class + @clazz = Parfait.object_space.create_class(@name , @super_class_name ) end + create_types @clazz end - def create_new_class - @clazz = Parfait.object_space.create_class(@name , @super_class_name ) - #TODO this should start from Object Type and add one name at a time. - # So the "trail" of types leading to this one exists. - # Also the Class always has a valid type. - ivar_hash = {} - self.each do |node| - next unless node.is_a?(InstanceVariable) or node.is_a?(IvarAssignment) - ivar_hash[node.name] = :Object + # goes through the code looking for instance variables (and their assignments) + # adding each to the respective type, ie class or meta_class, depending + # on if they are instance or class instance variables. + # + # Class variables are deemed a design mistake, ie not implemented (yet) + def create_types + self.body.statements.each do |node| + case node + when MethodExpression + target = @clazz + when ClassMethodExpression + target = @clazz.meta_class + else + raise "Only methods for now #{node.class}:#{node}" + end + node.each do |exp| + case exp + when InstanceVariable, IvarAssignment + target.add_instance_variable( exp.name , :Object ) + when ClassVariable #, ClassVarAssignment + raise "Class variables not implemented #{node.name}" + end + end end - @clazz.set_instance_type( Parfait::Type.for_hash( ivar_hash , @clazz ) ) end - def to_s(depth = 0) at_depth(depth , "class #{name}" , @body.to_s(depth + 1) , "end") end diff --git a/lib/vool/class_method_expression.rb b/lib/vool/class_method_expression.rb index 77040980..b4045767 100644 --- a/lib/vool/class_method_expression.rb +++ b/lib/vool/class_method_expression.rb @@ -11,7 +11,6 @@ module Vool raise "not meta" unless clazz.class == Parfait::MetaClass raise( "no class in #{self}") unless clazz method = clazz.add_method_for(name , make_arg_type , make_frame , body ) -#VoolMethod compiler = method.compiler_for(clazz.instance_type) each {|node| raise "Blocks not implemented" if node.is_a?(LambdaExpression)} compiler diff --git a/test/parfait/type/test_type_api.rb b/test/parfait/type/test_type_api.rb index 1915f034..b5650342 100644 --- a/test/parfait/type/test_type_api.rb +++ b/test/parfait/type/test_type_api.rb @@ -58,6 +58,10 @@ module Parfait assert_equal :Type , @type.type_at(0) end + def test_add_again + assert_equal @type.to_hash , @type.add_instance_variable(:type , :Type).to_hash + end + def test_inspect_added type = test_add_name assert type.inspect.include?("boo") , type.inspect diff --git a/test/vool/class_send/test_class_instance.rb b/test/vool/class_send/test_class_instance.rb index e6f38e33..71767e59 100644 --- a/test/vool/class_send/test_class_instance.rb +++ b/test/vool/class_send/test_class_instance.rb @@ -19,10 +19,15 @@ module Vool end def setup - source = "class Integer;def +(other);X.int_operator(:+);end;end;" + class_main - ret = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_mom(source) + ret = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_mom(class_main) @ins = ret.compilers.find{|c|c.callable.name==:some_inst}.mom_instructions.next end + def test_class_inst + space_class = Parfait.object_space.get_class + assert_equal :Space , space_class.name + names = space_class.meta_class.instance_type.names + assert names.index_of(:inst) , names + end def test_array check_array [SlotLoad, ReturnJump, Label, ReturnSequence, Label] , @ins end