Skip to content

Commit 8c5fb21

Browse files
makenowjustMartin Verzilli
authored and
Martin Verzilli
committedSep 29, 2017
Remove 1 item Expressions normalization (#4861)
Fix #4849 See #4852 (comment)
1 parent 8514651 commit 8c5fb21

File tree

4 files changed

+48
-7
lines changed

4 files changed

+48
-7
lines changed
 

Diff for: ‎spec/compiler/normalize/expressions_spec.cr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
require "../../spec_helper"
2+
3+
describe "Normalize: expressions" do
4+
it "normalizes an empty expression" do
5+
assert_normalize "begin\nend", ""
6+
end
7+
8+
it "normalizes an expression" do
9+
assert_normalize "(1 < 2).as(Bool)", "(1 < 2).as(Bool)"
10+
end
11+
12+
it "normalizes expressions" do
13+
assert_normalize "begin\n 1\n 2\nend", "1\n2"
14+
end
15+
end

Diff for: ‎spec/compiler/semantic/while_spec.cr

+8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ describe "Semantic: while" do
2222
assert_type("while true; end") { no_return }
2323
end
2424

25+
it "types while (true) as NoReturn" do
26+
assert_type("while (true); end") { no_return }
27+
end
28+
29+
it "types while ((true)) as NoReturn" do
30+
assert_type("while ((true)); end") { no_return }
31+
end
32+
2533
it "reports next cannot be used outside a while" do
2634
assert_error "next",
2735
"Invalid next"

Diff for: ‎src/compiler/crystal/semantic/main_visitor.cr

+25-5
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,9 @@ module Crystal
17371737
when Assign
17381738
target = exp.target
17391739
return target if target.is_a?(Var)
1740+
when Expressions
1741+
return unless exp = single_expression(exp)
1742+
return get_expression_var(exp)
17401743
end
17411744
nil
17421745
end
@@ -1843,15 +1846,17 @@ module Crystal
18431846
# block is when the condition is a Var (in the else it must be
18441847
# nil), IsA (in the else it's not that type), RespondsTo
18451848
# (in the else it doesn't respond to that message) or Not.
1846-
case cond = node.cond
1849+
case cond = single_expression(node.cond) || node.cond
18471850
when Var, IsA, RespondsTo, Not
18481851
filter_vars cond_type_filters, &.not
18491852
when Or
18501853
# Try to apply boolean logic: `!(a || b)` is `!a && !b`
1854+
cond_left = single_expression(cond.left) || cond.left
1855+
cond_right = single_expression(cond.right) || cond.right
18511856

18521857
# We can't deduce anything for sub && or || expressions
1853-
or_left_type_filters = nil if cond.left.is_a?(And) || cond.left.is_a?(Or)
1854-
or_right_type_filters = nil if cond.right.is_a?(And) || cond.right.is_a?(Or)
1858+
or_left_type_filters = nil if cond_left.is_a?(And) || cond_left.is_a?(Or)
1859+
or_right_type_filters = nil if cond_right.is_a?(And) || cond_right.is_a?(Or)
18551860

18561861
# No need to deduce anything for temp vars created by the compiler (won't be used by a user)
18571862
or_left_type_filters = nil if or_left_type_filters && or_left_type_filters.temp_var?
@@ -2017,8 +2022,10 @@ module Crystal
20172022
node.body.accept self
20182023
end
20192024

2020-
endless_while = node.cond.true_literal?
2021-
merge_while_vars node.cond, endless_while, before_cond_vars_copy, before_cond_vars, after_cond_vars, @vars, node.break_vars
2025+
cond = single_expression(node.cond) || node.cond
2026+
2027+
endless_while = cond.true_literal?
2028+
merge_while_vars cond, endless_while, before_cond_vars_copy, before_cond_vars, after_cond_vars, @vars, node.break_vars
20222029

20232030
@while_stack.pop
20242031
@block = old_block
@@ -2146,6 +2153,9 @@ module Crystal
21462153
end
21472154
when Call
21482155
return get_while_cond_assign_target(node.obj)
2156+
when Expressions
2157+
return unless node = single_expression(node)
2158+
return get_while_cond_assign_target(node)
21492159
end
21502160

21512161
nil
@@ -2178,6 +2188,16 @@ module Crystal
21782188
end
21792189
end
21802190

2191+
def single_expression(node)
2192+
result = nil
2193+
2194+
while node.is_a?(Expressions) && node.expressions.size == 1
2195+
result = node = node[0]
2196+
end
2197+
2198+
result
2199+
end
2200+
21812201
def end_visit(node : Break)
21822202
if last_block_kind == :ensure
21832203
node.raise "can't use break inside ensure"

Diff for: ‎src/compiler/crystal/semantic/normalizer.cr

-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ module Crystal
5151
case exps.size
5252
when 0
5353
Nop.new
54-
when 1
55-
exps[0]
5654
else
5755
node.expressions = exps
5856
node

0 commit comments

Comments
 (0)
Please sign in to comment.