Make to_mom a 2 stage process

First baby baby step on the way to passes
Create all parfait objects in first pass, so methods exist to be resolved in second path
This commit is contained in:
2019-09-24 15:44:33 +03:00
parent 3510637d21
commit dd810cfc49
15 changed files with 159 additions and 85 deletions

View File

@ -103,6 +103,7 @@ module RubyX
# return mom for the previously stored vool source.
def to_mom
@vool.to_parfait
@vool.to_mom(nil)
end

View File

@ -7,9 +7,18 @@ module Vool
def self.load_builtin(loads)
clazz , meth = loads.split(".")
"class #{clazz}; #{Vool::Builtin.builtin[loads]};end;"
"class #{clazz} #{derive(clazz)}; #{Vool::Builtin.builtin[loads]};end;"
end
def self.derive(clazz) #must get derived classes rigth, so no mismatch
case clazz
when "Integer"
"< Data4"
when "Word"
" < Data8"
else
""
end
end
def self.builtin
{
"Object.get" => "def get_internal_word(at); X.get_internal_word;end",

View File

@ -6,14 +6,16 @@ module Vool
#
# We store the class name and the parfait class
#
# The Parfait class gets created lazily on the way down to mom, ie the clazz
# attribute will only be set after to_mom, or a direct call to create_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 , @super_class_name = name , supe
@name = name
@super_class_name = supe || :Object
case body
when MethodExpression
@body = Statements.new([body])
@ -26,12 +28,32 @@ module Vool
end
end
# This create the Parfait class, and then transforms every method
# 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 MomCollection is returned,
# which is just a list of Mom::MethodCompilers
# The compilers help to transform the code further, into Risc next
def to_mom( _ )
create_class_object
method_compilers = body.statements.collect do |node|
case node
when MethodExpression
@ -45,24 +67,8 @@ module Vool
Mom::MomCollection.new(method_compilers)
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
# InstanceVariables or InstanceVariable Assignments, to do that.
def create_class_object
@clazz = Parfait.object_space.get_class_by_name(@name )
if(@clazz)
#FIXME super class check with "sup"
#existing class, don't overwrite type (parfait only?)
else
@clazz = Parfait.object_space.create_class(@name , @super_class_name )
end
create_types
@clazz
end
# goes through the code looking for instance variables (and their assignments)
# adding each to the respective type, ie class or singleton_class, depending
# 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)

View File

@ -7,10 +7,19 @@ module Vool
raise "no bod" unless @body
end
# create the parfait VoolMethod to hold the code for this method
#
# Must pass in the actual Parfait class (default nil is just to conform to api)
def to_parfait( clazz = nil )
raise "No class given to class method #{name}" unless clazz
clazz.add_instance_method_for(name , make_arg_type , make_frame , body )
end
def to_mom(clazz)
raise "not singleton" unless clazz.class == Parfait::SingletonClass
raise( "no class in #{self}") unless clazz
method = clazz.add_instance_method_for(name , make_arg_type , make_frame , body )
method = clazz.get_instance_method(name )
raise( "no class method in #{@name} in #{clazz}") unless method
#puts "CLass method Class:#{clazz}:#{name}"
compiler = method.compiler_for(clazz.instance_type)
each {|node| raise "Blocks not implemented" if node.is_a?(LambdaExpression)}

View File

@ -8,20 +8,21 @@ module Vool
raise "Not Vool #{@body}" unless @body.is_a?(Statement)
end
def to_mom(clazz)
raise( "no class in #{self}") unless clazz
method = make_method(clazz)
compiler = method.compiler_for(clazz.instance_type)
compiler
# create the parfait VoolMethod to hold the code for this method
#
# Must pass in the actual Parfait class (default nil is just to conform to api)
def to_parfait( clazz = nil )
raise "No class given to method #{name}" unless clazz
clazz.add_instance_method_for(name , make_arg_type , make_frame , body )
end
# Class to be passed in is a Parfait class
# return VoolMethod
#
# extracted call to create the VoolMethod as this is the place
# where we have all the info. Used in testing.
def make_method(clazz)
clazz.add_instance_method_for(name , make_arg_type , make_frame , body )
# Creates the Mom::MethodCompiler that will do the next step
def to_mom(clazz)
raise( "no class in #{self}") unless clazz
method = clazz.get_instance_method(@name)
raise( "no method in #{@name} in #{clazz.name}") unless method
compiler = method.compiler_for(clazz.instance_type)
compiler
end
def each(&block)

View File

@ -2,17 +2,23 @@
# Object Oriented
# Language
#
# VOOL is the abstraction of ruby, ruby minusthe fluff
# VOOL is the abstraction of ruby: ruby minus the fluff
# fluff is generally what makes ruby nice to use, like 3 ways to achieve the same thing
# if/unless/ternary , reverse ifs (ie statement if condition), reverse whiles,
# implicit blocks, splats and multiple assigns etc
#
# Also, Vool is a typed tree, not abstract, so there is a base class Statement
# and all it's derivation that make up the syntax tree
#
# Also Vool has expression and statements, revealing that age old dichotomy of code and
# Vool has expression and statements, revealing that age old dichotomy of code and
# data. Statements represent code whereas Expressions resolve to data.
# (in ruby there are no pure statements, everthing resolves to data)
#
# Vool resolves to Mom in the next step down. But it also the place where we create
# Parfait representations for the main oo players, ie classes and methods.
# The protocol is thus two stage:
# - first to_parfait with implicit side-effects of creating parfait objects that
# are added to the Parfait object_space
# - second to_mom , which will return a mom version of the statement. This may be code
# or a compiler (for methods), or compiler collection (for classes)
#
module Vool
# Base class for all statements in the tree. Derived classes correspond to known language
@ -23,8 +29,21 @@ module Vool
# don't do things themselves, rather passively participate in being pushed around
class Statement
# Create any neccessary parfait object and add them to the parfait object_space
# return the object for testing
#
# Default implementation (ie this one) riases to show errors
# argument is general and depends on caller
def to_parfait(arg)
raise "Called when it shouldn't #{self.class}"
end
# create mom version of the statement, this is often code, that is added to the
# compiler, but for methods it is a compiler and for classes a collection of those.
#
# The argument given most often is a compiler
# The default implementation (this) is to raise an error
def to_mom( _ )
# temporary warning to find unimplemented kids
raise "Not implemented for #{self}"
end

View File

@ -57,6 +57,10 @@ module Vool
@statements.pop
end
# apply for all statements , return collection (for testing)
def to_parfait
@statements.collect{|s| s.to_parfait}
end
# to_mom all the statements. Append subsequent ones to the first, and return the
# first.
#