1 /*
2  * Copyright (C) 2015, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "ast_cpp.h"
18 
19 #include <algorithm>
20 
21 #include "code_writer.h"
22 #include "logging.h"
23 
24 using std::string;
25 using std::unique_ptr;
26 using std::vector;
27 
28 namespace android {
29 namespace aidl {
30 namespace cpp {
31 
ToString()32 std::string AstNode::ToString() {
33   std::string str;
34   Write(CodeWriter::ForString(&str).get());
35   return str;
36 }
37 
LiteralDecl(const std::string & expression)38 LiteralDecl::LiteralDecl(const std::string& expression) : expression_(expression) {}
39 
Write(CodeWriter * to) const40 void LiteralDecl::Write(CodeWriter* to) const {
41   to->Write("%s", expression_.c_str());
42 }
43 
ClassDecl(const std::string & name,const std::string & parent)44 ClassDecl::ClassDecl(const std::string& name, const std::string& parent)
45     : name_(name),
46       parent_(parent) {}
47 
ClassDecl(const std::string & name,const std::string & parent,std::vector<unique_ptr<Declaration>> public_members,std::vector<unique_ptr<Declaration>> private_members)48 ClassDecl::ClassDecl(const std::string& name, const std::string& parent,
49                      std::vector<unique_ptr<Declaration>> public_members,
50                      std::vector<unique_ptr<Declaration>> private_members)
51     : name_(name),
52       parent_(parent),
53       public_members_(std::move(public_members)),
54       private_members_(std::move(private_members)) {}
55 
Write(CodeWriter * to) const56 void ClassDecl::Write(CodeWriter* to) const {
57   to->Write("class %s ", name_.c_str());
58 
59   if (parent_.length() > 0)
60       to->Write(": public %s ", parent_.c_str());
61 
62   to->Write("{\n");
63 
64   if (!public_members_.empty())
65       to->Write("public:\n");
66 
67   to->Indent();
68   for (const auto& dec : public_members_)
69     dec->Write(to);
70   to->Dedent();
71 
72   if (!private_members_.empty())
73       to->Write("private:\n");
74 
75   to->Indent();
76   for (const auto& dec : private_members_)
77     dec->Write(to);
78   to->Dedent();
79 
80   to->Write("};  // class %s\n", name_.c_str());
81 }
82 
AddPublic(std::unique_ptr<Declaration> member)83 void ClassDecl::AddPublic(std::unique_ptr<Declaration> member) {
84   public_members_.push_back(std::move(member));
85 }
86 
AddPrivate(std::unique_ptr<Declaration> member)87 void ClassDecl::AddPrivate(std::unique_ptr<Declaration> member) {
88   private_members_.push_back(std::move(member));
89 }
90 
EnumField(const string & k,const string & v)91 Enum::EnumField::EnumField(const string& k, const string& v)
92     : key(k),
93       value(v) {}
94 
Enum(const string & name,const string & base_type,bool is_class)95 Enum::Enum(const string& name, const string& base_type, bool is_class)
96     : enum_name_(name), underlying_type_(base_type), is_class_(is_class) {}
97 
Write(CodeWriter * to) const98 void Enum::Write(CodeWriter* to) const {
99   to->Write("enum ");
100   if (is_class_) {
101     to->Write("class ");
102   }
103   if (underlying_type_.empty()) {
104     to->Write("%s {\n", enum_name_.c_str());
105   } else {
106     to->Write("%s : %s {\n", enum_name_.c_str(), underlying_type_.c_str());
107   }
108   to->Indent();
109   for (const auto& field : fields_) {
110     if (field.value.empty()) {
111       to->Write("%s,\n", field.key.c_str());
112     } else {
113       to->Write("%s = %s,\n", field.key.c_str(), field.value.c_str());
114     }
115   }
116   to->Dedent();
117   to->Write("};\n");
118 }
119 
AddValue(const string & key,const string & value)120 void Enum::AddValue(const string& key, const string& value) {
121   fields_.emplace_back(key, value);
122 }
123 
ArgList(const std::string & single_argument)124 ArgList::ArgList(const std::string& single_argument)
125     : ArgList(vector<string>{single_argument}) {}
126 
ArgList(const std::vector<std::string> & arg_list)127 ArgList::ArgList(const std::vector<std::string>& arg_list) {
128   for (const auto& s : arg_list) {
129     arguments_.emplace_back(new LiteralExpression(s));
130   }
131 }
132 
ArgList(std::vector<std::unique_ptr<AstNode>> arg_list)133 ArgList::ArgList(std::vector<std::unique_ptr<AstNode>> arg_list)
134     : arguments_(std::move(arg_list)) {}
135 
ArgList(ArgList && arg_list)136 ArgList::ArgList(ArgList&& arg_list) noexcept : arguments_(std::move(arg_list.arguments_)) {}
137 
Write(CodeWriter * to) const138 void ArgList::Write(CodeWriter* to) const {
139   to->Write("(");
140   bool is_first = true;
141   for (const auto& s : arguments_) {
142     if (!is_first) { to->Write(", "); }
143     is_first = false;
144     s->Write(to);
145   }
146   to->Write(")");
147 }
148 
ConstructorDecl(const std::string & name,ArgList && arg_list)149 ConstructorDecl::ConstructorDecl(
150     const std::string& name,
151     ArgList&& arg_list)
152     : ConstructorDecl(name, std::move(arg_list), 0u) {}
153 
ConstructorDecl(const std::string & name,ArgList && arg_list,uint32_t modifiers)154 ConstructorDecl::ConstructorDecl(
155     const std::string& name,
156     ArgList&& arg_list,
157     uint32_t modifiers)
158     : name_(name),
159       arguments_(std::move(arg_list)),
160       modifiers_(modifiers) {}
161 
Write(CodeWriter * to) const162 void ConstructorDecl::Write(CodeWriter* to) const {
163   if (modifiers_ & Modifiers::IS_VIRTUAL)
164     to->Write("virtual ");
165 
166   if (modifiers_ & Modifiers::IS_EXPLICIT)
167     to->Write("explicit ");
168 
169   to->Write("%s", name_.c_str());
170 
171   arguments_.Write(to);
172 
173   if (modifiers_ & Modifiers::IS_DEFAULT)
174     to->Write(" = default");
175 
176   to->Write(";\n");
177 }
178 
MacroDecl(const std::string & name,ArgList && arg_list)179 MacroDecl::MacroDecl(const std::string& name, ArgList&& arg_list)
180     : name_(name),
181       arguments_(std::move(arg_list)) {}
182 
Write(CodeWriter * to) const183 void MacroDecl::Write(CodeWriter* to) const {
184   to->Write("%s", name_.c_str());
185   arguments_.Write(to);
186   to->Write("\n");
187 }
188 
MethodDecl(const std::string & return_type,const std::string & name,ArgList && arg_list)189 MethodDecl::MethodDecl(const std::string& return_type,
190                        const std::string& name,
191                        ArgList&& arg_list)
192     : MethodDecl(return_type, name, std::move(arg_list), 0u) {}
193 
MethodDecl(const std::string & return_type,const std::string & name,ArgList && arg_list,uint32_t modifiers)194 MethodDecl::MethodDecl(const std::string& return_type, const std::string& name, ArgList&& arg_list,
195                        uint32_t modifiers)
196     : return_type_(return_type),
197       name_(name),
198       arguments_(std::move(arg_list)),
199       is_const_(modifiers & IS_CONST),
200       is_virtual_(modifiers & IS_VIRTUAL),
201       is_override_(modifiers & IS_OVERRIDE),
202       is_pure_virtual_(modifiers & IS_PURE_VIRTUAL),
203       is_static_(modifiers & IS_STATIC),
204       is_final_(modifiers & IS_FINAL) {}
205 
Write(CodeWriter * to) const206 void MethodDecl::Write(CodeWriter* to) const {
207   if (is_virtual_)
208     to->Write("virtual ");
209 
210   if (is_static_)
211     to->Write("static ");
212 
213   to->Write("%s %s", return_type_.c_str(), name_.c_str());
214 
215   arguments_.Write(to);
216 
217   if (is_const_)
218     to->Write(" const");
219 
220   if (is_override_)
221     to->Write(" override");
222 
223   if (is_final_) to->Write(" final");
224 
225   if (is_pure_virtual_)
226     to->Write(" = 0");
227 
228   to->Write(";\n");
229 }
230 
AddStatement(unique_ptr<AstNode> statement)231 void StatementBlock::AddStatement(unique_ptr<AstNode> statement) {
232   statements_.push_back(std::move(statement));
233 }
234 
AddStatement(AstNode * statement)235 void StatementBlock::AddStatement(AstNode* statement) {
236   statements_.emplace_back(statement);
237 }
238 
AddLiteral(const std::string & expression_str,bool add_semicolon)239 void StatementBlock::AddLiteral(const std::string& expression_str,
240                                 bool add_semicolon) {
241   if (add_semicolon) {
242     statements_.push_back(unique_ptr<AstNode>(new Statement(expression_str)));
243   } else {
244     statements_.push_back(unique_ptr<AstNode>(
245         new LiteralExpression(expression_str)));
246   }
247 }
248 
Write(CodeWriter * to) const249 void StatementBlock::Write(CodeWriter* to) const {
250   to->Write("{\n");
251   to->Indent();
252   for (const auto& statement : statements_) {
253     statement->Write(to);
254   }
255   to->Dedent();
256   to->Write("}\n");
257 }
258 
ConstructorImpl(const string & class_name,ArgList && arg_list,const vector<string> & initializer_list)259 ConstructorImpl::ConstructorImpl(const string& class_name,
260                                  ArgList&& arg_list,
261                                  const vector<string>& initializer_list)
262       : class_name_(class_name),
263         arguments_(std::move(arg_list)),
264         initializer_list_(initializer_list) {}
265 
GetStatementBlock()266 StatementBlock* ConstructorImpl::GetStatementBlock() {
267   return &body_;
268 }
269 
Write(CodeWriter * to) const270 void ConstructorImpl::Write(CodeWriter* to) const {
271   to->Write("%s::%s", class_name_.c_str(), class_name_.c_str());
272   arguments_.Write(to);
273   to->Write("\n");
274 
275   bool is_first = true;
276   for (const string& i : initializer_list_) {
277     if (is_first) {
278       to->Write("    : %s", i.c_str());
279     } else {
280       to->Write(",\n      %s", i.c_str());
281     }
282     is_first = false;
283   }
284 
285   body_.Write(to);
286 }
287 
MethodImpl(const string & return_type,const string & class_name,const string & method_name,ArgList && arg_list,bool is_const_method)288 MethodImpl::MethodImpl(const string& return_type,
289                        const string& class_name,
290                        const string& method_name,
291                        ArgList&& arg_list,
292                        bool is_const_method)
293     : return_type_(return_type),
294       method_name_(method_name),
295       arguments_(std::move(arg_list)),
296       is_const_method_(is_const_method) {
297   if (!class_name.empty()) {
298     method_name_ = class_name + "::" + method_name;
299   }
300 }
301 
GetStatementBlock()302 StatementBlock* MethodImpl::GetStatementBlock() {
303   return &statements_;
304 }
305 
Write(CodeWriter * to) const306 void MethodImpl::Write(CodeWriter* to) const {
307   to->Write("%s %s", return_type_.c_str(), method_name_.c_str());
308   arguments_.Write(to);
309   to->Write("%s ", (is_const_method_) ? " const" : "");
310   statements_.Write(to);
311 }
312 
SwitchStatement(const std::string & expression)313 SwitchStatement::SwitchStatement(const std::string& expression)
314     : switch_expression_(expression) {}
315 
AddCase(const string & value_expression)316 StatementBlock* SwitchStatement::AddCase(const string& value_expression) {
317   auto it = std::find(case_values_.begin(), case_values_.end(), value_expression);
318   if (it != case_values_.end()) {
319     LOG(ERROR) << "internal error: duplicate switch case labels";
320     return nullptr;
321   }
322   StatementBlock* ret = new StatementBlock();
323   case_values_.push_back(value_expression);
324   case_logic_.push_back(unique_ptr<StatementBlock>{ret});
325   return ret;
326 }
327 
Write(CodeWriter * to) const328 void SwitchStatement::Write(CodeWriter* to) const {
329   to->Write("switch (%s) {\n", switch_expression_.c_str());
330   for (size_t i = 0; i < case_values_.size(); ++i) {
331     const string& case_value = case_values_[i];
332     const unique_ptr<StatementBlock>& statements = case_logic_[i];
333     if (case_value.empty()) {
334       to->Write("default:\n");
335     } else {
336       to->Write("case %s:\n", case_value.c_str());
337     }
338     statements->Write(to);
339     to->Write("break;\n");
340   }
341   to->Write("}\n");
342 }
343 
344 
Assignment(const std::string & left,const std::string & right)345 Assignment::Assignment(const std::string& left, const std::string& right)
346     : Assignment(left, new LiteralExpression{right}) {}
347 
Assignment(const std::string & left,AstNode * right)348 Assignment::Assignment(const std::string& left, AstNode* right)
349     : lhs_(left),
350       rhs_(right) {}
351 
Write(CodeWriter * to) const352 void Assignment::Write(CodeWriter* to) const {
353   to->Write("%s = ", lhs_.c_str());
354   rhs_->Write(to);
355   to->Write(";\n");
356 }
357 
MethodCall(const std::string & method_name,const std::string & single_argument)358 MethodCall::MethodCall(const std::string& method_name,
359                        const std::string& single_argument)
360     : MethodCall(method_name, ArgList{single_argument}) {}
361 
MethodCall(const std::string & method_name,ArgList && arg_list)362 MethodCall::MethodCall(const std::string& method_name,
363                        ArgList&& arg_list)
364     : method_name_(method_name),
365       arguments_{std::move(arg_list)} {}
366 
Write(CodeWriter * to) const367 void MethodCall::Write(CodeWriter* to) const {
368   to->Write("%s", method_name_.c_str());
369   arguments_.Write(to);
370 }
371 
IfStatement(AstNode * expression,bool invert_expression)372 IfStatement::IfStatement(AstNode* expression, bool invert_expression)
373     : expression_(expression),
374       invert_expression_(invert_expression) {}
375 
Write(CodeWriter * to) const376 void IfStatement::Write(CodeWriter* to) const {
377   to->Write("if (%s", (invert_expression_) ? "!(" : "");
378   expression_->Write(to);
379   to->Write(")%s ", (invert_expression_) ? ")" : "");
380   on_true_.Write(to);
381 
382   if (!on_false_.Empty()) {
383     to->Write("else ");
384     on_false_.Write(to);
385   }
386 }
387 
Statement(unique_ptr<AstNode> expression)388 Statement::Statement(unique_ptr<AstNode> expression)
389     : expression_(std::move(expression)) {}
390 
Statement(AstNode * expression)391 Statement::Statement(AstNode* expression) : expression_(expression) {}
392 
Statement(const string & expression)393 Statement::Statement(const string& expression)
394     : expression_(new LiteralExpression(expression)) {}
395 
Write(CodeWriter * to) const396 void Statement::Write(CodeWriter* to) const {
397   expression_->Write(to);
398   to->Write(";\n");
399 }
400 
Comparison(AstNode * lhs,const string & comparison,AstNode * rhs)401 Comparison::Comparison(AstNode* lhs, const string& comparison, AstNode* rhs)
402     : left_(lhs),
403       right_(rhs),
404       operator_(comparison) {}
405 
Write(CodeWriter * to) const406 void Comparison::Write(CodeWriter* to) const {
407   to->Write("((");
408   left_->Write(to);
409   to->Write(") %s (", operator_.c_str());
410   right_->Write(to);
411   to->Write("))");
412 }
413 
LiteralExpression(const std::string & expression)414 LiteralExpression::LiteralExpression(const std::string& expression)
415     : expression_(expression) {}
416 
Write(CodeWriter * to) const417 void LiteralExpression::Write(CodeWriter* to) const {
418   to->Write("%s", expression_.c_str());
419 }
420 
CppNamespace(const std::string & name,std::vector<unique_ptr<Declaration>> declarations)421 CppNamespace::CppNamespace(const std::string& name,
422                            std::vector<unique_ptr<Declaration>> declarations)
423     : declarations_(std::move(declarations)),
424       name_(name) {}
425 
CppNamespace(const std::string & name,unique_ptr<Declaration> declaration)426 CppNamespace::CppNamespace(const std::string& name,
427                            unique_ptr<Declaration> declaration)
428     : name_(name) {
429   declarations_.push_back(std::move(declaration));
430 }
CppNamespace(const std::string & name)431 CppNamespace::CppNamespace(const std::string& name)
432     : name_(name) {}
433 
Write(CodeWriter * to) const434 void CppNamespace::Write(CodeWriter* to) const {
435   to->Write("namespace %s {\n\n", name_.c_str());
436 
437   for (const auto& dec : declarations_) {
438     dec->Write(to);
439     to->Write("\n");
440   }
441 
442   to->Write("}  // namespace %s\n", name_.c_str());
443 }
444 
Document(const std::vector<std::string> & include_list,std::vector<unique_ptr<Declaration>> declarations)445 Document::Document(const std::vector<std::string>& include_list,
446                    std::vector<unique_ptr<Declaration>> declarations)
447     : include_list_(include_list), declarations_(std::move(declarations)) {}
448 
Write(CodeWriter * to) const449 void Document::Write(CodeWriter* to) const {
450   for (const auto& include : include_list_) {
451     to->Write("#include <%s>\n", include.c_str());
452   }
453   to->Write("\n");
454 
455   for (const auto& declaration : declarations_) {
456     declaration->Write(to);
457   }
458 }
459 
CppHeader(const std::string & include_guard,const std::vector<std::string> & include_list,std::vector<std::unique_ptr<Declaration>> declarations)460 CppHeader::CppHeader(const std::string& include_guard, const std::vector<std::string>& include_list,
461                      std::vector<std::unique_ptr<Declaration>> declarations)
462     : Document(include_list, std::move(declarations)), include_guard_(include_guard) {}
463 
Write(CodeWriter * to) const464 void CppHeader::Write(CodeWriter* to) const {
465   to->Write("#ifndef %s\n", include_guard_.c_str());
466   to->Write("#define %s\n\n", include_guard_.c_str());
467 
468   Document::Write(to);
469   to->Write("\n");
470 
471   to->Write("#endif  // %s\n", include_guard_.c_str());
472 }
473 
CppSource(const std::vector<std::string> & include_list,std::vector<std::unique_ptr<Declaration>> declarations)474 CppSource::CppSource(const std::vector<std::string>& include_list,
475                      std::vector<std::unique_ptr<Declaration>> declarations)
476     : Document(include_list, std::move(declarations)) {}
477 
478 }  // namespace cpp
479 }  // namespace aidl
480 }  // namespace android
481