AccessPath validate_and_infer_crtex_callee_port()

in source/Frame.cpp [174:246]


AccessPath validate_and_infer_crtex_callee_port(
    const Json::Value& value,
    const AccessPath& callee_port,
    const CanonicalNameSetAbstractDomain& canonical_names,
    const RootSetAbstractDomain& via_type_of_ports) {
  mt_assert(canonical_names.is_value() && !canonical_names.elements().empty());

  // Anchor ports only go with templated canonical names. Producer ports only
  // go with instantiated canonical names. No other ports are allowed.
  bool is_templated = false;
  bool is_instantiated = false;
  for (const auto& canonical_name : canonical_names.elements()) {
    if (canonical_name.instantiated_value()) {
      is_instantiated = true;
    } else {
      is_templated = true;
    }
  }

  if (is_instantiated == is_templated) {
    throw JsonValidationError(
        value,
        /* field */ "canonical_names",
        "all instantiated, or all templated values, not mix of both");
  }

  if (is_templated) {
    auto num_via_type_of_ports =
        via_type_of_ports.is_value() ? via_type_of_ports.elements().size() : 0;
    for (const auto& canonical_name : canonical_names.elements()) {
      auto is_via_type_of = canonical_name.is_via_type_of_template();
      if (is_via_type_of && num_via_type_of_ports != 1) {
        throw JsonValidationError(
            value,
            /* field */ std::nullopt,
            "exactly one 'via_type_of' port when canonical name contains 'via_type_of' template");
      }
    }
  }

  // If callee_port is user-specified and not Leaf, validate it.
  if (callee_port.root().is_anchor() && is_instantiated) {
    throw JsonValidationError(
        value,
        /* field */ std::nullopt,
        "`Anchor` callee ports to go with templated canonical names.");
  } else if (callee_port.root().is_producer() && is_templated) {
    throw JsonValidationError(
        value,
        /* field */ std::nullopt,
        "`Producer` callee ports to go with instantiated canonical names.");
  } else if (!callee_port.root().is_leaf_port()) {
    throw JsonValidationError(
        value,
        /* field */ std::nullopt,
        "`Anchor` or `Producer` callee port for crtex frame with canonical_names defined.");
  }

  if (callee_port.root().is_leaf()) {
    if (is_instantiated) {
      throw JsonValidationError(
          value,
          /* field */ std::nullopt,
          "Instantiated canonical names must have callee_port defined as `Producer.<producer_id>.<canonical_port>`");
    }

    // If the callee_port is defaulted to Leaf, it should be updated to an
    // Anchor to enable detection that this comes from a CRTEX producer.
    return AccessPath(Root(Root::Kind::Anchor));
  }

  return callee_port;
}