first propper hoisting test

had to change course, normalising and object creation is not possible
in one go
have to now generate random tmp vars  that will have to be picked up
later (sorted by tmp_ prefix?)
This commit is contained in:
Torsten Ruger 2018-03-15 12:46:56 +05:30
parent 9ddcb3224c
commit 3702411043
13 changed files with 149 additions and 54 deletions

View File

@ -26,6 +26,7 @@ module Common
end end
def <<(o) def <<(o)
@statements << o @statements << o
self
end end
def collect(arr) def collect(arr)
@statements.each { |s| s.collect(arr) } @statements.each { |s| s.collect(arr) }

View File

@ -27,13 +27,12 @@ module Vool
# after creation vool normalizes to ensure valid syntax and simplify # after creation vool normalizes to ensure valid syntax and simplify
# also throw errors if violation # also throw errors if violation
def normalize(method) def normalize()
return self raise self.class.name
end end
# flatten tree to array def each()
def collect(arr) yield self
arr << self
end end
def to_mom( _ ) def to_mom( _ )
@ -44,25 +43,15 @@ module Vool
def ct_type def ct_type
nil nil
end end
# create corresponding parfait objects, ie classes, types, methods
# mainly implemented by class/method statement
def create_objects
end
# used to collect type information
def add_ivar( array )
end
# used to collect frame information
def add_local( array )
end
# used for method creation
def set_class( clazz )
end
end end
class Expression class Expression
def normalize
raise "should not be normalized #{self}"
end
end end
end end

View File

@ -7,9 +7,9 @@ module Vool
end end
def normalize() def normalize()
raise "not named left #{name}" unless @name.is_a?(Named) raise "not named left #{name.class}" unless @name.is_a?(Symbol)
raise "unsupported right #{value}" unless @name.is_a?(Named) or raise "unsupported right #{value}" unless @value.is_a?(Named) or
@name.is_a?(SendStatement) or @name.is_a?(Constant) @value.is_a?(SendStatement) or @value.is_a?(Constant)
self self
end end

View File

@ -48,10 +48,8 @@ module Vool
end end
class SelfExpression < Expression class SelfExpression < Expression
attr_reader :clazz attr_reader :clazz
def set_class(clazz)
@clazz = clazz
end
def to_mom(in_method) def to_mom(in_method)
@clazz = in_method.clazz
Mom::SlotDefinition.new(:message , [:receiver]) Mom::SlotDefinition.new(:message , [:receiver])
end end
def ct_type def ct_type

View File

@ -5,12 +5,12 @@ module Vool
def initialize( name , supe , body) def initialize( name , supe , body)
@name , @super_class_name , @body = name , supe , body @name , @super_class_name , @body = name , supe , body
unless( body.is_a?(ScopeStatement)) @body = ScopeStatement.new([]) unless body
@body = ScopeStatement.new([])
@body.statements << body if body
end
end end
def normalize
ClassStatement.new(@name , @super_class_name, @body.normalize )
end
# compilation to the next layer, mom # compilation to the next layer, mom
# context coming in for class is nil, also for methods, henceafter a method is passed down # context coming in for class is nil, also for methods, henceafter a method is passed down
def to_mom( _ ) def to_mom( _ )
@ -18,7 +18,7 @@ module Vool
Mom::Statements.new(methods) Mom::Statements.new(methods)
end end
def collect(arr) def each()
@body.collect(arr) @body.collect(arr)
super super
end end

View File

@ -12,10 +12,10 @@ module Vool
simplify_condition simplify_condition
end end
def normalize(method) def normalize
cond , rest = *normalize_name(@condition, method) cond , rest = *normalize_name(@condition)
fals = @if_false ? @if_false.normalize(method) : nil fals = @if_false ? @if_false.normalize : nil
me = IfStatement.new(cond , @if_true.normalize(method), fals) me = IfStatement.new(cond , @if_true.normalize, fals)
return me unless rest return me unless rest
rest << me rest << me
end end

View File

@ -2,13 +2,10 @@ module Vool
class MethodStatement < Statement class MethodStatement < Statement
attr_reader :name, :args , :body , :clazz attr_reader :name, :args , :body , :clazz
def initialize( name , args , body) def initialize( name , args , body , clazz = nil)
@name , @args , @body = name , args , body @name , @args , @body = name , args , body
unless( body.is_a?(ScopeStatement)) @body = ScopeStatement.new([]) unless body
@body = ScopeStatement.new([]) @clazz = clazz
@body.statements << body if body
end
end end
# compile to mom instructions. methods themselves do no result in instructions (yet) # compile to mom instructions. methods themselves do no result in instructions (yet)
@ -24,8 +21,8 @@ module Vool
super super
end end
def set_class(clazz) def normalize
@clazz = clazz MethodStatement.new( @name , @args , @body.normalize)
end end
def create_objects def create_objects
@ -50,7 +47,7 @@ module Vool
def make_frame def make_frame
type_hash = {} type_hash = {}
vars = [] vars = []
@body.collect([]).each { |node| node.add_local(vars) } @body.each([]).each { |node| node.add_local(vars) }
vars.each { |var| type_hash[var] = :Object } vars.each { |var| type_hash[var] = :Object }
Parfait::NamedList.type_for( type_hash ) Parfait::NamedList.type_for( type_hash )
end end

View File

