19#include "absl/log/check.h"
20#include "absl/strings/ascii.h"
21#include "absl/strings/str_cat.h"
22#include "absl/strings/str_format.h"
23#include "absl/strings/string_view.h"
24#include "absl/types/span.h"
33void AddKeyParams(
int n, std::string* out) {
34 for (
int i = 0;
i < n; ++
i) {
35 absl::StrAppend(out,
", int64_t key_", i);
41void AddAttrKeyArg(
int n, absl::string_view symmetry, std::string* out) {
42 absl::StrAppendFormat(out,
", AttrKey<%i, %s>(", n, symmetry);
43 for (
int i = 0;
i < n; ++
i) {
45 absl::StrAppend(out,
", ");
47 absl::StrAppend(out,
"key_", i);
49 absl::StrAppend(out,
")");
53absl::string_view GetCTypeName(
67std::string NameToCamelCase(absl::string_view attr_name) {
69 result.reserve(attr_name.size());
70 CHECK(!attr_name.empty());
71 const char first = attr_name[0];
72 CHECK(absl::ascii_isalpha(first) && absl::ascii_islower(first))
73 <<
"invalid attr name: " << attr_name;
74 result.push_back(absl::ascii_toupper(first));
75 for (
int i = 1;
i < attr_name.size(); ++
i) {
76 const char c = attr_name[
i];
79 CHECK(i < attr_name.size()) <<
"invalid attr name: " << attr_name;
80 const char next_c = attr_name[
i];
81 CHECK(absl::ascii_isalnum(next_c)) <<
"invalid attr name: " << attr_name;
82 result.push_back(absl::ascii_toupper(next_c));
84 CHECK(absl::ascii_isalnum(
c)) <<
"invalid attr name: " << attr_name;
85 CHECK(absl::ascii_islower(
c)) <<
"invalid attr name: " << attr_name;
93std::shared_ptr<Type> GetStatusType() {
return Type::Named(
"int"); }
99 .return_type = GetStatusType(),
100 .has_key_parameter =
true,
105 .has_key_parameter =
true,
110 .return_type = GetStatusType(),
111 .has_key_parameter =
true,
113 .name =
"out_is_non_default"}}},
116 .return_type = GetStatusType(),
117 .has_key_parameter =
false,
119 .name =
"out_num_non_defaults"}}},
122 .return_type = GetStatusType(),
123 .has_key_parameter =
false,
127 .name =
"out_num_non_defaults"},
129 .name =
"out_non_defaults"},
139 void EmitHeader(std::string* out)
const final {
140 absl::StrAppend(out, R
"(
141/* DO NOT EDIT: This file is autogenerated. */
142#ifndef MATHOPTH_GENERATED
143#error "this file is intended to be included, do not use directly"
150void EmitPrototype(absl::string_view op_name,
153 absl::string_view attr_value_type = GetCTypeName(descriptor.value_type);
155 info.return_type->Print(attr_value_type, out);
156 absl::StrAppendFormat(out,
157 " MathOpt%s%s(struct "
158 "MathOptElemental* e, int attr",
159 descriptor.name, op_name);
161 if (info.has_key_parameter) {
162 AddKeyParams(descriptor.num_key_elements, out);
165 for (
const auto& extra_param : info.extra_parameters) {
166 absl::StrAppend(out,
", ");
167 extra_param.type->Print(attr_value_type, out);
168 absl::StrAppend(out,
" ", extra_param.name);
171 absl::StrAppend(out,
")");
174class C99DeclarationsGenerator :
public C99CodeGeneratorBase {
176 C99DeclarationsGenerator() : C99CodeGeneratorBase(GetC99FunctionInfos()) {}
178 void EmitElements(absl::Span<const absl::string_view> elements,
179 std::string* out)
const override {
182 "// The type of an element in the model.\n"
183 "enum MathOptElementType {\n");
184 for (
const auto& element_name : elements) {
185 absl::StrAppendFormat(out,
" kMathOpt%s,\n",
186 NameToCamelCase(element_name));
188 absl::StrAppend(out,
"};\n\n");
191 void EmitAttrOp(absl::string_view op_name,
192 const CodegenAttrTypeDescriptor& descriptor,
193 const AttrOpFunctionInfo& info,
194 std::string* out)
const override {
196 EmitPrototype(op_name, descriptor, info, out);
197 absl::StrAppend(out,
";\n");
200 void StartAttrType(
const CodegenAttrTypeDescriptor& descriptor,
201 std::string* out)
const override {
203 absl::StrAppendFormat(out,
"typedef enum {\n");
204 for (absl::string_view attr_name : descriptor.attribute_names) {
205 absl::StrAppendFormat(out,
" kMathOpt%s%s,\n", descriptor.name,
206 NameToCamelCase(attr_name));
208 absl::StrAppendFormat(out,
"} MathOpt%s;\n", descriptor.name);
212class C99DefinitionsGenerator :
public C99CodeGeneratorBase {
214 C99DefinitionsGenerator() : C99CodeGeneratorBase(GetC99FunctionInfos()) {}
216 void EmitAttrOp(absl::string_view op_name,
217 const CodegenAttrTypeDescriptor& descriptor,
218 const AttrOpFunctionInfo& info,
219 std::string* out)
const override {
220 EmitPrototype(op_name, descriptor, info, out);
222 absl::StrAppendFormat(out,
" {\n return CAttrOp<%s>::%s(e, attr",
223 descriptor.name, op_name);
225 if (info.has_key_parameter) {
226 AddAttrKeyArg(descriptor.num_key_elements, descriptor.symmetry, out);
229 for (
const auto& extra_param : info.extra_parameters) {
230 absl::StrAppend(out,
", ", extra_param.name);
232 absl::StrAppend(out,
");\n}\n");
238 return std::make_unique<C99DeclarationsGenerator>();
242 return std::make_unique<C99DefinitionsGenerator>();
The code generator interface.
CodeGenerator(const AttrOpFunctionInfos *attr_op_function_infos)
static std::shared_ptr< Type > Named(std::string name)
A named type, e.g. "double".
static std::shared_ptr< Type > Pointer(std::shared_ptr< Type > pointee)
A pointer type.
static std::shared_ptr< Type > AttrValueType()
Language-agnostic utilities for Elemental codegen.
std::unique_ptr< CodeGenerator > C99Definitions()
Returns a generator for C99 definitions.
std::unique_ptr< CodeGenerator > C99Declarations()
Returns a generator for C99 declarations.
std::array< AttrOpFunctionInfo, kNumAttrOps > AttrOpFunctionInfos
Information about how to codegen a given AttrOp in a given language.
A struct to represent an attribute type descriptor during codegen.
ValueType
The value type of the attribute.