{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/builtin-gen to generate builtin_table.inl
Used by BuiltinTable.cc for builtin overload resolution.

See:
* tools/cmd/intrinsic-gen/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}

// clang-format off

{{  with .Sem -}}
{{    range .Types -}}
{{      template "Type" . }}
{{    end -}}
{{    range .TypeMatchers -}}
{{      template "TypeMatcher" . }}
{{    end -}}
{{    range .EnumMatchers -}}
{{      template "EnumMatcher" . }}
{{    end -}}
{{- end -}}

{{- with IntrinsicTable -}}
{{- template "Matchers" . }}

constexpr MatcherIndex kMatcherIndices[] = {
{{- range $i, $idx := .MatcherIndices }}
  /* [{{$i}}] */ {{$idx}},
{{- end }}
};

// Assert that the MatcherIndex is big enough to index all the matchers, plus
// kNoMatcher.
static_assert(static_cast<int>(sizeof(kMatcherIndices) / sizeof(kMatcherIndices[0])) <
              static_cast<int>(std::numeric_limits<MatcherIndex>::max() - 1),
              "MatcherIndex is not large enough to index kMatcherIndices");

constexpr ParameterInfo kParameters[] = {
{{- range $i, $p := .Parameters }}
  {
    /* [{{$i}}] */
    /* usage */ ParameterUsage::
{{-   if $p.Usage }}k{{PascalCase $p.Usage}}
{{-   else        }}kNone
{{-   end         }},
    /* matcher indices */ &kMatcherIndices[{{$p.MatcherIndicesOffset}}],
  },
{{- end }}
};

constexpr TemplateTypeInfo kTemplateTypes[] = {
{{- range $i, $o := .TemplateTypes }}
  {
    /* [{{$i}}] */
    /* name */ "{{$o.Name}}",
    /* matcher index */
{{-   if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}}
{{-   else                    }} kNoMatcher
{{-   end                     }},
  },
{{- end }}
};

constexpr TemplateNumberInfo kTemplateNumbers[] = {
{{- range $i, $o := .TemplateNumbers }}
  {
    /* [{{$i}}] */
    /* name */ "{{$o.Name}}",
    /* matcher index */
{{-   if ge $o.MatcherIndex 0 }} {{$o.MatcherIndex}}
{{-   else                    }} kNoMatcher
{{-   end                     }},
  },
{{- end }}
};

constexpr OverloadInfo kOverloads[] = {
{{- range $i, $o := .Overloads }}
  {
    /* [{{$i}}] */
    /* num parameters */ {{$o.NumParameters}},
    /* num template types */ {{$o.NumTemplateTypes}},
    /* num template numbers */ {{$o.NumTemplateNumbers}},
    /* template types */
{{-   if $o.TemplateTypesOffset }} &kTemplateTypes[{{$o.TemplateTypesOffset}}],
{{-   else                  }} nullptr,
{{-   end }}
    /* template numbers */
{{-   if $o.TemplateNumbersOffset }} &kTemplateNumbers[{{$o.TemplateNumbersOffset}}]
{{-   else                    }} nullptr
{{-   end }},
    /* parameters */ &kParameters[{{$o.ParametersOffset}}],
    /* return matcher indices */
{{-   if $o.ReturnMatcherIndicesOffset }} &kMatcherIndices[{{$o.ReturnMatcherIndicesOffset}}]
{{-   else                             }} nullptr
{{-   end }},
    /* flags */ OverloadFlags(OverloadFlag::kIs{{Title $o.Kind}}
{{-   range $i, $u := $o.CanBeUsedInStage.List -}}
        , OverloadFlag::kSupports{{Title $u}}Pipeline
{{-   end }}
{{-   if $o.IsDeprecated}}, OverloadFlag::kIsDeprecated{{end }}),
  },
{{- end }}
};

constexpr IntrinsicInfo kBuiltins[] = {
{{- range $i, $b := .Builtins }}
  {
    /* [{{$i}}] */
{{-   range $b.OverloadDescriptions }}
    /* {{.}} */
{{-   end }}
    /* num overloads */ {{$b.NumOverloads}},
    /* overloads */ &kOverloads[{{$b.OverloadsOffset}}],
  },
{{- end }}
};

