1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/torque/cpp-builder.h"
6
7namespace v8 {
8namespace internal {
9namespace torque {
10namespace cpp {
11
12void Function::PrintDeclarationHeader(std::ostream& stream,
13                                      int indentation) const {
14  if (!description_.empty()) {
15    stream << std::string(indentation, ' ') << "// " << description_ << "\n";
16  }
17  stream << std::string(indentation, ' ') << "// " << pos_ << "\n";
18  stream << std::string(indentation, ' ');
19  if (IsExport()) stream << "V8_EXPORT_PRIVATE ";
20  if (IsV8Inline())
21    stream << "V8_INLINE ";
22  else if (IsInline())
23    stream << "inline ";
24  if (IsStatic()) stream << "static ";
25  if (IsConstexpr()) stream << "constexpr ";
26  stream << return_type_ << " " << name_ << "(";
27  bool first = true;
28  for (const auto& p : parameters_) {
29    if (!first) stream << ", ";
30    stream << p.type;
31    if (!p.name.empty()) stream << " " << p.name;
32    if (!p.default_value.empty()) stream << " = " << p.default_value;
33    first = false;
34  }
35  stream << ")";
36  if (IsConst()) stream << " const";
37}
38
39void Function::PrintDeclaration(std::ostream& stream, int indentation) const {
40  if (indentation == kAutomaticIndentation) {
41    indentation = owning_class_ ? 2 : 0;
42  }
43  PrintDeclarationHeader(stream, indentation);
44  stream << ";\n";
45}
46
47void Function::PrintDefinition(
48    std::ostream& stream, const std::function<void(std::ostream&)>& builder,
49    int indentation) const {
50  PrintBeginDefinition(stream, indentation);
51  if (builder) {
52    builder(stream);
53  }
54  PrintEndDefinition(stream, indentation);
55}
56
57void Function::PrintInlineDefinition(
58    std::ostream& stream, const std::function<void(std::ostream&)>& builder,
59    int indentation) const {
60  PrintDeclarationHeader(stream, indentation);
61  stream << " {\n";
62  if (builder) {
63    builder(stream);
64  }
65  PrintEndDefinition(stream, indentation);
66}
67
68void Function::PrintBeginDefinition(std::ostream& stream,
69                                    int indentation) const {
70  stream << std::string(indentation, ' ') << "// " << pos_ << "\n";
71  std::string scope;
72  if (owning_class_) {
73    scope = owning_class_->GetName();
74    const auto class_template_parameters =
75        owning_class_->GetTemplateParameters();
76    if (!class_template_parameters.empty()) {
77      stream << std::string(indentation, ' ');
78      stream << "template<";
79      scope += "<";
80      bool first = true;
81      for (const auto& p : class_template_parameters) {
82        if (!first) {
83          stream << ", ";
84          scope += ", ";
85        }
86        if (p.type.empty()) {
87          stream << "class " << p.name;
88        } else {
89          stream << p.type << " " << p.name;
90        }
91        scope += p.name;
92        first = false;
93      }
94      stream << ">\n";
95      scope += ">";
96    }
97    scope += "::";
98  }
99  stream << std::string(indentation, ' ') << return_type_ << " " << scope
100         << name_ << "(";
101  bool first = true;
102  for (const auto& p : parameters_) {
103    if (!first) stream << ", ";
104    stream << p.type;
105    if (!p.name.empty()) stream << " " << p.name;
106    first = false;
107  }
108  stream << ")";
109  if (IsConst()) {
110    stream << " const";
111  }
112  stream << " {\n";
113}
114
115void Function::PrintEndDefinition(std::ostream& stream, int indentation) const {
116  stream << std::string(indentation, ' ');
117  stream << "}\n\n";
118}
119
120void File::BeginIncludeGuard(const std::string& name) {
121  s() << "#ifndef " << name
122      << "\n"
123         "#define "
124      << name << "\n\n";
125}
126
127void File::EndIncludeGuard(const std::string& name) {
128  s() << "#endif // " << name << "\n";
129}
130
131void File::BeginNamespace(std::string name) {
132  DCHECK(!name.empty());
133  DCHECK_EQ(name.find(':'), std::string::npos);
134  s() << "namespace " << name << " {\n";
135  namespaces_.push(std::move(name));
136}
137
138void File::BeginNamespace(std::string name0, std::string name1) {
139  BeginNamespace(name0);
140  BeginNamespace(name1);
141}
142
143void File::EndNamespace(const std::string& name) {
144  DCHECK(!namespaces_.empty());
145  DCHECK_EQ(namespaces_.top(), name);
146  s() << "} // namespace " << namespaces_.top() << "\n";
147  namespaces_.pop();
148}
149
150void File::EndNamespace(const std::string& name0, const std::string& name1) {
151  EndNamespace(name1);
152  EndNamespace(name0);
153}
154
155}  // namespace cpp
156}  // namespace torque
157}  // namespace internal
158}  // namespace v8
159