start a new ruby layer to do the to_vool conversion
the "normalization" is getting more and more complicated and is not tested And it seems i really don't like working with the untyped ast
This commit is contained in:
parent
f624e38dbb
commit
38350dd198
28
lib/ruby.rb
Normal file
28
lib/ruby.rb
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
require "parser/ruby22"
|
||||||
|
require "ast"
|
||||||
|
|
||||||
|
AST::Node.class_eval do
|
||||||
|
def first
|
||||||
|
children.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require_relative "ruby/statement"
|
||||||
|
require_relative "ruby/statements"
|
||||||
|
require_relative "ruby/array_statement"
|
||||||
|
require_relative "ruby/block_statement"
|
||||||
|
require_relative "ruby/if_statement"
|
||||||
|
require_relative "ruby/normalizer"
|
||||||
|
require_relative "ruby/send_statement"
|
||||||
|
require_relative "ruby/assign_statement"
|
||||||
|
require_relative "ruby/class_statement"
|
||||||
|
require_relative "ruby/logical_statement"
|
||||||
|
require_relative "ruby/return_statement"
|
||||||
|
require_relative "ruby/while_statement"
|
||||||
|
require_relative "ruby/basic_values"
|
||||||
|
require_relative "ruby/hash_statement"
|
||||||
|
require_relative "ruby/method_statement"
|
||||||
|
require_relative "ruby/ruby_compiler"
|
||||||
|
require_relative "ruby/yield_statement"
|
||||||
|
|
||||||
|
require_relative "ruby/ruby_compiler"
|
13
lib/ruby/array_statement.rb
Normal file
13
lib/ruby/array_statement.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module Ruby
|
||||||
|
class ArrayStatement
|
||||||
|
attr_reader :values
|
||||||
|
|
||||||
|
def initialize( values )
|
||||||
|
@values = values
|
||||||
|
end
|
||||||
|
|
||||||
|
def length
|
||||||
|
@values.length
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
53
lib/ruby/assign_statement.rb
Normal file
53
lib/ruby/assign_statement.rb
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
module Ruby
|
||||||
|
|
||||||
|
class Assignment < Statement
|
||||||
|
attr_reader :name , :value
|
||||||
|
def initialize(name , value )
|
||||||
|
@name , @value = name , value
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize()
|
||||||
|
raise "not named left #{name.class}" unless name.is_a?(Symbol)
|
||||||
|
case value
|
||||||
|
when Named , Constant
|
||||||
|
return copy
|
||||||
|
when SendStatement
|
||||||
|
return normalize_send
|
||||||
|
else
|
||||||
|
raise "unsupported right #{value}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def copy(value = nil)
|
||||||
|
value ||= @value
|
||||||
|
self.class.new(name,value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_send
|
||||||
|
statements = value.normalize()
|
||||||
|
return copy( statements ) if statements.is_a?(SendStatement)
|
||||||
|
assign = statements.statements.pop
|
||||||
|
statements << copy(assign)
|
||||||
|
statements
|
||||||
|
end
|
||||||
|
|
||||||
|
def chain_assign(assign , compiler)
|
||||||
|
return assign unless @value.is_a?(SendStatement)
|
||||||
|
@value.to_mom(compiler) << assign
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(depth = 0)
|
||||||
|
at_depth(depth , "#{@name} = #{@value}")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class IvarAssignment < Assignment
|
||||||
|
|
||||||
|
def normalize()
|
||||||
|
super()
|
||||||
|
return IvarAssignment.new(@name , @value)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
108
lib/ruby/basic_values.rb
Normal file
108
lib/ruby/basic_values.rb
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
module Ruby
|
||||||
|
class Constant < Expression
|
||||||
|
#gobble it up
|
||||||
|
def each(&block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class IntegerConstant < Constant
|
||||||
|
attr_reader :value
|
||||||
|
def initialize(value)
|
||||||
|
@value = value
|
||||||
|
end
|
||||||
|
def slot_definition(compiler)
|
||||||
|
return Mom::SlotDefinition.new(Mom::IntegerConstant.new(@value) , [])
|
||||||
|
end
|
||||||
|
def ct_type
|
||||||
|
Parfait.object_space.get_type_by_class_name(:Integer)
|
||||||
|
end
|
||||||
|
def to_s
|
||||||
|
value.to_s
|
||||||
|
end
|
||||||
|
def each(&block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class FloatConstant < Constant
|
||||||
|
attr_reader :value
|
||||||
|
def initialize(value)
|
||||||
|
@value = value
|
||||||
|
end
|
||||||
|
def ct_type
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class TrueConstant < Constant
|
||||||
|
def ct_type
|
||||||
|
Parfait.object_space.get_type_by_class_name(:True)
|
||||||
|
end
|
||||||
|
def slot_definition(compiler)
|
||||||
|
return Mom::SlotDefinition.new(Parfait.object_space.true_object , [])
|
||||||
|
end
|
||||||
|
def to_s(depth = 0)
|
||||||
|
"true"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class FalseConstant < Constant
|
||||||
|
def ct_type
|
||||||
|
Parfait.object_space.get_type_by_class_name(:False)
|
||||||
|
end
|
||||||
|
def slot_definition(compiler)
|
||||||
|
return Mom::SlotDefinition.new(Parfait.object_space.false_object , [])
|
||||||
|
end
|
||||||
|
def to_s(depth = 0)
|
||||||
|
"false"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class NilConstant < Constant
|
||||||
|
def ct_type
|
||||||
|
Parfait.object_space.get_type_by_class_name(:Nil)
|
||||||
|
end
|
||||||
|
def slot_definition(compiler)
|
||||||
|
return Mom::SlotDefinition.new(Parfait.object_space.nil_object , [])
|
||||||
|
end
|
||||||
|
def to_s(depth = 0)
|
||||||
|
"nil"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class SelfExpression < Expression
|
||||||
|
attr_reader :my_type
|
||||||
|
def initialize(type = nil)
|
||||||
|
@my_type = type
|
||||||
|
end
|
||||||
|
def slot_definition(compiler)
|
||||||
|
@my_type = compiler.receiver_type
|
||||||
|
Mom::SlotDefinition.new(:message , [:receiver])
|
||||||
|
end
|
||||||
|
def ct_type
|
||||||
|
@my_type
|
||||||
|
end
|
||||||
|
def to_s(depth = 0)
|
||||||
|
"self"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class SuperExpression < Statement
|
||||||
|
def to_s(depth = 0)
|
||||||
|
"super"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class StringConstant < Constant
|
||||||
|
attr_reader :value
|
||||||
|
def initialize(value)
|
||||||
|
@value = value
|
||||||
|
end
|
||||||
|
def slot_definition(compiler)
|
||||||
|
return Mom::SlotDefinition.new(Mom::StringConstant.new(@value),[])
|
||||||
|
end
|
||||||
|
def ct_type
|
||||||
|
Parfait.object_space.get_type_by_class_name(:Word)
|
||||||
|
end
|
||||||
|
def to_s(depth = 0)
|
||||||
|
"'#{@value}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class SymbolConstant < StringConstant
|
||||||
|
def ct_type
|
||||||
|
Parfait.object_space.get_type_by_class_name(:Word)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
lib/ruby/block_statement.rb
Normal file
17
lib/ruby/block_statement.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
module Vool
|
||||||
|
|
||||||
|
class BlockStatement < Statement
|
||||||
|
attr_reader :args , :body , :clazz
|
||||||
|
|
||||||
|
def initialize( args , body , something_really_else)
|
||||||
|
@args , @body = args , body
|
||||||
|
raise "no bod" unless @body
|
||||||
|
@clazz = clazz
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
BlockStatement.new( @args , @body.normalize)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
28
lib/ruby/class_statement.rb
Normal file
28
lib/ruby/class_statement.rb
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
module Ruby
|
||||||
|
class ClassStatement < Statement
|
||||||
|
attr_reader :name, :super_class_name , :body
|
||||||
|
|
||||||
|
def initialize( name , supe , body)
|
||||||
|
@name , @super_class_name = name , supe
|
||||||
|
case body
|
||||||
|
when MethodStatement
|
||||||
|
@body = Statements.new([body])
|
||||||
|
when Statements
|
||||||
|
@body = body
|
||||||
|
when nil
|
||||||
|
@body = Statements.new([])
|
||||||
|
else
|
||||||
|
raise "what body #{body}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
meths = body.statements.collect{|meth| meth.normalize}
|
||||||
|
ClassStatement.new(@name , @super_class_name, Statements.new(meths) )
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(depth = 0)
|
||||||
|
at_depth(depth , "class #{name}" , @body.to_s(depth + 1) , "end")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
lib/ruby/hash_statement.rb
Normal file
17
lib/ruby/hash_statement.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
module Ruby
|
||||||
|
class HashStatement
|
||||||
|
attr_reader :hash
|
||||||
|
|
||||||
|
def initialize( )
|
||||||
|
@hash = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def add(key , value)
|
||||||
|
@hash[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def length
|
||||||
|
@hash.length
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
39
lib/ruby/if_statement.rb
Normal file
39
lib/ruby/if_statement.rb
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
require_relative "normalizer"
|
||||||
|
|
||||||
|
module Ruby
|
||||||
|
class IfStatement < Statement
|
||||||
|
include Normalizer
|
||||||
|
|
||||||
|
attr_reader :condition , :if_true , :if_false
|
||||||
|
|
||||||
|
def initialize( cond , if_true , if_false = nil)
|
||||||
|
@condition = cond
|
||||||
|
@if_true = if_true
|
||||||
|
@if_false = if_false
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
cond , rest = *normalize_name(@condition)
|
||||||
|
fals = @if_false ? @if_false.normalize : nil
|
||||||
|
me = IfStatement.new(cond , @if_true.normalize, fals)
|
||||||
|
return me unless rest
|
||||||
|
rest << me
|
||||||
|
rest
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_false?
|
||||||
|
@if_false != nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_true?
|
||||||
|
@if_true != nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(depth = 0)
|
||||||
|
parts = ["if (#{@condition})" , @body.to_s(depth + 1) ]
|
||||||
|
parts += ["else" , "@if_false.to_s(depth + 1)"] if(@false)
|
||||||
|
parts << "end"
|
||||||
|
at_depth(depth , *parts )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
16
lib/ruby/logical_statement.rb
Normal file
16
lib/ruby/logical_statement.rb
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
module Ruby
|
||||||
|
# Logical Statements are guaranteed to return boolean
|
||||||
|
# either :and or :or, which may be written as && and ||
|
||||||
|
class LogicalStatement < Statement
|
||||||
|
attr_reader :name , :left , :right
|
||||||
|
|
||||||
|
def initialize(name , left , right)
|
||||||
|
@name , @left , @right = name , left , right
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(depth = 0)
|
||||||
|
at_depth(depth , "#{left} #{name} #{right}")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
27
lib/ruby/method_statement.rb
Normal file
27
lib/ruby/method_statement.rb
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
module Ruby
|
||||||
|
class MethodStatement < Statement
|
||||||
|
attr_reader :name, :args , :body , :clazz
|
||||||
|
|
||||||
|
def initialize( name , args , body , clazz = nil)
|
||||||
|
@name , @args , @body = name , args , body
|
||||||
|
raise "no bod" unless @body
|
||||||
|
@clazz = clazz
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
MethodStatement.new( @name , @args , @body.normalize)
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_yield?
|
||||||
|
each{|statement| return true if statement.is_a?(YieldStatement)}
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(depth = 0)
|
||||||
|
arg_str = @args.collect{|a| a.to_s}.join(', ')
|
||||||
|
at_depth(depth , "def #{name}(#{arg_str})" , @body.to_s(depth + 1) , "end")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
22
lib/ruby/normalizer.rb
Normal file
22
lib/ruby/normalizer.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
module Ruby
|
||||||
|
module Normalizer
|
||||||
|
# given a something, determine if it is a Name
|
||||||
|
#
|
||||||
|
# Return a Name, and a possible rest that has a hoisted part of the statement
|
||||||
|
#
|
||||||
|
# eg if( @var % 5) is not normalized
|
||||||
|
# but if(tmp_123) is with tmp_123 = @var % 5 hoisted above the if
|
||||||
|
#
|
||||||
|
# also constants count, though they may not be so useful in ifs, but returns
|
||||||
|
def normalize_name( condition )
|
||||||
|
if( condition.is_a?(ScopeStatement) and condition.single?)
|
||||||
|
condition = condition.first
|
||||||
|
end
|
||||||
|
return [condition] if condition.is_a?(Named) or condition.is_a?(Constant)
|
||||||
|
condition = condition.normalize
|
||||||
|
local = "tmp_#{object_id}".to_sym
|
||||||
|
assign = Statements.new [LocalAssignment.new( local , condition)]
|
||||||
|
[LocalVariable.new(local) , assign]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
23
lib/ruby/return_statement.rb
Normal file
23
lib/ruby/return_statement.rb
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module Ruby
|
||||||
|
class ReturnStatement < Statement
|
||||||
|
include Normalizer
|
||||||
|
|
||||||
|
attr_reader :return_value
|
||||||
|
|
||||||
|
def initialize(value)
|
||||||
|
@return_value = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
val , rest = *normalize_name(@return_value)
|
||||||
|
me = ReturnStatement.new(val)
|
||||||
|
return me unless rest
|
||||||
|
rest << me
|
||||||
|
rest
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(depth = 0)
|
||||||
|
at_depth(depth , "return #{@return_value.to_s}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,12 +1,13 @@
|
|||||||
|
module Ruby
|
||||||
module RubyX
|
# This RubyCompiler compiles incoming ruby (string) into a typed
|
||||||
# This RubyCompiler compiles incoming ruby (string) into vools internal representation
|
# version of theast, with the help of the parser gem.
|
||||||
# with the help of the parser gem. The parser outputs an abstract ast (nodes)
|
# The parser outputs an abstract ast (nodes)
|
||||||
# that get transformed into concrete, specific classes.
|
# that get transformed into concrete, specific classes.
|
||||||
#
|
#
|
||||||
# As a second step, it extracts classes, methods, ivars and locals.
|
# As a second step, it extracts classes, methods, ivars and locals.
|
||||||
#
|
#
|
||||||
# The next step is then to normalize the code and then finally to compile
|
# The next step is then to go to the vool level, which is
|
||||||
|
# simpler, and then finally to compile
|
||||||
# to the next level down, MOM (Minimal Object Machine)
|
# to the next level down, MOM (Minimal Object Machine)
|
||||||
class RubyCompiler < AST::Processor
|
class RubyCompiler < AST::Processor
|
||||||
include AST::Sexp
|
include AST::Sexp
|
||||||
@ -23,13 +24,13 @@ module RubyX
|
|||||||
|
|
||||||
def on_class( statement )
|
def on_class( statement )
|
||||||
name , sup , body = *statement
|
name , sup , body = *statement
|
||||||
Vool::ClassStatement.new( get_name(name) , get_name(sup) , process(body) )
|
ClassStatement.new( get_name(name) , get_name(sup) , process(body) )
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_def( statement )
|
def on_def( statement )
|
||||||
name , args , body = *statement
|
name , args , body = *statement
|
||||||
arg_array = process_all( args )
|
arg_array = process_all( args )
|
||||||
Vool::MethodStatement.new( name , arg_array , process(body) )
|
MethodStatement.new( name , arg_array , process(body) )
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_arg( arg )
|
def on_arg( arg )
|
||||||
@ -40,13 +41,13 @@ module RubyX
|
|||||||
sendd = process(block_node.children[0])
|
sendd = process(block_node.children[0])
|
||||||
args = process(block_node.children[1])
|
args = process(block_node.children[1])
|
||||||
body = process(block_node.children[2])
|
body = process(block_node.children[2])
|
||||||
sendd.add_block Vool::BlockStatement.new(args , body)
|
sendd.add_block BlockStatement.new(args , body)
|
||||||
sendd
|
sendd
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_yield(node)
|
def on_yield(node)
|
||||||
args = process_all(node.children)
|
args = process_all(node.children)
|
||||||
Vool::YieldStatement.new(args)
|
YieldStatement.new(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_args(args)
|
def on_args(args)
|
||||||
@ -55,31 +56,31 @@ module RubyX
|
|||||||
|
|
||||||
#basic Values
|
#basic Values
|
||||||
def on_self exp
|
def on_self exp
|
||||||
Vool::SelfExpression.new
|
SelfExpression.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_nil expression
|
def on_nil expression
|
||||||
Vool::NilConstant.new
|
NilConstant.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_int expression
|
def on_int expression
|
||||||
Vool::IntegerConstant.new(expression.children.first)
|
IntegerConstant.new(expression.children.first)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_float expression
|
def on_float expression
|
||||||
Vool::FloatConstant.new(expression.children.first)
|
FloatConstant.new(expression.children.first)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_true expression
|
def on_true expression
|
||||||
Vool::TrueConstant.new
|
TrueConstant.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_false expression
|
def on_false expression
|
||||||
Vool::FalseConstant.new
|
FalseConstant.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_str expression
|
def on_str expression
|
||||||
Vool::StringConstant.new(expression.children.first)
|
StringConstant.new(expression.children.first)
|
||||||
end
|
end
|
||||||
alias :on_string :on_str
|
alias :on_string :on_str
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ module RubyX
|
|||||||
alias :on_xstr :on_dstr
|
alias :on_xstr :on_dstr
|
||||||
|
|
||||||
def on_sym expression
|
def on_sym expression
|
||||||
Vool::SymbolConstant.new(expression.children.first)
|
SymbolConstant.new(expression.children.first)
|
||||||
end
|
end
|
||||||
alias :on_string :on_str
|
alias :on_string :on_str
|
||||||
|
|
||||||
@ -97,17 +98,17 @@ module RubyX
|
|||||||
raise "Not implemented dynamix symbols (with interpolation)"
|
raise "Not implemented dynamix symbols (with interpolation)"
|
||||||
end
|
end
|
||||||
def on_kwbegin statement
|
def on_kwbegin statement
|
||||||
Vool::ScopeStatement.new process_all( statement.children )
|
ScopeStatement.new process_all( statement.children )
|
||||||
end
|
end
|
||||||
alias :on_begin :on_kwbegin
|
alias :on_begin :on_kwbegin
|
||||||
|
|
||||||
# Array + Hashes
|
# Array + Hashes
|
||||||
def on_array expression
|
def on_array expression
|
||||||
Vool::ArrayStatement.new expression.children.collect{ |elem| process(elem) }
|
ArrayStatement.new expression.children.collect{ |elem| process(elem) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_hash expression
|
def on_hash expression
|
||||||
hash = Vool::HashStatement.new
|
hash = HashStatement.new
|
||||||
expression.children.each do |elem|
|
expression.children.each do |elem|
|
||||||
raise "Hash error, hash contains non pair: #{elem.type}" if elem.type != :pair
|
raise "Hash error, hash contains non pair: #{elem.type}" if elem.type != :pair
|
||||||
hash.add( process(elem.children[0]) , process(elem.children[1]) )
|
hash.add( process(elem.children[0]) , process(elem.children[1]) )
|
||||||
@ -117,15 +118,15 @@ module RubyX
|
|||||||
|
|
||||||
#Variables
|
#Variables
|
||||||
def on_lvar expression
|
def on_lvar expression
|
||||||
Vool::LocalVariable.new(expression.children.first)
|
LocalVariable.new(expression.children.first)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_ivar expression
|
def on_ivar expression
|
||||||
Vool::InstanceVariable.new(instance_name(expression.children.first))
|
InstanceVariable.new(instance_name(expression.children.first))
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_cvar expression
|
def on_cvar expression
|
||||||
Vool::ClassVariable.new(expression.children.first.to_s[2 .. -1].to_sym)
|
ClassVariable.new(expression.children.first.to_s[2 .. -1].to_sym)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_const expression
|
def on_const expression
|
||||||
@ -133,20 +134,20 @@ module RubyX
|
|||||||
if scope
|
if scope
|
||||||
raise "Only unscoped Names implemented #{scope}" unless scope.type == :cbase
|
raise "Only unscoped Names implemented #{scope}" unless scope.type == :cbase
|
||||||
end
|
end
|
||||||
Vool::ModuleName.new(expression.children[1])
|
ModuleName.new(expression.children[1])
|
||||||
end
|
end
|
||||||
|
|
||||||
# Assignements
|
# Assignements
|
||||||
def on_lvasgn expression
|
def on_lvasgn expression
|
||||||
name = expression.children[0]
|
name = expression.children[0]
|
||||||
value = process(expression.children[1])
|
value = process(expression.children[1])
|
||||||
Vool::LocalAssignment.new(name,value)
|
LocalAssignment.new(name,value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_ivasgn expression
|
def on_ivasgn expression
|
||||||
name = expression.children[0]
|
name = expression.children[0]
|
||||||
value = process(expression.children[1])
|
value = process(expression.children[1])
|
||||||
Vool::IvarAssignment.new(instance_name(name),value)
|
IvarAssignment.new(instance_name(name),value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_op_asgn(expression)
|
def on_op_asgn(expression)
|
||||||
@ -161,52 +162,52 @@ module RubyX
|
|||||||
|
|
||||||
def on_return statement
|
def on_return statement
|
||||||
return_value = process(statement.children.first)
|
return_value = process(statement.children.first)
|
||||||
Vool::ReturnStatement.new( return_value )
|
ReturnStatement.new( return_value )
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_while statement
|
def on_while statement
|
||||||
condition , statements = *statement
|
condition , statements = *statement
|
||||||
Vool::WhileStatement.new( process(condition) , process(statements))
|
WhileStatement.new( process(condition) , process(statements))
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_if statement
|
def on_if statement
|
||||||
condition , if_true , if_false = *statement
|
condition , if_true , if_false = *statement
|
||||||
if_true = process(if_true)
|
if_true = process(if_true)
|
||||||
if_false = process(if_false)
|
if_false = process(if_false)
|
||||||
Vool::IfStatement.new( process(condition) , if_true , if_false )
|
IfStatement.new( process(condition) , if_true , if_false )
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_send statement
|
def on_send statement
|
||||||
kids = statement.children.dup
|
kids = statement.children.dup
|
||||||
receiver = process(kids.shift) || Vool::SelfExpression.new
|
receiver = process(kids.shift) || SelfExpression.new
|
||||||
name = kids.shift
|
name = kids.shift
|
||||||
arguments = process_all(kids)
|
arguments = process_all(kids)
|
||||||
Vool::SendStatement.new( name , receiver , arguments )
|
SendStatement.new( name , receiver , arguments )
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_and expression
|
def on_and expression
|
||||||
name = expression.type
|
name = expression.type
|
||||||
left = process(expression.children[0])
|
left = process(expression.children[0])
|
||||||
right = process( expression.children[1] )
|
right = process( expression.children[1] )
|
||||||
Vool::LogicalStatement.new( name , left , right)
|
LogicalStatement.new( name , left , right)
|
||||||
end
|
end
|
||||||
alias :on_or :on_and
|
alias :on_or :on_and
|
||||||
|
|
||||||
# this is a call to super without args (z = zero arity)
|
# this is a call to super without args (z = zero arity)
|
||||||
def on_zsuper exp
|
def on_zsuper exp
|
||||||
Vool::SendStatement.new( nil , Vool::SuperExpression.new , nil)
|
SendStatement.new( nil , SuperExpression.new , nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
# this is a call to super with args and
|
# this is a call to super with args and
|
||||||
# same name as current method, which is set later
|
# same name as current method, which is set later
|
||||||
def on_super( statement )
|
def on_super( statement )
|
||||||
arguments = process_all(statement.children)
|
arguments = process_all(statement.children)
|
||||||
Vool::SendStatement.new( nil , Vool::SuperExpression.new , arguments)
|
SendStatement.new( nil , SuperExpression.new , arguments)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_assignment statement
|
def on_assignment statement
|
||||||
name , value = *statement
|
name , value = *statement
|
||||||
w = Vool::Assignment.new()
|
w = Assignment.new()
|
||||||
w.name = process name
|
w.name = process name
|
||||||
w.value = process(value)
|
w.value = process(value)
|
||||||
w
|
w
|
39
lib/ruby/send_statement.rb
Normal file
39
lib/ruby/send_statement.rb
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
module Ruby
|
||||||
|
|
||||||
|
class SendStatement < Statement
|
||||||
|
attr_reader :name , :receiver , :arguments
|
||||||
|
|
||||||
|
def initialize(name , receiver , arguments )
|
||||||
|
@name , @receiver , @arguments = name , receiver , arguments
|
||||||
|
@arguments ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
statements = Statements.new([])
|
||||||
|
arguments = []
|
||||||
|
@arguments.each_with_index do |arg , index |
|
||||||
|
normalize_arg(arg , arguments , statements)
|
||||||
|
end
|
||||||
|
if statements.empty?
|
||||||
|
return SendStatement.new(@name, @receiver , @arguments)
|
||||||
|
else
|
||||||
|
statements << SendStatement.new(@name, @receiver , arguments)
|
||||||
|
return statements
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_arg(arg , arguments , statements)
|
||||||
|
if arg.respond_to?(:slot_definition) and !arg.is_a?(SendStatement)
|
||||||
|
arguments << arg
|
||||||
|
return
|
||||||
|
end
|
||||||
|
assign = LocalAssignment.new( "tmp_#{arg.object_id}".to_sym, arg)
|
||||||
|
statements << assign
|
||||||
|
arguments << LocalVariable.new(assign.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"#{receiver}.#{name}(#{arguments.join(', ')})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
25
lib/ruby/statement.rb
Normal file
25
lib/ruby/statement.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module Ruby
|
||||||
|
|
||||||
|
# Base class for all statements in the tree. Derived classes correspond to known language
|
||||||
|
# constructs
|
||||||
|
#
|
||||||
|
# Compilers or compiler passes are written by implementing methods.
|
||||||
|
#
|
||||||
|
class Statement
|
||||||
|
|
||||||
|
def at_depth(depth , *strings)
|
||||||
|
prefix = " " * 2 * depth
|
||||||
|
strings.collect{|str| prefix + str}.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class Expression
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
raise "should not be normalized #{self}"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
55
lib/ruby/statements.rb
Normal file
55
lib/ruby/statements.rb
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
module Ruby
|
||||||
|
class Statements < Statement
|
||||||
|
attr_reader :statements
|
||||||
|
def initialize(statements)
|
||||||
|
@statements = statements
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty?
|
||||||
|
@statements.empty?
|
||||||
|
end
|
||||||
|
def single?
|
||||||
|
@statements.length == 1
|
||||||
|
end
|
||||||
|
def first
|
||||||
|
@statements.first
|
||||||
|
end
|
||||||
|
def last
|
||||||
|
@statements.last
|
||||||
|
end
|
||||||
|
def length
|
||||||
|
@statements.length
|
||||||
|
end
|
||||||
|
def [](i)
|
||||||
|
@statements[i]
|
||||||
|
end
|
||||||
|
def <<(o)
|
||||||
|
@statements << o
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
# create mom instructions
|
||||||
|
def to_mom( compiler )
|
||||||
|
raise "Empty list ? #{statements.length}" if empty?
|
||||||
|
stats = @statements.dup
|
||||||
|
flat = stats.shift.to_mom(compiler)
|
||||||
|
while( nekst = stats.shift )
|
||||||
|
flat.append nekst.to_mom(compiler)
|
||||||
|
end
|
||||||
|
flat
|
||||||
|
end
|
||||||
|
|
||||||
|
def each(&block)
|
||||||
|
block.call(self)
|
||||||
|
@statements.each{|a| a.each(&block)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(depth = 0)
|
||||||
|
at_depth(depth , *@statements.collect{|st| st.to_s(depth)})
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class ScopeStatement < Statements
|
||||||
|
end
|
||||||
|
end
|
24
lib/ruby/while_statement.rb
Normal file
24
lib/ruby/while_statement.rb
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
require_relative "normalizer"
|
||||||
|
|
||||||
|
module Ruby
|
||||||
|
class WhileStatement < Statement
|
||||||
|
include Normalizer
|
||||||
|
attr_reader :condition , :body , :hoisted
|
||||||
|
|
||||||
|
def initialize( condition , body , hoisted = nil)
|
||||||
|
@hoisted = hoisted
|
||||||
|
@condition = condition
|
||||||
|
@body = body
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
cond , rest = *normalize_name(@condition)
|
||||||
|
WhileStatement.new(cond , @body.normalize , rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(depth = 0)
|
||||||
|
at_depth(depth , "while (#{@condition})" , @body.to_s(depth + 1) , "end" )
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
39
lib/ruby/yield_statement.rb
Normal file
39
lib/ruby/yield_statement.rb
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
module Ruby
|
||||||
|
|
||||||
|
class YieldStatement < Statement
|
||||||
|
attr_reader :arguments
|
||||||
|
|
||||||
|
def initialize(arguments )
|
||||||
|
@arguments = arguments
|
||||||
|
@arguments ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
statements = Statements.new([])
|
||||||
|
arguments = []
|
||||||
|
@arguments.each_with_index do |arg , index |
|
||||||
|
normalize_arg(arg , arguments , statements)
|
||||||
|
end
|
||||||
|
if statements.empty?
|
||||||
|
return YieldStatement.new(@name, @receiver , @arguments)
|
||||||
|
else
|
||||||
|
statements << YieldStatement.new(@name, @receiver , arguments)
|
||||||
|
return statements
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_arg(arg , arguments , statements)
|
||||||
|
if arg.respond_to?(:slot_definition) and !arg.is_a?(YieldStatement)
|
||||||
|
arguments << arg
|
||||||
|
return
|
||||||
|
end
|
||||||
|
assign = LocalAssignment.new( "tmp_#{arg.object_id}".to_sym, arg)
|
||||||
|
statements << assign
|
||||||
|
arguments << LocalVariable.new(assign.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"#{receiver}.#{name}(#{arguments.join(', ')})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
test/ruby/helper.rb
Normal file
17
test/ruby/helper.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
require_relative "../helper"
|
||||||
|
|
||||||
|
module Ruby
|
||||||
|
module RubyTests
|
||||||
|
def setup
|
||||||
|
Parfait.boot!
|
||||||
|
end
|
||||||
|
def compile(input)
|
||||||
|
RubyCompiler.compile(input)
|
||||||
|
end
|
||||||
|
|
||||||
|
def ruby_to_vool(input)
|
||||||
|
RubyXCompiler.new(input).ruby_to_vool
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestArrayX < MiniTest::Test
|
class TestArrayX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestBasicValuesX < MiniTest::Test
|
class TestBasicValuesX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestBlockStatementX < MiniTest::Test
|
class TestBlockStatementX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestEmptyClassStatementX < MiniTest::Test
|
class TestEmptyClassStatementX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class HashArrayX < MiniTest::Test
|
class HashArrayX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative 'helper'
|
require_relative 'helper'
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestIfStatementX < MiniTest::Test
|
class TestIfStatementX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestIvarAssignmentX < MiniTest::Test
|
class TestIvarAssignmentX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestLocalAssignmentX < MiniTest::Test
|
class TestLocalAssignmentX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestLogicalX < MiniTest::Test
|
class TestLogicalX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestMethodStatementX < MiniTest::Test
|
class TestMethodStatementX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
module OpAss
|
module OpAss
|
||||||
def test_local_name
|
def test_local_name
|
||||||
assert_equal :foo , @lst.name
|
assert_equal :foo , @lst.name
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestReturnStatementX < MiniTest::Test
|
class TestReturnStatementX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestSendX < MiniTest::Test
|
class TestSendX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestVariablesX < MiniTest::Test
|
class TestVariablesX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative 'helper'
|
require_relative 'helper'
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestWhileStatementX < MiniTest::Test
|
class TestWhileStatementX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Vool
|
module Ruby
|
||||||
class TestYieldStatementX < MiniTest::Test
|
class TestYieldStatementX < MiniTest::Test
|
||||||
include RubyTests
|
include RubyTests
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
require_relative "../../helper"
|
|
||||||
|
|
||||||
module Vool
|
|
||||||
module RubyTests
|
|
||||||
def compile(input)
|
|
||||||
RubyX::RubyCompiler.compile(input)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
x
Reference in New Issue
Block a user