// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "mpact/sim/decoder/proto_format_visitor.h"

#include <unistd.h>

#include <cctype>
#include <cstdint>
#include <fstream>
#include <functional>
#include <iostream>
#include <istream>
#include <memory>
#include <string>
#include <string_view>
#include <vector>

#include "absl/container/flat_hash_set.h"
#include "absl/functional/bind_front.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "antlr4-runtime/ParserRuleContext.h"
#include "mpact/sim/decoder/decoder_error_listener.h"
#include "mpact/sim/decoder/format_name.h"
#include "mpact/sim/decoder/proto_constraint_expression.h"
#include "mpact/sim/decoder/proto_encoding_info.h"
#include "mpact/sim/decoder/proto_format_contexts.h"
#include "mpact/sim/decoder/proto_instruction_decoder.h"
#include "mpact/sim/decoder/proto_instruction_encoding.h"
#include "mpact/sim/decoder/proto_instruction_group.h"
#include "re2/re2.h"
#include "src/google/protobuf/compiler/importer.h"
#include "src/google/protobuf/descriptor.h"

namespace mpact {
namespace sim {
namespace decoder {
namespace proto_fmt {

using ::mpact::sim::machine_description::instruction_set::ToHeaderGuard;

namespace {

std::string StripQuotes(const std::string &str) {
  return str.substr(1, str.length() - 2);
}

}  // namespace

// Error collector for .proto file parsing.
class MultiFileErrorCollector
    : public google::protobuf::compiler::MultiFileErrorCollector {
 public:
  MultiFileErrorCollector() {}
  MultiFileErrorCollector(const MultiFileErrorCollector &) = delete;
  MultiFileErrorCollector &operator=(const MultiFileErrorCollector &) = delete;

  void RecordError(absl::string_view filename, int line, int column,
                   absl::string_view message) override {
    LOG(ERROR) << absl::StrCat("Line ", line, " Column ", column, ": ", message,
                               "\n");
    absl::StrAppend(&error_, "Line ", line, " Column ", column, ": ", message,
                    "\n");
  }
  const std::string &GetError() const { return error_; }

 private:
  std::string error_;
};

// Main public method. This is called to parse a descriptor file and generate
// C++ code to decode protobuf encoded instructions.
// Parameters:
//   file_names: vector of source file names.
//   decoder_name: the decoder for which to generate code.
//   prefix: if non-empty, the prefix used in the generated file names.
//   include_roots: vector of directories from which to resolve include files.
//   proto_dirs: vector of directories from which to resolve proto files.
//   proto_files: vector of .proto files to import.
//   directory: target directory to generate the C++ files in.
absl::Status ProtoFormatVisitor::Process(
    const std::vector<std::string> &file_names, const std::string &decoder_name,
    std::string_view prefix, const std::vector<std::string> &include_roots,
    const std::vector<std::string> &proto_dirs,
    const std::vector<std::string> &proto_files, std::string_view directory) {
  decoder_name_ = decoder_name;

  include_dir_vec_.push_back(".");
  for (const auto &root : include_roots) {
    include_dir_vec_.push_back(root);
  }

  std::istream *source_stream = &std::cin;

  if (!file_names.empty()) {
    source_stream = new std::fstream(file_names[0], std::fstream::in);
  }

  // Create an antlr4 stream from the input stream.
  ProtoFmtAntlrParserWrapper parser_wrapper(source_stream);

  // Create and add the error listener.
  set_error_listener(std::make_unique<decoder::DecoderErrorListener>());
  error_listener_->set_file_name(file_names[0]);
  parser_wrapper.parser()->removeErrorListeners();
  parser_wrapper.parser()->addErrorListener(error_listener());

  // Initialize the proto source tree with the proto directories to resolve
  // proto files from.
  google::protobuf::compiler::DiskSourceTree source_tree;
  source_tree.MapPath("", "./");
  for (auto const &proto_dir : proto_dirs) {
    source_tree.MapPath("", proto_dir);
  }
  // Import the proto files.
  MultiFileErrorCollector proto_error_collector;
  google::protobuf::compiler::Importer importer(&source_tree,
                                                &proto_error_collector);
  for (auto const &proto_file : proto_files) {
    auto *file_desc = importer.Import(proto_file);
    if (file_desc == nullptr) {
      error_listener()->semanticError(
          nullptr, absl::StrCat("Failed to import '", proto_file, "'"));
      continue;
    }
    file_descriptor_map_.emplace(proto_file, file_desc);
  }
  // If there have been any errors, terminate.
  if (!proto_error_collector.GetError().empty()) {
    return absl::InternalError(proto_error_collector.GetError());
  }
  if (error_listener()->HasError()) {
    return absl::InternalError("Errors encountered - terminating.");
  }

  descriptor_pool_ = importer.pool();
  // Set the finder function objects.
  field_finder_ = absl::bind_front(
      &google::protobuf::DescriptorPool::FindFieldByName, descriptor_pool_);
  message_finder_ =
      absl::bind_front(&google::protobuf::DescriptorPool::FindMessageTypeByName,
                       descriptor_pool_);
  enum_type_finder_ = absl::bind_front(
      &google::protobuf::DescriptorPool::FindEnumTypeByName, descriptor_pool_);
  enum_value_finder_ = absl::bind_front(
      &google::protobuf::DescriptorPool::FindEnumValueByName, descriptor_pool_);

  // Parse the file and then create the data structures.
  TopLevelCtx *top_level = parser_wrapper.parser()->top_level();
  (void)top_level;
  if (!file_names.empty()) {
    delete source_stream;
    source_stream = nullptr;
  }

  if (error_listener_->HasError() > 0) {
    return absl::InternalError("Errors encountered - terminating.");
  }

  // Visit the parse tree.
  PreProcessDeclarations(top_level->declaration());
  // Process additional source files.
  for (int i = 1; i < file_names.size(); ++i) {
    ParseIncludeFile(top_level, file_names[i], {});
  }

  // Process the parse tree.
  auto encoding_info = ProcessTopLevel(decoder_name);
  // Include files may generate additional syntax errors.
  if (encoding_info == nullptr) {
    LOG(ERROR) << "No encoding specified";
    return absl::InternalError("No encoding specified");
  }
  if (error_listener_->HasError() > 0) {
    return absl::InternalError("Errors encountered - terminating.");
  }

  // Generate the decoder.
  auto [h_decoder, cc_decoder] = encoding_info->GenerateDecoderClass();

  // Terminate if there were errors.
  if (error_listener_->HasError() > 0) {
    return absl::InternalError("Errors encountered - terminating.");
  }
  // Create file names for the output files.
  std::string file_prefix(prefix);
  if (file_prefix.empty()) {
    // If there is no prefix specified, use the decoder name in snake case.
    file_prefix = mpact::sim::machine_description::instruction_set::ToSnakeCase(
        decoder_name);
  }
  std::string dot_h_name = absl::StrCat(file_prefix, "_proto_decoder.h");
  std::string dot_cc_name = absl::StrCat(file_prefix, "_proto_decoder.cc");
  // Create output streams for .h and .cc files.
  std::ofstream dot_h_file(absl::StrCat(directory, "/", dot_h_name));
  std::ofstream dot_cc_file(absl::StrCat(directory, "/", dot_cc_name));
  // Output the decoder with header guards inserted in the .h file.
  std::string header_guard_name = ToHeaderGuard(dot_h_name);
  dot_h_file << "#ifndef " << header_guard_name << "\n";
  dot_h_file << "#define " << header_guard_name << "\n\n";
  dot_h_file << h_decoder;
  dot_h_file << "\n#endif  // " << header_guard_name << "\n";
  dot_cc_file << absl::StrCat("#include \"", dot_h_name, "\"\n\n");
  dot_cc_file << cc_decoder;
  // Close files.
  dot_h_file.close();
  dot_cc_file.close();
  return absl::OkStatus();
}

// Check the using declarations map, and expand the name if it matches.
std::string ProtoFormatVisitor::Expand(std::string_view name) const {
  // The name might be a qualified name, in which case we only expand the
  // first part.
  std::string prefix(name);
  auto pos = name.find_first_of('.');
  std::string remainder;
  // If the name is qualified, try expanding the first part only.
  if (pos != std::string::npos) {
    remainder = name.substr(pos);
    prefix = prefix.substr(0, pos);
  }
  auto iter = using_decl_map_.find(prefix);
  if (iter == using_decl_map_.end()) return std::string(name);
  return iter->second + remainder;
}

// Helper templated function used to find proto objects by name.
template <typename T>
const T *ProtoFormatVisitor::FindByName(
    const std::string &name, const std::string &message_name,
    std::function<const T *(const std::string &)> finder) const {
  auto *object = finder(Expand(message_name + "." + name));
  if (object != nullptr) return object;
  object = finder(Expand(name));
  return object;
}

const google::protobuf::FieldDescriptor *ProtoFormatVisitor::GetField(
    const std::string &field_name,
    const google::protobuf::Descriptor *message_type,
    std::vector<const google::protobuf::FieldDescriptor *> &one_of_fields)
    const {
  auto pos = field_name.find_first_of('.');
  // If this is a "leaf" field, find it and return if found.
  if (pos == std::string::npos) {
    auto *field_desc = message_type->FindFieldByName(field_name);
    if (field_desc->containing_oneof() != nullptr) {
      one_of_fields.push_back(field_desc);
    }
    return field_desc;
  }
  // Recursively traverse the components of the field name.
  std::string field = field_name.substr(0, pos);
  std::string remainder = field_name.substr(pos + 1);
  auto const *field_desc = message_type->FindFieldByName(field);
  if (field_desc == nullptr) return nullptr;
  if (field_desc->containing_oneof() != nullptr) {
    one_of_fields.push_back(field_desc);
  }
  auto const *message_desc = field_desc->message_type();
  if (message_desc == nullptr) return nullptr;
  return GetField(remainder, message_desc, one_of_fields);
}

const google::protobuf::EnumValueDescriptor *
ProtoFormatVisitor::GetEnumValueDescriptor(const std::string &full_name) const {
  std::string expanded = Expand(full_name);
  auto pos = expanded.find_last_of('.');
  // If this is a "leaf", it fails. The enum must be qualified by enum type.
  if (pos == std::string::npos) {
    return nullptr;
  }
  std::string enum_name = expanded.substr(pos + 1);
  std::string enum_type_name = expanded.substr(0, pos);
  // Find the enum type.
  auto const *enum_type_desc =
      descriptor_pool_->FindEnumTypeByName(enum_type_name);
  if (enum_type_desc == nullptr) return nullptr;
  // Find the enum value in the enum type.
  auto const *enum_value_desc = enum_type_desc->FindValueByName(enum_name);
  return enum_value_desc;
}

absl::StatusOr<int> ProtoFormatVisitor::GetEnumValue(
    const std::string &enum_name) const {
  auto *enum_value_desc = GetEnumValueDescriptor(enum_name);
  if (enum_value_desc == nullptr) {
    return absl::NotFoundError(
        absl::StrCat("Enum '", enum_name, "' not found"));
  }
  return enum_value_desc->number();
}

void ProtoFormatVisitor::PreProcessDeclarations(
    const std::vector<DeclarationCtx *> &declarations) {
  std::vector<IncludeFileCtx *> include_files;
  for (auto *declaration : declarations) {
    // Create map from instruction group name to instruction group ctx. That
    // way we can visit those that are referenced by the decoder definition
    // later.
    if (declaration->instruction_group_def() != nullptr) {
      auto group_def = declaration->instruction_group_def();
      auto name = group_def->name->getText();
      auto iter = group_decl_map_.find(name);
      if (iter != group_decl_map_.end()) {
        error_listener()->semanticError(
            group_def->start,
            absl::StrCat(
                "Multiple definitions of instruction group '", name,
                "' first defined at line: ", iter->second->start->getLine()));
        continue;
      }
      group_decl_map_.emplace(name, group_def);
      continue;
    }
    // Visit all the 'using' declarations so they can be used to resolve
    // proto message and field references later.
    if (declaration->using_alias() != nullptr) {
      std::string alias;
      std::string name =
          declaration->using_alias()->qualified_ident()->getText();
      if (declaration->using_alias()->IDENT() != nullptr) {
        alias = declaration->using_alias()->IDENT()->getText();
      } else {
        auto pos = name.find_last_of('.');
        if (pos != std::string::npos) {
          alias = name.substr(pos + 1);
        } else {
          alias = name;
        }
      }
      if (using_decl_map_.find(name) != using_decl_map_.end()) {
        error_listener()->semanticError(
            declaration->start, absl::StrCat("Redefinition of '", name, "'"));
      }
      using_decl_map_.emplace(alias, name);
      continue;
    }
    // Create a map from decoder definitions to their parse contexts.
    if (declaration->decoder_def() != nullptr) {
      auto *decoder = declaration->decoder_def();
      auto name = decoder->name->getText();
      auto iter = decoder_decl_map_.find(name);
      if (iter != decoder_decl_map_.end()) {
        error_listener()->semanticError(
            decoder->start, absl::StrCat("Multiple definitions of decoder '",
                                         name, "' first defined at line: ",
                                         iter->second->start->getLine()));
        continue;
      }
      decoder_decl_map_.emplace(name, decoder);
      continue;
    }
    // Capture include files.
    include_files.push_back(declaration->include_file());
  }
  // Visit all the include files captured above.
  for (auto *include_file_ctx : include_files) {
    VisitIncludeFile(include_file_ctx);
  }
}

void ProtoFormatVisitor::VisitIncludeFile(IncludeFileCtx *ctx) {
  // The literal includes the double quotes.
  std::string literal = ctx->STRING_LITERAL()->getText();
  // Remove the double quotes from the literal and construct the full file name.
  std::string file_name = literal.substr(1, literal.length() - 2);
  // Check for recursive include by comparing the current name to those on the
  // current include file stack.
  for (auto const &name : include_file_stack_) {
    if (name == file_name) {
      error_listener()->semanticError(
          ctx->start,
          absl::StrCat(": ", "Recursive include of '", file_name, "'"));
      return;
    }
  }
  ParseIncludeFile(ctx, file_name, include_dir_vec_);
}

void ProtoFormatVisitor::ParseIncludeFile(
    antlr4::ParserRuleContext *ctx, const std::string &file_name,
    const std::vector<std::string> &dirs) {
  std::fstream include_file;
  // Open include file.
  include_file.open(file_name, std::fstream::in);
  if (!include_file.is_open()) {
    // Try each of the include file directories.
    for (auto const &dir : dirs) {
      std::string include_name = absl::StrCat(dir, "/", file_name);
      include_file.open(include_name, std::fstream::in);
      if (include_file.is_open()) break;
    }
    if (!include_file.is_open()) {
      // Try a local file.
      include_file.open(file_name, std::fstream::in);
      if (!include_file.is_open()) {
        error_listener()->semanticError(
            ctx->start, absl::StrCat("Failed to open '", file_name, "'"));
        return;
      }
    }
  }
  std::string previous_file_name = error_listener()->file_name();
  error_listener()->set_file_name(std::string(file_name));
  auto *include_parser = new ProtoFmtAntlrParserWrapper(&include_file);
  // We need to save the parser state so it's available for analysis after
  // we are done with building the parse trees.
  antlr_parser_wrappers_.push_back(include_parser);
  // Add the error listener.
  include_parser->parser()->removeErrorListeners();
  include_parser->parser()->addErrorListener(error_listener());
  // Start parsing at the top_level rule.
  auto declaration_vec = include_parser->parser()->top_level()->declaration();
  include_file.close();
  error_listener()->set_file_name(previous_file_name);
  if (error_listener()->syntax_error_count() > 0) {
    return;
  }
  include_file_stack_.emplace_back(file_name);
  // Process the declarations.
  PreProcessDeclarations(include_parser->parser()->top_level()->declaration());
  include_file_stack_.pop_back();
}

std::unique_ptr<ProtoEncodingInfo> ProtoFormatVisitor::ProcessTopLevel(
    const std::string &decoder_name) {
  // Look up the decoder declaration that matches the decoder name for which
  // to generate C++ code.
  auto decoder_iter = decoder_decl_map_.find(decoder_name);
  if (decoder_iter == decoder_decl_map_.end()) {
    error_listener()->semanticError(
        nullptr, absl::StrCat("Decoder '", decoder_name, "' not declared"));
    return nullptr;
  }
  auto proto_encoding_info = VisitDecoderDef(decoder_iter->second);
  return proto_encoding_info;
}

// Process instruction groups.
ProtoInstructionGroup *ProtoFormatVisitor::VisitInstructionGroupDef(
    InstructionGroupDefCtx *ctx, ProtoEncodingInfo *encoding_info) {
  if (ctx == nullptr) return nullptr;

  std::string group_name = ctx->name->getText();
  // Verify that the message type exists.
  std::string message_name = Expand(ctx->message_name->getText());
  auto const *message_desc =
      descriptor_pool_->FindMessageTypeByName(message_name);
  // If the message type doesn't exist, its an error
  if (message_desc == nullptr) {
    error_listener_->semanticError(
        ctx->start,
        absl::StrCat("Undefined proto message type: '", message_name, "'"));
    return nullptr;
  }
  // Create the named instruction group.
  auto inst_group_res =
      encoding_info->AddInstructionGroup(group_name, message_desc);
  if (!inst_group_res.ok()) {
    error_listener_->semanticError(ctx->start,
                                   inst_group_res.status().message());
    return nullptr;
  }

  auto *inst_group = inst_group_res.value();
  // First visit all the setter declarations.
  for (auto *group_def : ctx->setter_group_def()) {
    VisitSetterGroupDef(group_def, inst_group, encoding_info);
  }
  // Parse the instruction encoding definitions in the instruction group.
  for (auto *inst_def : ctx->instruction_def()) {
    VisitInstructionDef(inst_def, inst_group, encoding_info);
  }
  return inst_group;
}

// Process instruction definitions.
void ProtoFormatVisitor::VisitInstructionDef(InstructionDefCtx *ctx,
                                             ProtoInstructionGroup *inst_group,
                                             ProtoEncodingInfo *encoding_info) {
  if (ctx == nullptr) return;

  // If it is a generator, call the generator parsing function.
  if (ctx->generate != nullptr) {
    ProcessInstructionDefGenerator(ctx, inst_group, encoding_info);
    return;
  }
  // Get the instruction name.
  std::string name = ctx->name->getText();
  auto *inst_encoding = inst_group->AddInstructionEncoding(name);
  // Add Constraints to the instruction encoding.
  for (auto *constraint : ctx->field_constraint_list()->field_constraint()) {
    VisitFieldConstraint(constraint, inst_encoding, inst_group);
  }
  // Visit references to setters defined in the instruction group.
  for (auto *setter : ctx->setter_ref()) {
    VisitSetterRef(setter, inst_encoding, inst_group, encoding_info);
  }
  // Visit locally (to the instruction) defined setters.
  for (auto *setter : ctx->setter_def()) {
    VisitSetterDef(setter, inst_encoding, inst_group, encoding_info);
  }
  // Generate the setter code template.
  inst_encoding->GenerateSetterCode();
}

void ProtoFormatVisitor::VisitFieldConstraint(
    FieldConstraintCtx *ctx, ProtoInstructionEncoding *inst_encoding,
    const ProtoInstructionGroup *inst_group) {
  if (ctx == nullptr) return;

  // Constraints are based on field names ==/!=/>/>=/</<= to a value, or
  // HAS(field_name) to indicate mandated presence of submessage field_name. The
  // value may be an enumeration, so will have to check for that too.
  // TODO(torerik): In the future, enable expressions on the right hand side.

  absl::Status status;
  if (ctx->HAS() != nullptr) {
    std::string field_name = ctx->qualified_ident()->getText();
    std::vector<const google::protobuf::FieldDescriptor *> one_of_fields;
    auto *field_desc =
        GetField(field_name, inst_group->message_type(), one_of_fields);
    if (field_desc == nullptr) {
      error_listener()->semanticError(
          ctx->start,
          absl::StrCat("Field '", field_name, "' not found in message '",
                       inst_group->message_type()->name(), "'"));
      return;
    }
    // If the last field in one_of_fields is the field with the kHas constraint
    // remove that field from the vector, as it will be handled in the
    // constraint.
    if (field_desc == one_of_fields.back()) {
      one_of_fields.pop_back();
    }
    status = inst_encoding->AddConstraint(ctx, ConstraintType::kHas, field_desc,
                                          one_of_fields, nullptr);
  } else {
    // The field name is relative to the message type, but may refer to fields
    // in sub-messages contained within that message.
    std::string field_name = ctx->field->getText();
    std::vector<const google::protobuf::FieldDescriptor *> one_of_fields;
    auto *field_desc =
        GetField(field_name, inst_group->message_type(), one_of_fields);
    if (field_desc == nullptr) {
      error_listener()->semanticError(
          ctx->start,
          absl::StrCat("Field '", field_name, "' not found in message '",
                       inst_group->message_type()->name(), "'"));
      return;
    }
    std::string op = ctx->constraint_op()->getText();

    auto *constraint_expr = VisitConstraintExpression(ctx->constraint_expr(),
                                                      field_desc, inst_group);

    // Add the constraint according to the type.
    if (op == "==") {
      status = inst_encoding->AddConstraint(
          ctx, ConstraintType::kEq, field_desc, one_of_fields, constraint_expr);
    } else if (op == "!=") {
      status = inst_encoding->AddConstraint(
          ctx, ConstraintType::kNe, field_desc, one_of_fields, constraint_expr);
    } else if (op == ">") {
      status = inst_encoding->AddConstraint(
          ctx, ConstraintType::kGt, field_desc, one_of_fields, constraint_expr);
    } else if (op == ">=") {
      status = inst_encoding->AddConstraint(
          ctx, ConstraintType::kGe, field_desc, one_of_fields, constraint_expr);
    } else if (op == "<") {
      status = inst_encoding->AddConstraint(
          ctx, ConstraintType::kLt, field_desc, one_of_fields, constraint_expr);
    } else if (op == "<=") {
      status = inst_encoding->AddConstraint(
          ctx, ConstraintType::kLe, field_desc, one_of_fields, constraint_expr);
    }
  }
  if (!status.ok()) {
    error_listener()->semanticError(ctx->start, status.message());
  }
}

ProtoConstraintExpression *ProtoFormatVisitor::VisitConstraintExpression(
    ConstraintExprCtx *ctx, const google::protobuf::FieldDescriptor *field_desc,
    const ProtoInstructionGroup *inst_group) {
  if (ctx == nullptr) return nullptr;
  ProtoConstraintExpression *constraint_expr = nullptr;
  if (ctx->value() != nullptr) {
    constraint_expr = VisitValue(ctx->value());
  } else if (ctx->qualified_ident() != nullptr) {
    constraint_expr =
        VisitQualifiedIdent(ctx->qualified_ident(), field_desc, inst_group);
  }
  return constraint_expr;
}

ProtoConstraintExpression *ProtoFormatVisitor::VisitValue(ValueCtx *ctx) {
  if (ctx == nullptr) return nullptr;
  if (ctx->number() != nullptr) {
    return VisitNumber(ctx->number());
  }
  if (ctx->bool_value()) {
    bool value;
    if (!absl::SimpleAtob(ctx->bool_value()->getText(), &value)) {
      error_listener()->semanticError(ctx->start, "Invalid boolean literal");
      return nullptr;
    }
    return new ProtoConstraintValueExpression(value);
  }
  return new ProtoConstraintValueExpression(
      StripQuotes(ctx->string->getText()));
  return nullptr;
}

ProtoConstraintExpression *ProtoFormatVisitor::VisitNumber(NumberCtx *ctx) {
  std::string num_str = ctx->getText();
  // Convert to lower case to avoid capital chars in suffix.
  for (int i = 0; i < num_str.size(); ++i) num_str[i] = tolower(num_str[i]);
  bool is_signed = !absl::StrContains(num_str, "u");
  bool is_long_long = absl::StrContains(num_str, "ll");
  bool is_long = !is_long_long && absl::StrContains(num_str, "l");
  bool is_hex = num_str.substr(0, 2) == "0x";
  // If neither 'l' nor 'll' is specified, try using the 32 bit wide integer if
  // the value fits, otherwise use 64 bit.
  if (is_signed) {  // Either int32 or int64
    int32_t int32_val;
    int64_t int64_val;
    if (is_hex) {
      if (!is_long && !is_long_long &&
          absl::SimpleHexAtoi(num_str, &int32_val)) {
        return new ProtoConstraintValueExpression(int32_val);
      } else if (absl::SimpleHexAtoi(num_str, &int64_val)) {
        return new ProtoConstraintValueExpression(int64_val);
      } else {
        error_listener()->semanticError(ctx->start, "Invalid number literal");
        return nullptr;
      }
    } else {
      if (!is_long && !is_long_long && absl::SimpleAtoi(num_str, &int32_val)) {
        return new ProtoConstraintValueExpression(int32_val);
      } else if (absl::SimpleAtoi(num_str, &int64_val)) {
        return new ProtoConstraintValueExpression(int64_val);
      } else {
        error_listener()->semanticError(ctx->start, "Invalid number literal");
        return nullptr;
      }
    }
  } else {  // Either uint32 or uint64
    uint32_t uint32_val;
    uint64_t uint64_val;
    if (is_hex) {
      if (!is_long && !is_long_long &&
          absl::SimpleHexAtoi(num_str, &uint32_val)) {
        return new ProtoConstraintValueExpression(uint32_val);
      } else if (absl::SimpleHexAtoi(num_str, &uint64_val)) {
        return new ProtoConstraintValueExpression(uint64_val);
      } else {
        error_listener()->semanticError(ctx->start, "Invalid number literal");
        return nullptr;
      }
    } else {
      if (!is_long && !is_long_long && absl::SimpleAtoi(num_str, &uint32_val)) {
        return new ProtoConstraintValueExpression(uint32_val);
      } else if (absl::SimpleAtoi(num_str, &uint64_val)) {
        return new ProtoConstraintValueExpression(uint64_val);
      } else {
        error_listener()->semanticError(ctx->start, "Invalid number literal");
        return nullptr;
      }
    }
  }
}

// Visits a qualified identifier that specifies an enumerator value.
ProtoConstraintExpression *ProtoFormatVisitor::VisitQualifiedIdent(
    QualifiedIdentCtx *ctx, const google::protobuf::FieldDescriptor *field_desc,
    const ProtoInstructionGroup *inst_group) {
  if (ctx == nullptr) return nullptr;
  // Verify that the field is an enum.
  if (field_desc->enum_type() == nullptr) {
    error_listener()->semanticError(
        ctx->start,
        absl::StrCat("Field '", field_desc->name(), "' is not enum type"));
    return nullptr;
  }
  // Look up the value (if it exists).
  auto const *enum_value_desc =
      field_desc->enum_type()->FindValueByName(ctx->getText());
  if (enum_value_desc == nullptr) {
    error_listener()->semanticError(
        ctx->start,
        absl::StrCat("Enum value not found: '", ctx->getText(), "'"));
    return nullptr;
  }
  return new ProtoConstraintEnumExpression(enum_value_desc);
}

// Process the instruction group setters.
void ProtoFormatVisitor::VisitSetterGroupDef(SetterGroupDefCtx *ctx,
                                             ProtoInstructionGroup *inst_group,
                                             ProtoEncodingInfo *encoding_info) {
  if (ctx == nullptr) return;
  auto group_name = ctx->name->getText();
  for (auto *setter_def : ctx->setter_def()) {
    std::string name = setter_def->name->getText();
    std::string field_name = setter_def->qualified_ident()->getText();
    std::vector<const google::protobuf::FieldDescriptor *> one_of_fields;
    auto const *field_desc =
        GetField(field_name, inst_group->message_type(), one_of_fields);
    if (field_desc == nullptr) {
      error_listener()->semanticError(
          setter_def->start,
          absl::StrCat("Field '", field_name, "' not found in message '",
                       inst_group->message_type()->name(), "'"));
      return;
    }

    IfNotCtx *if_not = setter_def->if_not();
    auto status = encoding_info->CheckSetterType(name, field_desc);
    if (!status.ok()) {
      error_listener()->semanticError(setter_def->start, status.message());
      return;
    }
    status = inst_group->AddSetter(group_name, setter_def, name, field_desc,
                                   one_of_fields, if_not);
    if (!status.ok()) {
      error_listener()->semanticError(setter_def->start, status.message());
      return;
    }
  }
}

// Process local (to instruction) setters.
void ProtoFormatVisitor::VisitSetterDef(SetterDefCtx *ctx,
                                        ProtoInstructionEncoding *inst_encoding,
                                        ProtoInstructionGroup *inst_group,
                                        ProtoEncodingInfo *encoding_info) {
  if (ctx == nullptr) return;
  std::string name = ctx->name->getText();
  std::string field_name = ctx->qualified_ident()->getText();
  std::vector<const google::protobuf::FieldDescriptor *> one_of_fields;
  auto const *field_desc =
      GetField(field_name, inst_group->message_type(), one_of_fields);
  if (field_desc == nullptr) {
    error_listener()->semanticError(
        ctx->start,
        absl::StrCat("Field '", field_name, "' not found in message '",
                     inst_group->message_type()->name(), "'"));
    return;
  }

  IfNotCtx *if_not = ctx->if_not();
  auto status = encoding_info->CheckSetterType(name, field_desc);
  if (!status.ok()) {
    error_listener()->semanticError(ctx->start, status.message());
    return;
  }
  status =
      inst_encoding->AddSetter(ctx, name, field_desc, one_of_fields, if_not);
  if (!status.ok()) {
    error_listener()->semanticError(ctx->start, status.message());
    return;
  }
}

// Process references to instruction group setters.
void ProtoFormatVisitor::VisitSetterRef(SetterRefCtx *ctx,
                                        ProtoInstructionEncoding *inst_encoding,
                                        ProtoInstructionGroup *inst_group,
                                        ProtoEncodingInfo *encoding_info) {
  if (ctx == nullptr) return;
  auto res = inst_group->GetSetterGroup(ctx->name->getText());
  if (!res.ok()) {
    error_listener()->semanticError(ctx->start, res.status().message());
    return;
  }
  auto [iter, end] = res.value();
  while (iter != end) {
    auto *setter_info = iter->second;
    auto status = inst_encoding->AddSetter(
        setter_info->ctx, setter_info->name, setter_info->field_desc,
        setter_info->one_of_fields, setter_info->if_not);
    if (!status.ok()) {
      error_listener()->semanticError(setter_info->ctx->start,
                                      status.message());
      return;
    }
    iter++;
  }
}

// Process the instruction definition generators.
void ProtoFormatVisitor::ProcessInstructionDefGenerator(
    InstructionDefCtx *ctx, ProtoInstructionGroup *inst_group,
    ProtoEncodingInfo *encoding_info) {
  if (ctx == nullptr) return;
  absl::flat_hash_set<std::string> range_variable_names;
  std::vector<RangeAssignmentInfo *> range_info_vec;

  // Process range assignment lists. The range assignment is either a single
  // value or a structured binding assignment. If it's a binding assignment we
  // need to make sure each tuple has the same number of values as there are
  // idents to assign them to.
  for (auto *assign_ctx : ctx->range_assignment()) {
    auto *range_info = new RangeAssignmentInfo();
    range_info_vec.push_back(range_info);
    for (auto *ident_ctx : assign_ctx->IDENT()) {
      std::string name = ident_ctx->getText();
      if (range_variable_names.contains(name)) {
        error_listener()->semanticError(
            assign_ctx->start,
            absl::StrCat("Duplicate binding variable name '", name, "'"));
        continue;
      }
      range_variable_names.insert(name);
      range_info->range_names.push_back(ident_ctx->getText());
      range_info->range_values.push_back({});
      range_info->range_regexes.emplace_back(
          absl::StrCat("\\$\\(", name, "\\)"));
      // Verify that the range variable is used in the string.
      if (!RE2::PartialMatch(ctx->generator_instruction_def_list()->getText(),
                             range_info->range_regexes.back())) {
        error_listener()->semanticWarning(
            assign_ctx->start,
            absl::StrCat("Unreferenced binding variable '", name, "'."));
      }
    }
    // See if it's a list of simple values.
    if (!assign_ctx->gen_value().empty()) {
      for (auto *gen_value_ctx : assign_ctx->gen_value()) {
        if (gen_value_ctx->IDENT() != nullptr) {
          range_info->range_values[0].push_back(
              gen_value_ctx->IDENT()->getText());
        } else if ((gen_value_ctx->value() != nullptr) &&
                   (gen_value_ctx->value()->number() != nullptr)) {
          range_info->range_values[0].push_back(
              gen_value_ctx->value()->number()->getText());
        } else if ((gen_value_ctx->value() != nullptr) &&
                   (gen_value_ctx->value()->bool_value() != nullptr)) {
          range_info->range_values[0].push_back(
              gen_value_ctx->value()->bool_value()->getText());
        } else {
          // Strip off double quotes.
          std::string value = gen_value_ctx->value()->string->getText();
          range_info->range_values[0].push_back(
              value.substr(1, value.size() - 2));
        }
      }
      continue;
    }
    // It's a list of tuples with a structured binding assignment.
    for (auto *tuple_ctx : assign_ctx->tuple()) {
      if (tuple_ctx->gen_value().size() != range_info->range_names.size()) {
        // Clean up.
        for (auto *info : range_info_vec) delete info;
        error_listener_->semanticError(
            assign_ctx->start,
            "Number of values differs from number of identifiers");
        return;
      }
      for (int i = 0; i < tuple_ctx->gen_value().size(); ++i) {
        if (tuple_ctx->gen_value(i)->IDENT() != nullptr) {
          range_info->range_values[i].push_back(
              tuple_ctx->gen_value(i)->IDENT()->getText());
        } else if ((tuple_ctx->gen_value(i)->value() != nullptr) &&
                   (tuple_ctx->gen_value(i)->value()->number() != nullptr)) {
          range_info->range_values[i].push_back(
              tuple_ctx->gen_value(i)->value()->number()->getText());
        } else if ((tuple_ctx->gen_value(i)->value() != nullptr) &&
                   (tuple_ctx->gen_value(i)->value()->bool_value() !=
                    nullptr)) {
          range_info->range_values[i].push_back(
              tuple_ctx->gen_value(i)->value()->bool_value()->getText());
        } else {
          // Strip off double quotes.
          std::string value =
              tuple_ctx->gen_value(i)->value()->string->getText();
          range_info->range_values[i].push_back(
              value.substr(1, value.size() - 2));
        }
      }
    }
  }
  // Check that all binding variable references are valid.
  std::string input_text = ctx->generator_instruction_def_list()->getText();
  std::string::size_type start_pos = 0;
  auto pos = input_text.find_first_of('$', start_pos);
  while (pos != std::string::npos) {
    // Skip past the '$('
    start_pos = pos + 2;
    auto end_pos = input_text.find_first_of(')', pos);
    // Extract the ident.
    auto ident = input_text.substr(start_pos, end_pos - start_pos);
    if (!range_variable_names.contains(ident)) {
      error_listener()->semanticError(
          ctx->generator_instruction_def_list()->start,
          absl::StrCat("Undefined binding variable '", ident, "'"));
    }
    start_pos = end_pos;
    pos = input_text.find_first_of('$', start_pos);
  }
  if (error_listener()->HasError()) {
    // Clean up.
    for (auto *info : range_info_vec) delete info;
    return;
  }

  // Now we need to iterate over the range_info instances and substitution
  // ranges. This will produce new text that will be parsed and processed.
  std::string generated_text =
      GenerateInstructionDefList(range_info_vec, 0, input_text);
  // Parse and process the generated text.
  auto *parser = new ProtoFmtAntlrParserWrapper(generated_text);
  antlr_parser_wrappers_.push_back(parser);
  // Parse the text starting at the opcode_spec_list rule.
  auto instruction_defs =
      parser->parser()->instruction_group_def()->instruction_def();
  // Process the opcode spec.
  for (auto *inst_def : instruction_defs) {
    VisitInstructionDef(inst_def, inst_group, encoding_info);
  }
  // Clean up.
  for (auto *info : range_info_vec) delete info;
}

std::string ProtoFormatVisitor::GenerateInstructionDefList(
    const std::vector<RangeAssignmentInfo *> &range_info_vec, int index,
    const std::string &template_str_in) const {
  std::string generated;
  // Iterate for the number of values.
  for (int i = 0; i < range_info_vec[index]->range_values[0].size(); ++i) {
    // Copy the template string.
    std::string template_str = template_str_in;
    // For each ident, perform substitutions in the template copy with the
    // current set of values.
    int var_index = 0;
    int replace_count = 0;
    for (auto &re : range_info_vec[index]->range_regexes) {
      replace_count += RE2::GlobalReplace(
          &template_str, re,
          range_info_vec[index]->range_values[var_index++][i]);
    }
    // If there are multiple range specifications, then recursively call to
    // generate the cartesian product with the values of the next value range
    // substitutions.
    if (range_info_vec.size() > index + 1) {
      absl::StrAppend(&generated, GenerateInstructionDefList(
                                      range_info_vec, index + 1, template_str));
    } else {
      absl::StrAppend(&generated, template_str);
    }
    // If there were no replacements, then the range variables weren't used,
    // and the template string won't change for any other values in the range.
    // This can happen if there range variables aren't referenced in the string.
    // Thus, break out of the loop.
    if (replace_count == 0) break;
  }
  return generated;
}

std::unique_ptr<ProtoEncodingInfo> ProtoFormatVisitor::VisitDecoderDef(
    DecoderDefCtx *ctx) {
  if (ctx == nullptr) return nullptr;

  // First get the opcode enum.
  int opcode_count = 0;
  std::string opcode_enum;
  for (auto *attr_ctx : ctx->decoder_attribute()) {
    if (attr_ctx->opcode_enum_decl() != nullptr) {
      auto opcode_enum_literal =
          attr_ctx->opcode_enum_decl()->STRING_LITERAL()->getText();
      opcode_enum =
          opcode_enum_literal.substr(1, opcode_enum_literal.size() - 2);
      if (opcode_enum.empty()) {
        error_listener_->semanticError(attr_ctx->start,
                                       "Empty opcode enum string");
      }
      if (opcode_count > 0) {
        error_listener_->semanticError(attr_ctx->start,
                                       "More than one opcode enum declaration");
      }
      opcode_count++;
    }
  }

  // Instantiate encoding info class.
  std::string name = ctx->name->getText();
  auto encoding_info =
      std::make_unique<ProtoEncodingInfo>(opcode_enum, error_listener_.get());
  auto *decoder = encoding_info->SetProtoDecoder(name);
  if (decoder == nullptr) return nullptr;
  absl::flat_hash_set<std::string> group_name_set;
  int namespace_count = 0;
  // Iterate over the decoder attributes.
  for (auto *attr_ctx : ctx->decoder_attribute()) {
    // Include files.
    if (attr_ctx->include_files() != nullptr) {
      for (auto *file_ctx : attr_ctx->include_files()->include_file()) {
        auto include_text = file_ctx->STRING_LITERAL()->getText();
        encoding_info->AddIncludeFile(include_text);
      }
      continue;
    }
    // Namespace declaration.
    if (attr_ctx->namespace_decl() != nullptr) {
      auto decl = attr_ctx->namespace_decl();
      for (auto *namespace_name : decl->namespace_ident()) {
        decoder->namespaces().push_back(namespace_name->getText());
      }
      if (namespace_count > 0) {
        error_listener_->semanticError(attr_ctx->start,
                                       "More than one namespace declaration");
      }
      namespace_count++;
      continue;
    }

    // Instruction groups are listed as either a single instruction group,
    // or a parent group that contains several individual groups.

    // If it is a single group process it here. It's a single instruction
    // group if it does not contain an ident_list.
    if ((attr_ctx->group_name() != nullptr) &&
        (attr_ctx->group_name()->ident_list() == nullptr)) {
      ProcessSingleGroup(attr_ctx, encoding_info.get(), group_name_set);
      continue;
    }

    // If it is a parent group, process it here.
    if ((attr_ctx->group_name() != nullptr) &&
        (attr_ctx->group_name()->ident_list() != nullptr)) {
      ProcessParentGroup(attr_ctx, encoding_info.get(), group_name_set);
      continue;
    }
  }
  if (group_name_set.empty()) {
    error_listener_->semanticError(ctx->start, "No instruction groups found");
  }
  return encoding_info;
}

void ProtoFormatVisitor::ProcessSingleGroup(
    DecoderAttributeCtx *attr_ctx, ProtoEncodingInfo *encoding_info,
    absl::flat_hash_set<std::string> &group_name_set) {
  if (attr_ctx == nullptr) return;
  std::string group_name = attr_ctx->group_name()->IDENT()->getText();

  // If this group has been listed already, signal an error.
  if (group_name_set.contains(group_name)) {
    error_listener_->semanticError(
        attr_ctx->start,
        absl::StrCat("Instruction group '", group_name, "' listed twice"));
    return;
  }

  auto map_iter = encoding_info->instruction_group_map().find(group_name);
  ProtoInstructionGroup *inst_group = nullptr;

  // Check if the group has been visited before. If so, no need to visit.
  if (map_iter != encoding_info->instruction_group_map().end()) {
    inst_group = map_iter->second;
  } else {
    // Check if there is a group declaration for the group name. If not,
    // signal an error for undefined group.
    auto iter = group_decl_map_.find(group_name);
    if (iter == group_decl_map_.end()) {
      error_listener_->semanticError(
          attr_ctx->start,
          absl::StrCat("No such instruction group: '", group_name, "'"));
      return;
    }
    inst_group = VisitInstructionGroupDef(iter->second, encoding_info);
  }
  // Return if there was an error visiting the instruction group.
  if (inst_group == nullptr) return;

  group_name_set.insert(group_name);
  encoding_info->decoder()->AddInstructionGroup(inst_group);
}

void ProtoFormatVisitor::ProcessParentGroup(
    DecoderAttributeCtx *attr_ctx, ProtoEncodingInfo *encoding_info,
    absl::flat_hash_set<std::string> &group_name_set) {
  if (attr_ctx == nullptr) return;
  // Check each of the child groups. Visit any that hasn't been visited
  // yet, and make sure all use the same encoding proto message.
  std::string group_name = attr_ctx->group_name()->IDENT()->getText();
  // It's an error if the instruction group as already been listed.
  if (group_name_set.contains(group_name)) {
    error_listener_->semanticError(
        attr_ctx->start, absl::StrCat("Instruction group '", group_name,
                                      "' listed twice - ignored"));
    return;
  }
  std::vector<ProtoInstructionGroup *> child_groups;
  std::string group_format_name;
  // Iterate through the list of named "child" groups to combine.
  for (auto *ident : attr_ctx->group_name()->ident_list()->IDENT()) {
    auto child_name = ident->getText();
    // Make sure the child group hasn't been listed already.
    if (group_name_set.contains(child_name)) {
      error_listener_->semanticError(
          attr_ctx->start, absl::StrCat("Instruction group listed twice: '",
                                        child_name, "' - ignored"));
      return;
    }
    ProtoInstructionGroup *child_group = nullptr;
    auto map_iter = encoding_info->instruction_group_map().find(child_name);
    if (map_iter != encoding_info->instruction_group_map().end()) {
      // The instruction group has been visited already. Make sure it
      // hasn't bin listed twice in the list of child groups.
      child_group = map_iter->second;
      bool exists = false;
      for (auto const *group : child_groups) {
        if (child_name == group->name()) {
          exists = true;
          break;
        }
      }
      if (exists) {
        error_listener_->semanticError(
            attr_ctx->start,
            absl::StrCat("Instruction group '", child_name, "' listed twice"));
        // Clean up.
        for (auto *child_group : child_groups) delete child_group;
        return;
      }
    } else {
      // The instruction group hasn't been visited yet, so look up the
      // declaration and visit it now.
      auto iter = group_decl_map_.find(child_name);
      if (iter != group_decl_map_.end()) {
        child_group = VisitInstructionGroupDef(iter->second, encoding_info);
      }
      if (child_group == nullptr) {
        error_listener_->semanticError(
            attr_ctx->start,
            absl::StrCat("Instruction group '", child_name, "' not found"));
        // Clean up.
        for (auto *child_group : child_groups) delete child_group;
        continue;
      }
    }
    // If this is the first child group, get the proto message type name.
    if (child_groups.empty()) {
      group_format_name = child_group->message_type()->name();
    }
    // Check that the child groups all use the same proto message type
    // name.
    if (group_format_name != child_group->message_type()->name()) {
      error_listener_->semanticError(
          attr_ctx->start,
          absl::StrCat("Instruction group '", child_name, "' must use format '",
                       group_format_name, ", to be merged into group '",
                       group_name, "'"));
      // Clean up.
      for (auto *child_group : child_groups) delete child_group;
      return;
    }
    child_groups.push_back(child_group);
  }

  if (child_groups.empty()) {
    error_listener_->semanticError(attr_ctx->start, "No child groups");
    // Clean up.
    for (auto *child_group : child_groups) delete child_group;
    return;
  }
  // Create the "parent" instruction group.
  const google::protobuf::Descriptor *group_format =
      message_finder_(Expand(group_format_name));
  if (group_format == nullptr) {
    error_listener_->semanticError(
        attr_ctx->start,
        absl::StrCat("Could not find proto message type '", group_format_name,
                     "' in proto descriptor pool"));
    // Clean up.
    for (auto *child_group : child_groups) delete child_group;
    return;
  }
  auto res = encoding_info->AddInstructionGroup(group_name, group_format);
  if (!res.ok()) {
    error_listener_->semanticError(attr_ctx->start, res.status().message());
    // Clean up.
    for (auto *child_group : child_groups) delete child_group;
    return;
  }
  auto parent_group = res.value();
  // For each child group, add all of it's encodings to the parent group.
  for (auto *child_group : child_groups) {
    for (auto *encoding : child_group->encodings()) {
      parent_group->CopyInstructionEncoding(
          new ProtoInstructionEncoding(*encoding));
    }
    delete child_group;
  }
  // Add the parent instruction group to the decoder.
  group_name_set.insert(parent_group->name());
  encoding_info->decoder()->AddInstructionGroup(parent_group);
}

StringPair ProtoFormatVisitor::EmitCode(ProtoEncodingInfo *encoding_info) {
  return encoding_info->GenerateDecoderClass();
}

}  // namespace proto_fmt
}  // namespace decoder
}  // namespace sim
}  // namespace mpact
