Skip to content

Commit

Permalink
Revert "Add compile time string interpolation for char/num/bool const…
Browse files Browse the repository at this point in the history
…ants" (#14155)
  • Loading branch information
straight-shoota authored Jan 3, 2024
1 parent 316422f commit 8be53a4
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 63 deletions.
39 changes: 0 additions & 39 deletions spec/compiler/normalize/string_interpolation_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -52,43 +52,4 @@ describe "Normalize: string interpolation" do
string = node.should be_a(StringLiteral)
string.value.should eq("hello world")
end

it "replaces char constant" do
result = semantic(%(
def String.interpolation(*args); ""; end
OBJ = 'l'
"hello wor\#{OBJ}d"
))
node = result.node.as(Expressions).last
string = node.should be_a(StringLiteral)
string.value.should eq("hello world")
end

it "replaces number constant" do
result = semantic(%(
def String.interpolation(*args); ""; end
OBJ = 9_f32
"nine as a float: \#{OBJ}"
))
node = result.node.as(Expressions).last
string = node.should be_a(StringLiteral)
string.value.should eq("nine as a float: 9.0")
end

it "replaces boolean constant" do
result = semantic(%(
def String.interpolation(*args); ""; end
OBJ = false
"boolean false: \#{OBJ}"
))
node = result.node.as(Expressions).last
string = node.should be_a(StringLiteral)
string.value.should eq("boolean false: false")
end
end
55 changes: 31 additions & 24 deletions src/compiler/crystal/semantic/cleanup_transformer.cr
Original file line number Diff line number Diff line change
Expand Up @@ -256,28 +256,35 @@ module Crystal
end

def transform(node : StringInterpolation)
string = node.expressions.join do |exp|
if !(transformed_piece = solve_string_interpolation_expression(exp)).nil?
# Valid piece, continue joining
next transformed_piece
elsif expanded = node.expanded
# Invalid piece, transform expansion and exit early
return expanded.transform(self)
else
# No expansion, return self
return node
end
# See if we can solve all the pieces to string literals.
# If that's the case, we can replace the entire interpolation
# with a single string literal.
pieces = node.expressions.dup
solve_string_interpolation_expressions(pieces)

if pieces.all?(StringLiteral)
string = pieces.join(&.as(StringLiteral).value)
string_literal = StringLiteral.new(string).at(node)
string_literal.type = @program.string
return string_literal
end

if expanded = node.expanded
return expanded.transform(self)
end
string_literal = StringLiteral.new(string).at(node)
string_literal.type = @program.string
string_literal
node
end

# Returns the solved piece for string interpolation, if it can find one.
# For example, this returns a String when given a StringLiteral.
private def solve_string_interpolation_expression(piece : ASTNode) : String | Char | Number::Primitive | Bool | Nil
# Check for ExpandableNode happens first in case any nodes below are
# updated to be ExpandableNodes themselves.
private def solve_string_interpolation_expressions(pieces : Array(ASTNode))
pieces.each_with_index do |piece, i|
replacement = solve_string_interpolation_expression(piece)
next unless replacement

pieces[i] = replacement
end
end

private def solve_string_interpolation_expression(piece : ASTNode) : StringLiteral?
if piece.is_a?(ExpandableNode)
if expanded = piece.expanded
return solve_string_interpolation_expression(expanded)
Expand All @@ -287,13 +294,13 @@ module Crystal
case piece
when Path
if target_const = piece.target_const
solve_string_interpolation_expression(target_const.value)
return solve_string_interpolation_expression(target_const.value)
end
when StringLiteral then piece.value
when CharLiteral then piece.value
when NumberLiteral then piece.to_number
when BoolLiteral then piece.value
when StringLiteral
return piece
end

nil
end

def transform(node : ExpandableNode)
Expand Down

0 comments on commit 8be53a4

Please sign in to comment.