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 IntegerTypeSpec
&) { // R705
167 void Unparse(const KindSelector
&x
) { // R706
170 [&](const ScalarIntConstantExpr
&y
) {
171 Put('('), Word("KIND="), Walk(y
), Put(')');
173 [&](const KindSelector::StarSize
&y
) { Put('*'), Walk(y
.v
); },
177 void Unparse(const SignedIntLiteralConstant
&x
) { // R707
178 Put(std::get
<CharBlock
>(x
.t
).ToString());
179 Walk("_", std::get
<std::optional
<KindParam
>>(x
.t
));
181 void Unparse(const IntLiteralConstant
&x
) { // R708
182 Put(std::get
<CharBlock
>(x
.t
).ToString());
183 Walk("_", std::get
<std::optional
<KindParam
>>(x
.t
));
185 void Unparse(const Sign
&x
) { // R712
186 Put(x
== Sign::Negative
? '-' : '+');
188 void Unparse(const RealLiteralConstant
&x
) { // R714, R715
189 Put(x
.real
.source
.ToString()), Walk("_", x
.kind
);
191 void Unparse(const ComplexLiteralConstant
&x
) { // R718 - R720
192 Put('('), Walk(x
.t
, ","), Put(')');
194 void Unparse(const CharSelector::LengthAndKind
&x
) { // R721
195 Put('('), Word("KIND="), Walk(x
.kind
);
196 Walk(", LEN=", x
.length
), Put(')');
198 void Unparse(const LengthSelector
&x
) { // R722
199 std::visit(common::visitors
{
200 [&](const TypeParamValue
&y
) {
201 Put('('), Word("LEN="), Walk(y
), Put(')');
203 [&](const CharLength
&y
) { Put('*'), Walk(y
); },
207 void Unparse(const CharLength
&x
) { // R723
210 [&](const TypeParamValue
&y
) { Put('('), Walk(y
), Put(')'); },
211 [&](const std::int64_t &y
) { Walk(y
); },
215 void Unparse(const CharLiteralConstant
&x
) { // R724
216 const auto &str
{std::get
<std::string
>(x
.t
)};
217 if (const auto &k
{std::get
<std::optional
<KindParam
>>(x
.t
)}) {
222 void Unparse(const HollerithLiteralConstant
&x
) {
223 auto ucs
{DecodeString
<std::u32string
, Encoding::UTF_8
>(x
.v
, false)};
226 for (char32_t ch
: ucs
) {
227 EncodedCharacter encoded
{EncodeCharacter(encoding_
, ch
)};
228 for (int j
{0}; j
< encoded
.bytes
; ++j
) {
229 Put(encoded
.buffer
[j
]);
233 void Unparse(const LogicalLiteralConstant
&x
) { // R725
234 Put(std::get
<bool>(x
.t
) ? ".TRUE." : ".FALSE.");
235 Walk("_", std::get
<std::optional
<KindParam
>>(x
.t
));
237 void Unparse(const DerivedTypeStmt
&x
) { // R727
238 Word("TYPE"), Walk(", ", std::get
<std::list
<TypeAttrSpec
>>(x
.t
), ", ");
239 Put(" :: "), Walk(std::get
<Name
>(x
.t
));
240 Walk("(", std::get
<std::list
<Name
>>(x
.t
), ", ", ")");
243 void Unparse(const Abstract
&) { // R728, &c.
246 void Post(const TypeAttrSpec::BindC
&) { Word("BIND(C)"); }
247 void Unparse(const TypeAttrSpec::Extends
&x
) {
248 Word("EXTENDS("), Walk(x
.v
), Put(')');
250 void Unparse(const EndTypeStmt
&x
) { // R730
251 Outdent(), Word("END TYPE"), Walk(" ", x
.v
);
253 void Unparse(const SequenceStmt
&) { // R731
256 void Unparse(const TypeParamDefStmt
&x
) { // R732
257 Walk(std::get
<IntegerTypeSpec
>(x
.t
));
258 Put(", "), Walk(std::get
<common::TypeParamAttr
>(x
.t
));
259 Put(" :: "), Walk(std::get
<std::list
<TypeParamDecl
>>(x
.t
), ", ");
261 void Unparse(const TypeParamDecl
&x
) { // R733
262 Walk(std::get
<Name
>(x
.t
));
263 Walk("=", std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
265 void Unparse(const DataComponentDefStmt
&x
) { // R737
266 const auto &dts
{std::get
<DeclarationTypeSpec
>(x
.t
)};
267 const auto &attrs
{std::get
<std::list
<ComponentAttrSpec
>>(x
.t
)};
268 const auto &decls
{std::get
<std::list
<ComponentDecl
>>(x
.t
)};
269 Walk(dts
), Walk(", ", attrs
, ", ");
270 if (!attrs
.empty() ||
271 (!std::holds_alternative
<DeclarationTypeSpec::Record
>(dts
.u
) &&
273 decls
.begin(), decls
.end(), [](const ComponentDecl
&d
) {
275 std::get
<std::optional
<Initialization
>>(d
.t
)};
277 std::holds_alternative
<
278 std::list
<common::Indirection
<DataStmtValue
>>>(
283 Put(' '), Walk(decls
, ", ");
285 void Unparse(const Allocatable
&) { // R738
288 void Unparse(const Pointer
&) { Word("POINTER"); }
289 void Unparse(const Contiguous
&) { Word("CONTIGUOUS"); }
290 void Before(const ComponentAttrSpec
&x
) {
291 std::visit(common::visitors
{
292 [&](const CoarraySpec
&) { Word("CODIMENSION["); },
293 [&](const ComponentArraySpec
&) { Word("DIMENSION("); },
298 void Post(const ComponentAttrSpec
&x
) {
299 std::visit(common::visitors
{
300 [&](const CoarraySpec
&) { Put(']'); },
301 [&](const ComponentArraySpec
&) { Put(')'); },
306 void Unparse(const ComponentDecl
&x
) { // R739
307 Walk(std::get
<ObjectName
>(x
.t
));
308 Walk("(", std::get
<std::optional
<ComponentArraySpec
>>(x
.t
), ")");
309 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
310 Walk("*", std::get
<std::optional
<CharLength
>>(x
.t
));
311 Walk(std::get
<std::optional
<Initialization
>>(x
.t
));
313 void Unparse(const ComponentArraySpec
&x
) { // R740
314 std::visit(common::visitors
{
315 [&](const std::list
<ExplicitShapeSpec
> &y
) { Walk(y
, ","); },
316 [&](const DeferredShapeSpecList
&y
) { Walk(y
); },
320 void Unparse(const ProcComponentDefStmt
&x
) { // R741
322 Walk(std::get
<std::optional
<ProcInterface
>>(x
.t
)), Put(')');
323 Walk(", ", std::get
<std::list
<ProcComponentAttrSpec
>>(x
.t
), ", ");
324 Put(" :: "), Walk(std::get
<std::list
<ProcDecl
>>(x
.t
), ", ");
326 void Unparse(const NoPass
&) { // R742
329 void Unparse(const Pass
&x
) { Word("PASS"), Walk("(", x
.v
, ")"); }
330 void Unparse(const Initialization
&x
) { // R743 & R805
331 std::visit(common::visitors
{
332 [&](const ConstantExpr
&y
) { Put(" = "), Walk(y
); },
333 [&](const NullInit
&y
) { Put(" => "), Walk(y
); },
334 [&](const InitialDataTarget
&y
) { Put(" => "), Walk(y
); },
335 [&](const std::list
<common::Indirection
<DataStmtValue
>> &y
) {
336 Walk("/", y
, ", ", "/");
341 void Unparse(const PrivateStmt
&) { // R745
344 void Unparse(const TypeBoundProcedureStmt::WithoutInterface
&x
) { // R749
345 Word("PROCEDURE"), Walk(", ", x
.attributes
, ", ");
346 Put(" :: "), Walk(x
.declarations
, ", ");
348 void Unparse(const TypeBoundProcedureStmt::WithInterface
&x
) {
349 Word("PROCEDURE("), Walk(x
.interfaceName
), Put("), ");
351 Put(" :: "), Walk(x
.bindingNames
, ", ");
353 void Unparse(const TypeBoundProcDecl
&x
) { // R750
354 Walk(std::get
<Name
>(x
.t
));
355 Walk(" => ", std::get
<std::optional
<Name
>>(x
.t
));
357 void Unparse(const TypeBoundGenericStmt
&x
) { // R751
358 Word("GENERIC"), Walk(", ", std::get
<std::optional
<AccessSpec
>>(x
.t
));
359 Put(" :: "), Walk(std::get
<common::Indirection
<GenericSpec
>>(x
.t
));
360 Put(" => "), Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
362 void Post(const BindAttr::Deferred
&) { Word("DEFERRED"); } // R752
363 void Post(const BindAttr::Non_Overridable
&) { Word("NON_OVERRIDABLE"); }
364 void Unparse(const FinalProcedureStmt
&x
) { // R753
365 Word("FINAL :: "), Walk(x
.v
, ", ");
367 void Unparse(const DerivedTypeSpec
&x
) { // R754
368 Walk(std::get
<Name
>(x
.t
));
369 Walk("(", std::get
<std::list
<TypeParamSpec
>>(x
.t
), ",", ")");
371 void Unparse(const TypeParamSpec
&x
) { // R755
372 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
373 Walk(std::get
<TypeParamValue
>(x
.t
));
375 void Unparse(const StructureConstructor
&x
) { // R756
376 Walk(std::get
<DerivedTypeSpec
>(x
.t
));
377 Put('('), Walk(std::get
<std::list
<ComponentSpec
>>(x
.t
), ", "), Put(')');
379 void Unparse(const ComponentSpec
&x
) { // R757
380 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
381 Walk(std::get
<ComponentDataSource
>(x
.t
));
383 void Unparse(const EnumDefStmt
&) { // R760
384 Word("ENUM, BIND(C)"), Indent();
386 void Unparse(const EnumeratorDefStmt
&x
) { // R761
387 Word("ENUMERATOR :: "), Walk(x
.v
, ", ");
389 void Unparse(const Enumerator
&x
) { // R762
390 Walk(std::get
<NamedConstant
>(x
.t
));
391 Walk(" = ", std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
393 void Post(const EndEnumStmt
&) { // R763
394 Outdent(), Word("END ENUM");
396 void Unparse(const BOZLiteralConstant
&x
) { // R764 - R767
399 void Unparse(const AcValue::Triplet
&x
) { // R773
400 Walk(std::get
<0>(x
.t
)), Put(':'), Walk(std::get
<1>(x
.t
));
401 Walk(":", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
403 void Unparse(const ArrayConstructor
&x
) { // R769
404 Put('['), Walk(x
.v
), Put(']');
406 void Unparse(const AcSpec
&x
) { // R770
407 Walk(x
.type
, "::"), Walk(x
.values
, ", ");
409 template <typename A
, typename B
> void Unparse(const LoopBounds
<A
, B
> &x
) {
410 Walk(x
.name
), Put('='), Walk(x
.lower
), Put(','), Walk(x
.upper
);
413 void Unparse(const AcImpliedDo
&x
) { // R774
414 Put('('), Walk(std::get
<std::list
<AcValue
>>(x
.t
), ", ");
415 Put(", "), Walk(std::get
<AcImpliedDoControl
>(x
.t
)), Put(')');
417 void Unparse(const AcImpliedDoControl
&x
) { // R775
418 Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
419 Walk(std::get
<AcImpliedDoControl::Bounds
>(x
.t
));
422 void Unparse(const TypeDeclarationStmt
&x
) { // R801
423 const auto &dts
{std::get
<DeclarationTypeSpec
>(x
.t
)};
424 const auto &attrs
{std::get
<std::list
<AttrSpec
>>(x
.t
)};
425 const auto &decls
{std::get
<std::list
<EntityDecl
>>(x
.t
)};
426 Walk(dts
), Walk(", ", attrs
, ", ");
428 static const auto isInitializerOldStyle
{[](const Initialization
&i
) {
429 return std::holds_alternative
<
430 std::list
<common::Indirection
<DataStmtValue
>>>(i
.u
);
432 static const auto hasAssignmentInitializer
{[](const EntityDecl
&d
) {
433 // Does a declaration have a new-style =x initializer?
434 const auto &init
{std::get
<std::optional
<Initialization
>>(d
.t
)};
435 return init
&& !isInitializerOldStyle(*init
);
437 static const auto hasSlashDelimitedInitializer
{[](const EntityDecl
&d
) {
438 // Does a declaration have an old-style /x/ initializer?
439 const auto &init
{std::get
<std::optional
<Initialization
>>(d
.t
)};
440 return init
&& isInitializerOldStyle(*init
);
442 const auto useDoubledColons
{[&]() {
443 bool isRecord
{std::holds_alternative
<DeclarationTypeSpec::Record
>(dts
.u
)};
444 if (!attrs
.empty()) {
445 // Attributes after the type require :: before the entities.
449 if (std::any_of(decls
.begin(), decls
.end(), hasAssignmentInitializer
)) {
450 // Always use :: with new style standard initializers (=x),
451 // since the standard requires them to appear (even in free form,
452 // where mandatory spaces already disambiguate INTEGER J=666).
457 // Never put :: in a legacy extension RECORD// statement.
460 // The :: is optional for this declaration. Avoid usage that can
461 // crash the pgf90 compiler.
463 decls
.begin(), decls
.end(), hasSlashDelimitedInitializer
)) {
464 // Don't use :: when a declaration uses legacy DATA-statement-like
465 // /x/ initialization.
468 // Don't use :: with intrinsic types. Otherwise, use it.
469 return !std::holds_alternative
<IntrinsicTypeSpec
>(dts
.u
);
472 if (useDoubledColons()) {
475 Put(' '), Walk(std::get
<std::list
<EntityDecl
>>(x
.t
), ", ");
477 void Before(const AttrSpec
&x
) { // R802
478 std::visit(common::visitors
{
479 [&](const CoarraySpec
&) { Word("CODIMENSION["); },
480 [&](const ArraySpec
&) { Word("DIMENSION("); },
485 void Post(const AttrSpec
&x
) {
486 std::visit(common::visitors
{
487 [&](const CoarraySpec
&) { Put(']'); },
488 [&](const ArraySpec
&) { Put(')'); },
493 void Unparse(const EntityDecl
&x
) { // R803
494 Walk(std::get
<ObjectName
>(x
.t
));
495 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
496 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
497 Walk("*", std::get
<std::optional
<CharLength
>>(x
.t
));
498 Walk(std::get
<std::optional
<Initialization
>>(x
.t
));
500 void Unparse(const NullInit
&) { // R806
503 void Unparse(const LanguageBindingSpec
&x
) { // R808 & R1528
504 Word("BIND(C"), Walk(", NAME=", x
.v
), Put(')');
506 void Unparse(const CoarraySpec
&x
) { // R809
507 std::visit(common::visitors
{
508 [&](const DeferredCoshapeSpecList
&y
) { Walk(y
); },
509 [&](const ExplicitCoshapeSpec
&y
) { Walk(y
); },
513 void Unparse(const DeferredCoshapeSpecList
&x
) { // R810
514 for (auto j
{x
.v
}; j
> 0; --j
) {
521 void Unparse(const ExplicitCoshapeSpec
&x
) { // R811
522 Walk(std::get
<std::list
<ExplicitShapeSpec
>>(x
.t
), ",", ",");
523 Walk(std::get
<std::optional
<SpecificationExpr
>>(x
.t
), ":"), Put('*');
525 void Unparse(const ExplicitShapeSpec
&x
) { // R812 - R813 & R816 - R818
526 Walk(std::get
<std::optional
<SpecificationExpr
>>(x
.t
), ":");
527 Walk(std::get
<SpecificationExpr
>(x
.t
));
529 void Unparse(const ArraySpec
&x
) { // R815
530 std::visit(common::visitors
{
531 [&](const std::list
<ExplicitShapeSpec
> &y
) { Walk(y
, ","); },
532 [&](const std::list
<AssumedShapeSpec
> &y
) { Walk(y
, ","); },
533 [&](const DeferredShapeSpecList
&y
) { Walk(y
); },
534 [&](const AssumedSizeSpec
&y
) { Walk(y
); },
535 [&](const ImpliedShapeSpec
&y
) { Walk(y
); },
536 [&](const AssumedRankSpec
&y
) { Walk(y
); },
540 void Post(const AssumedShapeSpec
&) { Put(':'); } // R819
541 void Unparse(const DeferredShapeSpecList
&x
) { // R820
542 for (auto j
{x
.v
}; j
> 0; --j
) {
549 void Unparse(const AssumedImpliedSpec
&x
) { // R821
553 void Unparse(const AssumedSizeSpec
&x
) { // R822
554 Walk(std::get
<std::list
<ExplicitShapeSpec
>>(x
.t
), ",", ",");
555 Walk(std::get
<AssumedImpliedSpec
>(x
.t
));
557 void Unparse(const ImpliedShapeSpec
&x
) { // R823
560 void Post(const AssumedRankSpec
&) { Put(".."); } // R825
561 void Post(const Asynchronous
&) { Word("ASYNCHRONOUS"); }
562 void Post(const External
&) { Word("EXTERNAL"); }
563 void Post(const Intrinsic
&) { Word("INTRINSIC"); }
564 void Post(const Optional
&) { Word("OPTIONAL"); }
565 void Post(const Parameter
&) { Word("PARAMETER"); }
566 void Post(const Protected
&) { Word("PROTECTED"); }
567 void Post(const Save
&) { Word("SAVE"); }
568 void Post(const Target
&) { Word("TARGET"); }
569 void Post(const Value
&) { Word("VALUE"); }
570 void Post(const Volatile
&) { Word("VOLATILE"); }
571 void Unparse(const IntentSpec
&x
) { // R826
572 Word("INTENT("), Walk(x
.v
), Put(")");
574 void Unparse(const AccessStmt
&x
) { // R827
575 Walk(std::get
<AccessSpec
>(x
.t
));
576 Walk(" :: ", std::get
<std::list
<AccessId
>>(x
.t
), ", ");
578 void Unparse(const AllocatableStmt
&x
) { // R829
579 Word("ALLOCATABLE :: "), Walk(x
.v
, ", ");
581 void Unparse(const ObjectDecl
&x
) { // R830 & R860
582 Walk(std::get
<ObjectName
>(x
.t
));
583 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
584 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
586 void Unparse(const AsynchronousStmt
&x
) { // R831
587 Word("ASYNCHRONOUS :: "), Walk(x
.v
, ", ");
589 void Unparse(const BindStmt
&x
) { // R832
592 void Unparse(const BindEntity
&x
) { // R833
593 bool isCommon
{std::get
<BindEntity::Kind
>(x
.t
) == BindEntity::Kind::Common
};
594 const char *slash
{isCommon
? "/" : ""};
595 Put(slash
), Walk(std::get
<Name
>(x
.t
)), Put(slash
);
597 void Unparse(const CodimensionStmt
&x
) { // R834
598 Word("CODIMENSION :: "), Walk(x
.v
, ", ");
600 void Unparse(const CodimensionDecl
&x
) { // R835
601 Walk(std::get
<Name
>(x
.t
));
602 Put('['), Walk(std::get
<CoarraySpec
>(x
.t
)), Put(']');
604 void Unparse(const ContiguousStmt
&x
) { // R836
605 Word("CONTIGUOUS :: "), Walk(x
.v
, ", ");
607 void Unparse(const DataStmt
&x
) { // R837
608 Word("DATA "), Walk(x
.v
, ", ");
610 void Unparse(const DataStmtSet
&x
) { // R838
611 Walk(std::get
<std::list
<DataStmtObject
>>(x
.t
), ", ");
612 Put('/'), Walk(std::get
<std::list
<DataStmtValue
>>(x
.t
), ", "), Put('/');
614 void Unparse(const DataImpliedDo
&x
) { // R840, R842
615 Put('('), Walk(std::get
<std::list
<DataIDoObject
>>(x
.t
), ", "), Put(',');
616 Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
617 Walk(std::get
<DataImpliedDo::Bounds
>(x
.t
)), Put(')');
619 void Unparse(const DataStmtValue
&x
) { // R843
620 Walk(std::get
<std::optional
<DataStmtRepeat
>>(x
.t
), "*");
621 Walk(std::get
<DataStmtConstant
>(x
.t
));
623 void Unparse(const DimensionStmt
&x
) { // R848
624 Word("DIMENSION :: "), Walk(x
.v
, ", ");
626 void Unparse(const DimensionStmt::Declaration
&x
) {
627 Walk(std::get
<Name
>(x
.t
));
628 Put('('), Walk(std::get
<ArraySpec
>(x
.t
)), Put(')');
630 void Unparse(const IntentStmt
&x
) { // R849
633 void Unparse(const OptionalStmt
&x
) { // R850
634 Word("OPTIONAL :: "), Walk(x
.v
, ", ");
636 void Unparse(const ParameterStmt
&x
) { // R851
637 Word("PARAMETER("), Walk(x
.v
, ", "), Put(')');
639 void Unparse(const NamedConstantDef
&x
) { // R852
642 void Unparse(const PointerStmt
&x
) { // R853
643 Word("POINTER :: "), Walk(x
.v
, ", ");
645 void Unparse(const PointerDecl
&x
) { // R854
646 Walk(std::get
<Name
>(x
.t
));
647 Walk("(", std::get
<std::optional
<DeferredShapeSpecList
>>(x
.t
), ")");
649 void Unparse(const ProtectedStmt
&x
) { // R855
650 Word("PROTECTED :: "), Walk(x
.v
, ", ");
652 void Unparse(const SaveStmt
&x
) { // R856
653 Word("SAVE"), Walk(" :: ", x
.v
, ", ");
655 void Unparse(const SavedEntity
&x
) { // R857, R858
657 std::get
<SavedEntity::Kind
>(x
.t
) == SavedEntity::Kind::Common
};
658 const char *slash
{isCommon
? "/" : ""};
659 Put(slash
), Walk(std::get
<Name
>(x
.t
)), Put(slash
);
661 void Unparse(const TargetStmt
&x
) { // R859
662 Word("TARGET :: "), Walk(x
.v
, ", ");
664 void Unparse(const ValueStmt
&x
) { // R861
665 Word("VALUE :: "), Walk(x
.v
, ", ");
667 void Unparse(const VolatileStmt
&x
) { // R862
668 Word("VOLATILE :: "), Walk(x
.v
, ", ");
670 void Unparse(const ImplicitStmt
&x
) { // R863
672 std::visit(common::visitors
{
673 [&](const std::list
<ImplicitSpec
> &y
) { Walk(y
, ", "); },
674 [&](const std::list
<ImplicitStmt::ImplicitNoneNameSpec
> &y
) {
675 Word("NONE"), Walk(" (", y
, ", ", ")");
680 void Unparse(const ImplicitSpec
&x
) { // R864
681 Walk(std::get
<DeclarationTypeSpec
>(x
.t
));
682 Put('('), Walk(std::get
<std::list
<LetterSpec
>>(x
.t
), ", "), Put(')');
684 void Unparse(const LetterSpec
&x
) { // R865
685 Put(*std::get
<const char *>(x
.t
));
686 auto second
{std::get
<std::optional
<const char *>>(x
.t
)};
688 Put('-'), Put(**second
);
691 void Unparse(const ImportStmt
&x
) { // R867
694 case common::ImportKind::Default
:
695 Walk(" :: ", x
.names
, ", ");
697 case common::ImportKind::Only
:
698 Put(", "), Word("ONLY: ");
701 case common::ImportKind::None
:
704 case common::ImportKind::All
:
709 void Unparse(const NamelistStmt
&x
) { // R868
710 Word("NAMELIST"), Walk(x
.v
, ", ");
712 void Unparse(const NamelistStmt::Group
&x
) {
713 Put('/'), Walk(std::get
<Name
>(x
.t
)), Put('/');
714 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
716 void Unparse(const EquivalenceStmt
&x
) { // R870, R871
718 const char *separator
{" "};
719 for (const std::list
<EquivalenceObject
> &y
: x
.v
) {
720 Put(separator
), Put('('), Walk(y
), Put(')');
724 void Unparse(const CommonStmt
&x
) { // R873
728 void Unparse(const CommonBlockObject
&x
) { // R874
729 Walk(std::get
<Name
>(x
.t
));
730 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
732 void Unparse(const CommonStmt::Block
&x
) {
733 Word("/"), Walk(std::get
<std::optional
<Name
>>(x
.t
)), Word("/");
734 Walk(std::get
<std::list
<CommonBlockObject
>>(x
.t
));
737 void Unparse(const Substring
&x
) { // R908, R909
738 Walk(std::get
<DataRef
>(x
.t
));
739 Put('('), Walk(std::get
<SubstringRange
>(x
.t
)), Put(')');
741 void Unparse(const CharLiteralConstantSubstring
&x
) {
742 Walk(std::get
<CharLiteralConstant
>(x
.t
));
743 Put('('), Walk(std::get
<SubstringRange
>(x
.t
)), Put(')');
745 void Unparse(const SubstringRange
&x
) { // R910
748 void Unparse(const PartRef
&x
) { // R912
750 Walk("(", x
.subscripts
, ",", ")");
751 Walk(x
.imageSelector
);
753 void Unparse(const StructureComponent
&x
) { // R913
755 if (structureComponents_
.find(x
.component
.source
) !=
756 structureComponents_
.end()) {
763 void Unparse(const ArrayElement
&x
) { // R917
765 Put('('), Walk(x
.subscripts
, ","), Put(')');
767 void Unparse(const SubscriptTriplet
&x
) { // R921
768 Walk(std::get
<0>(x
.t
)), Put(':'), Walk(std::get
<1>(x
.t
));
769 Walk(":", std::get
<2>(x
.t
));
771 void Unparse(const ImageSelector
&x
) { // R924
772 Put('['), Walk(std::get
<std::list
<Cosubscript
>>(x
.t
), ",");
773 Walk(",", std::get
<std::list
<ImageSelectorSpec
>>(x
.t
), ","), Put(']');
775 void Before(const ImageSelectorSpec::Stat
&) { // R926
778 void Before(const ImageSelectorSpec::Team_Number
&) { Word("TEAM_NUMBER="); }
779 void Before(const ImageSelectorSpec
&x
) {
780 if (std::holds_alternative
<TeamValue
>(x
.u
)) {
784 void Unparse(const AllocateStmt
&x
) { // R927
786 Walk(std::get
<std::optional
<TypeSpec
>>(x
.t
), "::");
787 Walk(std::get
<std::list
<Allocation
>>(x
.t
), ", ");
788 Walk(", ", std::get
<std::list
<AllocOpt
>>(x
.t
), ", "), Put(')');
790 void Before(const AllocOpt
&x
) { // R928, R931
791 std::visit(common::visitors
{
792 [&](const AllocOpt::Mold
&) { Word("MOLD="); },
793 [&](const AllocOpt::Source
&) { Word("SOURCE="); },
794 [](const StatOrErrmsg
&) {},
798 void Unparse(const Allocation
&x
) { // R932
799 Walk(std::get
<AllocateObject
>(x
.t
));
800 Walk("(", std::get
<std::list
<AllocateShapeSpec
>>(x
.t
), ",", ")");
801 Walk("[", std::get
<std::optional
<AllocateCoarraySpec
>>(x
.t
), "]");
803 void Unparse(const AllocateShapeSpec
&x
) { // R934 & R938
804 Walk(std::get
<std::optional
<BoundExpr
>>(x
.t
), ":");
805 Walk(std::get
<BoundExpr
>(x
.t
));
807 void Unparse(const AllocateCoarraySpec
&x
) { // R937
808 Walk(std::get
<std::list
<AllocateCoshapeSpec
>>(x
.t
), ",", ",");
809 Walk(std::get
<std::optional
<BoundExpr
>>(x
.t
), ":"), Put('*');
811 void Unparse(const NullifyStmt
&x
) { // R939
812 Word("NULLIFY("), Walk(x
.v
, ", "), Put(')');
814 void Unparse(const DeallocateStmt
&x
) { // R941
816 Walk(std::get
<std::list
<AllocateObject
>>(x
.t
), ", ");
817 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
819 void Before(const StatOrErrmsg
&x
) { // R942 & R1165
820 std::visit(common::visitors
{
821 [&](const StatVariable
&) { Word("STAT="); },
822 [&](const MsgVariable
&) { Word("ERRMSG="); },
828 void Unparse(const Expr::Parentheses
&x
) { Put('('), Walk(x
.v
), Put(')'); }
829 void Before(const Expr::UnaryPlus
&) { Put("+"); }
830 void Before(const Expr::Negate
&) { Put("-"); }
831 void Before(const Expr::NOT
&) { Word(".NOT."); }
832 void Unparse(const Expr::PercentLoc
&x
) {
833 Word("%LOC("), Walk(x
.v
), Put(')');
835 void Unparse(const Expr::Power
&x
) { Walk(x
.t
, "**"); }
836 void Unparse(const Expr::Multiply
&x
) { Walk(x
.t
, "*"); }
837 void Unparse(const Expr::Divide
&x
) { Walk(x
.t
, "/"); }
838 void Unparse(const Expr::Add
&x
) { Walk(x
.t
, "+"); }
839 void Unparse(const Expr::Subtract
&x
) { Walk(x
.t
, "-"); }
840 void Unparse(const Expr::Concat
&x
) { Walk(x
.t
, "//"); }
841 void Unparse(const Expr::LT
&x
) { Walk(x
.t
, "<"); }
842 void Unparse(const Expr::LE
&x
) { Walk(x
.t
, "<="); }
843 void Unparse(const Expr::EQ
&x
) { Walk(x
.t
, "=="); }
844 void Unparse(const Expr::NE
&x
) { Walk(x
.t
, "/="); }
845 void Unparse(const Expr::GE
&x
) { Walk(x
.t
, ">="); }
846 void Unparse(const Expr::GT
&x
) { Walk(x
.t
, ">"); }
847 void Unparse(const Expr::AND
&x
) { Walk(x
.t
, ".AND."); }
848 void Unparse(const Expr::OR
&x
) { Walk(x
.t
, ".OR."); }
849 void Unparse(const Expr::EQV
&x
) { Walk(x
.t
, ".EQV."); }
850 void Unparse(const Expr::NEQV
&x
) { Walk(x
.t
, ".NEQV."); }
851 void Unparse(const Expr::ComplexConstructor
&x
) {
852 Put('('), Walk(x
.t
, ","), Put(')');
854 void Unparse(const Expr::DefinedBinary
&x
) {
855 Walk(std::get
<1>(x
.t
)); // left
856 Walk(std::get
<DefinedOpName
>(x
.t
));
857 Walk(std::get
<2>(x
.t
)); // right
859 void Unparse(const DefinedOpName
&x
) { // R1003, R1023, R1414, & R1415
862 void Unparse(const AssignmentStmt
&x
) { // R1032
863 if (asFortran_
&& x
.typedAssignment
.get()) {
865 asFortran_
->assignment(out_
, *x
.typedAssignment
);
871 void Unparse(const PointerAssignmentStmt
&x
) { // R1033, R1034, R1038
872 if (asFortran_
&& x
.typedAssignment
.get()) {
874 asFortran_
->assignment(out_
, *x
.typedAssignment
);
877 Walk(std::get
<DataRef
>(x
.t
));
880 [&](const std::list
<BoundsRemapping
> &y
) {
881 Put('('), Walk(y
), Put(')');
883 [&](const std::list
<BoundsSpec
> &y
) { Walk("(", y
, ", ", ")"); },
885 std::get
<PointerAssignmentStmt::Bounds
>(x
.t
).u
);
886 Put(" => "), Walk(std::get
<Expr
>(x
.t
));
889 void Post(const BoundsSpec
&) { // R1035
892 void Unparse(const BoundsRemapping
&x
) { // R1036
895 void Unparse(const WhereStmt
&x
) { // R1041, R1045, R1046
896 Word("WHERE ("), Walk(x
.t
, ") ");
898 void Unparse(const WhereConstructStmt
&x
) { // R1043
899 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
900 Word("WHERE ("), Walk(std::get
<LogicalExpr
>(x
.t
)), Put(')');
903 void Unparse(const MaskedElsewhereStmt
&x
) { // R1047
905 Word("ELSEWHERE ("), Walk(std::get
<LogicalExpr
>(x
.t
)), Put(')');
906 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
));
909 void Unparse(const ElsewhereStmt
&x
) { // R1048
910 Outdent(), Word("ELSEWHERE"), Walk(" ", x
.v
), Indent();
912 void Unparse(const EndWhereStmt
&x
) { // R1049
913 Outdent(), Word("END WHERE"), Walk(" ", x
.v
);
915 void Unparse(const ForallConstructStmt
&x
) { // R1051
916 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
917 Word("FORALL"), Walk(std::get
<common::Indirection
<ConcurrentHeader
>>(x
.t
));
920 void Unparse(const EndForallStmt
&x
) { // R1054
921 Outdent(), Word("END FORALL"), Walk(" ", x
.v
);
923 void Before(const ForallStmt
&) { // R1055
927 void Unparse(const AssociateStmt
&x
) { // R1103
928 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
930 Walk(std::get
<std::list
<Association
>>(x
.t
), ", "), Put(')'), Indent();
932 void Unparse(const Association
&x
) { // R1104
935 void Unparse(const EndAssociateStmt
&x
) { // R1106
936 Outdent(), Word("END ASSOCIATE"), Walk(" ", x
.v
);
938 void Unparse(const BlockStmt
&x
) { // R1108
939 Walk(x
.v
, ": "), Word("BLOCK"), Indent();
941 void Unparse(const EndBlockStmt
&x
) { // R1110
942 Outdent(), Word("END BLOCK"), Walk(" ", x
.v
);
944 void Unparse(const ChangeTeamStmt
&x
) { // R1112
945 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
946 Word("CHANGE TEAM ("), Walk(std::get
<TeamValue
>(x
.t
));
947 Walk(", ", std::get
<std::list
<CoarrayAssociation
>>(x
.t
), ", ");
948 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
951 void Unparse(const CoarrayAssociation
&x
) { // R1113
954 void Unparse(const EndChangeTeamStmt
&x
) { // R1114
955 Outdent(), Word("END TEAM (");
956 Walk(std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
957 Put(')'), Walk(" ", std::get
<std::optional
<Name
>>(x
.t
));
959 void Unparse(const CriticalStmt
&x
) { // R1117
960 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
961 Word("CRITICAL ("), Walk(std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
964 void Unparse(const EndCriticalStmt
&x
) { // R1118
965 Outdent(), Word("END CRITICAL"), Walk(" ", x
.v
);
967 void Unparse(const DoConstruct
&x
) { // R1119, R1120
968 Walk(std::get
<Statement
<NonLabelDoStmt
>>(x
.t
));
969 Indent(), Walk(std::get
<Block
>(x
.t
), ""), Outdent();
970 Walk(std::get
<Statement
<EndDoStmt
>>(x
.t
));
972 void Unparse(const LabelDoStmt
&x
) { // R1121
973 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
974 Word("DO "), Walk(std::get
<Label
>(x
.t
));
975 Walk(" ", std::get
<std::optional
<LoopControl
>>(x
.t
));
977 void Unparse(const NonLabelDoStmt
&x
) { // R1122
978 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
979 Word("DO "), Walk(std::get
<std::optional
<LoopControl
>>(x
.t
));
981 void Unparse(const LoopControl
&x
) { // R1123
982 std::visit(common::visitors
{
983 [&](const ScalarLogicalExpr
&y
) {
984 Word("WHILE ("), Walk(y
), Put(')');
986 [&](const auto &y
) { Walk(y
); },
990 void Unparse(const ConcurrentHeader
&x
) { // R1125
991 Put('('), Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
992 Walk(std::get
<std::list
<ConcurrentControl
>>(x
.t
), ", ");
993 Walk(", ", std::get
<std::optional
<ScalarLogicalExpr
>>(x
.t
)), Put(')');
995 void Unparse(const ConcurrentControl
&x
) { // R1126 - R1128
996 Walk(std::get
<Name
>(x
.t
)), Put('='), Walk(std::get
<1>(x
.t
));
997 Put(':'), Walk(std::get
<2>(x
.t
));
998 Walk(":", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
1000 void Before(const LoopControl::Concurrent
&) { // R1129
1003 void Unparse(const LocalitySpec::Local
&x
) {
1004 Word("LOCAL("), Walk(x
.v
, ", "), Put(')');
1006 void Unparse(const LocalitySpec::LocalInit
&x
) {
1007 Word("LOCAL_INIT("), Walk(x
.v
, ", "), Put(')');
1009 void Unparse(const LocalitySpec::Shared
&x
) {
1010 Word("SHARED("), Walk(x
.v
, ", "), Put(')');
1012 void Post(const LocalitySpec::DefaultNone
&) { Word("DEFAULT(NONE)"); }
1013 void Unparse(const EndDoStmt
&x
) { // R1132
1014 Word("END DO"), Walk(" ", x
.v
);
1016 void Unparse(const CycleStmt
&x
) { // R1133
1017 Word("CYCLE"), Walk(" ", x
.v
);
1019 void Unparse(const IfThenStmt
&x
) { // R1135
1020 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1021 Word("IF ("), Walk(std::get
<ScalarLogicalExpr
>(x
.t
));
1022 Put(") "), Word("THEN"), Indent();
1024 void Unparse(const ElseIfStmt
&x
) { // R1136
1025 Outdent(), Word("ELSE IF (");
1026 Walk(std::get
<ScalarLogicalExpr
>(x
.t
)), Put(") "), Word("THEN");
1027 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1029 void Unparse(const ElseStmt
&x
) { // R1137
1030 Outdent(), Word("ELSE"), Walk(" ", x
.v
), Indent();
1032 void Unparse(const EndIfStmt
&x
) { // R1138
1033 Outdent(), Word("END IF"), Walk(" ", x
.v
);
1035 void Unparse(const IfStmt
&x
) { // R1139
1036 Word("IF ("), Walk(x
.t
, ") ");
1038 void Unparse(const SelectCaseStmt
&x
) { // R1141, R1144
1039 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1040 Word("SELECT CASE (");
1041 Walk(std::get
<Scalar
<Expr
>>(x
.t
)), Put(')'), Indent();
1043 void Unparse(const CaseStmt
&x
) { // R1142
1044 Outdent(), Word("CASE "), Walk(std::get
<CaseSelector
>(x
.t
));
1045 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1047 void Unparse(const EndSelectStmt
&x
) { // R1143 & R1151 & R1155
1048 Outdent(), Word("END SELECT"), Walk(" ", x
.v
);
1050 void Unparse(const CaseSelector
&x
) { // R1145
1051 std::visit(common::visitors
{
1052 [&](const std::list
<CaseValueRange
> &y
) {
1053 Put('('), Walk(y
), Put(')');
1055 [&](const Default
&) { Word("DEFAULT"); },
1059 void Unparse(const CaseValueRange::Range
&x
) { // R1146
1060 Walk(x
.lower
), Put(':'), Walk(x
.upper
);
1062 void Unparse(const SelectRankStmt
&x
) { // R1149
1063 Walk(std::get
<0>(x
.t
), ": ");
1064 Word("SELECT RANK ("), Walk(std::get
<1>(x
.t
), " => ");
1065 Walk(std::get
<Selector
>(x
.t
)), Put(')'), Indent();
1067 void Unparse(const SelectRankCaseStmt
&x
) { // R1150
1068 Outdent(), Word("RANK ");
1069 std::visit(common::visitors
{
1070 [&](const ScalarIntConstantExpr
&y
) {
1071 Put('('), Walk(y
), Put(')');
1073 [&](const Star
&) { Put("(*)"); },
1074 [&](const Default
&) { Word("DEFAULT"); },
1076 std::get
<SelectRankCaseStmt::Rank
>(x
.t
).u
);
1077 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1079 void Unparse(const SelectTypeStmt
&x
) { // R1153
1080 Walk(std::get
<0>(x
.t
), ": ");
1081 Word("SELECT TYPE ("), Walk(std::get
<1>(x
.t
), " => ");
1082 Walk(std::get
<Selector
>(x
.t
)), Put(')'), Indent();
1084 void Unparse(const TypeGuardStmt
&x
) { // R1154
1085 Outdent(), Walk(std::get
<TypeGuardStmt::Guard
>(x
.t
));
1086 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1088 void Unparse(const TypeGuardStmt::Guard
&x
) {
1091 [&](const TypeSpec
&y
) { Word("TYPE IS ("), Walk(y
), Put(')'); },
1092 [&](const DerivedTypeSpec
&y
) {
1093 Word("CLASS IS ("), Walk(y
), Put(')');
1095 [&](const Default
&) { Word("CLASS DEFAULT"); },
1099 void Unparse(const ExitStmt
&x
) { // R1156
1100 Word("EXIT"), Walk(" ", x
.v
);
1102 void Before(const GotoStmt
&) { // R1157
1105 void Unparse(const ComputedGotoStmt
&x
) { // R1158
1106 Word("GO TO ("), Walk(x
.t
, "), ");
1108 void Unparse(const ContinueStmt
&) { // R1159
1111 void Unparse(const StopStmt
&x
) { // R1160, R1161
1112 if (std::get
<StopStmt::Kind
>(x
.t
) == StopStmt::Kind::ErrorStop
) {
1115 Word("STOP"), Walk(" ", std::get
<std::optional
<StopCode
>>(x
.t
));
1116 Walk(", QUIET=", std::get
<std::optional
<ScalarLogicalExpr
>>(x
.t
));
1118 void Unparse(const FailImageStmt
&) { // R1163
1121 void Unparse(const SyncAllStmt
&x
) { // R1164
1122 Word("SYNC ALL ("), Walk(x
.v
, ", "), Put(')');
1124 void Unparse(const SyncImagesStmt
&x
) { // R1166
1125 Word("SYNC IMAGES (");
1126 Walk(std::get
<SyncImagesStmt::ImageSet
>(x
.t
));
1127 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1129 void Unparse(const SyncMemoryStmt
&x
) { // R1168
1130 Word("SYNC MEMORY ("), Walk(x
.v
, ", "), Put(')');
1132 void Unparse(const SyncTeamStmt
&x
) { // R1169
1133 Word("SYNC TEAM ("), Walk(std::get
<TeamValue
>(x
.t
));
1134 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1136 void Unparse(const EventPostStmt
&x
) { // R1170
1137 Word("EVENT POST ("), Walk(std::get
<EventVariable
>(x
.t
));
1138 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1140 void Before(const EventWaitStmt::EventWaitSpec
&x
) { // R1173, R1174
1141 std::visit(common::visitors
{
1142 [&](const ScalarIntExpr
&) { Word("UNTIL_COUNT="); },
1143 [](const StatOrErrmsg
&) {},
1147 void Unparse(const EventWaitStmt
&x
) { // R1170
1148 Word("EVENT WAIT ("), Walk(std::get
<EventVariable
>(x
.t
));
1149 Walk(", ", std::get
<std::list
<EventWaitStmt::EventWaitSpec
>>(x
.t
), ", ");
1152 void Unparse(const FormTeamStmt
&x
) { // R1175, R1177
1153 Word("FORM TEAM ("), Walk(std::get
<ScalarIntExpr
>(x
.t
));
1154 Put(','), Walk(std::get
<TeamVariable
>(x
.t
));
1155 Walk(", ", std::get
<std::list
<FormTeamStmt::FormTeamSpec
>>(x
.t
), ", ");
1158 void Before(const FormTeamStmt::FormTeamSpec
&x
) { // R1176, R1178
1159 std::visit(common::visitors
{
1160 [&](const ScalarIntExpr
&) { Word("NEW_INDEX="); },
1161 [](const StatOrErrmsg
&) {},
1165 void Unparse(const LockStmt
&x
) { // R1179
1166 Word("LOCK ("), Walk(std::get
<LockVariable
>(x
.t
));
1167 Walk(", ", std::get
<std::list
<LockStmt::LockStat
>>(x
.t
), ", ");
1170 void Before(const LockStmt::LockStat
&x
) { // R1180
1173 [&](const ScalarLogicalVariable
&) { Word("ACQUIRED_LOCK="); },
1174 [](const StatOrErrmsg
&) {},
1178 void Unparse(const UnlockStmt
&x
) { // R1181
1179 Word("UNLOCK ("), Walk(std::get
<LockVariable
>(x
.t
));
1180 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
1184 void Unparse(const OpenStmt
&x
) { // R1204
1185 Word("OPEN ("), Walk(x
.v
, ", "), Put(')');
1187 bool Pre(const ConnectSpec
&x
) { // R1205
1188 return std::visit(common::visitors
{
1189 [&](const FileUnitNumber
&) {
1193 [&](const FileNameExpr
&) {
1197 [&](const ConnectSpec::CharExpr
&y
) {
1201 [&](const MsgVariable
&) {
1205 [&](const StatVariable
&) {
1209 [&](const ConnectSpec::Recl
&) {
1213 [&](const ConnectSpec::Newunit
&) {
1217 [&](const ErrLabel
&) {
1221 [&](const StatusExpr
&) {
1228 void Unparse(const CloseStmt
&x
) { // R1208
1229 Word("CLOSE ("), Walk(x
.v
, ", "), Put(')');
1231 void Before(const CloseStmt::CloseSpec
&x
) { // R1209
1232 std::visit(common::visitors
{
1233 [&](const FileUnitNumber
&) { Word("UNIT="); },
1234 [&](const StatVariable
&) { Word("IOSTAT="); },
1235 [&](const MsgVariable
&) { Word("IOMSG="); },
1236 [&](const ErrLabel
&) { Word("ERR="); },
1237 [&](const StatusExpr
&) { Word("STATUS="); },
1241 void Unparse(const ReadStmt
&x
) { // R1210
1244 Put('('), Walk(x
.iounit
);
1246 Put(", "), Walk(x
.format
);
1248 Walk(", ", x
.controls
, ", ");
1250 } else if (x
.format
) {
1252 if (!x
.items
.empty()) {
1256 Put('('), Walk(x
.controls
, ", "), Put(')');
1258 Walk(" ", x
.items
, ", ");
1260 void Unparse(const WriteStmt
&x
) { // R1211
1265 Put(", "), Walk(x
.format
);
1267 Walk(", ", x
.controls
, ", ");
1269 Walk(x
.controls
, ", ");
1271 Put(')'), Walk(" ", x
.items
, ", ");
1273 void Unparse(const PrintStmt
&x
) { // R1212
1274 Word("PRINT "), Walk(std::get
<Format
>(x
.t
));
1275 Walk(", ", std::get
<std::list
<OutputItem
>>(x
.t
), ", ");
1277 bool Pre(const IoControlSpec
&x
) { // R1213
1278 return std::visit(common::visitors
{
1279 [&](const IoUnit
&) {
1283 [&](const Format
&) {
1291 [&](const IoControlSpec::CharExpr
&y
) {
1295 [&](const IoControlSpec::Asynchronous
&) {
1296 Word("ASYNCHRONOUS=");
1299 [&](const EndLabel
&) {
1303 [&](const EorLabel
&) {
1307 [&](const ErrLabel
&) {
1311 [&](const IdVariable
&) {
1315 [&](const MsgVariable
&) {
1319 [&](const StatVariable
&) {
1323 [&](const IoControlSpec::Pos
&) {
1327 [&](const IoControlSpec::Rec
&) {
1331 [&](const IoControlSpec::Size
&) {
1338 void Unparse(const InputImpliedDo
&x
) { // R1218
1339 Put('('), Walk(std::get
<std::list
<InputItem
>>(x
.t
), ", "), Put(", ");
1340 Walk(std::get
<IoImpliedDoControl
>(x
.t
)), Put(')');
1342 void Unparse(const OutputImpliedDo
&x
) { // R1219
1343 Put('('), Walk(std::get
<std::list
<OutputItem
>>(x
.t
), ", "), Put(", ");
1344 Walk(std::get
<IoImpliedDoControl
>(x
.t
)), Put(')');
1346 void Unparse(const WaitStmt
&x
) { // R1222
1347 Word("WAIT ("), Walk(x
.v
, ", "), Put(')');
1349 void Before(const WaitSpec
&x
) { // R1223
1350 std::visit(common::visitors
{
1351 [&](const FileUnitNumber
&) { Word("UNIT="); },
1352 [&](const EndLabel
&) { Word("END="); },
1353 [&](const EorLabel
&) { Word("EOR="); },
1354 [&](const ErrLabel
&) { Word("ERR="); },
1355 [&](const IdExpr
&) { Word("ID="); },
1356 [&](const MsgVariable
&) { Word("IOMSG="); },
1357 [&](const StatVariable
&) { Word("IOSTAT="); },
1361 void Unparse(const BackspaceStmt
&x
) { // R1224
1362 Word("BACKSPACE ("), Walk(x
.v
, ", "), Put(')');
1364 void Unparse(const EndfileStmt
&x
) { // R1225
1365 Word("ENDFILE ("), Walk(x
.v
, ", "), Put(')');
1367 void Unparse(const RewindStmt
&x
) { // R1226
1368 Word("REWIND ("), Walk(x
.v
, ", "), Put(')');
1370 void Before(const PositionOrFlushSpec
&x
) { // R1227 & R1229
1371 std::visit(common::visitors
{
1372 [&](const FileUnitNumber
&) { Word("UNIT="); },
1373 [&](const MsgVariable
&) { Word("IOMSG="); },
1374 [&](const StatVariable
&) { Word("IOSTAT="); },
1375 [&](const ErrLabel
&) { Word("ERR="); },
1379 void Unparse(const FlushStmt
&x
) { // R1228
1380 Word("FLUSH ("), Walk(x
.v
, ", "), Put(')');
1382 void Unparse(const InquireStmt
&x
) { // R1230
1386 [&](const InquireStmt::Iolength
&y
) {
1387 Word("IOLENGTH="), Walk(y
.t
, ") ");
1389 [&](const std::list
<InquireSpec
> &y
) { Walk(y
, ", "), Put(')'); },
1393 bool Pre(const InquireSpec
&x
) { // R1231
1394 return std::visit(common::visitors
{
1395 [&](const FileUnitNumber
&) {
1399 [&](const FileNameExpr
&) {
1403 [&](const InquireSpec::CharVar
&y
) {
1407 [&](const InquireSpec::IntVar
&y
) {
1411 [&](const InquireSpec::LogVar
&y
) {
1415 [&](const IdExpr
&) {
1419 [&](const ErrLabel
&) {
1427 void Before(const FormatStmt
&) { // R1301
1430 void Unparse(const format::FormatSpecification
&x
) { // R1302, R1303, R1305
1431 Put('('), Walk("", x
.items
, ",", x
.unlimitedItems
.empty() ? "" : ",");
1432 Walk("*(", x
.unlimitedItems
, ",", ")"), Put(')');
1434 void Unparse(const format::FormatItem
&x
) { // R1304, R1306, R1321
1435 if (x
.repeatCount
) {
1436 Walk(*x
.repeatCount
);
1438 std::visit(common::visitors
{
1439 [&](const std::string
&y
) { PutNormalized(y
); },
1440 [&](const std::list
<format::FormatItem
> &y
) {
1441 Walk("(", y
, ",", ")");
1443 [&](const auto &y
) { Walk(y
); },
1448 const format::IntrinsicTypeDataEditDesc
&x
) { // R1307(1/2) - R1311
1451 case format::IntrinsicTypeDataEditDesc::Kind::x: \
1469 Walk(x
.width
), Walk(".", x
.digits
), Walk("E", x
.exponentWidth
);
1471 void Unparse(const format::DerivedTypeDataEditDesc
&x
) { // R1307(2/2), R1312
1473 if (!x
.type
.empty()) {
1474 Put('"'), Put(x
.type
), Put('"');
1476 Walk("(", x
.parameters
, ",", ")");
1478 void Unparse(const format::ControlEditDesc
&x
) { // R1313, R1315-R1320
1480 case format::ControlEditDesc::Kind::T
:
1484 case format::ControlEditDesc::Kind::TL
:
1488 case format::ControlEditDesc::Kind::TR
:
1492 case format::ControlEditDesc::Kind::X
:
1498 case format::ControlEditDesc::Kind::Slash
:
1504 case format::ControlEditDesc::Kind::Colon
:
1507 case format::ControlEditDesc::Kind::P
:
1512 case format::ControlEditDesc::Kind::x: \
1529 case format::ControlEditDesc::Kind::Dollar
:
1532 case format::ControlEditDesc::Kind::Backslash
:
1538 void Before(const MainProgram
&x
) { // R1401
1539 if (!std::get
<std::optional
<Statement
<ProgramStmt
>>>(x
.t
)) {
1543 void Before(const ProgramStmt
&) { // R1402
1544 Word("PROGRAM "), Indent();
1546 void Unparse(const EndProgramStmt
&x
) { // R1403
1547 EndSubprogram("PROGRAM", x
.v
);
1549 void Before(const ModuleStmt
&) { // R1405
1550 Word("MODULE "), Indent();
1552 void Unparse(const EndModuleStmt
&x
) { // R1406
1553 EndSubprogram("MODULE", x
.v
);
1555 void Unparse(const UseStmt
&x
) { // R1409
1556 Word("USE"), Walk(", ", x
.nature
), Put(" :: "), Walk(x
.moduleName
);
1557 std::visit(common::visitors
{
1558 [&](const std::list
<Rename
> &y
) { Walk(", ", y
, ", "); },
1559 [&](const std::list
<Only
> &y
) { Walk(", ONLY: ", y
, ", "); },
1563 void Unparse(const Rename
&x
) { // R1411
1564 std::visit(common::visitors
{
1565 [&](const Rename::Names
&y
) { Walk(y
.t
, " => "); },
1566 [&](const Rename::Operators
&y
) {
1567 Word("OPERATOR("), Walk(y
.t
, ") => OPERATOR("), Put(")");
1572 void Unparse(const SubmoduleStmt
&x
) { // R1417
1573 Word("SUBMODULE ("), WalkTupleElements(x
.t
, ")"), Indent();
1575 void Unparse(const ParentIdentifier
&x
) { // R1418
1576 Walk(std::get
<Name
>(x
.t
)), Walk(":", std::get
<std::optional
<Name
>>(x
.t
));
1578 void Unparse(const EndSubmoduleStmt
&x
) { // R1419
1579 EndSubprogram("SUBMODULE", x
.v
);
1581 void Unparse(const BlockDataStmt
&x
) { // R1421
1582 Word("BLOCK DATA"), Walk(" ", x
.v
), Indent();
1584 void Unparse(const EndBlockDataStmt
&x
) { // R1422
1585 EndSubprogram("BLOCK DATA", x
.v
);
1588 void Unparse(const InterfaceStmt
&x
) { // R1503
1589 std::visit(common::visitors
{
1590 [&](const std::optional
<GenericSpec
> &y
) {
1591 Word("INTERFACE"), Walk(" ", y
);
1593 [&](const Abstract
&) { Word("ABSTRACT INTERFACE"); },
1598 void Unparse(const EndInterfaceStmt
&x
) { // R1504
1599 Outdent(), Word("END INTERFACE"), Walk(" ", x
.v
);
1601 void Unparse(const ProcedureStmt
&x
) { // R1506
1602 if (std::get
<ProcedureStmt::Kind
>(x
.t
) ==
1603 ProcedureStmt::Kind::ModuleProcedure
) {
1606 Word("PROCEDURE :: ");
1607 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
1609 void Before(const GenericSpec
&x
) { // R1508, R1509
1612 [&](const DefinedOperator
&) { Word("OPERATOR("); },
1613 [&](const GenericSpec::Assignment
&) { Word("ASSIGNMENT(=)"); },
1614 [&](const GenericSpec::ReadFormatted
&) {
1615 Word("READ(FORMATTED)");
1617 [&](const GenericSpec::ReadUnformatted
&) {
1618 Word("READ(UNFORMATTED)");
1620 [&](const GenericSpec::WriteFormatted
&) {
1621 Word("WRITE(FORMATTED)");
1623 [&](const GenericSpec::WriteUnformatted
&) {
1624 Word("WRITE(UNFORMATTED)");
1626 [](const auto &) {},
1630 void Post(const GenericSpec
&x
) {
1631 std::visit(common::visitors
{
1632 [&](const DefinedOperator
&) { Put(')'); },
1633 [](const auto &) {},
1637 void Unparse(const GenericStmt
&x
) { // R1510
1638 Word("GENERIC"), Walk(", ", std::get
<std::optional
<AccessSpec
>>(x
.t
));
1639 Put(" :: "), Walk(std::get
<GenericSpec
>(x
.t
)), Put(" => ");
1640 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
1642 void Unparse(const ExternalStmt
&x
) { // R1511
1643 Word("EXTERNAL :: "), Walk(x
.v
, ", ");
1645 void Unparse(const ProcedureDeclarationStmt
&x
) { // R1512
1646 Word("PROCEDURE("), Walk(std::get
<std::optional
<ProcInterface
>>(x
.t
));
1647 Put(')'), Walk(", ", std::get
<std::list
<ProcAttrSpec
>>(x
.t
), ", ");
1648 Put(" :: "), Walk(std::get
<std::list
<ProcDecl
>>(x
.t
), ", ");
1650 void Unparse(const ProcDecl
&x
) { // R1515
1651 Walk(std::get
<Name
>(x
.t
));
1652 Walk(" => ", std::get
<std::optional
<ProcPointerInit
>>(x
.t
));
1654 void Unparse(const IntrinsicStmt
&x
) { // R1519
1655 Word("INTRINSIC :: "), Walk(x
.v
, ", ");
1657 void Unparse(const FunctionReference
&x
) { // R1520
1658 Walk(std::get
<ProcedureDesignator
>(x
.v
.t
));
1659 Put('('), Walk(std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
), ", "), Put(')');
1661 void Unparse(const CallStmt
&x
) { // R1521
1662 if (asFortran_
&& x
.typedCall
.get()) {
1664 asFortran_
->call(out_
, *x
.typedCall
);
1667 const auto &pd
{std::get
<ProcedureDesignator
>(x
.v
.t
)};
1668 const auto &args
{std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
)};
1669 Word("CALL "), Walk(pd
);
1671 if (std::holds_alternative
<ProcComponentRef
>(pd
.u
)) {
1672 Put("()"); // pgf90 crashes on CALL to tbp without parentheses
1675 Walk("(", args
, ", ", ")");
1679 void Unparse(const ActualArgSpec
&x
) { // R1523
1680 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
1681 Walk(std::get
<ActualArg
>(x
.t
));
1683 void Unparse(const ActualArg::PercentRef
&x
) { // R1524
1684 Word("%REF("), Walk(x
.v
), Put(')');
1686 void Unparse(const ActualArg::PercentVal
&x
) {
1687 Word("%VAL("), Walk(x
.v
), Put(')');
1689 void Before(const AltReturnSpec
&) { // R1525
1692 void Post(const PrefixSpec::Elemental
) { Word("ELEMENTAL"); } // R1527
1693 void Post(const PrefixSpec::Impure
) { Word("IMPURE"); }
1694 void Post(const PrefixSpec::Module
) { Word("MODULE"); }
1695 void Post(const PrefixSpec::Non_Recursive
) { Word("NON_RECURSIVE"); }
1696 void Post(const PrefixSpec::Pure
) { Word("PURE"); }
1697 void Post(const PrefixSpec::Recursive
) { Word("RECURSIVE"); }
1698 void Unparse(const FunctionStmt
&x
) { // R1530
1699 Walk("", std::get
<std::list
<PrefixSpec
>>(x
.t
), " ", " ");
1700 Word("FUNCTION "), Walk(std::get
<Name
>(x
.t
)), Put("(");
1701 Walk(std::get
<std::list
<Name
>>(x
.t
), ", "), Put(')');
1702 Walk(" ", std::get
<std::optional
<Suffix
>>(x
.t
)), Indent();
1704 void Unparse(const Suffix
&x
) { // R1532
1706 Word("RESULT("), Walk(x
.resultName
), Put(')');
1707 Walk(" ", x
.binding
);
1712 void Unparse(const EndFunctionStmt
&x
) { // R1533
1713 EndSubprogram("FUNCTION", x
.v
);
1715 void Unparse(const SubroutineStmt
&x
) { // R1535
1716 Walk("", std::get
<std::list
<PrefixSpec
>>(x
.t
), " ", " ");
1717 Word("SUBROUTINE "), Walk(std::get
<Name
>(x
.t
));
1718 const auto &args
{std::get
<std::list
<DummyArg
>>(x
.t
)};
1719 const auto &bind
{std::get
<std::optional
<LanguageBindingSpec
>>(x
.t
)};
1723 Walk(" (", args
, ", ", ")");
1728 void Unparse(const EndSubroutineStmt
&x
) { // R1537
1729 EndSubprogram("SUBROUTINE", x
.v
);
1731 void Before(const MpSubprogramStmt
&) { // R1539
1732 Word("MODULE PROCEDURE "), Indent();
1734 void Unparse(const EndMpSubprogramStmt
&x
) { // R1540
1735 EndSubprogram("PROCEDURE", x
.v
);
1737 void Unparse(const EntryStmt
&x
) { // R1541
1738 Word("ENTRY "), Walk(std::get
<Name
>(x
.t
)), Put("(");
1739 Walk(std::get
<std::list
<DummyArg
>>(x
.t
), ", "), Put(")");
1740 Walk(" ", std::get
<std::optional
<Suffix
>>(x
.t
));
1742 void Unparse(const ReturnStmt
&x
) { // R1542
1743 Word("RETURN"), Walk(" ", x
.v
);
1745 void Unparse(const ContainsStmt
&) { // R1543
1750 void Unparse(const StmtFunctionStmt
&x
) { // R1544
1751 Walk(std::get
<Name
>(x
.t
)), Put('(');
1752 Walk(std::get
<std::list
<Name
>>(x
.t
), ", "), Put(") = ");
1753 Walk(std::get
<Scalar
<Expr
>>(x
.t
));
1756 // Directives, extensions, and deprecated constructs
1757 void Unparse(const CompilerDirective
&x
) {
1760 [&](const std::list
<CompilerDirective::IgnoreTKR
> &tkr
) {
1761 Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty
1762 Walk(" ", tkr
, ", ");
1764 [&](const std::list
<CompilerDirective::NameValue
> &names
) {
1765 Walk("!DIR$ ", names
, " ");
1771 void Unparse(const CompilerDirective::IgnoreTKR
&x
) {
1772 const auto &list
{std::get
<std::list
<const char *>>(x
.t
)};
1773 if (!list
.empty()) {
1775 for (const char *tkr
: list
) {
1780 Walk(std::get
<Name
>(x
.t
));
1782 void Unparse(const CompilerDirective::NameValue
&x
) {
1783 Walk(std::get
<Name
>(x
.t
));
1784 Walk("=", std::get
<std::optional
<std::uint64_t>>(x
.t
));
1787 // OpenACC Directives & Clauses
1788 void Unparse(const AccAtomicCapture
&x
) {
1790 Word("!$ACC CAPTURE");
1793 Walk(std::get
<AccAtomicCapture::Stmt1
>(x
.t
));
1795 Walk(std::get
<AccAtomicCapture::Stmt2
>(x
.t
));
1797 Word("!$ACC END ATOMIC\n");
1800 void Unparse(const AccAtomicRead
&x
) {
1802 Word("!$ACC ATOMIC READ");
1805 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1807 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1810 void Unparse(const AccAtomicWrite
&x
) {
1812 Word("!$ACC ATOMIC WRITE");
1815 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1817 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1820 void Unparse(const AccAtomicUpdate
&x
) {
1822 Word("!$ACC ATOMIC UPDATE");
1825 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1827 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1830 void Unparse(const llvm::acc::Directive
&x
) {
1831 Word(llvm::acc::getOpenACCDirectiveName(x
).str());
1833 #define GEN_FLANG_CLAUSE_UNPARSE
1834 #include "llvm/Frontend/OpenACC/ACC.inc"
1835 void Unparse(const AccObjectListWithModifier
&x
) {
1836 Walk(std::get
<std::optional
<AccDataModifier
>>(x
.t
), ":");
1837 Walk(std::get
<AccObjectList
>(x
.t
));
1839 void Unparse(const AccDataModifier::Modifier
&x
) {
1840 Word(AccDataModifier::EnumToString(x
));
1842 void Unparse(const AccBindClause
&x
) {
1843 std::visit(common::visitors
{
1844 [&](const Name
&y
) { Put('('), Walk(y
), Put(')'); },
1845 [&](const ScalarDefaultCharExpr
&y
) {
1846 Put('('), Walk(y
), Put(')');
1851 void Unparse(const AccDefaultClause
&x
) {
1853 case llvm::acc::DefaultValue::ACC_Default_none
:
1856 case llvm::acc::DefaultValue::ACC_Default_present
:
1861 void Unparse(const AccClauseList
&x
) { Walk(" ", x
.v
, " "); }
1862 void Unparse(const AccGangArgument
&x
) {
1863 Walk("NUM:", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
1864 Walk(", STATIC:", std::get
<std::optional
<AccSizeExpr
>>(x
.t
));
1866 void Unparse(const OpenACCBlockConstruct
&x
) {
1869 Walk(std::get
<AccBeginBlockDirective
>(x
.t
));
1872 Walk(std::get
<Block
>(x
.t
), "");
1875 Walk(std::get
<AccEndBlockDirective
>(x
.t
));
1879 void Unparse(const OpenACCLoopConstruct
&x
) {
1882 Walk(std::get
<AccBeginLoopDirective
>(x
.t
));
1885 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
1887 void Unparse(const AccBeginLoopDirective
&x
) {
1888 Walk(std::get
<AccLoopDirective
>(x
.t
));
1889 Walk(std::get
<AccClauseList
>(x
.t
));
1891 void Unparse(const OpenACCStandaloneConstruct
&x
) {
1894 Walk(std::get
<AccStandaloneDirective
>(x
.t
));
1895 Walk(std::get
<AccClauseList
>(x
.t
));
1899 void Unparse(const OpenACCStandaloneDeclarativeConstruct
&x
) {
1902 Walk(std::get
<AccDeclarativeDirective
>(x
.t
));
1903 Walk(std::get
<AccClauseList
>(x
.t
));
1907 void Unparse(const OpenACCCombinedConstruct
&x
) {
1910 Walk(std::get
<AccBeginCombinedDirective
>(x
.t
));
1913 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
1915 Walk("!$ACC END ", std::get
<std::optional
<AccEndCombinedDirective
>>(x
.t
),
1919 void Unparse(const OpenACCRoutineConstruct
&x
) {
1921 Word("!$ACC ROUTINE");
1922 Walk("(", std::get
<std::optional
<Name
>>(x
.t
), ")");
1923 Walk(std::get
<AccClauseList
>(x
.t
));
1927 void Unparse(const AccObject
&x
) {
1928 std::visit(common::visitors
{
1929 [&](const Designator
&y
) { Walk(y
); },
1930 [&](const Name
&y
) { Put("/"), Walk(y
), Put("/"); },
1934 void Unparse(const AccObjectList
&x
) { Walk(x
.v
, ","); }
1935 void Unparse(const AccReductionOperator::Operator
&x
) {
1936 Word(AccReductionOperator::EnumToString(x
));
1938 void Unparse(const AccObjectListWithReduction
&x
) {
1939 Walk(std::get
<AccReductionOperator
>(x
.t
));
1941 Walk(std::get
<AccObjectList
>(x
.t
));
1943 void Unparse(const OpenACCCacheConstruct
&x
) {
1947 Walk(std::get
<AccObjectListWithModifier
>(x
.t
));
1952 void Unparse(const AccWaitArgument
&x
) {
1953 Walk("DEVNUM:", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
), ":");
1954 Walk(std::get
<std::list
<ScalarIntExpr
>>(x
.t
), ",");
1956 void Unparse(const OpenACCWaitConstruct
&x
) {
1960 Walk(std::get
<std::optional
<AccWaitArgument
>>(x
.t
));
1961 Walk(std::get
<AccClauseList
>(x
.t
));
1967 // OpenMP Clauses & Directives
1968 void Unparse(const OmpObject
&x
) {
1969 std::visit(common::visitors
{
1970 [&](const Designator
&y
) { Walk(y
); },
1971 [&](const Name
&y
) { Put("/"), Walk(y
), Put("/"); },
1975 void Unparse(const OmpMapType::Always
&) { Word("ALWAYS,"); }
1976 void Unparse(const OmpMapClause
&x
) {
1977 Walk(std::get
<std::optional
<OmpMapType
>>(x
.t
), ":");
1978 Walk(std::get
<OmpObjectList
>(x
.t
));
1980 void Unparse(const OmpScheduleModifier
&x
) {
1981 Walk(std::get
<OmpScheduleModifier::Modifier1
>(x
.t
));
1982 Walk(",", std::get
<std::optional
<OmpScheduleModifier::Modifier2
>>(x
.t
));
1984 void Unparse(const OmpScheduleClause
&x
) {
1985 Walk(std::get
<std::optional
<OmpScheduleModifier
>>(x
.t
), ":");
1986 Walk(std::get
<OmpScheduleClause::ScheduleType
>(x
.t
));
1987 Walk(",", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
1989 void Unparse(const OmpAlignedClause
&x
) {
1990 Walk(std::get
<std::list
<Name
>>(x
.t
), ",");
1991 Walk(std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
1993 void Unparse(const OmpIfClause
&x
) {
1994 Walk(std::get
<std::optional
<OmpIfClause::DirectiveNameModifier
>>(x
.t
), ":");
1995 Walk(std::get
<ScalarLogicalExpr
>(x
.t
));
1997 void Unparse(const OmpLinearClause::WithoutModifier
&x
) {
1998 Walk(x
.names
, ", ");
2001 void Unparse(const OmpLinearClause::WithModifier
&x
) {
2002 Walk(x
.modifier
), Put("("), Walk(x
.names
, ","), Put(")");
2005 void Unparse(const OmpReductionClause
&x
) {
2006 Walk(std::get
<OmpReductionOperator
>(x
.t
));
2008 Walk(std::get
<OmpObjectList
>(x
.t
));
2010 void Unparse(const OmpAllocateClause
&x
) {
2011 Walk(std::get
<std::optional
<OmpAllocateClause::Allocator
>>(x
.t
));
2013 Walk(std::get
<OmpObjectList
>(x
.t
));
2015 void Unparse(const OmpDependSinkVecLength
&x
) {
2016 Walk(std::get
<DefinedOperator
>(x
.t
));
2017 Walk(std::get
<ScalarIntConstantExpr
>(x
.t
));
2019 void Unparse(const OmpDependSinkVec
&x
) {
2020 Walk(std::get
<Name
>(x
.t
));
2021 Walk(std::get
<std::optional
<OmpDependSinkVecLength
>>(x
.t
));
2023 void Unparse(const OmpDependClause::InOut
&x
) {
2025 Walk(std::get
<OmpDependenceType
>(x
.t
));
2027 Walk(std::get
<std::list
<Designator
>>(x
.t
), ",");
2030 bool Pre(const OmpDependClause
&x
) {
2031 return std::visit(common::visitors
{
2032 [&](const OmpDependClause::Source
&) {
2036 [&](const OmpDependClause::Sink
&y
) {
2042 [&](const OmpDependClause::InOut
&) { return true; },
2046 void Unparse(const OmpDefaultmapClause
&x
) {
2047 Walk(std::get
<OmpDefaultmapClause::ImplicitBehavior
>(x
.t
));
2049 std::get
<std::optional
<OmpDefaultmapClause::VariableCategory
>>(x
.t
));
2051 #define GEN_FLANG_CLAUSE_UNPARSE
2052 #include "llvm/Frontend/OpenMP/OMP.inc"
2053 void Unparse(const OmpLoopDirective
&x
) {
2055 case llvm::omp::Directive::OMPD_distribute
:
2056 Word("DISTRIBUTE ");
2058 case llvm::omp::Directive::OMPD_distribute_parallel_do
:
2059 Word("DISTRIBUTE PARALLEL DO ");
2061 case llvm::omp::Directive::OMPD_distribute_parallel_do_simd
:
2062 Word("DISTRIBUTE PARALLEL DO SIMD ");
2064 case llvm::omp::Directive::OMPD_distribute_simd
:
2065 Word("DISTRIBUTE SIMD ");
2067 case llvm::omp::Directive::OMPD_do
:
2070 case llvm::omp::Directive::OMPD_do_simd
:
2073 case llvm::omp::Directive::OMPD_parallel_do
:
2074 Word("PARALLEL DO ");
2076 case llvm::omp::Directive::OMPD_parallel_do_simd
:
2077 Word("PARALLEL DO SIMD ");
2079 case llvm::omp::Directive::OMPD_simd
:
2082 case llvm::omp::Directive::OMPD_target_parallel_do
:
2083 Word("TARGET PARALLEL DO ");
2085 case llvm::omp::Directive::OMPD_target_parallel_do_simd
:
2086 Word("TARGET PARALLEL DO SIMD ");
2088 case llvm::omp::Directive::OMPD_target_teams_distribute
:
2089 Word("TARGET TEAMS DISTRIBUTE ");
2091 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do
:
2092 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO ");
2094 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd
:
2095 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2097 case llvm::omp::Directive::OMPD_target_teams_distribute_simd
:
2098 Word("TARGET TEAMS DISTRIBUTE SIMD ");
2100 case llvm::omp::Directive::OMPD_target_simd
:
2101 Word("TARGET SIMD ");
2103 case llvm::omp::Directive::OMPD_taskloop
:
2106 case llvm::omp::Directive::OMPD_taskloop_simd
:
2107 Word("TASKLOOP SIMD ");
2109 case llvm::omp::Directive::OMPD_teams_distribute
:
2110 Word("TEAMS DISTRIBUTE ");
2112 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do
:
2113 Word("TEAMS DISTRIBUTE PARALLEL DO ");
2115 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd
:
2116 Word("TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2118 case llvm::omp::Directive::OMPD_teams_distribute_simd
:
2119 Word("TEAMS DISTRIBUTE SIMD ");
2125 void Unparse(const OmpObjectList
&x
) { Walk(x
.v
, ","); }
2126 void Unparse(const OmpSimpleStandaloneDirective
&x
) {
2128 case llvm::omp::Directive::OMPD_barrier
:
2131 case llvm::omp::Directive::OMPD_taskwait
:
2134 case llvm::omp::Directive::OMPD_taskyield
:
2137 case llvm::omp::Directive::OMPD_target_enter_data
:
2138 Word("TARGET ENTER DATA ");
2140 case llvm::omp::Directive::OMPD_target_exit_data
:
2141 Word("TARGET EXIT DATA ");
2143 case llvm::omp::Directive::OMPD_target_update
:
2144 Word("TARGET UPDATE ");
2146 case llvm::omp::Directive::OMPD_ordered
:
2150 // Nothing to be done
2154 void Unparse(const OmpBlockDirective
&x
) {
2156 case llvm::omp::Directive::OMPD_master
:
2159 case llvm::omp::Directive::OMPD_ordered
:
2162 case llvm::omp::Directive::OMPD_parallel_workshare
:
2163 Word("PARALLEL WORKSHARE ");
2165 case llvm::omp::Directive::OMPD_parallel
:
2168 case llvm::omp::Directive::OMPD_single
:
2171 case llvm::omp::Directive::OMPD_target_data
:
2172 Word("TARGET DATA ");
2174 case llvm::omp::Directive::OMPD_target_parallel
:
2175 Word("TARGET PARALLEL ");
2177 case llvm::omp::Directive::OMPD_target_teams
:
2178 Word("TARGET TEAMS ");
2180 case llvm::omp::Directive::OMPD_target
:
2183 case llvm::omp::Directive::OMPD_taskgroup
:
2186 case llvm::omp::Directive::OMPD_task
:
2189 case llvm::omp::Directive::OMPD_teams
:
2192 case llvm::omp::Directive::OMPD_workshare
:
2196 // Nothing to be done
2200 void Unparse(const OmpAtomicClauseList
&x
) { Walk(" ", x
.v
, " "); }
2202 void Unparse(const OmpAtomic
&x
) {
2204 Word("!$OMP ATOMIC");
2205 Walk(std::get
<OmpAtomicClauseList
>(x
.t
));
2208 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2210 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2213 void Unparse(const OmpAtomicCapture
&x
) {
2215 Word("!$OMP ATOMIC");
2216 Walk(std::get
<0>(x
.t
));
2218 Walk(std::get
<2>(x
.t
));
2221 Walk(std::get
<OmpAtomicCapture::Stmt1
>(x
.t
));
2223 Walk(std::get
<OmpAtomicCapture::Stmt2
>(x
.t
));
2225 Word("!$OMP END ATOMIC\n");
2228 void Unparse(const OmpAtomicRead
&x
) {
2230 Word("!$OMP ATOMIC");
2231 Walk(std::get
<0>(x
.t
));
2233 Walk(std::get
<2>(x
.t
));
2236 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2238 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2241 void Unparse(const OmpAtomicUpdate
&x
) {
2243 Word("!$OMP ATOMIC");
2244 Walk(std::get
<0>(x
.t
));
2246 Walk(std::get
<2>(x
.t
));
2249 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2251 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2254 void Unparse(const OmpAtomicWrite
&x
) {
2256 Word("!$OMP ATOMIC");
2257 Walk(std::get
<0>(x
.t
));
2259 Walk(std::get
<2>(x
.t
));
2262 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2264 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2267 void Unparse(const OpenMPExecutableAllocate
&x
) {
2269 Word("!$OMP ALLOCATE");
2270 Walk(" (", std::get
<std::optional
<OmpObjectList
>>(x
.t
), ")");
2271 Walk(std::get
<OmpClauseList
>(x
.t
));
2274 Walk(std::get
<Statement
<AllocateStmt
>>(x
.t
));
2276 void Unparse(const OpenMPDeclarativeAllocate
&x
) {
2278 Word("!$OMP ALLOCATE");
2280 Walk(std::get
<OmpObjectList
>(x
.t
));
2282 Walk(std::get
<OmpClauseList
>(x
.t
));
2286 void Unparse(const OmpCriticalDirective
&x
) {
2288 Word("!$OMP CRITICAL");
2289 Walk(" (", std::get
<std::optional
<Name
>>(x
.t
), ")");
2290 Walk(std::get
<std::optional
<OmpClause
>>(x
.t
));
2294 void Unparse(const OmpEndCriticalDirective
&x
) {
2296 Word("!$OMP END CRITICAL");
2297 Walk(" (", std::get
<std::optional
<Name
>>(x
.t
), ")");
2301 void Unparse(const OpenMPCriticalConstruct
&x
) {
2302 Walk(std::get
<OmpCriticalDirective
>(x
.t
));
2303 Walk(std::get
<Block
>(x
.t
), "");
2304 Walk(std::get
<OmpEndCriticalDirective
>(x
.t
));
2306 void Unparse(const OmpDeclareTargetWithList
&x
) {
2307 Put("("), Walk(x
.v
), Put(")");
2309 void Unparse(const OmpReductionInitializerClause
&x
) {
2310 Word(" INITIALIZER(OMP_PRIV = ");
2314 void Unparse(const OmpReductionCombiner::FunctionCombiner
&x
) {
2315 const auto &pd
= std::get
<ProcedureDesignator
>(x
.v
.t
);
2316 const auto &args
= std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
);
2319 if (std::holds_alternative
<ProcComponentRef
>(pd
.u
)) {
2323 Walk("(", args
, ", ", ")");
2326 void Unparse(const OpenMPDeclareReductionConstruct
&x
) {
2328 Walk(std::get
<OmpReductionOperator
>(x
.t
)), Put(" : ");
2329 Walk(std::get
<std::list
<DeclarationTypeSpec
>>(x
.t
), ","), Put(" : ");
2330 Walk(std::get
<OmpReductionCombiner
>(x
.t
));
2332 Walk(std::get
<std::optional
<OmpReductionInitializerClause
>>(x
.t
));
2334 bool Pre(const OpenMPDeclarativeConstruct
&x
) {
2337 return std::visit(common::visitors
{
2338 [&](const OpenMPDeclarativeAllocate
&z
) {
2340 Walk(std::get
<OmpObjectList
>(z
.t
));
2342 Walk(std::get
<OmpClauseList
>(z
.t
));
2347 [&](const OpenMPDeclareReductionConstruct
&) {
2348 Word("DECLARE REDUCTION ");
2351 [&](const OpenMPDeclareSimdConstruct
&y
) {
2352 Word("DECLARE SIMD ");
2353 Walk("(", std::get
<std::optional
<Name
>>(y
.t
), ")");
2354 Walk(std::get
<OmpClauseList
>(y
.t
));
2359 [&](const OpenMPDeclareTargetConstruct
&) {
2360 Word("DECLARE TARGET ");
2363 [&](const OpenMPThreadprivate
&) {
2364 Word("THREADPRIVATE (");
2370 void Post(const OpenMPDeclarativeConstruct
&) {
2374 void Post(const OpenMPThreadprivate
&) {
2378 void Unparse(const OmpSectionsDirective
&x
) {
2380 case llvm::omp::Directive::OMPD_sections
:
2383 case llvm::omp::Directive::OMPD_parallel_sections
:
2384 Word("PARALLEL SECTIONS ");
2390 void Unparse(const OmpSectionBlocks
&x
) {
2391 for (const auto &y
: x
.v
) {
2393 Word("!$OMP SECTION");
2396 Walk(y
, ""); // y is Block
2399 void Unparse(const OpenMPSectionsConstruct
&x
) {
2402 Walk(std::get
<OmpBeginSectionsDirective
>(x
.t
));
2405 Walk(std::get
<OmpSectionBlocks
>(x
.t
));
2408 Walk(std::get
<OmpEndSectionsDirective
>(x
.t
));
2412 void Unparse(const OpenMPCancellationPointConstruct
&x
) {
2414 Word("!$OMP CANCELLATION POINT ");
2415 Walk(std::get
<OmpCancelType
>(x
.t
));
2419 void Unparse(const OpenMPCancelConstruct
&x
) {
2421 Word("!$OMP CANCEL ");
2422 Walk(std::get
<OmpCancelType
>(x
.t
));
2423 Walk(std::get
<std::optional
<OpenMPCancelConstruct::If
>>(x
.t
));
2427 void Unparse(const OmpMemoryOrderClause
&x
) { Walk(x
.v
); }
2428 void Unparse(const OmpAtomicClause
&x
) {
2429 std::visit(common::visitors
{
2430 [&](const OmpMemoryOrderClause
&y
) { Walk(y
); },
2431 [&](const OmpClause
&z
) { Walk(z
); },
2435 void Unparse(const OpenMPFlushConstruct
&x
) {
2437 Word("!$OMP FLUSH ");
2438 Walk(std::get
<std::optional
<std::list
<OmpMemoryOrderClause
>>>(x
.t
));
2439 Walk(" (", std::get
<std::optional
<OmpObjectList
>>(x
.t
), ")");
2443 void Unparse(const OmpEndLoopDirective
&x
) {
2446 Walk(std::get
<OmpLoopDirective
>(x
.t
));
2447 Walk(std::get
<OmpClauseList
>(x
.t
));
2451 void Unparse(const OmpClauseList
&x
) { Walk(" ", x
.v
, " "); }
2452 void Unparse(const OpenMPSimpleStandaloneConstruct
&x
) {
2455 Walk(std::get
<OmpSimpleStandaloneDirective
>(x
.t
));
2456 Walk(std::get
<OmpClauseList
>(x
.t
));
2460 void Unparse(const OpenMPBlockConstruct
&x
) {
2463 Walk(std::get
<OmpBeginBlockDirective
>(x
.t
));
2466 Walk(std::get
<Block
>(x
.t
), "");
2469 Walk(std::get
<OmpEndBlockDirective
>(x
.t
));
2473 void Unparse(const OpenMPLoopConstruct
&x
) {
2476 Walk(std::get
<OmpBeginLoopDirective
>(x
.t
));
2479 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
2480 Walk(std::get
<std::optional
<OmpEndLoopDirective
>>(x
.t
));
2482 void Unparse(const BasedPointer
&x
) {
2483 Put('('), Walk(std::get
<0>(x
.t
)), Put(","), Walk(std::get
<1>(x
.t
));
2484 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")"), Put(')');
2486 void Unparse(const BasedPointerStmt
&x
) { Walk("POINTER ", x
.v
, ","); }
2487 void Post(const StructureField
&x
) {
2488 if (const auto *def
{std::get_if
<Statement
<DataComponentDefStmt
>>(&x
.u
)}) {
2489 for (const auto &decl
:
2490 std::get
<std::list
<ComponentDecl
>>(def
->statement
.t
)) {
2491 structureComponents_
.insert(std::get
<Name
>(decl
.t
).source
);
2495 void Unparse(const StructureStmt
&x
) {
2497 if (std::get
<bool>(x
.t
)) { // slashes around name
2498 Put('/'), Walk(std::get
<Name
>(x
.t
)), Put('/');
2499 Walk(" ", std::get
<std::list
<EntityDecl
>>(x
.t
), ", ");
2501 CHECK(std::get
<std::list
<EntityDecl
>>(x
.t
).empty());
2502 Walk(std::get
<Name
>(x
.t
));
2506 void Post(const Union::UnionStmt
&) { Word("UNION"), Indent(); }
2507 void Post(const Union::EndUnionStmt
&) { Outdent(), Word("END UNION"); }
2508 void Post(const Map::MapStmt
&) { Word("MAP"), Indent(); }
2509 void Post(const Map::EndMapStmt
&) { Outdent(), Word("END MAP"); }
2510 void Post(const StructureDef::EndStructureStmt
&) {
2511 Outdent(), Word("END STRUCTURE");
2513 void Unparse(const OldParameterStmt
&x
) {
2514 Word("PARAMETER "), Walk(x
.v
, ", ");
2516 void Unparse(const ArithmeticIfStmt
&x
) {
2517 Word("IF ("), Walk(std::get
<Expr
>(x
.t
)), Put(") ");
2518 Walk(std::get
<1>(x
.t
)), Put(", ");
2519 Walk(std::get
<2>(x
.t
)), Put(", ");
2520 Walk(std::get
<3>(x
.t
));
2522 void Unparse(const AssignStmt
&x
) {
2523 Word("ASSIGN "), Walk(std::get
<Label
>(x
.t
));
2524 Word(" TO "), Walk(std::get
<Name
>(x
.t
));
2526 void Unparse(const AssignedGotoStmt
&x
) {
2527 Word("GO TO "), Walk(std::get
<Name
>(x
.t
));
2528 Walk(", (", std::get
<std::list
<Label
>>(x
.t
), ", ", ")");
2530 void Unparse(const PauseStmt
&x
) { Word("PAUSE"), Walk(" ", x
.v
); }
2532 #define WALK_NESTED_ENUM(CLASS, ENUM) \
2533 void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); }
2534 WALK_NESTED_ENUM(AccessSpec
, Kind
) // R807
2535 WALK_NESTED_ENUM(common
, TypeParamAttr
) // R734
2536 WALK_NESTED_ENUM(IntentSpec
, Intent
) // R826
2537 WALK_NESTED_ENUM(ImplicitStmt
, ImplicitNoneNameSpec
) // R866
2538 WALK_NESTED_ENUM(ConnectSpec::CharExpr
, Kind
) // R1205
2539 WALK_NESTED_ENUM(IoControlSpec::CharExpr
, Kind
)
2540 WALK_NESTED_ENUM(InquireSpec::CharVar
, Kind
)
2541 WALK_NESTED_ENUM(InquireSpec::IntVar
, Kind
)
2542 WALK_NESTED_ENUM(InquireSpec::LogVar
, Kind
)
2543 WALK_NESTED_ENUM(ProcedureStmt
, Kind
) // R1506
2544 WALK_NESTED_ENUM(UseStmt
, ModuleNature
) // R1410
2545 WALK_NESTED_ENUM(OmpProcBindClause
, Type
) // OMP PROC_BIND
2546 WALK_NESTED_ENUM(OmpDefaultClause
, Type
) // OMP DEFAULT
2547 WALK_NESTED_ENUM(OmpDefaultmapClause
, ImplicitBehavior
) // OMP DEFAULTMAP
2548 WALK_NESTED_ENUM(OmpDefaultmapClause
, VariableCategory
) // OMP DEFAULTMAP
2549 WALK_NESTED_ENUM(OmpScheduleModifierType
, ModType
) // OMP schedule-modifier
2550 WALK_NESTED_ENUM(OmpLinearModifier
, Type
) // OMP linear-modifier
2551 WALK_NESTED_ENUM(OmpDependenceType
, Type
) // OMP dependence-type
2552 WALK_NESTED_ENUM(OmpMapType
, Type
) // OMP map-type
2553 WALK_NESTED_ENUM(OmpScheduleClause
, ScheduleType
) // OMP schedule-type
2554 WALK_NESTED_ENUM(OmpIfClause
, DirectiveNameModifier
) // OMP directive-modifier
2555 WALK_NESTED_ENUM(OmpCancelType
, Type
) // OMP cancel-type
2556 #undef WALK_NESTED_ENUM
2558 void Done() const { CHECK(indent_
== 0); }
2562 void Put(const char *);
2563 void Put(const std::string
&);
2564 void PutNormalized(const std::string
&);
2565 void PutKeywordLetter(char);
2566 void Word(const char *);
2567 void Word(const std::string
&);
2568 void Indent() { indent_
+= indentationAmount_
; }
2570 CHECK(indent_
>= indentationAmount_
);
2571 indent_
-= indentationAmount_
;
2573 void BeginOpenMP() { openmpDirective_
= true; }
2574 void EndOpenMP() { openmpDirective_
= false; }
2575 void BeginOpenACC() { openaccDirective_
= true; }
2576 void EndOpenACC() { openaccDirective_
= false; }
2578 // Call back to the traversal framework.
2579 template <typename T
> void Walk(const T
&x
) {
2580 Fortran::parser::Walk(x
, *this);
2583 // Traverse a std::optional<> value. Emit a prefix and/or a suffix string
2584 // only when it contains a value.
2585 template <typename A
>
2587 const char *prefix
, const std::optional
<A
> &x
, const char *suffix
= "") {
2589 Word(prefix
), Walk(*x
), Word(suffix
);
2592 template <typename A
>
2593 void Walk(const std::optional
<A
> &x
, const char *suffix
= "") {
2594 return Walk("", x
, suffix
);
2597 // Traverse a std::list<>. Separate the elements with an optional string.
2598 // Emit a prefix and/or a suffix string only when the list is not empty.
2599 template <typename A
>
2600 void Walk(const char *prefix
, const std::list
<A
> &list
,
2601 const char *comma
= ", ", const char *suffix
= "") {
2602 if (!list
.empty()) {
2603 const char *str
{prefix
};
2604 for (const auto &x
: list
) {
2611 template <typename A
>
2612 void Walk(const std::list
<A
> &list
, const char *comma
= ", ",
2613 const char *suffix
= "") {
2614 return Walk("", list
, comma
, suffix
);
2617 // Traverse a std::tuple<>, with an optional separator.
2618 template <std::size_t J
= 0, typename T
>
2619 void WalkTupleElements(const T
&tuple
, const char *separator
) {
2620 if (J
> 0 && J
< std::tuple_size_v
<T
>) {
2621 Word(separator
); // this usage dodges "unused parameter" warning
2623 if constexpr (J
< std::tuple_size_v
<T
>) {
2624 Walk(std::get
<J
>(tuple
));
2625 WalkTupleElements
<J
+ 1>(tuple
, separator
);
2628 template <typename
... A
>
2629 void Walk(const std::tuple
<A
...> &tuple
, const char *separator
= "") {
2630 WalkTupleElements(tuple
, separator
);
2633 void EndSubprogram(const char *kind
, const std::optional
<Name
> &name
) {
2634 Outdent(), Word("END "), Word(kind
), Walk(" ", name
);
2635 structureComponents_
.clear();
2638 llvm::raw_ostream
&out_
;
2640 const int indentationAmount_
{1};
2642 const int maxColumns_
{80};
2643 std::set
<CharBlock
> structureComponents_
;
2644 Encoding encoding_
{Encoding::UTF_8
};
2645 bool capitalizeKeywords_
{true};
2646 bool openaccDirective_
{false};
2647 bool openmpDirective_
{false};
2648 bool backslashEscapes_
{false};
2649 preStatementType
*preStatement_
{nullptr};
2650 AnalyzedObjectsAsFortran
*asFortran_
{nullptr};
2653 void UnparseVisitor::Put(char ch
) {
2655 if (openmpDirective_
|| openaccDirective_
) {
2662 for (int j
{0}; j
< indent_
; ++j
) {
2665 column_
= indent_
+ 2;
2666 } else if (ch
== '\n') {
2668 } else if (++column_
>= maxColumns_
) {
2670 for (int j
{0}; j
< indent_
; ++j
) {
2673 if (openmpDirective_
) {
2676 } else if (openaccDirective_
) {
2681 column_
= indent_
+ 3;
2685 if (openmpDirective_
|| openaccDirective_
) {
2690 void UnparseVisitor::Put(const char *str
) {
2691 for (; *str
!= '\0'; ++str
) {
2696 void UnparseVisitor::Put(const std::string
&str
) {
2697 for (char ch
: str
) {
2702 void UnparseVisitor::PutNormalized(const std::string
&str
) {
2703 auto decoded
{DecodeString
<std::string
, Encoding::LATIN_1
>(str
, true)};
2704 std::string encoded
{EncodeString
<Encoding::LATIN_1
>(decoded
)};
2705 Put(QuoteCharacterLiteral(encoded
, backslashEscapes_
));
2708 void UnparseVisitor::PutKeywordLetter(char ch
) {
2709 if (capitalizeKeywords_
) {
2710 Put(ToUpperCaseLetter(ch
));
2712 Put(ToLowerCaseLetter(ch
));
2716 void UnparseVisitor::Word(const char *str
) {
2717 for (; *str
!= '\0'; ++str
) {
2718 PutKeywordLetter(*str
);
2722 void UnparseVisitor::Word(const std::string
&str
) { Word(str
.c_str()); }
2724 void Unparse(llvm::raw_ostream
&out
, const Program
&program
, Encoding encoding
,
2725 bool capitalizeKeywords
, bool backslashEscapes
,
2726 preStatementType
*preStatement
, AnalyzedObjectsAsFortran
*asFortran
) {
2727 UnparseVisitor visitor
{out
, 1, encoding
, capitalizeKeywords
, backslashEscapes
,
2728 preStatement
, asFortran
};
2729 Walk(program
, visitor
);
2732 } // namespace Fortran::parser