# Closed macro call expressions

@enum(Light, red, yellow, green)
@NamedTuple{a::Float64, b::String}

==>
Program(
  MacrocallExpression(
    MacroIdentifier(Identifier),
    Arguments(
      Identifier,
      Identifier,
      Identifier,
      Identifier,
    ),
  ),
  MacrocallExpression(
    MacroIdentifier(Identifier),
    BraceExpression(
      BinaryExpression(Identifier, SubTypeOp, Type(Identifier)),
      BinaryExpression(Identifier, SubTypeOp, Type(Identifier)),
    ),
  ),
)


# Open macro call expressions

@mac a b c

@assert x == y "a message"

@. a * x + b

joinpath(@__DIR__, "grammar.js")

@macroexpand @async accept(socket)

==>
Program(
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(Identifier, Identifier, Identifier),
  )
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(BinaryExpression(Identifier, ComparisonOp, Identifier), StringLiteral)
  ),
  MacrocallExpression(
    MacroIdentifier(Operator),
    MacroArguments(BinaryExpression(BinaryExpression(Identifier, TimesOp, Identifier), UnaryPlusOp, Identifier))
  ),
  CallExpression(
    Identifier,
    Arguments(
      MacrocallExpression(MacroIdentifier(Identifier))
      StringLiteral
    )
  )
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(
      MacrocallExpression(
        MacroIdentifier(Identifier),
        MacroArguments(
          CallExpression(Identifier, Arguments(Identifier))
        )
      )
    )
  )
)


# Qualified macro identifiers

Meta.@dump x = 1
# @Meta.dump 1, 2 # TODO

==>
Program(
  MacrocallExpression(
    FieldExpression(
      Identifier,
      MacroIdentifier(Identifier),
    ),
    MacroArguments(Assignment(Identifier, AssignmentOp, IntegerLiteral))
  )
  LineComment
)


# Open macro call expressions - Assignments and open tuple arguments

@m x = y = z

@m x, y = 1, 2

@m x, y, z x, y, z

==>
Program(
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(
      Assignment(
        Identifier,
        AssignmentOp,
        Assignment(
          Identifier,
          AssignmentOp,
          Identifier,
        )
      )
    )
  ),
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(
      Assignment(
        OpenTuple(Identifier, Identifier),
        AssignmentOp,
        OpenTuple(IntegerLiteral, IntegerLiteral),
      )
    )
  ),
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(
      OpenTuple(Identifier, Identifier, Identifier),
      OpenTuple(Identifier, Identifier, Identifier),
    )
  )
)


# Open macro call expressions - Arguments spanning multiple lines

@name a +
  2

==>
Program(
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(BinaryExpression(Identifier, UnaryPlusOp, IntegerLiteral)),
  )
)


# Open macro call expressions - Block arguments

@testset "a" begin
  b = c
end

==>
Program(
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(
      StringLiteral,
      BeginStatement(
        begin,
        Assignment(Identifier, AssignmentOp, Identifier),
        end)
    )
  )
)

# Closed macro call expressions - Do blocks


@test() do x
  xs
end

@test() do x, (y,z)
  body
end

==>

Program(
  MacrocallExpression(
    MacroIdentifier(Identifier),
    Arguments,
    DoClause(
      do,
      Parameters(Identifier),
      Identifier,
      end
    )
  ),
  
  MacrocallExpression(
    MacroIdentifier(Identifier),
    Arguments,
    DoClause(
      do,
      Parameters(Identifier, TupleExpression(Identifier,Identifier)),
      Identifier,
      end
    )
  ),
)


# Open vs closed macro calls

@m[1, 2] + 1
@m [1, 2] + 1

==>
Program(
  BinaryExpression(
    MacrocallExpression(
      MacroIdentifier(Identifier),
      VectorExpression(IntegerLiteral, IntegerLiteral),
    ),
    UnaryPlusOp,
    IntegerLiteral
  ),
  MacrocallExpression(
    MacroIdentifier(Identifier),
    MacroArguments(
      BinaryExpression(
        VectorExpression(IntegerLiteral, IntegerLiteral),
        UnaryPlusOp,
        IntegerLiteral
      )
    )
  )
)


# Macro calls as parameters

f(@nospecialize(x)) = x
g(@nospecialize x) = x + 1
h(@nospecialize x, y) = x + y

==>
Program(
  Assignment(
    CallExpression(
      Identifier
      Arguments(
        MacrocallExpression(MacroIdentifier(Identifier), Arguments(Identifier))
      )
    ),
    AssignmentOp,
    Identifier
  )
  Assignment(
    CallExpression(
      Identifier
      Arguments(
        MacrocallExpression(MacroIdentifier(Identifier), MacroArguments(Identifier))
      )
    ),
    AssignmentOp,
    BinaryExpression(Identifier, UnaryPlusOp, IntegerLiteral),
  )
  Assignment(
    CallExpression(
      Identifier
      Arguments(
        MacrocallExpression(MacroIdentifier(Identifier), MacroArguments(OpenTuple(Identifier, Identifier)))
      )
    ),
    AssignmentOp,
    BinaryExpression(Identifier, UnaryPlusOp, Identifier),
  )
)


# Open macro calls terminated by a generator `for` - issue #24

[@show (index) for index in eachindex(r_v)]
[@__FILE__ for index in eachindex(r_v)]
sum(@show x for x in y)
f(@m x for i in y end)

==>
Program(
  ComprehensionExpression(
    Generator(
      MacrocallExpression(MacroIdentifier(Identifier), MacroArguments(ParenExpression(Identifier))),
      GenFor(for, ForBinding(Identifier, AssignmentOp(in), CallExpression(Identifier, Arguments(Identifier)))),
    )
  ),
  ComprehensionExpression(
    Generator(
      MacrocallExpression(MacroIdentifier(Identifier)),
      GenFor(for, ForBinding(Identifier, AssignmentOp(in), CallExpression(Identifier, Arguments(Identifier)))),
    )
  ),
  CallExpression(
    Identifier,
    Arguments(
      Generator(
        MacrocallExpression(MacroIdentifier(Identifier), MacroArguments(Identifier)),
        GenFor(for, ForBinding(Identifier, AssignmentOp(in), Identifier)),
      )
    )
  ),
  CallExpression(
    Identifier,
    Arguments(
      MacrocallExpression(
        MacroIdentifier(Identifier),
        MacroArguments(Identifier, ForStatement(for, ForBinding(Identifier, AssignmentOp(in), Identifier), end)),
      )
    )
  ),
)