constexpr IntrinsicInfo kUnaryOperators[] = {
{{- range $i, $o := .UnaryOperators }}
  {
    /* [{{$i}}] */
{{-   range $o.OverloadDescriptions }}
    /* {{.}} */
{{-   end }}
    /* num overloads */ {{$o.NumOverloads}},
    /* overloads */ &kOverloads[{{$o.OverloadsOffset}}],
  },
{{- end }}
};

{{- range $i, $o := .UnaryOperators }}
constexpr uint8_t kUnaryOperator{{template "OperatorName" $o.Name}} = {{$i}};
{{- end }}

constexpr IntrinsicInfo kBinaryOperators[] = {
{{- range $i, $o := .BinaryOperators }}
  {
    /* [{{$i}}] */
{{-   range $o.OverloadDescriptions }}
    /* {{.}} */
{{-   end }}
    /* num overloads */ {{$o.NumOverloads}},
    /* overloads */ &kOverloads[{{$o.OverloadsOffset}}],
  },
{{- end }}
};

{{- range $i, $o := .BinaryOperators }}
constexpr uint8_t kBinaryOperator{{template "OperatorName" $o.Name}} = {{$i}};
{{- end }}

constexpr IntrinsicInfo kConstructorsAndConverters[] = {
{{- range $i, $o := .ConstructorsAndConverters }}
  {
    /* [{{$i}}] */
{{-   range $o.OverloadDescriptions }}
    /* {{.}} */
{{-   end }}
    /* num overloads */ {{$o.NumOverloads}},
    /* overloads */ &kOverloads[{{$o.OverloadsOffset}}],
  },
{{- end }}
};

// clang-format on
{{ end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                              define "Type"                               -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $class := PascalCase .Name -}}
/// TypeMatcher for 'type {{.Name}}'
{{- if .Decl.Source.S.Filepath  }}
/// @see {{.Decl.Source}}
{{- end  }}
class {{$class}} : public TypeMatcher {
 public:
  /// Checks whether the given type matches the matcher rules.
  /// Match may define and refine the template types and numbers in state.
  /// @param state the MatchState
  /// @param type the type to match
  /// @returns the canonicalized type on match, otherwise nullptr
  const sem::Type* Match(MatchState& state,
                         const sem::Type* type) const override;
  /// @param state the MatchState
  /// @return a string representation of the matcher.
  std::string String(MatchState& state) const override;
};

const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
{{- range .TemplateParams }}
{{-   template "DeclareLocalTemplateParam" . }}
{{- end  }}
  if (!match_{{TrimLeft .Name "_"}}(ty{{range .TemplateParams}}, {{.GetName}}{{end}})) {
    return nullptr;
  }
{{- range .TemplateParams }}
  {{.Name}} = {{ template "MatchTemplateParam" .}}({{.Name}});
  if ({{ template "IsTemplateParamInvalid" .}}) {
    return nullptr;
  }
{{- end  }}
  return build_{{TrimLeft .Name "_"}}(state{{range .TemplateParams}}, {{.GetName}}{{end}});
}

std::string {{$class}}::String(MatchState&{{if .TemplateParams}} state{{end}}) const {
{{- range .TemplateParams }}
{{-   template "DeclareLocalTemplateParamName" . }}
{{- end  }}

{{- if .DisplayName }}
  std::stringstream ss;
  ss{{range SplitDisplayName .DisplayName}} << {{.}}{{end}};
  return ss.str();
{{- else if .TemplateParams }}
  return "{{.Name}}<"{{template "AppendTemplateParamNames" .TemplateParams}} + ">";
{{- else }}
  return "{{.Name}}";
{{- end  }}
}
{{  end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                          define "TypeMatcher"                            -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $class := PascalCase .Name -}}
/// TypeMatcher for 'match {{.Name}}'
{{- if .Decl.Source.S.Filepath  }}
/// @see {{.Decl.Source}}
{{- end  }}
class {{$class}} : public TypeMatcher {
 public:
  /// Checks whether the given type matches the matcher rules, and returns the
  /// expected, canonicalized type on success.
  /// Match may define and refine the template types and numbers in state.
  /// @param state the MatchState
  /// @param type the type to match
  /// @returns the canonicalized type on match, otherwise nullptr
  const sem::Type* Match(MatchState& state,
                         const sem::Type* type) const override;
  /// @param state the MatchState
  /// @return a string representation of the matcher.
  std::string String(MatchState& state) const override;
};

