Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
gen_c.cc
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <memory>
17#include <string>
18
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"
27
29
30namespace {
31
32// A helper to generate parameters to pass `n` key element indices, e.g:
33// ", int64_t key_0, int64_t key_1" (parameters)
34void AddKeyParams(int n, std::string* out) {
35 for (int i = 0; i < n; ++i) {
36 absl::StrAppend(out, ", int64_t key_", i);
37 }
38}
39
40// A helper to generate an AttrKey argument to pass `n` key element indices,
41// e.g: "AttrKey<2, NoSymmetry>(key_0, key_1)".
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) {
45 if (i != 0) {
46 absl::StrAppend(out, ", ");
47 }
48 absl::StrAppend(out, "key_", i);
49 }
50 absl::StrAppend(out, ")");
51}
52
53// Returns the C99 name for the given type.
54absl::string_view GetCTypeName(
56 switch (value_type) {
58 return "_Bool";
60 return "int64_t";
62 return "double";
63 }
64 ABSL_UNREACHABLE();
65}
66
67// Turns an element/attribute name (e.g. "some_name") into a camel case name
68// (e.g. "SomeName").
69std::string NameToCamelCase(absl::string_view attr_name) {
70 std::string result;
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];
79 if (c == '_') {
80 ++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));
85 } else {
86 CHECK(absl::ascii_isalnum(c)) << "invalid attr name: " << attr_name;
87 CHECK(absl::ascii_islower(c)) << "invalid attr name: " << attr_name;
88 result.push_back(c);
89 }
90 }
91 return result;
92}
93
94// Returns the type of the C status.
95std::shared_ptr<Type> GetStatusType() { return Type::Named("int"); }
96
97const AttrOpFunctionInfos* GetC99FunctionInfos() {
98 static const auto* const kResult = new AttrOpFunctionInfos({
99 // Get.
101 .return_type = GetStatusType(),
102 .has_key_parameter = true,
103 .extra_parameters = {{.type = Type::Pointer(Type::AttrValueType()),
104 .name = "value"}}},
105 // Set.
106 AttrOpFunctionInfo{.return_type = GetStatusType(),
107 .has_key_parameter = true,
108 .extra_parameters = {{.type = Type::AttrValueType(),
109 .name = "value"}}},
110 // IsNonDefault.
112 .return_type = GetStatusType(),
113 .has_key_parameter = true,
114 .extra_parameters = {{.type = Type::Pointer(Type::Named("_Bool")),
115 .name = "out_is_non_default"}}},
116 // NumNonDefaults.
118 .return_type = GetStatusType(),
119 .has_key_parameter = false,
120 .extra_parameters = {{.type = Type::Pointer(Type::Named("int64_t")),
121 .name = "out_num_non_defaults"}}},
122 // GetNonDefaults.
124 .return_type = GetStatusType(),
125 .has_key_parameter = false,
126 .extra_parameters =
127 {
128 {.type = Type::Pointer(Type::Named("int64_t")),
129 .name = "out_num_non_defaults"},
130 {.type = Type::Pointer(Type::Pointer(Type::Named("int64_t"))),
131 .name = "out_non_defaults"},
132 }},
133 });
134 return kResult;
135}
136
137class C99CodeGeneratorBase : public CodeGenerator {
138 public:
140
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"
146#endif
147)");
148 }
149};
150
151// Emits the prototype for a function.
152void EmitPrototype(absl::string_view op_name,
153 const CodegenAttrTypeDescriptor& descriptor,
154 const AttrOpFunctionInfo& info, std::string* out) {
155 absl::string_view attr_value_type = GetCTypeName(descriptor.value_type);
156 // Adds the return type, function name and common parameters.
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);
162 // Add the key.
163 if (info.has_key_parameter) {
164 AddKeyParams(descriptor.num_key_elements, out);
165 }
166 // Add extra parameters.
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);
171 }
172 // Finish prototype.
173 absl::StrAppend(out, ")");
174}
175
176class C99DeclarationsGenerator : public C99CodeGeneratorBase {
177 public:
178 C99DeclarationsGenerator() : C99CodeGeneratorBase(GetC99FunctionInfos()) {}
179
180 void EmitElements(absl::Span<const absl::string_view> elements,
181 std::string* out) const override {
182 // Generate an enum for the elements.
183 absl::StrAppend(out,
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));
189 }
190 absl::StrAppend(out, "};\n\n");
191 }
192
193 void EmitAttrOp(absl::string_view op_name,
194 const CodegenAttrTypeDescriptor& descriptor,
195 const AttrOpFunctionInfo& info,
196 std::string* out) const override {
197 // Just emit a prototype.
198 EmitPrototype(op_name, descriptor, info, out);
199 absl::StrAppend(out, ";\n");
200 }
201
202 void StartAttrType(const CodegenAttrTypeDescriptor& descriptor,
203 std::string* out) const override {
204 // Generate an enum for the attribute type.
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));
209 }
210 absl::StrAppendFormat(out, "} MathOpt%s;\n", descriptor.name);
211 }
212};
213
214class C99DefinitionsGenerator : public C99CodeGeneratorBase {
215 public:
216 C99DefinitionsGenerator() : C99CodeGeneratorBase(GetC99FunctionInfos()) {}
217
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);
223 // Emit a call to the wrapper (e.g. `CAttrOp<Descriptor>::Op`).
224 absl::StrAppendFormat(out, " {\n return CAttrOp<%s>::%s(e, attr",
225 descriptor.name, op_name);
226 // Add the key argument.
227 if (info.has_key_parameter) {
228 AddAttrKeyArg(descriptor.num_key_elements, descriptor.symmetry, out);
229 }
230 // Add extra parameter arguments.
231 for (const auto& extra_param : info.extra_parameters) {
232 absl::StrAppend(out, ", ", extra_param.name);
233 }
234 absl::StrAppend(out, ");\n}\n");
235 }
236};
237} // namespace
238
239std::unique_ptr<CodeGenerator> C99Declarations() {
240 return std::make_unique<C99DeclarationsGenerator>();
241}
242
243std::unique_ptr<CodeGenerator> C99Definitions() {
244 return std::make_unique<C99DefinitionsGenerator>();
245}
246
247} // namespace operations_research::math_opt::codegen
CodeGenerator(const AttrOpFunctionInfos *attr_op_function_infos)
Definition gen.h:101
static std::shared_ptr< Type > Named(std::string name)
Definition gen.cc:68
static std::shared_ptr< Type > Pointer(std::shared_ptr< Type > pointee)
Definition gen.cc:72
static std::shared_ptr< Type > AttrValueType()
Definition gen.cc:76
std::unique_ptr< CodeGenerator > C99Definitions()
Definition gen_c.cc:243
std::unique_ptr< CodeGenerator > C99Declarations()
Definition gen_c.cc:239
std::array< AttrOpFunctionInfo, kNumAttrOps > AttrOpFunctionInfos
Definition gen.h:96