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:
parent
9ddcb3224c
commit
3702411043
@ -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) }
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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;") )
|
||||||
|
@ -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 "
|
||||||
|
16
test/vool/vool_compiler/helper.rb
Normal file
16
test/vool/vool_compiler/helper.rb
Normal 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
|
95
test/vool/vool_compiler/test_if_statement.rb
Normal file
95
test/vool/vool_compiler/test_if_statement.rb
Normal 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
|
Loading…
x
Reference in New Issue
Block a user