const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
{{- range .PrecedenceSortedTypes }}
  if (match_{{.Name}}(ty)) {
    return build_{{.Name}}(state);
  }
{{- end }}
  return nullptr;
}

std::string {{$class}}::String(MatchState&) const {
  return "
{{- range .Types -}}
{{-   if      IsFirstIn . $.Types }}{{.Name}}
{{-   else if IsLastIn  . $.Types }} or {{.Name}}
{{-   else                        }}, {{.Name}}
{{-   end -}}
{{- end -}}
  ";
}
{{  end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                          define "EnumMatcher"                            -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $class := PascalCase .Name -}}
{{- $enum := PascalCase .Enum.Name -}}
/// EnumMatcher for 'match {{.Name}}'
{{- if .Decl.Source.S.Filepath  }}
/// @see {{.Decl.Source}}
{{- end  }}
class {{$class}} : public NumberMatcher {
 public:
  /// Checks whether the given number matches the enum matcher rules.
  /// Match may define template numbers in state.
  /// @param state the MatchState
  /// @param number the enum value as a Number
  /// @return true if the enum value matches the set
  Number Match(MatchState& state, Number number) const override;
  /// @param state the MatchState
  /// @return a string representation of the matcher.
  std::string String(MatchState& state) const override;
};

{{ if eq 1 (len .Options) -}}
{{-   $option := index .Options 0 }}
{{-   $entry := printf "k%v" (PascalCase $option.Name) -}}
Number {{$class}}::Match(MatchState&, Number number) const {
  if (number.IsAny() || number.Value() == static_cast<uint32_t>({{$enum}}::{{$entry}})) {
    return Number(static_cast<uint32_t>({{$enum}}::{{$entry}}));
  }
  return Number::invalid;
}
{{- else -}}
Number {{$class}}::Match(MatchState&, Number number) const {
  switch (static_cast<{{$enum}}>(number.Value())) {
{{-   range .Options }}
    case {{$enum}}::k{{PascalCase .Name}}:
{{-   end }}
      return number;
    default:
      return Number::invalid;
  }
}
{{- end }}

std::string {{$class}}::String(MatchState&) const {
  return "
{{- range .Options -}}
{{-   if      IsFirstIn . $.Options }}{{.Name}}
{{-   else if IsLastIn  . $.Options }} or {{.Name}}
{{-   else                          }}, {{.Name}}
{{-   end -}}
{{- end -}}
";
}
{{  end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                            define "Matchers"                             -}}
{{- /* ------------------------------------------------------------------ */ -}}
/// Matchers holds type and number matchers
class Matchers {
 private:
{{- $t_names := Map -}}
{{- $n_names := Map -}}
{{- range Iterate .Sem.MaxTemplateTypes -}}
{{-   $name := printf "template_type_%v" . -}}
{{-   $t_names.Put . $name }}
  TemplateTypeMatcher {{$name}}_{ {{- . -}} };
{{- end }}
{{- range Iterate .Sem.MaxTemplateNumbers -}}
{{-   $name := printf "template_number_%v" . -}}
{{-   $n_names.Put . $name }}
  TemplateNumberMatcher {{$name}}_{ {{- . -}} };
{{- end }}
{{- range .Sem.Types -}}
{{-   $name := PascalCase .Name -}}
{{-   $t_names.Put . $name }}
  {{$name}} {{$name}}_;
{{- end }}
{{- range .Sem.TypeMatchers -}}
{{-   $name := PascalCase .Name -}}
{{-   $t_names.Put . $name }}
  {{$name}} {{$name}}_;
{{- end }}
{{- range .Sem.EnumMatchers -}}
{{-   $name := PascalCase .Name -}}
{{-   $n_names.Put . $name }}
  {{$name}} {{$name}}_;
{{- end }}

