123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695 |
- /*
- * Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include "AST.h"
- namespace Cpp {
- static void print_indent(FILE* output, int indent)
- {
- for (int i = 0; i < indent * 2; ++i)
- out(output, " ");
- }
- void ASTNode::dump(FILE* output, size_t indent) const
- {
- print_indent(output, indent);
- outln(output, "{}[{}:{}->{}:{}]", class_name(), start().line, start().column, end().line, end().column);
- }
- void TranslationUnit::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- for (auto const& child : m_declarations) {
- child->dump(output, indent + 1);
- }
- }
- void FunctionDeclaration::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- ByteString qualifiers_string;
- if (!m_qualifiers.is_empty()) {
- print_indent(output, indent + 1);
- outln(output, "[{}]", ByteString::join(' ', m_qualifiers));
- }
- m_return_type->dump(output, indent + 1);
- if (!m_name.is_null()) {
- print_indent(output, indent + 1);
- outln(output, "{}", m_name->full_name());
- }
- print_indent(output, indent + 1);
- outln(output, "(");
- for (auto const& arg : m_parameters) {
- arg->dump(output, indent + 1);
- }
- print_indent(output, indent + 1);
- outln(output, ")");
- if (!m_definition.is_null()) {
- m_definition->dump(output, indent + 1);
- }
- }
- Vector<NonnullRefPtr<Declaration const>> FunctionDeclaration::declarations() const
- {
- Vector<NonnullRefPtr<Declaration const>> declarations;
- for (auto& arg : m_parameters) {
- declarations.append(arg);
- }
- if (m_definition)
- declarations.extend(m_definition->declarations());
- return declarations;
- }
- void Type::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent + 1);
- outln(output, "{}", to_byte_string());
- }
- ByteString NamedType::to_byte_string() const
- {
- ByteString qualifiers_string;
- if (!qualifiers().is_empty())
- qualifiers_string = ByteString::formatted("[{}] ", ByteString::join(' ', qualifiers()));
- ByteString name;
- if (is_auto())
- name = "auto";
- else
- name = m_name.is_null() ? ""sv : m_name->full_name();
- return ByteString::formatted("{}{}", qualifiers_string, name);
- }
- ByteString Pointer::to_byte_string() const
- {
- if (!m_pointee)
- return {};
- StringBuilder builder;
- builder.append(m_pointee->to_byte_string());
- builder.append('*');
- return builder.to_byte_string();
- }
- ByteString Reference::to_byte_string() const
- {
- if (!m_referenced_type)
- return {};
- StringBuilder builder;
- builder.append(m_referenced_type->to_byte_string());
- if (m_kind == Kind::Lvalue)
- builder.append('&');
- else
- builder.append("&&"sv);
- return builder.to_byte_string();
- }
- ByteString FunctionType::to_byte_string() const
- {
- StringBuilder builder;
- builder.append(m_return_type->to_byte_string());
- builder.append('(');
- bool first = true;
- for (auto& parameter : m_parameters) {
- if (first)
- first = false;
- else
- builder.append(", "sv);
- if (parameter->type())
- builder.append(parameter->type()->to_byte_string());
- if (parameter->name() && !parameter->full_name().is_empty()) {
- builder.append(' ');
- builder.append(parameter->full_name());
- }
- }
- builder.append(')');
- return builder.to_byte_string();
- }
- void Parameter::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (m_is_ellipsis) {
- print_indent(output, indent + 1);
- outln(output, "...");
- }
- if (!m_name.is_null()) {
- print_indent(output, indent);
- outln(output, "{}", m_name->full_name());
- }
- if (m_type)
- m_type->dump(output, indent + 1);
- }
- void FunctionDefinition::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent);
- outln(output, "{{");
- for (auto const& statement : m_statements) {
- statement->dump(output, indent + 1);
- }
- print_indent(output, indent);
- outln(output, "}}");
- }
- Vector<NonnullRefPtr<Declaration const>> FunctionDefinition::declarations() const
- {
- Vector<NonnullRefPtr<Declaration const>> declarations;
- for (auto& statement : m_statements) {
- declarations.extend(statement->declarations());
- }
- return declarations;
- }
- void VariableDeclaration::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (m_type)
- m_type->dump(output, indent + 1);
- print_indent(output, indent + 1);
- outln(output, "{}", full_name());
- if (m_initial_value)
- m_initial_value->dump(output, indent + 1);
- }
- void Identifier::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent);
- outln(output, "{}", m_name);
- }
- void NumericLiteral::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent);
- outln(output, "{}", m_value);
- }
- void BinaryExpression::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- char const* op_string = nullptr;
- switch (m_op) {
- case BinaryOp::Addition:
- op_string = "+";
- break;
- case BinaryOp::Subtraction:
- op_string = "-";
- break;
- case BinaryOp::Multiplication:
- op_string = "*";
- break;
- case BinaryOp::Division:
- op_string = "/";
- break;
- case BinaryOp::Modulo:
- op_string = "%";
- break;
- case BinaryOp::GreaterThan:
- op_string = ">";
- break;
- case BinaryOp::GreaterThanEquals:
- op_string = ">=";
- break;
- case BinaryOp::LessThan:
- op_string = "<";
- break;
- case BinaryOp::LessThanEquals:
- op_string = "<=";
- break;
- case BinaryOp::BitwiseAnd:
- op_string = "&";
- break;
- case BinaryOp::BitwiseOr:
- op_string = "|";
- break;
- case BinaryOp::BitwiseXor:
- op_string = "^";
- break;
- case BinaryOp::LeftShift:
- op_string = "<<";
- break;
- case BinaryOp::RightShift:
- op_string = ">>";
- break;
- case BinaryOp::EqualsEquals:
- op_string = "==";
- break;
- case BinaryOp::NotEqual:
- op_string = "!=";
- break;
- case BinaryOp::LogicalOr:
- op_string = "||";
- break;
- case BinaryOp::LogicalAnd:
- op_string = "&&";
- break;
- case BinaryOp::Arrow:
- op_string = "->";
- break;
- }
- m_lhs->dump(output, indent + 1);
- print_indent(output, indent + 1);
- VERIFY(op_string);
- outln(output, "{}", op_string);
- m_rhs->dump(output, indent + 1);
- }
- void AssignmentExpression::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- char const* op_string = nullptr;
- switch (m_op) {
- case AssignmentOp::Assignment:
- op_string = "=";
- break;
- case AssignmentOp::AdditionAssignment:
- op_string = "+=";
- break;
- case AssignmentOp::SubtractionAssignment:
- op_string = "-=";
- break;
- }
- m_lhs->dump(output, indent + 1);
- print_indent(output, indent + 1);
- VERIFY(op_string);
- outln(output, "{}", op_string);
- m_rhs->dump(output, indent + 1);
- }
- void FunctionCall::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- m_callee->dump(output, indent + 1);
- for (auto const& arg : m_arguments) {
- arg->dump(output, indent + 1);
- }
- }
- void StringLiteral::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent + 1);
- outln(output, "{}", m_value);
- }
- void ReturnStatement::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (m_value)
- m_value->dump(output, indent + 1);
- }
- void EnumDeclaration::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent);
- outln(output, "{}", full_name());
- for (auto& entry : m_entries) {
- print_indent(output, indent + 1);
- outln(output, "{}", entry.name);
- if (entry.value)
- entry.value->dump(output, indent + 2);
- }
- }
- void StructOrClassDeclaration::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent);
- outln(output, "{}", full_name());
- if (!m_baseclasses.is_empty()) {
- print_indent(output, indent + 1);
- outln(output, ":");
- for (size_t i = 0; i < m_baseclasses.size(); ++i) {
- auto& baseclass = m_baseclasses[i];
- baseclass->dump(output, indent + 1);
- if (i < m_baseclasses.size() - 1) {
- print_indent(output, indent + 1);
- outln(output, ",");
- }
- }
- }
- outln(output, "");
- for (auto& member : m_members) {
- member->dump(output, indent + 1);
- }
- }
- Vector<NonnullRefPtr<Declaration const>> StructOrClassDeclaration::declarations() const
- {
- Vector<NonnullRefPtr<Declaration const>> declarations;
- for (auto& member : m_members)
- declarations.append(member);
- return declarations;
- }
- void UnaryExpression::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- char const* op_string = nullptr;
- switch (m_op) {
- case UnaryOp::BitwiseNot:
- op_string = "~";
- break;
- case UnaryOp::Not:
- op_string = "!";
- break;
- case UnaryOp::Plus:
- op_string = "+";
- break;
- case UnaryOp::Minus:
- op_string = "-";
- break;
- case UnaryOp::PlusPlus:
- op_string = "++";
- break;
- case UnaryOp::Address:
- op_string = "&";
- break;
- default:
- op_string = "<invalid>";
- }
- VERIFY(op_string);
- print_indent(output, indent + 1);
- outln(output, "{}", op_string);
- m_lhs->dump(output, indent + 1);
- }
- void BooleanLiteral::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent + 1);
- outln(output, "{}", m_value ? "true" : "false");
- }
- void Pointer::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (!m_pointee.is_null()) {
- m_pointee->dump(output, indent + 1);
- }
- }
- void Reference::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent + 1);
- outln(output, "{}", m_kind == Kind::Lvalue ? "&" : "&&");
- if (!m_referenced_type.is_null()) {
- m_referenced_type->dump(output, indent + 1);
- }
- }
- void FunctionType::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (m_return_type)
- m_return_type->dump(output, indent + 1);
- print_indent(output, indent + 1);
- outln("(");
- for (auto& parameter : m_parameters)
- parameter->dump(output, indent + 2);
- print_indent(output, indent + 1);
- outln(")");
- }
- void MemberExpression::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- m_object->dump(output, indent + 1);
- m_property->dump(output, indent + 1);
- }
- void BlockStatement::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- for (auto& statement : m_statements) {
- statement->dump(output, indent + 1);
- }
- }
- void ForStatement::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (m_init)
- m_init->dump(output, indent + 1);
- if (m_test)
- m_test->dump(output, indent + 1);
- if (m_update)
- m_update->dump(output, indent + 1);
- if (m_body)
- m_body->dump(output, indent + 1);
- }
- Vector<NonnullRefPtr<Declaration const>> Statement::declarations() const
- {
- if (is_declaration()) {
- Vector<NonnullRefPtr<Declaration const>> vec;
- auto const& decl = static_cast<Declaration const&>(*this);
- vec.empend(const_cast<Declaration&>(decl));
- return vec;
- }
- return {};
- }
- Vector<NonnullRefPtr<Declaration const>> ForStatement::declarations() const
- {
- Vector<NonnullRefPtr<Declaration const>> declarations;
- if (m_init)
- declarations.extend(m_init->declarations());
- if (m_body)
- declarations.extend(m_body->declarations());
- return declarations;
- }
- Vector<NonnullRefPtr<Declaration const>> BlockStatement::declarations() const
- {
- Vector<NonnullRefPtr<Declaration const>> declarations;
- for (auto& statement : m_statements) {
- declarations.extend(statement->declarations());
- }
- return declarations;
- }
- void IfStatement::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (m_predicate) {
- print_indent(output, indent + 1);
- outln(output, "Predicate:");
- m_predicate->dump(output, indent + 1);
- }
- if (m_then) {
- print_indent(output, indent + 1);
- outln(output, "Then:");
- m_then->dump(output, indent + 1);
- }
- if (m_else) {
- print_indent(output, indent + 1);
- outln(output, "Else:");
- m_else->dump(output, indent + 1);
- }
- }
- Vector<NonnullRefPtr<Declaration const>> IfStatement::declarations() const
- {
- Vector<NonnullRefPtr<Declaration const>> declarations;
- if (m_predicate)
- declarations.extend(m_predicate->declarations());
- if (m_then)
- declarations.extend(m_then->declarations());
- if (m_else)
- declarations.extend(m_else->declarations());
- return declarations;
- }
- void NamespaceDeclaration::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent + 1);
- outln(output, "{}", full_name());
- for (auto& decl : m_declarations)
- decl->dump(output, indent + 1);
- }
- void NullPointerLiteral::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- }
- void Name::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent);
- outln(output, "{}", full_name());
- }
- StringView Name::full_name() const
- {
- if (m_full_name.has_value())
- return *m_full_name;
- StringBuilder builder;
- if (!m_scope.is_empty()) {
- for (auto& scope : m_scope) {
- builder.appendff("{}::", scope->name());
- }
- }
- m_full_name = ByteString::formatted("{}{}", builder.to_byte_string(), m_name.is_null() ? ""sv : m_name->name());
- return *m_full_name;
- }
- StringView TemplatizedName::full_name() const
- {
- if (m_full_name.has_value())
- return *m_full_name;
- StringBuilder name;
- name.append(Name::full_name());
- name.append('<');
- for (auto& type : m_template_arguments) {
- name.append(type->to_byte_string());
- }
- name.append('>');
- m_full_name = name.to_byte_string();
- return *m_full_name;
- }
- void SizedName::dump(FILE* output, size_t indent) const
- {
- Name::dump(output, indent);
- print_indent(output, indent + 1);
- StringBuilder dimension_info;
- for (auto const& dim : m_dimensions) {
- dimension_info.append('[');
- dimension_info.append(dim);
- dimension_info.append(']');
- }
- if (dimension_info.is_empty()) {
- dimension_info.append("[]"sv);
- }
- outln(output, "{}", dimension_info.to_byte_string());
- }
- void CppCastExpression::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent);
- outln(output, "{}", m_cast_type);
- print_indent(output, indent + 1);
- outln(output, "<");
- if (m_type)
- m_type->dump(output, indent + 1);
- print_indent(output, indent + 1);
- outln(output, ">");
- if (m_expression)
- m_expression->dump(output, indent + 1);
- }
- void SizeofExpression::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (m_type)
- m_type->dump(output, indent + 1);
- }
- void BracedInitList::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- for (auto& exp : m_expressions) {
- exp->dump(output, indent + 1);
- }
- }
- void CStyleCastExpression::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- if (m_type)
- m_type->dump(output, indent + 1);
- if (m_expression)
- m_expression->dump(output, indent + 1);
- }
- void Constructor::dump(FILE* output, size_t indent) const
- {
- print_indent(output, indent);
- outln(output, "C'tor");
- print_indent(output, indent + 1);
- outln(output, "(");
- for (auto const& arg : parameters()) {
- arg->dump(output, indent + 1);
- }
- print_indent(output, indent + 1);
- outln(output, ")");
- if (definition()) {
- definition()->dump(output, indent + 1);
- }
- }
- void Destructor::dump(FILE* output, size_t indent) const
- {
- print_indent(output, indent);
- outln(output, "D'tor");
- print_indent(output, indent + 1);
- outln(output, "(");
- for (auto const& arg : parameters()) {
- arg->dump(output, indent + 1);
- }
- print_indent(output, indent + 1);
- outln(output, ")");
- if (definition()) {
- definition()->dump(output, indent + 1);
- }
- }
- StringView Declaration::full_name() const
- {
- if (!m_full_name.has_value()) {
- if (m_name)
- m_full_name = m_name->full_name();
- else
- m_full_name = ByteString::empty();
- }
- return *m_full_name;
- }
- void UsingNamespaceDeclaration::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent + 1);
- outln(output, "{}", full_name());
- }
- void TypedefDeclaration::dump(FILE* output, size_t indent) const
- {
- ASTNode::dump(output, indent);
- print_indent(output, indent + 1);
- outln(output, "{}", full_name());
- if (m_alias)
- m_alias->dump(output, indent + 1);
- }
- }
|