Serenity Operating System
at master 668 lines 17 kB view raw
1/* 2 * Copyright (c) 2021, Itamar S. <itamar8910@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "AST.h" 8 9namespace Cpp { 10 11static void print_indent(FILE* output, int indent) 12{ 13 for (int i = 0; i < indent * 2; ++i) 14 out(output, " "); 15} 16 17void ASTNode::dump(FILE* output, size_t indent) const 18{ 19 print_indent(output, indent); 20 outln(output, "{}[{}:{}->{}:{}]", class_name(), start().line, start().column, end().line, end().column); 21} 22 23void TranslationUnit::dump(FILE* output, size_t indent) const 24{ 25 ASTNode::dump(output, indent); 26 for (auto const& child : m_declarations) { 27 child->dump(output, indent + 1); 28 } 29} 30 31void FunctionDeclaration::dump(FILE* output, size_t indent) const 32{ 33 ASTNode::dump(output, indent); 34 35 DeprecatedString qualifiers_string; 36 if (!m_qualifiers.is_empty()) { 37 print_indent(output, indent + 1); 38 outln(output, "[{}]", DeprecatedString::join(' ', m_qualifiers)); 39 } 40 41 m_return_type->dump(output, indent + 1); 42 if (!m_name.is_null()) { 43 print_indent(output, indent + 1); 44 outln(output, "{}", m_name->full_name()); 45 } 46 print_indent(output, indent + 1); 47 outln(output, "("); 48 for (auto const& arg : m_parameters) { 49 arg->dump(output, indent + 1); 50 } 51 print_indent(output, indent + 1); 52 outln(output, ")"); 53 if (!m_definition.is_null()) { 54 m_definition->dump(output, indent + 1); 55 } 56} 57 58Vector<NonnullRefPtr<Declaration const>> FunctionDeclaration::declarations() const 59{ 60 Vector<NonnullRefPtr<Declaration const>> declarations; 61 for (auto& arg : m_parameters) { 62 declarations.append(arg); 63 } 64 65 if (m_definition) 66 declarations.extend(m_definition->declarations()); 67 68 return declarations; 69} 70 71void Type::dump(FILE* output, size_t indent) const 72{ 73 ASTNode::dump(output, indent); 74 print_indent(output, indent + 1); 75 outln(output, "{}", to_deprecated_string()); 76} 77 78DeprecatedString NamedType::to_deprecated_string() const 79{ 80 DeprecatedString qualifiers_string; 81 if (!qualifiers().is_empty()) 82 qualifiers_string = DeprecatedString::formatted("[{}] ", DeprecatedString::join(' ', qualifiers())); 83 84 DeprecatedString name; 85 if (is_auto()) 86 name = "auto"; 87 else 88 name = m_name.is_null() ? ""sv : m_name->full_name(); 89 90 return DeprecatedString::formatted("{}{}", qualifiers_string, name); 91} 92 93DeprecatedString Pointer::to_deprecated_string() const 94{ 95 if (!m_pointee) 96 return {}; 97 StringBuilder builder; 98 builder.append(m_pointee->to_deprecated_string()); 99 builder.append('*'); 100 return builder.to_deprecated_string(); 101} 102 103DeprecatedString Reference::to_deprecated_string() const 104{ 105 if (!m_referenced_type) 106 return {}; 107 StringBuilder builder; 108 builder.append(m_referenced_type->to_deprecated_string()); 109 if (m_kind == Kind::Lvalue) 110 builder.append('&'); 111 else 112 builder.append("&&"sv); 113 return builder.to_deprecated_string(); 114} 115 116DeprecatedString FunctionType::to_deprecated_string() const 117{ 118 StringBuilder builder; 119 builder.append(m_return_type->to_deprecated_string()); 120 builder.append('('); 121 bool first = true; 122 for (auto& parameter : m_parameters) { 123 if (first) 124 first = false; 125 else 126 builder.append(", "sv); 127 if (parameter->type()) 128 builder.append(parameter->type()->to_deprecated_string()); 129 if (parameter->name() && !parameter->full_name().is_empty()) { 130 builder.append(' '); 131 builder.append(parameter->full_name()); 132 } 133 } 134 builder.append(')'); 135 return builder.to_deprecated_string(); 136} 137 138void Parameter::dump(FILE* output, size_t indent) const 139{ 140 ASTNode::dump(output, indent); 141 if (m_is_ellipsis) { 142 print_indent(output, indent + 1); 143 outln(output, "..."); 144 } 145 if (!m_name.is_null()) { 146 print_indent(output, indent); 147 outln(output, "{}", m_name->full_name()); 148 } 149 if (m_type) 150 m_type->dump(output, indent + 1); 151} 152 153void FunctionDefinition::dump(FILE* output, size_t indent) const 154{ 155 ASTNode::dump(output, indent); 156 print_indent(output, indent); 157 outln(output, "{{"); 158 for (auto const& statement : m_statements) { 159 statement->dump(output, indent + 1); 160 } 161 print_indent(output, indent); 162 outln(output, "}}"); 163} 164 165Vector<NonnullRefPtr<Declaration const>> FunctionDefinition::declarations() const 166{ 167 Vector<NonnullRefPtr<Declaration const>> declarations; 168 for (auto& statement : m_statements) { 169 declarations.extend(statement->declarations()); 170 } 171 return declarations; 172} 173 174void VariableDeclaration::dump(FILE* output, size_t indent) const 175{ 176 ASTNode::dump(output, indent); 177 if (m_type) 178 m_type->dump(output, indent + 1); 179 print_indent(output, indent + 1); 180 outln(output, "{}", full_name()); 181 if (m_initial_value) 182 m_initial_value->dump(output, indent + 1); 183} 184 185void Identifier::dump(FILE* output, size_t indent) const 186{ 187 ASTNode::dump(output, indent); 188 print_indent(output, indent); 189 outln(output, "{}", m_name); 190} 191 192void NumericLiteral::dump(FILE* output, size_t indent) const 193{ 194 ASTNode::dump(output, indent); 195 print_indent(output, indent); 196 outln(output, "{}", m_value); 197} 198 199void BinaryExpression::dump(FILE* output, size_t indent) const 200{ 201 ASTNode::dump(output, indent); 202 203 char const* op_string = nullptr; 204 switch (m_op) { 205 case BinaryOp::Addition: 206 op_string = "+"; 207 break; 208 case BinaryOp::Subtraction: 209 op_string = "-"; 210 break; 211 case BinaryOp::Multiplication: 212 op_string = "*"; 213 break; 214 case BinaryOp::Division: 215 op_string = "/"; 216 break; 217 case BinaryOp::Modulo: 218 op_string = "%"; 219 break; 220 case BinaryOp::GreaterThan: 221 op_string = ">"; 222 break; 223 case BinaryOp::GreaterThanEquals: 224 op_string = ">="; 225 break; 226 case BinaryOp::LessThan: 227 op_string = "<"; 228 break; 229 case BinaryOp::LessThanEquals: 230 op_string = "<="; 231 break; 232 case BinaryOp::BitwiseAnd: 233 op_string = "&"; 234 break; 235 case BinaryOp::BitwiseOr: 236 op_string = "|"; 237 break; 238 case BinaryOp::BitwiseXor: 239 op_string = "^"; 240 break; 241 case BinaryOp::LeftShift: 242 op_string = "<<"; 243 break; 244 case BinaryOp::RightShift: 245 op_string = ">>"; 246 break; 247 case BinaryOp::EqualsEquals: 248 op_string = "=="; 249 break; 250 case BinaryOp::NotEqual: 251 op_string = "!="; 252 break; 253 case BinaryOp::LogicalOr: 254 op_string = "||"; 255 break; 256 case BinaryOp::LogicalAnd: 257 op_string = "&&"; 258 break; 259 case BinaryOp::Arrow: 260 op_string = "->"; 261 break; 262 } 263 264 m_lhs->dump(output, indent + 1); 265 print_indent(output, indent + 1); 266 VERIFY(op_string); 267 outln(output, "{}", op_string); 268 m_rhs->dump(output, indent + 1); 269} 270 271void AssignmentExpression::dump(FILE* output, size_t indent) const 272{ 273 ASTNode::dump(output, indent); 274 275 char const* op_string = nullptr; 276 switch (m_op) { 277 case AssignmentOp::Assignment: 278 op_string = "="; 279 break; 280 case AssignmentOp::AdditionAssignment: 281 op_string = "+="; 282 break; 283 case AssignmentOp::SubtractionAssignment: 284 op_string = "-="; 285 break; 286 } 287 288 m_lhs->dump(output, indent + 1); 289 print_indent(output, indent + 1); 290 VERIFY(op_string); 291 outln(output, "{}", op_string); 292 m_rhs->dump(output, indent + 1); 293} 294 295void FunctionCall::dump(FILE* output, size_t indent) const 296{ 297 ASTNode::dump(output, indent); 298 m_callee->dump(output, indent + 1); 299 for (auto const& arg : m_arguments) { 300 arg->dump(output, indent + 1); 301 } 302} 303 304void StringLiteral::dump(FILE* output, size_t indent) const 305{ 306 ASTNode::dump(output, indent); 307 print_indent(output, indent + 1); 308 outln(output, "{}", m_value); 309} 310 311void ReturnStatement::dump(FILE* output, size_t indent) const 312{ 313 ASTNode::dump(output, indent); 314 if (m_value) 315 m_value->dump(output, indent + 1); 316} 317 318void EnumDeclaration::dump(FILE* output, size_t indent) const 319{ 320 ASTNode::dump(output, indent); 321 print_indent(output, indent); 322 outln(output, "{}", full_name()); 323 for (auto& entry : m_entries) { 324 print_indent(output, indent + 1); 325 outln(output, "{}", entry.name); 326 if (entry.value) 327 entry.value->dump(output, indent + 2); 328 } 329} 330 331void StructOrClassDeclaration::dump(FILE* output, size_t indent) const 332{ 333 ASTNode::dump(output, indent); 334 print_indent(output, indent); 335 outln(output, "{}", full_name()); 336 if (!m_baseclasses.is_empty()) { 337 print_indent(output, indent + 1); 338 outln(output, ":"); 339 for (size_t i = 0; i < m_baseclasses.size(); ++i) { 340 auto& baseclass = m_baseclasses[i]; 341 baseclass->dump(output, indent + 1); 342 if (i < m_baseclasses.size() - 1) { 343 print_indent(output, indent + 1); 344 outln(output, ","); 345 } 346 } 347 } 348 outln(output, ""); 349 for (auto& member : m_members) { 350 member->dump(output, indent + 1); 351 } 352} 353Vector<NonnullRefPtr<Declaration const>> StructOrClassDeclaration::declarations() const 354{ 355 Vector<NonnullRefPtr<Declaration const>> declarations; 356 for (auto& member : m_members) 357 declarations.append(member); 358 return declarations; 359} 360 361void UnaryExpression::dump(FILE* output, size_t indent) const 362{ 363 ASTNode::dump(output, indent); 364 365 char const* op_string = nullptr; 366 switch (m_op) { 367 case UnaryOp::BitwiseNot: 368 op_string = "~"; 369 break; 370 case UnaryOp::Not: 371 op_string = "!"; 372 break; 373 case UnaryOp::Plus: 374 op_string = "+"; 375 break; 376 case UnaryOp::Minus: 377 op_string = "-"; 378 break; 379 case UnaryOp::PlusPlus: 380 op_string = "++"; 381 break; 382 case UnaryOp::Address: 383 op_string = "&"; 384 break; 385 default: 386 op_string = "<invalid>"; 387 } 388 389 VERIFY(op_string); 390 print_indent(output, indent + 1); 391 outln(output, "{}", op_string); 392 m_lhs->dump(output, indent + 1); 393} 394 395void BooleanLiteral::dump(FILE* output, size_t indent) const 396{ 397 ASTNode::dump(output, indent); 398 print_indent(output, indent + 1); 399 outln(output, "{}", m_value ? "true" : "false"); 400} 401 402void Pointer::dump(FILE* output, size_t indent) const 403{ 404 ASTNode::dump(output, indent); 405 if (!m_pointee.is_null()) { 406 m_pointee->dump(output, indent + 1); 407 } 408} 409 410void Reference::dump(FILE* output, size_t indent) const 411{ 412 ASTNode::dump(output, indent); 413 print_indent(output, indent + 1); 414 outln(output, "{}", m_kind == Kind::Lvalue ? "&" : "&&"); 415 if (!m_referenced_type.is_null()) { 416 m_referenced_type->dump(output, indent + 1); 417 } 418} 419 420void FunctionType::dump(FILE* output, size_t indent) const 421{ 422 ASTNode::dump(output, indent); 423 if (m_return_type) 424 m_return_type->dump(output, indent + 1); 425 print_indent(output, indent + 1); 426 outln("("); 427 for (auto& parameter : m_parameters) 428 parameter->dump(output, indent + 2); 429 print_indent(output, indent + 1); 430 outln(")"); 431} 432 433void MemberExpression::dump(FILE* output, size_t indent) const 434{ 435 ASTNode::dump(output, indent); 436 m_object->dump(output, indent + 1); 437 m_property->dump(output, indent + 1); 438} 439 440void BlockStatement::dump(FILE* output, size_t indent) const 441{ 442 ASTNode::dump(output, indent); 443 for (auto& statement : m_statements) { 444 statement->dump(output, indent + 1); 445 } 446} 447 448void ForStatement::dump(FILE* output, size_t indent) const 449{ 450 ASTNode::dump(output, indent); 451 if (m_init) 452 m_init->dump(output, indent + 1); 453 if (m_test) 454 m_test->dump(output, indent + 1); 455 if (m_update) 456 m_update->dump(output, indent + 1); 457 if (m_body) 458 m_body->dump(output, indent + 1); 459} 460 461Vector<NonnullRefPtr<Declaration const>> Statement::declarations() const 462{ 463 if (is_declaration()) { 464 Vector<NonnullRefPtr<Declaration const>> vec; 465 auto const& decl = static_cast<Declaration const&>(*this); 466 vec.empend(const_cast<Declaration&>(decl)); 467 return vec; 468 } 469 return {}; 470} 471 472Vector<NonnullRefPtr<Declaration const>> ForStatement::declarations() const 473{ 474 Vector<NonnullRefPtr<Declaration const>> declarations; 475 if (m_init) 476 declarations.extend(m_init->declarations()); 477 if (m_body) 478 declarations.extend(m_body->declarations()); 479 return declarations; 480} 481 482Vector<NonnullRefPtr<Declaration const>> BlockStatement::declarations() const 483{ 484 Vector<NonnullRefPtr<Declaration const>> declarations; 485 for (auto& statement : m_statements) { 486 declarations.extend(statement->declarations()); 487 } 488 return declarations; 489} 490 491void IfStatement::dump(FILE* output, size_t indent) const 492{ 493 ASTNode::dump(output, indent); 494 if (m_predicate) { 495 print_indent(output, indent + 1); 496 outln(output, "Predicate:"); 497 m_predicate->dump(output, indent + 1); 498 } 499 if (m_then) { 500 print_indent(output, indent + 1); 501 outln(output, "Then:"); 502 m_then->dump(output, indent + 1); 503 } 504 if (m_else) { 505 print_indent(output, indent + 1); 506 outln(output, "Else:"); 507 m_else->dump(output, indent + 1); 508 } 509} 510 511Vector<NonnullRefPtr<Declaration const>> IfStatement::declarations() const 512{ 513 Vector<NonnullRefPtr<Declaration const>> declarations; 514 if (m_predicate) 515 declarations.extend(m_predicate->declarations()); 516 if (m_then) 517 declarations.extend(m_then->declarations()); 518 if (m_else) 519 declarations.extend(m_else->declarations()); 520 return declarations; 521} 522 523void NamespaceDeclaration::dump(FILE* output, size_t indent) const 524{ 525 ASTNode::dump(output, indent); 526 print_indent(output, indent + 1); 527 outln(output, "{}", full_name()); 528 for (auto& decl : m_declarations) 529 decl->dump(output, indent + 1); 530} 531 532void NullPointerLiteral::dump(FILE* output, size_t indent) const 533{ 534 ASTNode::dump(output, indent); 535} 536 537void Name::dump(FILE* output, size_t indent) const 538{ 539 ASTNode::dump(output, indent); 540 print_indent(output, indent); 541 outln(output, "{}", full_name()); 542} 543 544StringView Name::full_name() const 545{ 546 if (m_full_name.has_value()) 547 return *m_full_name; 548 549 StringBuilder builder; 550 if (!m_scope.is_empty()) { 551 for (auto& scope : m_scope) { 552 builder.appendff("{}::", scope->name()); 553 } 554 } 555 m_full_name = DeprecatedString::formatted("{}{}", builder.to_deprecated_string(), m_name.is_null() ? ""sv : m_name->name()); 556 return *m_full_name; 557} 558 559StringView TemplatizedName::full_name() const 560{ 561 if (m_full_name.has_value()) 562 return *m_full_name; 563 564 StringBuilder name; 565 name.append(Name::full_name()); 566 name.append('<'); 567 for (auto& type : m_template_arguments) { 568 name.append(type->to_deprecated_string()); 569 } 570 name.append('>'); 571 m_full_name = name.to_deprecated_string(); 572 return *m_full_name; 573} 574 575void CppCastExpression::dump(FILE* output, size_t indent) const 576{ 577 ASTNode::dump(output, indent); 578 579 print_indent(output, indent); 580 outln(output, "{}", m_cast_type); 581 582 print_indent(output, indent + 1); 583 outln(output, "<"); 584 if (m_type) 585 m_type->dump(output, indent + 1); 586 print_indent(output, indent + 1); 587 outln(output, ">"); 588 589 if (m_expression) 590 m_expression->dump(output, indent + 1); 591} 592 593void SizeofExpression::dump(FILE* output, size_t indent) const 594{ 595 ASTNode::dump(output, indent); 596 if (m_type) 597 m_type->dump(output, indent + 1); 598} 599 600void BracedInitList::dump(FILE* output, size_t indent) const 601{ 602 ASTNode::dump(output, indent); 603 for (auto& exp : m_expressions) { 604 exp->dump(output, indent + 1); 605 } 606} 607 608void CStyleCastExpression::dump(FILE* output, size_t indent) const 609{ 610 ASTNode::dump(output, indent); 611 if (m_type) 612 m_type->dump(output, indent + 1); 613 if (m_expression) 614 m_expression->dump(output, indent + 1); 615} 616 617void Constructor::dump(FILE* output, size_t indent) const 618{ 619 print_indent(output, indent); 620 outln(output, "C'tor"); 621 print_indent(output, indent + 1); 622 outln(output, "("); 623 for (auto const& arg : parameters()) { 624 arg->dump(output, indent + 1); 625 } 626 print_indent(output, indent + 1); 627 outln(output, ")"); 628 if (definition()) { 629 definition()->dump(output, indent + 1); 630 } 631} 632 633void Destructor::dump(FILE* output, size_t indent) const 634{ 635 print_indent(output, indent); 636 outln(output, "D'tor"); 637 print_indent(output, indent + 1); 638 outln(output, "("); 639 for (auto const& arg : parameters()) { 640 arg->dump(output, indent + 1); 641 } 642 print_indent(output, indent + 1); 643 outln(output, ")"); 644 if (definition()) { 645 definition()->dump(output, indent + 1); 646 } 647} 648 649StringView Declaration::full_name() const 650{ 651 if (!m_full_name.has_value()) { 652 if (m_name) 653 m_full_name = m_name->full_name(); 654 else 655 m_full_name = DeprecatedString::empty(); 656 } 657 658 return *m_full_name; 659} 660 661void UsingNamespaceDeclaration::dump(FILE* output, size_t indent) const 662{ 663 ASTNode::dump(output, indent); 664 print_indent(output, indent + 1); 665 outln(output, "{}", full_name()); 666} 667 668}