Skip to content

Commit

Permalink
Refactor to only touch ToSVisitor
Browse files Browse the repository at this point in the history
  • Loading branch information
Blacksmoke16 committed Dec 22, 2024
1 parent 1264859 commit 12b061b
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 38 deletions.
6 changes: 3 additions & 3 deletions spec/compiler/parser/parser_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,7 @@ module Crystal
it_parses "puts {{**1}}", Call.new(nil, "puts", MacroExpression.new(DoubleSplat.new(1.int32)))
it_parses "{{a = 1 if 2}}", MacroExpression.new(If.new(2.int32, Assign.new("a".var, 1.int32)))
it_parses "{% a = 1 %}", MacroExpression.new(Assign.new("a".var, 1.int32), output: false)
it_parses "{%\n a = 1\n%}", MacroExpression.new(Assign.new("a".var, 1.int32), output: false, multiline: true)
it_parses "{%\n a = 1\n%}", MacroExpression.new(Assign.new("a".var, 1.int32), output: false)
it_parses "{% a = 1 if 2 %}", MacroExpression.new(If.new(2.int32, Assign.new("a".var, 1.int32)), output: false)
it_parses "{% if 1; 2; end %}", MacroExpression.new(If.new(1.int32, 2.int32), output: false)
it_parses "{%\nif 1; 2; end\n%}", MacroExpression.new(If.new(1.int32, 2.int32), output: false)
Expand All @@ -1128,8 +1128,8 @@ module Crystal
it_parses "{% unless 1; 2; else 3; end %}", MacroExpression.new(Unless.new(1.int32, 2.int32, 3.int32), output: false)
it_parses "{% unless 1\n x\nend %}", MacroExpression.new(Unless.new(1.int32, "x".var), output: false)
it_parses "{% x unless 1 %}", MacroExpression.new(Unless.new(1.int32, "x".var), output: false)
it_parses "{%\n x unless 1\n%}", MacroExpression.new(Unless.new(1.int32, "x".var), output: false, multiline: true)
it_parses "{%\n 1\n 2\n 3\n%}", MacroExpression.new(Expressions.new([1.int32, 2.int32, 3.int32] of ASTNode), output: false, multiline: true)
it_parses "{%\n x unless 1\n%}", MacroExpression.new(Unless.new(1.int32, "x".var), output: false)
it_parses "{%\n 1\n 2\n 3\n%}", MacroExpression.new(Expressions.new([1.int32, 2.int32, 3.int32] of ASTNode), output: false)

assert_syntax_error "{% unless 1; 2; elsif 3; 4; end %}"
assert_syntax_error "{% unless 1 %} 2 {% elsif 3 %} 3 {% end %}"
Expand Down
18 changes: 5 additions & 13 deletions src/compiler/crystal/syntax/ast.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2187,32 +2187,24 @@ module Crystal
end

# A macro expression,
# surrounded by {{ ... }}` (output = true, multiline = false)
# or by `{% ... %}` (output = false, multiline = false)
#
# ```
# # (output = false, multiline = true)
# {%
# ...
# %}
# ```
# surrounded by {{ ... }} (output = true)
# or by {% ... %} (output = false)
class MacroExpression < ASTNode
property exp : ASTNode
property? output : Bool
property? multiline : Bool

def initialize(@exp : ASTNode, @output = true, @multiline : Bool = false)
def initialize(@exp : ASTNode, @output = true)
end

def accept_children(visitor)
@exp.accept visitor
end

def clone_without_location
MacroExpression.new(@exp.clone, @output, @multiline)
MacroExpression.new(@exp.clone, @output)
end

def_equals_and_hash exp, output?, multiline?
def_equals_and_hash exp, output?
end

# Free text that is part of a macro
Expand Down
10 changes: 2 additions & 8 deletions src/compiler/crystal/syntax/parser.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3353,13 +3353,7 @@ module Crystal

def parse_macro_control(start_location, macro_state = Token::MacroState.default)
location = @token.location
next_token_skip_space
multiline = false

if @token.type.newline?
multiline = true
next_token_skip_space_or_newline
end
next_token_skip_space_or_newline

case @token.value
when Keyword::FOR
Expand Down Expand Up @@ -3446,7 +3440,7 @@ module Crystal
exps = parse_expressions
@in_macro_expression = false

MacroExpression.new(exps, output: false, multiline: multiline).at(location).at_end(token_end_location)
MacroExpression.new(exps, output: false).at(location).at_end(token_end_location)
end

def parse_macro_if(start_location, macro_state, check_end = true, is_unless = false)
Expand Down
32 changes: 18 additions & 14 deletions src/compiler/crystal/syntax/to_s.cr
Original file line number Diff line number Diff line change
Expand Up @@ -717,11 +717,11 @@ module Crystal
end
newline

@indent += 1
inside_macro do
accept node.body
with_indent do
inside_macro do
accept node.body
end
end
@indent -= 1

# newline
append_indent
Expand All @@ -730,30 +730,34 @@ module Crystal
end

def visit(node : MacroExpression)
@str << (node.output? ? "{{ " : node.multiline? ? "{%" : "{% ")
# The node is considered multiline if its starting location is on a different line than its expression.
is_multiline = (start_loc = node.location) && (end_loc = node.exp.location) && end_loc.line_number > start_loc.line_number

@str << (node.output? ? "{{ " : is_multiline ? "{%" : "{% ")

if node.multiline?
if is_multiline
newline
@indent += 1
end

outside_macro do
# If the MacroExpression consists of a single node we need to manually handle appending indent and trailing newline if #multiline?
# If the MacroExpression consists of a single node we need to manually handle appending indent and trailing newline if *is_multiline*
# Otherwise, the Expressions logic handles that for us
if node.multiline? && !node.exp.is_a?(Expressions)
if is_multiline && !node.exp.is_a?(Expressions)
append_indent
end

node.exp.accept self
end

if node.multiline?
# If the opening tag has a newline after it, force trailing tag to have one as well
if is_multiline
@indent -= 1
append_indent
newline if !node.exp.is_a? Expressions
end

@str << (node.output? ? " }}" : node.multiline? ? "%}" : " %}")
@str << (node.output? ? " }}" : is_multiline ? "%}" : " %}")
false
end

Expand Down Expand Up @@ -810,11 +814,11 @@ module Crystal
def visit(node : MacroVerbatim)
@str << "{% verbatim do %}"

@indent += 1
inside_macro do
node.exp.accept self
with_indent do
inside_macro do
node.exp.accept self
end
end
@indent -= 1

@str << "{% end %}"
false
Expand Down

0 comments on commit 12b061b

Please sign in to comment.