create rubyx dir and move previous vool_compiler there

This commit is contained in:
Torsten Ruger
2018-06-29 22:46:39 +03:00
parent 63dd6d9039
commit c8451d0048
32 changed files with 363 additions and 156 deletions

93
lib/vool/basic_values.rb Normal file
View File

@ -0,0 +1,93 @@
module Vool
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(method)
return Mom::SlotDefinition.new(Mom::IntegerConstant.new(@value) , [])
end
def ct_type
Parfait.object_space.get_class_by_name(:Integer).instance_type
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_class_by_name(:True).instance_type
end
def slot_definition(method)
return Mom::SlotDefinition.new(Parfait.object_space.true_object , [])
end
end
class FalseConstant < Constant
def ct_type
Parfait.object_space.get_class_by_name(:False).instance_type
end
def slot_definition(method)
return Mom::SlotDefinition.new(Parfait.object_space.false_object , [])
end
end
class NilConstant < Constant
def ct_type
Parfait.object_space.get_class_by_name(:Nil).instance_type
end
def slot_definition(method)
return Mom::SlotDefinition.new(Parfait.object_space.nil_object , [])
end
end
class SelfExpression < Expression
attr_reader :my_type
def initialize(type = nil)
@my_type = type
end
def slot_definition(in_method)
@my_type = in_method.for_type
Mom::SlotDefinition.new(:message , [:receiver])
end
def ct_type
@my_type
end
def to_s
"self"
end
end
class SuperExpression < Statement
end
class StringConstant < Constant
attr_reader :value
def initialize(value)
@value = value
end
def slot_definition(method)
return Mom::SlotDefinition.new(Mom::StringConstant.new(@value),[])
end
def ct_type
Parfait.object_space.get_class_by_name(:Word).instance_type
end
end
class SymbolConstant < StringConstant
def ct_type
Parfait.object_space.get_class_by_name(:Word).instance_type
end
end
end

View File

@ -0,0 +1,17 @@
module Vool
class LocalAssignment < Assignment
def to_mom( method )
if method.arguments_type.variable_index(@name)
type = :arguments
else
type = :frame
end
to = Mom::SlotDefinition.new(:message ,[ type , @name])
from = @value.slot_definition(method)
return chain_assign( Mom::SlotLoad.new(to,from) , method)
end
end
end

22
lib/vool/normalizer.rb Normal file
View File

@ -0,0 +1,22 @@
module Vool
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

View File

