CodeTools::AST << {

Invoke < Node {
  node_type invoke
  field receiver, field name, field arguments, field block

  bytecode: |g| pos(g); implementation.bytecode(g)

  implementation: {
    use_args = self.arguments

    # TODO: error if passing both block argument and block literal
    # Currently, this fails silently and ignores the block argument
    self.block && (
      use_args = (use_args && use_args.dup) || ArgumentAssembly.new(line:self.line, body:[])
      use_args.block = self.block
    )

    !self.receiver && !use_args &? (
            (self.name == :self)  &? (Self        .new(line: self.line)
      ) ?? ((self.name == :null)  &? (NullLiteral .new(line: self.line)
      ) ?? ((self.name == :void)  &? (VoidLiteral .new(line: self.line)
      ) ?? ((self.name == :true)  &? (TrueLiteral .new(line: self.line)
      ) ?? ((self.name == :false) &? (FalseLiteral.new(line: self.line)
      ) ?? (
        LocalVariableAccessAmbiguous.new(line: self.line, name: self.name)
      )))))
    ) ?? (
      InvokeMethod.new(
        line:      self.line
        receiver:  self.receiver || Self.new(line:self.line)
        name:      self.name
        arguments: use_args || ArgumentAssembly.new(line:self.line, body:[])
      )
    )
  }
}

}