 public:
  /// Constructor
  Matchers();
  /// Destructor
  ~Matchers();

  /// The template types, types, and type matchers
  TypeMatcher const* const type[{{len .TMatchers}}] = {
{{- range $i, $m := .TMatchers }}
    /* [{{$i}}] */
{{-   if $m }} &{{$t_names.Get $m}}_,
{{-   else  }} &{{$t_names.Get $i}}_,
{{-   end   }}
{{- end }}
  };

  /// The template numbers, and number matchers
  NumberMatcher const* const number[{{len .NMatchers}}] = {
{{- range $i, $m := .NMatchers }}
    /* [{{$i}}] */
{{-   if $m }} &{{$n_names.Get $m}}_,
{{-   else  }} &{{$n_names.Get $i}}_,
{{-   end   }}
{{- end }}
  };
};

Matchers::Matchers() = default;
Matchers::~Matchers() = default;
{{- end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                     define "DeclareLocalTemplateParam"                   -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{-   if      IsTemplateTypeParam . }}
  const sem::Type* {{.Name}} = nullptr;
{{-   else if IsTemplateNumberParam . }}
  Number {{.Name}} = Number::invalid;
{{-   else if IsTemplateEnumParam . }}
  Number {{.Name}} = Number::invalid;
{{-   end -}}
{{- end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                   define "DeclareLocalTemplateParamName"                 -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{-   if      IsTemplateTypeParam . }}
  const std::string {{.Name}} = state.TypeName();
{{-   else if IsTemplateNumberParam . }}
  const std::string {{.Name}} = state.NumName();
{{-   else if IsTemplateEnumParam . }}
  const std::string {{.Name}} = state.NumName();
{{-   end -}}
{{- end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                       define "MatchTemplateParam"                        -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{-   if      IsTemplateTypeParam . -}}
  state.Type
{{-   else if IsTemplateNumberParam . -}}
  state.Num
{{-   else if IsTemplateEnumParam . -}}
  state.Num
{{-   end -}}
{{- end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                       define "IsTemplateParamInvalid"                    -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{-   if      IsTemplateTypeParam . -}}
  {{.Name}} == nullptr
{{-   else if IsTemplateNumberParam . -}}
  !{{.Name}}.IsValid()
{{-   else if IsTemplateEnumParam . -}}
  !{{.Name}}.IsValid()
{{-   end -}}
{{- end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                      define "AppendTemplateParamNames"                   -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{-   range $i, $ := . -}}
{{-     if $i }} + ", " + {{.Name}}
{{-     else }} + {{.Name}}
{{-     end -}}
{{-   end -}}
{{- end -}}

{{- /* ------------------------------------------------------------------ */ -}}
{{-                          define "OperatorName"                           -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{-        if eq . "<<" -}}ShiftLeft
{{-   else if eq . "&"  -}}And
{{-   else if eq . "|"  -}}Or
{{-   else if eq . "^"  -}}Xor
{{-   else if eq . "&&" -}}LogicalAnd
{{-   else if eq . "||" -}}LogicalOr
{{-   else if eq . "==" -}}Equal
{{-   else if eq . "!"  -}}Not
{{-   else if eq . "!=" -}}NotEqual
{{-   else if eq . "~"  -}}Complement
{{-   else if eq . "<"  -}}LessThan
{{-   else if eq . ">"  -}}GreaterThan
{{-   else if eq . "<=" -}}LessThanEqual
{{-   else if eq . ">=" -}}GreaterThanEqual
{{-   else if eq . "<<" -}}ShiftLeft
{{-   else if eq . ">>" -}}ShiftRight
{{-   else if eq . "+"  -}}Plus
{{-   else if eq . "-"  -}}Minus
{{-   else if eq . "*"  -}}Star
{{-   else if eq . "/"  -}}Divide
{{-   else if eq . "%"  -}}Modulo
{{-   else -}}<unknown-{{.}}>
{{-   end -}}
{{- end -}}
