Skip to content

Commit

Permalink
Add MacroIf#is_unless? AST node method
Browse files Browse the repository at this point in the history
  • Loading branch information
Blacksmoke16 committed Dec 21, 2024
1 parent 5545bca commit 8cd19dd
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 5 deletions.
5 changes: 5 additions & 0 deletions spec/compiler/macro/macro_methods_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2726,6 +2726,11 @@ module Crystal
it "executes else" do
assert_macro %({{x.else}}), "\"foo\"", {x: MacroIf.new(BoolLiteral.new(true), StringLiteral.new("test"), StringLiteral.new("foo"))}
end

it "executes is_unless?" do
assert_macro %({{x.is_unless?}}), "true", {x: MacroIf.new(BoolLiteral.new(true), StringLiteral.new("test"), StringLiteral.new("foo"), is_unless: true)}
assert_macro %({{x.is_unless?}}), "false", {x: MacroIf.new(BoolLiteral.new(false), StringLiteral.new("test"), StringLiteral.new("foo"), is_unless: false)}
end
end

describe "macro for methods" do
Expand Down
12 changes: 11 additions & 1 deletion src/compiler/crystal/macros.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2361,14 +2361,20 @@ module Crystal::Macros
end
end

# An `if` inside a macro, e.g.
# An `if`/`unless` inside a macro, e.g.
#
# ```
# {% if cond %}
# puts "Then"
# {% else %}
# puts "Else"
# {% end %}
#
# {% unless cond %}
# puts "Then"
# {% else %}
# puts "Else"
# {% end %}
# ```
class MacroIf < ASTNode
# The condition of the `if` clause.
Expand All @@ -2382,6 +2388,10 @@ module Crystal::Macros
# The `else` branch of the `if`.
def else : ASTNode
end

# Returns `true` if this node represents an `unless` conditional, otherwise returns `false`.
def is_unless? : BoolLiteral
end
end

# A `for` loop inside a macro, e.g.
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/crystal/macros/methods.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,8 @@ module Crystal
interpret_check_args { @then }
when "else"
interpret_check_args { @else }
when "is_unless?"
interpret_check_args { BoolLiteral.new @is_unless }
else
super
end
Expand Down
7 changes: 4 additions & 3 deletions src/compiler/crystal/syntax/ast.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2238,8 +2238,9 @@ module Crystal
property cond : ASTNode
property then : ASTNode
property else : ASTNode
property? is_unless : Bool

def initialize(@cond, a_then = nil, a_else = nil)
def initialize(@cond, a_then = nil, a_else = nil, @is_unless : Bool = false)
@then = Expressions.from a_then
@else = Expressions.from a_else
end
Expand All @@ -2251,10 +2252,10 @@ module Crystal
end

def clone_without_location
MacroIf.new(@cond.clone, @then.clone, @else.clone)
MacroIf.new(@cond.clone, @then.clone, @else.clone, @is_unless)
end

def_equals_and_hash @cond, @then, @else
def_equals_and_hash @cond, @then, @else, @is_unless
end

# for inside a macro:
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/crystal/syntax/parser.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3505,7 +3505,7 @@ module Crystal
end

a_then, a_else = a_else, a_then if is_unless
MacroIf.new(cond, a_then, a_else).at_end(token_end_location)
MacroIf.new(cond, a_then, a_else, is_unless: is_unless).at_end(token_end_location)
end

def parse_expression_inside_macro
Expand Down

0 comments on commit 8cd19dd

Please sign in to comment.