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