Torsten Rüger
d1f8733623
Simple is really the descriptive name for the layer Sure, it is "virtual" but that is not as important as the fact that it is simple (or simplified) Also objct (based really) is better, since orientated implies it is a little like that, but only orientated, not really it. Sol only has objects, nothing else Just cause i was renaming anyway
93 lines
3.3 KiB
Ruby
93 lines
3.3 KiB
Ruby
module Sol
|
|
# This represents a class at the sol level. Sol is a syntax tree,
|
|
# so here the only child (or children) is a body.
|
|
# Body may either be a MethodStatement, or Statements (either empty or
|
|
# containing MethodStatement)
|
|
#
|
|
# We store the class name and the parfait class
|
|
#
|
|
# The Parfait class gets created by to_parfait, ie only after that is the clazz
|
|
# attribute set.
|
|
#
|
|
class ClassExpression < Expression
|
|
attr_reader :name, :super_class_name , :body
|
|
attr_reader :clazz
|
|
|
|
def initialize( name , supe , body)
|
|
@name = name
|
|
@super_class_name = supe || :Object
|
|
raise "what body #{body}" unless body.is_a?(Statements)
|
|
@body = body
|
|
end
|
|
|
|
# This creates the Parfait class.
|
|
# 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
|
|
# InstanceVariables or InstanceVariable Assignments, to do that.
|
|
def to_parfait
|
|
@clazz = Parfait.object_space.get_class_by_name(@name )
|
|
if(@clazz)
|
|
if( @super_class_name != clazz.super_class_name)
|
|
raise "Superclass mismatch for #{@name} , was #{clazz.super_class_name}, now: #{super_class_name}"
|
|
end
|
|
else
|
|
@clazz = Parfait.object_space.create_class(@name , @super_class_name )
|
|
end
|
|
create_types
|
|
@body.statements.each {|meth| meth.to_parfait(@clazz)}
|
|
@clazz
|
|
end
|
|
|
|
# We transforms every method (class and object)
|
|
# Other statements are not yet allowed (baring in mind that attribute
|
|
# accessors are transformed to methods in the ruby layer )
|
|
#
|
|
# As there is no class equivalnet in code, a SlotCollection is returned,
|
|
# which is just a list of SlotMachine::MethodCompilers
|
|
# The compilers help to transform the code further, into Risc next
|
|
def to_slot( _ )
|
|
method_compilers = body.statements.collect do |node|
|
|
case node
|
|
when MethodExpression
|
|
node.to_slot(@clazz)
|
|
when ClassMethodExpression
|
|
node.to_slot(@clazz.single_class)
|
|
else
|
|
raise "Only methods for now #{node.class}:#{node}"
|
|
end
|
|
end
|
|
SlotMachine::SlotCollection.new(method_compilers)
|
|
end
|
|
|
|
# goes through the code looking for instance variables and their assignments.
|
|
# Adding each to the respective type, ie class or singleton_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.single_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
|
|
end
|
|
def to_s(depth = 0)
|
|
derive = super_class_name ? "< #{super_class_name}" : ""
|
|
at_depth(depth , "class #{name} #{derive}\n#{@body.to_s(depth + 1)}\nend")
|
|
end
|
|
end
|
|
end
|