Wrap all compiler assignments in begin/end

This is much safer than having to explicitly call "wrap" in a potential
large amount of places.
This commit is contained in:
Yorick Peterse 2015-08-18 16:40:55 +02:00
parent aaba0049ab
commit 4b50a161ed
4 changed files with 16 additions and 48 deletions

View File

@ -56,11 +56,14 @@ module Oga
##
# Returns an assignment node.
#
# This method wraps assigned values in a begin/end block to ensure that
# multiple lines of code result in the proper value being assigned.
#
# @param [Oga::Ruby::Node] other
# @return [Oga::Ruby::Node]
#
def assign(other)
Node.new(:assign, [self, other])
Node.new(:assign, [self, other.wrap])
end
##

View File

@ -1358,49 +1358,6 @@ module Oga
#
# Everything else is processed the usual (and possibly slower) way.
#
# The variables used by this operator are assigned a "begin" block
# containing the actual result. This ensures that each variable is
# assigned the result of the entire block instead of the first expression
# that occurs.
#
# For example, take the following expression:
#
# 10 = 10 = 20
#
# Without a "begin" we'd end up with the following code (trimmed for
# readability):
#
# eq_left3 = eq_left1 = ...
#
# eq_left2 = ...
#
# eq_left1, eq_left2 = to_compatible_types(eq_left1, eq_left2)
#
# eq_left1 == eq_left2
#
# eq_left4 = ...
#
# eq_left3 == eq_left4
#
# This would be incorrect as the first boolean expression (`10 = 10`)
# would be ignored. By using a "begin" we instead get the following:
#
# eq_left3 = begin
# eq_left1 = ...
#
# eq_left2 = ...
#
# eq_left1, eq_left2 = to_compatible_types(eq_left1, eq_left2)
#
# eq_left1 == eq_left2
# end
#
# eq_left4 = begin
# ...
# end
#
# eq_left3 == eq_left4
#
# @param [AST::Node] ast
# @param [Oga::Ruby::Node] input
# @param [TrueClass|FalseClass] optimize_first
@ -1415,8 +1372,8 @@ module Oga
left_ast = try_match_first_node(left, input, optimize_first)
right_ast = try_match_first_node(right, input, optimize_first)
initial_assign = left_var.assign(left_ast.wrap)
.followed_by(right_var.assign(right_ast.wrap))
initial_assign = left_var.assign(left_ast)
.followed_by(right_var.assign(right_ast))
.followed_by { yield left_var, right_var }
end

View File

@ -21,7 +21,11 @@ describe Oga::Ruby::Generator do
val = Oga::Ruby::Node.new(:lit, %w{10})
assign = var.assign(val)
@generator.on_assign(assign).should == 'number = 10'
@generator.on_assign(assign).should == <<-EOF
number = begin
10
end
EOF
end
end

View File

@ -34,7 +34,11 @@ describe Oga::Ruby::Node do
node = left.assign(right)
node.type.should == :assign
node.to_a.should == [left, right]
node.to_a[0].should == left
node.to_a[1].type.should == :begin
node.to_a[1].to_a[0].should == right
end
end