// 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->value_list()) {
      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