@ -1,235 +0,0 @@
require_relative "statement"
module Vool
# This RubyCompiler compiles incoming ruby (string) into vools internal representation
# with the help of the parser gem. The parser outputs an abstract ast (nodes)
# that get transformed into concrete, specific classes.
#
# 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
# to the next level down, MOM (Minimal Object Machine)
class RubyCompiler < AST::Processor
include AST::Sexp
def self.compile(input)
ast = Parser::Ruby22.parse( input )
self.new.process(ast)
end
# default to error, so non implemented stuff shows early
def handler_missing(node)
raise "Not implemented #{node.type} #{node}"
end
def on_class( statement )
name , sup , body = *statement
ClassStatement.new( get_name(name) , get_name(sup) , process(body) )
end
def on_def( statement )
name , args , body = *statement
arg_array = process_all( args )
MethodStatement.new( name , arg_array , process(body) )
end
def on_arg( arg )
arg.first
end
def on_block(block_node)
sendd = process(block_node.children[0])
args = process(block_node.children[1])
body = process(block_node.children[2])
sendd.add_block BlockStatement.new(args , body)
sendd
end
def on_yield(node)
args = process_all(node.children)
YieldStatement.new(args)
end
def on_args(args)
args.children.collect{|a| process(a)}
end
#basic Values
def on_self exp
SelfExpression.new
end
def on_nil expression
NilConstant.new
end
def on_int expression
IntegerConstant.new(expression.children.first)
end
def on_float expression
FloatConstant.new(expression.children.first)
end
def on_true expression
TrueConstant.new
end
def on_false expression
FalseConstant.new
end
def on_str expression
StringConstant.new(expression.children.first)
end
alias :on_string :on_str
def on_dstr expression
raise "Not implemented dynamic strings (with interpolation)"
end
alias :on_xstr :on_dstr
def on_sym expression
SymbolConstant.new(expression.children.first)
end
alias :on_string :on_str
def on_dsym
raise "Not implemented dynamix symbols (with interpolation)"
end
def on_kwbegin statement
ScopeStatement.new process_all( statement.children )
end
alias :on_begin :on_kwbegin
# Array + Hashes
def on_array expression
ArrayStatement.new expression.children.collect{ |elem| process(elem) }
end
def on_hash expression
hash = HashStatement.new
expression.children.each do |elem|
raise "Hash error, hash contains non pair: #{elem.type}" if elem.type != :pair
hash.add( process(elem.children[0]) , process(elem.children[1]) )
end
hash
end
#Variables
def on_lvar expression
LocalVariable.new(expression.children.first)
end
def on_ivar expression
InstanceVariable.new(instance_name(expression.children.first))
end
def on_cvar expression
ClassVariable.new(expression.children.first.to_s[2 .. -1].to_sym)
end
def on_const expression
scope = expression.children.first
if scope
raise "Only unscoped Names implemented #{scope}" unless scope.type == :cbase
end
ModuleName.new(expression.children[1])
end
# Assignements
def on_lvasgn expression
name = expression.children[0]
value = process(expression.children[1])
LocalAssignment.new(name,value)
end
def on_ivasgn expression
name = expression.children[0]
value = process(expression.children[1])
IvarAssignment.new(instance_name(name),value)
end
def on_op_asgn(expression)
ass , op , exp = *expression
name = ass.children[0]
a_type = ass.type.to_s[0,3]
rewrite = s( a_type + "sgn" ,
name ,
s(:send , s( a_type + "r" , name ) , op , exp ) )
process(rewrite)
end
def on_return statement
return_value = process(statement.children.first)
ReturnStatement.new( return_value )
end
def on_while statement
condition , statements = *statement
WhileStatement.new( process(condition) , process(statements))
end
def on_if statement
condition , if_true , if_false = *statement
if_true = process(if_true)
if_false = process(if_false)
IfStatement.new( process(condition) , if_true , if_false )
end
def on_send statement
kids = statement.children.dup
receiver = process(kids.shift) || SelfExpression.new
name = kids.shift
arguments = process_all(kids)
SendStatement.new( name , receiver , arguments )
end
def on_and expression
name = expression.type
left = process(expression.children[0])
right = process( expression.children[1] )
LogicalStatement.new( name , left , right)
end
alias :on_or :on_and
# this is a call to super without args (z = zero arity)
def on_zsuper exp
SendStatement.new( nil , SuperExpression.new , nil)
end
# this is a call to super with args and
# same name as current method, which is set later
def on_super( statement )
arguments = process_all(statement.children)
SendStatement.new( nil , SuperExpression.new , arguments)
end
def on_assignment statement
name , value = *statement
w = Assignment.new()
w.name = process name
w.value = process(value)
w
end
def handler_missing(node)
raise "Handler missing #{node}"
end
private
def instance_name sym
sym.to_s[1 .. -1].to_sym
end
def get_name( statement )
return nil unless statement
raise "Not const #{statement}" unless statement.type == :const
name = statement.children[1]
raise "Not symbol #{name}" unless name.is_a? Symbol
name
end
end
end

41
lib/vool/variables.rb Normal file
View File

@ -0,0 +1,41 @@
module Vool
module Named
attr_reader :name
def initialize name
@name = name
end
def each(&block)
end
end
class LocalVariable < Expression
include Named
def slot_definition(method)
if method.arguments_type.variable_index(@name)
type = :arguments
else
type = :frame
end
Mom::SlotDefinition.new(:message , [type , @name])
end
end
class InstanceVariable < Expression
include Named
def slot_definition(method)
Mom::SlotDefinition.new(:message , [ :receiver , @name] )
end
# used to collect type information
def add_ivar( array )
array << @name
end
end
class ClassVariable < Expression
include Named
end
class ModuleName < Expression
include Named
end
end

View File

@ -1,21 +0,0 @@
require_relative "ruby_compiler"
module Vool
class VoolCompiler
def self.ruby_to_vool( ruby_source )
vool = RubyCompiler.compile( ruby_source )
vool = vool.normalize
vool
end
def self.ruby_to_binary(source , platform = :arm)
machine = Risc.machine.boot
vool = self.ruby_to_vool(source)
vool.to_mom(nil)
machine.translate(platform)
machine.position_all
machine.create_binary
end
end
end