1 //===-- lib/Parser/unparse.cpp --------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // Generates Fortran from the content of a parse tree, using the 10 // traversal templates in parse-tree-visitor.h. 11 12 #include "flang/Parser/unparse.h" 13 #include "flang/Common/Fortran.h" 14 #include "flang/Common/idioms.h" 15 #include "flang/Common/indirection.h" 16 #include "flang/Parser/characters.h" 17 #include "flang/Parser/parse-tree-visitor.h" 18 #include "flang/Parser/parse-tree.h" 19 #include "flang/Parser/tools.h" 20 #include "llvm/Support/raw_ostream.h" 21 #include <algorithm> 22 #include <cinttypes> 23 #include <cstddef> 24 #include <set> 25 26 namespace Fortran::parser { 27 28 class UnparseVisitor { 29 public: 30 UnparseVisitor(llvm::raw_ostream &out, int indentationAmount, 31 Encoding encoding, bool capitalize, bool backslashEscapes, 32 preStatementType *preStatement, AnalyzedObjectsAsFortran *asFortran) 33 : out_{out}, indentationAmount_{indentationAmount}, encoding_{encoding}, 34 capitalizeKeywords_{capitalize}, backslashEscapes_{backslashEscapes}, 35 preStatement_{preStatement}, asFortran_{asFortran} {} 36 37 // In nearly all cases, this code avoids defining Boolean-valued Pre() 38 // callbacks for the parse tree walking framework in favor of two void 39 // functions, Before() and Unparse(), which imply true and false return 40 // values for Pre() respectively. 41 template <typename T> void Before(const T &) {} 42 template <typename T> double Unparse(const T &); // not void, never used 43 44 template <typename T> bool Pre(const T &x) { 45 if constexpr (std::is_void_v<decltype(Unparse(x))>) { 46 // There is a local definition of Unparse() for this type. It 47 // overrides the parse tree walker's default Walk() over the descendents. 48 Before(x); 49 Unparse(x); 50 Post(x); 51 return false; // Walk() does not visit descendents 52 } else if constexpr (HasTypedExpr<T>::value) { 53 // Format the expression representation from semantics 54 if (asFortran_ && x.typedExpr) { 55 asFortran_->expr(out_, *x.typedExpr); 56 return false; 57 } else { 58 return true; 59 } 60 } else { 61 Before(x); 62 return true; // there's no Unparse() defined here, Walk() the descendents 63 } 64 } 65 template <typename T> void Post(const T &) {} 66 67 // Emit simple types as-is. 68 void Unparse(const std::string &x) { Put(x); } 69 void Unparse(int x) { Put(std::to_string(x)); } 70 void Unparse(unsigned int x) { Put(std::to_string(x)); } 71 void Unparse(long x) { Put(std::to_string(x)); } 72 void Unparse(unsigned long x) { Put(std::to_string(x)); } 73 void Unparse(long long x) { Put(std::to_string(x)); } 74 void Unparse(unsigned long long x) { Put(std::to_string(x)); } 75 void Unparse(char x) { Put(x); } 76 77 // Statement labels and ends of lines 78 template <typename T> void Before(const Statement<T> &x) { 79 if (preStatement_) { 80 (*preStatement_)(x.source, out_, indent_); 81 } 82 Walk(x.label, " "); 83 } 84 template <typename T> void Post(const Statement<T> &) { Put('\n'); } 85 86 // The special-case formatting functions for these productions are 87 // ordered to correspond roughly to their order of appearance in 88 // the Fortran 2018 standard (and parse-tree.h). 89 90 void Unparse(const Program &x) { // R501 91 Walk("", x.v, "\n"); // put blank lines between ProgramUnits 92 } 93 94 void Unparse(const Name &x) { // R603 95 Put(x.ToString()); 96 } 97 void Unparse(const DefinedOperator::IntrinsicOperator &x) { // R608 98 switch (x) { 99 case DefinedOperator::IntrinsicOperator::Power: 100 Put("**"); 101 break; 102 case DefinedOperator::IntrinsicOperator::Multiply: 103 Put('*'); 104 break; 105 case DefinedOperator::IntrinsicOperator::Divide: 106 Put('/'); 107 break; 108 case DefinedOperator::IntrinsicOperator::Add: 109 Put('+'); 110 break; 111 case DefinedOperator::IntrinsicOperator::Subtract: 112 Put('-'); 113 break; 114 case DefinedOperator::IntrinsicOperator::Concat: 115 Put("//"); 116 break; 117 case DefinedOperator::IntrinsicOperator::LT: 118 Put('<'); 119 break; 120 case DefinedOperator::IntrinsicOperator::LE: 121 Put("<="); 122 break; 123 case DefinedOperator::IntrinsicOperator::EQ: 124 Put("=="); 125 break; 126 case DefinedOperator::IntrinsicOperator::NE: 127 Put("/="); 128 break; 129 case DefinedOperator::IntrinsicOperator::GE: 130 Put(">="); 131 break; 132 case DefinedOperator::IntrinsicOperator::GT: 133 Put('>'); 134 break; 135 default: 136 Put('.'), Word(DefinedOperator::EnumToString(x)), Put('.'); 137 } 138 } 139 void Post(const Star &) { Put('*'); } // R701 &c. 140 void Post(const TypeParamValue::Deferred &) { Put(':'); } // R701 141 void Unparse(const DeclarationTypeSpec::Type &x) { // R703 142 Word("TYPE("), Walk(x.derived), Put(')'); 143 } 144 void Unparse(const DeclarationTypeSpec::Class &x) { 145 Word("CLASS("), Walk(x.derived), Put(')'); 146 } 147 void Post(const DeclarationTypeSpec::ClassStar &) { Word("CLASS(*)"); } 148 void Post(const DeclarationTypeSpec::TypeStar &) { Word("TYPE(*)"); } 149 void Unparse(const DeclarationTypeSpec::Record &x) { 150 Word("RECORD/"), Walk(x.v), Put('/'); 151 } 152 void Before(const IntrinsicTypeSpec::Real &) { // R704 153 Word("REAL"); 154 } 155 void Before(const IntrinsicTypeSpec::Complex &) { Word("COMPLEX"); } 156 void Post(const IntrinsicTypeSpec::DoublePrecision &) { 157 Word("DOUBLE PRECISION"); 158 } 159 void Before(const IntrinsicTypeSpec::Character &) { Word("CHARACTER"); } 160 void Before(const IntrinsicTypeSpec::Logical &) { Word("LOGICAL"); } 161 void Post(const IntrinsicTypeSpec::DoubleComplex &) { 162 Word("DOUBLE COMPLEX"); 163 } 164 void Before(const IntegerTypeSpec &) { // R705 165 Word("INTEGER"); 166 } 167 void Unparse(const KindSelector &x) { // R706 168 common::visit( 169 common::visitors{ 170 [&](const ScalarIntConstantExpr &y) { 171 Put('('), Word("KIND="), Walk(y), Put(')'); 172 }, 173 [&](const KindSelector::StarSize &y) { Put('*'), Walk(y.v); }, 174 }, 175 x.u); 176 } 177 void Unparse(const SignedIntLiteralConstant &x) { // R707 178 Put(std::get<CharBlock>(x.t).ToString()); 179 Walk("_", std::get<std::optional<KindParam>>(x.t)); 180 } 181 void Unparse(const IntLiteralConstant &x) { // R708 182 Put(std::get<CharBlock>(x.t).ToString()); 183 Walk("_", std::get<std::optional<KindParam>>(x.t)); 184 } 185 void Unparse(const Sign &x) { // R712 186 Put(x == Sign::Negative ? '-' : '+'); 187 } 188 void Unparse(const RealLiteralConstant &x) { // R714, R715 189 Put(x.real.source.ToString()), Walk("_", x.kind); 190 } 191 void Unparse(const ComplexLiteralConstant &x) { // R718 - R720 192 Put('('), Walk(x.t, ","), Put(')'); 193 } 194 void Unparse(const CharSelector::LengthAndKind &x) { // R721 195 Put('('), Word("KIND="), Walk(x.kind); 196 Walk(", LEN=", x.length), Put(')'); 197 } 198 void Unparse(const LengthSelector &x) { // R722 199 common::visit(common::visitors{ 200 [&](const TypeParamValue &y) { 201 Put('('), Word("LEN="), Walk(y), Put(')'); 202 }, 203 [&](const CharLength &y) { Put('*'), Walk(y); }, 204 }, 205 x.u); 206 } 207 void Unparse(const CharLength &x) { // R723 208 common::visit( 209 common::visitors{ 210 [&](const TypeParamValue &y) { Put('('), Walk(y), Put(')'); }, 211 [&](const std::int64_t &y) { Walk(y); }, 212 }, 213 x.u); 214 } 215 void Unparse(const CharLiteralConstant &x) { // R724 216 const auto &str{std::get<std::string>(x.t)}; 217 if (const auto &k{std::get<std::optional<KindParam>>(x.t)}) { 218 Walk(*k), Put('_'); 219 } 220 PutNormalized(str); 221 } 222 void Unparse(const HollerithLiteralConstant &x) { 223 auto ucs{DecodeString<std::u32string, Encoding::UTF_8>(x.v, false)}; 224 Unparse(ucs.size()); 225 Put('H'); 226 for (char32_t ch : ucs) { 227 EncodedCharacter encoded{EncodeCharacter(encoding_, ch)}; 228 for (int j{0}; j < encoded.bytes; ++j) { 229 Put(encoded.buffer[j]); 230 } 231 } 232 } 233 void Unparse(const LogicalLiteralConstant &x) { // R725 234 Put(std::get<bool>(x.t) ? ".TRUE." : ".FALSE."); 235 Walk("_", std::get<std::optional<KindParam>>(x.t)); 236 } 237 void Unparse(const DerivedTypeStmt &x) { // R727 238 Word("TYPE"), Walk(", ", std::get<std::list<TypeAttrSpec>>(x.t), ", "); 239 Put(" :: "), Walk(std::get<Name>(x.t)); 240 Walk("(", std::get<std::list<Name>>(x.t), ", ", ")"); 241 Indent(); 242 } 243 void Unparse(const Abstract &) { // R728, &c. 244 Word("ABSTRACT"); 245 } 246 void Post(const TypeAttrSpec::BindC &) { Word("BIND(C)"); } 247 void Unparse(const TypeAttrSpec::Extends &x) { 248 Word("EXTENDS("), Walk(x.v), Put(')'); 249 } 250 void Unparse(const EndTypeStmt &x) { // R730 251 Outdent(), Word("END TYPE"), Walk(" ", x.v); 252 } 253 void Unparse(const SequenceStmt &) { // R731 254 Word("SEQUENCE"); 255 } 256 void Unparse(const TypeParamDefStmt &x) { // R732 257 Walk(std::get<IntegerTypeSpec>(x.t)); 258 Put(", "), Walk(std::get<common::TypeParamAttr>(x.t)); 259 Put(" :: "), Walk(std::get<std::list<TypeParamDecl>>(x.t), ", "); 260 } 261 void Unparse(const TypeParamDecl &x) { // R733 262 Walk(std::get<Name>(x.t)); 263 Walk("=", std::get<std::optional<ScalarIntConstantExpr>>(x.t)); 264 } 265 void Unparse(const DataComponentDefStmt &x) { // R737 266 const auto &dts{std::get<DeclarationTypeSpec>(x.t)}; 267 const auto &attrs{std::get<std::list<ComponentAttrSpec>>(x.t)}; 268 const auto &decls{std::get<std::list<ComponentOrFill>>(x.t)}; 269 Walk(dts), Walk(", ", attrs, ", "); 270 if (!attrs.empty() || 271 (!std::holds_alternative<DeclarationTypeSpec::Record>(dts.u) && 272 std::none_of( 273 decls.begin(), decls.end(), [](const ComponentOrFill &c) { 274 return common::visit( 275 common::visitors{ 276 [](const ComponentDecl &d) { 277 const auto &init{ 278 std::get<std::optional<Initialization>>(d.t)}; 279 return init && 280 std::holds_alternative<std::list< 281 common::Indirection<DataStmtValue>>>( 282 init->u); 283 }, 284 [](const FillDecl &) { return false; }, 285 }, 286 c.u); 287 }))) { 288 Put(" ::"); 289 } 290 Put(' '), Walk(decls, ", "); 291 } 292 void Unparse(const Allocatable &) { // R738 293 Word("ALLOCATABLE"); 294 } 295 void Unparse(const Pointer &) { Word("POINTER"); } 296 void Unparse(const Contiguous &) { Word("CONTIGUOUS"); } 297 void Before(const ComponentAttrSpec &x) { 298 common::visit(common::visitors{ 299 [&](const CoarraySpec &) { Word("CODIMENSION["); }, 300 [&](const ComponentArraySpec &) { Word("DIMENSION("); }, 301 [](const auto &) {}, 302 }, 303 x.u); 304 } 305 void Post(const ComponentAttrSpec &x) { 306 common::visit(common::visitors{ 307 [&](const CoarraySpec &) { Put(']'); }, 308 [&](const ComponentArraySpec &) { Put(')'); }, 309 [](const auto &) {}, 310 }, 311 x.u); 312 } 313 void Unparse(const ComponentDecl &x) { // R739 314 Walk(std::get<ObjectName>(x.t)); 315 Walk("(", std::get<std::optional<ComponentArraySpec>>(x.t), ")"); 316 Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]"); 317 Walk("*", std::get<std::optional<CharLength>>(x.t)); 318 Walk(std::get<std::optional<Initialization>>(x.t)); 319 } 320 void Unparse(const FillDecl &x) { // DEC extension 321 Put("%FILL"); 322 Walk("(", std::get<std::optional<ComponentArraySpec>>(x.t), ")"); 323 Walk("*", std::get<std::optional<CharLength>>(x.t)); 324 } 325 void Unparse(const ComponentArraySpec &x) { // R740 326 common::visit( 327 common::visitors{ 328 [&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); }, 329 [&](const DeferredShapeSpecList &y) { Walk(y); }, 330 }, 331 x.u); 332 } 333 void Unparse(const ProcComponentDefStmt &x) { // R741 334 Word("PROCEDURE("); 335 Walk(std::get<std::optional<ProcInterface>>(x.t)), Put(')'); 336 Walk(", ", std::get<std::list<ProcComponentAttrSpec>>(x.t), ", "); 337 Put(" :: "), Walk(std::get<std::list<ProcDecl>>(x.t), ", "); 338 } 339 void Unparse(const NoPass &) { // R742 340 Word("NOPASS"); 341 } 342 void Unparse(const Pass &x) { Word("PASS"), Walk("(", x.v, ")"); } 343 void Unparse(const Initialization &x) { // R743 & R805 344 common::visit( 345 common::visitors{ 346 [&](const ConstantExpr &y) { Put(" = "), Walk(y); }, 347 [&](const NullInit &y) { Put(" => "), Walk(y); }, 348 [&](const InitialDataTarget &y) { Put(" => "), Walk(y); }, 349 [&](const std::list<common::Indirection<DataStmtValue>> &y) { 350 Walk("/", y, ", ", "/"); 351 }, 352 }, 353 x.u); 354 } 355 void Unparse(const PrivateStmt &) { // R745 356 Word("PRIVATE"); 357 } 358 void Unparse(const TypeBoundProcedureStmt::WithoutInterface &x) { // R749 359 Word("PROCEDURE"), Walk(", ", x.attributes, ", "); 360 Put(" :: "), Walk(x.declarations, ", "); 361 } 362 void Unparse(const TypeBoundProcedureStmt::WithInterface &x) { 363 Word("PROCEDURE("), Walk(x.interfaceName), Put("), "); 364 Walk(x.attributes); 365 Put(" :: "), Walk(x.bindingNames, ", "); 366 } 367 void Unparse(const TypeBoundProcDecl &x) { // R750 368 Walk(std::get<Name>(x.t)); 369 Walk(" => ", std::get<std::optional<Name>>(x.t)); 370 } 371 void Unparse(const TypeBoundGenericStmt &x) { // R751 372 Word("GENERIC"), Walk(", ", std::get<std::optional<AccessSpec>>(x.t)); 373 Put(" :: "), Walk(std::get<common::Indirection<GenericSpec>>(x.t)); 374 Put(" => "), Walk(std::get<std::list<Name>>(x.t), ", "); 375 } 376 void Post(const BindAttr::Deferred &) { Word("DEFERRED"); } // R752 377 void Post(const BindAttr::Non_Overridable &) { Word("NON_OVERRIDABLE"); } 378 void Unparse(const FinalProcedureStmt &x) { // R753 379 Word("FINAL :: "), Walk(x.v, ", "); 380 } 381 void Unparse(const DerivedTypeSpec &x) { // R754 382 Walk(std::get<Name>(x.t)); 383 Walk("(", std::get<std::list<TypeParamSpec>>(x.t), ",", ")"); 384 } 385 void Unparse(const TypeParamSpec &x) { // R755 386 Walk(std::get<std::optional<Keyword>>(x.t), "="); 387 Walk(std::get<TypeParamValue>(x.t)); 388 } 389 void Unparse(const StructureConstructor &x) { // R756 390 Walk(std::get<DerivedTypeSpec>(x.t)); 391 Put('('), Walk(std::get<std::list<ComponentSpec>>(x.t), ", "), Put(')'); 392 } 393 void Unparse(const ComponentSpec &x) { // R757 394 Walk(std::get<std::optional<Keyword>>(x.t), "="); 395 Walk(std::get<ComponentDataSource>(x.t)); 396 } 397 void Unparse(const EnumDefStmt &) { // R760 398 Word("ENUM, BIND(C)"), Indent(); 399 } 400 void Unparse(const EnumeratorDefStmt &x) { // R761 401 Word("ENUMERATOR :: "), Walk(x.v, ", "); 402 } 403 void Unparse(const Enumerator &x) { // R762 404 Walk(std::get<NamedConstant>(x.t)); 405 Walk(" = ", std::get<std::optional<ScalarIntConstantExpr>>(x.t)); 406 } 407 void Post(const EndEnumStmt &) { // R763 408 Outdent(), Word("END ENUM"); 409 } 410 void Unparse(const BOZLiteralConstant &x) { // R764 - R767 411 Put(x.v); 412 } 413 void Unparse(const AcValue::Triplet &x) { // R773 414 Walk(std::get<0>(x.t)), Put(':'), Walk(std::get<1>(x.t)); 415 Walk(":", std::get<std::optional<ScalarIntExpr>>(x.t)); 416 } 417 void Unparse(const ArrayConstructor &x) { // R769 418 Put('['), Walk(x.v), Put(']'); 419 } 420 void Unparse(const AcSpec &x) { // R770 421 Walk(x.type, "::"), Walk(x.values, ", "); 422 } 423 template <typename A, typename B> void Unparse(const LoopBounds<A, B> &x) { 424 Walk(x.name), Put('='), Walk(x.lower), Put(','), Walk(x.upper); 425 Walk(",", x.step); 426 } 427 void Unparse(const AcImpliedDo &x) { // R774 428 Put('('), Walk(std::get<std::list<AcValue>>(x.t), ", "); 429 Put(", "), Walk(std::get<AcImpliedDoControl>(x.t)), Put(')'); 430 } 431 void Unparse(const AcImpliedDoControl &x) { // R775 432 Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::"); 433 Walk(std::get<AcImpliedDoControl::Bounds>(x.t)); 434 } 435 436 void Unparse(const TypeDeclarationStmt &x) { // R801 437 const auto &dts{std::get<DeclarationTypeSpec>(x.t)}; 438 const auto &attrs{std::get<std::list<AttrSpec>>(x.t)}; 439 const auto &decls{std::get<std::list<EntityDecl>>(x.t)}; 440 Walk(dts), Walk(", ", attrs, ", "); 441 442 static const auto isInitializerOldStyle{[](const Initialization &i) { 443 return std::holds_alternative< 444 std::list<common::Indirection<DataStmtValue>>>(i.u); 445 }}; 446 static const auto hasAssignmentInitializer{[](const EntityDecl &d) { 447 // Does a declaration have a new-style =x initializer? 448 const auto &init{std::get<std::optional<Initialization>>(d.t)}; 449 return init && !isInitializerOldStyle(*init); 450 }}; 451 static const auto hasSlashDelimitedInitializer{[](const EntityDecl &d) { 452 // Does a declaration have an old-style /x/ initializer? 453 const auto &init{std::get<std::optional<Initialization>>(d.t)}; 454 return init && isInitializerOldStyle(*init); 455 }}; 456 const auto useDoubledColons{[&]() { 457 bool isRecord{std::holds_alternative<DeclarationTypeSpec::Record>(dts.u)}; 458 if (!attrs.empty()) { 459 // Attributes after the type require :: before the entities. 460 CHECK(!isRecord); 461 return true; 462 } 463 if (std::any_of(decls.begin(), decls.end(), hasAssignmentInitializer)) { 464 // Always use :: with new style standard initializers (=x), 465 // since the standard requires them to appear (even in free form, 466 // where mandatory spaces already disambiguate INTEGER J=666). 467 CHECK(!isRecord); 468 return true; 469 } 470 if (isRecord) { 471 // Never put :: in a legacy extension RECORD// statement. 472 return false; 473 } 474 // The :: is optional for this declaration. Avoid usage that can 475 // crash the pgf90 compiler. 476 if (std::any_of( 477 decls.begin(), decls.end(), hasSlashDelimitedInitializer)) { 478 // Don't use :: when a declaration uses legacy DATA-statement-like 479 // /x/ initialization. 480 return false; 481 } 482 // Don't use :: with intrinsic types. Otherwise, use it. 483 return !std::holds_alternative<IntrinsicTypeSpec>(dts.u); 484 }}; 485 486 if (useDoubledColons()) { 487 Put(" ::"); 488 } 489 Put(' '), Walk(std::get<std::list<EntityDecl>>(x.t), ", "); 490 } 491 void Before(const AttrSpec &x) { // R802 492 common::visit(common::visitors{ 493 [&](const CoarraySpec &) { Word("CODIMENSION["); }, 494 [&](const ArraySpec &) { Word("DIMENSION("); }, 495 [](const auto &) {}, 496 }, 497 x.u); 498 } 499 void Post(const AttrSpec &x) { 500 common::visit(common::visitors{ 501 [&](const CoarraySpec &) { Put(']'); }, 502 [&](const ArraySpec &) { Put(')'); }, 503 [](const auto &) {}, 504 }, 505 x.u); 506 } 507 void Unparse(const EntityDecl &x) { // R803 508 Walk(std::get<ObjectName>(x.t)); 509 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"); 510 Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]"); 511 Walk("*", std::get<std::optional<CharLength>>(x.t)); 512 Walk(std::get<std::optional<Initialization>>(x.t)); 513 } 514 void Unparse(const NullInit &) { // R806 515 Word("NULL()"); 516 } 517 void Unparse(const LanguageBindingSpec &x) { // R808 & R1528 518 Word("BIND(C"), Walk(", NAME=", x.v), Put(')'); 519 } 520 void Unparse(const CoarraySpec &x) { // R809 521 common::visit(common::visitors{ 522 [&](const DeferredCoshapeSpecList &y) { Walk(y); }, 523 [&](const ExplicitCoshapeSpec &y) { Walk(y); }, 524 }, 525 x.u); 526 } 527 void Unparse(const DeferredCoshapeSpecList &x) { // R810 528 for (auto j{x.v}; j > 0; --j) { 529 Put(':'); 530 if (j > 1) { 531 Put(','); 532 } 533 } 534 } 535 void Unparse(const ExplicitCoshapeSpec &x) { // R811 536 Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ","); 537 Walk(std::get<std::optional<SpecificationExpr>>(x.t), ":"), Put('*'); 538 } 539 void Unparse(const ExplicitShapeSpec &x) { // R812 - R813 & R816 - R818 540 Walk(std::get<std::optional<SpecificationExpr>>(x.t), ":"); 541 Walk(std::get<SpecificationExpr>(x.t)); 542 } 543 void Unparse(const ArraySpec &x) { // R815 544 common::visit( 545 common::visitors{ 546 [&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); }, 547 [&](const std::list<AssumedShapeSpec> &y) { Walk(y, ","); }, 548 [&](const DeferredShapeSpecList &y) { Walk(y); }, 549 [&](const AssumedSizeSpec &y) { Walk(y); }, 550 [&](const ImpliedShapeSpec &y) { Walk(y); }, 551 [&](const AssumedRankSpec &y) { Walk(y); }, 552 }, 553 x.u); 554 } 555 void Post(const AssumedShapeSpec &) { Put(':'); } // R819 556 void Unparse(const DeferredShapeSpecList &x) { // R820 557 for (auto j{x.v}; j > 0; --j) { 558 Put(':'); 559 if (j > 1) { 560 Put(','); 561 } 562 } 563 } 564 void Unparse(const AssumedImpliedSpec &x) { // R821 565 Walk(x.v, ":"); 566 Put('*'); 567 } 568 void Unparse(const AssumedSizeSpec &x) { // R822 569 Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ","); 570 Walk(std::get<AssumedImpliedSpec>(x.t)); 571 } 572 void Unparse(const ImpliedShapeSpec &x) { // R823 573 Walk(x.v, ","); 574 } 575 void Post(const AssumedRankSpec &) { Put(".."); } // R825 576 void Post(const Asynchronous &) { Word("ASYNCHRONOUS"); } 577 void Post(const External &) { Word("EXTERNAL"); } 578 void Post(const Intrinsic &) { Word("INTRINSIC"); } 579 void Post(const Optional &) { Word("OPTIONAL"); } 580 void Post(const Parameter &) { Word("PARAMETER"); } 581 void Post(const Protected &) { Word("PROTECTED"); } 582 void Post(const Save &) { Word("SAVE"); } 583 void Post(const Target &) { Word("TARGET"); } 584 void Post(const Value &) { Word("VALUE"); } 585 void Post(const Volatile &) { Word("VOLATILE"); } 586 void Unparse(const IntentSpec &x) { // R826 587 Word("INTENT("), Walk(x.v), Put(")"); 588 } 589 void Unparse(const AccessStmt &x) { // R827 590 Walk(std::get<AccessSpec>(x.t)); 591 Walk(" :: ", std::get<std::list<AccessId>>(x.t), ", "); 592 } 593 void Unparse(const AllocatableStmt &x) { // R829 594 Word("ALLOCATABLE :: "), Walk(x.v, ", "); 595 } 596 void Unparse(const ObjectDecl &x) { // R830 & R860 597 Walk(std::get<ObjectName>(x.t)); 598 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"); 599 Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]"); 600 } 601 void Unparse(const AsynchronousStmt &x) { // R831 602 Word("ASYNCHRONOUS :: "), Walk(x.v, ", "); 603 } 604 void Unparse(const BindStmt &x) { // R832 605 Walk(x.t, " :: "); 606 } 607 void Unparse(const BindEntity &x) { // R833 608 bool isCommon{std::get<BindEntity::Kind>(x.t) == BindEntity::Kind::Common}; 609 const char *slash{isCommon ? "/" : ""}; 610 Put(slash), Walk(std::get<Name>(x.t)), Put(slash); 611 } 612 void Unparse(const CodimensionStmt &x) { // R834 613 Word("CODIMENSION :: "), Walk(x.v, ", "); 614 } 615 void Unparse(const CodimensionDecl &x) { // R835 616 Walk(std::get<Name>(x.t)); 617 Put('['), Walk(std::get<CoarraySpec>(x.t)), Put(']'); 618 } 619 void Unparse(const ContiguousStmt &x) { // R836 620 Word("CONTIGUOUS :: "), Walk(x.v, ", "); 621 } 622 void Unparse(const DataStmt &x) { // R837 623 Word("DATA "), Walk(x.v, ", "); 624 } 625 void Unparse(const DataStmtSet &x) { // R838 626 Walk(std::get<std::list<DataStmtObject>>(x.t), ", "); 627 Put('/'), Walk(std::get<std::list<DataStmtValue>>(x.t), ", "), Put('/'); 628 } 629 void Unparse(const DataImpliedDo &x) { // R840, R842 630 Put('('), Walk(std::get<std::list<DataIDoObject>>(x.t), ", "), Put(','); 631 Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::"); 632 Walk(std::get<DataImpliedDo::Bounds>(x.t)), Put(')'); 633 } 634 void Unparse(const DataStmtValue &x) { // R843 635 Walk(std::get<std::optional<DataStmtRepeat>>(x.t), "*"); 636 Walk(std::get<DataStmtConstant>(x.t)); 637 } 638 void Unparse(const DimensionStmt &x) { // R848 639 Word("DIMENSION :: "), Walk(x.v, ", "); 640 } 641 void Unparse(const DimensionStmt::Declaration &x) { 642 Walk(std::get<Name>(x.t)); 643 Put('('), Walk(std::get<ArraySpec>(x.t)), Put(')'); 644 } 645 void Unparse(const IntentStmt &x) { // R849 646 Walk(x.t, " :: "); 647 } 648 void Unparse(const OptionalStmt &x) { // R850 649 Word("OPTIONAL :: "), Walk(x.v, ", "); 650 } 651 void Unparse(const ParameterStmt &x) { // R851 652 Word("PARAMETER("), Walk(x.v, ", "), Put(')'); 653 } 654 void Unparse(const NamedConstantDef &x) { // R852 655 Walk(x.t, "="); 656 } 657 void Unparse(const PointerStmt &x) { // R853 658 Word("POINTER :: "), Walk(x.v, ", "); 659 } 660 void Unparse(const PointerDecl &x) { // R854 661 Walk(std::get<Name>(x.t)); 662 Walk("(", std::get<std::optional<DeferredShapeSpecList>>(x.t), ")"); 663 } 664 void Unparse(const ProtectedStmt &x) { // R855 665 Word("PROTECTED :: "), Walk(x.v, ", "); 666 } 667 void Unparse(const SaveStmt &x) { // R856 668 Word("SAVE"), Walk(" :: ", x.v, ", "); 669 } 670 void Unparse(const SavedEntity &x) { // R857, R858 671 bool isCommon{ 672 std::get<SavedEntity::Kind>(x.t) == SavedEntity::Kind::Common}; 673 const char *slash{isCommon ? "/" : ""}; 674 Put(slash), Walk(std::get<Name>(x.t)), Put(slash); 675 } 676 void Unparse(const TargetStmt &x) { // R859 677 Word("TARGET :: "), Walk(x.v, ", "); 678 } 679 void Unparse(const ValueStmt &x) { // R861 680 Word("VALUE :: "), Walk(x.v, ", "); 681 } 682 void Unparse(const VolatileStmt &x) { // R862 683 Word("VOLATILE :: "), Walk(x.v, ", "); 684 } 685 void Unparse(const ImplicitStmt &x) { // R863 686 Word("IMPLICIT "); 687 common::visit( 688 common::visitors{ 689 [&](const std::list<ImplicitSpec> &y) { Walk(y, ", "); }, 690 [&](const std::list<ImplicitStmt::ImplicitNoneNameSpec> &y) { 691 Word("NONE"), Walk(" (", y, ", ", ")"); 692 }, 693 }, 694 x.u); 695 } 696 void Unparse(const ImplicitSpec &x) { // R864 697 Walk(std::get<DeclarationTypeSpec>(x.t)); 698 Put('('), Walk(std::get<std::list<LetterSpec>>(x.t), ", "), Put(')'); 699 } 700 void Unparse(const LetterSpec &x) { // R865 701 Put(*std::get<const char *>(x.t)); 702 auto second{std::get<std::optional<const char *>>(x.t)}; 703 if (second) { 704 Put('-'), Put(**second); 705 } 706 } 707 void Unparse(const ImportStmt &x) { // R867 708 Word("IMPORT"); 709 switch (x.kind) { 710 case common::ImportKind::Default: 711 Walk(" :: ", x.names, ", "); 712 break; 713 case common::ImportKind::Only: 714 Put(", "), Word("ONLY: "); 715 Walk(x.names, ", "); 716 break; 717 case common::ImportKind::None: 718 Word(", NONE"); 719 break; 720 case common::ImportKind::All: 721 Word(", ALL"); 722 break; 723 } 724 } 725 void Unparse(const NamelistStmt &x) { // R868 726 Word("NAMELIST"), Walk(x.v, ", "); 727 } 728 void Unparse(const NamelistStmt::Group &x) { 729 Put('/'), Walk(std::get<Name>(x.t)), Put('/'); 730 Walk(std::get<std::list<Name>>(x.t), ", "); 731 } 732 void Unparse(const EquivalenceStmt &x) { // R870, R871 733 Word("EQUIVALENCE"); 734 const char *separator{" "}; 735 for (const std::list<EquivalenceObject> &y : x.v) { 736 Put(separator), Put('('), Walk(y), Put(')'); 737 separator = ", "; 738 } 739 } 740 void Unparse(const CommonStmt &x) { // R873 741 Word("COMMON "); 742 Walk(x.blocks); 743 } 744 void Unparse(const CommonBlockObject &x) { // R874 745 Walk(std::get<Name>(x.t)); 746 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"); 747 } 748 void Unparse(const CommonStmt::Block &x) { 749 Word("/"), Walk(std::get<std::optional<Name>>(x.t)), Word("/"); 750 Walk(std::get<std::list<CommonBlockObject>>(x.t)); 751 } 752 753 void Unparse(const Substring &x) { // R908, R909 754 Walk(std::get<DataRef>(x.t)); 755 Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')'); 756 } 757 void Unparse(const CharLiteralConstantSubstring &x) { 758 Walk(std::get<CharLiteralConstant>(x.t)); 759 Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')'); 760 } 761 void Unparse(const SubstringInquiry &x) { 762 Walk(x.v); 763 Put(x.source.end()[-1] == 'n' ? "%LEN" : "%KIND"); 764 } 765 void Unparse(const SubstringRange &x) { // R910 766 Walk(x.t, ":"); 767 } 768 void Unparse(const PartRef &x) { // R912 769 Walk(x.name); 770 Walk("(", x.subscripts, ",", ")"); 771 Walk(x.imageSelector); 772 } 773 void Unparse(const StructureComponent &x) { // R913 774 Walk(x.base); 775 if (structureComponents_.find(x.component.source) != 776 structureComponents_.end()) { 777 Put('.'); 778 } else { 779 Put('%'); 780 } 781 Walk(x.component); 782 } 783 void Unparse(const ArrayElement &x) { // R917 784 Walk(x.base); 785 Put('('), Walk(x.subscripts, ","), Put(')'); 786 } 787 void Unparse(const SubscriptTriplet &x) { // R921 788 Walk(std::get<0>(x.t)), Put(':'), Walk(std::get<1>(x.t)); 789 Walk(":", std::get<2>(x.t)); 790 } 791 void Unparse(const ImageSelector &x) { // R924 792 Put('['), Walk(std::get<std::list<Cosubscript>>(x.t), ","); 793 Walk(",", std::get<std::list<ImageSelectorSpec>>(x.t), ","), Put(']'); 794 } 795 void Before(const ImageSelectorSpec::Stat &) { // R926 796 Word("STAT="); 797 } 798 void Before(const ImageSelectorSpec::Team_Number &) { Word("TEAM_NUMBER="); } 799 void Before(const ImageSelectorSpec &x) { 800 if (std::holds_alternative<TeamValue>(x.u)) { 801 Word("TEAM="); 802 } 803 } 804 void Unparse(const AllocateStmt &x) { // R927 805 Word("ALLOCATE("); 806 Walk(std::get<std::optional<TypeSpec>>(x.t), "::"); 807 Walk(std::get<std::list<Allocation>>(x.t), ", "); 808 Walk(", ", std::get<std::list<AllocOpt>>(x.t), ", "), Put(')'); 809 } 810 void Before(const AllocOpt &x) { // R928, R931 811 common::visit(common::visitors{ 812 [&](const AllocOpt::Mold &) { Word("MOLD="); }, 813 [&](const AllocOpt::Source &) { Word("SOURCE="); }, 814 [](const StatOrErrmsg &) {}, 815 }, 816 x.u); 817 } 818 void Unparse(const Allocation &x) { // R932 819 Walk(std::get<AllocateObject>(x.t)); 820 Walk("(", std::get<std::list<AllocateShapeSpec>>(x.t), ",", ")"); 821 Walk("[", std::get<std::optional<AllocateCoarraySpec>>(x.t), "]"); 822 } 823 void Unparse(const AllocateShapeSpec &x) { // R934 & R938 824 Walk(std::get<std::optional<BoundExpr>>(x.t), ":"); 825 Walk(std::get<BoundExpr>(x.t)); 826 } 827 void Unparse(const AllocateCoarraySpec &x) { // R937 828 Walk(std::get<std::list<AllocateCoshapeSpec>>(x.t), ",", ","); 829 Walk(std::get<std::optional<BoundExpr>>(x.t), ":"), Put('*'); 830 } 831 void Unparse(const NullifyStmt &x) { // R939 832 Word("NULLIFY("), Walk(x.v, ", "), Put(')'); 833 } 834 void Unparse(const DeallocateStmt &x) { // R941 835 Word("DEALLOCATE("); 836 Walk(std::get<std::list<AllocateObject>>(x.t), ", "); 837 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); 838 } 839 void Before(const StatOrErrmsg &x) { // R942 & R1165 840 common::visit(common::visitors{ 841 [&](const StatVariable &) { Word("STAT="); }, 842 [&](const MsgVariable &) { Word("ERRMSG="); }, 843 }, 844 x.u); 845 } 846 847 // R1001 - R1022 848 void Unparse(const Expr::Parentheses &x) { Put('('), Walk(x.v), Put(')'); } 849 void Before(const Expr::UnaryPlus &) { Put("+"); } 850 void Before(const Expr::Negate &) { Put("-"); } 851 void Before(const Expr::NOT &) { Word(".NOT."); } 852 void Unparse(const Expr::PercentLoc &x) { 853 Word("%LOC("), Walk(x.v), Put(')'); 854 } 855 void Unparse(const Expr::Power &x) { Walk(x.t, "**"); } 856 void Unparse(const Expr::Multiply &x) { Walk(x.t, "*"); } 857 void Unparse(const Expr::Divide &x) { Walk(x.t, "/"); } 858 void Unparse(const Expr::Add &x) { Walk(x.t, "+"); } 859 void Unparse(const Expr::Subtract &x) { Walk(x.t, "-"); } 860 void Unparse(const Expr::Concat &x) { Walk(x.t, "//"); } 861 void Unparse(const Expr::LT &x) { Walk(x.t, "<"); } 862 void Unparse(const Expr::LE &x) { Walk(x.t, "<="); } 863 void Unparse(const Expr::EQ &x) { Walk(x.t, "=="); } 864 void Unparse(const Expr::NE &x) { Walk(x.t, "/="); } 865 void Unparse(const Expr::GE &x) { Walk(x.t, ">="); } 866 void Unparse(const Expr::GT &x) { Walk(x.t, ">"); } 867 void Unparse(const Expr::AND &x) { Walk(x.t, ".AND."); } 868 void Unparse(const Expr::OR &x) { Walk(x.t, ".OR."); } 869 void Unparse(const Expr::EQV &x) { Walk(x.t, ".EQV."); } 870 void Unparse(const Expr::NEQV &x) { Walk(x.t, ".NEQV."); } 871 void Unparse(const Expr::ComplexConstructor &x) { 872 Put('('), Walk(x.t, ","), Put(')'); 873 } 874 void Unparse(const Expr::DefinedBinary &x) { 875 Walk(std::get<1>(x.t)); // left 876 Walk(std::get<DefinedOpName>(x.t)); 877 Walk(std::get<2>(x.t)); // right 878 } 879 void Unparse(const DefinedOpName &x) { // R1003, R1023, R1414, & R1415 880 Walk(x.v); 881 } 882 void Unparse(const AssignmentStmt &x) { // R1032 883 if (asFortran_ && x.typedAssignment.get()) { 884 Put(' '); 885 asFortran_->assignment(out_, *x.typedAssignment); 886 Put('\n'); 887 } else { 888 Walk(x.t, " = "); 889 } 890 } 891 void Unparse(const PointerAssignmentStmt &x) { // R1033, R1034, R1038 892 if (asFortran_ && x.typedAssignment.get()) { 893 Put(' '); 894 asFortran_->assignment(out_, *x.typedAssignment); 895 Put('\n'); 896 } else { 897 Walk(std::get<DataRef>(x.t)); 898 common::visit( 899 common::visitors{ 900 [&](const std::list<BoundsRemapping> &y) { 901 Put('('), Walk(y), Put(')'); 902 }, 903 [&](const std::list<BoundsSpec> &y) { Walk("(", y, ", ", ")"); }, 904 }, 905 std::get<PointerAssignmentStmt::Bounds>(x.t).u); 906 Put(" => "), Walk(std::get<Expr>(x.t)); 907 } 908 } 909 void Post(const BoundsSpec &) { // R1035 910 Put(':'); 911 } 912 void Unparse(const BoundsRemapping &x) { // R1036 913 Walk(x.t, ":"); 914 } 915 void Unparse(const WhereStmt &x) { // R1041, R1045, R1046 916 Word("WHERE ("), Walk(x.t, ") "); 917 } 918 void Unparse(const WhereConstructStmt &x) { // R1043 919 Walk(std::get<std::optional<Name>>(x.t), ": "); 920 Word("WHERE ("), Walk(std::get<LogicalExpr>(x.t)), Put(')'); 921 Indent(); 922 } 923 void Unparse(const MaskedElsewhereStmt &x) { // R1047 924 Outdent(); 925 Word("ELSEWHERE ("), Walk(std::get<LogicalExpr>(x.t)), Put(')'); 926 Walk(" ", std::get<std::optional<Name>>(x.t)); 927 Indent(); 928 } 929 void Unparse(const ElsewhereStmt &x) { // R1048 930 Outdent(), Word("ELSEWHERE"), Walk(" ", x.v), Indent(); 931 } 932 void Unparse(const EndWhereStmt &x) { // R1049 933 Outdent(), Word("END WHERE"), Walk(" ", x.v); 934 } 935 void Unparse(const ForallConstructStmt &x) { // R1051 936 Walk(std::get<std::optional<Name>>(x.t), ": "); 937 Word("FORALL"), Walk(std::get<common::Indirection<ConcurrentHeader>>(x.t)); 938 Indent(); 939 } 940 void Unparse(const EndForallStmt &x) { // R1054 941 Outdent(), Word("END FORALL"), Walk(" ", x.v); 942 } 943 void Before(const ForallStmt &) { // R1055 944 Word("FORALL"); 945 } 946 947 void Unparse(const AssociateStmt &x) { // R1103 948 Walk(std::get<std::optional<Name>>(x.t), ": "); 949 Word("ASSOCIATE ("); 950 Walk(std::get<std::list<Association>>(x.t), ", "), Put(')'), Indent(); 951 } 952 void Unparse(const Association &x) { // R1104 953 Walk(x.t, " => "); 954 } 955 void Unparse(const EndAssociateStmt &x) { // R1106 956 Outdent(), Word("END ASSOCIATE"), Walk(" ", x.v); 957 } 958 void Unparse(const BlockStmt &x) { // R1108 959 Walk(x.v, ": "), Word("BLOCK"), Indent(); 960 } 961 void Unparse(const EndBlockStmt &x) { // R1110 962 Outdent(), Word("END BLOCK"), Walk(" ", x.v); 963 } 964 void Unparse(const ChangeTeamStmt &x) { // R1112 965 Walk(std::get<std::optional<Name>>(x.t), ": "); 966 Word("CHANGE TEAM ("), Walk(std::get<TeamValue>(x.t)); 967 Walk(", ", std::get<std::list<CoarrayAssociation>>(x.t), ", "); 968 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); 969 Indent(); 970 } 971 void Unparse(const CoarrayAssociation &x) { // R1113 972 Walk(x.t, " => "); 973 } 974 void Unparse(const EndChangeTeamStmt &x) { // R1114 975 Outdent(), Word("END TEAM ("); 976 Walk(std::get<std::list<StatOrErrmsg>>(x.t), ", "); 977 Put(')'), Walk(" ", std::get<std::optional<Name>>(x.t)); 978 } 979 void Unparse(const CriticalStmt &x) { // R1117 980 Walk(std::get<std::optional<Name>>(x.t), ": "); 981 Word("CRITICAL ("), Walk(std::get<std::list<StatOrErrmsg>>(x.t), ", "); 982 Put(')'), Indent(); 983 } 984 void Unparse(const EndCriticalStmt &x) { // R1118 985 Outdent(), Word("END CRITICAL"), Walk(" ", x.v); 986 } 987 void Unparse(const DoConstruct &x) { // R1119, R1120 988 Walk(std::get<Statement<NonLabelDoStmt>>(x.t)); 989 Indent(), Walk(std::get<Block>(x.t), ""), Outdent(); 990 Walk(std::get<Statement<EndDoStmt>>(x.t)); 991 } 992 void Unparse(const LabelDoStmt &x) { // R1121 993 Walk(std::get<std::optional<Name>>(x.t), ": "); 994 Word("DO "), Walk(std::get<Label>(x.t)); 995 Walk(" ", std::get<std::optional<LoopControl>>(x.t)); 996 } 997 void Unparse(const NonLabelDoStmt &x) { // R1122 998 Walk(std::get<std::optional<Name>>(x.t), ": "); 999 Word("DO "), Walk(std::get<std::optional<LoopControl>>(x.t)); 1000 } 1001 void Unparse(const LoopControl &x) { // R1123 1002 common::visit(common::visitors{ 1003 [&](const ScalarLogicalExpr &y) { 1004 Word("WHILE ("), Walk(y), Put(')'); 1005 }, 1006 [&](const auto &y) { Walk(y); }, 1007 }, 1008 x.u); 1009 } 1010 void Unparse(const ConcurrentHeader &x) { // R1125 1011 Put('('), Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::"); 1012 Walk(std::get<std::list<ConcurrentControl>>(x.t), ", "); 1013 Walk(", ", std::get<std::optional<ScalarLogicalExpr>>(x.t)), Put(')'); 1014 } 1015 void Unparse(const ConcurrentControl &x) { // R1126 - R1128 1016 Walk(std::get<Name>(x.t)), Put('='), Walk(std::get<1>(x.t)); 1017 Put(':'), Walk(std::get<2>(x.t)); 1018 Walk(":", std::get<std::optional<ScalarIntExpr>>(x.t)); 1019 } 1020 void Before(const LoopControl::Concurrent &) { // R1129 1021 Word("CONCURRENT"); 1022 } 1023 void Unparse(const LocalitySpec::Local &x) { 1024 Word("LOCAL("), Walk(x.v, ", "), Put(')'); 1025 } 1026 void Unparse(const LocalitySpec::LocalInit &x) { 1027 Word("LOCAL_INIT("), Walk(x.v, ", "), Put(')'); 1028 } 1029 void Unparse(const LocalitySpec::Shared &x) { 1030 Word("SHARED("), Walk(x.v, ", "), Put(')'); 1031 } 1032 void Post(const LocalitySpec::DefaultNone &) { Word("DEFAULT(NONE)"); } 1033 void Unparse(const EndDoStmt &x) { // R1132 1034 Word("END DO"), Walk(" ", x.v); 1035 } 1036 void Unparse(const CycleStmt &x) { // R1133 1037 Word("CYCLE"), Walk(" ", x.v); 1038 } 1039 void Unparse(const IfThenStmt &x) { // R1135 1040 Walk(std::get<std::optional<Name>>(x.t), ": "); 1041 Word("IF ("), Walk(std::get<ScalarLogicalExpr>(x.t)); 1042 Put(") "), Word("THEN"), Indent(); 1043 } 1044 void Unparse(const ElseIfStmt &x) { // R1136 1045 Outdent(), Word("ELSE IF ("); 1046 Walk(std::get<ScalarLogicalExpr>(x.t)), Put(") "), Word("THEN"); 1047 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent(); 1048 } 1049 void Unparse(const ElseStmt &x) { // R1137 1050 Outdent(), Word("ELSE"), Walk(" ", x.v), Indent(); 1051 } 1052 void Unparse(const EndIfStmt &x) { // R1138 1053 Outdent(), Word("END IF"), Walk(" ", x.v); 1054 } 1055 void Unparse(const IfStmt &x) { // R1139 1056 Word("IF ("), Walk(x.t, ") "); 1057 } 1058 void Unparse(const SelectCaseStmt &x) { // R1141, R1144 1059 Walk(std::get<std::optional<Name>>(x.t), ": "); 1060 Word("SELECT CASE ("); 1061 Walk(std::get<Scalar<Expr>>(x.t)), Put(')'), Indent(); 1062 } 1063 void Unparse(const CaseStmt &x) { // R1142 1064 Outdent(), Word("CASE "), Walk(std::get<CaseSelector>(x.t)); 1065 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent(); 1066 } 1067 void Unparse(const EndSelectStmt &x) { // R1143 & R1151 & R1155 1068 Outdent(), Word("END SELECT"), Walk(" ", x.v); 1069 } 1070 void Unparse(const CaseSelector &x) { // R1145 1071 common::visit(common::visitors{ 1072 [&](const std::list<CaseValueRange> &y) { 1073 Put('('), Walk(y), Put(')'); 1074 }, 1075 [&](const Default &) { Word("DEFAULT"); }, 1076 }, 1077 x.u); 1078 } 1079 void Unparse(const CaseValueRange::Range &x) { // R1146 1080 Walk(x.lower), Put(':'), Walk(x.upper); 1081 } 1082 void Unparse(const SelectRankStmt &x) { // R1149 1083 Walk(std::get<0>(x.t), ": "); 1084 Word("SELECT RANK ("), Walk(std::get<1>(x.t), " => "); 1085 Walk(std::get<Selector>(x.t)), Put(')'), Indent(); 1086 } 1087 void Unparse(const SelectRankCaseStmt &x) { // R1150 1088 Outdent(), Word("RANK "); 1089 common::visit(common::visitors{ 1090 [&](const ScalarIntConstantExpr &y) { 1091 Put('('), Walk(y), Put(')'); 1092 }, 1093 [&](const Star &) { Put("(*)"); }, 1094 [&](const Default &) { Word("DEFAULT"); }, 1095 }, 1096 std::get<SelectRankCaseStmt::Rank>(x.t).u); 1097 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent(); 1098 } 1099 void Unparse(const SelectTypeStmt &x) { // R1153 1100 Walk(std::get<0>(x.t), ": "); 1101 Word("SELECT TYPE ("), Walk(std::get<1>(x.t), " => "); 1102 Walk(std::get<Selector>(x.t)), Put(')'), Indent(); 1103 } 1104 void Unparse(const TypeGuardStmt &x) { // R1154 1105 Outdent(), Walk(std::get<TypeGuardStmt::Guard>(x.t)); 1106 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent(); 1107 } 1108 void Unparse(const TypeGuardStmt::Guard &x) { 1109 common::visit( 1110 common::visitors{ 1111 [&](const TypeSpec &y) { Word("TYPE IS ("), Walk(y), Put(')'); }, 1112 [&](const DerivedTypeSpec &y) { 1113 Word("CLASS IS ("), Walk(y), Put(')'); 1114 }, 1115 [&](const Default &) { Word("CLASS DEFAULT"); }, 1116 }, 1117 x.u); 1118 } 1119 void Unparse(const ExitStmt &x) { // R1156 1120 Word("EXIT"), Walk(" ", x.v); 1121 } 1122 void Before(const GotoStmt &) { // R1157 1123 Word("GO TO "); 1124 } 1125 void Unparse(const ComputedGotoStmt &x) { // R1158 1126 Word("GO TO ("), Walk(x.t, "), "); 1127 } 1128 void Unparse(const ContinueStmt &) { // R1159 1129 Word("CONTINUE"); 1130 } 1131 void Unparse(const StopStmt &x) { // R1160, R1161 1132 if (std::get<StopStmt::Kind>(x.t) == StopStmt::Kind::ErrorStop) { 1133 Word("ERROR "); 1134 } 1135 Word("STOP"), Walk(" ", std::get<std::optional<StopCode>>(x.t)); 1136 Walk(", QUIET=", std::get<std::optional<ScalarLogicalExpr>>(x.t)); 1137 } 1138 void Unparse(const FailImageStmt &) { // R1163 1139 Word("FAIL IMAGE"); 1140 } 1141 void Unparse(const SyncAllStmt &x) { // R1164 1142 Word("SYNC ALL ("), Walk(x.v, ", "), Put(')'); 1143 } 1144 void Unparse(const SyncImagesStmt &x) { // R1166 1145 Word("SYNC IMAGES ("); 1146 Walk(std::get<SyncImagesStmt::ImageSet>(x.t)); 1147 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); 1148 } 1149 void Unparse(const SyncMemoryStmt &x) { // R1168 1150 Word("SYNC MEMORY ("), Walk(x.v, ", "), Put(')'); 1151 } 1152 void Unparse(const SyncTeamStmt &x) { // R1169 1153 Word("SYNC TEAM ("), Walk(std::get<TeamValue>(x.t)); 1154 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); 1155 } 1156 void Unparse(const EventPostStmt &x) { // R1170 1157 Word("EVENT POST ("), Walk(std::get<EventVariable>(x.t)); 1158 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); 1159 } 1160 void Before(const EventWaitStmt::EventWaitSpec &x) { // R1173, R1174 1161 common::visit(common::visitors{ 1162 [&](const ScalarIntExpr &) { Word("UNTIL_COUNT="); }, 1163 [](const StatOrErrmsg &) {}, 1164 }, 1165 x.u); 1166 } 1167 void Unparse(const EventWaitStmt &x) { // R1170 1168 Word("EVENT WAIT ("), Walk(std::get<EventVariable>(x.t)); 1169 Walk(", ", std::get<std::list<EventWaitStmt::EventWaitSpec>>(x.t), ", "); 1170 Put(')'); 1171 } 1172 void Unparse(const FormTeamStmt &x) { // R1175, R1177 1173 Word("FORM TEAM ("), Walk(std::get<ScalarIntExpr>(x.t)); 1174 Put(','), Walk(std::get<TeamVariable>(x.t)); 1175 Walk(", ", std::get<std::list<FormTeamStmt::FormTeamSpec>>(x.t), ", "); 1176 Put(')'); 1177 } 1178 void Before(const FormTeamStmt::FormTeamSpec &x) { // R1176, R1178 1179 common::visit(common::visitors{ 1180 [&](const ScalarIntExpr &) { Word("NEW_INDEX="); }, 1181 [](const StatOrErrmsg &) {}, 1182 }, 1183 x.u); 1184 } 1185 void Unparse(const LockStmt &x) { // R1179 1186 Word("LOCK ("), Walk(std::get<LockVariable>(x.t)); 1187 Walk(", ", std::get<std::list<LockStmt::LockStat>>(x.t), ", "); 1188 Put(')'); 1189 } 1190 void Before(const LockStmt::LockStat &x) { // R1180 1191 common::visit( 1192 common::visitors{ 1193 [&](const ScalarLogicalVariable &) { Word("ACQUIRED_LOCK="); }, 1194 [](const StatOrErrmsg &) {}, 1195 }, 1196 x.u); 1197 } 1198 void Unparse(const UnlockStmt &x) { // R1181 1199 Word("UNLOCK ("), Walk(std::get<LockVariable>(x.t)); 1200 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "); 1201 Put(')'); 1202 } 1203 1204 void Unparse(const OpenStmt &x) { // R1204 1205 Word("OPEN ("), Walk(x.v, ", "), Put(')'); 1206 } 1207 bool Pre(const ConnectSpec &x) { // R1205 1208 return common::visit(common::visitors{ 1209 [&](const FileUnitNumber &) { 1210 Word("UNIT="); 1211 return true; 1212 }, 1213 [&](const FileNameExpr &) { 1214 Word("FILE="); 1215 return true; 1216 }, 1217 [&](const ConnectSpec::CharExpr &y) { 1218 Walk(y.t, "="); 1219 return false; 1220 }, 1221 [&](const MsgVariable &) { 1222 Word("IOMSG="); 1223 return true; 1224 }, 1225 [&](const StatVariable &) { 1226 Word("IOSTAT="); 1227 return true; 1228 }, 1229 [&](const ConnectSpec::Recl &) { 1230 Word("RECL="); 1231 return true; 1232 }, 1233 [&](const ConnectSpec::Newunit &) { 1234 Word("NEWUNIT="); 1235 return true; 1236 }, 1237 [&](const ErrLabel &) { 1238 Word("ERR="); 1239 return true; 1240 }, 1241 [&](const StatusExpr &) { 1242 Word("STATUS="); 1243 return true; 1244 }, 1245 }, 1246 x.u); 1247 } 1248 void Unparse(const CloseStmt &x) { // R1208 1249 Word("CLOSE ("), Walk(x.v, ", "), Put(')'); 1250 } 1251 void Before(const CloseStmt::CloseSpec &x) { // R1209 1252 common::visit(common::visitors{ 1253 [&](const FileUnitNumber &) { Word("UNIT="); }, 1254 [&](const StatVariable &) { Word("IOSTAT="); }, 1255 [&](const MsgVariable &) { Word("IOMSG="); }, 1256 [&](const ErrLabel &) { Word("ERR="); }, 1257 [&](const StatusExpr &) { Word("STATUS="); }, 1258 }, 1259 x.u); 1260 } 1261 void Unparse(const ReadStmt &x) { // R1210 1262 Word("READ "); 1263 if (x.iounit) { 1264 Put('('), Walk(x.iounit); 1265 if (x.format) { 1266 Put(", "), Walk(x.format); 1267 } 1268 Walk(", ", x.controls, ", "); 1269 Put(')'); 1270 } else if (x.format) { 1271 Walk(x.format); 1272 if (!x.items.empty()) { 1273 Put(", "); 1274 } 1275 } else { 1276 Put('('), Walk(x.controls, ", "), Put(')'); 1277 } 1278 Walk(" ", x.items, ", "); 1279 } 1280 void Unparse(const WriteStmt &x) { // R1211 1281 Word("WRITE ("); 1282 if (x.iounit) { 1283 Walk(x.iounit); 1284 if (x.format) { 1285 Put(", "), Walk(x.format); 1286 } 1287 Walk(", ", x.controls, ", "); 1288 } else { 1289 Walk(x.controls, ", "); 1290 } 1291 Put(')'), Walk(" ", x.items, ", "); 1292 } 1293 void Unparse(const PrintStmt &x) { // R1212 1294 Word("PRINT "), Walk(std::get<Format>(x.t)); 1295 Walk(", ", std::get<std::list<OutputItem>>(x.t), ", "); 1296 } 1297 bool Pre(const IoControlSpec &x) { // R1213 1298 return common::visit(common::visitors{ 1299 [&](const IoUnit &) { 1300 Word("UNIT="); 1301 return true; 1302 }, 1303 [&](const Format &) { 1304 Word("FMT="); 1305 return true; 1306 }, 1307 [&](const Name &) { 1308 Word("NML="); 1309 return true; 1310 }, 1311 [&](const IoControlSpec::CharExpr &y) { 1312 Walk(y.t, "="); 1313 return false; 1314 }, 1315 [&](const IoControlSpec::Asynchronous &) { 1316 Word("ASYNCHRONOUS="); 1317 return true; 1318 }, 1319 [&](const EndLabel &) { 1320 Word("END="); 1321 return true; 1322 }, 1323 [&](const EorLabel &) { 1324 Word("EOR="); 1325 return true; 1326 }, 1327 [&](const ErrLabel &) { 1328 Word("ERR="); 1329 return true; 1330 }, 1331 [&](const IdVariable &) { 1332 Word("ID="); 1333 return true; 1334 }, 1335 [&](const MsgVariable &) { 1336 Word("IOMSG="); 1337 return true; 1338 }, 1339 [&](const StatVariable &) { 1340 Word("IOSTAT="); 1341 return true; 1342 }, 1343 [&](const IoControlSpec::Pos &) { 1344 Word("POS="); 1345 return true; 1346 }, 1347 [&](const IoControlSpec::Rec &) { 1348 Word("REC="); 1349 return true; 1350 }, 1351 [&](const IoControlSpec::Size &) { 1352 Word("SIZE="); 1353 return true; 1354 }, 1355 }, 1356 x.u); 1357 } 1358 void Unparse(const InputImpliedDo &x) { // R1218 1359 Put('('), Walk(std::get<std::list<InputItem>>(x.t), ", "), Put(", "); 1360 Walk(std::get<IoImpliedDoControl>(x.t)), Put(')'); 1361 } 1362 void Unparse(const OutputImpliedDo &x) { // R1219 1363 Put('('), Walk(std::get<std::list<OutputItem>>(x.t), ", "), Put(", "); 1364 Walk(std::get<IoImpliedDoControl>(x.t)), Put(')'); 1365 } 1366 void Unparse(const WaitStmt &x) { // R1222 1367 Word("WAIT ("), Walk(x.v, ", "), Put(')'); 1368 } 1369 void Before(const WaitSpec &x) { // R1223 1370 common::visit(common::visitors{ 1371 [&](const FileUnitNumber &) { Word("UNIT="); }, 1372 [&](const EndLabel &) { Word("END="); }, 1373 [&](const EorLabel &) { Word("EOR="); }, 1374 [&](const ErrLabel &) { Word("ERR="); }, 1375 [&](const IdExpr &) { Word("ID="); }, 1376 [&](const MsgVariable &) { Word("IOMSG="); }, 1377 [&](const StatVariable &) { Word("IOSTAT="); }, 1378 }, 1379 x.u); 1380 } 1381 void Unparse(const BackspaceStmt &x) { // R1224 1382 Word("BACKSPACE ("), Walk(x.v, ", "), Put(')'); 1383 } 1384 void Unparse(const EndfileStmt &x) { // R1225 1385 Word("ENDFILE ("), Walk(x.v, ", "), Put(')'); 1386 } 1387 void Unparse(const RewindStmt &x) { // R1226 1388 Word("REWIND ("), Walk(x.v, ", "), Put(')'); 1389 } 1390 void Before(const PositionOrFlushSpec &x) { // R1227 & R1229 1391 common::visit(common::visitors{ 1392 [&](const FileUnitNumber &) { Word("UNIT="); }, 1393 [&](const MsgVariable &) { Word("IOMSG="); }, 1394 [&](const StatVariable &) { Word("IOSTAT="); }, 1395 [&](const ErrLabel &) { Word("ERR="); }, 1396 }, 1397 x.u); 1398 } 1399 void Unparse(const FlushStmt &x) { // R1228 1400 Word("FLUSH ("), Walk(x.v, ", "), Put(')'); 1401 } 1402 void Unparse(const InquireStmt &x) { // R1230 1403 Word("INQUIRE ("); 1404 common::visit( 1405 common::visitors{ 1406 [&](const InquireStmt::Iolength &y) { 1407 Word("IOLENGTH="), Walk(y.t, ") "); 1408 }, 1409 [&](const std::list<InquireSpec> &y) { Walk(y, ", "), Put(')'); }, 1410 }, 1411 x.u); 1412 } 1413 bool Pre(const InquireSpec &x) { // R1231 1414 return common::visit(common::visitors{ 1415 [&](const FileUnitNumber &) { 1416 Word("UNIT="); 1417 return true; 1418 }, 1419 [&](const FileNameExpr &) { 1420 Word("FILE="); 1421 return true; 1422 }, 1423 [&](const InquireSpec::CharVar &y) { 1424 Walk(y.t, "="); 1425 return false; 1426 }, 1427 [&](const InquireSpec::IntVar &y) { 1428 Walk(y.t, "="); 1429 return false; 1430 }, 1431 [&](const InquireSpec::LogVar &y) { 1432 Walk(y.t, "="); 1433 return false; 1434 }, 1435 [&](const IdExpr &) { 1436 Word("ID="); 1437 return true; 1438 }, 1439 [&](const ErrLabel &) { 1440 Word("ERR="); 1441 return true; 1442 }, 1443 }, 1444 x.u); 1445 } 1446 1447 void Before(const FormatStmt &) { // R1301 1448 Word("FORMAT"); 1449 } 1450 void Unparse(const format::FormatSpecification &x) { // R1302, R1303, R1305 1451 Put('('), Walk("", x.items, ",", x.unlimitedItems.empty() ? "" : ","); 1452 Walk("*(", x.unlimitedItems, ",", ")"), Put(')'); 1453 } 1454 void Unparse(const format::FormatItem &x) { // R1304, R1306, R1321 1455 if (x.repeatCount) { 1456 Walk(*x.repeatCount); 1457 } 1458 common::visit(common::visitors{ 1459 [&](const std::string &y) { PutNormalized(y); }, 1460 [&](const std::list<format::FormatItem> &y) { 1461 Walk("(", y, ",", ")"); 1462 }, 1463 [&](const auto &y) { Walk(y); }, 1464 }, 1465 x.u); 1466 } 1467 void Unparse( 1468 const format::IntrinsicTypeDataEditDesc &x) { // R1307(1/2) - R1311 1469 switch (x.kind) { 1470 #define FMT(x) \ 1471 case format::IntrinsicTypeDataEditDesc::Kind::x: \ 1472 Put(#x); \ 1473 break 1474 FMT(I); 1475 FMT(B); 1476 FMT(O); 1477 FMT(Z); 1478 FMT(F); 1479 FMT(E); 1480 FMT(EN); 1481 FMT(ES); 1482 FMT(EX); 1483 FMT(G); 1484 FMT(L); 1485 FMT(A); 1486 FMT(D); 1487 #undef FMT 1488 } 1489 Walk(x.width), Walk(".", x.digits), Walk("E", x.exponentWidth); 1490 } 1491 void Unparse(const format::DerivedTypeDataEditDesc &x) { // R1307(2/2), R1312 1492 Word("DT"); 1493 if (!x.type.empty()) { 1494 Put('"'), Put(x.type), Put('"'); 1495 } 1496 Walk("(", x.parameters, ",", ")"); 1497 } 1498 void Unparse(const format::ControlEditDesc &x) { // R1313, R1315-R1320 1499 switch (x.kind) { 1500 case format::ControlEditDesc::Kind::T: 1501 Word("T"); 1502 Walk(x.count); 1503 break; 1504 case format::ControlEditDesc::Kind::TL: 1505 Word("TL"); 1506 Walk(x.count); 1507 break; 1508 case format::ControlEditDesc::Kind::TR: 1509 Word("TR"); 1510 Walk(x.count); 1511 break; 1512 case format::ControlEditDesc::Kind::X: 1513 if (x.count != 1) { 1514 Walk(x.count); 1515 } 1516 Word("X"); 1517 break; 1518 case format::ControlEditDesc::Kind::Slash: 1519 if (x.count != 1) { 1520 Walk(x.count); 1521 } 1522 Put('/'); 1523 break; 1524 case format::ControlEditDesc::Kind::Colon: 1525 Put(':'); 1526 break; 1527 case format::ControlEditDesc::Kind::P: 1528 Walk(x.count); 1529 Word("P"); 1530 break; 1531 #define FMT(x) \ 1532 case format::ControlEditDesc::Kind::x: \ 1533 Put(#x); \ 1534 break 1535 FMT(SS); 1536 FMT(SP); 1537 FMT(S); 1538 FMT(BN); 1539 FMT(BZ); 1540 FMT(RU); 1541 FMT(RD); 1542 FMT(RZ); 1543 FMT(RN); 1544 FMT(RC); 1545 FMT(RP); 1546 FMT(DC); 1547 FMT(DP); 1548 #undef FMT 1549 case format::ControlEditDesc::Kind::Dollar: 1550 Put('$'); 1551 break; 1552 case format::ControlEditDesc::Kind::Backslash: 1553 Put('\\'); 1554 break; 1555 } 1556 } 1557 1558 void Before(const MainProgram &x) { // R1401 1559 if (!std::get<std::optional<Statement<ProgramStmt>>>(x.t)) { 1560 Indent(); 1561 } 1562 } 1563 void Before(const ProgramStmt &) { // R1402 1564 Word("PROGRAM "), Indent(); 1565 } 1566 void Unparse(const EndProgramStmt &x) { // R1403 1567 EndSubprogram("PROGRAM", x.v); 1568 } 1569 void Before(const ModuleStmt &) { // R1405 1570 Word("MODULE "), Indent(); 1571 } 1572 void Unparse(const EndModuleStmt &x) { // R1406 1573 EndSubprogram("MODULE", x.v); 1574 } 1575 void Unparse(const UseStmt &x) { // R1409 1576 Word("USE"), Walk(", ", x.nature), Put(" :: "), Walk(x.moduleName); 1577 common::visit( 1578 common::visitors{ 1579 [&](const std::list<Rename> &y) { Walk(", ", y, ", "); }, 1580 [&](const std::list<Only> &y) { Walk(", ONLY: ", y, ", "); }, 1581 }, 1582 x.u); 1583 } 1584 void Unparse(const Rename &x) { // R1411 1585 common::visit(common::visitors{ 1586 [&](const Rename::Names &y) { Walk(y.t, " => "); }, 1587 [&](const Rename::Operators &y) { 1588 Word("OPERATOR("), Walk(y.t, ") => OPERATOR("), 1589 Put(")"); 1590 }, 1591 }, 1592 x.u); 1593 } 1594 void Unparse(const SubmoduleStmt &x) { // R1417 1595 Word("SUBMODULE ("), WalkTupleElements(x.t, ")"), Indent(); 1596 } 1597 void Unparse(const ParentIdentifier &x) { // R1418 1598 Walk(std::get<Name>(x.t)), Walk(":", std::get<std::optional<Name>>(x.t)); 1599 } 1600 void Unparse(const EndSubmoduleStmt &x) { // R1419 1601 EndSubprogram("SUBMODULE", x.v); 1602 } 1603 void Unparse(const BlockDataStmt &x) { // R1421 1604 Word("BLOCK DATA"), Walk(" ", x.v), Indent(); 1605 } 1606 void Unparse(const EndBlockDataStmt &x) { // R1422 1607 EndSubprogram("BLOCK DATA", x.v); 1608 } 1609 1610 void Unparse(const InterfaceStmt &x) { // R1503 1611 common::visit(common::visitors{ 1612 [&](const std::optional<GenericSpec> &y) { 1613 Word("INTERFACE"), Walk(" ", y); 1614 }, 1615 [&](const Abstract &) { Word("ABSTRACT INTERFACE"); }, 1616 }, 1617 x.u); 1618 Indent(); 1619 } 1620 void Unparse(const EndInterfaceStmt &x) { // R1504 1621 Outdent(), Word("END INTERFACE"), Walk(" ", x.v); 1622 } 1623 void Unparse(const ProcedureStmt &x) { // R1506 1624 if (std::get<ProcedureStmt::Kind>(x.t) == 1625 ProcedureStmt::Kind::ModuleProcedure) { 1626 Word("MODULE "); 1627 } 1628 Word("PROCEDURE :: "); 1629 Walk(std::get<std::list<Name>>(x.t), ", "); 1630 } 1631 void Before(const GenericSpec &x) { // R1508, R1509 1632 common::visit( 1633 common::visitors{ 1634 [&](const DefinedOperator &) { Word("OPERATOR("); }, 1635 [&](const GenericSpec::Assignment &) { Word("ASSIGNMENT(=)"); }, 1636 [&](const GenericSpec::ReadFormatted &) { 1637 Word("READ(FORMATTED)"); 1638 }, 1639 [&](const GenericSpec::ReadUnformatted &) { 1640 Word("READ(UNFORMATTED)"); 1641 }, 1642 [&](const GenericSpec::WriteFormatted &) { 1643 Word("WRITE(FORMATTED)"); 1644 }, 1645 [&](const GenericSpec::WriteUnformatted &) { 1646 Word("WRITE(UNFORMATTED)"); 1647 }, 1648 [](const auto &) {}, 1649 }, 1650 x.u); 1651 } 1652 void Post(const GenericSpec &x) { 1653 common::visit(common::visitors{ 1654 [&](const DefinedOperator &) { Put(')'); }, 1655 [](const auto &) {}, 1656 }, 1657 x.u); 1658 } 1659 void Unparse(const GenericStmt &x) { // R1510 1660 Word("GENERIC"), Walk(", ", std::get<std::optional<AccessSpec>>(x.t)); 1661 Put(" :: "), Walk(std::get<GenericSpec>(x.t)), Put(" => "); 1662 Walk(std::get<std::list<Name>>(x.t), ", "); 1663 } 1664 void Unparse(const ExternalStmt &x) { // R1511 1665 Word("EXTERNAL :: "), Walk(x.v, ", "); 1666 } 1667 void Unparse(const ProcedureDeclarationStmt &x) { // R1512 1668 Word("PROCEDURE("), Walk(std::get<std::optional<ProcInterface>>(x.t)); 1669 Put(')'), Walk(", ", std::get<std::list<ProcAttrSpec>>(x.t), ", "); 1670 Put(" :: "), Walk(std::get<std::list<ProcDecl>>(x.t), ", "); 1671 } 1672 void Unparse(const ProcDecl &x) { // R1515 1673 Walk(std::get<Name>(x.t)); 1674 Walk(" => ", std::get<std::optional<ProcPointerInit>>(x.t)); 1675 } 1676 void Unparse(const IntrinsicStmt &x) { // R1519 1677 Word("INTRINSIC :: "), Walk(x.v, ", "); 1678 } 1679 void Unparse(const FunctionReference &x) { // R1520 1680 Walk(std::get<ProcedureDesignator>(x.v.t)); 1681 Put('('), Walk(std::get<std::list<ActualArgSpec>>(x.v.t), ", "), Put(')'); 1682 } 1683 void Unparse(const CallStmt &x) { // R1521 1684 if (asFortran_ && x.typedCall.get()) { 1685 Put(' '); 1686 asFortran_->call(out_, *x.typedCall); 1687 Put('\n'); 1688 } else { 1689 const auto &pd{std::get<ProcedureDesignator>(x.v.t)}; 1690 const auto &args{std::get<std::list<ActualArgSpec>>(x.v.t)}; 1691 Word("CALL "), Walk(pd); 1692 if (args.empty()) { 1693 if (std::holds_alternative<ProcComponentRef>(pd.u)) { 1694 Put("()"); // pgf90 crashes on CALL to tbp without parentheses 1695 } 1696 } else { 1697 Walk("(", args, ", ", ")"); 1698 } 1699 } 1700 } 1701 void Unparse(const ActualArgSpec &x) { // R1523 1702 Walk(std::get<std::optional<Keyword>>(x.t), "="); 1703 Walk(std::get<ActualArg>(x.t)); 1704 } 1705 void Unparse(const ActualArg::PercentRef &x) { // R1524 1706 Word("%REF("), Walk(x.v), Put(')'); 1707 } 1708 void Unparse(const ActualArg::PercentVal &x) { 1709 Word("%VAL("), Walk(x.v), Put(')'); 1710 } 1711 void Before(const AltReturnSpec &) { // R1525 1712 Put('*'); 1713 } 1714 void Post(const PrefixSpec::Elemental) { Word("ELEMENTAL"); } // R1527 1715 void Post(const PrefixSpec::Impure) { Word("IMPURE"); } 1716 void Post(const PrefixSpec::Module) { Word("MODULE"); } 1717 void Post(const PrefixSpec::Non_Recursive) { Word("NON_RECURSIVE"); } 1718 void Post(const PrefixSpec::Pure) { Word("PURE"); } 1719 void Post(const PrefixSpec::Recursive) { Word("RECURSIVE"); } 1720 void Unparse(const FunctionStmt &x) { // R1530 1721 Walk("", std::get<std::list<PrefixSpec>>(x.t), " ", " "); 1722 Word("FUNCTION "), Walk(std::get<Name>(x.t)), Put("("); 1723 Walk(std::get<std::list<Name>>(x.t), ", "), Put(')'); 1724 Walk(" ", std::get<std::optional<Suffix>>(x.t)), Indent(); 1725 } 1726 void Unparse(const Suffix &x) { // R1532 1727 if (x.resultName) { 1728 Word("RESULT("), Walk(x.resultName), Put(')'); 1729 Walk(" ", x.binding); 1730 } else { 1731 Walk(x.binding); 1732 } 1733 } 1734 void Unparse(const EndFunctionStmt &x) { // R1533 1735 EndSubprogram("FUNCTION", x.v); 1736 } 1737 void Unparse(const SubroutineStmt &x) { // R1535 1738 Walk("", std::get<std::list<PrefixSpec>>(x.t), " ", " "); 1739 Word("SUBROUTINE "), Walk(std::get<Name>(x.t)); 1740 const auto &args{std::get<std::list<DummyArg>>(x.t)}; 1741 const auto &bind{std::get<std::optional<LanguageBindingSpec>>(x.t)}; 1742 if (args.empty()) { 1743 Walk(" () ", bind); 1744 } else { 1745 Walk(" (", args, ", ", ")"); 1746 Walk(" ", bind); 1747 } 1748 Indent(); 1749 } 1750 void Unparse(const EndSubroutineStmt &x) { // R1537 1751 EndSubprogram("SUBROUTINE", x.v); 1752 } 1753 void Before(const MpSubprogramStmt &) { // R1539 1754 Word("MODULE PROCEDURE "), Indent(); 1755 } 1756 void Unparse(const EndMpSubprogramStmt &x) { // R1540 1757 EndSubprogram("PROCEDURE", x.v); 1758 } 1759 void Unparse(const EntryStmt &x) { // R1541 1760 Word("ENTRY "), Walk(std::get<Name>(x.t)), Put("("); 1761 Walk(std::get<std::list<DummyArg>>(x.t), ", "), Put(")"); 1762 Walk(" ", std::get<std::optional<Suffix>>(x.t)); 1763 } 1764 void Unparse(const ReturnStmt &x) { // R1542 1765 Word("RETURN"), Walk(" ", x.v); 1766 } 1767 void Unparse(const ContainsStmt &) { // R1543 1768 Outdent(); 1769 Word("CONTAINS"); 1770 Indent(); 1771 } 1772 void Unparse(const StmtFunctionStmt &x) { // R1544 1773 Walk(std::get<Name>(x.t)), Put('('); 1774 Walk(std::get<std::list<Name>>(x.t), ", "), Put(") = "); 1775 Walk(std::get<Scalar<Expr>>(x.t)); 1776 } 1777 1778 // Directives, extensions, and deprecated constructs 1779 void Unparse(const CompilerDirective &x) { 1780 common::visit( 1781 common::visitors{ 1782 [&](const std::list<CompilerDirective::IgnoreTKR> &tkr) { 1783 Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty 1784 Walk(" ", tkr, ", "); 1785 }, 1786 [&](const std::list<CompilerDirective::NameValue> &names) { 1787 Walk("!DIR$ ", names, " "); 1788 }, 1789 }, 1790 x.u); 1791 Put('\n'); 1792 } 1793 void Unparse(const CompilerDirective::IgnoreTKR &x) { 1794 const auto &list{std::get<std::list<const char *>>(x.t)}; 1795 if (!list.empty()) { 1796 Put("("); 1797 for (const char *tkr : list) { 1798 Put(*tkr); 1799 } 1800 Put(") "); 1801 } 1802 Walk(std::get<Name>(x.t)); 1803 } 1804 void Unparse(const CompilerDirective::NameValue &x) { 1805 Walk(std::get<Name>(x.t)); 1806 Walk("=", std::get<std::optional<std::uint64_t>>(x.t)); 1807 } 1808 1809 // OpenACC Directives & Clauses 1810 void Unparse(const AccAtomicCapture &x) { 1811 BeginOpenACC(); 1812 Word("!$ACC CAPTURE"); 1813 Put("\n"); 1814 EndOpenACC(); 1815 Walk(std::get<AccAtomicCapture::Stmt1>(x.t)); 1816 Put("\n"); 1817 Walk(std::get<AccAtomicCapture::Stmt2>(x.t)); 1818 BeginOpenACC(); 1819 Word("!$ACC END ATOMIC\n"); 1820 EndOpenACC(); 1821 } 1822 void Unparse(const AccAtomicRead &x) { 1823 BeginOpenACC(); 1824 Word("!$ACC ATOMIC READ"); 1825 Put("\n"); 1826 EndOpenACC(); 1827 Walk(std::get<Statement<AssignmentStmt>>(x.t)); 1828 BeginOpenACC(); 1829 Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n"); 1830 EndOpenACC(); 1831 } 1832 void Unparse(const AccAtomicWrite &x) { 1833 BeginOpenACC(); 1834 Word("!$ACC ATOMIC WRITE"); 1835 Put("\n"); 1836 EndOpenACC(); 1837 Walk(std::get<Statement<AssignmentStmt>>(x.t)); 1838 BeginOpenACC(); 1839 Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n"); 1840 EndOpenACC(); 1841 } 1842 void Unparse(const AccAtomicUpdate &x) { 1843 BeginOpenACC(); 1844 Word("!$ACC ATOMIC UPDATE"); 1845 Put("\n"); 1846 EndOpenACC(); 1847 Walk(std::get<Statement<AssignmentStmt>>(x.t)); 1848 BeginOpenACC(); 1849 Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n"); 1850 EndOpenACC(); 1851 } 1852 void Unparse(const llvm::acc::Directive &x) { 1853 Word(llvm::acc::getOpenACCDirectiveName(x).str()); 1854 } 1855 #define GEN_FLANG_CLAUSE_UNPARSE 1856 #include "llvm/Frontend/OpenACC/ACC.inc" 1857 void Unparse(const AccObjectListWithModifier &x) { 1858 Walk(std::get<std::optional<AccDataModifier>>(x.t), ":"); 1859 Walk(std::get<AccObjectList>(x.t)); 1860 } 1861 void Unparse(const AccDataModifier::Modifier &x) { 1862 Word(AccDataModifier::EnumToString(x)); 1863 } 1864 void Unparse(const AccBindClause &x) { 1865 common::visit(common::visitors{ 1866 [&](const Name &y) { Put('('), Walk(y), Put(')'); }, 1867 [&](const ScalarDefaultCharExpr &y) { 1868 Put('('), Walk(y), Put(')'); 1869 }, 1870 }, 1871 x.u); 1872 } 1873 void Unparse(const AccDefaultClause &x) { 1874 switch (x.v) { 1875 case llvm::acc::DefaultValue::ACC_Default_none: 1876 Put("NONE"); 1877 break; 1878 case llvm::acc::DefaultValue::ACC_Default_present: 1879 Put("PRESENT"); 1880 break; 1881 } 1882 } 1883 void Unparse(const AccClauseList &x) { Walk(" ", x.v, " "); } 1884 void Unparse(const AccGangArgument &x) { 1885 Walk("NUM:", std::get<std::optional<ScalarIntExpr>>(x.t)); 1886 Walk(", STATIC:", std::get<std::optional<AccSizeExpr>>(x.t)); 1887 } 1888 void Unparse(const OpenACCBlockConstruct &x) { 1889 BeginOpenACC(); 1890 Word("!$ACC "); 1891 Walk(std::get<AccBeginBlockDirective>(x.t)); 1892 Put("\n"); 1893 EndOpenACC(); 1894 Walk(std::get<Block>(x.t), ""); 1895 BeginOpenACC(); 1896 Word("!$ACC END "); 1897 Walk(std::get<AccEndBlockDirective>(x.t)); 1898 Put("\n"); 1899 EndOpenACC(); 1900 } 1901 void Unparse(const OpenACCLoopConstruct &x) { 1902 BeginOpenACC(); 1903 Word("!$ACC "); 1904 Walk(std::get<AccBeginLoopDirective>(x.t)); 1905 Put("\n"); 1906 EndOpenACC(); 1907 Walk(std::get<std::optional<DoConstruct>>(x.t)); 1908 } 1909 void Unparse(const AccBeginLoopDirective &x) { 1910 Walk(std::get<AccLoopDirective>(x.t)); 1911 Walk(std::get<AccClauseList>(x.t)); 1912 } 1913 void Unparse(const OpenACCStandaloneConstruct &x) { 1914 BeginOpenACC(); 1915 Word("!$ACC "); 1916 Walk(std::get<AccStandaloneDirective>(x.t)); 1917 Walk(std::get<AccClauseList>(x.t)); 1918 Put("\n"); 1919 EndOpenACC(); 1920 } 1921 void Unparse(const OpenACCStandaloneDeclarativeConstruct &x) { 1922 BeginOpenACC(); 1923 Word("!$ACC "); 1924 Walk(std::get<AccDeclarativeDirective>(x.t)); 1925 Walk(std::get<AccClauseList>(x.t)); 1926 Put("\n"); 1927 EndOpenACC(); 1928 } 1929 void Unparse(const OpenACCCombinedConstruct &x) { 1930 BeginOpenACC(); 1931 Word("!$ACC "); 1932 Walk(std::get<AccBeginCombinedDirective>(x.t)); 1933 Put("\n"); 1934 EndOpenACC(); 1935 Walk(std::get<std::optional<DoConstruct>>(x.t)); 1936 BeginOpenACC(); 1937 Walk("!$ACC END ", std::get<std::optional<AccEndCombinedDirective>>(x.t), 1938 "\n"); 1939 EndOpenACC(); 1940 } 1941 void Unparse(const OpenACCRoutineConstruct &x) { 1942 BeginOpenACC(); 1943 Word("!$ACC ROUTINE"); 1944 Walk("(", std::get<std::optional<Name>>(x.t), ")"); 1945 Walk(std::get<AccClauseList>(x.t)); 1946 Put("\n"); 1947 EndOpenACC(); 1948 } 1949 void Unparse(const AccObject &x) { 1950 common::visit(common::visitors{ 1951 [&](const Designator &y) { Walk(y); }, 1952 [&](const Name &y) { Put("/"), Walk(y), Put("/"); }, 1953 }, 1954 x.u); 1955 } 1956 void Unparse(const AccObjectList &x) { Walk(x.v, ","); } 1957 void Unparse(const AccReductionOperator::Operator &x) { 1958 Word(AccReductionOperator::EnumToString(x)); 1959 } 1960 void Unparse(const AccObjectListWithReduction &x) { 1961 Walk(std::get<AccReductionOperator>(x.t)); 1962 Put(":"); 1963 Walk(std::get<AccObjectList>(x.t)); 1964 } 1965 void Unparse(const OpenACCCacheConstruct &x) { 1966 BeginOpenACC(); 1967 Word("!$ACC "); 1968 Word("CACHE("); 1969 Walk(std::get<AccObjectListWithModifier>(x.t)); 1970 Put(")"); 1971 Put("\n"); 1972 EndOpenACC(); 1973 } 1974 void Unparse(const AccWaitArgument &x) { 1975 Walk("DEVNUM:", std::get<std::optional<ScalarIntExpr>>(x.t), ":"); 1976 Walk(std::get<std::list<ScalarIntExpr>>(x.t), ","); 1977 } 1978 void Unparse(const OpenACCWaitConstruct &x) { 1979 BeginOpenACC(); 1980 Word("!$ACC "); 1981 Word("WAIT("); 1982 Walk(std::get<std::optional<AccWaitArgument>>(x.t)); 1983 Walk(std::get<AccClauseList>(x.t)); 1984 Put(")"); 1985 Put("\n"); 1986 EndOpenACC(); 1987 } 1988 1989 // OpenMP Clauses & Directives 1990 void Unparse(const OmpObject &x) { 1991 common::visit(common::visitors{ 1992 [&](const Designator &y) { Walk(y); }, 1993 [&](const Name &y) { Put("/"), Walk(y), Put("/"); }, 1994 }, 1995 x.u); 1996 } 1997 void Unparse(const OmpMapType::Always &) { Word("ALWAYS,"); } 1998 void Unparse(const OmpMapClause &x) { 1999 Walk(std::get<std::optional<OmpMapType>>(x.t), ":"); 2000 Walk(std::get<OmpObjectList>(x.t)); 2001 } 2002 void Unparse(const OmpScheduleModifier &x) { 2003 Walk(std::get<OmpScheduleModifier::Modifier1>(x.t)); 2004 Walk(",", std::get<std::optional<OmpScheduleModifier::Modifier2>>(x.t)); 2005 } 2006 void Unparse(const OmpScheduleClause &x) { 2007 Walk(std::get<std::optional<OmpScheduleModifier>>(x.t), ":"); 2008 Walk(std::get<OmpScheduleClause::ScheduleType>(x.t)); 2009 Walk(",", std::get<std::optional<ScalarIntExpr>>(x.t)); 2010 } 2011 void Unparse(const OmpAlignedClause &x) { 2012 Walk(std::get<std::list<Name>>(x.t), ","); 2013 Walk(std::get<std::optional<ScalarIntConstantExpr>>(x.t)); 2014 } 2015 void Unparse(const OmpIfClause &x) { 2016 Walk(std::get<std::optional<OmpIfClause::DirectiveNameModifier>>(x.t), ":"); 2017 Walk(std::get<ScalarLogicalExpr>(x.t)); 2018 } 2019 void Unparse(const OmpLinearClause::WithoutModifier &x) { 2020 Walk(x.names, ", "); 2021 Walk(":", x.step); 2022 } 2023 void Unparse(const OmpLinearClause::WithModifier &x) { 2024 Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")"); 2025 Walk(":", x.step); 2026 } 2027 void Unparse(const OmpReductionClause &x) { 2028 Walk(std::get<OmpReductionOperator>(x.t)); 2029 Put(":"); 2030 Walk(std::get<OmpObjectList>(x.t)); 2031 } 2032 void Unparse(const OmpInReductionClause &x) { 2033 Walk(std::get<OmpReductionOperator>(x.t)); 2034 Put(":"); 2035 Walk(std::get<OmpObjectList>(x.t)); 2036 } 2037 void Unparse(const OmpAllocateClause &x) { 2038 Walk(std::get<std::optional<OmpAllocateClause::Allocator>>(x.t)); 2039 Put(":"); 2040 Walk(std::get<OmpObjectList>(x.t)); 2041 } 2042 void Unparse(const OmpDependSinkVecLength &x) { 2043 Walk(std::get<DefinedOperator>(x.t)); 2044 Walk(std::get<ScalarIntConstantExpr>(x.t)); 2045 } 2046 void Unparse(const OmpDependSinkVec &x) { 2047 Walk(std::get<Name>(x.t)); 2048 Walk(std::get<std::optional<OmpDependSinkVecLength>>(x.t)); 2049 } 2050 void Unparse(const OmpDependClause::InOut &x) { 2051 Put("("); 2052 Walk(std::get<OmpDependenceType>(x.t)); 2053 Put(":"); 2054 Walk(std::get<std::list<Designator>>(x.t), ","); 2055 Put(")"); 2056 } 2057 bool Pre(const OmpDependClause &x) { 2058 return common::visit( 2059 common::visitors{ 2060 [&](const OmpDependClause::Source &) { 2061 Word("SOURCE"); 2062 return false; 2063 }, 2064 [&](const OmpDependClause::Sink &y) { 2065 Word("SINK:"); 2066 Walk(y.v); 2067 Put(")"); 2068 return false; 2069 }, 2070 [&](const OmpDependClause::InOut &) { return true; }, 2071 }, 2072 x.u); 2073 } 2074 void Unparse(const OmpDefaultmapClause &x) { 2075 Walk(std::get<OmpDefaultmapClause::ImplicitBehavior>(x.t)); 2076 Walk(":", 2077 std::get<std::optional<OmpDefaultmapClause::VariableCategory>>(x.t)); 2078 } 2079 #define GEN_FLANG_CLAUSE_UNPARSE 2080 #include "llvm/Frontend/OpenMP/OMP.inc" 2081 void Unparse(const OmpLoopDirective &x) { 2082 switch (x.v) { 2083 case llvm::omp::Directive::OMPD_distribute: 2084 Word("DISTRIBUTE "); 2085 break; 2086 case llvm::omp::Directive::OMPD_distribute_parallel_do: 2087 Word("DISTRIBUTE PARALLEL DO "); 2088 break; 2089 case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: 2090 Word("DISTRIBUTE PARALLEL DO SIMD "); 2091 break; 2092 case llvm::omp::Directive::OMPD_distribute_simd: 2093 Word("DISTRIBUTE SIMD "); 2094 break; 2095 case llvm::omp::Directive::OMPD_do: 2096 Word("DO "); 2097 break; 2098 case llvm::omp::Directive::OMPD_do_simd: 2099 Word("DO SIMD "); 2100 break; 2101 case llvm::omp::Directive::OMPD_parallel_do: 2102 Word("PARALLEL DO "); 2103 break; 2104 case llvm::omp::Directive::OMPD_parallel_do_simd: 2105 Word("PARALLEL DO SIMD "); 2106 break; 2107 case llvm::omp::Directive::OMPD_simd: 2108 Word("SIMD "); 2109 break; 2110 case llvm::omp::Directive::OMPD_target_parallel_do: 2111 Word("TARGET PARALLEL DO "); 2112 break; 2113 case llvm::omp::Directive::OMPD_target_parallel_do_simd: 2114 Word("TARGET PARALLEL DO SIMD "); 2115 break; 2116 case llvm::omp::Directive::OMPD_target_teams_distribute: 2117 Word("TARGET TEAMS DISTRIBUTE "); 2118 break; 2119 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do: 2120 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO "); 2121 break; 2122 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd: 2123 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD "); 2124 break; 2125 case llvm::omp::Directive::OMPD_target_teams_distribute_simd: 2126 Word("TARGET TEAMS DISTRIBUTE SIMD "); 2127 break; 2128 case llvm::omp::Directive::OMPD_target_simd: 2129 Word("TARGET SIMD "); 2130 break; 2131 case llvm::omp::Directive::OMPD_taskloop: 2132 Word("TASKLOOP "); 2133 break; 2134 case llvm::omp::Directive::OMPD_taskloop_simd: 2135 Word("TASKLOOP SIMD "); 2136 break; 2137 case llvm::omp::Directive::OMPD_teams_distribute: 2138 Word("TEAMS DISTRIBUTE "); 2139 break; 2140 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do: 2141 Word("TEAMS DISTRIBUTE PARALLEL DO "); 2142 break; 2143 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd: 2144 Word("TEAMS DISTRIBUTE PARALLEL DO SIMD "); 2145 break; 2146 case llvm::omp::Directive::OMPD_teams_distribute_simd: 2147 Word("TEAMS DISTRIBUTE SIMD "); 2148 break; 2149 default: 2150 break; 2151 } 2152 } 2153 void Unparse(const OmpObjectList &x) { Walk(x.v, ","); } 2154 void Unparse(const OmpSimpleStandaloneDirective &x) { 2155 switch (x.v) { 2156 case llvm::omp::Directive::OMPD_barrier: 2157 Word("BARRIER "); 2158 break; 2159 case llvm::omp::Directive::OMPD_taskwait: 2160 Word("TASKWAIT "); 2161 break; 2162 case llvm::omp::Directive::OMPD_taskyield: 2163 Word("TASKYIELD "); 2164 break; 2165 case llvm::omp::Directive::OMPD_target_enter_data: 2166 Word("TARGET ENTER DATA "); 2167 break; 2168 case llvm::omp::Directive::OMPD_target_exit_data: 2169 Word("TARGET EXIT DATA "); 2170 break; 2171 case llvm::omp::Directive::OMPD_target_update: 2172 Word("TARGET UPDATE "); 2173 break; 2174 case llvm::omp::Directive::OMPD_ordered: 2175 Word("ORDERED "); 2176 break; 2177 default: 2178 // Nothing to be done 2179 break; 2180 } 2181 } 2182 void Unparse(const OmpBlockDirective &x) { 2183 switch (x.v) { 2184 case llvm::omp::Directive::OMPD_master: 2185 Word("MASTER"); 2186 break; 2187 case llvm::omp::Directive::OMPD_ordered: 2188 Word("ORDERED "); 2189 break; 2190 case llvm::omp::Directive::OMPD_parallel_workshare: 2191 Word("PARALLEL WORKSHARE "); 2192 break; 2193 case llvm::omp::Directive::OMPD_parallel: 2194 Word("PARALLEL "); 2195 break; 2196 case llvm::omp::Directive::OMPD_single: 2197 Word("SINGLE "); 2198 break; 2199 case llvm::omp::Directive::OMPD_target_data: 2200 Word("TARGET DATA "); 2201 break; 2202 case llvm::omp::Directive::OMPD_target_parallel: 2203 Word("TARGET PARALLEL "); 2204 break; 2205 case llvm::omp::Directive::OMPD_target_teams: 2206 Word("TARGET TEAMS "); 2207 break; 2208 case llvm::omp::Directive::OMPD_target: 2209 Word("TARGET "); 2210 break; 2211 case llvm::omp::Directive::OMPD_taskgroup: 2212 Word("TASKGROUP "); 2213 break; 2214 case llvm::omp::Directive::OMPD_task: 2215 Word("TASK "); 2216 break; 2217 case llvm::omp::Directive::OMPD_teams: 2218 Word("TEAMS "); 2219 break; 2220 case llvm::omp::Directive::OMPD_workshare: 2221 Word("WORKSHARE "); 2222 break; 2223 default: 2224 // Nothing to be done 2225 break; 2226 } 2227 } 2228 void Unparse(const OmpAtomicClauseList &x) { Walk(" ", x.v, " "); } 2229 2230 void Unparse(const OmpAtomic &x) { 2231 BeginOpenMP(); 2232 Word("!$OMP ATOMIC"); 2233 Walk(std::get<OmpAtomicClauseList>(x.t)); 2234 Put("\n"); 2235 EndOpenMP(); 2236 Walk(std::get<Statement<AssignmentStmt>>(x.t)); 2237 BeginOpenMP(); 2238 Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n"); 2239 EndOpenMP(); 2240 } 2241 void Unparse(const OmpAtomicCapture &x) { 2242 BeginOpenMP(); 2243 Word("!$OMP ATOMIC"); 2244 Walk(std::get<0>(x.t)); 2245 Word(" CAPTURE"); 2246 Walk(std::get<2>(x.t)); 2247 Put("\n"); 2248 EndOpenMP(); 2249 Walk(std::get<OmpAtomicCapture::Stmt1>(x.t)); 2250 Put("\n"); 2251 Walk(std::get<OmpAtomicCapture::Stmt2>(x.t)); 2252 BeginOpenMP(); 2253 Word("!$OMP END ATOMIC\n"); 2254 EndOpenMP(); 2255 } 2256 void Unparse(const OmpAtomicRead &x) { 2257 BeginOpenMP(); 2258 Word("!$OMP ATOMIC"); 2259 Walk(std::get<0>(x.t)); 2260 Word(" READ"); 2261 Walk(std::get<2>(x.t)); 2262 Put("\n"); 2263 EndOpenMP(); 2264 Walk(std::get<Statement<AssignmentStmt>>(x.t)); 2265 BeginOpenMP(); 2266 Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n"); 2267 EndOpenMP(); 2268 } 2269 void Unparse(const OmpAtomicUpdate &x) { 2270 BeginOpenMP(); 2271 Word("!$OMP ATOMIC"); 2272 Walk(std::get<0>(x.t)); 2273 Word(" UPDATE"); 2274 Walk(std::get<2>(x.t)); 2275 Put("\n"); 2276 EndOpenMP(); 2277 Walk(std::get<Statement<AssignmentStmt>>(x.t)); 2278 BeginOpenMP(); 2279 Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n"); 2280 EndOpenMP(); 2281 } 2282 void Unparse(const OmpAtomicWrite &x) { 2283 BeginOpenMP(); 2284 Word("!$OMP ATOMIC"); 2285 Walk(std::get<0>(x.t)); 2286 Word(" WRITE"); 2287 Walk(std::get<2>(x.t)); 2288 Put("\n"); 2289 EndOpenMP(); 2290 Walk(std::get<Statement<AssignmentStmt>>(x.t)); 2291 BeginOpenMP(); 2292 Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n"); 2293 EndOpenMP(); 2294 } 2295 void Unparse(const OpenMPExecutableAllocate &x) { 2296 BeginOpenMP(); 2297 Word("!$OMP ALLOCATE"); 2298 Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")"); 2299 Walk(std::get<OmpClauseList>(x.t)); 2300 Put("\n"); 2301 EndOpenMP(); 2302 Walk(std::get<Statement<AllocateStmt>>(x.t)); 2303 } 2304 void Unparse(const OpenMPDeclarativeAllocate &x) { 2305 BeginOpenMP(); 2306 Word("!$OMP ALLOCATE"); 2307 Put(" ("); 2308 Walk(std::get<OmpObjectList>(x.t)); 2309 Put(")"); 2310 Walk(std::get<OmpClauseList>(x.t)); 2311 Put("\n"); 2312 EndOpenMP(); 2313 } 2314 void Unparse(const OmpCriticalDirective &x) { 2315 BeginOpenMP(); 2316 Word("!$OMP CRITICAL"); 2317 Walk(" (", std::get<std::optional<Name>>(x.t), ")"); 2318 Walk(std::get<OmpClauseList>(x.t)); 2319 Put("\n"); 2320 EndOpenMP(); 2321 } 2322 void Unparse(const OmpEndCriticalDirective &x) { 2323 BeginOpenMP(); 2324 Word("!$OMP END CRITICAL"); 2325 Walk(" (", std::get<std::optional<Name>>(x.t), ")"); 2326 Put("\n"); 2327 EndOpenMP(); 2328 } 2329 void Unparse(const OpenMPCriticalConstruct &x) { 2330 Walk(std::get<OmpCriticalDirective>(x.t)); 2331 Walk(std::get<Block>(x.t), ""); 2332 Walk(std::get<OmpEndCriticalDirective>(x.t)); 2333 } 2334 void Unparse(const OmpDeclareTargetWithList &x) { 2335 Put("("), Walk(x.v), Put(")"); 2336 } 2337 void Unparse(const OmpReductionInitializerClause &x) { 2338 Word(" INITIALIZER(OMP_PRIV = "); 2339 Walk(x.v); 2340 Put(")"); 2341 } 2342 void Unparse(const OmpReductionCombiner::FunctionCombiner &x) { 2343 const auto &pd = std::get<ProcedureDesignator>(x.v.t); 2344 const auto &args = std::get<std::list<ActualArgSpec>>(x.v.t); 2345 Walk(pd); 2346 if (args.empty()) { 2347 if (std::holds_alternative<ProcComponentRef>(pd.u)) { 2348 Put("()"); 2349 } 2350 } else { 2351 Walk("(", args, ", ", ")"); 2352 } 2353 } 2354 void Unparse(const OpenMPDeclareReductionConstruct &x) { 2355 Put("("); 2356 Walk(std::get<OmpReductionOperator>(x.t)), Put(" : "); 2357 Walk(std::get<std::list<DeclarationTypeSpec>>(x.t), ","), Put(" : "); 2358 Walk(std::get<OmpReductionCombiner>(x.t)); 2359 Put(")"); 2360 Walk(std::get<std::optional<OmpReductionInitializerClause>>(x.t)); 2361 } 2362 bool Pre(const OpenMPDeclarativeConstruct &x) { 2363 BeginOpenMP(); 2364 Word("!$OMP "); 2365 return common::visit( 2366 common::visitors{ 2367 [&](const OpenMPDeclarativeAllocate &z) { 2368 Word("ALLOCATE ("); 2369 Walk(std::get<OmpObjectList>(z.t)); 2370 Put(")"); 2371 Walk(std::get<OmpClauseList>(z.t)); 2372 Put("\n"); 2373 EndOpenMP(); 2374 return false; 2375 }, 2376 [&](const OpenMPDeclareReductionConstruct &) { 2377 Word("DECLARE REDUCTION "); 2378 return true; 2379 }, 2380 [&](const OpenMPDeclareSimdConstruct &y) { 2381 Word("DECLARE SIMD "); 2382 Walk("(", std::get<std::optional<Name>>(y.t), ")"); 2383 Walk(std::get<OmpClauseList>(y.t)); 2384 Put("\n"); 2385 EndOpenMP(); 2386 return false; 2387 }, 2388 [&](const OpenMPDeclareTargetConstruct &) { 2389 Word("DECLARE TARGET "); 2390 return true; 2391 }, 2392 [&](const OpenMPThreadprivate &) { 2393 Word("THREADPRIVATE ("); 2394 return true; 2395 }, 2396 }, 2397 x.u); 2398 } 2399 void Post(const OpenMPDeclarativeConstruct &) { 2400 Put("\n"); 2401 EndOpenMP(); 2402 } 2403 void Post(const OpenMPThreadprivate &) { 2404 Put(")\n"); 2405 EndOpenMP(); 2406 } 2407 void Unparse(const OmpSectionsDirective &x) { 2408 switch (x.v) { 2409 case llvm::omp::Directive::OMPD_sections: 2410 Word("SECTIONS "); 2411 break; 2412 case llvm::omp::Directive::OMPD_parallel_sections: 2413 Word("PARALLEL SECTIONS "); 2414 break; 2415 default: 2416 break; 2417 } 2418 } 2419 void Unparse(const OmpSectionBlocks &x) { 2420 for (const auto &y : x.v) { 2421 BeginOpenMP(); 2422 Word("!$OMP SECTION"); 2423 Put("\n"); 2424 EndOpenMP(); 2425 // y.u is an OpenMPSectionConstruct 2426 // (y.u).v is Block 2427 Walk(std::get<OpenMPSectionConstruct>(y.u).v, ""); 2428 } 2429 } 2430 void Unparse(const OpenMPSectionsConstruct &x) { 2431 BeginOpenMP(); 2432 Word("!$OMP "); 2433 Walk(std::get<OmpBeginSectionsDirective>(x.t)); 2434 Put("\n"); 2435 EndOpenMP(); 2436 Walk(std::get<OmpSectionBlocks>(x.t)); 2437 BeginOpenMP(); 2438 Word("!$OMP END "); 2439 Walk(std::get<OmpEndSectionsDirective>(x.t)); 2440 Put("\n"); 2441 EndOpenMP(); 2442 } 2443 void Unparse(const OpenMPCancellationPointConstruct &x) { 2444 BeginOpenMP(); 2445 Word("!$OMP CANCELLATION POINT "); 2446 Walk(std::get<OmpCancelType>(x.t)); 2447 Put("\n"); 2448 EndOpenMP(); 2449 } 2450 void Unparse(const OpenMPCancelConstruct &x) { 2451 BeginOpenMP(); 2452 Word("!$OMP CANCEL "); 2453 Walk(std::get<OmpCancelType>(x.t)); 2454 Walk(std::get<std::optional<OpenMPCancelConstruct::If>>(x.t)); 2455 Put("\n"); 2456 EndOpenMP(); 2457 } 2458 void Unparse(const OmpMemoryOrderClause &x) { Walk(x.v); } 2459 void Unparse(const OmpAtomicClause &x) { 2460 common::visit(common::visitors{ 2461 [&](const OmpMemoryOrderClause &y) { Walk(y); }, 2462 [&](const OmpClause &z) { Walk(z); }, 2463 }, 2464 x.u); 2465 } 2466 void Unparse(const OpenMPFlushConstruct &x) { 2467 BeginOpenMP(); 2468 Word("!$OMP FLUSH "); 2469 Walk(std::get<std::optional<std::list<OmpMemoryOrderClause>>>(x.t)); 2470 Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")"); 2471 Put("\n"); 2472 EndOpenMP(); 2473 } 2474 void Unparse(const OmpEndLoopDirective &x) { 2475 BeginOpenMP(); 2476 Word("!$OMP END "); 2477 Walk(std::get<OmpLoopDirective>(x.t)); 2478 Walk(std::get<OmpClauseList>(x.t)); 2479 Put("\n"); 2480 EndOpenMP(); 2481 } 2482 void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); } 2483 void Unparse(const OpenMPSimpleStandaloneConstruct &x) { 2484 BeginOpenMP(); 2485 Word("!$OMP "); 2486 Walk(std::get<OmpSimpleStandaloneDirective>(x.t)); 2487 Walk(std::get<OmpClauseList>(x.t)); 2488 Put("\n"); 2489 EndOpenMP(); 2490 } 2491 void Unparse(const OpenMPBlockConstruct &x) { 2492 BeginOpenMP(); 2493 Word("!$OMP "); 2494 Walk(std::get<OmpBeginBlockDirective>(x.t)); 2495 Put("\n"); 2496 EndOpenMP(); 2497 Walk(std::get<Block>(x.t), ""); 2498 BeginOpenMP(); 2499 Word("!$OMP END "); 2500 Walk(std::get<OmpEndBlockDirective>(x.t)); 2501 Put("\n"); 2502 EndOpenMP(); 2503 } 2504 void Unparse(const OpenMPLoopConstruct &x) { 2505 BeginOpenMP(); 2506 Word("!$OMP "); 2507 Walk(std::get<OmpBeginLoopDirective>(x.t)); 2508 Put("\n"); 2509 EndOpenMP(); 2510 Walk(std::get<std::optional<DoConstruct>>(x.t)); 2511 Walk(std::get<std::optional<OmpEndLoopDirective>>(x.t)); 2512 } 2513 void Unparse(const BasedPointer &x) { 2514 Put('('), Walk(std::get<0>(x.t)), Put(","), Walk(std::get<1>(x.t)); 2515 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"), Put(')'); 2516 } 2517 void Unparse(const BasedPointerStmt &x) { Walk("POINTER ", x.v, ","); } 2518 void Post(const StructureField &x) { 2519 if (const auto *def{std::get_if<Statement<DataComponentDefStmt>>(&x.u)}) { 2520 for (const auto &item : 2521 std::get<std::list<ComponentOrFill>>(def->statement.t)) { 2522 if (const auto *comp{std::get_if<ComponentDecl>(&item.u)}) { 2523 structureComponents_.insert(std::get<Name>(comp->t).source); 2524 } 2525 } 2526 } 2527 } 2528 void Unparse(const StructureStmt &x) { 2529 Word("STRUCTURE "); 2530 // The name, if present, includes the /slashes/ 2531 Walk(std::get<std::optional<Name>>(x.t)); 2532 Walk(" ", std::get<std::list<EntityDecl>>(x.t), ", "); 2533 Indent(); 2534 } 2535 void Post(const Union::UnionStmt &) { Word("UNION"), Indent(); } 2536 void Post(const Union::EndUnionStmt &) { Outdent(), Word("END UNION"); } 2537 void Post(const Map::MapStmt &) { Word("MAP"), Indent(); } 2538 void Post(const Map::EndMapStmt &) { Outdent(), Word("END MAP"); } 2539 void Post(const StructureDef::EndStructureStmt &) { 2540 Outdent(), Word("END STRUCTURE"); 2541 } 2542 void Unparse(const OldParameterStmt &x) { 2543 Word("PARAMETER "), Walk(x.v, ", "); 2544 } 2545 void Unparse(const ArithmeticIfStmt &x) { 2546 Word("IF ("), Walk(std::get<Expr>(x.t)), Put(") "); 2547 Walk(std::get<1>(x.t)), Put(", "); 2548 Walk(std::get<2>(x.t)), Put(", "); 2549 Walk(std::get<3>(x.t)); 2550 } 2551 void Unparse(const AssignStmt &x) { 2552 Word("ASSIGN "), Walk(std::get<Label>(x.t)); 2553 Word(" TO "), Walk(std::get<Name>(x.t)); 2554 } 2555 void Unparse(const AssignedGotoStmt &x) { 2556 Word("GO TO "), Walk(std::get<Name>(x.t)); 2557 Walk(", (", std::get<std::list<Label>>(x.t), ", ", ")"); 2558 } 2559 void Unparse(const PauseStmt &x) { Word("PAUSE"), Walk(" ", x.v); } 2560 2561 #define WALK_NESTED_ENUM(CLASS, ENUM) \ 2562 void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); } 2563 WALK_NESTED_ENUM(AccessSpec, Kind) // R807 2564 WALK_NESTED_ENUM(common, TypeParamAttr) // R734 2565 WALK_NESTED_ENUM(IntentSpec, Intent) // R826 2566 WALK_NESTED_ENUM(ImplicitStmt, ImplicitNoneNameSpec) // R866 2567 WALK_NESTED_ENUM(ConnectSpec::CharExpr, Kind) // R1205 2568 WALK_NESTED_ENUM(IoControlSpec::CharExpr, Kind) 2569 WALK_NESTED_ENUM(InquireSpec::CharVar, Kind) 2570 WALK_NESTED_ENUM(InquireSpec::IntVar, Kind) 2571 WALK_NESTED_ENUM(InquireSpec::LogVar, Kind) 2572 WALK_NESTED_ENUM(ProcedureStmt, Kind) // R1506 2573 WALK_NESTED_ENUM(UseStmt, ModuleNature) // R1410 2574 WALK_NESTED_ENUM(OmpProcBindClause, Type) // OMP PROC_BIND 2575 WALK_NESTED_ENUM(OmpDefaultClause, Type) // OMP DEFAULT 2576 WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP DEFAULTMAP 2577 WALK_NESTED_ENUM(OmpDefaultmapClause, VariableCategory) // OMP DEFAULTMAP 2578 WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier 2579 WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier 2580 WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type 2581 WALK_NESTED_ENUM(OmpMapType, Type) // OMP map-type 2582 WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type 2583 WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier 2584 WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type 2585 #undef WALK_NESTED_ENUM 2586 2587 void Done() const { CHECK(indent_ == 0); } 2588 2589 private: 2590 void Put(char); 2591 void Put(const char *); 2592 void Put(const std::string &); 2593 void PutNormalized(const std::string &); 2594 void PutKeywordLetter(char); 2595 void Word(const char *); 2596 void Word(const std::string &); 2597 void Indent() { indent_ += indentationAmount_; } 2598 void Outdent() { 2599 CHECK(indent_ >= indentationAmount_); 2600 indent_ -= indentationAmount_; 2601 } 2602 void BeginOpenMP() { openmpDirective_ = true; } 2603 void EndOpenMP() { openmpDirective_ = false; } 2604 void BeginOpenACC() { openaccDirective_ = true; } 2605 void EndOpenACC() { openaccDirective_ = false; } 2606 2607 // Call back to the traversal framework. 2608 template <typename T> void Walk(const T &x) { 2609 Fortran::parser::Walk(x, *this); 2610 } 2611 2612 // Traverse a std::optional<> value. Emit a prefix and/or a suffix string 2613 // only when it contains a value. 2614 template <typename A> 2615 void Walk( 2616 const char *prefix, const std::optional<A> &x, const char *suffix = "") { 2617 if (x) { 2618 Word(prefix), Walk(*x), Word(suffix); 2619 } 2620 } 2621 template <typename A> 2622 void Walk(const std::optional<A> &x, const char *suffix = "") { 2623 return Walk("", x, suffix); 2624 } 2625 2626 // Traverse a std::list<>. Separate the elements with an optional string. 2627 // Emit a prefix and/or a suffix string only when the list is not empty. 2628 template <typename A> 2629 void Walk(const char *prefix, const std::list<A> &list, 2630 const char *comma = ", ", const char *suffix = "") { 2631 if (!list.empty()) { 2632 const char *str{prefix}; 2633 for (const auto &x : list) { 2634 Word(str), Walk(x); 2635 str = comma; 2636 } 2637 Word(suffix); 2638 } 2639 } 2640 template <typename A> 2641 void Walk(const std::list<A> &list, const char *comma = ", ", 2642 const char *suffix = "") { 2643 return Walk("", list, comma, suffix); 2644 } 2645 2646 // Traverse a std::tuple<>, with an optional separator. 2647 template <std::size_t J = 0, typename T> 2648 void WalkTupleElements(const T &tuple, const char *separator) { 2649 if (J > 0 && J < std::tuple_size_v<T>) { 2650 Word(separator); // this usage dodges "unused parameter" warning 2651 } 2652 if constexpr (J < std::tuple_size_v<T>) { 2653 Walk(std::get<J>(tuple)); 2654 WalkTupleElements<J + 1>(tuple, separator); 2655 } 2656 } 2657 template <typename... A> 2658 void Walk(const std::tuple<A...> &tuple, const char *separator = "") { 2659 WalkTupleElements(tuple, separator); 2660 } 2661 2662 void EndSubprogram(const char *kind, const std::optional<Name> &name) { 2663 Outdent(), Word("END "), Word(kind), Walk(" ", name); 2664 structureComponents_.clear(); 2665 } 2666 2667 llvm::raw_ostream &out_; 2668 int indent_{0}; 2669 const int indentationAmount_{1}; 2670 int column_{1}; 2671 const int maxColumns_{80}; 2672 std::set<CharBlock> structureComponents_; 2673 Encoding encoding_{Encoding::UTF_8}; 2674 bool capitalizeKeywords_{true}; 2675 bool openaccDirective_{false}; 2676 bool openmpDirective_{false}; 2677 bool backslashEscapes_{false}; 2678 preStatementType *preStatement_{nullptr}; 2679 AnalyzedObjectsAsFortran *asFortran_{nullptr}; 2680 }; 2681 2682 void UnparseVisitor::Put(char ch) { 2683 int sav = indent_; 2684 if (openmpDirective_ || openaccDirective_) { 2685 indent_ = 0; 2686 } 2687 if (column_ <= 1) { 2688 if (ch == '\n') { 2689 return; 2690 } 2691 for (int j{0}; j < indent_; ++j) { 2692 out_ << ' '; 2693 } 2694 column_ = indent_ + 2; 2695 } else if (ch == '\n') { 2696 column_ = 1; 2697 } else if (++column_ >= maxColumns_) { 2698 out_ << "&\n"; 2699 for (int j{0}; j < indent_; ++j) { 2700 out_ << ' '; 2701 } 2702 if (openmpDirective_) { 2703 out_ << "!$OMP&"; 2704 column_ = 8; 2705 } else if (openaccDirective_) { 2706 out_ << "!$ACC&"; 2707 column_ = 8; 2708 } else { 2709 out_ << '&'; 2710 column_ = indent_ + 3; 2711 } 2712 } 2713 out_ << ch; 2714 if (openmpDirective_ || openaccDirective_) { 2715 indent_ = sav; 2716 } 2717 } 2718 2719 void UnparseVisitor::Put(const char *str) { 2720 for (; *str != '\0'; ++str) { 2721 Put(*str); 2722 } 2723 } 2724 2725 void UnparseVisitor::Put(const std::string &str) { 2726 for (char ch : str) { 2727 Put(ch); 2728 } 2729 } 2730 2731 void UnparseVisitor::PutNormalized(const std::string &str) { 2732 auto decoded{DecodeString<std::string, Encoding::LATIN_1>(str, true)}; 2733 std::string encoded{EncodeString<Encoding::LATIN_1>(decoded)}; 2734 Put(QuoteCharacterLiteral(encoded, backslashEscapes_)); 2735 } 2736 2737 void UnparseVisitor::PutKeywordLetter(char ch) { 2738 if (capitalizeKeywords_) { 2739 Put(ToUpperCaseLetter(ch)); 2740 } else { 2741 Put(ToLowerCaseLetter(ch)); 2742 } 2743 } 2744 2745 void UnparseVisitor::Word(const char *str) { 2746 for (; *str != '\0'; ++str) { 2747 PutKeywordLetter(*str); 2748 } 2749 } 2750 2751 void UnparseVisitor::Word(const std::string &str) { Word(str.c_str()); } 2752 2753 template <typename A> 2754 void Unparse(llvm::raw_ostream &out, const A &root, Encoding encoding, 2755 bool capitalizeKeywords, bool backslashEscapes, 2756 preStatementType *preStatement, AnalyzedObjectsAsFortran *asFortran) { 2757 UnparseVisitor visitor{out, 1, encoding, capitalizeKeywords, backslashEscapes, 2758 preStatement, asFortran}; 2759 Walk(root, visitor); 2760 visitor.Done(); 2761 } 2762 2763 template void Unparse<Program>(llvm::raw_ostream &, const Program &, Encoding, 2764 bool, bool, preStatementType *, AnalyzedObjectsAsFortran *); 2765 template void Unparse<Expr>(llvm::raw_ostream &, const Expr &, Encoding, bool, 2766 bool, preStatementType *, AnalyzedObjectsAsFortran *); 2767 } // namespace Fortran::parser 2768