@ -6,10 +6,10 @@ module Vool
# #
# eg if( @var % 5) is not normalized # eg if( @var % 5) is not normalized
# but if(tmp_123) is with tmp_123 = @var % 5 hoited above the if # but if(tmp_123) is with tmp_123 = @var % 5 hoited above the if
def normalize_name( condition , method ) def normalize_name( condition )
return [condition] if condition.is_a?(Named) return [condition] if condition.is_a?(Named)
local = method.create_tmp local = "tmp_#{object_id}"
assign = LocalAssignment.new( local , condition) assign = Statements.new [LocalAssignment.new( local , condition)]
[LocalVariable.new(local) , assign] [LocalVariable.new(local) , assign]
end end
end end

View File

@ -5,8 +5,8 @@ module Vool
def self.ruby_to_vool( ruby_source ) def self.ruby_to_vool( ruby_source )
statements = RubyCompiler.compile( ruby_source ) statements = RubyCompiler.compile( ruby_source )
statements = statements.normalize(nil) statements = statements.normalize
statements.create_objects #statements.create_objects
statements statements
end end
def self.ruby_to_mom(source) def self.ruby_to_mom(source)

View File

@ -30,9 +30,8 @@ module Vool
include CompilerHelper include CompilerHelper
def test_compile_one_method def test_compile_one_method
lst = RubyCompiler.compile( in_Test("@ivar") ) lst = RubyCompiler.compile( in_Test("@ivar = 4") )
assert_equal ScopeStatement , lst.body.class assert_equal IvarAssignment , lst.body.class
assert_equal InstanceVariable , lst.body.statements.first.class
end end
def test_compile_two_methods def test_compile_two_methods
lst = RubyCompiler.compile( in_Test("false; true;") ) lst = RubyCompiler.compile( in_Test("false; true;") )

View File

@ -27,9 +27,9 @@ module Vool
assert_equal 2 , @lst.body.length assert_equal 2 , @lst.body.length
end end
def test_body_is_scope_one_statement def test_body_is_scope_one_statement
input = "def tryout(arg1, arg2) ; true ; end " input = "def tryout(arg1, arg2) ; a = true ; end "
lst = RubyCompiler.compile( input ) lst = RubyCompiler.compile( input )
assert_equal ScopeStatement , lst.body.class assert_equal LocalAssignment , lst.body.class
end end
def test_body_is_scope_zero_statement def test_body_is_scope_zero_statement
input = "def tryout(arg1, arg2) ; ; end " input = "def tryout(arg1, arg2) ; ; end "

View File

@ -0,0 +1,16 @@
require_relative "../helper"
module VoolHelper
include CompilerHelper
def compile_main( input )
st = Vool::VoolCompiler.ruby_to_vool as_test_main( input )
assert_equal st.class , Vool::ClassStatement
assert_equal st.body.class , Vool::MethodStatement
st.body.body
end
def compile_plain( input )
Vool::VoolCompiler.ruby_to_vool input
end
end

View File

@ -0,0 +1,95 @@
require_relative 'helper'
module Vool
module VoolC
class TestIfStatement < MiniTest::Test
include VoolHelper
def basic_if
"if(10 < 12) ; a = true ; end"
end
def test_if_basic_hoist
lst = compile_main( basic_if )
assert_equal Statements , lst.class
assert_equal IfStatement , lst.statements[1].class
end
def pest_if_basic_cond
lst = RubyCompiler.compile( basic_if )
assert_equal SendStatement , lst.condition.class
end
def pest_if_basic_branches
lst = RubyCompiler.compile( basic_if )
assert_equal TrueConstant , lst.if_true.class
assert_nil lst.if_false
end
def double_if
"if(false) ; true ; else ; false; end"
end
def pest_if_double
lst = RubyCompiler.compile( double_if )
assert_equal IfStatement , lst.class
end
def pest_if_double_cond
lst = RubyCompiler.compile( double_if )
assert_equal FalseConstant , lst.condition.class
end
def pest_if_double_branches
lst = RubyCompiler.compile( double_if )
assert_equal TrueConstant , lst.if_true.class
assert_equal FalseConstant, lst.if_false.class
end
def reverse_if
"true if(false)"
end
def pest_if_reverse
lst = RubyCompiler.compile( reverse_if )
assert_equal IfStatement , lst.class
end
def pest_if_reverse_cond
lst = RubyCompiler.compile( reverse_if )
assert_equal FalseConstant , lst.condition.class
end
def pest_if_reverse_branches
lst = RubyCompiler.compile( reverse_if )
assert_equal TrueConstant , lst.if_true.class
assert_nil lst.if_false
end
def reverse_unless
"true unless(false)"
end
def pest_if_reverse
lst = RubyCompiler.compile( reverse_unless )
assert_equal IfStatement , lst.class
end
def pest_if_reverse_cond
lst = RubyCompiler.compile( reverse_unless )
assert_equal FalseConstant , lst.condition.class
end
def pest_if_reverse_branches
lst = RubyCompiler.compile( reverse_unless )
assert_nil lst.if_true
assert_equal TrueConstant ,lst.if_false.class
end
def ternary
"false ? true : false"
end
def pest_if_ternary
lst = RubyCompiler.compile( ternary )
assert_equal IfStatement , lst.class
end
def pest_if_ternary_cond
lst = RubyCompiler.compile( ternary )
assert_equal FalseConstant , lst.condition.class
end
def pest_if_ternary_branches
lst = RubyCompiler.compile( ternary )
assert_equal TrueConstant , lst.if_true.class
assert_equal FalseConstant, lst.if_false.class
end
end
end
end