
#include "rust-ast-fragment.h"
#include "rust-macro-builtins.h"
#include "rust-macro-builtins-helpers.h"
#include "expected.h"
#include "rust-macro-invoc-lexer.h"
#include "rust/ast/rust-expr.h"
#include "system.h"
namespace Rust {

enum InlineAsmParseError
{
  // Enum for InlineAsmParseError

  // Currently with two error, COMMITTED AND NONCOMMITTED (to a token),
  // which directs the parser to either bubbles the error up, or keep on going
  // (vertical or horizontal)

  // COMMITTED can be use as a way for parser to bubble up
  // after it has exhausted its search space despite it not having committed to
  // any token

  COMMITTED,
  NONCOMMITED,
};
class InlineAsmContext
{
public:
  bool allow_templates;
  bool is_explicit;
  bool consumed_comma_without_formatted_string;
  AST::InlineAsm &inline_asm;
  Parser<MacroInvocLexer> &parser;
  int last_token_id;

  InlineAsmContext (AST::InlineAsm &inline_asm, Parser<MacroInvocLexer> &parser,
		    int last_token_id)
    : allow_templates (true), is_explicit (false),
      consumed_comma_without_formatted_string (false), inline_asm (inline_asm),
      parser (parser), last_token_id (last_token_id)
  {}

  InlineAsmContext (const InlineAsmContext &inline_asm_ctx)
    : allow_templates (inline_asm_ctx.allow_templates),
      is_explicit (inline_asm_ctx.is_explicit),
      consumed_comma_without_formatted_string (false),
      inline_asm (inline_asm_ctx.inline_asm), parser (inline_asm_ctx.parser),
      last_token_id (inline_asm_ctx.last_token_id)
  {}
  // explicit InlineAsmContext (InlineAsmContext&& inline_asm_ctx)
  //   : allow_templates (inline_asm_ctx.allow_templates), is_explicit
  //   (inline_asm_ctx.is_explicit),
  //     consumed_comma_without_formatted_string (false), inline_asm
  //     (inline_asm_ctx.inline_asm), parser (inline_asm_ctx.parser),
  //     last_token_id (inline_asm_ctx.last_token_id)
  // {}

  // InlineAsmContext(tl::expected<InlineAsmContext, InlineAsmParseError>
  // &expected)
  //     : allow_templates(expected->allow_templates),
  //     is_explicit(expected->is_explicit),
  //       consumed_comma_without_formatted_string(expected->consumed_comma_without_formatted_string),
  //       inline_asm(expected->inline_asm), parser(expected->parser),
  //       last_token_id(expected->last_token_id)
  // {

  // }
  InlineAsmContext &operator= (const InlineAsmContext &inline_asm_ctx)
  {
    allow_templates = inline_asm_ctx.allow_templates;
    is_explicit = inline_asm_ctx.is_explicit;
    consumed_comma_without_formatted_string = false;
    last_token_id = inline_asm_ctx.last_token_id;
    return *this;
  }

  bool is_global_asm () { return inline_asm.is_global_asm; }

  bool allows_templates () { return allow_templates; }

  void set_allow_templates (bool allow_templates)
  {
    this->allow_templates = allow_templates;
  }
};
WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
expand_inline_asm_strings (InlineAsmContext inline_asm_ctx);

// Expected calls
WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
validate (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_asm_arg (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_format_strings (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_clobber_abi (InlineAsmContext inline_asm_ctx);

// From rustc
WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_in (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_out (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_lateout (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_inout (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_inlateout (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_const (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_sym (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx);

WARN_UNUSED_RESULT
tl::optional<AST::Fragment> parse_asm (location_t invoc_locus,
				       AST::MacroInvocData &invoc,
				       AST::InvocKind semicolon,
				       AST::AsmKind is_global_asm);

WARN_UNUSED_RESULT
bool check_identifier (Parser<MacroInvocLexer> &parser, std::string ident);

void check_and_set (InlineAsmContext &inline_asm_ctx,
		    AST::InlineAsm::Option option);

// From rustc
WARN_UNUSED_RESULT
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_options (InlineAsmContext &inline_asm_ctx);

// From rustc
WARN_UNUSED_RESULT
tl::optional<AST::InlineAsmRegOrRegClass>
parse_reg (InlineAsmContext &inline_asm_ctx);

WARN_UNUSED_RESULT
tl::optional<std::string>
parse_format_string (InlineAsmContext &inline_asm_ctx);

WARN_UNUSED_RESULT
tl::optional<std::string> parse_label (Parser<MacroInvocLexer> &parser,
				       TokenId last_token_id,
				       InlineAsmContext &inline_asm_ctx);

// LLVM ASM bits

class LlvmAsmContext
{
public:
  AST::LlvmInlineAsm &llvm_asm;
  Parser<MacroInvocLexer> &parser;
  int last_token_id;

public:
  LlvmAsmContext (AST::LlvmInlineAsm &llvm_asm, Parser<MacroInvocLexer> &parser,
		  int last_token_id)
    : llvm_asm (llvm_asm), parser (parser), last_token_id (last_token_id)
  {}
};

void parse_llvm_outputs (LlvmAsmContext &ctx);

void parse_llvm_inputs (LlvmAsmContext &ctx);

void parse_llvm_clobbers (LlvmAsmContext &ctx);

void parse_llvm_options (LlvmAsmContext &ctx);

WARN_UNUSED_RESULT tl::optional<AST::Fragment>
parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
		AST::InvocKind semicolon, AST::AsmKind is_global_asm);

} // namespace Rust
