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 common::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
<ComponentOrFill
>>(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 ComponentOrFill
&c
) {
274 return common::visit(
276 [](const ComponentDecl
&d
) {
278 std::get
<std::optional
<Initialization
>>(d
.t
)};
280 std::holds_alternative
<std::list
<
281 common::Indirection
<DataStmtValue
>>>(
284 [](const FillDecl
&) { return false; },
290 Put(' '), Walk(decls
, ", ");
292 void Unparse(const Allocatable
&) { // R738
295 void Unparse(const Pointer
&) { Word("POINTER"); }
296 void Unparse(const Contiguous
&) { Word("CONTIGUOUS"); }
297 void Before(const ComponentAttrSpec
&x
) {
298 common::visit(common::visitors
{
299 [&](const CoarraySpec
&) { Word("CODIMENSION["); },
300 [&](const ComponentArraySpec
&) { Word("DIMENSION("); },
305 void Post(const ComponentAttrSpec
&x
) {
306 common::visit(common::visitors
{
307 [&](const CoarraySpec
&) { Put(']'); },
308 [&](const ComponentArraySpec
&) { Put(')'); },
313 void Unparse(const ComponentDecl
&x
) { // R739
314 Walk(std::get
<ObjectName
>(x
.t
));
315 Walk("(", std::get
<std::optional
<ComponentArraySpec
>>(x
.t
), ")");
316 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
317 Walk("*", std::get
<std::optional
<CharLength
>>(x
.t
));
318 Walk(std::get
<std::optional
<Initialization
>>(x
.t
));
320 void Unparse(const FillDecl
&x
) { // DEC extension
322 Walk("(", std::get
<std::optional
<ComponentArraySpec
>>(x
.t
), ")");
323 Walk("*", std::get
<std::optional
<CharLength
>>(x
.t
));
325 void Unparse(const ComponentArraySpec
&x
) { // R740
328 [&](const std::list
<ExplicitShapeSpec
> &y
) { Walk(y
, ","); },
329 [&](const DeferredShapeSpecList
&y
) { Walk(y
); },
333 void Unparse(const ProcComponentDefStmt
&x
) { // R741
335 Walk(std::get
<std::optional
<ProcInterface
>>(x
.t
)), Put(')');
336 Walk(", ", std::get
<std::list
<ProcComponentAttrSpec
>>(x
.t
), ", ");
337 Put(" :: "), Walk(std::get
<std::list
<ProcDecl
>>(x
.t
), ", ");
339 void Unparse(const NoPass
&) { // R742
342 void Unparse(const Pass
&x
) { Word("PASS"), Walk("(", x
.v
, ")"); }
343 void Unparse(const Initialization
&x
) { // R743 & R805
346 [&](const ConstantExpr
&y
) { Put(" = "), Walk(y
); },
347 [&](const NullInit
&y
) { Put(" => "), Walk(y
); },
348 [&](const InitialDataTarget
&y
) { Put(" => "), Walk(y
); },
349 [&](const std::list
<common::Indirection
<DataStmtValue
>> &y
) {
350 Walk("/", y
, ", ", "/");
355 void Unparse(const PrivateStmt
&) { // R745
358 void Unparse(const TypeBoundProcedureStmt::WithoutInterface
&x
) { // R749
359 Word("PROCEDURE"), Walk(", ", x
.attributes
, ", ");
360 Put(" :: "), Walk(x
.declarations
, ", ");
362 void Unparse(const TypeBoundProcedureStmt::WithInterface
&x
) {
363 Word("PROCEDURE("), Walk(x
.interfaceName
), Put("), ");
365 Put(" :: "), Walk(x
.bindingNames
, ", ");
367 void Unparse(const TypeBoundProcDecl
&x
) { // R750
368 Walk(std::get
<Name
>(x
.t
));
369 Walk(" => ", std::get
<std::optional
<Name
>>(x
.t
));
371 void Unparse(const TypeBoundGenericStmt
&x
) { // R751
372 Word("GENERIC"), Walk(", ", std::get
<std::optional
<AccessSpec
>>(x
.t
));
373 Put(" :: "), Walk(std::get
<common::Indirection
<GenericSpec
>>(x
.t
));
374 Put(" => "), Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
376 void Post(const BindAttr::Deferred
&) { Word("DEFERRED"); } // R752
377 void Post(const BindAttr::Non_Overridable
&) { Word("NON_OVERRIDABLE"); }
378 void Unparse(const FinalProcedureStmt
&x
) { // R753
379 Word("FINAL :: "), Walk(x
.v
, ", ");
381 void Unparse(const DerivedTypeSpec
&x
) { // R754
382 Walk(std::get
<Name
>(x
.t
));
383 Walk("(", std::get
<std::list
<TypeParamSpec
>>(x
.t
), ",", ")");
385 void Unparse(const TypeParamSpec
&x
) { // R755
386 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
387 Walk(std::get
<TypeParamValue
>(x
.t
));
389 void Unparse(const StructureConstructor
&x
) { // R756
390 Walk(std::get
<DerivedTypeSpec
>(x
.t
));
391 Put('('), Walk(std::get
<std::list
<ComponentSpec
>>(x
.t
), ", "), Put(')');
393 void Unparse(const ComponentSpec
&x
) { // R757
394 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
395 Walk(std::get
<ComponentDataSource
>(x
.t
));
397 void Unparse(const EnumDefStmt
&) { // R760
398 Word("ENUM, BIND(C)"), Indent();
400 void Unparse(const EnumeratorDefStmt
&x
) { // R761
401 Word("ENUMERATOR :: "), Walk(x
.v
, ", ");
403 void Unparse(const Enumerator
&x
) { // R762
404 Walk(std::get
<NamedConstant
>(x
.t
));
405 Walk(" = ", std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
407 void Post(const EndEnumStmt
&) { // R763
408 Outdent(), Word("END ENUM");
410 void Unparse(const BOZLiteralConstant
&x
) { // R764 - R767
413 void Unparse(const AcValue::Triplet
&x
) { // R773
414 Walk(std::get
<0>(x
.t
)), Put(':'), Walk(std::get
<1>(x
.t
));
415 Walk(":", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
417 void Unparse(const ArrayConstructor
&x
) { // R769
418 Put('['), Walk(x
.v
), Put(']');
420 void Unparse(const AcSpec
&x
) { // R770
421 Walk(x
.type
, "::"), Walk(x
.values
, ", ");
423 template <typename A
, typename B
> void Unparse(const LoopBounds
<A
, B
> &x
) {
424 Walk(x
.name
), Put('='), Walk(x
.lower
), Put(','), Walk(x
.upper
);
427 void Unparse(const AcImpliedDo
&x
) { // R774
428 Put('('), Walk(std::get
<std::list
<AcValue
>>(x
.t
), ", ");
429 Put(", "), Walk(std::get
<AcImpliedDoControl
>(x
.t
)), Put(')');
431 void Unparse(const AcImpliedDoControl
&x
) { // R775
432 Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
433 Walk(std::get
<AcImpliedDoControl::Bounds
>(x
.t
));
436 void Unparse(const TypeDeclarationStmt
&x
) { // R801
437 const auto &dts
{std::get
<DeclarationTypeSpec
>(x
.t
)};
438 const auto &attrs
{std::get
<std::list
<AttrSpec
>>(x
.t
)};
439 const auto &decls
{std::get
<std::list
<EntityDecl
>>(x
.t
)};
440 Walk(dts
), Walk(", ", attrs
, ", ");
442 static const auto isInitializerOldStyle
{[](const Initialization
&i
) {
443 return std::holds_alternative
<
444 std::list
<common::Indirection
<DataStmtValue
>>>(i
.u
);
446 static const auto hasAssignmentInitializer
{[](const EntityDecl
&d
) {
447 // Does a declaration have a new-style =x initializer?
448 const auto &init
{std::get
<std::optional
<Initialization
>>(d
.t
)};
449 return init
&& !isInitializerOldStyle(*init
);
451 static const auto hasSlashDelimitedInitializer
{[](const EntityDecl
&d
) {
452 // Does a declaration have an old-style /x/ initializer?
453 const auto &init
{std::get
<std::optional
<Initialization
>>(d
.t
)};
454 return init
&& isInitializerOldStyle(*init
);
456 const auto useDoubledColons
{[&]() {
457 bool isRecord
{std::holds_alternative
<DeclarationTypeSpec::Record
>(dts
.u
)};
458 if (!attrs
.empty()) {
459 // Attributes after the type require :: before the entities.
463 if (std::any_of(decls
.begin(), decls
.end(), hasAssignmentInitializer
)) {
464 // Always use :: with new style standard initializers (=x),
465 // since the standard requires them to appear (even in free form,
466 // where mandatory spaces already disambiguate INTEGER J=666).
471 // Never put :: in a legacy extension RECORD// statement.
474 // The :: is optional for this declaration. Avoid usage that can
475 // crash the pgf90 compiler.
477 decls
.begin(), decls
.end(), hasSlashDelimitedInitializer
)) {
478 // Don't use :: when a declaration uses legacy DATA-statement-like
479 // /x/ initialization.
482 // Don't use :: with intrinsic types. Otherwise, use it.
483 return !std::holds_alternative
<IntrinsicTypeSpec
>(dts
.u
);
486 if (useDoubledColons()) {
489 Put(' '), Walk(std::get
<std::list
<EntityDecl
>>(x
.t
), ", ");
491 void Before(const AttrSpec
&x
) { // R802
492 common::visit(common::visitors
{
493 [&](const CoarraySpec
&) { Word("CODIMENSION["); },
494 [&](const ArraySpec
&) { Word("DIMENSION("); },
499 void Post(const AttrSpec
&x
) {
500 common::visit(common::visitors
{
501 [&](const CoarraySpec
&) { Put(']'); },
502 [&](const ArraySpec
&) { Put(')'); },
507 void Unparse(const EntityDecl
&x
) { // R803
508 Walk(std::get
<ObjectName
>(x
.t
));
509 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
510 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
511 Walk("*", std::get
<std::optional
<CharLength
>>(x
.t
));
512 Walk(std::get
<std::optional
<Initialization
>>(x
.t
));
514 void Unparse(const NullInit
&) { // R806
517 void Unparse(const LanguageBindingSpec
&x
) { // R808 & R1528
518 Word("BIND(C"), Walk(", NAME=", x
.v
), Put(')');
520 void Unparse(const CoarraySpec
&x
) { // R809
521 common::visit(common::visitors
{
522 [&](const DeferredCoshapeSpecList
&y
) { Walk(y
); },
523 [&](const ExplicitCoshapeSpec
&y
) { Walk(y
); },
527 void Unparse(const DeferredCoshapeSpecList
&x
) { // R810
528 for (auto j
{x
.v
}; j
> 0; --j
) {
535 void Unparse(const ExplicitCoshapeSpec
&x
) { // R811
536 Walk(std::get
<std::list
<ExplicitShapeSpec
>>(x
.t
), ",", ",");
537 Walk(std::get
<std::optional
<SpecificationExpr
>>(x
.t
), ":"), Put('*');
539 void Unparse(const ExplicitShapeSpec
&x
) { // R812 - R813 & R816 - R818
540 Walk(std::get
<std::optional
<SpecificationExpr
>>(x
.t
), ":");
541 Walk(std::get
<SpecificationExpr
>(x
.t
));
543 void Unparse(const ArraySpec
&x
) { // R815
546 [&](const std::list
<ExplicitShapeSpec
> &y
) { Walk(y
, ","); },
547 [&](const std::list
<AssumedShapeSpec
> &y
) { Walk(y
, ","); },
548 [&](const DeferredShapeSpecList
&y
) { Walk(y
); },
549 [&](const AssumedSizeSpec
&y
) { Walk(y
); },
550 [&](const ImpliedShapeSpec
&y
) { Walk(y
); },
551 [&](const AssumedRankSpec
&y
) { Walk(y
); },
555 void Post(const AssumedShapeSpec
&) { Put(':'); } // R819
556 void Unparse(const DeferredShapeSpecList
&x
) { // R820
557 for (auto j
{x
.v
}; j
> 0; --j
) {
564 void Unparse(const AssumedImpliedSpec
&x
) { // R821
568 void Unparse(const AssumedSizeSpec
&x
) { // R822
569 Walk(std::get
<std::list
<ExplicitShapeSpec
>>(x
.t
), ",", ",");
570 Walk(std::get
<AssumedImpliedSpec
>(x
.t
));
572 void Unparse(const ImpliedShapeSpec
&x
) { // R823
575 void Post(const AssumedRankSpec
&) { Put(".."); } // R825
576 void Post(const Asynchronous
&) { Word("ASYNCHRONOUS"); }
577 void Post(const External
&) { Word("EXTERNAL"); }
578 void Post(const Intrinsic
&) { Word("INTRINSIC"); }
579 void Post(const Optional
&) { Word("OPTIONAL"); }
580 void Post(const Parameter
&) { Word("PARAMETER"); }
581 void Post(const Protected
&) { Word("PROTECTED"); }
582 void Post(const Save
&) { Word("SAVE"); }
583 void Post(const Target
&) { Word("TARGET"); }
584 void Post(const Value
&) { Word("VALUE"); }
585 void Post(const Volatile
&) { Word("VOLATILE"); }
586 void Unparse(const IntentSpec
&x
) { // R826
587 Word("INTENT("), Walk(x
.v
), Put(")");
589 void Unparse(const AccessStmt
&x
) { // R827
590 Walk(std::get
<AccessSpec
>(x
.t
));
591 Walk(" :: ", std::get
<std::list
<AccessId
>>(x
.t
), ", ");
593 void Unparse(const AllocatableStmt
&x
) { // R829
594 Word("ALLOCATABLE :: "), Walk(x
.v
, ", ");
596 void Unparse(const ObjectDecl
&x
) { // R830 & R860
597 Walk(std::get
<ObjectName
>(x
.t
));
598 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
599 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
601 void Unparse(const AsynchronousStmt
&x
) { // R831
602 Word("ASYNCHRONOUS :: "), Walk(x
.v
, ", ");
604 void Unparse(const BindStmt
&x
) { // R832
607 void Unparse(const BindEntity
&x
) { // R833
608 bool isCommon
{std::get
<BindEntity::Kind
>(x
.t
) == BindEntity::Kind::Common
};
609 const char *slash
{isCommon
? "/" : ""};
610 Put(slash
), Walk(std::get
<Name
>(x
.t
)), Put(slash
);
612 void Unparse(const CodimensionStmt
&x
) { // R834
613 Word("CODIMENSION :: "), Walk(x
.v
, ", ");
615 void Unparse(const CodimensionDecl
&x
) { // R835
616 Walk(std::get
<Name
>(x
.t
));
617 Put('['), Walk(std::get
<CoarraySpec
>(x
.t
)), Put(']');
619 void Unparse(const ContiguousStmt
&x
) { // R836
620 Word("CONTIGUOUS :: "), Walk(x
.v
, ", ");
622 void Unparse(const DataStmt
&x
) { // R837
623 Word("DATA "), Walk(x
.v
, ", ");
625 void Unparse(const DataStmtSet
&x
) { // R838
626 Walk(std::get
<std::list
<DataStmtObject
>>(x
.t
), ", ");
627 Put('/'), Walk(std::get
<std::list
<DataStmtValue
>>(x
.t
), ", "), Put('/');
629 void Unparse(const DataImpliedDo
&x
) { // R840, R842
630 Put('('), Walk(std::get
<std::list
<DataIDoObject
>>(x
.t
), ", "), Put(',');
631 Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
632 Walk(std::get
<DataImpliedDo::Bounds
>(x
.t
)), Put(')');
634 void Unparse(const DataStmtValue
&x
) { // R843
635 Walk(std::get
<std::optional
<DataStmtRepeat
>>(x
.t
), "*");
636 Walk(std::get
<DataStmtConstant
>(x
.t
));
638 void Unparse(const DimensionStmt
&x
) { // R848
639 Word("DIMENSION :: "), Walk(x
.v
, ", ");
641 void Unparse(const DimensionStmt::Declaration
&x
) {
642 Walk(std::get
<Name
>(x
.t
));
643 Put('('), Walk(std::get
<ArraySpec
>(x
.t
)), Put(')');
645 void Unparse(const IntentStmt
&x
) { // R849
648 void Unparse(const OptionalStmt
&x
) { // R850
649 Word("OPTIONAL :: "), Walk(x
.v
, ", ");
651 void Unparse(const ParameterStmt
&x
) { // R851
652 Word("PARAMETER("), Walk(x
.v
, ", "), Put(')');
654 void Unparse(const NamedConstantDef
&x
) { // R852
657 void Unparse(const PointerStmt
&x
) { // R853
658 Word("POINTER :: "), Walk(x
.v
, ", ");
660 void Unparse(const PointerDecl
&x
) { // R854
661 Walk(std::get
<Name
>(x
.t
));
662 Walk("(", std::get
<std::optional
<DeferredShapeSpecList
>>(x
.t
), ")");
664 void Unparse(const ProtectedStmt
&x
) { // R855
665 Word("PROTECTED :: "), Walk(x
.v
, ", ");
667 void Unparse(const SaveStmt
&x
) { // R856
668 Word("SAVE"), Walk(" :: ", x
.v
, ", ");
670 void Unparse(const SavedEntity
&x
) { // R857, R858
672 std::get
<SavedEntity::Kind
>(x
.t
) == SavedEntity::Kind::Common
};
673 const char *slash
{isCommon
? "/" : ""};
674 Put(slash
), Walk(std::get
<Name
>(x
.t
)), Put(slash
);
676 void Unparse(const TargetStmt
&x
) { // R859
677 Word("TARGET :: "), Walk(x
.v
, ", ");
679 void Unparse(const ValueStmt
&x
) { // R861
680 Word("VALUE :: "), Walk(x
.v
, ", ");
682 void Unparse(const VolatileStmt
&x
) { // R862
683 Word("VOLATILE :: "), Walk(x
.v
, ", ");
685 void Unparse(const ImplicitStmt
&x
) { // R863
689 [&](const std::list
<ImplicitSpec
> &y
) { Walk(y
, ", "); },
690 [&](const std::list
<ImplicitStmt::ImplicitNoneNameSpec
> &y
) {
691 Word("NONE"), Walk(" (", y
, ", ", ")");
696 void Unparse(const ImplicitSpec
&x
) { // R864
697 Walk(std::get
<DeclarationTypeSpec
>(x
.t
));
698 Put('('), Walk(std::get
<std::list
<LetterSpec
>>(x
.t
), ", "), Put(')');
700 void Unparse(const LetterSpec
&x
) { // R865
701 Put(*std::get
<const char *>(x
.t
));
702 auto second
{std::get
<std::optional
<const char *>>(x
.t
)};
704 Put('-'), Put(**second
);
707 void Unparse(const ImportStmt
&x
) { // R867
710 case common::ImportKind::Default
:
711 Walk(" :: ", x
.names
, ", ");
713 case common::ImportKind::Only
:
714 Put(", "), Word("ONLY: ");
717 case common::ImportKind::None
:
720 case common::ImportKind::All
:
725 void Unparse(const NamelistStmt
&x
) { // R868
726 Word("NAMELIST"), Walk(x
.v
, ", ");
728 void Unparse(const NamelistStmt::Group
&x
) {
729 Put('/'), Walk(std::get
<Name
>(x
.t
)), Put('/');
730 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
732 void Unparse(const EquivalenceStmt
&x
) { // R870, R871
734 const char *separator
{" "};
735 for (const std::list
<EquivalenceObject
> &y
: x
.v
) {
736 Put(separator
), Put('('), Walk(y
), Put(')');
740 void Unparse(const CommonStmt
&x
) { // R873
744 void Unparse(const CommonBlockObject
&x
) { // R874
745 Walk(std::get
<Name
>(x
.t
));
746 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
748 void Unparse(const CommonStmt::Block
&x
) {
749 Word("/"), Walk(std::get
<std::optional
<Name
>>(x
.t
)), Word("/");
750 Walk(std::get
<std::list
<CommonBlockObject
>>(x
.t
));
753 void Unparse(const Substring
&x
) { // R908, R909
754 Walk(std::get
<DataRef
>(x
.t
));
755 Put('('), Walk(std::get
<SubstringRange
>(x
.t
)), Put(')');
757 void Unparse(const CharLiteralConstantSubstring
&x
) {
758 Walk(std::get
<CharLiteralConstant
>(x
.t
));
759 Put('('), Walk(std::get
<SubstringRange
>(x
.t
)), Put(')');
761 void Unparse(const SubstringInquiry
&x
) {
763 Put(x
.source
.end()[-1] == 'n' ? "%LEN" : "%KIND");
765 void Unparse(const SubstringRange
&x
) { // R910
768 void Unparse(const PartRef
&x
) { // R912
770 Walk("(", x
.subscripts
, ",", ")");
771 Walk(x
.imageSelector
);
773 void Unparse(const StructureComponent
&x
) { // R913
775 if (structureComponents_
.find(x
.component
.source
) !=
776 structureComponents_
.end()) {
783 void Unparse(const ArrayElement
&x
) { // R917
785 Put('('), Walk(x
.subscripts
, ","), Put(')');
787 void Unparse(const SubscriptTriplet
&x
) { // R921
788 Walk(std::get
<0>(x
.t
)), Put(':'), Walk(std::get
<1>(x
.t
));
789 Walk(":", std::get
<2>(x
.t
));
791 void Unparse(const ImageSelector
&x
) { // R924
792 Put('['), Walk(std::get
<std::list
<Cosubscript
>>(x
.t
), ",");
793 Walk(",", std::get
<std::list
<ImageSelectorSpec
>>(x
.t
), ","), Put(']');
795 void Before(const ImageSelectorSpec::Stat
&) { // R926
798 void Before(const ImageSelectorSpec::Team_Number
&) { Word("TEAM_NUMBER="); }
799 void Before(const ImageSelectorSpec
&x
) {
800 if (std::holds_alternative
<TeamValue
>(x
.u
)) {
804 void Unparse(const AllocateStmt
&x
) { // R927
806 Walk(std::get
<std::optional
<TypeSpec
>>(x
.t
), "::");
807 Walk(std::get
<std::list
<Allocation
>>(x
.t
), ", ");
808 Walk(", ", std::get
<std::list
<AllocOpt
>>(x
.t
), ", "), Put(')');
810 void Before(const AllocOpt
&x
) { // R928, R931
811 common::visit(common::visitors
{
812 [&](const AllocOpt::Mold
&) { Word("MOLD="); },
813 [&](const AllocOpt::Source
&) { Word("SOURCE="); },
814 [](const StatOrErrmsg
&) {},
818 void Unparse(const Allocation
&x
) { // R932
819 Walk(std::get
<AllocateObject
>(x
.t
));
820 Walk("(", std::get
<std::list
<AllocateShapeSpec
>>(x
.t
), ",", ")");
821 Walk("[", std::get
<std::optional
<AllocateCoarraySpec
>>(x
.t
), "]");
823 void Unparse(const AllocateShapeSpec
&x
) { // R934 & R938
824 Walk(std::get
<std::optional
<BoundExpr
>>(x
.t
), ":");
825 Walk(std::get
<BoundExpr
>(x
.t
));
827 void Unparse(const AllocateCoarraySpec
&x
) { // R937
828 Walk(std::get
<std::list
<AllocateCoshapeSpec
>>(x
.t
), ",", ",");
829 Walk(std::get
<std::optional
<BoundExpr
>>(x
.t
), ":"), Put('*');
831 void Unparse(const NullifyStmt
&x
) { // R939
832 Word("NULLIFY("), Walk(x
.v
, ", "), Put(')');
834 void Unparse(const DeallocateStmt
&x
) { // R941
836 Walk(std::get
<std::list
<AllocateObject
>>(x
.t
), ", ");
837 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
839 void Before(const StatOrErrmsg
&x
) { // R942 & R1165
840 common::visit(common::visitors
{
841 [&](const StatVariable
&) { Word("STAT="); },
842 [&](const MsgVariable
&) { Word("ERRMSG="); },
848 void Unparse(const Expr::Parentheses
&x
) { Put('('), Walk(x
.v
), Put(')'); }
849 void Before(const Expr::UnaryPlus
&) { Put("+"); }
850 void Before(const Expr::Negate
&) { Put("-"); }
851 void Before(const Expr::NOT
&) { Word(".NOT."); }
852 void Unparse(const Expr::PercentLoc
&x
) {
853 Word("%LOC("), Walk(x
.v
), Put(')');
855 void Unparse(const Expr::Power
&x
) { Walk(x
.t
, "**"); }
856 void Unparse(const Expr::Multiply
&x
) { Walk(x
.t
, "*"); }
857 void Unparse(const Expr::Divide
&x
) { Walk(x
.t
, "/"); }
858 void Unparse(const Expr::Add
&x
) { Walk(x
.t
, "+"); }
859 void Unparse(const Expr::Subtract
&x
) { Walk(x
.t
, "-"); }
860 void Unparse(const Expr::Concat
&x
) { Walk(x
.t
, "//"); }
861 void Unparse(const Expr::LT
&x
) { Walk(x
.t
, "<"); }
862 void Unparse(const Expr::LE
&x
) { Walk(x
.t
, "<="); }
863 void Unparse(const Expr::EQ
&x
) { Walk(x
.t
, "=="); }
864 void Unparse(const Expr::NE
&x
) { Walk(x
.t
, "/="); }
865 void Unparse(const Expr::GE
&x
) { Walk(x
.t
, ">="); }
866 void Unparse(const Expr::GT
&x
) { Walk(x
.t
, ">"); }
867 void Unparse(const Expr::AND
&x
) { Walk(x
.t
, ".AND."); }
868 void Unparse(const Expr::OR
&x
) { Walk(x
.t
, ".OR."); }
869 void Unparse(const Expr::EQV
&x
) { Walk(x
.t
, ".EQV."); }
870 void Unparse(const Expr::NEQV
&x
) { Walk(x
.t
, ".NEQV."); }
871 void Unparse(const Expr::ComplexConstructor
&x
) {
872 Put('('), Walk(x
.t
, ","), Put(')');
874 void Unparse(const Expr::DefinedBinary
&x
) {
875 Walk(std::get
<1>(x
.t
)); // left
876 Walk(std::get
<DefinedOpName
>(x
.t
));
877 Walk(std::get
<2>(x
.t
)); // right
879 void Unparse(const DefinedOpName
&x
) { // R1003, R1023, R1414, & R1415
882 void Unparse(const AssignmentStmt
&x
) { // R1032
883 if (asFortran_
&& x
.typedAssignment
.get()) {
885 asFortran_
->assignment(out_
, *x
.typedAssignment
);
891 void Unparse(const PointerAssignmentStmt
&x
) { // R1033, R1034, R1038
892 if (asFortran_
&& x
.typedAssignment
.get()) {
894 asFortran_
->assignment(out_
, *x
.typedAssignment
);
897 Walk(std::get
<DataRef
>(x
.t
));
900 [&](const std::list
<BoundsRemapping
> &y
) {
901 Put('('), Walk(y
), Put(')');
903 [&](const std::list
<BoundsSpec
> &y
) { Walk("(", y
, ", ", ")"); },
905 std::get
<PointerAssignmentStmt::Bounds
>(x
.t
).u
);
906 Put(" => "), Walk(std::get
<Expr
>(x
.t
));
909 void Post(const BoundsSpec
&) { // R1035
912 void Unparse(const BoundsRemapping
&x
) { // R1036
915 void Unparse(const WhereStmt
&x
) { // R1041, R1045, R1046
916 Word("WHERE ("), Walk(x
.t
, ") ");
918 void Unparse(const WhereConstructStmt
&x
) { // R1043
919 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
920 Word("WHERE ("), Walk(std::get
<LogicalExpr
>(x
.t
)), Put(')');
923 void Unparse(const MaskedElsewhereStmt
&x
) { // R1047
925 Word("ELSEWHERE ("), Walk(std::get
<LogicalExpr
>(x
.t
)), Put(')');
926 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
));
929 void Unparse(const ElsewhereStmt
&x
) { // R1048
930 Outdent(), Word("ELSEWHERE"), Walk(" ", x
.v
), Indent();
932 void Unparse(const EndWhereStmt
&x
) { // R1049
933 Outdent(), Word("END WHERE"), Walk(" ", x
.v
);
935 void Unparse(const ForallConstructStmt
&x
) { // R1051
936 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
937 Word("FORALL"), Walk(std::get
<common::Indirection
<ConcurrentHeader
>>(x
.t
));
940 void Unparse(const EndForallStmt
&x
) { // R1054
941 Outdent(), Word("END FORALL"), Walk(" ", x
.v
);
943 void Before(const ForallStmt
&) { // R1055
947 void Unparse(const AssociateStmt
&x
) { // R1103
948 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
950 Walk(std::get
<std::list
<Association
>>(x
.t
), ", "), Put(')'), Indent();
952 void Unparse(const Association
&x
) { // R1104
955 void Unparse(const EndAssociateStmt
&x
) { // R1106
956 Outdent(), Word("END ASSOCIATE"), Walk(" ", x
.v
);
958 void Unparse(const BlockStmt
&x
) { // R1108
959 Walk(x
.v
, ": "), Word("BLOCK"), Indent();
961 void Unparse(const EndBlockStmt
&x
) { // R1110
962 Outdent(), Word("END BLOCK"), Walk(" ", x
.v
);
964 void Unparse(const ChangeTeamStmt
&x
) { // R1112
965 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
966 Word("CHANGE TEAM ("), Walk(std::get
<TeamValue
>(x
.t
));
967 Walk(", ", std::get
<std::list
<CoarrayAssociation
>>(x
.t
), ", ");
968 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
971 void Unparse(const CoarrayAssociation
&x
) { // R1113
974 void Unparse(const EndChangeTeamStmt
&x
) { // R1114
975 Outdent(), Word("END TEAM (");
976 Walk(std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
977 Put(')'), Walk(" ", std::get
<std::optional
<Name
>>(x
.t
));
979 void Unparse(const CriticalStmt
&x
) { // R1117
980 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
981 Word("CRITICAL ("), Walk(std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
984 void Unparse(const EndCriticalStmt
&x
) { // R1118
985 Outdent(), Word("END CRITICAL"), Walk(" ", x
.v
);
987 void Unparse(const DoConstruct
&x
) { // R1119, R1120
988 Walk(std::get
<Statement
<NonLabelDoStmt
>>(x
.t
));
989 Indent(), Walk(std::get
<Block
>(x
.t
), ""), Outdent();
990 Walk(std::get
<Statement
<EndDoStmt
>>(x
.t
));
992 void Unparse(const LabelDoStmt
&x
) { // R1121
993 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
994 Word("DO "), Walk(std::get
<Label
>(x
.t
));
995 Walk(" ", std::get
<std::optional
<LoopControl
>>(x
.t
));
997 void Unparse(const NonLabelDoStmt
&x
) { // R1122
998 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
999 Word("DO "), Walk(std::get
<std::optional
<LoopControl
>>(x
.t
));
1001 void Unparse(const LoopControl
&x
) { // R1123
1002 common::visit(common::visitors
{
1003 [&](const ScalarLogicalExpr
&y
) {
1004 Word("WHILE ("), Walk(y
), Put(')');
1006 [&](const auto &y
) { Walk(y
); },
1010 void Unparse(const ConcurrentHeader
&x
) { // R1125
1011 Put('('), Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
1012 Walk(std::get
<std::list
<ConcurrentControl
>>(x
.t
), ", ");
1013 Walk(", ", std::get
<std::optional
<ScalarLogicalExpr
>>(x
.t
)), Put(')');
1015 void Unparse(const ConcurrentControl
&x
) { // R1126 - R1128
1016 Walk(std::get
<Name
>(x
.t
)), Put('='), Walk(std::get
<1>(x
.t
));
1017 Put(':'), Walk(std::get
<2>(x
.t
));
1018 Walk(":", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
1020 void Before(const LoopControl::Concurrent
&) { // R1129
1023 void Unparse(const LocalitySpec::Local
&x
) {
1024 Word("LOCAL("), Walk(x
.v
, ", "), Put(')');
1026 void Unparse(const LocalitySpec::LocalInit
&x
) {
1027 Word("LOCAL_INIT("), Walk(x
.v
, ", "), Put(')');
1029 void Unparse(const LocalitySpec::Shared
&x
) {
1030 Word("SHARED("), Walk(x
.v
, ", "), Put(')');
1032 void Post(const LocalitySpec::DefaultNone
&) { Word("DEFAULT(NONE)"); }
1033 void Unparse(const EndDoStmt
&x
) { // R1132
1034 Word("END DO"), Walk(" ", x
.v
);
1036 void Unparse(const CycleStmt
&x
) { // R1133
1037 Word("CYCLE"), Walk(" ", x
.v
);
1039 void Unparse(const IfThenStmt
&x
) { // R1135
1040 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1041 Word("IF ("), Walk(std::get
<ScalarLogicalExpr
>(x
.t
));
1042 Put(") "), Word("THEN"), Indent();
1044 void Unparse(const ElseIfStmt
&x
) { // R1136
1045 Outdent(), Word("ELSE IF (");
1046 Walk(std::get
<ScalarLogicalExpr
>(x
.t
)), Put(") "), Word("THEN");
1047 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1049 void Unparse(const ElseStmt
&x
) { // R1137
1050 Outdent(), Word("ELSE"), Walk(" ", x
.v
), Indent();
1052 void Unparse(const EndIfStmt
&x
) { // R1138
1053 Outdent(), Word("END IF"), Walk(" ", x
.v
);
1055 void Unparse(const IfStmt
&x
) { // R1139
1056 Word("IF ("), Walk(x
.t
, ") ");
1058 void Unparse(const SelectCaseStmt
&x
) { // R1141, R1144
1059 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1060 Word("SELECT CASE (");
1061 Walk(std::get
<Scalar
<Expr
>>(x
.t
)), Put(')'), Indent();
1063 void Unparse(const CaseStmt
&x
) { // R1142
1064 Outdent(), Word("CASE "), Walk(std::get
<CaseSelector
>(x
.t
));
1065 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1067 void Unparse(const EndSelectStmt
&x
) { // R1143 & R1151 & R1155
1068 Outdent(), Word("END SELECT"), Walk(" ", x
.v
);
1070 void Unparse(const CaseSelector
&x
) { // R1145
1071 common::visit(common::visitors
{
1072 [&](const std::list
<CaseValueRange
> &y
) {
1073 Put('('), Walk(y
), Put(')');
1075 [&](const Default
&) { Word("DEFAULT"); },
1079 void Unparse(const CaseValueRange::Range
&x
) { // R1146
1080 Walk(x
.lower
), Put(':'), Walk(x
.upper
);
1082 void Unparse(const SelectRankStmt
&x
) { // R1149
1083 Walk(std::get
<0>(x
.t
), ": ");
1084 Word("SELECT RANK ("), Walk(std::get
<1>(x
.t
), " => ");
1085 Walk(std::get
<Selector
>(x
.t
)), Put(')'), Indent();
1087 void Unparse(const SelectRankCaseStmt
&x
) { // R1150
1088 Outdent(), Word("RANK ");
1089 common::visit(common::visitors
{
1090 [&](const ScalarIntConstantExpr
&y
) {
1091 Put('('), Walk(y
), Put(')');
1093 [&](const Star
&) { Put("(*)"); },
1094 [&](const Default
&) { Word("DEFAULT"); },
1096 std::get
<SelectRankCaseStmt::Rank
>(x
.t
).u
);
1097 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1099 void Unparse(const SelectTypeStmt
&x
) { // R1153
1100 Walk(std::get
<0>(x
.t
), ": ");
1101 Word("SELECT TYPE ("), Walk(std::get
<1>(x
.t
), " => ");
1102 Walk(std::get
<Selector
>(x
.t
)), Put(')'), Indent();
1104 void Unparse(const TypeGuardStmt
&x
) { // R1154
1105 Outdent(), Walk(std::get
<TypeGuardStmt::Guard
>(x
.t
));
1106 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1108 void Unparse(const TypeGuardStmt::Guard
&x
) {
1111 [&](const TypeSpec
&y
) { Word("TYPE IS ("), Walk(y
), Put(')'); },
1112 [&](const DerivedTypeSpec
&y
) {
1113 Word("CLASS IS ("), Walk(y
), Put(')');
1115 [&](const Default
&) { Word("CLASS DEFAULT"); },
1119 void Unparse(const ExitStmt
&x
) { // R1156
1120 Word("EXIT"), Walk(" ", x
.v
);
1122 void Before(const GotoStmt
&) { // R1157
1125 void Unparse(const ComputedGotoStmt
&x
) { // R1158
1126 Word("GO TO ("), Walk(x
.t
, "), ");
1128 void Unparse(const ContinueStmt
&) { // R1159
1131 void Unparse(const StopStmt
&x
) { // R1160, R1161
1132 if (std::get
<StopStmt::Kind
>(x
.t
) == StopStmt::Kind::ErrorStop
) {
1135 Word("STOP"), Walk(" ", std::get
<std::optional
<StopCode
>>(x
.t
));
1136 Walk(", QUIET=", std::get
<std::optional
<ScalarLogicalExpr
>>(x
.t
));
1138 void Unparse(const FailImageStmt
&) { // R1163
1141 void Unparse(const SyncAllStmt
&x
) { // R1164
1142 Word("SYNC ALL ("), Walk(x
.v
, ", "), Put(')');
1144 void Unparse(const SyncImagesStmt
&x
) { // R1166
1145 Word("SYNC IMAGES (");
1146 Walk(std::get
<SyncImagesStmt::ImageSet
>(x
.t
));
1147 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1149 void Unparse(const SyncMemoryStmt
&x
) { // R1168
1150 Word("SYNC MEMORY ("), Walk(x
.v
, ", "), Put(')');
1152 void Unparse(const SyncTeamStmt
&x
) { // R1169
1153 Word("SYNC TEAM ("), Walk(std::get
<TeamValue
>(x
.t
));
1154 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1156 void Unparse(const EventPostStmt
&x
) { // R1170
1157 Word("EVENT POST ("), Walk(std::get
<EventVariable
>(x
.t
));
1158 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1160 void Before(const EventWaitStmt::EventWaitSpec
&x
) { // R1173, R1174
1161 common::visit(common::visitors
{
1162 [&](const ScalarIntExpr
&) { Word("UNTIL_COUNT="); },
1163 [](const StatOrErrmsg
&) {},
1167 void Unparse(const EventWaitStmt
&x
) { // R1170
1168 Word("EVENT WAIT ("), Walk(std::get
<EventVariable
>(x
.t
));
1169 Walk(", ", std::get
<std::list
<EventWaitStmt::EventWaitSpec
>>(x
.t
), ", ");
1172 void Unparse(const FormTeamStmt
&x
) { // R1175, R1177
1173 Word("FORM TEAM ("), Walk(std::get
<ScalarIntExpr
>(x
.t
));
1174 Put(','), Walk(std::get
<TeamVariable
>(x
.t
));
1175 Walk(", ", std::get
<std::list
<FormTeamStmt::FormTeamSpec
>>(x
.t
), ", ");
1178 void Before(const FormTeamStmt::FormTeamSpec
&x
) { // R1176, R1178
1179 common::visit(common::visitors
{
1180 [&](const ScalarIntExpr
&) { Word("NEW_INDEX="); },
1181 [](const StatOrErrmsg
&) {},
1185 void Unparse(const LockStmt
&x
) { // R1179
1186 Word("LOCK ("), Walk(std::get
<LockVariable
>(x
.t
));
1187 Walk(", ", std::get
<std::list
<LockStmt::LockStat
>>(x
.t
), ", ");
1190 void Before(const LockStmt::LockStat
&x
) { // R1180
1193 [&](const ScalarLogicalVariable
&) { Word("ACQUIRED_LOCK="); },
1194 [](const StatOrErrmsg
&) {},
1198 void Unparse(const UnlockStmt
&x
) { // R1181
1199 Word("UNLOCK ("), Walk(std::get
<LockVariable
>(x
.t
));
1200 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
1204 void Unparse(const OpenStmt
&x
) { // R1204
1205 Word("OPEN ("), Walk(x
.v
, ", "), Put(')');
1207 bool Pre(const ConnectSpec
&x
) { // R1205
1208 return common::visit(common::visitors
{
1209 [&](const FileUnitNumber
&) {
1213 [&](const FileNameExpr
&) {
1217 [&](const ConnectSpec::CharExpr
&y
) {
1221 [&](const MsgVariable
&) {
1225 [&](const StatVariable
&) {
1229 [&](const ConnectSpec::Recl
&) {
1233 [&](const ConnectSpec::Newunit
&) {
1237 [&](const ErrLabel
&) {
1241 [&](const StatusExpr
&) {
1248 void Unparse(const CloseStmt
&x
) { // R1208
1249 Word("CLOSE ("), Walk(x
.v
, ", "), Put(')');
1251 void Before(const CloseStmt::CloseSpec
&x
) { // R1209
1252 common::visit(common::visitors
{
1253 [&](const FileUnitNumber
&) { Word("UNIT="); },
1254 [&](const StatVariable
&) { Word("IOSTAT="); },
1255 [&](const MsgVariable
&) { Word("IOMSG="); },
1256 [&](const ErrLabel
&) { Word("ERR="); },
1257 [&](const StatusExpr
&) { Word("STATUS="); },
1261 void Unparse(const ReadStmt
&x
) { // R1210
1264 Put('('), Walk(x
.iounit
);
1266 Put(", "), Walk(x
.format
);
1268 Walk(", ", x
.controls
, ", ");
1270 } else if (x
.format
) {
1272 if (!x
.items
.empty()) {
1276 Put('('), Walk(x
.controls
, ", "), Put(')');
1278 Walk(" ", x
.items
, ", ");
1280 void Unparse(const WriteStmt
&x
) { // R1211
1285 Put(", "), Walk(x
.format
);
1287 Walk(", ", x
.controls
, ", ");
1289 Walk(x
.controls
, ", ");
1291 Put(')'), Walk(" ", x
.items
, ", ");
1293 void Unparse(const PrintStmt
&x
) { // R1212
1294 Word("PRINT "), Walk(std::get
<Format
>(x
.t
));
1295 Walk(", ", std::get
<std::list
<OutputItem
>>(x
.t
), ", ");
1297 bool Pre(const IoControlSpec
&x
) { // R1213
1298 return common::visit(common::visitors
{
1299 [&](const IoUnit
&) {
1303 [&](const Format
&) {
1311 [&](const IoControlSpec::CharExpr
&y
) {
1315 [&](const IoControlSpec::Asynchronous
&) {
1316 Word("ASYNCHRONOUS=");
1319 [&](const EndLabel
&) {
1323 [&](const EorLabel
&) {
1327 [&](const ErrLabel
&) {
1331 [&](const IdVariable
&) {
1335 [&](const MsgVariable
&) {
1339 [&](const StatVariable
&) {
1343 [&](const IoControlSpec::Pos
&) {
1347 [&](const IoControlSpec::Rec
&) {
1351 [&](const IoControlSpec::Size
&) {
1358 void Unparse(const InputImpliedDo
&x
) { // R1218
1359 Put('('), Walk(std::get
<std::list
<InputItem
>>(x
.t
), ", "), Put(", ");
1360 Walk(std::get
<IoImpliedDoControl
>(x
.t
)), Put(')');
1362 void Unparse(const OutputImpliedDo
&x
) { // R1219
1363 Put('('), Walk(std::get
<std::list
<OutputItem
>>(x
.t
), ", "), Put(", ");
1364 Walk(std::get
<IoImpliedDoControl
>(x
.t
)), Put(')');
1366 void Unparse(const WaitStmt
&x
) { // R1222
1367 Word("WAIT ("), Walk(x
.v
, ", "), Put(')');
1369 void Before(const WaitSpec
&x
) { // R1223
1370 common::visit(common::visitors
{
1371 [&](const FileUnitNumber
&) { Word("UNIT="); },
1372 [&](const EndLabel
&) { Word("END="); },
1373 [&](const EorLabel
&) { Word("EOR="); },
1374 [&](const ErrLabel
&) { Word("ERR="); },
1375 [&](const IdExpr
&) { Word("ID="); },
1376 [&](const MsgVariable
&) { Word("IOMSG="); },
1377 [&](const StatVariable
&) { Word("IOSTAT="); },
1381 void Unparse(const BackspaceStmt
&x
) { // R1224
1382 Word("BACKSPACE ("), Walk(x
.v
, ", "), Put(')');
1384 void Unparse(const EndfileStmt
&x
) { // R1225
1385 Word("ENDFILE ("), Walk(x
.v
, ", "), Put(')');
1387 void Unparse(const RewindStmt
&x
) { // R1226
1388 Word("REWIND ("), Walk(x
.v
, ", "), Put(')');
1390 void Before(const PositionOrFlushSpec
&x
) { // R1227 & R1229
1391 common::visit(common::visitors
{
1392 [&](const FileUnitNumber
&) { Word("UNIT="); },
1393 [&](const MsgVariable
&) { Word("IOMSG="); },
1394 [&](const StatVariable
&) { Word("IOSTAT="); },
1395 [&](const ErrLabel
&) { Word("ERR="); },
1399 void Unparse(const FlushStmt
&x
) { // R1228
1400 Word("FLUSH ("), Walk(x
.v
, ", "), Put(')');
1402 void Unparse(const InquireStmt
&x
) { // R1230
1406 [&](const InquireStmt::Iolength
&y
) {
1407 Word("IOLENGTH="), Walk(y
.t
, ") ");
1409 [&](const std::list
<InquireSpec
> &y
) { Walk(y
, ", "), Put(')'); },
1413 bool Pre(const InquireSpec
&x
) { // R1231
1414 return common::visit(common::visitors
{
1415 [&](const FileUnitNumber
&) {
1419 [&](const FileNameExpr
&) {
1423 [&](const InquireSpec::CharVar
&y
) {
1427 [&](const InquireSpec::IntVar
&y
) {
1431 [&](const InquireSpec::LogVar
&y
) {
1435 [&](const IdExpr
&) {
1439 [&](const ErrLabel
&) {
1447 void Before(const FormatStmt
&) { // R1301
1450 void Unparse(const format::FormatSpecification
&x
) { // R1302, R1303, R1305
1451 Put('('), Walk("", x
.items
, ",", x
.unlimitedItems
.empty() ? "" : ",");
1452 Walk("*(", x
.unlimitedItems
, ",", ")"), Put(')');
1454 void Unparse(const format::FormatItem
&x
) { // R1304, R1306, R1321
1455 if (x
.repeatCount
) {
1456 Walk(*x
.repeatCount
);
1458 common::visit(common::visitors
{
1459 [&](const std::string
&y
) { PutNormalized(y
); },
1460 [&](const std::list
<format::FormatItem
> &y
) {
1461 Walk("(", y
, ",", ")");
1463 [&](const auto &y
) { Walk(y
); },
1468 const format::IntrinsicTypeDataEditDesc
&x
) { // R1307(1/2) - R1311
1471 case format::IntrinsicTypeDataEditDesc::Kind::x: \
1489 Walk(x
.width
), Walk(".", x
.digits
), Walk("E", x
.exponentWidth
);
1491 void Unparse(const format::DerivedTypeDataEditDesc
&x
) { // R1307(2/2), R1312
1493 if (!x
.type
.empty()) {
1494 Put('"'), Put(x
.type
), Put('"');
1496 Walk("(", x
.parameters
, ",", ")");
1498 void Unparse(const format::ControlEditDesc
&x
) { // R1313, R1315-R1320
1500 case format::ControlEditDesc::Kind::T
:
1504 case format::ControlEditDesc::Kind::TL
:
1508 case format::ControlEditDesc::Kind::TR
:
1512 case format::ControlEditDesc::Kind::X
:
1518 case format::ControlEditDesc::Kind::Slash
:
1524 case format::ControlEditDesc::Kind::Colon
:
1527 case format::ControlEditDesc::Kind::P
:
1532 case format::ControlEditDesc::Kind::x: \
1549 case format::ControlEditDesc::Kind::Dollar
:
1552 case format::ControlEditDesc::Kind::Backslash
:
1558 void Before(const MainProgram
&x
) { // R1401
1559 if (!std::get
<std::optional
<Statement
<ProgramStmt
>>>(x
.t
)) {
1563 void Before(const ProgramStmt
&) { // R1402
1564 Word("PROGRAM "), Indent();
1566 void Unparse(const EndProgramStmt
&x
) { // R1403
1567 EndSubprogram("PROGRAM", x
.v
);
1569 void Before(const ModuleStmt
&) { // R1405
1570 Word("MODULE "), Indent();
1572 void Unparse(const EndModuleStmt
&x
) { // R1406
1573 EndSubprogram("MODULE", x
.v
);
1575 void Unparse(const UseStmt
&x
) { // R1409
1576 Word("USE"), Walk(", ", x
.nature
), Put(" :: "), Walk(x
.moduleName
);
1579 [&](const std::list
<Rename
> &y
) { Walk(", ", y
, ", "); },
1580 [&](const std::list
<Only
> &y
) { Walk(", ONLY: ", y
, ", "); },
1584 void Unparse(const Rename
&x
) { // R1411
1585 common::visit(common::visitors
{
1586 [&](const Rename::Names
&y
) { Walk(y
.t
, " => "); },
1587 [&](const Rename::Operators
&y
) {
1588 Word("OPERATOR("), Walk(y
.t
, ") => OPERATOR("),
1594 void Unparse(const SubmoduleStmt
&x
) { // R1417
1595 Word("SUBMODULE ("), WalkTupleElements(x
.t
, ")"), Indent();
1597 void Unparse(const ParentIdentifier
&x
) { // R1418
1598 Walk(std::get
<Name
>(x
.t
)), Walk(":", std::get
<std::optional
<Name
>>(x
.t
));
1600 void Unparse(const EndSubmoduleStmt
&x
) { // R1419
1601 EndSubprogram("SUBMODULE", x
.v
);
1603 void Unparse(const BlockDataStmt
&x
) { // R1421
1604 Word("BLOCK DATA"), Walk(" ", x
.v
), Indent();
1606 void Unparse(const EndBlockDataStmt
&x
) { // R1422
1607 EndSubprogram("BLOCK DATA", x
.v
);
1610 void Unparse(const InterfaceStmt
&x
) { // R1503
1611 common::visit(common::visitors
{
1612 [&](const std::optional
<GenericSpec
> &y
) {
1613 Word("INTERFACE"), Walk(" ", y
);
1615 [&](const Abstract
&) { Word("ABSTRACT INTERFACE"); },
1620 void Unparse(const EndInterfaceStmt
&x
) { // R1504
1621 Outdent(), Word("END INTERFACE"), Walk(" ", x
.v
);
1623 void Unparse(const ProcedureStmt
&x
) { // R1506
1624 if (std::get
<ProcedureStmt::Kind
>(x
.t
) ==
1625 ProcedureStmt::Kind::ModuleProcedure
) {
1628 Word("PROCEDURE :: ");
1629 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
1631 void Before(const GenericSpec
&x
) { // R1508, R1509
1634 [&](const DefinedOperator
&) { Word("OPERATOR("); },
1635 [&](const GenericSpec::Assignment
&) { Word("ASSIGNMENT(=)"); },
1636 [&](const GenericSpec::ReadFormatted
&) {
1637 Word("READ(FORMATTED)");
1639 [&](const GenericSpec::ReadUnformatted
&) {
1640 Word("READ(UNFORMATTED)");
1642 [&](const GenericSpec::WriteFormatted
&) {
1643 Word("WRITE(FORMATTED)");
1645 [&](const GenericSpec::WriteUnformatted
&) {
1646 Word("WRITE(UNFORMATTED)");
1648 [](const auto &) {},
1652 void Post(const GenericSpec
&x
) {
1653 common::visit(common::visitors
{
1654 [&](const DefinedOperator
&) { Put(')'); },
1655 [](const auto &) {},
1659 void Unparse(const GenericStmt
&x
) { // R1510
1660 Word("GENERIC"), Walk(", ", std::get
<std::optional
<AccessSpec
>>(x
.t
));
1661 Put(" :: "), Walk(std::get
<GenericSpec
>(x
.t
)), Put(" => ");
1662 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
1664 void Unparse(const ExternalStmt
&x
) { // R1511
1665 Word("EXTERNAL :: "), Walk(x
.v
, ", ");
1667 void Unparse(const ProcedureDeclarationStmt
&x
) { // R1512
1668 Word("PROCEDURE("), Walk(std::get
<std::optional
<ProcInterface
>>(x
.t
));
1669 Put(')'), Walk(", ", std::get
<std::list
<ProcAttrSpec
>>(x
.t
), ", ");
1670 Put(" :: "), Walk(std::get
<std::list
<ProcDecl
>>(x
.t
), ", ");
1672 void Unparse(const ProcDecl
&x
) { // R1515
1673 Walk(std::get
<Name
>(x
.t
));
1674 Walk(" => ", std::get
<std::optional
<ProcPointerInit
>>(x
.t
));
1676 void Unparse(const IntrinsicStmt
&x
) { // R1519
1677 Word("INTRINSIC :: "), Walk(x
.v
, ", ");
1679 void Unparse(const FunctionReference
&x
) { // R1520
1680 Walk(std::get
<ProcedureDesignator
>(x
.v
.t
));
1681 Put('('), Walk(std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
), ", "), Put(')');
1683 void Unparse(const CallStmt
&x
) { // R1521
1684 if (asFortran_
&& x
.typedCall
.get()) {
1686 asFortran_
->call(out_
, *x
.typedCall
);
1689 const auto &pd
{std::get
<ProcedureDesignator
>(x
.v
.t
)};
1690 const auto &args
{std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
)};
1691 Word("CALL "), Walk(pd
);
1693 if (std::holds_alternative
<ProcComponentRef
>(pd
.u
)) {
1694 Put("()"); // pgf90 crashes on CALL to tbp without parentheses
1697 Walk("(", args
, ", ", ")");
1701 void Unparse(const ActualArgSpec
&x
) { // R1523
1702 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
1703 Walk(std::get
<ActualArg
>(x
.t
));
1705 void Unparse(const ActualArg::PercentRef
&x
) { // R1524
1706 Word("%REF("), Walk(x
.v
), Put(')');
1708 void Unparse(const ActualArg::PercentVal
&x
) {
1709 Word("%VAL("), Walk(x
.v
), Put(')');
1711 void Before(const AltReturnSpec
&) { // R1525
1714 void Post(const PrefixSpec::Elemental
) { Word("ELEMENTAL"); } // R1527
1715 void Post(const PrefixSpec::Impure
) { Word("IMPURE"); }
1716 void Post(const PrefixSpec::Module
) { Word("MODULE"); }
1717 void Post(const PrefixSpec::Non_Recursive
) { Word("NON_RECURSIVE"); }
1718 void Post(const PrefixSpec::Pure
) { Word("PURE"); }
1719 void Post(const PrefixSpec::Recursive
) { Word("RECURSIVE"); }
1720 void Unparse(const FunctionStmt
&x
) { // R1530
1721 Walk("", std::get
<std::list
<PrefixSpec
>>(x
.t
), " ", " ");
1722 Word("FUNCTION "), Walk(std::get
<Name
>(x
.t
)), Put("(");
1723 Walk(std::get
<std::list
<Name
>>(x
.t
), ", "), Put(')');
1724 Walk(" ", std::get
<std::optional
<Suffix
>>(x
.t
)), Indent();
1726 void Unparse(const Suffix
&x
) { // R1532
1728 Word("RESULT("), Walk(x
.resultName
), Put(')');
1729 Walk(" ", x
.binding
);
1734 void Unparse(const EndFunctionStmt
&x
) { // R1533
1735 EndSubprogram("FUNCTION", x
.v
);
1737 void Unparse(const SubroutineStmt
&x
) { // R1535
1738 Walk("", std::get
<std::list
<PrefixSpec
>>(x
.t
), " ", " ");
1739 Word("SUBROUTINE "), Walk(std::get
<Name
>(x
.t
));
1740 const auto &args
{std::get
<std::list
<DummyArg
>>(x
.t
)};
1741 const auto &bind
{std::get
<std::optional
<LanguageBindingSpec
>>(x
.t
)};
1745 Walk(" (", args
, ", ", ")");
1750 void Unparse(const EndSubroutineStmt
&x
) { // R1537
1751 EndSubprogram("SUBROUTINE", x
.v
);
1753 void Before(const MpSubprogramStmt
&) { // R1539
1754 Word("MODULE PROCEDURE "), Indent();
1756 void Unparse(const EndMpSubprogramStmt
&x
) { // R1540
1757 EndSubprogram("PROCEDURE", x
.v
);
1759 void Unparse(const EntryStmt
&x
) { // R1541
1760 Word("ENTRY "), Walk(std::get
<Name
>(x
.t
)), Put("(");
1761 Walk(std::get
<std::list
<DummyArg
>>(x
.t
), ", "), Put(")");
1762 Walk(" ", std::get
<std::optional
<Suffix
>>(x
.t
));
1764 void Unparse(const ReturnStmt
&x
) { // R1542
1765 Word("RETURN"), Walk(" ", x
.v
);
1767 void Unparse(const ContainsStmt
&) { // R1543
1772 void Unparse(const StmtFunctionStmt
&x
) { // R1544
1773 Walk(std::get
<Name
>(x
.t
)), Put('(');
1774 Walk(std::get
<std::list
<Name
>>(x
.t
), ", "), Put(") = ");
1775 Walk(std::get
<Scalar
<Expr
>>(x
.t
));
1778 // Directives, extensions, and deprecated constructs
1779 void Unparse(const CompilerDirective
&x
) {
1782 [&](const std::list
<CompilerDirective::IgnoreTKR
> &tkr
) {
1783 Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty
1784 Walk(" ", tkr
, ", ");
1786 [&](const CompilerDirective::LoopCount
&lcount
) {
1787 Walk("!DIR$ LOOP COUNT (", lcount
.v
, ", ", ")");
1789 [&](const std::list
<CompilerDirective::NameValue
> &names
) {
1790 Walk("!DIR$ ", names
, " ");
1796 void Unparse(const CompilerDirective::IgnoreTKR
&x
) {
1797 const auto &list
{std::get
<std::list
<const char *>>(x
.t
)};
1798 if (!list
.empty()) {
1800 for (const char *tkr
: list
) {
1805 Walk(std::get
<Name
>(x
.t
));
1807 void Unparse(const CompilerDirective::NameValue
&x
) {
1808 Walk(std::get
<Name
>(x
.t
));
1809 Walk("=", std::get
<std::optional
<std::uint64_t>>(x
.t
));
1812 // OpenACC Directives & Clauses
1813 void Unparse(const AccAtomicCapture
&x
) {
1815 Word("!$ACC CAPTURE");
1818 Walk(std::get
<AccAtomicCapture::Stmt1
>(x
.t
));
1820 Walk(std::get
<AccAtomicCapture::Stmt2
>(x
.t
));
1822 Word("!$ACC END ATOMIC\n");
1825 void Unparse(const AccAtomicRead
&x
) {
1827 Word("!$ACC ATOMIC READ");
1830 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1832 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1835 void Unparse(const AccAtomicWrite
&x
) {
1837 Word("!$ACC ATOMIC WRITE");
1840 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1842 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1845 void Unparse(const AccAtomicUpdate
&x
) {
1847 Word("!$ACC ATOMIC UPDATE");
1850 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1852 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1855 void Unparse(const llvm::acc::Directive
&x
) {
1856 Word(llvm::acc::getOpenACCDirectiveName(x
).str());
1858 #define GEN_FLANG_CLAUSE_UNPARSE
1859 #include "llvm/Frontend/OpenACC/ACC.inc"
1860 void Unparse(const AccObjectListWithModifier
&x
) {
1861 Walk(std::get
<std::optional
<AccDataModifier
>>(x
.t
), ":");
1862 Walk(std::get
<AccObjectList
>(x
.t
));
1864 void Unparse(const AccDataModifier::Modifier
&x
) {
1865 Word(AccDataModifier::EnumToString(x
));
1867 void Unparse(const AccBindClause
&x
) {
1868 common::visit(common::visitors
{
1869 [&](const Name
&y
) { Put('('), Walk(y
), Put(')'); },
1870 [&](const ScalarDefaultCharExpr
&y
) {
1871 Put('('), Walk(y
), Put(')');
1876 void Unparse(const AccDefaultClause
&x
) {
1878 case llvm::acc::DefaultValue::ACC_Default_none
:
1881 case llvm::acc::DefaultValue::ACC_Default_present
:
1886 void Unparse(const AccClauseList
&x
) { Walk(" ", x
.v
, " "); }
1887 void Unparse(const AccGangArgument
&x
) {
1888 Walk("NUM:", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
1889 Walk(", STATIC:", std::get
<std::optional
<AccSizeExpr
>>(x
.t
));
1891 void Unparse(const OpenACCBlockConstruct
&x
) {
1894 Walk(std::get
<AccBeginBlockDirective
>(x
.t
));
1897 Walk(std::get
<Block
>(x
.t
), "");
1900 Walk(std::get
<AccEndBlockDirective
>(x
.t
));
1904 void Unparse(const OpenACCLoopConstruct
&x
) {
1907 Walk(std::get
<AccBeginLoopDirective
>(x
.t
));
1910 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
1912 void Unparse(const AccBeginLoopDirective
&x
) {
1913 Walk(std::get
<AccLoopDirective
>(x
.t
));
1914 Walk(std::get
<AccClauseList
>(x
.t
));
1916 void Unparse(const OpenACCStandaloneConstruct
&x
) {
1919 Walk(std::get
<AccStandaloneDirective
>(x
.t
));
1920 Walk(std::get
<AccClauseList
>(x
.t
));
1924 void Unparse(const OpenACCStandaloneDeclarativeConstruct
&x
) {
1927 Walk(std::get
<AccDeclarativeDirective
>(x
.t
));
1928 Walk(std::get
<AccClauseList
>(x
.t
));
1932 void Unparse(const OpenACCCombinedConstruct
&x
) {
1935 Walk(std::get
<AccBeginCombinedDirective
>(x
.t
));
1938 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
1940 Walk("!$ACC END ", std::get
<std::optional
<AccEndCombinedDirective
>>(x
.t
),
1944 void Unparse(const OpenACCRoutineConstruct
&x
) {
1946 Word("!$ACC ROUTINE");
1947 Walk("(", std::get
<std::optional
<Name
>>(x
.t
), ")");
1948 Walk(std::get
<AccClauseList
>(x
.t
));
1952 void Unparse(const AccObject
&x
) {
1953 common::visit(common::visitors
{
1954 [&](const Designator
&y
) { Walk(y
); },
1955 [&](const Name
&y
) { Put("/"), Walk(y
), Put("/"); },
1959 void Unparse(const AccObjectList
&x
) { Walk(x
.v
, ","); }
1960 void Unparse(const AccReductionOperator::Operator
&x
) {
1961 Word(AccReductionOperator::EnumToString(x
));
1963 void Unparse(const AccObjectListWithReduction
&x
) {
1964 Walk(std::get
<AccReductionOperator
>(x
.t
));
1966 Walk(std::get
<AccObjectList
>(x
.t
));
1968 void Unparse(const OpenACCCacheConstruct
&x
) {
1972 Walk(std::get
<AccObjectListWithModifier
>(x
.t
));
1977 void Unparse(const AccWaitArgument
&x
) {
1978 Walk("DEVNUM:", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
), ":");
1979 Walk(std::get
<std::list
<ScalarIntExpr
>>(x
.t
), ",");
1981 void Unparse(const OpenACCWaitConstruct
&x
) {
1985 Walk(std::get
<std::optional
<AccWaitArgument
>>(x
.t
));
1986 Walk(std::get
<AccClauseList
>(x
.t
));
1992 // OpenMP Clauses & Directives
1993 void Unparse(const OmpObject
&x
) {
1994 common::visit(common::visitors
{
1995 [&](const Designator
&y
) { Walk(y
); },
1996 [&](const Name
&y
) { Put("/"), Walk(y
), Put("/"); },
2000 void Unparse(const OmpMapType::Always
&) { Word("ALWAYS,"); }
2001 void Unparse(const OmpMapClause
&x
) {
2002 Walk(std::get
<std::optional
<OmpMapType
>>(x
.t
), ":");
2003 Walk(std::get
<OmpObjectList
>(x
.t
));
2005 void Unparse(const OmpScheduleModifier
&x
) {
2006 Walk(std::get
<OmpScheduleModifier::Modifier1
>(x
.t
));
2007 Walk(",", std::get
<std::optional
<OmpScheduleModifier::Modifier2
>>(x
.t
));
2009 void Unparse(const OmpScheduleClause
&x
) {
2010 Walk(std::get
<std::optional
<OmpScheduleModifier
>>(x
.t
), ":");
2011 Walk(std::get
<OmpScheduleClause::ScheduleType
>(x
.t
));
2012 Walk(",", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
2014 void Unparse(const OmpDeviceClause
&x
) {
2015 Walk(std::get
<std::optional
<OmpDeviceClause::DeviceModifier
>>(x
.t
), ":");
2016 Walk(std::get
<ScalarIntExpr
>(x
.t
));
2018 void Unparse(const OmpAlignedClause
&x
) {
2019 Walk(std::get
<std::list
<Name
>>(x
.t
), ",");
2020 Walk(std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
2022 void Unparse(const OmpIfClause
&x
) {
2023 Walk(std::get
<std::optional
<OmpIfClause::DirectiveNameModifier
>>(x
.t
), ":");
2024 Walk(std::get
<ScalarLogicalExpr
>(x
.t
));
2026 void Unparse(const OmpLinearClause::WithoutModifier
&x
) {
2027 Walk(x
.names
, ", ");
2030 void Unparse(const OmpLinearClause::WithModifier
&x
) {
2031 Walk(x
.modifier
), Put("("), Walk(x
.names
, ","), Put(")");
2034 void Unparse(const OmpReductionClause
&x
) {
2035 Walk(std::get
<OmpReductionOperator
>(x
.t
));
2037 Walk(std::get
<OmpObjectList
>(x
.t
));
2039 void Unparse(const OmpInReductionClause
&x
) {
2040 Walk(std::get
<OmpReductionOperator
>(x
.t
));
2042 Walk(std::get
<OmpObjectList
>(x
.t
));
2044 void Unparse(const OmpAllocateClause
&x
) {
2045 Walk(std::get
<std::optional
<OmpAllocateClause::Allocator
>>(x
.t
));
2047 Walk(std::get
<OmpObjectList
>(x
.t
));
2049 void Unparse(const OmpOrderClause
&x
) {
2050 Walk(std::get
<std::optional
<OmpOrderModifier
>>(x
.t
), ":");
2051 Walk(std::get
<OmpOrderClause::Type
>(x
.t
));
2053 void Unparse(const OmpDependSinkVecLength
&x
) {
2054 Walk(std::get
<DefinedOperator
>(x
.t
));
2055 Walk(std::get
<ScalarIntConstantExpr
>(x
.t
));
2057 void Unparse(const OmpDependSinkVec
&x
) {
2058 Walk(std::get
<Name
>(x
.t
));
2059 Walk(std::get
<std::optional
<OmpDependSinkVecLength
>>(x
.t
));
2061 void Unparse(const OmpDependClause::InOut
&x
) {
2063 Walk(std::get
<OmpDependenceType
>(x
.t
));
2065 Walk(std::get
<std::list
<Designator
>>(x
.t
), ",");
2068 bool Pre(const OmpDependClause
&x
) {
2069 return common::visit(
2071 [&](const OmpDependClause::Source
&) {
2075 [&](const OmpDependClause::Sink
&y
) {
2081 [&](const OmpDependClause::InOut
&) { return true; },
2085 void Unparse(const OmpDefaultmapClause
&x
) {
2086 Walk(std::get
<OmpDefaultmapClause::ImplicitBehavior
>(x
.t
));
2088 std::get
<std::optional
<OmpDefaultmapClause::VariableCategory
>>(x
.t
));
2090 #define GEN_FLANG_CLAUSE_UNPARSE
2091 #include "llvm/Frontend/OpenMP/OMP.inc"
2092 void Unparse(const OmpLoopDirective
&x
) {
2094 case llvm::omp::Directive::OMPD_distribute
:
2095 Word("DISTRIBUTE ");
2097 case llvm::omp::Directive::OMPD_distribute_parallel_do
:
2098 Word("DISTRIBUTE PARALLEL DO ");
2100 case llvm::omp::Directive::OMPD_distribute_parallel_do_simd
:
2101 Word("DISTRIBUTE PARALLEL DO SIMD ");
2103 case llvm::omp::Directive::OMPD_distribute_simd
:
2104 Word("DISTRIBUTE SIMD ");
2106 case llvm::omp::Directive::OMPD_do
:
2109 case llvm::omp::Directive::OMPD_do_simd
:
2112 case llvm::omp::Directive::OMPD_parallel_do
:
2113 Word("PARALLEL DO ");
2115 case llvm::omp::Directive::OMPD_parallel_do_simd
:
2116 Word("PARALLEL DO SIMD ");
2118 case llvm::omp::Directive::OMPD_simd
:
2121 case llvm::omp::Directive::OMPD_target_parallel_do
:
2122 Word("TARGET PARALLEL DO ");
2124 case llvm::omp::Directive::OMPD_target_parallel_do_simd
:
2125 Word("TARGET PARALLEL DO SIMD ");
2127 case llvm::omp::Directive::OMPD_target_teams_distribute
:
2128 Word("TARGET TEAMS DISTRIBUTE ");
2130 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do
:
2131 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO ");
2133 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd
:
2134 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2136 case llvm::omp::Directive::OMPD_target_teams_distribute_simd
:
2137 Word("TARGET TEAMS DISTRIBUTE SIMD ");
2139 case llvm::omp::Directive::OMPD_target_simd
:
2140 Word("TARGET SIMD ");
2142 case llvm::omp::Directive::OMPD_taskloop
:
2145 case llvm::omp::Directive::OMPD_taskloop_simd
:
2146 Word("TASKLOOP SIMD ");
2148 case llvm::omp::Directive::OMPD_teams_distribute
:
2149 Word("TEAMS DISTRIBUTE ");
2151 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do
:
2152 Word("TEAMS DISTRIBUTE PARALLEL DO ");
2154 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd
:
2155 Word("TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2157 case llvm::omp::Directive::OMPD_teams_distribute_simd
:
2158 Word("TEAMS DISTRIBUTE SIMD ");
2160 case llvm::omp::Directive::OMPD_tile
:
2163 case llvm::omp::Directive::OMPD_unroll
:
2170 void Unparse(const OmpObjectList
&x
) { Walk(x
.v
, ","); }
2171 void Unparse(const OmpSimpleStandaloneDirective
&x
) {
2173 case llvm::omp::Directive::OMPD_barrier
:
2176 case llvm::omp::Directive::OMPD_taskwait
:
2179 case llvm::omp::Directive::OMPD_taskyield
:
2182 case llvm::omp::Directive::OMPD_target_enter_data
:
2183 Word("TARGET ENTER DATA ");
2185 case llvm::omp::Directive::OMPD_target_exit_data
:
2186 Word("TARGET EXIT DATA ");
2188 case llvm::omp::Directive::OMPD_target_update
:
2189 Word("TARGET UPDATE ");
2191 case llvm::omp::Directive::OMPD_ordered
:
2195 // Nothing to be done
2199 void Unparse(const OmpBlockDirective
&x
) {
2201 case llvm::omp::Directive::OMPD_master
:
2204 case llvm::omp::Directive::OMPD_ordered
:
2207 case llvm::omp::Directive::OMPD_parallel_workshare
:
2208 Word("PARALLEL WORKSHARE ");
2210 case llvm::omp::Directive::OMPD_parallel
:
2213 case llvm::omp::Directive::OMPD_single
:
2216 case llvm::omp::Directive::OMPD_target_data
:
2217 Word("TARGET DATA ");
2219 case llvm::omp::Directive::OMPD_target_parallel
:
2220 Word("TARGET PARALLEL ");
2222 case llvm::omp::Directive::OMPD_target_teams
:
2223 Word("TARGET TEAMS ");
2225 case llvm::omp::Directive::OMPD_target
:
2228 case llvm::omp::Directive::OMPD_taskgroup
:
2231 case llvm::omp::Directive::OMPD_task
:
2234 case llvm::omp::Directive::OMPD_teams
:
2237 case llvm::omp::Directive::OMPD_workshare
:
2241 // Nothing to be done
2246 void Unparse(const OmpAtomicDefaultMemOrderClause
&x
) {
2248 case OmpAtomicDefaultMemOrderClause::Type::SeqCst
:
2251 case OmpAtomicDefaultMemOrderClause::Type::AcqRel
:
2254 case OmpAtomicDefaultMemOrderClause::Type::Relaxed
:
2260 void Unparse(const OmpAtomicClauseList
&x
) { Walk(" ", x
.v
, " "); }
2262 void Unparse(const OmpAtomic
&x
) {
2264 Word("!$OMP ATOMIC");
2265 Walk(std::get
<OmpAtomicClauseList
>(x
.t
));
2268 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2270 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2273 void Unparse(const OmpAtomicCapture
&x
) {
2275 Word("!$OMP ATOMIC");
2276 Walk(std::get
<0>(x
.t
));
2278 Walk(std::get
<2>(x
.t
));
2281 Walk(std::get
<OmpAtomicCapture::Stmt1
>(x
.t
));
2283 Walk(std::get
<OmpAtomicCapture::Stmt2
>(x
.t
));
2285 Word("!$OMP END ATOMIC\n");
2288 void Unparse(const OmpAtomicRead
&x
) {
2290 Word("!$OMP ATOMIC");
2291 Walk(std::get
<0>(x
.t
));
2293 Walk(std::get
<2>(x
.t
));
2296 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2298 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2301 void Unparse(const OmpAtomicUpdate
&x
) {
2303 Word("!$OMP ATOMIC");
2304 Walk(std::get
<0>(x
.t
));
2306 Walk(std::get
<2>(x
.t
));
2309 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2311 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2314 void Unparse(const OmpAtomicWrite
&x
) {
2316 Word("!$OMP ATOMIC");
2317 Walk(std::get
<0>(x
.t
));
2319 Walk(std::get
<2>(x
.t
));
2322 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2324 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2327 void Unparse(const OpenMPExecutableAllocate
&x
) {
2329 Word("!$OMP ALLOCATE");
2330 Walk(" (", std::get
<std::optional
<OmpObjectList
>>(x
.t
), ")");
2331 Walk(std::get
<OmpClauseList
>(x
.t
));
2334 Walk(std::get
<Statement
<AllocateStmt
>>(x
.t
));
2336 void Unparse(const OpenMPDeclarativeAllocate
&x
) {
2338 Word("!$OMP ALLOCATE");
2340 Walk(std::get
<OmpObjectList
>(x
.t
));
2342 Walk(std::get
<OmpClauseList
>(x
.t
));
2346 void Unparse(const OmpCriticalDirective
&x
) {
2348 Word("!$OMP CRITICAL");
2349 Walk(" (", std::get
<std::optional
<Name
>>(x
.t
), ")");
2350 Walk(std::get
<OmpClauseList
>(x
.t
));
2354 void Unparse(const OmpEndCriticalDirective
&x
) {
2356 Word("!$OMP END CRITICAL");
2357 Walk(" (", std::get
<std::optional
<Name
>>(x
.t
), ")");
2361 void Unparse(const OpenMPCriticalConstruct
&x
) {
2362 Walk(std::get
<OmpCriticalDirective
>(x
.t
));
2363 Walk(std::get
<Block
>(x
.t
), "");
2364 Walk(std::get
<OmpEndCriticalDirective
>(x
.t
));
2366 void Unparse(const OmpDeclareTargetWithList
&x
) {
2367 Put("("), Walk(x
.v
), Put(")");
2369 void Unparse(const OmpReductionInitializerClause
&x
) {
2370 Word(" INITIALIZER(OMP_PRIV = ");
2374 void Unparse(const OmpReductionCombiner::FunctionCombiner
&x
) {
2375 const auto &pd
= std::get
<ProcedureDesignator
>(x
.v
.t
);
2376 const auto &args
= std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
);
2379 if (std::holds_alternative
<ProcComponentRef
>(pd
.u
)) {
2383 Walk("(", args
, ", ", ")");
2386 void Unparse(const OpenMPDeclareReductionConstruct
&x
) {
2388 Walk(std::get
<OmpReductionOperator
>(x
.t
)), Put(" : ");
2389 Walk(std::get
<std::list
<DeclarationTypeSpec
>>(x
.t
), ","), Put(" : ");
2390 Walk(std::get
<OmpReductionCombiner
>(x
.t
));
2392 Walk(std::get
<std::optional
<OmpReductionInitializerClause
>>(x
.t
));
2394 bool Pre(const OpenMPDeclarativeConstruct
&x
) {
2397 return common::visit(
2399 [&](const OpenMPDeclarativeAllocate
&z
) {
2401 Walk(std::get
<OmpObjectList
>(z
.t
));
2403 Walk(std::get
<OmpClauseList
>(z
.t
));
2408 [&](const OpenMPDeclareReductionConstruct
&) {
2409 Word("DECLARE REDUCTION ");
2412 [&](const OpenMPDeclareSimdConstruct
&y
) {
2413 Word("DECLARE SIMD ");
2414 Walk("(", std::get
<std::optional
<Name
>>(y
.t
), ")");
2415 Walk(std::get
<OmpClauseList
>(y
.t
));
2420 [&](const OpenMPDeclareTargetConstruct
&) {
2421 Word("DECLARE TARGET ");
2424 [&](const OpenMPRequiresConstruct
&y
) {
2426 Walk(std::get
<OmpClauseList
>(y
.t
));
2431 [&](const OpenMPThreadprivate
&) {
2432 Word("THREADPRIVATE (");
2438 void Post(const OpenMPDeclarativeConstruct
&) {
2442 void Post(const OpenMPThreadprivate
&) {
2446 void Unparse(const OmpSectionsDirective
&x
) {
2448 case llvm::omp::Directive::OMPD_sections
:
2451 case llvm::omp::Directive::OMPD_parallel_sections
:
2452 Word("PARALLEL SECTIONS ");
2458 void Unparse(const OmpSectionBlocks
&x
) {
2459 for (const auto &y
: x
.v
) {
2461 Word("!$OMP SECTION");
2464 // y.u is an OpenMPSectionConstruct
2466 Walk(std::get
<OpenMPSectionConstruct
>(y
.u
).v
, "");
2469 void Unparse(const OpenMPSectionsConstruct
&x
) {
2472 Walk(std::get
<OmpBeginSectionsDirective
>(x
.t
));
2475 Walk(std::get
<OmpSectionBlocks
>(x
.t
));
2478 Walk(std::get
<OmpEndSectionsDirective
>(x
.t
));
2482 void Unparse(const OpenMPCancellationPointConstruct
&x
) {
2484 Word("!$OMP CANCELLATION POINT ");
2485 Walk(std::get
<OmpCancelType
>(x
.t
));
2489 void Unparse(const OpenMPCancelConstruct
&x
) {
2491 Word("!$OMP CANCEL ");
2492 Walk(std::get
<OmpCancelType
>(x
.t
));
2493 Walk(std::get
<std::optional
<OpenMPCancelConstruct::If
>>(x
.t
));
2497 void Unparse(const OmpMemoryOrderClause
&x
) { Walk(x
.v
); }
2498 void Unparse(const OmpAtomicClause
&x
) {
2499 common::visit(common::visitors
{
2500 [&](const OmpMemoryOrderClause
&y
) { Walk(y
); },
2501 [&](const OmpClause
&z
) { Walk(z
); },
2505 void Unparse(const OpenMPFlushConstruct
&x
) {
2507 Word("!$OMP FLUSH ");
2508 Walk(std::get
<std::optional
<std::list
<OmpMemoryOrderClause
>>>(x
.t
));
2509 Walk(" (", std::get
<std::optional
<OmpObjectList
>>(x
.t
), ")");
2513 void Unparse(const OmpEndLoopDirective
&x
) {
2516 Walk(std::get
<OmpLoopDirective
>(x
.t
));
2517 Walk(std::get
<OmpClauseList
>(x
.t
));
2521 void Unparse(const OmpClauseList
&x
) { Walk(" ", x
.v
, " "); }
2522 void Unparse(const OpenMPSimpleStandaloneConstruct
&x
) {
2525 Walk(std::get
<OmpSimpleStandaloneDirective
>(x
.t
));
2526 Walk(std::get
<OmpClauseList
>(x
.t
));
2530 void Unparse(const OpenMPBlockConstruct
&x
) {
2533 Walk(std::get
<OmpBeginBlockDirective
>(x
.t
));
2536 Walk(std::get
<Block
>(x
.t
), "");
2539 Walk(std::get
<OmpEndBlockDirective
>(x
.t
));
2543 void Unparse(const OpenMPLoopConstruct
&x
) {
2546 Walk(std::get
<OmpBeginLoopDirective
>(x
.t
));
2549 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
2550 Walk(std::get
<std::optional
<OmpEndLoopDirective
>>(x
.t
));
2552 void Unparse(const BasedPointer
&x
) {
2553 Put('('), Walk(std::get
<0>(x
.t
)), Put(","), Walk(std::get
<1>(x
.t
));
2554 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")"), Put(')');
2556 void Unparse(const BasedPointerStmt
&x
) { Walk("POINTER ", x
.v
, ","); }
2557 void Post(const StructureField
&x
) {
2558 if (const auto *def
{std::get_if
<Statement
<DataComponentDefStmt
>>(&x
.u
)}) {
2559 for (const auto &item
:
2560 std::get
<std::list
<ComponentOrFill
>>(def
->statement
.t
)) {
2561 if (const auto *comp
{std::get_if
<ComponentDecl
>(&item
.u
)}) {
2562 structureComponents_
.insert(std::get
<Name
>(comp
->t
).source
);
2567 void Unparse(const StructureStmt
&x
) {
2569 // The name, if present, includes the /slashes/
2570 Walk(std::get
<std::optional
<Name
>>(x
.t
));
2571 Walk(" ", std::get
<std::list
<EntityDecl
>>(x
.t
), ", ");
2574 void Post(const Union::UnionStmt
&) { Word("UNION"), Indent(); }
2575 void Post(const Union::EndUnionStmt
&) { Outdent(), Word("END UNION"); }
2576 void Post(const Map::MapStmt
&) { Word("MAP"), Indent(); }
2577 void Post(const Map::EndMapStmt
&) { Outdent(), Word("END MAP"); }
2578 void Post(const StructureDef::EndStructureStmt
&) {
2579 Outdent(), Word("END STRUCTURE");
2581 void Unparse(const OldParameterStmt
&x
) {
2582 Word("PARAMETER "), Walk(x
.v
, ", ");
2584 void Unparse(const ArithmeticIfStmt
&x
) {
2585 Word("IF ("), Walk(std::get
<Expr
>(x
.t
)), Put(") ");
2586 Walk(std::get
<1>(x
.t
)), Put(", ");
2587 Walk(std::get
<2>(x
.t
)), Put(", ");
2588 Walk(std::get
<3>(x
.t
));
2590 void Unparse(const AssignStmt
&x
) {
2591 Word("ASSIGN "), Walk(std::get
<Label
>(x
.t
));
2592 Word(" TO "), Walk(std::get
<Name
>(x
.t
));
2594 void Unparse(const AssignedGotoStmt
&x
) {
2595 Word("GO TO "), Walk(std::get
<Name
>(x
.t
));
2596 Walk(", (", std::get
<std::list
<Label
>>(x
.t
), ", ", ")");
2598 void Unparse(const PauseStmt
&x
) { Word("PAUSE"), Walk(" ", x
.v
); }
2600 #define WALK_NESTED_ENUM(CLASS, ENUM) \
2601 void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); }
2602 WALK_NESTED_ENUM(AccessSpec
, Kind
) // R807
2603 WALK_NESTED_ENUM(common
, TypeParamAttr
) // R734
2604 WALK_NESTED_ENUM(IntentSpec
, Intent
) // R826
2605 WALK_NESTED_ENUM(ImplicitStmt
, ImplicitNoneNameSpec
) // R866
2606 WALK_NESTED_ENUM(ConnectSpec::CharExpr
, Kind
) // R1205
2607 WALK_NESTED_ENUM(IoControlSpec::CharExpr
, Kind
)
2608 WALK_NESTED_ENUM(InquireSpec::CharVar
, Kind
)
2609 WALK_NESTED_ENUM(InquireSpec::IntVar
, Kind
)
2610 WALK_NESTED_ENUM(InquireSpec::LogVar
, Kind
)
2611 WALK_NESTED_ENUM(ProcedureStmt
, Kind
) // R1506
2612 WALK_NESTED_ENUM(UseStmt
, ModuleNature
) // R1410
2613 WALK_NESTED_ENUM(OmpProcBindClause
, Type
) // OMP PROC_BIND
2614 WALK_NESTED_ENUM(OmpDefaultClause
, Type
) // OMP DEFAULT
2615 WALK_NESTED_ENUM(OmpDefaultmapClause
, ImplicitBehavior
) // OMP DEFAULTMAP
2616 WALK_NESTED_ENUM(OmpDefaultmapClause
, VariableCategory
) // OMP DEFAULTMAP
2617 WALK_NESTED_ENUM(OmpScheduleModifierType
, ModType
) // OMP schedule-modifier
2618 WALK_NESTED_ENUM(OmpLinearModifier
, Type
) // OMP linear-modifier
2619 WALK_NESTED_ENUM(OmpDependenceType
, Type
) // OMP dependence-type
2620 WALK_NESTED_ENUM(OmpMapType
, Type
) // OMP map-type
2621 WALK_NESTED_ENUM(OmpScheduleClause
, ScheduleType
) // OMP schedule-type
2622 WALK_NESTED_ENUM(OmpDeviceClause
, DeviceModifier
) // OMP device modifier
2623 WALK_NESTED_ENUM(OmpDeviceTypeClause
, Type
) // OMP DEVICE_TYPE
2624 WALK_NESTED_ENUM(OmpIfClause
, DirectiveNameModifier
) // OMP directive-modifier
2625 WALK_NESTED_ENUM(OmpCancelType
, Type
) // OMP cancel-type
2626 WALK_NESTED_ENUM(OmpOrderClause
, Type
) // OMP order-type
2627 WALK_NESTED_ENUM(OmpOrderModifier
, Kind
) // OMP order-modifier
2628 #undef WALK_NESTED_ENUM
2630 void Done() const { CHECK(indent_
== 0); }
2634 void Put(const char *);
2635 void Put(const std::string
&);
2636 void PutNormalized(const std::string
&);
2637 void PutKeywordLetter(char);
2638 void Word(const char *);
2639 void Word(const std::string
&);
2640 void Word(const std::string_view
&);
2641 void Indent() { indent_
+= indentationAmount_
; }
2643 CHECK(indent_
>= indentationAmount_
);
2644 indent_
-= indentationAmount_
;
2646 void BeginOpenMP() { openmpDirective_
= true; }
2647 void EndOpenMP() { openmpDirective_
= false; }
2648 void BeginOpenACC() { openaccDirective_
= true; }
2649 void EndOpenACC() { openaccDirective_
= false; }
2651 // Call back to the traversal framework.
2652 template <typename T
> void Walk(const T
&x
) {
2653 Fortran::parser::Walk(x
, *this);
2656 // Traverse a std::optional<> value. Emit a prefix and/or a suffix string
2657 // only when it contains a value.
2658 template <typename A
>
2660 const char *prefix
, const std::optional
<A
> &x
, const char *suffix
= "") {
2662 Word(prefix
), Walk(*x
), Word(suffix
);
2665 template <typename A
>
2666 void Walk(const std::optional
<A
> &x
, const char *suffix
= "") {
2667 return Walk("", x
, suffix
);
2670 // Traverse a std::list<>. Separate the elements with an optional string.
2671 // Emit a prefix and/or a suffix string only when the list is not empty.
2672 template <typename A
>
2673 void Walk(const char *prefix
, const std::list
<A
> &list
,
2674 const char *comma
= ", ", const char *suffix
= "") {
2675 if (!list
.empty()) {
2676 const char *str
{prefix
};
2677 for (const auto &x
: list
) {
2684 template <typename A
>
2685 void Walk(const std::list
<A
> &list
, const char *comma
= ", ",
2686 const char *suffix
= "") {
2687 return Walk("", list
, comma
, suffix
);
2690 // Traverse a std::tuple<>, with an optional separator.
2691 template <std::size_t J
= 0, typename T
>
2692 void WalkTupleElements(const T
&tuple
, const char *separator
) {
2693 if (J
> 0 && J
< std::tuple_size_v
<T
>) {
2694 Word(separator
); // this usage dodges "unused parameter" warning
2696 if constexpr (J
< std::tuple_size_v
<T
>) {
2697 Walk(std::get
<J
>(tuple
));
2698 WalkTupleElements
<J
+ 1>(tuple
, separator
);
2701 template <typename
... A
>
2702 void Walk(const std::tuple
<A
...> &tuple
, const char *separator
= "") {
2703 WalkTupleElements(tuple
, separator
);
2706 void EndSubprogram(const char *kind
, const std::optional
<Name
> &name
) {
2707 Outdent(), Word("END "), Word(kind
), Walk(" ", name
);
2708 structureComponents_
.clear();
2711 llvm::raw_ostream
&out_
;
2713 const int indentationAmount_
{1};
2715 const int maxColumns_
{80};
2716 std::set
<CharBlock
> structureComponents_
;
2717 Encoding encoding_
{Encoding::UTF_8
};
2718 bool capitalizeKeywords_
{true};
2719 bool openaccDirective_
{false};
2720 bool openmpDirective_
{false};
2721 bool backslashEscapes_
{false};
2722 preStatementType
*preStatement_
{nullptr};
2723 AnalyzedObjectsAsFortran
*asFortran_
{nullptr};
2726 void UnparseVisitor::Put(char ch
) {
2728 if (openmpDirective_
|| openaccDirective_
) {
2735 for (int j
{0}; j
< indent_
; ++j
) {
2738 column_
= indent_
+ 2;
2739 } else if (ch
== '\n') {
2741 } else if (++column_
>= maxColumns_
) {
2743 for (int j
{0}; j
< indent_
; ++j
) {
2746 if (openmpDirective_
) {
2749 } else if (openaccDirective_
) {
2754 column_
= indent_
+ 3;
2758 if (openmpDirective_
|| openaccDirective_
) {
2763 void UnparseVisitor::Put(const char *str
) {
2764 for (; *str
!= '\0'; ++str
) {
2769 void UnparseVisitor::Put(const std::string
&str
) {
2770 for (char ch
: str
) {
2775 void UnparseVisitor::PutNormalized(const std::string
&str
) {
2776 auto decoded
{DecodeString
<std::string
, Encoding::LATIN_1
>(str
, true)};
2777 std::string encoded
{EncodeString
<Encoding::LATIN_1
>(decoded
)};
2778 Put(QuoteCharacterLiteral(encoded
, backslashEscapes_
));
2781 void UnparseVisitor::PutKeywordLetter(char ch
) {
2782 if (capitalizeKeywords_
) {
2783 Put(ToUpperCaseLetter(ch
));
2785 Put(ToLowerCaseLetter(ch
));
2789 void UnparseVisitor::Word(const char *str
) {
2790 for (; *str
!= '\0'; ++str
) {
2791 PutKeywordLetter(*str
);
2795 void UnparseVisitor::Word(const std::string
&str
) { Word(str
.c_str()); }
2797 void UnparseVisitor::Word(const std::string_view
&str
) {
2798 for (std::size_t j
{0}; j
< str
.length(); ++j
) {
2799 PutKeywordLetter(str
[j
]);
2803 template <typename A
>
2804 void Unparse(llvm::raw_ostream
&out
, const A
&root
, Encoding encoding
,
2805 bool capitalizeKeywords
, bool backslashEscapes
,
2806 preStatementType
*preStatement
, AnalyzedObjectsAsFortran
*asFortran
) {
2807 UnparseVisitor visitor
{out
, 1, encoding
, capitalizeKeywords
, backslashEscapes
,
2808 preStatement
, asFortran
};
2809 Walk(root
, visitor
);
2813 template void Unparse
<Program
>(llvm::raw_ostream
&, const Program
&, Encoding
,
2814 bool, bool, preStatementType
*, AnalyzedObjectsAsFortran
*);
2815 template void Unparse
<Expr
>(llvm::raw_ostream
&, const Expr
&, Encoding
, bool,
2816 bool, preStatementType
*, AnalyzedObjectsAsFortran
*);
2817 } // namespace Fortran::parser