19#include "absl/base/optimization.h"
20#include "absl/log/check.h"
21#include "absl/strings/ascii.h"
22#include "absl/strings/str_cat.h"
23#include "absl/strings/str_format.h"
24#include "absl/strings/string_view.h"
25#include "absl/types/span.h"
34void AddKeyParams(
int n, std::string* out) {
35 for (
int i = 0;
i < n; ++
i) {
36 absl::StrAppend(out,
", int64_t key_", i);
42void AddAttrKeyArg(
int n, absl::string_view symmetry, std::string* out) {
43 absl::StrAppendFormat(out,
", AttrKey<%i, %s>(", n, symmetry);
44 for (
int i = 0;
i < n; ++
i) {
46 absl::StrAppend(out,
", ");
48 absl::StrAppend(out,
"key_", i);
50 absl::StrAppend(out,
")");
54absl::string_view GetCTypeName(
69std::string NameToCamelCase(absl::string_view attr_name) {
71 result.reserve(attr_name.size());
72 CHECK(!attr_name.empty());
73 const char first = attr_name[0];
74 CHECK(absl::ascii_isalpha(first) && absl::ascii_islower(first))
75 <<
"invalid attr name: " << attr_name;
76 result.push_back(absl::ascii_toupper(first));
77 for (
int i = 1;
i < attr_name.size(); ++
i) {
78 const char c = attr_name[
i];
81 CHECK(i < attr_name.size()) <<
"invalid attr name: " << attr_name;
82 const char next_c = attr_name[
i];
83 CHECK(absl::ascii_isalnum(next_c)) <<
"invalid attr name: " << attr_name;
84 result.push_back(absl::ascii_toupper(next_c));
86 CHECK(absl::ascii_isalnum(
c)) <<
"invalid attr name: " << attr_name;
87 CHECK(absl::ascii_islower(
c)) <<
"invalid attr name: " << attr_name;
95std::shared_ptr<Type> GetStatusType() {
return Type::Named(
"int"); }
101 .return_type = GetStatusType(),
102 .has_key_parameter =
true,
107 .has_key_parameter =
true,
112 .return_type = GetStatusType(),
113 .has_key_parameter =
true,
115 .name =
"out_is_non_default"}}},
118 .return_type = GetStatusType(),
119 .has_key_parameter =
false,
121 .name =
"out_num_non_defaults"}}},
124 .return_type = GetStatusType(),
125 .has_key_parameter =
false,
129 .name =
"out_num_non_defaults"},
131 .name =
"out_non_defaults"},
141 void EmitHeader(std::string* out)
const final {
142 absl::StrAppend(out, R
"(
143/* DO NOT EDIT: This file is autogenerated. */
144#ifndef MATHOPTH_GENERATED
145#error "this file is intended to be included, do not use directly"
152void EmitPrototype(absl::string_view op_name,
155 absl::string_view attr_value_type = GetCTypeName(descriptor.value_type);
157 info.return_type->Print(attr_value_type, out);
158 absl::StrAppendFormat(out,
159 " MathOpt%s%s(struct "
160 "MathOptElemental* e, int attr",
161 descriptor.name, op_name);
163 if (info.has_key_parameter) {
164 AddKeyParams(descriptor.num_key_elements, out);
167 for (
const auto& extra_param : info.extra_parameters) {
168 absl::StrAppend(out,
", ");
169 extra_param.type->Print(attr_value_type, out);
170 absl::StrAppend(out,
" ", extra_param.name);
173 absl::StrAppend(out,
")");
176class C99DeclarationsGenerator :
public C99CodeGeneratorBase {
178 C99DeclarationsGenerator() : C99CodeGeneratorBase(GetC99FunctionInfos()) {}
180 void EmitElements(absl::Span<const absl::string_view> elements,
181 std::string* out)
const override {
184 "// The type of an element in the model.\n"
185 "enum MathOptElementType {\n");
186 for (
const auto& element_name : elements) {
187 absl::StrAppendFormat(out,
" kMathOpt%s,\n",
188 NameToCamelCase(element_name));
190 absl::StrAppend(out,
"};\n\n");
193 void EmitAttrOp(absl::string_view op_name,
194 const CodegenAttrTypeDescriptor& descriptor,
195 const AttrOpFunctionInfo& info,
196 std::string* out)
const override {
198 EmitPrototype(op_name, descriptor, info, out);
199 absl::StrAppend(out,
";\n");
202 void StartAttrType(
const CodegenAttrTypeDescriptor& descriptor,
203 std::string* out)
const override {
205 absl::StrAppendFormat(out,
"typedef enum {\n");
206 for (absl::string_view attr_name : descriptor.attribute_names) {
207 absl::StrAppendFormat(out,
" kMathOpt%s%s,\n", descriptor.name,
208 NameToCamelCase(attr_name));
210 absl::StrAppendFormat(out,
"} MathOpt%s;\n", descriptor.name);
214class C99DefinitionsGenerator :
public C99CodeGeneratorBase {
216 C99DefinitionsGenerator() : C99CodeGeneratorBase(GetC99FunctionInfos()) {}
218 void EmitAttrOp(absl::string_view op_name,
219 const CodegenAttrTypeDescriptor& descriptor,
220 const AttrOpFunctionInfo& info,
221 std::string* out)
const override {
222 EmitPrototype(op_name, descriptor, info, out);
224 absl::StrAppendFormat(out,
" {\n return CAttrOp<%s>::%s(e, attr",
225 descriptor.name, op_name);
227 if (info.has_key_parameter) {
228 AddAttrKeyArg(descriptor.num_key_elements, descriptor.symmetry, out);
231 for (
const auto& extra_param : info.extra_parameters) {
232 absl::StrAppend(out,
", ", extra_param.name);
234 absl::StrAppend(out,
");\n}\n");
240 return std::make_unique<C99DeclarationsGenerator>();
244 return std::make_unique<C99DefinitionsGenerator>();
CodeGenerator(const AttrOpFunctionInfos *attr_op_function_infos)
static std::shared_ptr< Type > Named(std::string name)
static std::shared_ptr< Type > Pointer(std::shared_ptr< Type > pointee)
static std::shared_ptr< Type > AttrValueType()
std::unique_ptr< CodeGenerator > C99Definitions()
std::unique_ptr< CodeGenerator > C99Declarations()
std::array< AttrOpFunctionInfo, kNumAttrOps > AttrOpFunctionInfos