[flang][OpenMP]Add parsing support for MAP(MAPPER(name) ...) (#116274)
[llvm-project.git] / flang / lib / Parser / unparse.cpp
blobed843bf69f892895298403da8da4d3df5f62cfaa
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 //===----------------------------------------------------------------------===//
9 // Generates Fortran from the content of a parse tree, using the
10 // traversal templates in parse-tree-visitor.h.
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>
26 namespace Fortran::parser {
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} {}
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
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;
60 } else {
61 Before(x);
62 return true; // there's no Unparse() defined here, Walk() the descendents
65 template <typename T> void Post(const T &) {}
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); }
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_);
82 Walk(x.label, " ");
84 template <typename T> void Post(const Statement<T> &) { Put('\n'); }
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).
90 void Unparse(const Program &x) { // R501
91 Walk("", x.v, "\n"); // put blank lines between ProgramUnits
94 void Unparse(const Name &x) { // R603
95 Put(x.ToString());
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('.');
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(')');
144 void Unparse(const DeclarationTypeSpec::Class &x) {
145 Word("CLASS("), Walk(x.derived), Put(')');
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('/');
152 void Before(const IntrinsicTypeSpec::Real &) { // R704
153 Word("REAL");
155 void Before(const IntrinsicTypeSpec::Complex &) { Word("COMPLEX"); }
156 void Post(const IntrinsicTypeSpec::DoublePrecision &) {
157 Word("DOUBLE PRECISION");
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");
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");
170 void Post(const VectorTypeSpec::QuadVectorTypeSpec &) {
171 Word("__VECTOR_QUAD");
173 void Before(const IntegerTypeSpec &) { // R705
174 Word("INTEGER");
176 void Unparse(const KindSelector &x) { // R706
177 common::visit(
178 common::visitors{
179 [&](const ScalarIntConstantExpr &y) {
180 Put('('), Word("KIND="), Walk(y), Put(')');
182 [&](const KindSelector::StarSize &y) { Put('*'), Walk(y.v); },
184 x.u);
186 void Unparse(const SignedIntLiteralConstant &x) { // R707
187 Put(std::get<CharBlock>(x.t).ToString());
188 Walk("_", std::get<std::optional<KindParam>>(x.t));
190 void Unparse(const IntLiteralConstant &x) { // R708
191 Put(std::get<CharBlock>(x.t).ToString());
192 Walk("_", std::get<std::optional<KindParam>>(x.t));
194 void Unparse(const Sign &x) { // R712
195 Put(x == Sign::Negative ? '-' : '+');
197 void Unparse(const RealLiteralConstant &x) { // R714, R715
198 Put(x.real.source.ToString()), Walk("_", x.kind);
200 void Unparse(const ComplexLiteralConstant &x) { // R718 - R720
201 Put('('), Walk(x.t, ","), Put(')');
203 void Unparse(const CharSelector::LengthAndKind &x) { // R721
204 Put('('), Word("KIND="), Walk(x.kind);
205 Walk(", LEN=", x.length), Put(')');
207 void Unparse(const LengthSelector &x) { // R722
208 common::visit(common::visitors{
209 [&](const TypeParamValue &y) {
210 Put('('), Word("LEN="), Walk(y), Put(')');
212 [&](const CharLength &y) { Put('*'), Walk(y); },
214 x.u);
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); },
222 x.u);
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('_');
229 PutNormalized(str);
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]);
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));
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();
252 void Unparse(const Abstract &) { // R728, &c.
253 Word("ABSTRACT");
255 void Post(const TypeAttrSpec::BindC &) { Word("BIND(C)"); }
256 void Unparse(const TypeAttrSpec::Extends &x) {
257 Word("EXTENDS("), Walk(x.v), Put(')');
259 void Unparse(const EndTypeStmt &x) { // R730
260 Outdent(), Word("END TYPE"), Walk(" ", x.v);
262 void Unparse(const SequenceStmt &) { // R731
263 Word("SEQUENCE");
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), ", ");
270 void Unparse(const TypeParamDecl &x) { // R733
271 Walk(std::get<Name>(x.t));
272 Walk("=", std::get<std::optional<ScalarIntConstantExpr>>(x.t));
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);
293 [](const FillDecl &) { return false; },
295 c.u);
296 }))) {
297 Put(" ::");
299 Put(' '), Walk(decls, ", ");
301 void Unparse(const Allocatable &) { // R738
302 Word("ALLOCATABLE");
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 &) {},
312 x.u);
314 void Post(const ComponentAttrSpec &x) {
315 common::visit(common::visitors{
316 [&](const CoarraySpec &) { Put(']'); },
317 [&](const ComponentArraySpec &) { Put(')'); },
318 [](const auto &) {},
320 x.u);
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));
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));
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); },
340 x.u);
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), ", ");
348 void Unparse(const NoPass &) { // R742
349 Word("NOPASS");
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, ", ", "/");
362 x.u);
364 void Unparse(const PrivateStmt &) { // R745
365 Word("PRIVATE");
367 void Unparse(const TypeBoundProcedureStmt::WithoutInterface &x) { // R749
368 Word("PROCEDURE"), Walk(", ", x.attributes, ", ");
369 Put(" :: "), Walk(x.declarations, ", ");
371 void Unparse(const TypeBoundProcedureStmt::WithInterface &x) {
372 Word("PROCEDURE("), Walk(x.interfaceName), Put("), ");
373 Walk(x.attributes);
374 Put(" :: "), Walk(x.bindingNames, ", ");
376 void Unparse(const TypeBoundProcDecl &x) { // R750
377 Walk(std::get<Name>(x.t));
378 Walk(" => ", std::get<std::optional<Name>>(x.t));
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), ", ");
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, ", ");
390 void Unparse(const DerivedTypeSpec &x) { // R754
391 Walk(std::get<Name>(x.t));
392 Walk("(", std::get<std::list<TypeParamSpec>>(x.t), ",", ")");
394 void Unparse(const TypeParamSpec &x) { // R755
395 Walk(std::get<std::optional<Keyword>>(x.t), "=");
396 Walk(std::get<TypeParamValue>(x.t));
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(')');
402 void Unparse(const ComponentSpec &x) { // R757
403 Walk(std::get<std::optional<Keyword>>(x.t), "=");
404 Walk(std::get<ComponentDataSource>(x.t));
406 void Unparse(const EnumDefStmt &) { // R760
407 Word("ENUM, BIND(C)"), Indent();
409 void Unparse(const EnumeratorDefStmt &x) { // R761
410 Word("ENUMERATOR :: "), Walk(x.v, ", ");
412 void Unparse(const Enumerator &x) { // R762
413 Walk(std::get<NamedConstant>(x.t));
414 Walk(" = ", std::get<std::optional<ScalarIntConstantExpr>>(x.t));
416 void Post(const EndEnumStmt &) { // R763
417 Outdent(), Word("END ENUM");
419 void Unparse(const BOZLiteralConstant &x) { // R764 - R767
420 Put(x.v);
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));
426 void Unparse(const ArrayConstructor &x) { // R769
427 Put('['), Walk(x.v), Put(']');
429 void Unparse(const AcSpec &x) { // R770
430 Walk(x.type, "::"), Walk(x.values, ", ");
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);
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(')');
440 void Unparse(const AcImpliedDoControl &x) { // R775
441 Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::");
442 Walk(std::get<AcImpliedDoControl::Bounds>(x.t));
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, ", ");
451 static const auto isInitializerOldStyle{[](const Initialization &i) {
452 return std::holds_alternative<
453 std::list<common::Indirection<DataStmtValue>>>(i.u);
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);
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);
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;
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;
479 if (isRecord) {
480 // Never put :: in a legacy extension RECORD// statement.
481 return false;
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;
491 // Don't use :: with intrinsic types. Otherwise, use it.
492 return !std::holds_alternative<IntrinsicTypeSpec>(dts.u);
495 if (useDoubledColons()) {
496 Put(" ::");
498 Put(' '), Walk(std::get<std::list<EntityDecl>>(x.t), ", ");
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 &) {},
506 x.u);
508 void Post(const AttrSpec &x) {
509 common::visit(common::visitors{
510 [&](const CoarraySpec &) { Put(']'); },
511 [&](const ArraySpec &) { Put(')'); },
512 [](const auto &) {},
514 x.u);
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));
523 void Unparse(const NullInit &) { // R806
524 Word("NULL()");
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");
533 Put(')');
535 void Unparse(const CoarraySpec &x) { // R809
536 common::visit(common::visitors{
537 [&](const DeferredCoshapeSpecList &y) { Walk(y); },
538 [&](const ExplicitCoshapeSpec &y) { Walk(y); },
540 x.u);
542 void Unparse(const DeferredCoshapeSpecList &x) { // R810
543 for (auto j{x.v}; j > 0; --j) {
544 Put(':');
545 if (j > 1) {
546 Put(',');
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('*');
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));
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); },
568 x.u);
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(',');
579 void Unparse(const AssumedImpliedSpec &x) { // R821
580 Walk(x.v, ":");
581 Put('*');
583 void Unparse(const AssumedSizeSpec &x) { // R822
584 Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ",");
585 Walk(std::get<AssumedImpliedSpec>(x.t));
587 void Unparse(const ImpliedShapeSpec &x) { // R823
588 Walk(x.v, ",");
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(")");
604 void Unparse(const AccessStmt &x) { // R827
605 Walk(std::get<AccessSpec>(x.t));
606 Walk(" :: ", std::get<std::list<AccessId>>(x.t), ", ");
608 void Unparse(const AllocatableStmt &x) { // R829
609 Word("ALLOCATABLE :: "), Walk(x.v, ", ");
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), "]");
616 void Unparse(const AsynchronousStmt &x) { // R831
617 Word("ASYNCHRONOUS :: "), Walk(x.v, ", ");
619 void Unparse(const BindStmt &x) { // R832
620 Walk(x.t, " :: ");
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);
627 void Unparse(const CodimensionStmt &x) { // R834
628 Word("CODIMENSION :: "), Walk(x.v, ", ");
630 void Unparse(const CodimensionDecl &x) { // R835
631 Walk(std::get<Name>(x.t));
632 Put('['), Walk(std::get<CoarraySpec>(x.t)), Put(']');
634 void Unparse(const ContiguousStmt &x) { // R836
635 Word("CONTIGUOUS :: "), Walk(x.v, ", ");
637 void Unparse(const DataStmt &x) { // R837
638 Word("DATA "), Walk(x.v, ", ");
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('/');
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(')');
649 void Unparse(const DataStmtValue &x) { // R843
650 Walk(std::get<std::optional<DataStmtRepeat>>(x.t), "*");
651 Walk(std::get<DataStmtConstant>(x.t));
653 void Unparse(const DimensionStmt &x) { // R848
654 Word("DIMENSION :: "), Walk(x.v, ", ");
656 void Unparse(const DimensionStmt::Declaration &x) {
657 Walk(std::get<Name>(x.t));
658 Put('('), Walk(std::get<ArraySpec>(x.t)), Put(')');
660 void Unparse(const IntentStmt &x) { // R849
661 Walk(x.t, " :: ");
663 void Unparse(const OptionalStmt &x) { // R850
664 Word("OPTIONAL :: "), Walk(x.v, ", ");
666 void Unparse(const ParameterStmt &x) { // R851
667 Word("PARAMETER("), Walk(x.v, ", "), Put(')');
669 void Unparse(const NamedConstantDef &x) { // R852
670 Walk(x.t, "=");
672 void Unparse(const PointerStmt &x) { // R853
673 Word("POINTER :: "), Walk(x.v, ", ");
675 void Unparse(const PointerDecl &x) { // R854
676 Walk(std::get<Name>(x.t));
677 Walk("(", std::get<std::optional<DeferredShapeSpecList>>(x.t), ")");
679 void Unparse(const ProtectedStmt &x) { // R855
680 Word("PROTECTED :: "), Walk(x.v, ", ");
682 void Unparse(const SaveStmt &x) { // R856
683 Word("SAVE"), Walk(" :: ", x.v, ", ");
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);
691 void Unparse(const TargetStmt &x) { // R859
692 Word("TARGET :: "), Walk(x.v, ", ");
694 void Unparse(const ValueStmt &x) { // R861
695 Word("VALUE :: "), Walk(x.v, ", ");
697 void Unparse(const VolatileStmt &x) { // R862
698 Word("VOLATILE :: "), Walk(x.v, ", ");
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, ", ", ")");
709 x.u);
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(')');
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);
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;
740 void Unparse(const NamelistStmt &x) { // R868
741 Word("NAMELIST"), Walk(x.v, ", ");
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), ", ");
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 = ", ";
755 void Unparse(const CommonStmt &x) { // R873
756 Word("COMMON ");
757 Walk(x.blocks);
759 void Unparse(const CommonBlockObject &x) { // R874
760 Walk(std::get<Name>(x.t));
761 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")");
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));
768 void Unparse(const Substring &x) { // R908, R909
769 Walk(std::get<DataRef>(x.t));
770 Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')');
772 void Unparse(const CharLiteralConstantSubstring &x) {
773 Walk(std::get<CharLiteralConstant>(x.t));
774 Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')');
776 void Unparse(const SubstringInquiry &x) {
777 Walk(x.v);
778 Put(x.source.end()[-1] == 'n' ? "%LEN" : "%KIND");
780 void Unparse(const SubstringRange &x) { // R910
781 Walk(x.t, ":");
783 void Unparse(const PartRef &x) { // R912
784 Walk(x.name);
785 Walk("(", x.subscripts, ",", ")");
786 Walk(x.imageSelector);
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('%');
796 Walk(x.component);
798 void Unparse(const ArrayElement &x) { // R917
799 Walk(x.base);
800 Put('('), Walk(x.subscripts, ","), Put(')');
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));
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(']');
810 void Before(const ImageSelectorSpec::Stat &) { // R926
811 Word("STAT=");
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=");
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(')');
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 &) {},
833 x.u);
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), "]");
840 void Unparse(const AllocateShapeSpec &x) { // R934 & R938
841 Walk(std::get<std::optional<BoundExpr>>(x.t), ":");
842 Walk(std::get<BoundExpr>(x.t));
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('*');
848 void Unparse(const NullifyStmt &x) { // R939
849 Word("NULLIFY("), Walk(x.v, ", "), Put(')');
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(')');
856 void Before(const StatOrErrmsg &x) { // R942 & R1165
857 common::visit(common::visitors{
858 [&](const StatVariable &) { Word("STAT="); },
859 [&](const MsgVariable &) { Word("ERRMSG="); },
861 x.u);
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(')');
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(')');
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
896 void Unparse(const DefinedOpName &x) { // R1003, R1023, R1414, & R1415
897 Walk(x.v);
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, " = ");
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(')');
920 [&](const std::list<BoundsSpec> &y) { Walk("(", y, ", ", ")"); },
922 std::get<PointerAssignmentStmt::Bounds>(x.t).u);
923 Put(" => "), Walk(std::get<Expr>(x.t));
926 void Post(const BoundsSpec &) { // R1035
927 Put(':');
929 void Unparse(const BoundsRemapping &x) { // R1036
930 Walk(x.t, ":");
932 void Unparse(const WhereStmt &x) { // R1041, R1045, R1046
933 Word("WHERE ("), Walk(x.t, ") ");
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();
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();
946 void Unparse(const ElsewhereStmt &x) { // R1048
947 Outdent(), Word("ELSEWHERE"), Walk(" ", x.v), Indent();
949 void Unparse(const EndWhereStmt &x) { // R1049
950 Outdent(), Word("END WHERE"), Walk(" ", x.v);
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();
957 void Unparse(const EndForallStmt &x) { // R1054
958 Outdent(), Word("END FORALL"), Walk(" ", x.v);
960 void Before(const ForallStmt &) { // R1055
961 Word("FORALL");
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();
969 void Unparse(const Association &x) { // R1104
970 Walk(x.t, " => ");
972 void Unparse(const EndAssociateStmt &x) { // R1106
973 Outdent(), Word("END ASSOCIATE"), Walk(" ", x.v);
975 void Unparse(const BlockStmt &x) { // R1108
976 Walk(x.v, ": "), Word("BLOCK"), Indent();
978 void Unparse(const EndBlockStmt &x) { // R1110
979 Outdent(), Word("END BLOCK"), Walk(" ", x.v);
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();
988 void Unparse(const CoarrayAssociation &x) { // R1113
989 Walk(x.t, " => ");
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));
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();
1001 void Unparse(const EndCriticalStmt &x) { // R1118
1002 Outdent(), Word("END CRITICAL"), Walk(" ", x.v);
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));
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));
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));
1019 void Unparse(const LoopControl &x) { // R1123
1020 common::visit(common::visitors{
1021 [&](const ScalarLogicalExpr &y) {
1022 Word("WHILE ("), Walk(y), Put(')');
1024 [&](const auto &y) { Walk(y); },
1026 x.u);
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(')');
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));
1038 void Before(const LoopControl::Concurrent &) { // R1129
1039 Word("CONCURRENT");
1041 void Unparse(const LocalitySpec::Local &x) {
1042 Word("LOCAL("), Walk(x.v, ", "), Put(')');
1044 void Unparse(const LocalitySpec::LocalInit &x) {
1045 Word("LOCAL_INIT("), Walk(x.v, ", "), Put(')');
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), ",", ")");
1051 void Unparse(const LocalitySpec::Shared &x) {
1052 Word("SHARED("), Walk(x.v, ", "), Put(')');
1054 void Post(const LocalitySpec::DefaultNone &) { Word("DEFAULT(NONE)"); }
1055 void Unparse(const EndDoStmt &x) { // R1132
1056 Word("END DO"), Walk(" ", x.v);
1058 void Unparse(const CycleStmt &x) { // R1133
1059 Word("CYCLE"), Walk(" ", x.v);
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();
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();
1071 void Unparse(const ElseStmt &x) { // R1137
1072 Outdent(), Word("ELSE"), Walk(" ", x.v), Indent();
1074 void Unparse(const EndIfStmt &x) { // R1138
1075 Outdent(), Word("END IF"), Walk(" ", x.v);
1077 void Unparse(const IfStmt &x) { // R1139
1078 Word("IF ("), Walk(x.t, ") ");
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();
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();
1089 void Unparse(const EndSelectStmt &x) { // R1143 & R1151 & R1155
1090 Outdent(), Word("END SELECT"), Walk(" ", x.v);
1092 void Unparse(const CaseSelector &x) { // R1145
1093 common::visit(common::visitors{
1094 [&](const std::list<CaseValueRange> &y) {
1095 Put('('), Walk(y), Put(')');
1097 [&](const Default &) { Word("DEFAULT"); },
1099 x.u);
1101 void Unparse(const CaseValueRange::Range &x) { // R1146
1102 Walk(x.lower), Put(':'), Walk(x.upper);
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();
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(')');
1115 [&](const Star &) { Put("(*)"); },
1116 [&](const Default &) { Word("DEFAULT"); },
1118 std::get<SelectRankCaseStmt::Rank>(x.t).u);
1119 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
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();
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();
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(')');
1137 [&](const Default &) { Word("CLASS DEFAULT"); },
1139 x.u);
1141 void Unparse(const ExitStmt &x) { // R1156
1142 Word("EXIT"), Walk(" ", x.v);
1144 void Before(const GotoStmt &) { // R1157
1145 Word("GO TO ");
1147 void Unparse(const ComputedGotoStmt &x) { // R1158
1148 Word("GO TO ("), Walk(x.t, "), ");
1150 void Unparse(const ContinueStmt &) { // R1159
1151 Word("CONTINUE");
1153 void Unparse(const StopStmt &x) { // R1160, R1161
1154 if (std::get<StopStmt::Kind>(x.t) == StopStmt::Kind::ErrorStop) {
1155 Word("ERROR ");
1157 Word("STOP"), Walk(" ", std::get<std::optional<StopCode>>(x.t));
1158 Walk(", QUIET=", std::get<std::optional<ScalarLogicalExpr>>(x.t));
1160 void Unparse(const FailImageStmt &) { // R1163
1161 Word("FAIL IMAGE");
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(')');
1168 void Unparse(const SyncAllStmt &x) { // R1164
1169 Word("SYNC ALL ("), Walk(x.v, ", "), Put(')');
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(')');
1176 void Unparse(const SyncMemoryStmt &x) { // R1168
1177 Word("SYNC MEMORY ("), Walk(x.v, ", "), Put(')');
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(')');
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(')');
1187 void Before(const EventWaitSpec &x) { // R1173, R1174
1188 common::visit(common::visitors{
1189 [&](const ScalarIntExpr &) { Word("UNTIL_COUNT="); },
1190 [](const StatOrErrmsg &) {},
1192 x.u);
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(')');
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(')');
1205 void Before(const FormTeamStmt::FormTeamSpec &x) { // R1176, R1178
1206 common::visit(common::visitors{
1207 [&](const ScalarIntExpr &) { Word("NEW_INDEX="); },
1208 [](const StatOrErrmsg &) {},
1210 x.u);
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(')');
1217 void Before(const LockStmt::LockStat &x) { // R1180
1218 common::visit(
1219 common::visitors{
1220 [&](const ScalarLogicalVariable &) { Word("ACQUIRED_LOCK="); },
1221 [](const StatOrErrmsg &) {},
1223 x.u);
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(')');
1231 void Unparse(const OpenStmt &x) { // R1204
1232 Word("OPEN ("), Walk(x.v, ", "), Put(')');
1234 bool Pre(const ConnectSpec &x) { // R1205
1235 return common::visit(common::visitors{
1236 [&](const FileUnitNumber &) {
1237 Word("UNIT=");
1238 return true;
1240 [&](const FileNameExpr &) {
1241 Word("FILE=");
1242 return true;
1244 [&](const ConnectSpec::CharExpr &y) {
1245 Walk(y.t, "=");
1246 return false;
1248 [&](const MsgVariable &) {
1249 Word("IOMSG=");
1250 return true;
1252 [&](const StatVariable &) {
1253 Word("IOSTAT=");
1254 return true;
1256 [&](const ConnectSpec::Recl &) {
1257 Word("RECL=");
1258 return true;
1260 [&](const ConnectSpec::Newunit &) {
1261 Word("NEWUNIT=");
1262 return true;
1264 [&](const ErrLabel &) {
1265 Word("ERR=");
1266 return true;
1268 [&](const StatusExpr &) {
1269 Word("STATUS=");
1270 return true;
1273 x.u);
1275 void Unparse(const CloseStmt &x) { // R1208
1276 Word("CLOSE ("), Walk(x.v, ", "), Put(')');
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="); },
1286 x.u);
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);
1295 Walk(", ", x.controls, ", ");
1296 Put(')');
1297 } else if (x.format) {
1298 Walk(x.format);
1299 if (!x.items.empty()) {
1300 Put(", ");
1302 } else {
1303 Put('('), Walk(x.controls, ", "), Put(')');
1305 Walk(" ", x.items, ", ");
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);
1314 Walk(", ", x.controls, ", ");
1315 } else {
1316 Walk(x.controls, ", ");
1318 Put(')'), Walk(" ", x.items, ", ");
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), ", ");
1324 bool Pre(const IoControlSpec &x) { // R1213
1325 return common::visit(common::visitors{
1326 [&](const IoUnit &) {
1327 Word("UNIT=");
1328 return true;
1330 [&](const Format &) {
1331 Word("FMT=");
1332 return true;
1334 [&](const Name &) {
1335 Word("NML=");
1336 return true;
1338 [&](const IoControlSpec::CharExpr &y) {
1339 Walk(y.t, "=");
1340 return false;
1342 [&](const IoControlSpec::Asynchronous &) {
1343 Word("ASYNCHRONOUS=");
1344 return true;
1346 [&](const EndLabel &) {
1347 Word("END=");
1348 return true;
1350 [&](const EorLabel &) {
1351 Word("EOR=");
1352 return true;
1354 [&](const ErrLabel &) {
1355 Word("ERR=");
1356 return true;
1358 [&](const IdVariable &) {
1359 Word("ID=");
1360 return true;
1362 [&](const MsgVariable &) {
1363 Word("IOMSG=");
1364 return true;
1366 [&](const StatVariable &) {
1367 Word("IOSTAT=");
1368 return true;
1370 [&](const IoControlSpec::Pos &) {
1371 Word("POS=");
1372 return true;
1374 [&](const IoControlSpec::Rec &) {
1375 Word("REC=");
1376 return true;
1378 [&](const IoControlSpec::Size &) {
1379 Word("SIZE=");
1380 return true;
1383 x.u);
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(')');
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(')');
1393 void Unparse(const WaitStmt &x) { // R1222
1394 Word("WAIT ("), Walk(x.v, ", "), Put(')');
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="); },
1406 x.u);
1408 void Unparse(const BackspaceStmt &x) { // R1224
1409 Word("BACKSPACE ("), Walk(x.v, ", "), Put(')');
1411 void Unparse(const EndfileStmt &x) { // R1225
1412 Word("ENDFILE ("), Walk(x.v, ", "), Put(')');
1414 void Unparse(const RewindStmt &x) { // R1226
1415 Word("REWIND ("), Walk(x.v, ", "), Put(')');
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="); },
1424 x.u);
1426 void Unparse(const FlushStmt &x) { // R1228
1427 Word("FLUSH ("), Walk(x.v, ", "), Put(')');
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, ") ");
1436 [&](const std::list<InquireSpec> &y) { Walk(y, ", "), Put(')'); },
1438 x.u);
1440 bool Pre(const InquireSpec &x) { // R1231
1441 return common::visit(common::visitors{
1442 [&](const FileUnitNumber &) {
1443 Word("UNIT=");
1444 return true;
1446 [&](const FileNameExpr &) {
1447 Word("FILE=");
1448 return true;
1450 [&](const InquireSpec::CharVar &y) {
1451 Walk(y.t, "=");
1452 return false;
1454 [&](const InquireSpec::IntVar &y) {
1455 Walk(y.t, "=");
1456 return false;
1458 [&](const InquireSpec::LogVar &y) {
1459 Walk(y.t, "=");
1460 return false;
1462 [&](const IdExpr &) {
1463 Word("ID=");
1464 return true;
1466 [&](const ErrLabel &) {
1467 Word("ERR=");
1468 return true;
1471 x.u);
1474 void Before(const FormatStmt &) { // R1301
1475 Word("FORMAT");
1477 void Unparse(const format::FormatSpecification &x) { // R1302, R1303, R1305
1478 Put('('), Walk("", x.items, ",", x.unlimitedItems.empty() ? "" : ",");
1479 Walk("*(", x.unlimitedItems, ",", ")"), Put(')');
1481 void Unparse(const format::FormatItem &x) { // R1304, R1306, R1321
1482 if (x.repeatCount) {
1483 Walk(*x.repeatCount);
1485 common::visit(common::visitors{
1486 [&](const std::string &y) { PutNormalized(y); },
1487 [&](const std::list<format::FormatItem> &y) {
1488 Walk("(", y, ",", ")");
1490 [&](const auto &y) { Walk(y); },
1492 x.u);
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
1516 Walk(x.width), Walk(".", x.digits), Walk("E", x.exponentWidth);
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('"');
1523 Walk("(", x.parameters, ",", ")");
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);
1543 Word("X");
1544 break;
1545 case format::ControlEditDesc::Kind::Slash:
1546 if (x.count != 1) {
1547 Walk(x.count);
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;
1585 void Before(const MainProgram &x) { // R1401
1586 if (!std::get<std::optional<Statement<ProgramStmt>>>(x.t)) {
1587 Indent();
1590 void Before(const ProgramStmt &) { // R1402
1591 Word("PROGRAM "), Indent();
1593 void Unparse(const EndProgramStmt &x) { // R1403
1594 EndSubprogram("PROGRAM", x.v);
1596 void Before(const ModuleStmt &) { // R1405
1597 Word("MODULE "), Indent();
1599 void Unparse(const EndModuleStmt &x) { // R1406
1600 EndSubprogram("MODULE", x.v);
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, ", "); },
1609 x.u);
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(")");
1619 x.u);
1621 void Unparse(const SubmoduleStmt &x) { // R1417
1622 Word("SUBMODULE ("), WalkTupleElements(x.t, ")"), Indent();
1624 void Unparse(const ParentIdentifier &x) { // R1418
1625 Walk(std::get<Name>(x.t)), Walk(":", std::get<std::optional<Name>>(x.t));
1627 void Unparse(const EndSubmoduleStmt &x) { // R1419
1628 EndSubprogram("SUBMODULE", x.v);
1630 void Unparse(const BlockDataStmt &x) { // R1421
1631 Word("BLOCK DATA"), Walk(" ", x.v), Indent();
1633 void Unparse(const EndBlockDataStmt &x) { // R1422
1634 EndSubprogram("BLOCK DATA", x.v);
1637 void Unparse(const InterfaceStmt &x) { // R1503
1638 common::visit(common::visitors{
1639 [&](const std::optional<GenericSpec> &y) {
1640 Word("INTERFACE"), Walk(" ", y);
1642 [&](const Abstract &) { Word("ABSTRACT INTERFACE"); },
1644 x.u);
1645 Indent();
1647 void Unparse(const EndInterfaceStmt &x) { // R1504
1648 Outdent(), Word("END INTERFACE"), Walk(" ", x.v);
1650 void Unparse(const ProcedureStmt &x) { // R1506
1651 if (std::get<ProcedureStmt::Kind>(x.t) ==
1652 ProcedureStmt::Kind::ModuleProcedure) {
1653 Word("MODULE ");
1655 Word("PROCEDURE :: ");
1656 Walk(std::get<std::list<Name>>(x.t), ", ");
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)");
1666 [&](const GenericSpec::ReadUnformatted &) {
1667 Word("READ(UNFORMATTED)");
1669 [&](const GenericSpec::WriteFormatted &) {
1670 Word("WRITE(FORMATTED)");
1672 [&](const GenericSpec::WriteUnformatted &) {
1673 Word("WRITE(UNFORMATTED)");
1675 [](const auto &) {},
1677 x.u);
1679 void Post(const GenericSpec &x) {
1680 common::visit(common::visitors{
1681 [&](const DefinedOperator &) { Put(')'); },
1682 [](const auto &) {},
1684 x.u);
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), ", ");
1691 void Unparse(const ExternalStmt &x) { // R1511
1692 Word("EXTERNAL :: "), Walk(x.v, ", ");
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), ", ");
1699 void Unparse(const ProcDecl &x) { // R1515
1700 Walk(std::get<Name>(x.t));
1701 Walk(" => ", std::get<std::optional<ProcPointerInit>>(x.t));
1703 void Unparse(const IntrinsicStmt &x) { // R1519
1704 Word("INTRINSIC :: "), Walk(x.v, ", ");
1706 void Unparse(const CallStmt::StarOrExpr &x) {
1707 if (x.v) {
1708 Walk(*x.v);
1709 } else {
1710 Word("*");
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
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(')');
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
1737 } else {
1738 Walk("(", args, ", ", ")");
1742 void Unparse(const ActualArgSpec &x) { // R1523
1743 Walk(std::get<std::optional<Keyword>>(x.t), "=");
1744 Walk(std::get<ActualArg>(x.t));
1746 void Unparse(const ActualArg::PercentRef &x) { // R1524
1747 Word("%REF("), Walk(x.v), Put(')');
1749 void Unparse(const ActualArg::PercentVal &x) {
1750 Word("%VAL("), Walk(x.v), Put(')');
1752 void Before(const AltReturnSpec &) { // R1525
1753 Put('*');
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(")");
1764 void Unparse(const PrefixSpec::Launch_Bounds &x) {
1765 Word("LAUNCH_BOUNDS("), Walk(x.v), Word(")");
1767 void Unparse(const PrefixSpec::Cluster_Dims &x) {
1768 Word("CLUSTER_DIMS("), Walk(x.v), Word(")");
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();
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);
1784 void Unparse(const EndFunctionStmt &x) { // R1533
1785 EndSubprogram("FUNCTION", x.v);
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);
1798 Indent();
1800 void Unparse(const EndSubroutineStmt &x) { // R1537
1801 EndSubprogram("SUBROUTINE", x.v);
1803 void Before(const MpSubprogramStmt &) { // R1539
1804 Word("MODULE PROCEDURE "), Indent();
1806 void Unparse(const EndMpSubprogramStmt &x) { // R1540
1807 EndSubprogram("PROCEDURE", x.v);
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));
1814 void Unparse(const ReturnStmt &x) { // R1542
1815 Word("RETURN"), Walk(" ", x.v);
1817 void Unparse(const ContainsStmt &) { // R1543
1818 Outdent();
1819 Word("CONTAINS");
1820 Indent();
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));
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, ", ");
1836 [&](const CompilerDirective::LoopCount &lcount) {
1837 Walk("!DIR$ LOOP COUNT (", lcount.v, ", ", ")");
1839 [&](const std::list<CompilerDirective::AssumeAligned>
1840 &assumeAligned) {
1841 Word("!DIR$ ASSUME_ALIGNED ");
1842 Walk(" ", assumeAligned, ", ");
1844 [&](const CompilerDirective::VectorAlways &valways) {
1845 Word("!DIR$ VECTOR ALWAYS");
1847 [&](const std::list<CompilerDirective::NameValue> &names) {
1848 Walk("!DIR$ ", names, " ");
1850 [&](const CompilerDirective::Unrecognized &) {
1851 Word("!DIR$ ");
1852 Word(x.source.ToString());
1855 x.u);
1856 Put('\n');
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);
1865 Put(") ");
1867 Walk(std::get<Name>(x.t));
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));
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));
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();
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();
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();
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();
1922 void Unparse(const llvm::acc::Directive &x) {
1923 Word(llvm::acc::getOpenACCDirectiveName(x).str());
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));
1931 void Unparse(const AccBindClause &x) {
1932 common::visit(common::visitors{
1933 [&](const Name &y) { Walk(y); },
1934 [&](const ScalarDefaultCharExpr &y) { Walk(y); },
1936 x.u);
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;
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("*");
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 &) {},
1961 x.u);
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:");
1969 Walk(collapseValue);
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();
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));
1992 void Unparse(const AccBeginLoopDirective &x) {
1993 Walk(std::get<AccLoopDirective>(x.t));
1994 Walk(std::get<AccClauseList>(x.t));
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();
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();
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();
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();
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("/"); },
2037 x.u);
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));
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();
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), ",");
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();
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("/"); },
2075 x.u);
2077 void Unparse(const OmpIteratorSpecifier &x) {
2078 Walk(std::get<TypeDeclarationStmt>(x.t));
2079 Put(" = ");
2080 Walk(std::get<SubscriptTriplet>(x.t));
2082 void Unparse(const OmpIteratorModifier &x) {
2083 Word("ITERATOR(");
2084 Walk(x.v);
2085 Put(")");
2087 void Unparse(const OmpLastprivateClause &x) {
2088 Walk(
2089 std::get<std::optional<OmpLastprivateClause::LastprivateModifier>>(x.t),
2090 ":");
2091 Walk(std::get<OmpObjectList>(x.t));
2093 void Unparse(const OmpMapClause &x) {
2094 auto &typeMod =
2095 std::get<std::optional<std::list<OmpMapClause::TypeModifier>>>(x.t);
2096 auto &iter = std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t);
2097 auto &type = std::get<std::optional<std::list<OmpMapClause::Type>>>(x.t);
2098 auto &mapper = std::get<OmpMapperIdentifier>(x.t);
2100 // For a given list of items, if the item has a value, then walk it.
2101 // Print commas between items that have values.
2102 // Return 'true' if something did get printed, otherwise 'false'.
2103 bool needComma{false};
2104 if (mapper.v) {
2105 Word("MAPPER(");
2106 Walk(*mapper.v);
2107 Put(")");
2108 needComma = true;
2110 if (typeMod) {
2111 if (needComma) {
2112 Put(", ");
2114 Walk(*typeMod);
2115 needComma = true;
2117 if (iter) {
2118 if (needComma) {
2119 Put(", ");
2121 Walk(*iter);
2122 needComma = true;
2124 if (type) {
2125 if (needComma) {
2126 Put(", ");
2128 Walk(*type);
2129 needComma = true;
2131 if (needComma) {
2132 Put(": ");
2134 Walk(std::get<OmpObjectList>(x.t));
2136 void Unparse(const OmpScheduleModifier &x) {
2137 Walk(std::get<OmpScheduleModifier::Modifier1>(x.t));
2138 Walk(",", std::get<std::optional<OmpScheduleModifier::Modifier2>>(x.t));
2140 void Unparse(const OmpScheduleClause &x) {
2141 Walk(std::get<std::optional<OmpScheduleModifier>>(x.t), ":");
2142 Walk(std::get<OmpScheduleClause::ScheduleType>(x.t));
2143 Walk(",", std::get<std::optional<ScalarIntExpr>>(x.t));
2145 void Unparse(const OmpDeviceClause &x) {
2146 Walk(std::get<std::optional<OmpDeviceClause::DeviceModifier>>(x.t), ":");
2147 Walk(std::get<ScalarIntExpr>(x.t));
2149 void Unparse(const OmpAffinityClause &x) {
2150 Walk(std::get<std::optional<OmpIteratorModifier>>(x.t), ":");
2151 Walk(std::get<OmpObjectList>(x.t));
2153 void Unparse(const OmpAlignedClause &x) {
2154 Walk(std::get<OmpObjectList>(x.t));
2155 Put(",");
2156 Walk(std::get<std::optional<ScalarIntConstantExpr>>(x.t));
2158 void Unparse(const OmpFromClause &x) {
2159 auto &expect{
2160 std::get<std::optional<std::list<OmpFromClause::Expectation>>>(x.t)};
2161 auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
2162 bool needComma{false};
2163 if (expect) {
2164 Walk(*expect);
2165 needComma = true;
2167 if (iter) {
2168 if (needComma) {
2169 Put(", ");
2171 Walk(*iter);
2172 needComma = true;
2174 if (needComma) {
2175 Put(": ");
2177 Walk(std::get<OmpObjectList>(x.t));
2179 void Unparse(const OmpIfClause &x) {
2180 Walk(std::get<std::optional<OmpIfClause::DirectiveNameModifier>>(x.t), ":");
2181 Walk(std::get<ScalarLogicalExpr>(x.t));
2183 void Unparse(const OmpLinearClause::WithoutModifier &x) {
2184 Walk(x.names, ", ");
2185 Walk(":", x.step);
2187 void Unparse(const OmpLinearClause::WithModifier &x) {
2188 Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")");
2189 Walk(":", x.step);
2191 void Unparse(const OmpReductionClause &x) {
2192 Walk(std::get<std::optional<OmpReductionClause::ReductionModifier>>(x.t),
2193 ",");
2194 Walk(std::get<OmpReductionOperator>(x.t));
2195 Put(":");
2196 Walk(std::get<OmpObjectList>(x.t));
2198 void Unparse(const OmpDetachClause &x) { Walk(x.v); }
2199 void Unparse(const OmpInReductionClause &x) {
2200 Walk(std::get<OmpReductionOperator>(x.t));
2201 Put(":");
2202 Walk(std::get<OmpObjectList>(x.t));
2204 void Unparse(const OmpAllocateClause &x) {
2205 Walk(
2206 std::get<std::optional<OmpAllocateClause::AllocateModifier>>(x.t), ":");
2207 Walk(std::get<OmpObjectList>(x.t));
2209 void Unparse(const OmpAllocateClause::AllocateModifier &x) {
2210 common::visit(
2211 common::visitors{
2212 [&](const OmpAllocateClause::AllocateModifier::Allocator &y) {
2213 Walk(y);
2215 [&](const OmpAllocateClause::AllocateModifier::ComplexModifier &y) {
2216 Word("ALLOCATOR(");
2217 Walk(std::get<OmpAllocateClause::AllocateModifier::Allocator>(
2218 y.t));
2219 Put(")");
2220 Put(",");
2221 Walk(std::get<OmpAllocateClause::AllocateModifier::Align>(y.t));
2223 [&](const OmpAllocateClause::AllocateModifier::Align &y) {
2224 Walk(y);
2227 x.u);
2229 void Unparse(const OmpAllocateClause::AllocateModifier::Align &x) {
2230 Word("ALIGN(");
2231 Walk(x.v);
2232 Put(")");
2234 void Unparse(const OmpOrderClause &x) {
2235 Walk(std::get<std::optional<OmpOrderModifier>>(x.t), ":");
2236 Walk(std::get<OmpOrderClause::Type>(x.t));
2238 void Unparse(const OmpGrainsizeClause &x) {
2239 Walk(std::get<std::optional<OmpGrainsizeClause::Prescriptiveness>>(x.t),
2240 ":");
2241 Walk(std::get<ScalarIntExpr>(x.t));
2243 void Unparse(const OmpNumTasksClause &x) {
2244 Walk(
2245 std::get<std::optional<OmpNumTasksClause::Prescriptiveness>>(x.t), ":");
2246 Walk(std::get<ScalarIntExpr>(x.t));
2248 void Unparse(const OmpDoacross::Sink &x) {
2249 Word("SINK: ");
2250 Walk(x.v.v);
2252 void Unparse(const OmpDoacross::Source &) { Word("SOURCE"); }
2253 void Unparse(const OmpDependClause::TaskDep &x) {
2254 Walk(std::get<OmpTaskDependenceType>(x.t));
2255 Put(":");
2256 Walk(std::get<OmpObjectList>(x.t));
2258 void Unparse(const OmpDefaultmapClause &x) {
2259 Walk(std::get<OmpDefaultmapClause::ImplicitBehavior>(x.t));
2260 Walk(":",
2261 std::get<std::optional<OmpDefaultmapClause::VariableCategory>>(x.t));
2263 void Unparse(const OmpToClause &x) {
2264 auto &expect{
2265 std::get<std::optional<std::list<OmpToClause::Expectation>>>(x.t)};
2266 auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
2267 bool needComma{false};
2268 if (expect) {
2269 Walk(*expect);
2270 needComma = true;
2272 if (iter) {
2273 if (needComma) {
2274 Put(", ");
2276 Walk(*iter);
2277 needComma = true;
2279 if (needComma) {
2280 Put(": ");
2282 Walk(std::get<OmpObjectList>(x.t));
2284 #define GEN_FLANG_CLAUSE_UNPARSE
2285 #include "llvm/Frontend/OpenMP/OMP.inc"
2286 void Unparse(const OmpLoopDirective &x) {
2287 switch (x.v) {
2288 case llvm::omp::Directive::OMPD_distribute:
2289 Word("DISTRIBUTE ");
2290 break;
2291 case llvm::omp::Directive::OMPD_distribute_parallel_do:
2292 Word("DISTRIBUTE PARALLEL DO ");
2293 break;
2294 case llvm::omp::Directive::OMPD_distribute_parallel_do_simd:
2295 Word("DISTRIBUTE PARALLEL DO SIMD ");
2296 break;
2297 case llvm::omp::Directive::OMPD_distribute_simd:
2298 Word("DISTRIBUTE SIMD ");
2299 break;
2300 case llvm::omp::Directive::OMPD_do:
2301 Word("DO ");
2302 break;
2303 case llvm::omp::Directive::OMPD_do_simd:
2304 Word("DO SIMD ");
2305 break;
2306 case llvm::omp::Directive::OMPD_loop:
2307 Word("LOOP ");
2308 break;
2309 case llvm::omp::Directive::OMPD_masked_taskloop_simd:
2310 Word("MASKED TASKLOOP SIMD");
2311 break;
2312 case llvm::omp::Directive::OMPD_masked_taskloop:
2313 Word("MASKED TASKLOOP");
2314 break;
2315 case llvm::omp::Directive::OMPD_master_taskloop_simd:
2316 Word("MASTER TASKLOOP SIMD");
2317 break;
2318 case llvm::omp::Directive::OMPD_master_taskloop:
2319 Word("MASTER TASKLOOP");
2320 break;
2321 case llvm::omp::Directive::OMPD_parallel_do:
2322 Word("PARALLEL DO ");
2323 break;
2324 case llvm::omp::Directive::OMPD_parallel_do_simd:
2325 Word("PARALLEL DO SIMD ");
2326 break;
2327 case llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd:
2328 Word("PARALLEL MASKED TASKLOOP SIMD");
2329 break;
2330 case llvm::omp::Directive::OMPD_parallel_masked_taskloop:
2331 Word("PARALLEL MASKED TASKLOOP");
2332 break;
2333 case llvm::omp::Directive::OMPD_parallel_master_taskloop_simd:
2334 Word("PARALLEL MASTER TASKLOOP SIMD");
2335 break;
2336 case llvm::omp::Directive::OMPD_parallel_master_taskloop:
2337 Word("PARALLEL MASTER TASKLOOP");
2338 break;
2339 case llvm::omp::Directive::OMPD_simd:
2340 Word("SIMD ");
2341 break;
2342 case llvm::omp::Directive::OMPD_target_loop:
2343 Word("TARGET LOOP ");
2344 break;
2345 case llvm::omp::Directive::OMPD_target_parallel_do:
2346 Word("TARGET PARALLEL DO ");
2347 break;
2348 case llvm::omp::Directive::OMPD_target_parallel_do_simd:
2349 Word("TARGET PARALLEL DO SIMD ");
2350 break;
2351 case llvm::omp::Directive::OMPD_target_parallel_loop:
2352 Word("TARGET PARALLEL LOOP ");
2353 break;
2354 case llvm::omp::Directive::OMPD_target_teams_distribute:
2355 Word("TARGET TEAMS DISTRIBUTE ");
2356 break;
2357 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
2358 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO ");
2359 break;
2360 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
2361 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2362 break;
2363 case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
2364 Word("TARGET TEAMS DISTRIBUTE SIMD ");
2365 break;
2366 case llvm::omp::Directive::OMPD_target_teams_loop:
2367 Word("TARGET TEAMS LOOP ");
2368 break;
2369 case llvm::omp::Directive::OMPD_target_simd:
2370 Word("TARGET SIMD ");
2371 break;
2372 case llvm::omp::Directive::OMPD_taskloop:
2373 Word("TASKLOOP ");
2374 break;
2375 case llvm::omp::Directive::OMPD_taskloop_simd:
2376 Word("TASKLOOP SIMD ");
2377 break;
2378 case llvm::omp::Directive::OMPD_teams_distribute:
2379 Word("TEAMS DISTRIBUTE ");
2380 break;
2381 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do:
2382 Word("TEAMS DISTRIBUTE PARALLEL DO ");
2383 break;
2384 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd:
2385 Word("TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2386 break;
2387 case llvm::omp::Directive::OMPD_teams_distribute_simd:
2388 Word("TEAMS DISTRIBUTE SIMD ");
2389 break;
2390 case llvm::omp::Directive::OMPD_tile:
2391 Word("TILE ");
2392 break;
2393 case llvm::omp::Directive::OMPD_unroll:
2394 Word("UNROLL ");
2395 break;
2396 default:
2397 break;
2400 void Unparse(const OmpObjectList &x) { Walk(x.v, ","); }
2401 void Unparse(const OmpSimpleStandaloneDirective &x) {
2402 switch (x.v) {
2403 case llvm::omp::Directive::OMPD_barrier:
2404 Word("BARRIER ");
2405 break;
2406 case llvm::omp::Directive::OMPD_scan:
2407 Word("SCAN ");
2408 break;
2409 case llvm::omp::Directive::OMPD_taskwait:
2410 Word("TASKWAIT ");
2411 break;
2412 case llvm::omp::Directive::OMPD_taskyield:
2413 Word("TASKYIELD ");
2414 break;
2415 case llvm::omp::Directive::OMPD_target_enter_data:
2416 Word("TARGET ENTER DATA ");
2417 break;
2418 case llvm::omp::Directive::OMPD_target_exit_data:
2419 Word("TARGET EXIT DATA ");
2420 break;
2421 case llvm::omp::Directive::OMPD_target_update:
2422 Word("TARGET UPDATE ");
2423 break;
2424 case llvm::omp::Directive::OMPD_ordered:
2425 Word("ORDERED ");
2426 break;
2427 default:
2428 // Nothing to be done
2429 break;
2432 void Unparse(const OmpBlockDirective &x) {
2433 switch (x.v) {
2434 case llvm::omp::Directive::OMPD_masked:
2435 Word("MASKED");
2436 break;
2437 case llvm::omp::Directive::OMPD_master:
2438 Word("MASTER");
2439 break;
2440 case llvm::omp::Directive::OMPD_ordered:
2441 Word("ORDERED ");
2442 break;
2443 case llvm::omp::Directive::OMPD_parallel_masked:
2444 Word("PARALLEL MASKED");
2445 break;
2446 case llvm::omp::Directive::OMPD_parallel_master:
2447 Word("PARALLEL MASTER");
2448 break;
2449 case llvm::omp::Directive::OMPD_parallel_workshare:
2450 Word("PARALLEL WORKSHARE ");
2451 break;
2452 case llvm::omp::Directive::OMPD_parallel:
2453 Word("PARALLEL ");
2454 break;
2455 case llvm::omp::Directive::OMPD_scope:
2456 Word("SCOPE ");
2457 break;
2458 case llvm::omp::Directive::OMPD_single:
2459 Word("SINGLE ");
2460 break;
2461 case llvm::omp::Directive::OMPD_target_data:
2462 Word("TARGET DATA ");
2463 break;
2464 case llvm::omp::Directive::OMPD_target_parallel:
2465 Word("TARGET PARALLEL ");
2466 break;
2467 case llvm::omp::Directive::OMPD_target_teams:
2468 Word("TARGET TEAMS ");
2469 break;
2470 case llvm::omp::Directive::OMPD_target:
2471 Word("TARGET ");
2472 break;
2473 case llvm::omp::Directive::OMPD_taskgroup:
2474 Word("TASKGROUP ");
2475 break;
2476 case llvm::omp::Directive::OMPD_task:
2477 Word("TASK ");
2478 break;
2479 case llvm::omp::Directive::OMPD_teams:
2480 Word("TEAMS ");
2481 break;
2482 case llvm::omp::Directive::OMPD_workshare:
2483 Word("WORKSHARE ");
2484 break;
2485 default:
2486 // Nothing to be done
2487 break;
2491 void Unparse(const OmpAtomicDefaultMemOrderClause &x) {
2492 Word(ToUpperCaseLetters(common::EnumToString(x.v)));
2495 void Unparse(const OmpAtomicClauseList &x) { Walk(" ", x.v, " "); }
2497 void Unparse(const OmpAtomic &x) {
2498 BeginOpenMP();
2499 Word("!$OMP ATOMIC");
2500 Walk(std::get<OmpAtomicClauseList>(x.t));
2501 Put("\n");
2502 EndOpenMP();
2503 Walk(std::get<Statement<AssignmentStmt>>(x.t));
2504 BeginOpenMP();
2505 Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
2506 EndOpenMP();
2508 void Unparse(const OmpAtomicCapture &x) {
2509 BeginOpenMP();
2510 Word("!$OMP ATOMIC");
2511 Walk(std::get<0>(x.t));
2512 Word(" CAPTURE");
2513 Walk(std::get<2>(x.t));
2514 Put("\n");
2515 EndOpenMP();
2516 Walk(std::get<OmpAtomicCapture::Stmt1>(x.t));
2517 Put("\n");
2518 Walk(std::get<OmpAtomicCapture::Stmt2>(x.t));
2519 BeginOpenMP();
2520 Word("!$OMP END ATOMIC\n");
2521 EndOpenMP();
2523 void Unparse(const OmpAtomicRead &x) {
2524 BeginOpenMP();
2525 Word("!$OMP ATOMIC");
2526 Walk(std::get<0>(x.t));
2527 Word(" READ");
2528 Walk(std::get<2>(x.t));
2529 Put("\n");
2530 EndOpenMP();
2531 Walk(std::get<Statement<AssignmentStmt>>(x.t));
2532 BeginOpenMP();
2533 Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
2534 EndOpenMP();
2536 void Unparse(const OmpAtomicUpdate &x) {
2537 BeginOpenMP();
2538 Word("!$OMP ATOMIC");
2539 Walk(std::get<0>(x.t));
2540 Word(" UPDATE");
2541 Walk(std::get<2>(x.t));
2542 Put("\n");
2543 EndOpenMP();
2544 Walk(std::get<Statement<AssignmentStmt>>(x.t));
2545 BeginOpenMP();
2546 Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
2547 EndOpenMP();
2549 void Unparse(const OmpAtomicWrite &x) {
2550 BeginOpenMP();
2551 Word("!$OMP ATOMIC");
2552 Walk(std::get<0>(x.t));
2553 Word(" WRITE");
2554 Walk(std::get<2>(x.t));
2555 Put("\n");
2556 EndOpenMP();
2557 Walk(std::get<Statement<AssignmentStmt>>(x.t));
2558 BeginOpenMP();
2559 Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
2560 EndOpenMP();
2562 void Unparse(const OpenMPExecutableAllocate &x) {
2563 const auto &fields =
2564 std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>(
2565 x.t);
2566 if (fields) {
2567 for (const auto &decl : *fields) {
2568 Walk(decl);
2571 BeginOpenMP();
2572 Word("!$OMP ALLOCATE");
2573 Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")");
2574 Walk(std::get<OmpClauseList>(x.t));
2575 Put("\n");
2576 EndOpenMP();
2577 Walk(std::get<Statement<AllocateStmt>>(x.t));
2579 void Unparse(const OpenMPDeclarativeAllocate &x) {
2580 BeginOpenMP();
2581 Word("!$OMP ALLOCATE");
2582 Put(" (");
2583 Walk(std::get<OmpObjectList>(x.t));
2584 Put(")");
2585 Walk(std::get<OmpClauseList>(x.t));
2586 Put("\n");
2587 EndOpenMP();
2589 void Unparse(const OmpEndAllocators &x) {
2590 BeginOpenMP();
2591 Word("!$OMP END ALLOCATE");
2592 Put("\n");
2593 EndOpenMP();
2595 void Unparse(const OpenMPAllocatorsConstruct &x) {
2596 BeginOpenMP();
2597 Word("!$OMP ALLOCATE");
2598 Walk(std::get<OmpClauseList>(x.t));
2599 Put("\n");
2600 EndOpenMP();
2601 Walk(std::get<Statement<AllocateStmt>>(x.t));
2602 if (const auto &end = std::get<std::optional<OmpEndAllocators>>(x.t)) {
2603 Walk(*end);
2606 void Unparse(const OmpCriticalDirective &x) {
2607 BeginOpenMP();
2608 Word("!$OMP CRITICAL");
2609 Walk(" (", std::get<std::optional<Name>>(x.t), ")");
2610 Walk(std::get<OmpClauseList>(x.t));
2611 Put("\n");
2612 EndOpenMP();
2614 void Unparse(const OmpEndCriticalDirective &x) {
2615 BeginOpenMP();
2616 Word("!$OMP END CRITICAL");
2617 Walk(" (", std::get<std::optional<Name>>(x.t), ")");
2618 Put("\n");
2619 EndOpenMP();
2621 void Unparse(const OpenMPCriticalConstruct &x) {
2622 Walk(std::get<OmpCriticalDirective>(x.t));
2623 Walk(std::get<Block>(x.t), "");
2624 Walk(std::get<OmpEndCriticalDirective>(x.t));
2626 void Unparse(const OmpDeclareTargetWithList &x) {
2627 Put("("), Walk(x.v), Put(")");
2629 void Unparse(const OmpReductionInitializerClause &x) {
2630 Word(" INITIALIZER(OMP_PRIV = ");
2631 Walk(x.v);
2632 Put(")");
2634 void Unparse(const OmpReductionCombiner::FunctionCombiner &x) {
2635 const auto &pd = std::get<ProcedureDesignator>(x.v.t);
2636 const auto &args = std::get<std::list<ActualArgSpec>>(x.v.t);
2637 Walk(pd);
2638 if (args.empty()) {
2639 if (std::holds_alternative<ProcComponentRef>(pd.u)) {
2640 Put("()");
2642 } else {
2643 Walk("(", args, ", ", ")");
2646 void Unparse(const OpenMPDeclareReductionConstruct &x) {
2647 Put("(");
2648 Walk(std::get<OmpReductionOperator>(x.t)), Put(" : ");
2649 Walk(std::get<std::list<DeclarationTypeSpec>>(x.t), ","), Put(" : ");
2650 Walk(std::get<OmpReductionCombiner>(x.t));
2651 Put(")");
2652 Walk(std::get<std::optional<OmpReductionInitializerClause>>(x.t));
2654 bool Pre(const OpenMPDeclarativeConstruct &x) {
2655 BeginOpenMP();
2656 Word("!$OMP ");
2657 return common::visit(
2658 common::visitors{
2659 [&](const OpenMPDeclarativeAllocate &z) {
2660 Word("ALLOCATE (");
2661 Walk(std::get<OmpObjectList>(z.t));
2662 Put(")");
2663 Walk(std::get<OmpClauseList>(z.t));
2664 Put("\n");
2665 EndOpenMP();
2666 return false;
2668 [&](const OpenMPDeclareMapperConstruct &z) {
2669 Word("DECLARE MAPPER (");
2670 const auto &spec{std::get<OmpDeclareMapperSpecifier>(z.t)};
2671 if (auto mapname{std::get<std::optional<Name>>(spec.t)}) {
2672 Walk(mapname);
2673 Put(":");
2675 Walk(std::get<TypeSpec>(spec.t));
2676 Put("::");
2677 Walk(std::get<Name>(spec.t));
2678 Put(")");
2680 Walk(std::get<OmpClauseList>(z.t));
2681 Put("\n");
2682 return false;
2684 [&](const OpenMPDeclareReductionConstruct &) {
2685 Word("DECLARE REDUCTION ");
2686 return true;
2688 [&](const OpenMPDeclareSimdConstruct &y) {
2689 Word("DECLARE SIMD ");
2690 Walk("(", std::get<std::optional<Name>>(y.t), ")");
2691 Walk(std::get<OmpClauseList>(y.t));
2692 Put("\n");
2693 EndOpenMP();
2694 return false;
2696 [&](const OpenMPDeclareTargetConstruct &) {
2697 Word("DECLARE TARGET ");
2698 return true;
2700 [&](const OpenMPRequiresConstruct &y) {
2701 Word("REQUIRES ");
2702 Walk(std::get<OmpClauseList>(y.t));
2703 Put("\n");
2704 EndOpenMP();
2705 return false;
2707 [&](const OpenMPThreadprivate &) {
2708 Word("THREADPRIVATE (");
2709 return true;
2712 x.u);
2714 void Post(const OpenMPDeclarativeConstruct &) {
2715 Put("\n");
2716 EndOpenMP();
2718 void Post(const OpenMPThreadprivate &) {
2719 Put(")\n");
2720 EndOpenMP();
2722 void Unparse(const OmpSectionsDirective &x) {
2723 switch (x.v) {
2724 case llvm::omp::Directive::OMPD_sections:
2725 Word("SECTIONS ");
2726 break;
2727 case llvm::omp::Directive::OMPD_parallel_sections:
2728 Word("PARALLEL SECTIONS ");
2729 break;
2730 default:
2731 break;
2734 void Unparse(const OmpSectionBlocks &x) {
2735 for (const auto &y : x.v) {
2736 BeginOpenMP();
2737 Word("!$OMP SECTION");
2738 Put("\n");
2739 EndOpenMP();
2740 // y.u is an OpenMPSectionConstruct
2741 // (y.u).v is Block
2742 Walk(std::get<OpenMPSectionConstruct>(y.u).v, "");
2745 void Unparse(const OpenMPSectionsConstruct &x) {
2746 BeginOpenMP();
2747 Word("!$OMP ");
2748 Walk(std::get<OmpBeginSectionsDirective>(x.t));
2749 Put("\n");
2750 EndOpenMP();
2751 Walk(std::get<OmpSectionBlocks>(x.t));
2752 BeginOpenMP();
2753 Word("!$OMP END ");
2754 Walk(std::get<OmpEndSectionsDirective>(x.t));
2755 Put("\n");
2756 EndOpenMP();
2758 void Unparse(const OpenMPCancellationPointConstruct &x) {
2759 BeginOpenMP();
2760 Word("!$OMP CANCELLATION POINT ");
2761 Walk(std::get<OmpCancelType>(x.t));
2762 Put("\n");
2763 EndOpenMP();
2765 void Unparse(const OpenMPCancelConstruct &x) {
2766 BeginOpenMP();
2767 Word("!$OMP CANCEL ");
2768 Walk(std::get<OmpCancelType>(x.t));
2769 Walk(std::get<std::optional<OpenMPCancelConstruct::If>>(x.t));
2770 Put("\n");
2771 EndOpenMP();
2773 void Unparse(const OmpMemoryOrderClause &x) { Walk(x.v); }
2774 void Unparse(const OmpAtomicClause &x) {
2775 common::visit(common::visitors{
2776 [&](const OmpMemoryOrderClause &y) { Walk(y); },
2777 [&](const OmpClause &z) { Walk(z); },
2779 x.u);
2781 void Unparse(const OpenMPDepobjConstruct &x) {
2782 BeginOpenMP();
2783 Word("!$OMP DEPOBJ");
2784 Put("(");
2785 Walk(std::get<OmpObject>(x.t));
2786 Put(") ");
2787 Walk(std::get<OmpClause>(x.t));
2788 Put("\n");
2789 EndOpenMP();
2791 void Unparse(const OpenMPFlushConstruct &x) {
2792 BeginOpenMP();
2793 Word("!$OMP FLUSH ");
2794 Walk(std::get<std::optional<std::list<OmpMemoryOrderClause>>>(x.t));
2795 Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")");
2796 Put("\n");
2797 EndOpenMP();
2799 void Unparse(const OmpEndLoopDirective &x) {
2800 BeginOpenMP();
2801 Word("!$OMP END ");
2802 Walk(std::get<OmpLoopDirective>(x.t));
2803 Walk(std::get<OmpClauseList>(x.t));
2804 Put("\n");
2805 EndOpenMP();
2807 void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); }
2808 void Unparse(const OpenMPSimpleStandaloneConstruct &x) {
2809 BeginOpenMP();
2810 Word("!$OMP ");
2811 Walk(std::get<OmpSimpleStandaloneDirective>(x.t));
2812 Walk(std::get<OmpClauseList>(x.t));
2813 Put("\n");
2814 EndOpenMP();
2816 void Unparse(const OpenMPBlockConstruct &x) {
2817 BeginOpenMP();
2818 Word("!$OMP ");
2819 Walk(std::get<OmpBeginBlockDirective>(x.t));
2820 Put("\n");
2821 EndOpenMP();
2822 Walk(std::get<Block>(x.t), "");
2823 BeginOpenMP();
2824 Word("!$OMP END ");
2825 Walk(std::get<OmpEndBlockDirective>(x.t));
2826 Put("\n");
2827 EndOpenMP();
2829 void Unparse(const OpenMPLoopConstruct &x) {
2830 BeginOpenMP();
2831 Word("!$OMP ");
2832 Walk(std::get<OmpBeginLoopDirective>(x.t));
2833 Put("\n");
2834 EndOpenMP();
2835 Walk(std::get<std::optional<DoConstruct>>(x.t));
2836 Walk(std::get<std::optional<OmpEndLoopDirective>>(x.t));
2838 void Unparse(const BasedPointer &x) {
2839 Put('('), Walk(std::get<0>(x.t)), Put(","), Walk(std::get<1>(x.t));
2840 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"), Put(')');
2842 void Unparse(const BasedPointerStmt &x) { Walk("POINTER ", x.v, ","); }
2843 void Unparse(const CUDAAttributesStmt &x) {
2844 Word("ATTRIBUTES("), Walk(std::get<common::CUDADataAttr>(x.t));
2845 Word(") "), Walk(std::get<std::list<Name>>(x.t), ", ");
2847 void Post(const StructureField &x) {
2848 if (const auto *def{std::get_if<Statement<DataComponentDefStmt>>(&x.u)}) {
2849 for (const auto &item :
2850 std::get<std::list<ComponentOrFill>>(def->statement.t)) {
2851 if (const auto *comp{std::get_if<ComponentDecl>(&item.u)}) {
2852 structureComponents_.insert(std::get<Name>(comp->t).source);
2857 void Unparse(const StructureStmt &x) {
2858 Word("STRUCTURE ");
2859 // The name, if present, includes the /slashes/
2860 Walk(std::get<std::optional<Name>>(x.t));
2861 Walk(" ", std::get<std::list<EntityDecl>>(x.t), ", ");
2862 Indent();
2864 void Post(const Union::UnionStmt &) { Word("UNION"), Indent(); }
2865 void Post(const Union::EndUnionStmt &) { Outdent(), Word("END UNION"); }
2866 void Post(const Map::MapStmt &) { Word("MAP"), Indent(); }
2867 void Post(const Map::EndMapStmt &) { Outdent(), Word("END MAP"); }
2868 void Post(const StructureDef::EndStructureStmt &) {
2869 Outdent(), Word("END STRUCTURE");
2871 void Unparse(const OldParameterStmt &x) {
2872 Word("PARAMETER "), Walk(x.v, ", ");
2874 void Unparse(const ArithmeticIfStmt &x) {
2875 Word("IF ("), Walk(std::get<Expr>(x.t)), Put(") ");
2876 Walk(std::get<1>(x.t)), Put(", ");
2877 Walk(std::get<2>(x.t)), Put(", ");
2878 Walk(std::get<3>(x.t));
2880 void Unparse(const AssignStmt &x) {
2881 Word("ASSIGN "), Walk(std::get<Label>(x.t));
2882 Word(" TO "), Walk(std::get<Name>(x.t));
2884 void Unparse(const AssignedGotoStmt &x) {
2885 Word("GO TO "), Walk(std::get<Name>(x.t));
2886 Walk(", (", std::get<std::list<Label>>(x.t), ", ", ")");
2888 void Unparse(const PauseStmt &x) { Word("PAUSE"), Walk(" ", x.v); }
2890 #define WALK_NESTED_ENUM(CLASS, ENUM) \
2891 void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); }
2892 WALK_NESTED_ENUM(AccDataModifier, Modifier)
2893 WALK_NESTED_ENUM(AccessSpec, Kind) // R807
2894 WALK_NESTED_ENUM(common, TypeParamAttr) // R734
2895 WALK_NESTED_ENUM(common, CUDADataAttr) // CUDA
2896 WALK_NESTED_ENUM(common, CUDASubprogramAttrs) // CUDA
2897 WALK_NESTED_ENUM(IntentSpec, Intent) // R826
2898 WALK_NESTED_ENUM(ImplicitStmt, ImplicitNoneNameSpec) // R866
2899 WALK_NESTED_ENUM(ConnectSpec::CharExpr, Kind) // R1205
2900 WALK_NESTED_ENUM(IoControlSpec::CharExpr, Kind)
2901 WALK_NESTED_ENUM(InquireSpec::CharVar, Kind)
2902 WALK_NESTED_ENUM(InquireSpec::IntVar, Kind)
2903 WALK_NESTED_ENUM(InquireSpec::LogVar, Kind)
2904 WALK_NESTED_ENUM(ProcedureStmt, Kind) // R1506
2905 WALK_NESTED_ENUM(UseStmt, ModuleNature) // R1410
2906 WALK_NESTED_ENUM(OmpProcBindClause, Type) // OMP PROC_BIND
2907 WALK_NESTED_ENUM(OmpDefaultClause, Type) // OMP DEFAULT
2908 WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP DEFAULTMAP
2909 WALK_NESTED_ENUM(OmpDefaultmapClause, VariableCategory) // OMP DEFAULTMAP
2910 WALK_NESTED_ENUM(
2911 OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
2912 WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
2913 WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
2914 WALK_NESTED_ENUM(OmpTaskDependenceType, Type) // OMP task-dependence-type
2915 WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
2916 WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
2917 WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
2918 WALK_NESTED_ENUM(
2919 OmpReductionClause, ReductionModifier) // OMP reduction-modifier
2920 WALK_NESTED_ENUM(OmpFromClause, Expectation) // OMP motion-expectation
2921 WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
2922 WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
2923 WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type
2924 WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier
2925 WALK_NESTED_ENUM(
2926 OmpGrainsizeClause, Prescriptiveness) // OMP grainsize-modifier
2927 WALK_NESTED_ENUM(OmpNumTasksClause, Prescriptiveness) // OMP numtasks-modifier
2928 WALK_NESTED_ENUM(OmpMapClause, Type) // OMP map-type
2929 WALK_NESTED_ENUM(OmpMapClause, TypeModifier) // OMP map-type-modifier
2930 #undef WALK_NESTED_ENUM
2931 void Unparse(const ReductionOperator::Operator x) {
2932 switch (x) {
2933 case ReductionOperator::Operator::Plus:
2934 Word("+");
2935 break;
2936 case ReductionOperator::Operator::Multiply:
2937 Word("*");
2938 break;
2939 case ReductionOperator::Operator::And:
2940 Word(".AND.");
2941 break;
2942 case ReductionOperator::Operator::Or:
2943 Word(".OR.");
2944 break;
2945 case ReductionOperator::Operator::Eqv:
2946 Word(".EQV.");
2947 break;
2948 case ReductionOperator::Operator::Neqv:
2949 Word(".NEQV.");
2950 break;
2951 default:
2952 Word(ReductionOperator::EnumToString(x));
2953 break;
2957 void Unparse(const CUFKernelDoConstruct::StarOrExpr &x) {
2958 if (x.v) {
2959 Walk(*x.v);
2960 } else {
2961 Word("*");
2964 void Unparse(const CUFKernelDoConstruct::LaunchConfiguration &x) {
2965 Word(" <<<");
2966 const auto &grid{std::get<0>(x.t)};
2967 if (grid.empty()) {
2968 Word("*");
2969 } else if (grid.size() == 1) {
2970 Walk(grid.front());
2971 } else {
2972 Walk("(", grid, ",", ")");
2974 Word(",");
2975 const auto &block{std::get<1>(x.t)};
2976 if (block.empty()) {
2977 Word("*");
2978 } else if (block.size() == 1) {
2979 Walk(block.front());
2980 } else {
2981 Walk("(", block, ",", ")");
2983 if (const auto &stream{std::get<2>(x.t)}) {
2984 Word(",STREAM="), Walk(*stream);
2986 Word(">>>");
2988 void Unparse(const CUFKernelDoConstruct::Directive &x) {
2989 Word("!$CUF KERNEL DO");
2990 Walk(" (", std::get<std::optional<ScalarIntConstantExpr>>(x.t), ")");
2991 Walk(std::get<std::optional<CUFKernelDoConstruct::LaunchConfiguration>>(
2992 x.t));
2993 Walk(" ", std::get<std::list<CUFReduction>>(x.t), " ");
2994 Word("\n");
2996 void Unparse(const CUFKernelDoConstruct &x) {
2997 Walk(std::get<CUFKernelDoConstruct::Directive>(x.t));
2998 Walk(std::get<std::optional<DoConstruct>>(x.t));
3000 void Unparse(const CUFReduction &x) {
3001 Word("REDUCE(");
3002 Walk(std::get<CUFReduction::Operator>(x.t));
3003 Walk(":", std::get<std::list<Scalar<Variable>>>(x.t), ",", ")");
3006 void Done() const { CHECK(indent_ == 0); }
3008 private:
3009 void Put(char);
3010 void Put(const char *);
3011 void Put(const std::string &);
3012 void PutNormalized(const std::string &);
3013 void PutKeywordLetter(char);
3014 void Word(const char *);
3015 void Word(const std::string &);
3016 void Word(const std::string_view &);
3017 void Indent() { indent_ += indentationAmount_; }
3018 void Outdent() {
3019 CHECK(indent_ >= indentationAmount_);
3020 indent_ -= indentationAmount_;
3022 void BeginOpenMP() { openmpDirective_ = true; }
3023 void EndOpenMP() { openmpDirective_ = false; }
3024 void BeginOpenACC() { openaccDirective_ = true; }
3025 void EndOpenACC() { openaccDirective_ = false; }
3027 // Call back to the traversal framework.
3028 template <typename T> void Walk(const T &x) {
3029 Fortran::parser::Walk(x, *this);
3032 // Traverse a std::optional<> value. Emit a prefix and/or a suffix string
3033 // only when it contains a value.
3034 template <typename A>
3035 void Walk(
3036 const char *prefix, const std::optional<A> &x, const char *suffix = "") {
3037 if (x) {
3038 Word(prefix), Walk(*x), Word(suffix);
3041 template <typename A>
3042 void Walk(const std::optional<A> &x, const char *suffix = "") {
3043 return Walk("", x, suffix);
3046 // Traverse a std::list<>. Separate the elements with an optional string.
3047 // Emit a prefix and/or a suffix string only when the list is not empty.
3048 template <typename A>
3049 void Walk(const char *prefix, const std::list<A> &list,
3050 const char *comma = ", ", const char *suffix = "") {
3051 if (!list.empty()) {
3052 const char *str{prefix};
3053 for (const auto &x : list) {
3054 Word(str), Walk(x);
3055 str = comma;
3057 Word(suffix);
3060 template <typename A>
3061 void Walk(const std::list<A> &list, const char *comma = ", ",
3062 const char *suffix = "") {
3063 return Walk("", list, comma, suffix);
3066 // Traverse a std::tuple<>, with an optional separator.
3067 template <std::size_t J = 0, typename T>
3068 void WalkTupleElements(const T &tuple, const char *separator) {
3069 if (J > 0 && J < std::tuple_size_v<T>) {
3070 Word(separator); // this usage dodges "unused parameter" warning
3072 if constexpr (J < std::tuple_size_v<T>) {
3073 Walk(std::get<J>(tuple));
3074 WalkTupleElements<J + 1>(tuple, separator);
3077 template <typename... A>
3078 void Walk(const std::tuple<A...> &tuple, const char *separator = "") {
3079 WalkTupleElements(tuple, separator);
3082 void EndSubprogram(const char *kind, const std::optional<Name> &name) {
3083 Outdent(), Word("END "), Word(kind), Walk(" ", name);
3084 structureComponents_.clear();
3087 llvm::raw_ostream &out_;
3088 int indent_{0};
3089 const int indentationAmount_{1};
3090 int column_{1};
3091 const int maxColumns_{80};
3092 std::set<CharBlock> structureComponents_;
3093 Encoding encoding_{Encoding::UTF_8};
3094 bool capitalizeKeywords_{true};
3095 bool openaccDirective_{false};
3096 bool openmpDirective_{false};
3097 bool backslashEscapes_{false};
3098 preStatementType *preStatement_{nullptr};
3099 AnalyzedObjectsAsFortran *asFortran_{nullptr};
3102 void UnparseVisitor::Put(char ch) {
3103 int sav = indent_;
3104 if (openmpDirective_ || openaccDirective_) {
3105 indent_ = 0;
3107 if (column_ <= 1) {
3108 if (ch == '\n') {
3109 return;
3111 for (int j{0}; j < indent_; ++j) {
3112 out_ << ' ';
3114 column_ = indent_ + 2;
3115 } else if (ch == '\n') {
3116 column_ = 1;
3117 } else if (++column_ >= maxColumns_) {
3118 out_ << "&\n";
3119 for (int j{0}; j < indent_; ++j) {
3120 out_ << ' ';
3122 if (openmpDirective_) {
3123 out_ << "!$OMP&";
3124 column_ = 8;
3125 } else if (openaccDirective_) {
3126 out_ << "!$ACC&";
3127 column_ = 8;
3128 } else {
3129 out_ << '&';
3130 column_ = indent_ + 3;
3133 out_ << ch;
3134 if (openmpDirective_ || openaccDirective_) {
3135 indent_ = sav;
3139 void UnparseVisitor::Put(const char *str) {
3140 for (; *str != '\0'; ++str) {
3141 Put(*str);
3145 void UnparseVisitor::Put(const std::string &str) {
3146 for (char ch : str) {
3147 Put(ch);
3151 void UnparseVisitor::PutNormalized(const std::string &str) {
3152 auto decoded{DecodeString<std::string, Encoding::LATIN_1>(str, true)};
3153 std::string encoded{EncodeString<Encoding::LATIN_1>(decoded)};
3154 Put(QuoteCharacterLiteral(encoded, backslashEscapes_));
3157 void UnparseVisitor::PutKeywordLetter(char ch) {
3158 if (capitalizeKeywords_) {
3159 Put(ToUpperCaseLetter(ch));
3160 } else {
3161 Put(ToLowerCaseLetter(ch));
3165 void UnparseVisitor::Word(const char *str) {
3166 for (; *str != '\0'; ++str) {
3167 PutKeywordLetter(*str);
3171 void UnparseVisitor::Word(const std::string &str) { Word(str.c_str()); }
3173 void UnparseVisitor::Word(const std::string_view &str) {
3174 for (std::size_t j{0}; j < str.length(); ++j) {
3175 PutKeywordLetter(str[j]);
3179 template <typename A>
3180 void Unparse(llvm::raw_ostream &out, const A &root, Encoding encoding,
3181 bool capitalizeKeywords, bool backslashEscapes,
3182 preStatementType *preStatement, AnalyzedObjectsAsFortran *asFortran) {
3183 UnparseVisitor visitor{out, 1, encoding, capitalizeKeywords, backslashEscapes,
3184 preStatement, asFortran};
3185 Walk(root, visitor);
3186 visitor.Done();
3189 template void Unparse<Program>(llvm::raw_ostream &, const Program &, Encoding,
3190 bool, bool, preStatementType *, AnalyzedObjectsAsFortran *);
3191 template void Unparse<Expr>(llvm::raw_ostream &, const Expr &, Encoding, bool,
3192 bool, preStatementType *, AnalyzedObjectsAsFortran *);
3193 } // namespace Fortran::parser