1 //===-- lib/Parser/unparse.cpp --------------------------------------------===//
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
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"
26 namespace Fortran::parser
{
28 class UnparseVisitor
{
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.
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
);
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
) {
80 (*preStatement_
)(x
.source
, out_
, indent_
);
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
97 void Unparse(const DefinedOperator::IntrinsicOperator
&x
) { // R608
99 case DefinedOperator::IntrinsicOperator::Power
:
102 case DefinedOperator::IntrinsicOperator::Multiply
:
105 case DefinedOperator::IntrinsicOperator::Divide
:
108 case DefinedOperator::IntrinsicOperator::Add
:
111 case DefinedOperator::IntrinsicOperator::Subtract
:
114 case DefinedOperator::IntrinsicOperator::Concat
:
117 case DefinedOperator::IntrinsicOperator::LT
:
120 case DefinedOperator::IntrinsicOperator::LE
:
123 case DefinedOperator::IntrinsicOperator::EQ
:
126 case DefinedOperator::IntrinsicOperator::NE
:
129 case DefinedOperator::IntrinsicOperator::GE
:
132 case DefinedOperator::IntrinsicOperator::GT
:
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
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
176 void Unparse(const KindSelector
&x
) { // R706
179 [&](const ScalarIntConstantExpr
&y
) {
180 Put('('), Word("KIND="), Walk(y
), Put(')');
182 [&](const KindSelector::StarSize
&y
) { Put('*'), Walk(y
.v
); },
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
); },
216 void Unparse(const CharLength
&x
) { // R723
219 [&](const TypeParamValue
&y
) { Put('('), Walk(y
), Put(')'); },
220 [&](const std::int64_t &y
) { Walk(y
); },
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
)}) {
231 void Unparse(const HollerithLiteralConstant
&x
) {
232 auto ucs
{DecodeString
<std::u32string
, Encoding::UTF_8
>(x
.v
, false)};
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
), ", ", ")");
252 void Unparse(const Abstract
&) { // R728, &c.
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
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
) &&
282 decls
.begin(), decls
.end(), [](const ComponentOrFill
&c
) {
283 return common::visit(
285 [](const ComponentDecl
&d
) {
287 std::get
<std::optional
<Initialization
>>(d
.t
)};
289 std::holds_alternative
<std::list
<
290 common::Indirection
<DataStmtValue
>>>(
293 [](const FillDecl
&) { return false; },
299 Put(' '), Walk(decls
, ", ");
301 void Unparse(const Allocatable
&) { // R738
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("); },
314 void Post(const ComponentAttrSpec
&x
) {
315 common::visit(common::visitors
{
316 [&](const CoarraySpec
&) { Put(']'); },
317 [&](const ComponentArraySpec
&) { Put(')'); },
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
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
337 [&](const std::list
<ExplicitShapeSpec
> &y
) { Walk(y
, ","); },
338 [&](const DeferredShapeSpecList
&y
) { Walk(y
); },
342 void Unparse(const ProcComponentDefStmt
&x
) { // R741
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
351 void Unparse(const Pass
&x
) { Word("PASS"), Walk("(", x
.v
, ")"); }
352 void Unparse(const Initialization
&x
) { // R743 & R805
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
, ", ", "/");
364 void Unparse(const PrivateStmt
&) { // R745
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("), ");
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
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
);
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.
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).
480 // Never put :: in a legacy extension RECORD// statement.
483 // The :: is optional for this declaration. Avoid usage that can
484 // crash the pgf90 compiler.
486 decls
.begin(), decls
.end(), hasSlashDelimitedInitializer
)) {
487 // Don't use :: when a declaration uses legacy DATA-statement-like
488 // /x/ initialization.
491 // Don't use :: with intrinsic types. Otherwise, use it.
492 return !std::holds_alternative
<IntrinsicTypeSpec
>(dts
.u
);
495 if (useDoubledColons()) {
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("); },
508 void Post(const AttrSpec
&x
) {
509 common::visit(common::visitors
{
510 [&](const CoarraySpec
&) { Put(']'); },
511 [&](const ArraySpec
&) { Put(')'); },
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
526 void Unparse(const LanguageBindingSpec
&x
) { // R808 & R1528
527 Word("BIND(C"), Walk(", NAME=", x
.v
), Put(')');
529 void Unparse(const CoarraySpec
&x
) { // R809
530 common::visit(common::visitors
{
531 [&](const DeferredCoshapeSpecList
&y
) { Walk(y
); },
532 [&](const ExplicitCoshapeSpec
&y
) { Walk(y
); },
536 void Unparse(const DeferredCoshapeSpecList
&x
) { // R810
537 for (auto j
{x
.v
}; j
> 0; --j
) {
544 void Unparse(const ExplicitCoshapeSpec
&x
) { // R811
545 Walk(std::get
<std::list
<ExplicitShapeSpec
>>(x
.t
), ",", ",");
546 Walk(std::get
<std::optional
<SpecificationExpr
>>(x
.t
), ":"), Put('*');
548 void Unparse(const ExplicitShapeSpec
&x
) { // R812 - R813 & R816 - R818
549 Walk(std::get
<std::optional
<SpecificationExpr
>>(x
.t
), ":");
550 Walk(std::get
<SpecificationExpr
>(x
.t
));
552 void Unparse(const ArraySpec
&x
) { // R815
555 [&](const std::list
<ExplicitShapeSpec
> &y
) { Walk(y
, ","); },
556 [&](const std::list
<AssumedShapeSpec
> &y
) { Walk(y
, ","); },
557 [&](const DeferredShapeSpecList
&y
) { Walk(y
); },
558 [&](const AssumedSizeSpec
&y
) { Walk(y
); },
559 [&](const ImpliedShapeSpec
&y
) { Walk(y
); },
560 [&](const AssumedRankSpec
&y
) { Walk(y
); },
564 void Post(const AssumedShapeSpec
&) { Put(':'); } // R819
565 void Unparse(const DeferredShapeSpecList
&x
) { // R820
566 for (auto j
{x
.v
}; j
> 0; --j
) {
573 void Unparse(const AssumedImpliedSpec
&x
) { // R821
577 void Unparse(const AssumedSizeSpec
&x
) { // R822
578 Walk(std::get
<std::list
<ExplicitShapeSpec
>>(x
.t
), ",", ",");
579 Walk(std::get
<AssumedImpliedSpec
>(x
.t
));
581 void Unparse(const ImpliedShapeSpec
&x
) { // R823
584 void Post(const AssumedRankSpec
&) { Put(".."); } // R825
585 void Post(const Asynchronous
&) { Word("ASYNCHRONOUS"); }
586 void Post(const External
&) { Word("EXTERNAL"); }
587 void Post(const Intrinsic
&) { Word("INTRINSIC"); }
588 void Post(const Optional
&) { Word("OPTIONAL"); }
589 void Post(const Parameter
&) { Word("PARAMETER"); }
590 void Post(const Protected
&) { Word("PROTECTED"); }
591 void Post(const Save
&) { Word("SAVE"); }
592 void Post(const Target
&) { Word("TARGET"); }
593 void Post(const Value
&) { Word("VALUE"); }
594 void Post(const Volatile
&) { Word("VOLATILE"); }
595 void Unparse(const IntentSpec
&x
) { // R826
596 Word("INTENT("), Walk(x
.v
), Put(")");
598 void Unparse(const AccessStmt
&x
) { // R827
599 Walk(std::get
<AccessSpec
>(x
.t
));
600 Walk(" :: ", std::get
<std::list
<AccessId
>>(x
.t
), ", ");
602 void Unparse(const AllocatableStmt
&x
) { // R829
603 Word("ALLOCATABLE :: "), Walk(x
.v
, ", ");
605 void Unparse(const ObjectDecl
&x
) { // R830 & R860
606 Walk(std::get
<ObjectName
>(x
.t
));
607 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
608 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
610 void Unparse(const AsynchronousStmt
&x
) { // R831
611 Word("ASYNCHRONOUS :: "), Walk(x
.v
, ", ");
613 void Unparse(const BindStmt
&x
) { // R832
616 void Unparse(const BindEntity
&x
) { // R833
617 bool isCommon
{std::get
<BindEntity::Kind
>(x
.t
) == BindEntity::Kind::Common
};
618 const char *slash
{isCommon
? "/" : ""};
619 Put(slash
), Walk(std::get
<Name
>(x
.t
)), Put(slash
);
621 void Unparse(const CodimensionStmt
&x
) { // R834
622 Word("CODIMENSION :: "), Walk(x
.v
, ", ");
624 void Unparse(const CodimensionDecl
&x
) { // R835
625 Walk(std::get
<Name
>(x
.t
));
626 Put('['), Walk(std::get
<CoarraySpec
>(x
.t
)), Put(']');
628 void Unparse(const ContiguousStmt
&x
) { // R836
629 Word("CONTIGUOUS :: "), Walk(x
.v
, ", ");
631 void Unparse(const DataStmt
&x
) { // R837
632 Word("DATA "), Walk(x
.v
, ", ");
634 void Unparse(const DataStmtSet
&x
) { // R838
635 Walk(std::get
<std::list
<DataStmtObject
>>(x
.t
), ", ");
636 Put('/'), Walk(std::get
<std::list
<DataStmtValue
>>(x
.t
), ", "), Put('/');
638 void Unparse(const DataImpliedDo
&x
) { // R840, R842
639 Put('('), Walk(std::get
<std::list
<DataIDoObject
>>(x
.t
), ", "), Put(',');
640 Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
641 Walk(std::get
<DataImpliedDo::Bounds
>(x
.t
)), Put(')');
643 void Unparse(const DataStmtValue
&x
) { // R843
644 Walk(std::get
<std::optional
<DataStmtRepeat
>>(x
.t
), "*");
645 Walk(std::get
<DataStmtConstant
>(x
.t
));
647 void Unparse(const DimensionStmt
&x
) { // R848
648 Word("DIMENSION :: "), Walk(x
.v
, ", ");
650 void Unparse(const DimensionStmt::Declaration
&x
) {
651 Walk(std::get
<Name
>(x
.t
));
652 Put('('), Walk(std::get
<ArraySpec
>(x
.t
)), Put(')');
654 void Unparse(const IntentStmt
&x
) { // R849
657 void Unparse(const OptionalStmt
&x
) { // R850
658 Word("OPTIONAL :: "), Walk(x
.v
, ", ");
660 void Unparse(const ParameterStmt
&x
) { // R851
661 Word("PARAMETER("), Walk(x
.v
, ", "), Put(')');
663 void Unparse(const NamedConstantDef
&x
) { // R852
666 void Unparse(const PointerStmt
&x
) { // R853
667 Word("POINTER :: "), Walk(x
.v
, ", ");
669 void Unparse(const PointerDecl
&x
) { // R854
670 Walk(std::get
<Name
>(x
.t
));
671 Walk("(", std::get
<std::optional
<DeferredShapeSpecList
>>(x
.t
), ")");
673 void Unparse(const ProtectedStmt
&x
) { // R855
674 Word("PROTECTED :: "), Walk(x
.v
, ", ");
676 void Unparse(const SaveStmt
&x
) { // R856
677 Word("SAVE"), Walk(" :: ", x
.v
, ", ");
679 void Unparse(const SavedEntity
&x
) { // R857, R858
681 std::get
<SavedEntity::Kind
>(x
.t
) == SavedEntity::Kind::Common
};
682 const char *slash
{isCommon
? "/" : ""};
683 Put(slash
), Walk(std::get
<Name
>(x
.t
)), Put(slash
);
685 void Unparse(const TargetStmt
&x
) { // R859
686 Word("TARGET :: "), Walk(x
.v
, ", ");
688 void Unparse(const ValueStmt
&x
) { // R861
689 Word("VALUE :: "), Walk(x
.v
, ", ");
691 void Unparse(const VolatileStmt
&x
) { // R862
692 Word("VOLATILE :: "), Walk(x
.v
, ", ");
694 void Unparse(const ImplicitStmt
&x
) { // R863
698 [&](const std::list
<ImplicitSpec
> &y
) { Walk(y
, ", "); },
699 [&](const std::list
<ImplicitStmt::ImplicitNoneNameSpec
> &y
) {
700 Word("NONE"), Walk(" (", y
, ", ", ")");
705 void Unparse(const ImplicitSpec
&x
) { // R864
706 Walk(std::get
<DeclarationTypeSpec
>(x
.t
));
707 Put('('), Walk(std::get
<std::list
<LetterSpec
>>(x
.t
), ", "), Put(')');
709 void Unparse(const LetterSpec
&x
) { // R865
710 Put(*std::get
<const char *>(x
.t
));
711 auto second
{std::get
<std::optional
<const char *>>(x
.t
)};
713 Put('-'), Put(**second
);
716 void Unparse(const ImportStmt
&x
) { // R867
719 case common::ImportKind::Default
:
720 Walk(" :: ", x
.names
, ", ");
722 case common::ImportKind::Only
:
723 Put(", "), Word("ONLY: ");
726 case common::ImportKind::None
:
729 case common::ImportKind::All
:
734 void Unparse(const NamelistStmt
&x
) { // R868
735 Word("NAMELIST"), Walk(x
.v
, ", ");
737 void Unparse(const NamelistStmt::Group
&x
) {
738 Put('/'), Walk(std::get
<Name
>(x
.t
)), Put('/');
739 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
741 void Unparse(const EquivalenceStmt
&x
) { // R870, R871
743 const char *separator
{" "};
744 for (const std::list
<EquivalenceObject
> &y
: x
.v
) {
745 Put(separator
), Put('('), Walk(y
), Put(')');
749 void Unparse(const CommonStmt
&x
) { // R873
753 void Unparse(const CommonBlockObject
&x
) { // R874
754 Walk(std::get
<Name
>(x
.t
));
755 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
757 void Unparse(const CommonStmt::Block
&x
) {
758 Word("/"), Walk(std::get
<std::optional
<Name
>>(x
.t
)), Word("/");
759 Walk(std::get
<std::list
<CommonBlockObject
>>(x
.t
));
762 void Unparse(const Substring
&x
) { // R908, R909
763 Walk(std::get
<DataRef
>(x
.t
));
764 Put('('), Walk(std::get
<SubstringRange
>(x
.t
)), Put(')');
766 void Unparse(const CharLiteralConstantSubstring
&x
) {
767 Walk(std::get
<CharLiteralConstant
>(x
.t
));
768 Put('('), Walk(std::get
<SubstringRange
>(x
.t
)), Put(')');
770 void Unparse(const SubstringInquiry
&x
) {
772 Put(x
.source
.end()[-1] == 'n' ? "%LEN" : "%KIND");
774 void Unparse(const SubstringRange
&x
) { // R910
777 void Unparse(const PartRef
&x
) { // R912
779 Walk("(", x
.subscripts
, ",", ")");
780 Walk(x
.imageSelector
);
782 void Unparse(const StructureComponent
&x
) { // R913
784 if (structureComponents_
.find(x
.component
.source
) !=
785 structureComponents_
.end()) {
792 void Unparse(const ArrayElement
&x
) { // R917
794 Put('('), Walk(x
.subscripts
, ","), Put(')');
796 void Unparse(const SubscriptTriplet
&x
) { // R921
797 Walk(std::get
<0>(x
.t
)), Put(':'), Walk(std::get
<1>(x
.t
));
798 Walk(":", std::get
<2>(x
.t
));
800 void Unparse(const ImageSelector
&x
) { // R924
801 Put('['), Walk(std::get
<std::list
<Cosubscript
>>(x
.t
), ",");
802 Walk(",", std::get
<std::list
<ImageSelectorSpec
>>(x
.t
), ","), Put(']');
804 void Before(const ImageSelectorSpec::Stat
&) { // R926
807 void Before(const ImageSelectorSpec::Team_Number
&) { Word("TEAM_NUMBER="); }
808 void Before(const ImageSelectorSpec
&x
) {
809 if (std::holds_alternative
<TeamValue
>(x
.u
)) {
813 void Unparse(const AllocateStmt
&x
) { // R927
815 Walk(std::get
<std::optional
<TypeSpec
>>(x
.t
), "::");
816 Walk(std::get
<std::list
<Allocation
>>(x
.t
), ", ");
817 Walk(", ", std::get
<std::list
<AllocOpt
>>(x
.t
), ", "), Put(')');
819 void Before(const AllocOpt
&x
) { // R928, R931
820 common::visit(common::visitors
{
821 [&](const AllocOpt::Mold
&) { Word("MOLD="); },
822 [&](const AllocOpt::Source
&) { Word("SOURCE="); },
823 [&](const AllocOpt::Stream
&) { Word("STREAM="); },
824 [&](const AllocOpt::Pinned
&) { Word("PINNED="); },
825 [](const StatOrErrmsg
&) {},
829 void Unparse(const Allocation
&x
) { // R932
830 Walk(std::get
<AllocateObject
>(x
.t
));
831 Walk("(", std::get
<std::list
<AllocateShapeSpec
>>(x
.t
), ",", ")");
832 Walk("[", std::get
<std::optional
<AllocateCoarraySpec
>>(x
.t
), "]");
834 void Unparse(const AllocateShapeSpec
&x
) { // R934 & R938
835 Walk(std::get
<std::optional
<BoundExpr
>>(x
.t
), ":");
836 Walk(std::get
<BoundExpr
>(x
.t
));
838 void Unparse(const AllocateCoarraySpec
&x
) { // R937
839 Walk(std::get
<std::list
<AllocateCoshapeSpec
>>(x
.t
), ",", ",");
840 Walk(std::get
<std::optional
<BoundExpr
>>(x
.t
), ":"), Put('*');
842 void Unparse(const NullifyStmt
&x
) { // R939
843 Word("NULLIFY("), Walk(x
.v
, ", "), Put(')');
845 void Unparse(const DeallocateStmt
&x
) { // R941
847 Walk(std::get
<std::list
<AllocateObject
>>(x
.t
), ", ");
848 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
850 void Before(const StatOrErrmsg
&x
) { // R942 & R1165
851 common::visit(common::visitors
{
852 [&](const StatVariable
&) { Word("STAT="); },
853 [&](const MsgVariable
&) { Word("ERRMSG="); },
859 void Unparse(const Expr::Parentheses
&x
) { Put('('), Walk(x
.v
), Put(')'); }
860 void Before(const Expr::UnaryPlus
&) { Put("+"); }
861 void Before(const Expr::Negate
&) { Put("-"); }
862 void Before(const Expr::NOT
&) { Word(".NOT."); }
863 void Unparse(const Expr::PercentLoc
&x
) {
864 Word("%LOC("), Walk(x
.v
), Put(')');
866 void Unparse(const Expr::Power
&x
) { Walk(x
.t
, "**"); }
867 void Unparse(const Expr::Multiply
&x
) { Walk(x
.t
, "*"); }
868 void Unparse(const Expr::Divide
&x
) { Walk(x
.t
, "/"); }
869 void Unparse(const Expr::Add
&x
) { Walk(x
.t
, "+"); }
870 void Unparse(const Expr::Subtract
&x
) { Walk(x
.t
, "-"); }
871 void Unparse(const Expr::Concat
&x
) { Walk(x
.t
, "//"); }
872 void Unparse(const Expr::LT
&x
) { Walk(x
.t
, "<"); }
873 void Unparse(const Expr::LE
&x
) { Walk(x
.t
, "<="); }
874 void Unparse(const Expr::EQ
&x
) { Walk(x
.t
, "=="); }
875 void Unparse(const Expr::NE
&x
) { Walk(x
.t
, "/="); }
876 void Unparse(const Expr::GE
&x
) { Walk(x
.t
, ">="); }
877 void Unparse(const Expr::GT
&x
) { Walk(x
.t
, ">"); }
878 void Unparse(const Expr::AND
&x
) { Walk(x
.t
, ".AND."); }
879 void Unparse(const Expr::OR
&x
) { Walk(x
.t
, ".OR."); }
880 void Unparse(const Expr::EQV
&x
) { Walk(x
.t
, ".EQV."); }
881 void Unparse(const Expr::NEQV
&x
) { Walk(x
.t
, ".NEQV."); }
882 void Unparse(const Expr::ComplexConstructor
&x
) {
883 Put('('), Walk(x
.t
, ","), Put(')');
885 void Unparse(const Expr::DefinedBinary
&x
) {
886 Walk(std::get
<1>(x
.t
)); // left
887 Walk(std::get
<DefinedOpName
>(x
.t
));
888 Walk(std::get
<2>(x
.t
)); // right
890 void Unparse(const DefinedOpName
&x
) { // R1003, R1023, R1414, & R1415
893 void Unparse(const AssignmentStmt
&x
) { // R1032
894 if (asFortran_
&& x
.typedAssignment
.get()) {
896 asFortran_
->assignment(out_
, *x
.typedAssignment
);
902 void Unparse(const PointerAssignmentStmt
&x
) { // R1033, R1034, R1038
903 if (asFortran_
&& x
.typedAssignment
.get()) {
905 asFortran_
->assignment(out_
, *x
.typedAssignment
);
908 Walk(std::get
<DataRef
>(x
.t
));
911 [&](const std::list
<BoundsRemapping
> &y
) {
912 Put('('), Walk(y
), Put(')');
914 [&](const std::list
<BoundsSpec
> &y
) { Walk("(", y
, ", ", ")"); },
916 std::get
<PointerAssignmentStmt::Bounds
>(x
.t
).u
);
917 Put(" => "), Walk(std::get
<Expr
>(x
.t
));
920 void Post(const BoundsSpec
&) { // R1035
923 void Unparse(const BoundsRemapping
&x
) { // R1036
926 void Unparse(const WhereStmt
&x
) { // R1041, R1045, R1046
927 Word("WHERE ("), Walk(x
.t
, ") ");
929 void Unparse(const WhereConstructStmt
&x
) { // R1043
930 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
931 Word("WHERE ("), Walk(std::get
<LogicalExpr
>(x
.t
)), Put(')');
934 void Unparse(const MaskedElsewhereStmt
&x
) { // R1047
936 Word("ELSEWHERE ("), Walk(std::get
<LogicalExpr
>(x
.t
)), Put(')');
937 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
));
940 void Unparse(const ElsewhereStmt
&x
) { // R1048
941 Outdent(), Word("ELSEWHERE"), Walk(" ", x
.v
), Indent();
943 void Unparse(const EndWhereStmt
&x
) { // R1049
944 Outdent(), Word("END WHERE"), Walk(" ", x
.v
);
946 void Unparse(const ForallConstructStmt
&x
) { // R1051
947 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
948 Word("FORALL"), Walk(std::get
<common::Indirection
<ConcurrentHeader
>>(x
.t
));
951 void Unparse(const EndForallStmt
&x
) { // R1054
952 Outdent(), Word("END FORALL"), Walk(" ", x
.v
);
954 void Before(const ForallStmt
&) { // R1055
958 void Unparse(const AssociateStmt
&x
) { // R1103
959 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
961 Walk(std::get
<std::list
<Association
>>(x
.t
), ", "), Put(')'), Indent();
963 void Unparse(const Association
&x
) { // R1104
966 void Unparse(const EndAssociateStmt
&x
) { // R1106
967 Outdent(), Word("END ASSOCIATE"), Walk(" ", x
.v
);
969 void Unparse(const BlockStmt
&x
) { // R1108
970 Walk(x
.v
, ": "), Word("BLOCK"), Indent();
972 void Unparse(const EndBlockStmt
&x
) { // R1110
973 Outdent(), Word("END BLOCK"), Walk(" ", x
.v
);
975 void Unparse(const ChangeTeamStmt
&x
) { // R1112
976 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
977 Word("CHANGE TEAM ("), Walk(std::get
<TeamValue
>(x
.t
));
978 Walk(", ", std::get
<std::list
<CoarrayAssociation
>>(x
.t
), ", ");
979 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
982 void Unparse(const CoarrayAssociation
&x
) { // R1113
985 void Unparse(const EndChangeTeamStmt
&x
) { // R1114
986 Outdent(), Word("END TEAM (");
987 Walk(std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
988 Put(')'), Walk(" ", std::get
<std::optional
<Name
>>(x
.t
));
990 void Unparse(const CriticalStmt
&x
) { // R1117
991 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
992 Word("CRITICAL ("), Walk(std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
995 void Unparse(const EndCriticalStmt
&x
) { // R1118
996 Outdent(), Word("END CRITICAL"), Walk(" ", x
.v
);
998 void Unparse(const DoConstruct
&x
) { // R1119, R1120
999 Walk(std::get
<Statement
<NonLabelDoStmt
>>(x
.t
));
1000 Indent(), Walk(std::get
<Block
>(x
.t
), ""), Outdent();
1001 Walk(std::get
<Statement
<EndDoStmt
>>(x
.t
));
1003 void Unparse(const LabelDoStmt
&x
) { // R1121
1004 Word("DO "), Walk(std::get
<Label
>(x
.t
));
1005 Walk(" ", std::get
<std::optional
<LoopControl
>>(x
.t
));
1007 void Unparse(const NonLabelDoStmt
&x
) { // R1122
1008 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1010 Walk(std::get
<std::optional
<Label
>>(x
.t
), " ");
1011 Walk(std::get
<std::optional
<LoopControl
>>(x
.t
));
1013 void Unparse(const LoopControl
&x
) { // R1123
1014 common::visit(common::visitors
{
1015 [&](const ScalarLogicalExpr
&y
) {
1016 Word("WHILE ("), Walk(y
), Put(')');
1018 [&](const auto &y
) { Walk(y
); },
1022 void Unparse(const ConcurrentHeader
&x
) { // R1125
1023 Put('('), Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
1024 Walk(std::get
<std::list
<ConcurrentControl
>>(x
.t
), ", ");
1025 Walk(", ", std::get
<std::optional
<ScalarLogicalExpr
>>(x
.t
)), Put(')');
1027 void Unparse(const ConcurrentControl
&x
) { // R1126 - R1128
1028 Walk(std::get
<Name
>(x
.t
)), Put('='), Walk(std::get
<1>(x
.t
));
1029 Put(':'), Walk(std::get
<2>(x
.t
));
1030 Walk(":", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
1032 void Before(const LoopControl::Concurrent
&) { // R1129
1035 void Unparse(const LocalitySpec::Local
&x
) {
1036 Word("LOCAL("), Walk(x
.v
, ", "), Put(')');
1038 void Unparse(const LocalitySpec::LocalInit
&x
) {
1039 Word("LOCAL_INIT("), Walk(x
.v
, ", "), Put(')');
1041 void Unparse(const LocalitySpec::Shared
&x
) {
1042 Word("SHARED("), Walk(x
.v
, ", "), Put(')');
1044 void Post(const LocalitySpec::DefaultNone
&) { Word("DEFAULT(NONE)"); }
1045 void Unparse(const EndDoStmt
&x
) { // R1132
1046 Word("END DO"), Walk(" ", x
.v
);
1048 void Unparse(const CycleStmt
&x
) { // R1133
1049 Word("CYCLE"), Walk(" ", x
.v
);
1051 void Unparse(const IfThenStmt
&x
) { // R1135
1052 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1053 Word("IF ("), Walk(std::get
<ScalarLogicalExpr
>(x
.t
));
1054 Put(") "), Word("THEN"), Indent();
1056 void Unparse(const ElseIfStmt
&x
) { // R1136
1057 Outdent(), Word("ELSE IF (");
1058 Walk(std::get
<ScalarLogicalExpr
>(x
.t
)), Put(") "), Word("THEN");
1059 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1061 void Unparse(const ElseStmt
&x
) { // R1137
1062 Outdent(), Word("ELSE"), Walk(" ", x
.v
), Indent();
1064 void Unparse(const EndIfStmt
&x
) { // R1138
1065 Outdent(), Word("END IF"), Walk(" ", x
.v
);
1067 void Unparse(const IfStmt
&x
) { // R1139
1068 Word("IF ("), Walk(x
.t
, ") ");
1070 void Unparse(const SelectCaseStmt
&x
) { // R1141, R1144
1071 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1072 Word("SELECT CASE (");
1073 Walk(std::get
<Scalar
<Expr
>>(x
.t
)), Put(')'), Indent();
1075 void Unparse(const CaseStmt
&x
) { // R1142
1076 Outdent(), Word("CASE "), Walk(std::get
<CaseSelector
>(x
.t
));
1077 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1079 void Unparse(const EndSelectStmt
&x
) { // R1143 & R1151 & R1155
1080 Outdent(), Word("END SELECT"), Walk(" ", x
.v
);
1082 void Unparse(const CaseSelector
&x
) { // R1145
1083 common::visit(common::visitors
{
1084 [&](const std::list
<CaseValueRange
> &y
) {
1085 Put('('), Walk(y
), Put(')');
1087 [&](const Default
&) { Word("DEFAULT"); },
1091 void Unparse(const CaseValueRange::Range
&x
) { // R1146
1092 Walk(x
.lower
), Put(':'), Walk(x
.upper
);
1094 void Unparse(const SelectRankStmt
&x
) { // R1149
1095 Walk(std::get
<0>(x
.t
), ": ");
1096 Word("SELECT RANK ("), Walk(std::get
<1>(x
.t
), " => ");
1097 Walk(std::get
<Selector
>(x
.t
)), Put(')'), Indent();
1099 void Unparse(const SelectRankCaseStmt
&x
) { // R1150
1100 Outdent(), Word("RANK ");
1101 common::visit(common::visitors
{
1102 [&](const ScalarIntConstantExpr
&y
) {
1103 Put('('), Walk(y
), Put(')');
1105 [&](const Star
&) { Put("(*)"); },
1106 [&](const Default
&) { Word("DEFAULT"); },
1108 std::get
<SelectRankCaseStmt::Rank
>(x
.t
).u
);
1109 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1111 void Unparse(const SelectTypeStmt
&x
) { // R1153
1112 Walk(std::get
<0>(x
.t
), ": ");
1113 Word("SELECT TYPE ("), Walk(std::get
<1>(x
.t
), " => ");
1114 Walk(std::get
<Selector
>(x
.t
)), Put(')'), Indent();
1116 void Unparse(const TypeGuardStmt
&x
) { // R1154
1117 Outdent(), Walk(std::get
<TypeGuardStmt::Guard
>(x
.t
));
1118 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1120 void Unparse(const TypeGuardStmt::Guard
&x
) {
1123 [&](const TypeSpec
&y
) { Word("TYPE IS ("), Walk(y
), Put(')'); },
1124 [&](const DerivedTypeSpec
&y
) {
1125 Word("CLASS IS ("), Walk(y
), Put(')');
1127 [&](const Default
&) { Word("CLASS DEFAULT"); },
1131 void Unparse(const ExitStmt
&x
) { // R1156
1132 Word("EXIT"), Walk(" ", x
.v
);
1134 void Before(const GotoStmt
&) { // R1157
1137 void Unparse(const ComputedGotoStmt
&x
) { // R1158
1138 Word("GO TO ("), Walk(x
.t
, "), ");
1140 void Unparse(const ContinueStmt
&) { // R1159
1143 void Unparse(const StopStmt
&x
) { // R1160, R1161
1144 if (std::get
<StopStmt::Kind
>(x
.t
) == StopStmt::Kind::ErrorStop
) {
1147 Word("STOP"), Walk(" ", std::get
<std::optional
<StopCode
>>(x
.t
));
1148 Walk(", QUIET=", std::get
<std::optional
<ScalarLogicalExpr
>>(x
.t
));
1150 void Unparse(const FailImageStmt
&) { // R1163
1153 void Unparse(const NotifyWaitStmt
&x
) { // F2023: R1166
1154 Word("NOTIFY WAIT ("), Walk(std::get
<Scalar
<Variable
>>(x
.t
));
1155 Walk(", ", std::get
<std::list
<EventWaitSpec
>>(x
.t
), ", ");
1158 void Unparse(const SyncAllStmt
&x
) { // R1164
1159 Word("SYNC ALL ("), Walk(x
.v
, ", "), Put(')');
1161 void Unparse(const SyncImagesStmt
&x
) { // R1166
1162 Word("SYNC IMAGES (");
1163 Walk(std::get
<SyncImagesStmt::ImageSet
>(x
.t
));
1164 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1166 void Unparse(const SyncMemoryStmt
&x
) { // R1168
1167 Word("SYNC MEMORY ("), Walk(x
.v
, ", "), Put(')');
1169 void Unparse(const SyncTeamStmt
&x
) { // R1169
1170 Word("SYNC TEAM ("), Walk(std::get
<TeamValue
>(x
.t
));
1171 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1173 void Unparse(const EventPostStmt
&x
) { // R1170
1174 Word("EVENT POST ("), Walk(std::get
<EventVariable
>(x
.t
));
1175 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1177 void Before(const EventWaitSpec
&x
) { // R1173, R1174
1178 common::visit(common::visitors
{
1179 [&](const ScalarIntExpr
&) { Word("UNTIL_COUNT="); },
1180 [](const StatOrErrmsg
&) {},
1184 void Unparse(const EventWaitStmt
&x
) { // R1170
1185 Word("EVENT WAIT ("), Walk(std::get
<EventVariable
>(x
.t
));
1186 Walk(", ", std::get
<std::list
<EventWaitSpec
>>(x
.t
), ", ");
1189 void Unparse(const FormTeamStmt
&x
) { // R1175, R1177
1190 Word("FORM TEAM ("), Walk(std::get
<ScalarIntExpr
>(x
.t
));
1191 Put(','), Walk(std::get
<TeamVariable
>(x
.t
));
1192 Walk(", ", std::get
<std::list
<FormTeamStmt::FormTeamSpec
>>(x
.t
), ", ");
1195 void Before(const FormTeamStmt::FormTeamSpec
&x
) { // R1176, R1178
1196 common::visit(common::visitors
{
1197 [&](const ScalarIntExpr
&) { Word("NEW_INDEX="); },
1198 [](const StatOrErrmsg
&) {},
1202 void Unparse(const LockStmt
&x
) { // R1179
1203 Word("LOCK ("), Walk(std::get
<LockVariable
>(x
.t
));
1204 Walk(", ", std::get
<std::list
<LockStmt::LockStat
>>(x
.t
), ", ");
1207 void Before(const LockStmt::LockStat
&x
) { // R1180
1210 [&](const ScalarLogicalVariable
&) { Word("ACQUIRED_LOCK="); },
1211 [](const StatOrErrmsg
&) {},
1215 void Unparse(const UnlockStmt
&x
) { // R1181
1216 Word("UNLOCK ("), Walk(std::get
<LockVariable
>(x
.t
));
1217 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
1221 void Unparse(const OpenStmt
&x
) { // R1204
1222 Word("OPEN ("), Walk(x
.v
, ", "), Put(')');
1224 bool Pre(const ConnectSpec
&x
) { // R1205
1225 return common::visit(common::visitors
{
1226 [&](const FileUnitNumber
&) {
1230 [&](const FileNameExpr
&) {
1234 [&](const ConnectSpec::CharExpr
&y
) {
1238 [&](const MsgVariable
&) {
1242 [&](const StatVariable
&) {
1246 [&](const ConnectSpec::Recl
&) {
1250 [&](const ConnectSpec::Newunit
&) {
1254 [&](const ErrLabel
&) {
1258 [&](const StatusExpr
&) {
1265 void Unparse(const CloseStmt
&x
) { // R1208
1266 Word("CLOSE ("), Walk(x
.v
, ", "), Put(')');
1268 void Before(const CloseStmt::CloseSpec
&x
) { // R1209
1269 common::visit(common::visitors
{
1270 [&](const FileUnitNumber
&) { Word("UNIT="); },
1271 [&](const StatVariable
&) { Word("IOSTAT="); },
1272 [&](const MsgVariable
&) { Word("IOMSG="); },
1273 [&](const ErrLabel
&) { Word("ERR="); },
1274 [&](const StatusExpr
&) { Word("STATUS="); },
1278 void Unparse(const ReadStmt
&x
) { // R1210
1281 Put('('), Walk(x
.iounit
);
1283 Put(", "), Walk(x
.format
);
1285 Walk(", ", x
.controls
, ", ");
1287 } else if (x
.format
) {
1289 if (!x
.items
.empty()) {
1293 Put('('), Walk(x
.controls
, ", "), Put(')');
1295 Walk(" ", x
.items
, ", ");
1297 void Unparse(const WriteStmt
&x
) { // R1211
1302 Put(", "), Walk(x
.format
);
1304 Walk(", ", x
.controls
, ", ");
1306 Walk(x
.controls
, ", ");
1308 Put(')'), Walk(" ", x
.items
, ", ");
1310 void Unparse(const PrintStmt
&x
) { // R1212
1311 Word("PRINT "), Walk(std::get
<Format
>(x
.t
));
1312 Walk(", ", std::get
<std::list
<OutputItem
>>(x
.t
), ", ");
1314 bool Pre(const IoControlSpec
&x
) { // R1213
1315 return common::visit(common::visitors
{
1316 [&](const IoUnit
&) {
1320 [&](const Format
&) {
1328 [&](const IoControlSpec::CharExpr
&y
) {
1332 [&](const IoControlSpec::Asynchronous
&) {
1333 Word("ASYNCHRONOUS=");
1336 [&](const EndLabel
&) {
1340 [&](const EorLabel
&) {
1344 [&](const ErrLabel
&) {
1348 [&](const IdVariable
&) {
1352 [&](const MsgVariable
&) {
1356 [&](const StatVariable
&) {
1360 [&](const IoControlSpec::Pos
&) {
1364 [&](const IoControlSpec::Rec
&) {
1368 [&](const IoControlSpec::Size
&) {
1375 void Unparse(const InputImpliedDo
&x
) { // R1218
1376 Put('('), Walk(std::get
<std::list
<InputItem
>>(x
.t
), ", "), Put(", ");
1377 Walk(std::get
<IoImpliedDoControl
>(x
.t
)), Put(')');
1379 void Unparse(const OutputImpliedDo
&x
) { // R1219
1380 Put('('), Walk(std::get
<std::list
<OutputItem
>>(x
.t
), ", "), Put(", ");
1381 Walk(std::get
<IoImpliedDoControl
>(x
.t
)), Put(')');
1383 void Unparse(const WaitStmt
&x
) { // R1222
1384 Word("WAIT ("), Walk(x
.v
, ", "), Put(')');
1386 void Before(const WaitSpec
&x
) { // R1223
1387 common::visit(common::visitors
{
1388 [&](const FileUnitNumber
&) { Word("UNIT="); },
1389 [&](const EndLabel
&) { Word("END="); },
1390 [&](const EorLabel
&) { Word("EOR="); },
1391 [&](const ErrLabel
&) { Word("ERR="); },
1392 [&](const IdExpr
&) { Word("ID="); },
1393 [&](const MsgVariable
&) { Word("IOMSG="); },
1394 [&](const StatVariable
&) { Word("IOSTAT="); },
1398 void Unparse(const BackspaceStmt
&x
) { // R1224
1399 Word("BACKSPACE ("), Walk(x
.v
, ", "), Put(')');
1401 void Unparse(const EndfileStmt
&x
) { // R1225
1402 Word("ENDFILE ("), Walk(x
.v
, ", "), Put(')');
1404 void Unparse(const RewindStmt
&x
) { // R1226
1405 Word("REWIND ("), Walk(x
.v
, ", "), Put(')');
1407 void Before(const PositionOrFlushSpec
&x
) { // R1227 & R1229
1408 common::visit(common::visitors
{
1409 [&](const FileUnitNumber
&) { Word("UNIT="); },
1410 [&](const MsgVariable
&) { Word("IOMSG="); },
1411 [&](const StatVariable
&) { Word("IOSTAT="); },
1412 [&](const ErrLabel
&) { Word("ERR="); },
1416 void Unparse(const FlushStmt
&x
) { // R1228
1417 Word("FLUSH ("), Walk(x
.v
, ", "), Put(')');
1419 void Unparse(const InquireStmt
&x
) { // R1230
1423 [&](const InquireStmt::Iolength
&y
) {
1424 Word("IOLENGTH="), Walk(y
.t
, ") ");
1426 [&](const std::list
<InquireSpec
> &y
) { Walk(y
, ", "), Put(')'); },
1430 bool Pre(const InquireSpec
&x
) { // R1231
1431 return common::visit(common::visitors
{
1432 [&](const FileUnitNumber
&) {
1436 [&](const FileNameExpr
&) {
1440 [&](const InquireSpec::CharVar
&y
) {
1444 [&](const InquireSpec::IntVar
&y
) {
1448 [&](const InquireSpec::LogVar
&y
) {
1452 [&](const IdExpr
&) {
1456 [&](const ErrLabel
&) {
1464 void Before(const FormatStmt
&) { // R1301
1467 void Unparse(const format::FormatSpecification
&x
) { // R1302, R1303, R1305
1468 Put('('), Walk("", x
.items
, ",", x
.unlimitedItems
.empty() ? "" : ",");
1469 Walk("*(", x
.unlimitedItems
, ",", ")"), Put(')');
1471 void Unparse(const format::FormatItem
&x
) { // R1304, R1306, R1321
1472 if (x
.repeatCount
) {
1473 Walk(*x
.repeatCount
);
1475 common::visit(common::visitors
{
1476 [&](const std::string
&y
) { PutNormalized(y
); },
1477 [&](const std::list
<format::FormatItem
> &y
) {
1478 Walk("(", y
, ",", ")");
1480 [&](const auto &y
) { Walk(y
); },
1485 const format::IntrinsicTypeDataEditDesc
&x
) { // R1307(1/2) - R1311
1488 case format::IntrinsicTypeDataEditDesc::Kind::x: \
1506 Walk(x
.width
), Walk(".", x
.digits
), Walk("E", x
.exponentWidth
);
1508 void Unparse(const format::DerivedTypeDataEditDesc
&x
) { // R1307(2/2), R1312
1510 if (!x
.type
.empty()) {
1511 Put('"'), Put(x
.type
), Put('"');
1513 Walk("(", x
.parameters
, ",", ")");
1515 void Unparse(const format::ControlEditDesc
&x
) { // R1313, R1315-R1320
1517 case format::ControlEditDesc::Kind::T
:
1521 case format::ControlEditDesc::Kind::TL
:
1525 case format::ControlEditDesc::Kind::TR
:
1529 case format::ControlEditDesc::Kind::X
:
1535 case format::ControlEditDesc::Kind::Slash
:
1541 case format::ControlEditDesc::Kind::Colon
:
1544 case format::ControlEditDesc::Kind::P
:
1549 case format::ControlEditDesc::Kind::x: \
1566 case format::ControlEditDesc::Kind::Dollar
:
1569 case format::ControlEditDesc::Kind::Backslash
:
1575 void Before(const MainProgram
&x
) { // R1401
1576 if (!std::get
<std::optional
<Statement
<ProgramStmt
>>>(x
.t
)) {
1580 void Before(const ProgramStmt
&) { // R1402
1581 Word("PROGRAM "), Indent();
1583 void Unparse(const EndProgramStmt
&x
) { // R1403
1584 EndSubprogram("PROGRAM", x
.v
);
1586 void Before(const ModuleStmt
&) { // R1405
1587 Word("MODULE "), Indent();
1589 void Unparse(const EndModuleStmt
&x
) { // R1406
1590 EndSubprogram("MODULE", x
.v
);
1592 void Unparse(const UseStmt
&x
) { // R1409
1593 Word("USE"), Walk(", ", x
.nature
), Put(" :: "), Walk(x
.moduleName
);
1596 [&](const std::list
<Rename
> &y
) { Walk(", ", y
, ", "); },
1597 [&](const std::list
<Only
> &y
) { Walk(", ONLY: ", y
, ", "); },
1601 void Unparse(const Rename
&x
) { // R1411
1602 common::visit(common::visitors
{
1603 [&](const Rename::Names
&y
) { Walk(y
.t
, " => "); },
1604 [&](const Rename::Operators
&y
) {
1605 Word("OPERATOR("), Walk(y
.t
, ") => OPERATOR("),
1611 void Unparse(const SubmoduleStmt
&x
) { // R1417
1612 Word("SUBMODULE ("), WalkTupleElements(x
.t
, ")"), Indent();
1614 void Unparse(const ParentIdentifier
&x
) { // R1418
1615 Walk(std::get
<Name
>(x
.t
)), Walk(":", std::get
<std::optional
<Name
>>(x
.t
));
1617 void Unparse(const EndSubmoduleStmt
&x
) { // R1419
1618 EndSubprogram("SUBMODULE", x
.v
);
1620 void Unparse(const BlockDataStmt
&x
) { // R1421
1621 Word("BLOCK DATA"), Walk(" ", x
.v
), Indent();
1623 void Unparse(const EndBlockDataStmt
&x
) { // R1422
1624 EndSubprogram("BLOCK DATA", x
.v
);
1627 void Unparse(const InterfaceStmt
&x
) { // R1503
1628 common::visit(common::visitors
{
1629 [&](const std::optional
<GenericSpec
> &y
) {
1630 Word("INTERFACE"), Walk(" ", y
);
1632 [&](const Abstract
&) { Word("ABSTRACT INTERFACE"); },
1637 void Unparse(const EndInterfaceStmt
&x
) { // R1504
1638 Outdent(), Word("END INTERFACE"), Walk(" ", x
.v
);
1640 void Unparse(const ProcedureStmt
&x
) { // R1506
1641 if (std::get
<ProcedureStmt::Kind
>(x
.t
) ==
1642 ProcedureStmt::Kind::ModuleProcedure
) {
1645 Word("PROCEDURE :: ");
1646 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
1648 void Before(const GenericSpec
&x
) { // R1508, R1509
1651 [&](const DefinedOperator
&) { Word("OPERATOR("); },
1652 [&](const GenericSpec::Assignment
&) { Word("ASSIGNMENT(=)"); },
1653 [&](const GenericSpec::ReadFormatted
&) {
1654 Word("READ(FORMATTED)");
1656 [&](const GenericSpec::ReadUnformatted
&) {
1657 Word("READ(UNFORMATTED)");
1659 [&](const GenericSpec::WriteFormatted
&) {
1660 Word("WRITE(FORMATTED)");
1662 [&](const GenericSpec::WriteUnformatted
&) {
1663 Word("WRITE(UNFORMATTED)");
1665 [](const auto &) {},
1669 void Post(const GenericSpec
&x
) {
1670 common::visit(common::visitors
{
1671 [&](const DefinedOperator
&) { Put(')'); },
1672 [](const auto &) {},
1676 void Unparse(const GenericStmt
&x
) { // R1510
1677 Word("GENERIC"), Walk(", ", std::get
<std::optional
<AccessSpec
>>(x
.t
));
1678 Put(" :: "), Walk(std::get
<GenericSpec
>(x
.t
)), Put(" => ");
1679 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
1681 void Unparse(const ExternalStmt
&x
) { // R1511
1682 Word("EXTERNAL :: "), Walk(x
.v
, ", ");
1684 void Unparse(const ProcedureDeclarationStmt
&x
) { // R1512
1685 Word("PROCEDURE("), Walk(std::get
<std::optional
<ProcInterface
>>(x
.t
));
1686 Put(')'), Walk(", ", std::get
<std::list
<ProcAttrSpec
>>(x
.t
), ", ");
1687 Put(" :: "), Walk(std::get
<std::list
<ProcDecl
>>(x
.t
), ", ");
1689 void Unparse(const ProcDecl
&x
) { // R1515
1690 Walk(std::get
<Name
>(x
.t
));
1691 Walk(" => ", std::get
<std::optional
<ProcPointerInit
>>(x
.t
));
1693 void Unparse(const IntrinsicStmt
&x
) { // R1519
1694 Word("INTRINSIC :: "), Walk(x
.v
, ", ");
1696 void Unparse(const CallStmt::Chevrons
&x
) { // CUDA
1697 Walk(std::get
<0>(x
.t
)); // grid
1698 Word(","), Walk(std::get
<1>(x
.t
)); // block
1699 Walk(",", std::get
<2>(x
.t
)); // bytes
1700 Walk(",", std::get
<3>(x
.t
)); // stream
1702 void Unparse(const FunctionReference
&x
) { // R1520
1703 Walk(std::get
<ProcedureDesignator
>(x
.v
.t
));
1704 Put('('), Walk(std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
), ", "), Put(')');
1706 void Unparse(const CallStmt
&x
) { // R1521
1707 if (asFortran_
&& x
.typedCall
.get()) {
1709 asFortran_
->call(out_
, *x
.typedCall
);
1712 const auto &pd
{std::get
<ProcedureDesignator
>(x
.call
.t
)};
1713 Word("CALL "), Walk(pd
);
1714 Walk("<<<", x
.chevrons
, ">>>");
1715 const auto &args
{std::get
<std::list
<ActualArgSpec
>>(x
.call
.t
)};
1717 if (std::holds_alternative
<ProcComponentRef
>(pd
.u
)) {
1718 Put("()"); // pgf90 crashes on CALL to tbp without parentheses
1721 Walk("(", args
, ", ", ")");
1725 void Unparse(const ActualArgSpec
&x
) { // R1523
1726 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
1727 Walk(std::get
<ActualArg
>(x
.t
));
1729 void Unparse(const ActualArg::PercentRef
&x
) { // R1524
1730 Word("%REF("), Walk(x
.v
), Put(')');
1732 void Unparse(const ActualArg::PercentVal
&x
) {
1733 Word("%VAL("), Walk(x
.v
), Put(')');
1735 void Before(const AltReturnSpec
&) { // R1525
1738 void Post(const PrefixSpec::Elemental
) { Word("ELEMENTAL"); } // R1527
1739 void Post(const PrefixSpec::Impure
) { Word("IMPURE"); }
1740 void Post(const PrefixSpec::Module
) { Word("MODULE"); }
1741 void Post(const PrefixSpec::Non_Recursive
) { Word("NON_RECURSIVE"); }
1742 void Post(const PrefixSpec::Pure
) { Word("PURE"); }
1743 void Post(const PrefixSpec::Recursive
) { Word("RECURSIVE"); }
1744 void Unparse(const PrefixSpec::Attributes
&x
) {
1745 Word("ATTRIBUTES("), Walk(x
.v
), Word(")");
1747 void Unparse(const PrefixSpec::Launch_Bounds
&x
) {
1748 Word("LAUNCH_BOUNDS("), Walk(x
.v
), Word(")");
1750 void Unparse(const PrefixSpec::Cluster_Dims
&x
) {
1751 Word("CLUSTER_DIMS("), Walk(x
.v
), Word(")");
1753 void Unparse(const FunctionStmt
&x
) { // R1530
1754 Walk("", std::get
<std::list
<PrefixSpec
>>(x
.t
), " ", " ");
1755 Word("FUNCTION "), Walk(std::get
<Name
>(x
.t
)), Put("(");
1756 Walk(std::get
<std::list
<Name
>>(x
.t
), ", "), Put(')');
1757 Walk(" ", std::get
<std::optional
<Suffix
>>(x
.t
)), Indent();
1759 void Unparse(const Suffix
&x
) { // R1532
1761 Word("RESULT("), Walk(x
.resultName
), Put(')');
1762 Walk(" ", x
.binding
);
1767 void Unparse(const EndFunctionStmt
&x
) { // R1533
1768 EndSubprogram("FUNCTION", x
.v
);
1770 void Unparse(const SubroutineStmt
&x
) { // R1535
1771 Walk("", std::get
<std::list
<PrefixSpec
>>(x
.t
), " ", " ");
1772 Word("SUBROUTINE "), Walk(std::get
<Name
>(x
.t
));
1773 const auto &args
{std::get
<std::list
<DummyArg
>>(x
.t
)};
1774 const auto &bind
{std::get
<std::optional
<LanguageBindingSpec
>>(x
.t
)};
1778 Walk(" (", args
, ", ", ")");
1783 void Unparse(const EndSubroutineStmt
&x
) { // R1537
1784 EndSubprogram("SUBROUTINE", x
.v
);
1786 void Before(const MpSubprogramStmt
&) { // R1539
1787 Word("MODULE PROCEDURE "), Indent();
1789 void Unparse(const EndMpSubprogramStmt
&x
) { // R1540
1790 EndSubprogram("PROCEDURE", x
.v
);
1792 void Unparse(const EntryStmt
&x
) { // R1541
1793 Word("ENTRY "), Walk(std::get
<Name
>(x
.t
)), Put("(");
1794 Walk(std::get
<std::list
<DummyArg
>>(x
.t
), ", "), Put(")");
1795 Walk(" ", std::get
<std::optional
<Suffix
>>(x
.t
));
1797 void Unparse(const ReturnStmt
&x
) { // R1542
1798 Word("RETURN"), Walk(" ", x
.v
);
1800 void Unparse(const ContainsStmt
&) { // R1543
1805 void Unparse(const StmtFunctionStmt
&x
) { // R1544
1806 Walk(std::get
<Name
>(x
.t
)), Put('(');
1807 Walk(std::get
<std::list
<Name
>>(x
.t
), ", "), Put(") = ");
1808 Walk(std::get
<Scalar
<Expr
>>(x
.t
));
1811 // Directives, extensions, and deprecated constructs
1812 void Unparse(const CompilerDirective
&x
) {
1815 [&](const std::list
<CompilerDirective::IgnoreTKR
> &tkr
) {
1816 Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty
1817 Walk(" ", tkr
, ", ");
1819 [&](const CompilerDirective::LoopCount
&lcount
) {
1820 Walk("!DIR$ LOOP COUNT (", lcount
.v
, ", ", ")");
1822 [&](const std::list
<CompilerDirective::NameValue
> &names
) {
1823 Walk("!DIR$ ", names
, " ");
1829 void Unparse(const CompilerDirective::IgnoreTKR
&x
) {
1830 if (const auto &maybeList
{
1831 std::get
<std::optional
<std::list
<const char *>>>(x
.t
)}) {
1833 for (const char *tkr
: *maybeList
) {
1838 Walk(std::get
<Name
>(x
.t
));
1840 void Unparse(const CompilerDirective::NameValue
&x
) {
1841 Walk(std::get
<Name
>(x
.t
));
1842 Walk("=", std::get
<std::optional
<std::uint64_t>>(x
.t
));
1845 // OpenACC Directives & Clauses
1846 void Unparse(const AccAtomicCapture
&x
) {
1848 Word("!$ACC CAPTURE");
1851 Walk(std::get
<AccAtomicCapture::Stmt1
>(x
.t
));
1853 Walk(std::get
<AccAtomicCapture::Stmt2
>(x
.t
));
1855 Word("!$ACC END ATOMIC\n");
1858 void Unparse(const AccAtomicRead
&x
) {
1860 Word("!$ACC ATOMIC READ");
1863 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1865 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1868 void Unparse(const AccAtomicWrite
&x
) {
1870 Word("!$ACC ATOMIC WRITE");
1873 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1875 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1878 void Unparse(const AccAtomicUpdate
&x
) {
1880 Word("!$ACC ATOMIC UPDATE");
1883 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1885 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1888 void Unparse(const llvm::acc::Directive
&x
) {
1889 Word(llvm::acc::getOpenACCDirectiveName(x
).str());
1891 #define GEN_FLANG_CLAUSE_UNPARSE
1892 #include "llvm/Frontend/OpenACC/ACC.inc"
1893 void Unparse(const AccObjectListWithModifier
&x
) {
1894 Walk(std::get
<std::optional
<AccDataModifier
>>(x
.t
), ":");
1895 Walk(std::get
<AccObjectList
>(x
.t
));
1897 void Unparse(const AccBindClause
&x
) {
1898 common::visit(common::visitors
{
1899 [&](const Name
&y
) { Walk(y
); },
1900 [&](const ScalarDefaultCharExpr
&y
) { Walk(y
); },
1904 void Unparse(const AccDefaultClause
&x
) {
1906 case llvm::acc::DefaultValue::ACC_Default_none
:
1909 case llvm::acc::DefaultValue::ACC_Default_present
:
1914 void Unparse(const AccClauseList
&x
) { Walk(" ", x
.v
, " "); }
1915 void Unparse(const AccGangArgList
&x
) { Walk(x
.v
, ","); }
1916 void Before(const AccSizeExpr
&x
) {
1920 void Before(const AccGangArg
&x
) {
1921 common::visit(common::visitors
{
1922 [&](const AccGangArg::Num
&) { Word("NUM:"); },
1923 [&](const AccGangArg::Dim
&) { Word("DIM:"); },
1924 [&](const AccGangArg::Static
&) { Word("STATIC:"); },
1925 [](const StatOrErrmsg
&) {},
1929 void Unparse(const AccCollapseArg
&x
) {
1930 const auto &force
{std::get
<bool>(x
.t
)};
1931 const auto &collapseValue
{std::get
<parser::ScalarIntConstantExpr
>(x
.t
)};
1935 Walk(collapseValue
);
1937 void Unparse(const OpenACCBlockConstruct
&x
) {
1940 Walk(std::get
<AccBeginBlockDirective
>(x
.t
));
1943 Walk(std::get
<Block
>(x
.t
), "");
1946 Walk(std::get
<AccEndBlockDirective
>(x
.t
));
1950 void Unparse(const OpenACCLoopConstruct
&x
) {
1953 Walk(std::get
<AccBeginLoopDirective
>(x
.t
));
1956 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
1958 void Unparse(const AccBeginLoopDirective
&x
) {
1959 Walk(std::get
<AccLoopDirective
>(x
.t
));
1960 Walk(std::get
<AccClauseList
>(x
.t
));
1962 void Unparse(const OpenACCStandaloneConstruct
&x
) {
1965 Walk(std::get
<AccStandaloneDirective
>(x
.t
));
1966 Walk(std::get
<AccClauseList
>(x
.t
));
1970 void Unparse(const OpenACCStandaloneDeclarativeConstruct
&x
) {
1973 Walk(std::get
<AccDeclarativeDirective
>(x
.t
));
1974 Walk(std::get
<AccClauseList
>(x
.t
));
1978 void Unparse(const OpenACCCombinedConstruct
&x
) {
1981 Walk(std::get
<AccBeginCombinedDirective
>(x
.t
));
1984 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
1986 Walk("!$ACC END ", std::get
<std::optional
<AccEndCombinedDirective
>>(x
.t
),
1990 void Unparse(const OpenACCRoutineConstruct
&x
) {
1992 Word("!$ACC ROUTINE");
1993 Walk("(", std::get
<std::optional
<Name
>>(x
.t
), ")");
1994 Walk(std::get
<AccClauseList
>(x
.t
));
1998 void Unparse(const AccObject
&x
) {
1999 common::visit(common::visitors
{
2000 [&](const Designator
&y
) { Walk(y
); },
2001 [&](const Name
&y
) { Put("/"), Walk(y
), Put("/"); },
2005 void Unparse(const AccObjectList
&x
) { Walk(x
.v
, ","); }
2006 void Unparse(const AccObjectListWithReduction
&x
) {
2007 Walk(std::get
<AccReductionOperator
>(x
.t
));
2009 Walk(std::get
<AccObjectList
>(x
.t
));
2011 void Unparse(const OpenACCCacheConstruct
&x
) {
2015 Walk(std::get
<AccObjectListWithModifier
>(x
.t
));
2020 void Unparse(const AccWaitArgument
&x
) {
2021 Walk("DEVNUM:", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
), ":");
2022 Walk(std::get
<std::list
<ScalarIntExpr
>>(x
.t
), ",");
2024 void Unparse(const OpenACCWaitConstruct
&x
) {
2028 Walk(std::get
<std::optional
<AccWaitArgument
>>(x
.t
));
2029 Walk(std::get
<AccClauseList
>(x
.t
));
2035 // OpenMP Clauses & Directives
2036 void Unparse(const OmpObject
&x
) {
2037 common::visit(common::visitors
{
2038 [&](const Designator
&y
) { Walk(y
); },
2039 [&](const Name
&y
) { Put("/"), Walk(y
), Put("/"); },
2043 void Unparse(const OmpMapType::Always
&) { Word("ALWAYS,"); }
2044 void Unparse(const OmpMapClause
&x
) {
2045 Walk(std::get
<std::optional
<OmpMapType
>>(x
.t
), ":");
2046 Walk(std::get
<OmpObjectList
>(x
.t
));
2048 void Unparse(const OmpScheduleModifier
&x
) {
2049 Walk(std::get
<OmpScheduleModifier::Modifier1
>(x
.t
));
2050 Walk(",", std::get
<std::optional
<OmpScheduleModifier::Modifier2
>>(x
.t
));
2052 void Unparse(const OmpScheduleClause
&x
) {
2053 Walk(std::get
<std::optional
<OmpScheduleModifier
>>(x
.t
), ":");
2054 Walk(std::get
<OmpScheduleClause::ScheduleType
>(x
.t
));
2055 Walk(",", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
2057 void Unparse(const OmpDeviceClause
&x
) {
2058 Walk(std::get
<std::optional
<OmpDeviceClause::DeviceModifier
>>(x
.t
), ":");
2059 Walk(std::get
<ScalarIntExpr
>(x
.t
));
2061 void Unparse(const OmpAlignedClause
&x
) {
2062 Walk(std::get
<OmpObjectList
>(x
.t
));
2064 Walk(std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
2066 void Unparse(const OmpIfClause
&x
) {
2067 Walk(std::get
<std::optional
<OmpIfClause::DirectiveNameModifier
>>(x
.t
), ":");
2068 Walk(std::get
<ScalarLogicalExpr
>(x
.t
));
2070 void Unparse(const OmpLinearClause::WithoutModifier
&x
) {
2071 Walk(x
.names
, ", ");
2074 void Unparse(const OmpLinearClause::WithModifier
&x
) {
2075 Walk(x
.modifier
), Put("("), Walk(x
.names
, ","), Put(")");
2078 void Unparse(const OmpReductionClause
&x
) {
2079 Walk(std::get
<OmpReductionOperator
>(x
.t
));
2081 Walk(std::get
<OmpObjectList
>(x
.t
));
2083 void Unparse(const OmpInReductionClause
&x
) {
2084 Walk(std::get
<OmpReductionOperator
>(x
.t
));
2086 Walk(std::get
<OmpObjectList
>(x
.t
));
2088 void Unparse(const OmpAllocateClause
&x
) {
2090 std::get
<std::optional
<OmpAllocateClause::AllocateModifier
>>(x
.t
), ":");
2091 Walk(std::get
<OmpObjectList
>(x
.t
));
2093 void Unparse(const OmpAllocateClause::AllocateModifier
&x
) {
2096 [&](const OmpAllocateClause::AllocateModifier::Allocator
&y
) {
2099 [&](const OmpAllocateClause::AllocateModifier::ComplexModifier
&y
) {
2101 Walk(std::get
<OmpAllocateClause::AllocateModifier::Allocator
>(
2105 Walk(std::get
<OmpAllocateClause::AllocateModifier::Align
>(y
.t
));
2107 [&](const OmpAllocateClause::AllocateModifier::Align
&y
) {
2113 void Unparse(const OmpAllocateClause::AllocateModifier::Align
&x
) {
2118 void Unparse(const OmpOrderClause
&x
) {
2119 Walk(std::get
<std::optional
<OmpOrderModifier
>>(x
.t
), ":");
2120 Walk(std::get
<OmpOrderClause::Type
>(x
.t
));
2122 void Unparse(const OmpDependSinkVecLength
&x
) {
2123 Walk(std::get
<DefinedOperator
>(x
.t
));
2124 Walk(std::get
<ScalarIntConstantExpr
>(x
.t
));
2126 void Unparse(const OmpDependSinkVec
&x
) {
2127 Walk(std::get
<Name
>(x
.t
));
2128 Walk(std::get
<std::optional
<OmpDependSinkVecLength
>>(x
.t
));
2130 void Unparse(const OmpDependClause::InOut
&x
) {
2132 Walk(std::get
<OmpDependenceType
>(x
.t
));
2134 Walk(std::get
<std::list
<Designator
>>(x
.t
), ",");
2137 bool Pre(const OmpDependClause
&x
) {
2138 return common::visit(
2140 [&](const OmpDependClause::Source
&) {
2144 [&](const OmpDependClause::Sink
&y
) {
2150 [&](const OmpDependClause::InOut
&) { return true; },
2154 void Unparse(const OmpDefaultmapClause
&x
) {
2155 Walk(std::get
<OmpDefaultmapClause::ImplicitBehavior
>(x
.t
));
2157 std::get
<std::optional
<OmpDefaultmapClause::VariableCategory
>>(x
.t
));
2159 #define GEN_FLANG_CLAUSE_UNPARSE
2160 #include "llvm/Frontend/OpenMP/OMP.inc"
2161 void Unparse(const OmpLoopDirective
&x
) {
2163 case llvm::omp::Directive::OMPD_distribute
:
2164 Word("DISTRIBUTE ");
2166 case llvm::omp::Directive::OMPD_distribute_parallel_do
:
2167 Word("DISTRIBUTE PARALLEL DO ");
2169 case llvm::omp::Directive::OMPD_distribute_parallel_do_simd
:
2170 Word("DISTRIBUTE PARALLEL DO SIMD ");
2172 case llvm::omp::Directive::OMPD_distribute_simd
:
2173 Word("DISTRIBUTE SIMD ");
2175 case llvm::omp::Directive::OMPD_do
:
2178 case llvm::omp::Directive::OMPD_do_simd
:
2181 case llvm::omp::Directive::OMPD_parallel_do
:
2182 Word("PARALLEL DO ");
2184 case llvm::omp::Directive::OMPD_parallel_do_simd
:
2185 Word("PARALLEL DO SIMD ");
2187 case llvm::omp::Directive::OMPD_simd
:
2190 case llvm::omp::Directive::OMPD_target_parallel_do
:
2191 Word("TARGET PARALLEL DO ");
2193 case llvm::omp::Directive::OMPD_target_parallel_do_simd
:
2194 Word("TARGET PARALLEL DO SIMD ");
2196 case llvm::omp::Directive::OMPD_target_teams_distribute
:
2197 Word("TARGET TEAMS DISTRIBUTE ");
2199 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do
:
2200 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO ");
2202 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd
:
2203 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2205 case llvm::omp::Directive::OMPD_target_teams_distribute_simd
:
2206 Word("TARGET TEAMS DISTRIBUTE SIMD ");
2208 case llvm::omp::Directive::OMPD_target_simd
:
2209 Word("TARGET SIMD ");
2211 case llvm::omp::Directive::OMPD_taskloop
:
2214 case llvm::omp::Directive::OMPD_taskloop_simd
:
2215 Word("TASKLOOP SIMD ");
2217 case llvm::omp::Directive::OMPD_teams_distribute
:
2218 Word("TEAMS DISTRIBUTE ");
2220 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do
:
2221 Word("TEAMS DISTRIBUTE PARALLEL DO ");
2223 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd
:
2224 Word("TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2226 case llvm::omp::Directive::OMPD_teams_distribute_simd
:
2227 Word("TEAMS DISTRIBUTE SIMD ");
2229 case llvm::omp::Directive::OMPD_tile
:
2232 case llvm::omp::Directive::OMPD_unroll
:
2239 void Unparse(const OmpObjectList
&x
) { Walk(x
.v
, ","); }
2240 void Unparse(const OmpSimpleStandaloneDirective
&x
) {
2242 case llvm::omp::Directive::OMPD_barrier
:
2245 case llvm::omp::Directive::OMPD_taskwait
:
2248 case llvm::omp::Directive::OMPD_taskyield
:
2251 case llvm::omp::Directive::OMPD_target_enter_data
:
2252 Word("TARGET ENTER DATA ");
2254 case llvm::omp::Directive::OMPD_target_exit_data
:
2255 Word("TARGET EXIT DATA ");
2257 case llvm::omp::Directive::OMPD_target_update
:
2258 Word("TARGET UPDATE ");
2260 case llvm::omp::Directive::OMPD_ordered
:
2264 // Nothing to be done
2268 void Unparse(const OmpBlockDirective
&x
) {
2270 case llvm::omp::Directive::OMPD_master
:
2273 case llvm::omp::Directive::OMPD_ordered
:
2276 case llvm::omp::Directive::OMPD_parallel_workshare
:
2277 Word("PARALLEL WORKSHARE ");
2279 case llvm::omp::Directive::OMPD_parallel
:
2282 case llvm::omp::Directive::OMPD_single
:
2285 case llvm::omp::Directive::OMPD_target_data
:
2286 Word("TARGET DATA ");
2288 case llvm::omp::Directive::OMPD_target_parallel
:
2289 Word("TARGET PARALLEL ");
2291 case llvm::omp::Directive::OMPD_target_teams
:
2292 Word("TARGET TEAMS ");
2294 case llvm::omp::Directive::OMPD_target
:
2297 case llvm::omp::Directive::OMPD_taskgroup
:
2300 case llvm::omp::Directive::OMPD_task
:
2303 case llvm::omp::Directive::OMPD_teams
:
2306 case llvm::omp::Directive::OMPD_workshare
:
2310 // Nothing to be done
2315 void Unparse(const OmpAtomicDefaultMemOrderClause
&x
) {
2316 Word(ToUpperCaseLetters(common::EnumToString(x
.v
)));
2319 void Unparse(const OmpAtomicClauseList
&x
) { Walk(" ", x
.v
, " "); }
2321 void Unparse(const OmpAtomic
&x
) {
2323 Word("!$OMP ATOMIC");
2324 Walk(std::get
<OmpAtomicClauseList
>(x
.t
));
2327 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2329 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2332 void Unparse(const OmpAtomicCapture
&x
) {
2334 Word("!$OMP ATOMIC");
2335 Walk(std::get
<0>(x
.t
));
2337 Walk(std::get
<2>(x
.t
));
2340 Walk(std::get
<OmpAtomicCapture::Stmt1
>(x
.t
));
2342 Walk(std::get
<OmpAtomicCapture::Stmt2
>(x
.t
));
2344 Word("!$OMP END ATOMIC\n");
2347 void Unparse(const OmpAtomicRead
&x
) {
2349 Word("!$OMP ATOMIC");
2350 Walk(std::get
<0>(x
.t
));
2352 Walk(std::get
<2>(x
.t
));
2355 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2357 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2360 void Unparse(const OmpAtomicUpdate
&x
) {
2362 Word("!$OMP ATOMIC");
2363 Walk(std::get
<0>(x
.t
));
2365 Walk(std::get
<2>(x
.t
));
2368 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2370 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2373 void Unparse(const OmpAtomicWrite
&x
) {
2375 Word("!$OMP ATOMIC");
2376 Walk(std::get
<0>(x
.t
));
2378 Walk(std::get
<2>(x
.t
));
2381 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2383 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2386 void Unparse(const OpenMPExecutableAllocate
&x
) {
2387 const auto &fields
=
2388 std::get
<std::optional
<std::list
<parser::OpenMPDeclarativeAllocate
>>>(
2391 for (const auto &decl
: *fields
) {
2396 Word("!$OMP ALLOCATE");
2397 Walk(" (", std::get
<std::optional
<OmpObjectList
>>(x
.t
), ")");
2398 Walk(std::get
<OmpClauseList
>(x
.t
));
2401 Walk(std::get
<Statement
<AllocateStmt
>>(x
.t
));
2403 void Unparse(const OpenMPDeclarativeAllocate
&x
) {
2405 Word("!$OMP ALLOCATE");
2407 Walk(std::get
<OmpObjectList
>(x
.t
));
2409 Walk(std::get
<OmpClauseList
>(x
.t
));
2413 void Unparse(const OmpEndAllocators
&x
) {
2415 Word("!$OMP END ALLOCATE");
2419 void Unparse(const OpenMPAllocatorsConstruct
&x
) {
2421 Word("!$OMP ALLOCATE");
2422 Walk(std::get
<OmpClauseList
>(x
.t
));
2425 Walk(std::get
<Statement
<AllocateStmt
>>(x
.t
));
2426 if (const auto &end
= std::get
<std::optional
<OmpEndAllocators
>>(x
.t
)) {
2430 void Unparse(const OmpCriticalDirective
&x
) {
2432 Word("!$OMP CRITICAL");
2433 Walk(" (", std::get
<std::optional
<Name
>>(x
.t
), ")");
2434 Walk(std::get
<OmpClauseList
>(x
.t
));
2438 void Unparse(const OmpEndCriticalDirective
&x
) {
2440 Word("!$OMP END CRITICAL");
2441 Walk(" (", std::get
<std::optional
<Name
>>(x
.t
), ")");
2445 void Unparse(const OpenMPCriticalConstruct
&x
) {
2446 Walk(std::get
<OmpCriticalDirective
>(x
.t
));
2447 Walk(std::get
<Block
>(x
.t
), "");
2448 Walk(std::get
<OmpEndCriticalDirective
>(x
.t
));
2450 void Unparse(const OmpDeclareTargetWithList
&x
) {
2451 Put("("), Walk(x
.v
), Put(")");
2453 void Unparse(const OmpReductionInitializerClause
&x
) {
2454 Word(" INITIALIZER(OMP_PRIV = ");
2458 void Unparse(const OmpReductionCombiner::FunctionCombiner
&x
) {
2459 const auto &pd
= std::get
<ProcedureDesignator
>(x
.v
.t
);
2460 const auto &args
= std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
);
2463 if (std::holds_alternative
<ProcComponentRef
>(pd
.u
)) {
2467 Walk("(", args
, ", ", ")");
2470 void Unparse(const OpenMPDeclareReductionConstruct
&x
) {
2472 Walk(std::get
<OmpReductionOperator
>(x
.t
)), Put(" : ");
2473 Walk(std::get
<std::list
<DeclarationTypeSpec
>>(x
.t
), ","), Put(" : ");
2474 Walk(std::get
<OmpReductionCombiner
>(x
.t
));
2476 Walk(std::get
<std::optional
<OmpReductionInitializerClause
>>(x
.t
));
2478 bool Pre(const OpenMPDeclarativeConstruct
&x
) {
2481 return common::visit(
2483 [&](const OpenMPDeclarativeAllocate
&z
) {
2485 Walk(std::get
<OmpObjectList
>(z
.t
));
2487 Walk(std::get
<OmpClauseList
>(z
.t
));
2492 [&](const OpenMPDeclareReductionConstruct
&) {
2493 Word("DECLARE REDUCTION ");
2496 [&](const OpenMPDeclareSimdConstruct
&y
) {
2497 Word("DECLARE SIMD ");
2498 Walk("(", std::get
<std::optional
<Name
>>(y
.t
), ")");
2499 Walk(std::get
<OmpClauseList
>(y
.t
));
2504 [&](const OpenMPDeclareTargetConstruct
&) {
2505 Word("DECLARE TARGET ");
2508 [&](const OpenMPRequiresConstruct
&y
) {
2510 Walk(std::get
<OmpClauseList
>(y
.t
));
2515 [&](const OpenMPThreadprivate
&) {
2516 Word("THREADPRIVATE (");
2522 void Post(const OpenMPDeclarativeConstruct
&) {
2526 void Post(const OpenMPThreadprivate
&) {
2530 void Unparse(const OmpSectionsDirective
&x
) {
2532 case llvm::omp::Directive::OMPD_sections
:
2535 case llvm::omp::Directive::OMPD_parallel_sections
:
2536 Word("PARALLEL SECTIONS ");
2542 void Unparse(const OmpSectionBlocks
&x
) {
2543 for (const auto &y
: x
.v
) {
2545 Word("!$OMP SECTION");
2548 // y.u is an OpenMPSectionConstruct
2550 Walk(std::get
<OpenMPSectionConstruct
>(y
.u
).v
, "");
2553 void Unparse(const OpenMPSectionsConstruct
&x
) {
2556 Walk(std::get
<OmpBeginSectionsDirective
>(x
.t
));
2559 Walk(std::get
<OmpSectionBlocks
>(x
.t
));
2562 Walk(std::get
<OmpEndSectionsDirective
>(x
.t
));
2566 void Unparse(const OpenMPCancellationPointConstruct
&x
) {
2568 Word("!$OMP CANCELLATION POINT ");
2569 Walk(std::get
<OmpCancelType
>(x
.t
));
2573 void Unparse(const OpenMPCancelConstruct
&x
) {
2575 Word("!$OMP CANCEL ");
2576 Walk(std::get
<OmpCancelType
>(x
.t
));
2577 Walk(std::get
<std::optional
<OpenMPCancelConstruct::If
>>(x
.t
));
2581 void Unparse(const OmpMemoryOrderClause
&x
) { Walk(x
.v
); }
2582 void Unparse(const OmpAtomicClause
&x
) {
2583 common::visit(common::visitors
{
2584 [&](const OmpMemoryOrderClause
&y
) { Walk(y
); },
2585 [&](const OmpClause
&z
) { Walk(z
); },
2589 void Unparse(const OpenMPFlushConstruct
&x
) {
2591 Word("!$OMP FLUSH ");
2592 Walk(std::get
<std::optional
<std::list
<OmpMemoryOrderClause
>>>(x
.t
));
2593 Walk(" (", std::get
<std::optional
<OmpObjectList
>>(x
.t
), ")");
2597 void Unparse(const OmpEndLoopDirective
&x
) {
2600 Walk(std::get
<OmpLoopDirective
>(x
.t
));
2601 Walk(std::get
<OmpClauseList
>(x
.t
));
2605 void Unparse(const OmpClauseList
&x
) { Walk(" ", x
.v
, " "); }
2606 void Unparse(const OpenMPSimpleStandaloneConstruct
&x
) {
2609 Walk(std::get
<OmpSimpleStandaloneDirective
>(x
.t
));
2610 Walk(std::get
<OmpClauseList
>(x
.t
));
2614 void Unparse(const OpenMPBlockConstruct
&x
) {
2617 Walk(std::get
<OmpBeginBlockDirective
>(x
.t
));
2620 Walk(std::get
<Block
>(x
.t
), "");
2623 Walk(std::get
<OmpEndBlockDirective
>(x
.t
));
2627 void Unparse(const OpenMPLoopConstruct
&x
) {
2630 Walk(std::get
<OmpBeginLoopDirective
>(x
.t
));
2633 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
2634 Walk(std::get
<std::optional
<OmpEndLoopDirective
>>(x
.t
));
2636 void Unparse(const BasedPointer
&x
) {
2637 Put('('), Walk(std::get
<0>(x
.t
)), Put(","), Walk(std::get
<1>(x
.t
));
2638 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")"), Put(')');
2640 void Unparse(const BasedPointerStmt
&x
) { Walk("POINTER ", x
.v
, ","); }
2641 void Unparse(const CUDAAttributesStmt
&x
) {
2642 Word("ATTRIBUTES("), Walk(std::get
<common::CUDADataAttr
>(x
.t
));
2643 Word(") "), Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
2645 void Post(const StructureField
&x
) {
2646 if (const auto *def
{std::get_if
<Statement
<DataComponentDefStmt
>>(&x
.u
)}) {
2647 for (const auto &item
:
2648 std::get
<std::list
<ComponentOrFill
>>(def
->statement
.t
)) {
2649 if (const auto *comp
{std::get_if
<ComponentDecl
>(&item
.u
)}) {
2650 structureComponents_
.insert(std::get
<Name
>(comp
->t
).source
);
2655 void Unparse(const StructureStmt
&x
) {
2657 // The name, if present, includes the /slashes/
2658 Walk(std::get
<std::optional
<Name
>>(x
.t
));
2659 Walk(" ", std::get
<std::list
<EntityDecl
>>(x
.t
), ", ");
2662 void Post(const Union::UnionStmt
&) { Word("UNION"), Indent(); }
2663 void Post(const Union::EndUnionStmt
&) { Outdent(), Word("END UNION"); }
2664 void Post(const Map::MapStmt
&) { Word("MAP"), Indent(); }
2665 void Post(const Map::EndMapStmt
&) { Outdent(), Word("END MAP"); }
2666 void Post(const StructureDef::EndStructureStmt
&) {
2667 Outdent(), Word("END STRUCTURE");
2669 void Unparse(const OldParameterStmt
&x
) {
2670 Word("PARAMETER "), Walk(x
.v
, ", ");
2672 void Unparse(const ArithmeticIfStmt
&x
) {
2673 Word("IF ("), Walk(std::get
<Expr
>(x
.t
)), Put(") ");
2674 Walk(std::get
<1>(x
.t
)), Put(", ");
2675 Walk(std::get
<2>(x
.t
)), Put(", ");
2676 Walk(std::get
<3>(x
.t
));
2678 void Unparse(const AssignStmt
&x
) {
2679 Word("ASSIGN "), Walk(std::get
<Label
>(x
.t
));
2680 Word(" TO "), Walk(std::get
<Name
>(x
.t
));
2682 void Unparse(const AssignedGotoStmt
&x
) {
2683 Word("GO TO "), Walk(std::get
<Name
>(x
.t
));
2684 Walk(", (", std::get
<std::list
<Label
>>(x
.t
), ", ", ")");
2686 void Unparse(const PauseStmt
&x
) { Word("PAUSE"), Walk(" ", x
.v
); }
2688 #define WALK_NESTED_ENUM(CLASS, ENUM) \
2689 void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); }
2690 WALK_NESTED_ENUM(AccDataModifier
, Modifier
)
2691 WALK_NESTED_ENUM(AccessSpec
, Kind
) // R807
2692 WALK_NESTED_ENUM(AccReductionOperator
, Operator
)
2693 WALK_NESTED_ENUM(common
, TypeParamAttr
) // R734
2694 WALK_NESTED_ENUM(common
, CUDADataAttr
) // CUDA
2695 WALK_NESTED_ENUM(common
, CUDASubprogramAttrs
) // CUDA
2696 WALK_NESTED_ENUM(IntentSpec
, Intent
) // R826
2697 WALK_NESTED_ENUM(ImplicitStmt
, ImplicitNoneNameSpec
) // R866
2698 WALK_NESTED_ENUM(ConnectSpec::CharExpr
, Kind
) // R1205
2699 WALK_NESTED_ENUM(IoControlSpec::CharExpr
, Kind
)
2700 WALK_NESTED_ENUM(InquireSpec::CharVar
, Kind
)
2701 WALK_NESTED_ENUM(InquireSpec::IntVar
, Kind
)
2702 WALK_NESTED_ENUM(InquireSpec::LogVar
, Kind
)
2703 WALK_NESTED_ENUM(ProcedureStmt
, Kind
) // R1506
2704 WALK_NESTED_ENUM(UseStmt
, ModuleNature
) // R1410
2705 WALK_NESTED_ENUM(OmpProcBindClause
, Type
) // OMP PROC_BIND
2706 WALK_NESTED_ENUM(OmpDefaultClause
, Type
) // OMP DEFAULT
2707 WALK_NESTED_ENUM(OmpDefaultmapClause
, ImplicitBehavior
) // OMP DEFAULTMAP
2708 WALK_NESTED_ENUM(OmpDefaultmapClause
, VariableCategory
) // OMP DEFAULTMAP
2709 WALK_NESTED_ENUM(OmpScheduleModifierType
, ModType
) // OMP schedule-modifier
2710 WALK_NESTED_ENUM(OmpLinearModifier
, Type
) // OMP linear-modifier
2711 WALK_NESTED_ENUM(OmpDependenceType
, Type
) // OMP dependence-type
2712 WALK_NESTED_ENUM(OmpMapType
, Type
) // OMP map-type
2713 WALK_NESTED_ENUM(OmpScheduleClause
, ScheduleType
) // OMP schedule-type
2714 WALK_NESTED_ENUM(OmpDeviceClause
, DeviceModifier
) // OMP device modifier
2715 WALK_NESTED_ENUM(OmpDeviceTypeClause
, Type
) // OMP DEVICE_TYPE
2716 WALK_NESTED_ENUM(OmpIfClause
, DirectiveNameModifier
) // OMP directive-modifier
2717 WALK_NESTED_ENUM(OmpCancelType
, Type
) // OMP cancel-type
2718 WALK_NESTED_ENUM(OmpOrderClause
, Type
) // OMP order-type
2719 WALK_NESTED_ENUM(OmpOrderModifier
, Kind
) // OMP order-modifier
2720 #undef WALK_NESTED_ENUM
2722 void Unparse(const CUFKernelDoConstruct::Directive
&x
) {
2723 Word("!$CUF KERNEL DO");
2724 Walk(" (", std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
), ")");
2726 const auto &grid
{std::get
<1>(x
.t
)};
2729 } else if (grid
.size() == 1) {
2732 Walk("(", grid
, ",", ")");
2735 const auto &block
{std::get
<2>(x
.t
)};
2736 if (block
.empty()) {
2738 } else if (block
.size() == 1) {
2739 Walk(block
.front());
2741 Walk("(", block
, ",", ")");
2743 if (const auto &stream
{std::get
<3>(x
.t
)}) {
2744 Word(",STREAM="), Walk(*stream
);
2749 void Unparse(const CUFKernelDoConstruct
&x
) {
2750 Walk(std::get
<CUFKernelDoConstruct::Directive
>(x
.t
));
2751 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
2754 void Done() const { CHECK(indent_
== 0); }
2758 void Put(const char *);
2759 void Put(const std::string
&);
2760 void PutNormalized(const std::string
&);
2761 void PutKeywordLetter(char);
2762 void Word(const char *);
2763 void Word(const std::string
&);
2764 void Word(const std::string_view
&);
2765 void Indent() { indent_
+= indentationAmount_
; }
2767 CHECK(indent_
>= indentationAmount_
);
2768 indent_
-= indentationAmount_
;
2770 void BeginOpenMP() { openmpDirective_
= true; }
2771 void EndOpenMP() { openmpDirective_
= false; }
2772 void BeginOpenACC() { openaccDirective_
= true; }
2773 void EndOpenACC() { openaccDirective_
= false; }
2775 // Call back to the traversal framework.
2776 template <typename T
> void Walk(const T
&x
) {
2777 Fortran::parser::Walk(x
, *this);
2780 // Traverse a std::optional<> value. Emit a prefix and/or a suffix string
2781 // only when it contains a value.
2782 template <typename A
>
2784 const char *prefix
, const std::optional
<A
> &x
, const char *suffix
= "") {
2786 Word(prefix
), Walk(*x
), Word(suffix
);
2789 template <typename A
>
2790 void Walk(const std::optional
<A
> &x
, const char *suffix
= "") {
2791 return Walk("", x
, suffix
);
2794 // Traverse a std::list<>. Separate the elements with an optional string.
2795 // Emit a prefix and/or a suffix string only when the list is not empty.
2796 template <typename A
>
2797 void Walk(const char *prefix
, const std::list
<A
> &list
,
2798 const char *comma
= ", ", const char *suffix
= "") {
2799 if (!list
.empty()) {
2800 const char *str
{prefix
};
2801 for (const auto &x
: list
) {
2808 template <typename A
>
2809 void Walk(const std::list
<A
> &list
, const char *comma
= ", ",
2810 const char *suffix
= "") {
2811 return Walk("", list
, comma
, suffix
);
2814 // Traverse a std::tuple<>, with an optional separator.
2815 template <std::size_t J
= 0, typename T
>
2816 void WalkTupleElements(const T
&tuple
, const char *separator
) {
2817 if (J
> 0 && J
< std::tuple_size_v
<T
>) {
2818 Word(separator
); // this usage dodges "unused parameter" warning
2820 if constexpr (J
< std::tuple_size_v
<T
>) {
2821 Walk(std::get
<J
>(tuple
));
2822 WalkTupleElements
<J
+ 1>(tuple
, separator
);
2825 template <typename
... A
>
2826 void Walk(const std::tuple
<A
...> &tuple
, const char *separator
= "") {
2827 WalkTupleElements(tuple
, separator
);
2830 void EndSubprogram(const char *kind
, const std::optional
<Name
> &name
) {
2831 Outdent(), Word("END "), Word(kind
), Walk(" ", name
);
2832 structureComponents_
.clear();
2835 llvm::raw_ostream
&out_
;
2837 const int indentationAmount_
{1};
2839 const int maxColumns_
{80};
2840 std::set
<CharBlock
> structureComponents_
;
2841 Encoding encoding_
{Encoding::UTF_8
};
2842 bool capitalizeKeywords_
{true};
2843 bool openaccDirective_
{false};
2844 bool openmpDirective_
{false};
2845 bool backslashEscapes_
{false};
2846 preStatementType
*preStatement_
{nullptr};
2847 AnalyzedObjectsAsFortran
*asFortran_
{nullptr};
2850 void UnparseVisitor::Put(char ch
) {
2852 if (openmpDirective_
|| openaccDirective_
) {
2859 for (int j
{0}; j
< indent_
; ++j
) {
2862 column_
= indent_
+ 2;
2863 } else if (ch
== '\n') {
2865 } else if (++column_
>= maxColumns_
) {
2867 for (int j
{0}; j
< indent_
; ++j
) {
2870 if (openmpDirective_
) {
2873 } else if (openaccDirective_
) {
2878 column_
= indent_
+ 3;
2882 if (openmpDirective_
|| openaccDirective_
) {
2887 void UnparseVisitor::Put(const char *str
) {
2888 for (; *str
!= '\0'; ++str
) {
2893 void UnparseVisitor::Put(const std::string
&str
) {
2894 for (char ch
: str
) {
2899 void UnparseVisitor::PutNormalized(const std::string
&str
) {
2900 auto decoded
{DecodeString
<std::string
, Encoding::LATIN_1
>(str
, true)};
2901 std::string encoded
{EncodeString
<Encoding::LATIN_1
>(decoded
)};
2902 Put(QuoteCharacterLiteral(encoded
, backslashEscapes_
));
2905 void UnparseVisitor::PutKeywordLetter(char ch
) {
2906 if (capitalizeKeywords_
) {
2907 Put(ToUpperCaseLetter(ch
));
2909 Put(ToLowerCaseLetter(ch
));
2913 void UnparseVisitor::Word(const char *str
) {
2914 for (; *str
!= '\0'; ++str
) {
2915 PutKeywordLetter(*str
);
2919 void UnparseVisitor::Word(const std::string
&str
) { Word(str
.c_str()); }
2921 void UnparseVisitor::Word(const std::string_view
&str
) {
2922 for (std::size_t j
{0}; j
< str
.length(); ++j
) {
2923 PutKeywordLetter(str
[j
]);
2927 template <typename A
>
2928 void Unparse(llvm::raw_ostream
&out
, const A
&root
, Encoding encoding
,
2929 bool capitalizeKeywords
, bool backslashEscapes
,
2930 preStatementType
*preStatement
, AnalyzedObjectsAsFortran
*asFortran
) {
2931 UnparseVisitor visitor
{out
, 1, encoding
, capitalizeKeywords
, backslashEscapes
,
2932 preStatement
, asFortran
};
2933 Walk(root
, visitor
);
2937 template void Unparse
<Program
>(llvm::raw_ostream
&, const Program
&, Encoding
,
2938 bool, bool, preStatementType
*, AnalyzedObjectsAsFortran
*);
2939 template void Unparse
<Expr
>(llvm::raw_ostream
&, const Expr
&, Encoding
, bool,
2940 bool, preStatementType
*, AnalyzedObjectsAsFortran
*);
2941 } // namespace Fortran::parser