You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
500 lines
14 KiB
500 lines
14 KiB
/*
|
|
* Copyright (C) 2015, The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "ast_cpp.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <android-base/strings.h>
|
|
|
|
#include "code_writer.h"
|
|
#include "logging.h"
|
|
|
|
using std::string;
|
|
using std::unique_ptr;
|
|
using std::vector;
|
|
|
|
namespace android {
|
|
namespace aidl {
|
|
namespace cpp {
|
|
|
|
std::string AstNode::ToString() {
|
|
std::string str;
|
|
Write(CodeWriter::ForString(&str).get());
|
|
return str;
|
|
}
|
|
|
|
LiteralDecl::LiteralDecl(const std::string& expression) : expression_(expression) {}
|
|
|
|
void LiteralDecl::Write(CodeWriter* to) const {
|
|
to->Write("%s", expression_.c_str());
|
|
}
|
|
|
|
ClassDecl::ClassDecl(const std::string& name, const std::string& parent,
|
|
const std::vector<std::string>& template_params, const std::string& attributes)
|
|
: name_(name), parent_(parent), attributes_(attributes), template_params_(template_params) {}
|
|
|
|
ClassDecl::ClassDecl(const std::string& name, const std::string& parent,
|
|
const std::vector<std::string>& template_params,
|
|
std::vector<unique_ptr<Declaration>> public_members,
|
|
std::vector<unique_ptr<Declaration>> private_members,
|
|
const std::string& attributes)
|
|
: name_(name),
|
|
parent_(parent),
|
|
attributes_(attributes),
|
|
template_params_(template_params),
|
|
public_members_(std::move(public_members)),
|
|
private_members_(std::move(private_members)) {}
|
|
|
|
void ClassDecl::Write(CodeWriter* to) const {
|
|
if (!template_params_.empty())
|
|
to->Write("template <typename %s>\n", base::Join(template_params_, ", typename ").c_str());
|
|
|
|
to->Write("class");
|
|
if (!attributes_.empty()) {
|
|
to->Write(" %s", attributes_.c_str());
|
|
}
|
|
to->Write(" %s ", name_.c_str());
|
|
|
|
if (parent_.length() > 0) to->Write(": public %s ", parent_.c_str());
|
|
|
|
to->Write("{\n");
|
|
|
|
if (!public_members_.empty()) to->Write("public:\n");
|
|
|
|
to->Indent();
|
|
for (const auto& dec : public_members_)
|
|
dec->Write(to);
|
|
to->Dedent();
|
|
|
|
if (!private_members_.empty()) to->Write("private:\n");
|
|
|
|
to->Indent();
|
|
for (const auto& dec : private_members_)
|
|
dec->Write(to);
|
|
to->Dedent();
|
|
|
|
to->Write("}; // class %s\n", name_.c_str());
|
|
}
|
|
|
|
void ClassDecl::AddPublic(std::unique_ptr<Declaration> member) {
|
|
public_members_.push_back(std::move(member));
|
|
}
|
|
|
|
void ClassDecl::AddPrivate(std::unique_ptr<Declaration> member) {
|
|
private_members_.push_back(std::move(member));
|
|
}
|
|
|
|
Enum::EnumField::EnumField(const string& k, const string& v, const string& a)
|
|
: key(k), value(v), attribute(a) {}
|
|
|
|
Enum::Enum(const string& name, const string& base_type, bool is_class,
|
|
const std::string& attributes)
|
|
: enum_name_(name), underlying_type_(base_type), attributes_(attributes), is_class_(is_class) {}
|
|
|
|
void Enum::Write(CodeWriter* to) const {
|
|
to->Write("enum ");
|
|
if (is_class_) {
|
|
to->Write("class ");
|
|
}
|
|
if (!attributes_.empty()) {
|
|
to->Write("%s ", attributes_.c_str());
|
|
}
|
|
if (underlying_type_.empty()) {
|
|
to->Write("%s {\n", enum_name_.c_str());
|
|
} else {
|
|
to->Write("%s : %s {\n", enum_name_.c_str(), underlying_type_.c_str());
|
|
}
|
|
to->Indent();
|
|
for (const auto& field : fields_) {
|
|
to->Write("%s", field.key.c_str());
|
|
if (!field.attribute.empty()) {
|
|
to->Write(" %s", field.attribute.c_str());
|
|
}
|
|
if (!field.value.empty()) {
|
|
to->Write(" = %s", field.value.c_str());
|
|
}
|
|
to->Write(",\n");
|
|
}
|
|
to->Dedent();
|
|
to->Write("};\n");
|
|
}
|
|
|
|
void Enum::AddValue(const string& key, const string& value, const string& attribute) {
|
|
fields_.emplace_back(key, value, attribute);
|
|
}
|
|
|
|
ArgList::ArgList(const std::string& single_argument)
|
|
: ArgList(vector<string>{single_argument}) {}
|
|
|
|
ArgList::ArgList(const std::vector<std::string>& arg_list) {
|
|
for (const auto& s : arg_list) {
|
|
arguments_.emplace_back(new LiteralExpression(s));
|
|
}
|
|
}
|
|
|
|
ArgList::ArgList(std::vector<std::unique_ptr<AstNode>> arg_list)
|
|
: arguments_(std::move(arg_list)) {}
|
|
|
|
ArgList::ArgList(ArgList&& arg_list) noexcept : arguments_(std::move(arg_list.arguments_)) {}
|
|
|
|
void ArgList::Write(CodeWriter* to) const {
|
|
to->Write("(");
|
|
bool is_first = true;
|
|
for (const auto& s : arguments_) {
|
|
if (!is_first) { to->Write(", "); }
|
|
is_first = false;
|
|
s->Write(to);
|
|
}
|
|
to->Write(")");
|
|
}
|
|
|
|
ConstructorDecl::ConstructorDecl(
|
|
const std::string& name,
|
|
ArgList&& arg_list)
|
|
: ConstructorDecl(name, std::move(arg_list), 0u) {}
|
|
|
|
ConstructorDecl::ConstructorDecl(
|
|
const std::string& name,
|
|
ArgList&& arg_list,
|
|
uint32_t modifiers)
|
|
: name_(name),
|
|
arguments_(std::move(arg_list)),
|
|
modifiers_(modifiers) {}
|
|
|
|
void ConstructorDecl::Write(CodeWriter* to) const {
|
|
if (modifiers_ & Modifiers::IS_VIRTUAL)
|
|
to->Write("virtual ");
|
|
|
|
if (modifiers_ & Modifiers::IS_EXPLICIT)
|
|
to->Write("explicit ");
|
|
|
|
to->Write("%s", name_.c_str());
|
|
|
|
arguments_.Write(to);
|
|
|
|
if (modifiers_ & Modifiers::IS_DEFAULT)
|
|
to->Write(" = default");
|
|
|
|
to->Write(";\n");
|
|
}
|
|
|
|
MacroDecl::MacroDecl(const std::string& name, ArgList&& arg_list)
|
|
: name_(name),
|
|
arguments_(std::move(arg_list)) {}
|
|
|
|
void MacroDecl::Write(CodeWriter* to) const {
|
|
to->Write("%s", name_.c_str());
|
|
arguments_.Write(to);
|
|
to->Write("\n");
|
|
}
|
|
|
|
MethodDecl::MethodDecl(const std::string& return_type, const std::string& name, ArgList&& arg_list,
|
|
const std::string& attributes)
|
|
: MethodDecl(return_type, name, std::move(arg_list), 0u, attributes) {}
|
|
|
|
MethodDecl::MethodDecl(const std::string& return_type, const std::string& name, ArgList&& arg_list,
|
|
uint32_t modifiers, const std::string& attributes)
|
|
: return_type_(return_type),
|
|
name_(name),
|
|
attributes_(attributes),
|
|
arguments_(std::move(arg_list)),
|
|
is_const_(modifiers & IS_CONST),
|
|
is_virtual_(modifiers & IS_VIRTUAL),
|
|
is_override_(modifiers & IS_OVERRIDE),
|
|
is_pure_virtual_(modifiers & IS_PURE_VIRTUAL),
|
|
is_static_(modifiers & IS_STATIC),
|
|
is_final_(modifiers & IS_FINAL) {}
|
|
|
|
void MethodDecl::Write(CodeWriter* to) const {
|
|
if (is_virtual_)
|
|
to->Write("virtual ");
|
|
|
|
if (is_static_)
|
|
to->Write("static ");
|
|
|
|
to->Write("%s %s", return_type_.c_str(), name_.c_str());
|
|
|
|
arguments_.Write(to);
|
|
|
|
if (is_const_)
|
|
to->Write(" const");
|
|
|
|
if (is_override_)
|
|
to->Write(" override");
|
|
|
|
if (is_final_) to->Write(" final");
|
|
|
|
if (!attributes_.empty()) to->Write(" %s", attributes_.c_str());
|
|
|
|
if (is_pure_virtual_)
|
|
to->Write(" = 0");
|
|
|
|
to->Write(";\n");
|
|
}
|
|
|
|
void StatementBlock::AddStatement(unique_ptr<AstNode> statement) {
|
|
statements_.push_back(std::move(statement));
|
|
}
|
|
|
|
void StatementBlock::AddStatement(AstNode* statement) {
|
|
statements_.emplace_back(statement);
|
|
}
|
|
|
|
void StatementBlock::AddLiteral(const std::string& expression_str,
|
|
bool add_semicolon) {
|
|
if (add_semicolon) {
|
|
statements_.push_back(unique_ptr<AstNode>(new Statement(expression_str)));
|
|
} else {
|
|
statements_.push_back(unique_ptr<AstNode>(
|
|
new LiteralExpression(expression_str)));
|
|
}
|
|
}
|
|
|
|
void StatementBlock::Write(CodeWriter* to) const {
|
|
to->Write("{\n");
|
|
to->Indent();
|
|
for (const auto& statement : statements_) {
|
|
statement->Write(to);
|
|
}
|
|
to->Dedent();
|
|
to->Write("}\n");
|
|
}
|
|
|
|
ConstructorImpl::ConstructorImpl(const string& class_name,
|
|
ArgList&& arg_list,
|
|
const vector<string>& initializer_list)
|
|
: class_name_(class_name),
|
|
arguments_(std::move(arg_list)),
|
|
initializer_list_(initializer_list) {}
|
|
|
|
StatementBlock* ConstructorImpl::GetStatementBlock() {
|
|
return &body_;
|
|
}
|
|
|
|
void ConstructorImpl::Write(CodeWriter* to) const {
|
|
to->Write("%s::%s", class_name_.c_str(), class_name_.c_str());
|
|
arguments_.Write(to);
|
|
to->Write("\n");
|
|
|
|
bool is_first = true;
|
|
for (const string& i : initializer_list_) {
|
|
if (is_first) {
|
|
to->Write(" : %s", i.c_str());
|
|
} else {
|
|
to->Write(",\n %s", i.c_str());
|
|
}
|
|
is_first = false;
|
|
}
|
|
|
|
body_.Write(to);
|
|
}
|
|
|
|
MethodImpl::MethodImpl(const string& return_type, const string& class_name,
|
|
const string& method_name, const std::vector<std::string>& template_params,
|
|
ArgList&& arg_list, bool is_const_method)
|
|
: return_type_(return_type),
|
|
method_name_(method_name),
|
|
arguments_(std::move(arg_list)),
|
|
is_const_method_(is_const_method),
|
|
template_params_(template_params) {
|
|
if (!class_name.empty()) {
|
|
if (!template_params.empty()) {
|
|
method_name_ = class_name + "<" + base::Join(template_params, ",") + ">::" + method_name;
|
|
} else {
|
|
method_name_ = class_name + "::" + method_name;
|
|
}
|
|
}
|
|
}
|
|
|
|
StatementBlock* MethodImpl::GetStatementBlock() {
|
|
return &statements_;
|
|
}
|
|
|
|
void MethodImpl::Write(CodeWriter* to) const {
|
|
if (!template_params_.empty())
|
|
to->Write("template <typename %s>\n", base::Join(template_params_, ", typename ").c_str());
|
|
to->Write("%s %s", return_type_.c_str(), method_name_.c_str());
|
|
arguments_.Write(to);
|
|
to->Write("%s ", (is_const_method_) ? " const" : "");
|
|
statements_.Write(to);
|
|
}
|
|
|
|
SwitchStatement::SwitchStatement(const std::string& expression)
|
|
: switch_expression_(expression) {}
|
|
|
|
StatementBlock* SwitchStatement::AddCase(const string& value_expression) {
|
|
auto it = std::find(case_values_.begin(), case_values_.end(), value_expression);
|
|
if (it != case_values_.end()) {
|
|
AIDL_ERROR(value_expression) << "Duplicate switch case labels";
|
|
return nullptr;
|
|
}
|
|
StatementBlock* ret = new StatementBlock();
|
|
case_values_.push_back(value_expression);
|
|
case_logic_.push_back(unique_ptr<StatementBlock>{ret});
|
|
return ret;
|
|
}
|
|
|
|
void SwitchStatement::Write(CodeWriter* to) const {
|
|
to->Write("switch (%s) {\n", switch_expression_.c_str());
|
|
for (size_t i = 0; i < case_values_.size(); ++i) {
|
|
const string& case_value = case_values_[i];
|
|
const unique_ptr<StatementBlock>& statements = case_logic_[i];
|
|
if (case_value.empty()) {
|
|
to->Write("default:\n");
|
|
} else {
|
|
to->Write("case %s:\n", case_value.c_str());
|
|
}
|
|
statements->Write(to);
|
|
to->Write("break;\n");
|
|
}
|
|
to->Write("}\n");
|
|
}
|
|
|
|
|
|
Assignment::Assignment(const std::string& left, const std::string& right)
|
|
: Assignment(left, new LiteralExpression{right}) {}
|
|
|
|
Assignment::Assignment(const std::string& left, AstNode* right)
|
|
: lhs_(left),
|
|
rhs_(right) {}
|
|
|
|
void Assignment::Write(CodeWriter* to) const {
|
|
to->Write("%s = ", lhs_.c_str());
|
|
rhs_->Write(to);
|
|
to->Write(";\n");
|
|
}
|
|
|
|
MethodCall::MethodCall(const std::string& method_name,
|
|
const std::string& single_argument)
|
|
: MethodCall(method_name, ArgList{single_argument}) {}
|
|
|
|
MethodCall::MethodCall(const std::string& method_name,
|
|
ArgList&& arg_list)
|
|
: method_name_(method_name),
|
|
arguments_{std::move(arg_list)} {}
|
|
|
|
void MethodCall::Write(CodeWriter* to) const {
|
|
to->Write("%s", method_name_.c_str());
|
|
arguments_.Write(to);
|
|
}
|
|
|
|
IfStatement::IfStatement(AstNode* expression, bool invert_expression)
|
|
: expression_(expression),
|
|
invert_expression_(invert_expression) {}
|
|
|
|
void IfStatement::Write(CodeWriter* to) const {
|
|
to->Write("if (%s", (invert_expression_) ? "!(" : "");
|
|
expression_->Write(to);
|
|
to->Write(")%s ", (invert_expression_) ? ")" : "");
|
|
on_true_.Write(to);
|
|
|
|
if (!on_false_.Empty()) {
|
|
to->Write("else ");
|
|
on_false_.Write(to);
|
|
}
|
|
}
|
|
|
|
Statement::Statement(unique_ptr<AstNode> expression)
|
|
: expression_(std::move(expression)) {}
|
|
|
|
Statement::Statement(AstNode* expression) : expression_(expression) {}
|
|
|
|
Statement::Statement(const string& expression)
|
|
: expression_(new LiteralExpression(expression)) {}
|
|
|
|
void Statement::Write(CodeWriter* to) const {
|
|
expression_->Write(to);
|
|
to->Write(";\n");
|
|
}
|
|
|
|
Comparison::Comparison(AstNode* lhs, const string& comparison, AstNode* rhs)
|
|
: left_(lhs),
|
|
right_(rhs),
|
|
operator_(comparison) {}
|
|
|
|
void Comparison::Write(CodeWriter* to) const {
|
|
to->Write("((");
|
|
left_->Write(to);
|
|
to->Write(") %s (", operator_.c_str());
|
|
right_->Write(to);
|
|
to->Write("))");
|
|
}
|
|
|
|
LiteralExpression::LiteralExpression(const std::string& expression)
|
|
: expression_(expression) {}
|
|
|
|
void LiteralExpression::Write(CodeWriter* to) const {
|
|
to->Write("%s", expression_.c_str());
|
|
}
|
|
|
|
CppNamespace::CppNamespace(const std::string& name,
|
|
std::vector<unique_ptr<Declaration>> declarations)
|
|
: declarations_(std::move(declarations)),
|
|
name_(name) {}
|
|
|
|
CppNamespace::CppNamespace(const std::string& name,
|
|
unique_ptr<Declaration> declaration)
|
|
: name_(name) {
|
|
declarations_.push_back(std::move(declaration));
|
|
}
|
|
CppNamespace::CppNamespace(const std::string& name)
|
|
: name_(name) {}
|
|
|
|
void CppNamespace::Write(CodeWriter* to) const {
|
|
to->Write("namespace %s {\n\n", name_.c_str());
|
|
|
|
for (const auto& dec : declarations_) {
|
|
dec->Write(to);
|
|
to->Write("\n");
|
|
}
|
|
|
|
to->Write("} // namespace %s\n", name_.c_str());
|
|
}
|
|
|
|
Document::Document(const std::vector<std::string>& include_list,
|
|
std::vector<unique_ptr<Declaration>> declarations)
|
|
: include_list_(include_list), declarations_(std::move(declarations)) {}
|
|
|
|
void Document::Write(CodeWriter* to) const {
|
|
for (const auto& include : include_list_) {
|
|
to->Write("#include <%s>\n", include.c_str());
|
|
}
|
|
to->Write("\n");
|
|
|
|
for (const auto& declaration : declarations_) {
|
|
declaration->Write(to);
|
|
}
|
|
}
|
|
|
|
CppHeader::CppHeader(const std::vector<std::string>& include_list,
|
|
std::vector<std::unique_ptr<Declaration>> declarations)
|
|
: Document(include_list, std::move(declarations)) {}
|
|
|
|
void CppHeader::Write(CodeWriter* to) const {
|
|
to->Write("#pragma once\n\n");
|
|
|
|
Document::Write(to);
|
|
}
|
|
|
|
CppSource::CppSource(const std::vector<std::string>& include_list,
|
|
std::vector<std::unique_ptr<Declaration>> declarations)
|
|
: Document(include_list, std::move(declarations)) {}
|
|
|
|
} // namespace cpp
|
|
} // namespace aidl
|
|
} // namespace android
|