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
def <<(o)
@statements << o
self
end
def 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
# also throw errors if violation
def normalize(method)
return self
def normalize()
raise self.class.name
end
# flatten tree to array
def collect(arr)
arr << self
def each()
yield self
end
def to_mom( _ )
@ -44,25 +43,15 @@ module Vool
def ct_type
nil
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
class Expression
def normalize
raise "should not be normalized #{self}"
end
end
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,10 +6,10 @@ module Vool
#
# eg if( @var % 5) is not normalized
# 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)
local = method.create_tmp
assign = LocalAssignment.new( local , condition)
local = "tmp_#{object_id}"
assign = Statements.new [LocalAssignment.new( local , condition)]
[LocalVariable.new(local) , assign]
end
end

View File

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

View File

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

View File

@ -27,9 +27,9 @@ module Vool
assert_equal 2 , @lst.body.length
end
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 )
assert_equal ScopeStatement , lst.body.class
assert_equal LocalAssignment , lst.body.class
end
def test_body_is_scope_zero_statement
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