Skip to content

Commit

Permalink
Compiler: ensure parentheses inside assign value
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite authored and ysbaddaden committed Jun 7, 2018
1 parent 9ddaf28 commit 068edc4
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 16 deletions.
19 changes: 19 additions & 0 deletions spec/compiler/codegen/macro_spec.cr
Expand Up @@ -1794,4 +1794,23 @@ describe "Code gen: macro" do
a
)).to_i.should eq(1)
end

it "expands macro with op assign inside assign (#5568)" do
run(%(
require "prelude"
macro expand
{{ yield }}
end
def foo
{:foo => 1}
end
expand do
x = foo[:foo] += 1
puts x
end
)).to_string.chomp.should eq("2")
end
end
2 changes: 1 addition & 1 deletion spec/compiler/normalize/and_spec.cr
Expand Up @@ -18,7 +18,7 @@ describe "Normalize: and" do
end

it "normalizes and with ! on var.is_a?(...)" do
assert_expand_second "a = 1; !a.is_a?(Int32) && b", "if !(a.is_a?(Int32))\n b\nelse\n !(a.is_a?(Int32))\nend"
assert_expand_second "a = 1; !a.is_a?(Int32) && b", "if !a.is_a?(Int32)\n b\nelse\n !a.is_a?(Int32)\nend"
end

it "normalizes and with is_a? on exp" do
Expand Down
4 changes: 2 additions & 2 deletions spec/compiler/normalize/case_spec.cr
Expand Up @@ -74,7 +74,7 @@ describe "Normalize: case" do
end

it "normalizes case with multiple expressions and types" do
assert_expand_second "x, y = 1, 2; case {x, y}; when {Int32, Float64}; 4; end", "if (x.is_a?(Int32)) && (y.is_a?(Float64))\n 4\nend"
assert_expand_second "x, y = 1, 2; case {x, y}; when {Int32, Float64}; 4; end", "if x.is_a?(Int32) && y.is_a?(Float64)\n 4\nend"
end

it "normalizes case with multiple expressions and implicit obj" do
Expand All @@ -98,6 +98,6 @@ describe "Normalize: case" do
end

it "normalizes case with multiple expressions and non-tuple" do
assert_expand_second "x, y = 1, 2; case {x, y}; when 1; 4; end", "if 1 === ({x, y})\n 4\nend"
assert_expand_second "x, y = 1, 2; case {x, y}; when 1; 4; end", "if 1 === {x, y}\n 4\nend"
end
end
2 changes: 1 addition & 1 deletion spec/compiler/normalize/or_spec.cr
Expand Up @@ -22,6 +22,6 @@ describe "Normalize: or" do
end

it "normalizes or with ! on var.is_a?(...)" do
assert_expand_second "a = 1; !a.is_a?(Int32) || b", "if !(a.is_a?(Int32))\n !(a.is_a?(Int32))\nelse\n b\nend"
assert_expand_second "a = 1; !a.is_a?(Int32) || b", "if !a.is_a?(Int32)\n !a.is_a?(Int32)\nelse\n b\nend"
end
end
27 changes: 17 additions & 10 deletions spec/compiler/parser/to_s_spec.cr
Expand Up @@ -3,17 +3,23 @@ require "../../support/syntax"
private def expect_to_s(original, expected = original, emit_doc = false, file = __FILE__, line = __LINE__)
it "does to_s of #{original.inspect}", file, line do
str = IO::Memory.new expected.bytesize
parser = Parser.new original
parser.wants_doc = emit_doc
node = parser.parse
node.to_s(str, emit_doc: emit_doc)
str.to_s.should eq(expected), file, line

# Check keeping information for `to_s` on clone
cloned = node.clone
str.clear
cloned.to_s(str, emit_doc: emit_doc)
str.to_s.should eq(expected), file, line
source = original
if source.is_a?(String)
parser = Parser.new source
parser.wants_doc = emit_doc
node = parser.parse
node.to_s(str, emit_doc: emit_doc)
str.to_s.should eq(expected), file, line

# Check keeping information for `to_s` on clone
cloned = node.clone
str.clear
cloned.to_s(str, emit_doc: emit_doc)
str.to_s.should eq(expected), file, line
else
source.to_s.should eq(expected), file, line
end
end
end

Expand Down Expand Up @@ -132,4 +138,5 @@ describe "ASTNode#to_s" do
expect_to_s %q(`\n\0`), %q(`\n\u0000`)
expect_to_s %q(`#{1}\n\0`), %q(`#{1}\n\u0000`)
expect_to_s "macro foo\n{% verbatim do %}1{% end %}\nend"
expect_to_s Assign.new("x".var, Expressions.new([1.int32, 2.int32] of ASTNode)), "x = (1\n2\n)"
end
7 changes: 5 additions & 2 deletions src/compiler/crystal/syntax/to_s.cr
Expand Up @@ -467,7 +467,7 @@ module Crystal
end
when Var, NilLiteral, BoolLiteral, CharLiteral, NumberLiteral, StringLiteral,
StringInterpolation, Path, Generic, InstanceVar, ClassVar, Global,
ImplicitObj
ImplicitObj, TupleLiteral, NamedTupleLiteral, IsA
false
when ArrayLiteral
!!obj.of
Expand Down Expand Up @@ -560,7 +560,10 @@ module Crystal
def visit(node : Assign)
node.target.accept self
@str << " = "
node.value.accept self

need_parens = node.value.is_a?(Expressions)
in_parenthesis(need_parens, node.value)

false
end

Expand Down

0 comments on commit 068edc4

Please sign in to comment.