1 //===-- lib/Parser/unparse.cpp --------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Generates Fortran from the content of a parse tree, using the
10 // traversal templates in parse-tree-visitor.h.
12 #include "flang/Parser/unparse.h"
13 #include "flang/Common/Fortran.h"
14 #include "flang/Common/idioms.h"
15 #include "flang/Common/indirection.h"
16 #include "flang/Parser/characters.h"
17 #include "flang/Parser/parse-tree-visitor.h"
18 #include "flang/Parser/parse-tree.h"
19 #include "flang/Parser/tools.h"
20 #include "llvm/Support/raw_ostream.h"
26 namespace Fortran::parser
{
28 class UnparseVisitor
{
30 UnparseVisitor(llvm::raw_ostream
&out
, int indentationAmount
,
31 Encoding encoding
, bool capitalize
, bool backslashEscapes
,
32 preStatementType
*preStatement
, AnalyzedObjectsAsFortran
*asFortran
)
33 : out_
{out
}, indentationAmount_
{indentationAmount
}, encoding_
{encoding
},
34 capitalizeKeywords_
{capitalize
}, backslashEscapes_
{backslashEscapes
},
35 preStatement_
{preStatement
}, asFortran_
{asFortran
} {}
37 // In nearly all cases, this code avoids defining Boolean-valued Pre()
38 // callbacks for the parse tree walking framework in favor of two void
39 // functions, Before() and Unparse(), which imply true and false return
40 // values for Pre() respectively.
41 template <typename T
> void Before(const T
&) {}
42 template <typename T
> double Unparse(const T
&); // not void, never used
44 template <typename T
> bool Pre(const T
&x
) {
45 if constexpr (std::is_void_v
<decltype(Unparse(x
))>) {
46 // There is a local definition of Unparse() for this type. It
47 // overrides the parse tree walker's default Walk() over the descendents.
51 return false; // Walk() does not visit descendents
52 } else if constexpr (HasTypedExpr
<T
>::value
) {
53 // Format the expression representation from semantics
54 if (asFortran_
&& x
.typedExpr
) {
55 asFortran_
->expr(out_
, *x
.typedExpr
);
62 return true; // there's no Unparse() defined here, Walk() the descendents
65 template <typename T
> void Post(const T
&) {}
67 // Emit simple types as-is.
68 void Unparse(const std::string
&x
) { Put(x
); }
69 void Unparse(int x
) { Put(std::to_string(x
)); }
70 void Unparse(unsigned int x
) { Put(std::to_string(x
)); }
71 void Unparse(long x
) { Put(std::to_string(x
)); }
72 void Unparse(unsigned long x
) { Put(std::to_string(x
)); }
73 void Unparse(long long x
) { Put(std::to_string(x
)); }
74 void Unparse(unsigned long long x
) { Put(std::to_string(x
)); }
75 void Unparse(char x
) { Put(x
); }
77 // Statement labels and ends of lines
78 template <typename T
> void Before(const Statement
<T
> &x
) {
80 (*preStatement_
)(x
.source
, out_
, indent_
);
84 template <typename T
> void Post(const Statement
<T
> &) { Put('\n'); }
86 // The special-case formatting functions for these productions are
87 // ordered to correspond roughly to their order of appearance in
88 // the Fortran 2018 standard (and parse-tree.h).
90 void Unparse(const Program
&x
) { // R501
91 Walk("", x
.v
, "\n"); // put blank lines between ProgramUnits
94 void Unparse(const Name
&x
) { // R603
97 void Unparse(const DefinedOperator::IntrinsicOperator
&x
) { // R608
99 case DefinedOperator::IntrinsicOperator::Power
:
102 case DefinedOperator::IntrinsicOperator::Multiply
:
105 case DefinedOperator::IntrinsicOperator::Divide
:
108 case DefinedOperator::IntrinsicOperator::Add
:
111 case DefinedOperator::IntrinsicOperator::Subtract
:
114 case DefinedOperator::IntrinsicOperator::Concat
:
117 case DefinedOperator::IntrinsicOperator::LT
:
120 case DefinedOperator::IntrinsicOperator::LE
:
123 case DefinedOperator::IntrinsicOperator::EQ
:
126 case DefinedOperator::IntrinsicOperator::NE
:
129 case DefinedOperator::IntrinsicOperator::GE
:
132 case DefinedOperator::IntrinsicOperator::GT
:
136 Put('.'), Word(DefinedOperator::EnumToString(x
)), Put('.');
139 void Post(const Star
&) { Put('*'); } // R701 &c.
140 void Post(const TypeParamValue::Deferred
&) { Put(':'); } // R701
141 void Unparse(const DeclarationTypeSpec::Type
&x
) { // R703
142 Word("TYPE("), Walk(x
.derived
), Put(')');
144 void Unparse(const DeclarationTypeSpec::Class
&x
) {
145 Word("CLASS("), Walk(x
.derived
), Put(')');
147 void Post(const DeclarationTypeSpec::ClassStar
&) { Word("CLASS(*)"); }
148 void Post(const DeclarationTypeSpec::TypeStar
&) { Word("TYPE(*)"); }
149 void Unparse(const DeclarationTypeSpec::Record
&x
) {
150 Word("RECORD/"), Walk(x
.v
), Put('/');
152 void Before(const IntrinsicTypeSpec::Real
&) { // R704
155 void Before(const IntrinsicTypeSpec::Complex
&) { Word("COMPLEX"); }
156 void Post(const IntrinsicTypeSpec::DoublePrecision
&) {
157 Word("DOUBLE PRECISION");
159 void Before(const IntrinsicTypeSpec::Character
&) { Word("CHARACTER"); }
160 void Before(const IntrinsicTypeSpec::Logical
&) { Word("LOGICAL"); }
161 void Post(const IntrinsicTypeSpec::DoubleComplex
&) {
162 Word("DOUBLE COMPLEX");
164 void Before(const UnsignedTypeSpec
&) { Word("UNSIGNED"); }
165 void Before(const IntrinsicVectorTypeSpec
&) { Word("VECTOR("); }
166 void Post(const IntrinsicVectorTypeSpec
&) { Put(')'); }
167 void Post(const VectorTypeSpec::PairVectorTypeSpec
&) {
168 Word("__VECTOR_PAIR");
170 void Post(const VectorTypeSpec::QuadVectorTypeSpec
&) {
171 Word("__VECTOR_QUAD");
173 void Before(const IntegerTypeSpec
&) { // R705
176 void Unparse(const KindSelector
&x
) { // R706
179 [&](const ScalarIntConstantExpr
&y
) {
180 Put('('), Word("KIND="), Walk(y
), Put(')');
182 [&](const KindSelector::StarSize
&y
) { Put('*'), Walk(y
.v
); },
186 void Unparse(const SignedIntLiteralConstant
&x
) { // R707
187 Put(std::get
<CharBlock
>(x
.t
).ToString());
188 Walk("_", std::get
<std::optional
<KindParam
>>(x
.t
));
190 void Unparse(const IntLiteralConstant
&x
) { // R708
191 Put(std::get
<CharBlock
>(x
.t
).ToString());
192 Walk("_", std::get
<std::optional
<KindParam
>>(x
.t
));
194 void Unparse(const Sign
&x
) { // R712
195 Put(x
== Sign::Negative
? '-' : '+');
197 void Unparse(const RealLiteralConstant
&x
) { // R714, R715
198 Put(x
.real
.source
.ToString()), Walk("_", x
.kind
);
200 void Unparse(const ComplexLiteralConstant
&x
) { // R718 - R720
201 Put('('), Walk(x
.t
, ","), Put(')');
203 void Unparse(const CharSelector::LengthAndKind
&x
) { // R721
204 Put('('), Word("KIND="), Walk(x
.kind
);
205 Walk(", LEN=", x
.length
), Put(')');
207 void Unparse(const LengthSelector
&x
) { // R722
208 common::visit(common::visitors
{
209 [&](const TypeParamValue
&y
) {
210 Put('('), Word("LEN="), Walk(y
), Put(')');
212 [&](const CharLength
&y
) { Put('*'), Walk(y
); },
216 void Unparse(const CharLength
&x
) { // R723
219 [&](const TypeParamValue
&y
) { Put('('), Walk(y
), Put(')'); },
220 [&](const std::int64_t &y
) { Walk(y
); },
224 void Unparse(const CharLiteralConstant
&x
) { // R724
225 const auto &str
{std::get
<std::string
>(x
.t
)};
226 if (const auto &k
{std::get
<std::optional
<KindParam
>>(x
.t
)}) {
231 void Unparse(const HollerithLiteralConstant
&x
) {
232 auto ucs
{DecodeString
<std::u32string
, Encoding::UTF_8
>(x
.v
, false)};
235 for (char32_t ch
: ucs
) {
236 EncodedCharacter encoded
{EncodeCharacter(encoding_
, ch
)};
237 for (int j
{0}; j
< encoded
.bytes
; ++j
) {
238 Put(encoded
.buffer
[j
]);
242 void Unparse(const LogicalLiteralConstant
&x
) { // R725
243 Put(std::get
<bool>(x
.t
) ? ".TRUE." : ".FALSE.");
244 Walk("_", std::get
<std::optional
<KindParam
>>(x
.t
));
246 void Unparse(const DerivedTypeStmt
&x
) { // R727
247 Word("TYPE"), Walk(", ", std::get
<std::list
<TypeAttrSpec
>>(x
.t
), ", ");
248 Put(" :: "), Walk(std::get
<Name
>(x
.t
));
249 Walk("(", std::get
<std::list
<Name
>>(x
.t
), ", ", ")");
252 void Unparse(const Abstract
&) { // R728, &c.
255 void Post(const TypeAttrSpec::BindC
&) { Word("BIND(C)"); }
256 void Unparse(const TypeAttrSpec::Extends
&x
) {
257 Word("EXTENDS("), Walk(x
.v
), Put(')');
259 void Unparse(const EndTypeStmt
&x
) { // R730
260 Outdent(), Word("END TYPE"), Walk(" ", x
.v
);
262 void Unparse(const SequenceStmt
&) { // R731
265 void Unparse(const TypeParamDefStmt
&x
) { // R732
266 Walk(std::get
<IntegerTypeSpec
>(x
.t
));
267 Put(", "), Walk(std::get
<common::TypeParamAttr
>(x
.t
));
268 Put(" :: "), Walk(std::get
<std::list
<TypeParamDecl
>>(x
.t
), ", ");
270 void Unparse(const TypeParamDecl
&x
) { // R733
271 Walk(std::get
<Name
>(x
.t
));
272 Walk("=", std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
274 void Unparse(const DataComponentDefStmt
&x
) { // R737
275 const auto &dts
{std::get
<DeclarationTypeSpec
>(x
.t
)};
276 const auto &attrs
{std::get
<std::list
<ComponentAttrSpec
>>(x
.t
)};
277 const auto &decls
{std::get
<std::list
<ComponentOrFill
>>(x
.t
)};
278 Walk(dts
), Walk(", ", attrs
, ", ");
279 if (!attrs
.empty() ||
280 (!std::holds_alternative
<DeclarationTypeSpec::Record
>(dts
.u
) &&
282 decls
.begin(), decls
.end(), [](const ComponentOrFill
&c
) {
283 return common::visit(
285 [](const ComponentDecl
&d
) {
287 std::get
<std::optional
<Initialization
>>(d
.t
)};
289 std::holds_alternative
<std::list
<
290 common::Indirection
<DataStmtValue
>>>(
293 [](const FillDecl
&) { return false; },
299 Put(' '), Walk(decls
, ", ");
301 void Unparse(const Allocatable
&) { // R738
304 void Unparse(const Pointer
&) { Word("POINTER"); }
305 void Unparse(const Contiguous
&) { Word("CONTIGUOUS"); }
306 void Before(const ComponentAttrSpec
&x
) {
307 common::visit(common::visitors
{
308 [&](const CoarraySpec
&) { Word("CODIMENSION["); },
309 [&](const ComponentArraySpec
&) { Word("DIMENSION("); },
314 void Post(const ComponentAttrSpec
&x
) {
315 common::visit(common::visitors
{
316 [&](const CoarraySpec
&) { Put(']'); },
317 [&](const ComponentArraySpec
&) { Put(')'); },
322 void Unparse(const ComponentDecl
&x
) { // R739
323 Walk(std::get
<ObjectName
>(x
.t
));
324 Walk("(", std::get
<std::optional
<ComponentArraySpec
>>(x
.t
), ")");
325 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
326 Walk("*", std::get
<std::optional
<CharLength
>>(x
.t
));
327 Walk(std::get
<std::optional
<Initialization
>>(x
.t
));
329 void Unparse(const FillDecl
&x
) { // DEC extension
331 Walk("(", std::get
<std::optional
<ComponentArraySpec
>>(x
.t
), ")");
332 Walk("*", std::get
<std::optional
<CharLength
>>(x
.t
));
334 void Unparse(const ComponentArraySpec
&x
) { // R740
337 [&](const std::list
<ExplicitShapeSpec
> &y
) { Walk(y
, ","); },
338 [&](const DeferredShapeSpecList
&y
) { Walk(y
); },
342 void Unparse(const ProcComponentDefStmt
&x
) { // R741
344 Walk(std::get
<std::optional
<ProcInterface
>>(x
.t
)), Put(')');
345 Walk(", ", std::get
<std::list
<ProcComponentAttrSpec
>>(x
.t
), ", ");
346 Put(" :: "), Walk(std::get
<std::list
<ProcDecl
>>(x
.t
), ", ");
348 void Unparse(const NoPass
&) { // R742
351 void Unparse(const Pass
&x
) { Word("PASS"), Walk("(", x
.v
, ")"); }
352 void Unparse(const Initialization
&x
) { // R743 & R805
355 [&](const ConstantExpr
&y
) { Put(" = "), Walk(y
); },
356 [&](const NullInit
&y
) { Put(" => "), Walk(y
); },
357 [&](const InitialDataTarget
&y
) { Put(" => "), Walk(y
); },
358 [&](const std::list
<common::Indirection
<DataStmtValue
>> &y
) {
359 Walk("/", y
, ", ", "/");
364 void Unparse(const PrivateStmt
&) { // R745
367 void Unparse(const TypeBoundProcedureStmt::WithoutInterface
&x
) { // R749
368 Word("PROCEDURE"), Walk(", ", x
.attributes
, ", ");
369 Put(" :: "), Walk(x
.declarations
, ", ");
371 void Unparse(const TypeBoundProcedureStmt::WithInterface
&x
) {
372 Word("PROCEDURE("), Walk(x
.interfaceName
), Put("), ");
374 Put(" :: "), Walk(x
.bindingNames
, ", ");
376 void Unparse(const TypeBoundProcDecl
&x
) { // R750
377 Walk(std::get
<Name
>(x
.t
));
378 Walk(" => ", std::get
<std::optional
<Name
>>(x
.t
));
380 void Unparse(const TypeBoundGenericStmt
&x
) { // R751
381 Word("GENERIC"), Walk(", ", std::get
<std::optional
<AccessSpec
>>(x
.t
));
382 Put(" :: "), Walk(std::get
<common::Indirection
<GenericSpec
>>(x
.t
));
383 Put(" => "), Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
385 void Post(const BindAttr::Deferred
&) { Word("DEFERRED"); } // R752
386 void Post(const BindAttr::Non_Overridable
&) { Word("NON_OVERRIDABLE"); }
387 void Unparse(const FinalProcedureStmt
&x
) { // R753
388 Word("FINAL :: "), Walk(x
.v
, ", ");
390 void Unparse(const DerivedTypeSpec
&x
) { // R754
391 Walk(std::get
<Name
>(x
.t
));
392 Walk("(", std::get
<std::list
<TypeParamSpec
>>(x
.t
), ",", ")");
394 void Unparse(const TypeParamSpec
&x
) { // R755
395 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
396 Walk(std::get
<TypeParamValue
>(x
.t
));
398 void Unparse(const StructureConstructor
&x
) { // R756
399 Walk(std::get
<DerivedTypeSpec
>(x
.t
));
400 Put('('), Walk(std::get
<std::list
<ComponentSpec
>>(x
.t
), ", "), Put(')');
402 void Unparse(const ComponentSpec
&x
) { // R757
403 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
404 Walk(std::get
<ComponentDataSource
>(x
.t
));
406 void Unparse(const EnumDefStmt
&) { // R760
407 Word("ENUM, BIND(C)"), Indent();
409 void Unparse(const EnumeratorDefStmt
&x
) { // R761
410 Word("ENUMERATOR :: "), Walk(x
.v
, ", ");
412 void Unparse(const Enumerator
&x
) { // R762
413 Walk(std::get
<NamedConstant
>(x
.t
));
414 Walk(" = ", std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
416 void Post(const EndEnumStmt
&) { // R763
417 Outdent(), Word("END ENUM");
419 void Unparse(const BOZLiteralConstant
&x
) { // R764 - R767
422 void Unparse(const AcValue::Triplet
&x
) { // R773
423 Walk(std::get
<0>(x
.t
)), Put(':'), Walk(std::get
<1>(x
.t
));
424 Walk(":", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
426 void Unparse(const ArrayConstructor
&x
) { // R769
427 Put('['), Walk(x
.v
), Put(']');
429 void Unparse(const AcSpec
&x
) { // R770
430 Walk(x
.type
, "::"), Walk(x
.values
, ", ");
432 template <typename A
, typename B
> void Unparse(const LoopBounds
<A
, B
> &x
) {
433 Walk(x
.name
), Put('='), Walk(x
.lower
), Put(','), Walk(x
.upper
);
436 void Unparse(const AcImpliedDo
&x
) { // R774
437 Put('('), Walk(std::get
<std::list
<AcValue
>>(x
.t
), ", ");
438 Put(", "), Walk(std::get
<AcImpliedDoControl
>(x
.t
)), Put(')');
440 void Unparse(const AcImpliedDoControl
&x
) { // R775
441 Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
442 Walk(std::get
<AcImpliedDoControl::Bounds
>(x
.t
));
445 void Unparse(const TypeDeclarationStmt
&x
) { // R801
446 const auto &dts
{std::get
<DeclarationTypeSpec
>(x
.t
)};
447 const auto &attrs
{std::get
<std::list
<AttrSpec
>>(x
.t
)};
448 const auto &decls
{std::get
<std::list
<EntityDecl
>>(x
.t
)};
449 Walk(dts
), Walk(", ", attrs
, ", ");
451 static const auto isInitializerOldStyle
{[](const Initialization
&i
) {
452 return std::holds_alternative
<
453 std::list
<common::Indirection
<DataStmtValue
>>>(i
.u
);
455 static const auto hasAssignmentInitializer
{[](const EntityDecl
&d
) {
456 // Does a declaration have a new-style =x initializer?
457 const auto &init
{std::get
<std::optional
<Initialization
>>(d
.t
)};
458 return init
&& !isInitializerOldStyle(*init
);
460 static const auto hasSlashDelimitedInitializer
{[](const EntityDecl
&d
) {
461 // Does a declaration have an old-style /x/ initializer?
462 const auto &init
{std::get
<std::optional
<Initialization
>>(d
.t
)};
463 return init
&& isInitializerOldStyle(*init
);
465 const auto useDoubledColons
{[&]() {
466 bool isRecord
{std::holds_alternative
<DeclarationTypeSpec::Record
>(dts
.u
)};
467 if (!attrs
.empty()) {
468 // Attributes after the type require :: before the entities.
472 if (std::any_of(decls
.begin(), decls
.end(), hasAssignmentInitializer
)) {
473 // Always use :: with new style standard initializers (=x),
474 // since the standard requires them to appear (even in free form,
475 // where mandatory spaces already disambiguate INTEGER J=666).
480 // Never put :: in a legacy extension RECORD// statement.
483 // The :: is optional for this declaration. Avoid usage that can
484 // crash the pgf90 compiler.
486 decls
.begin(), decls
.end(), hasSlashDelimitedInitializer
)) {
487 // Don't use :: when a declaration uses legacy DATA-statement-like
488 // /x/ initialization.
491 // Don't use :: with intrinsic types. Otherwise, use it.
492 return !std::holds_alternative
<IntrinsicTypeSpec
>(dts
.u
);
495 if (useDoubledColons()) {
498 Put(' '), Walk(std::get
<std::list
<EntityDecl
>>(x
.t
), ", ");
500 void Before(const AttrSpec
&x
) { // R802
501 common::visit(common::visitors
{
502 [&](const CoarraySpec
&) { Word("CODIMENSION["); },
503 [&](const ArraySpec
&) { Word("DIMENSION("); },
508 void Post(const AttrSpec
&x
) {
509 common::visit(common::visitors
{
510 [&](const CoarraySpec
&) { Put(']'); },
511 [&](const ArraySpec
&) { Put(')'); },
516 void Unparse(const EntityDecl
&x
) { // R803
517 Walk(std::get
<ObjectName
>(x
.t
));
518 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
519 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
520 Walk("*", std::get
<std::optional
<CharLength
>>(x
.t
));
521 Walk(std::get
<std::optional
<Initialization
>>(x
.t
));
523 void Unparse(const NullInit
&) { // R806
526 void Unparse(const LanguageBindingSpec
&x
) { // R808 & R1528
529 ", NAME=", std::get
<std::optional
<ScalarDefaultCharConstantExpr
>>(x
.t
));
530 if (std::get
<bool>(x
.t
)) {
535 void Unparse(const CoarraySpec
&x
) { // R809
536 common::visit(common::visitors
{
537 [&](const DeferredCoshapeSpecList
&y
) { Walk(y
); },
538 [&](const ExplicitCoshapeSpec
&y
) { Walk(y
); },
542 void Unparse(const DeferredCoshapeSpecList
&x
) { // R810
543 for (auto j
{x
.v
}; j
> 0; --j
) {
550 void Unparse(const ExplicitCoshapeSpec
&x
) { // R811
551 Walk(std::get
<std::list
<ExplicitShapeSpec
>>(x
.t
), ",", ",");
552 Walk(std::get
<std::optional
<SpecificationExpr
>>(x
.t
), ":"), Put('*');
554 void Unparse(const ExplicitShapeSpec
&x
) { // R812 - R813 & R816 - R818
555 Walk(std::get
<std::optional
<SpecificationExpr
>>(x
.t
), ":");
556 Walk(std::get
<SpecificationExpr
>(x
.t
));
558 void Unparse(const ArraySpec
&x
) { // R815
561 [&](const std::list
<ExplicitShapeSpec
> &y
) { Walk(y
, ","); },
562 [&](const std::list
<AssumedShapeSpec
> &y
) { Walk(y
, ","); },
563 [&](const DeferredShapeSpecList
&y
) { Walk(y
); },
564 [&](const AssumedSizeSpec
&y
) { Walk(y
); },
565 [&](const ImpliedShapeSpec
&y
) { Walk(y
); },
566 [&](const AssumedRankSpec
&y
) { Walk(y
); },
570 void Post(const AssumedShapeSpec
&) { Put(':'); } // R819
571 void Unparse(const DeferredShapeSpecList
&x
) { // R820
572 for (auto j
{x
.v
}; j
> 0; --j
) {
579 void Unparse(const AssumedImpliedSpec
&x
) { // R821
583 void Unparse(const AssumedSizeSpec
&x
) { // R822
584 Walk(std::get
<std::list
<ExplicitShapeSpec
>>(x
.t
), ",", ",");
585 Walk(std::get
<AssumedImpliedSpec
>(x
.t
));
587 void Unparse(const ImpliedShapeSpec
&x
) { // R823
590 void Post(const AssumedRankSpec
&) { Put(".."); } // R825
591 void Post(const Asynchronous
&) { Word("ASYNCHRONOUS"); }
592 void Post(const External
&) { Word("EXTERNAL"); }
593 void Post(const Intrinsic
&) { Word("INTRINSIC"); }
594 void Post(const Optional
&) { Word("OPTIONAL"); }
595 void Post(const Parameter
&) { Word("PARAMETER"); }
596 void Post(const Protected
&) { Word("PROTECTED"); }
597 void Post(const Save
&) { Word("SAVE"); }
598 void Post(const Target
&) { Word("TARGET"); }
599 void Post(const Value
&) { Word("VALUE"); }
600 void Post(const Volatile
&) { Word("VOLATILE"); }
601 void Unparse(const IntentSpec
&x
) { // R826
602 Word("INTENT("), Walk(x
.v
), Put(")");
604 void Unparse(const AccessStmt
&x
) { // R827
605 Walk(std::get
<AccessSpec
>(x
.t
));
606 Walk(" :: ", std::get
<std::list
<AccessId
>>(x
.t
), ", ");
608 void Unparse(const AllocatableStmt
&x
) { // R829
609 Word("ALLOCATABLE :: "), Walk(x
.v
, ", ");
611 void Unparse(const ObjectDecl
&x
) { // R830 & R860
612 Walk(std::get
<ObjectName
>(x
.t
));
613 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
614 Walk("[", std::get
<std::optional
<CoarraySpec
>>(x
.t
), "]");
616 void Unparse(const AsynchronousStmt
&x
) { // R831
617 Word("ASYNCHRONOUS :: "), Walk(x
.v
, ", ");
619 void Unparse(const BindStmt
&x
) { // R832
622 void Unparse(const BindEntity
&x
) { // R833
623 bool isCommon
{std::get
<BindEntity::Kind
>(x
.t
) == BindEntity::Kind::Common
};
624 const char *slash
{isCommon
? "/" : ""};
625 Put(slash
), Walk(std::get
<Name
>(x
.t
)), Put(slash
);
627 void Unparse(const CodimensionStmt
&x
) { // R834
628 Word("CODIMENSION :: "), Walk(x
.v
, ", ");
630 void Unparse(const CodimensionDecl
&x
) { // R835
631 Walk(std::get
<Name
>(x
.t
));
632 Put('['), Walk(std::get
<CoarraySpec
>(x
.t
)), Put(']');
634 void Unparse(const ContiguousStmt
&x
) { // R836
635 Word("CONTIGUOUS :: "), Walk(x
.v
, ", ");
637 void Unparse(const DataStmt
&x
) { // R837
638 Word("DATA "), Walk(x
.v
, ", ");
640 void Unparse(const DataStmtSet
&x
) { // R838
641 Walk(std::get
<std::list
<DataStmtObject
>>(x
.t
), ", ");
642 Put('/'), Walk(std::get
<std::list
<DataStmtValue
>>(x
.t
), ", "), Put('/');
644 void Unparse(const DataImpliedDo
&x
) { // R840, R842
645 Put('('), Walk(std::get
<std::list
<DataIDoObject
>>(x
.t
), ", "), Put(',');
646 Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
647 Walk(std::get
<DataImpliedDo::Bounds
>(x
.t
)), Put(')');
649 void Unparse(const DataStmtValue
&x
) { // R843
650 Walk(std::get
<std::optional
<DataStmtRepeat
>>(x
.t
), "*");
651 Walk(std::get
<DataStmtConstant
>(x
.t
));
653 void Unparse(const DimensionStmt
&x
) { // R848
654 Word("DIMENSION :: "), Walk(x
.v
, ", ");
656 void Unparse(const DimensionStmt::Declaration
&x
) {
657 Walk(std::get
<Name
>(x
.t
));
658 Put('('), Walk(std::get
<ArraySpec
>(x
.t
)), Put(')');
660 void Unparse(const IntentStmt
&x
) { // R849
663 void Unparse(const OptionalStmt
&x
) { // R850
664 Word("OPTIONAL :: "), Walk(x
.v
, ", ");
666 void Unparse(const ParameterStmt
&x
) { // R851
667 Word("PARAMETER("), Walk(x
.v
, ", "), Put(')');
669 void Unparse(const NamedConstantDef
&x
) { // R852
672 void Unparse(const PointerStmt
&x
) { // R853
673 Word("POINTER :: "), Walk(x
.v
, ", ");
675 void Unparse(const PointerDecl
&x
) { // R854
676 Walk(std::get
<Name
>(x
.t
));
677 Walk("(", std::get
<std::optional
<DeferredShapeSpecList
>>(x
.t
), ")");
679 void Unparse(const ProtectedStmt
&x
) { // R855
680 Word("PROTECTED :: "), Walk(x
.v
, ", ");
682 void Unparse(const SaveStmt
&x
) { // R856
683 Word("SAVE"), Walk(" :: ", x
.v
, ", ");
685 void Unparse(const SavedEntity
&x
) { // R857, R858
687 std::get
<SavedEntity::Kind
>(x
.t
) == SavedEntity::Kind::Common
};
688 const char *slash
{isCommon
? "/" : ""};
689 Put(slash
), Walk(std::get
<Name
>(x
.t
)), Put(slash
);
691 void Unparse(const TargetStmt
&x
) { // R859
692 Word("TARGET :: "), Walk(x
.v
, ", ");
694 void Unparse(const ValueStmt
&x
) { // R861
695 Word("VALUE :: "), Walk(x
.v
, ", ");
697 void Unparse(const VolatileStmt
&x
) { // R862
698 Word("VOLATILE :: "), Walk(x
.v
, ", ");
700 void Unparse(const ImplicitStmt
&x
) { // R863
704 [&](const std::list
<ImplicitSpec
> &y
) { Walk(y
, ", "); },
705 [&](const std::list
<ImplicitStmt::ImplicitNoneNameSpec
> &y
) {
706 Word("NONE"), Walk(" (", y
, ", ", ")");
711 void Unparse(const ImplicitSpec
&x
) { // R864
712 Walk(std::get
<DeclarationTypeSpec
>(x
.t
));
713 Put('('), Walk(std::get
<std::list
<LetterSpec
>>(x
.t
), ", "), Put(')');
715 void Unparse(const LetterSpec
&x
) { // R865
716 Put(*std::get
<const char *>(x
.t
));
717 auto second
{std::get
<std::optional
<const char *>>(x
.t
)};
719 Put('-'), Put(**second
);
722 void Unparse(const ImportStmt
&x
) { // R867
725 case common::ImportKind::Default
:
726 Walk(" :: ", x
.names
, ", ");
728 case common::ImportKind::Only
:
729 Put(", "), Word("ONLY: ");
732 case common::ImportKind::None
:
735 case common::ImportKind::All
:
740 void Unparse(const NamelistStmt
&x
) { // R868
741 Word("NAMELIST"), Walk(x
.v
, ", ");
743 void Unparse(const NamelistStmt::Group
&x
) {
744 Put('/'), Walk(std::get
<Name
>(x
.t
)), Put('/');
745 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
747 void Unparse(const EquivalenceStmt
&x
) { // R870, R871
749 const char *separator
{" "};
750 for (const std::list
<EquivalenceObject
> &y
: x
.v
) {
751 Put(separator
), Put('('), Walk(y
), Put(')');
755 void Unparse(const CommonStmt
&x
) { // R873
759 void Unparse(const CommonBlockObject
&x
) { // R874
760 Walk(std::get
<Name
>(x
.t
));
761 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")");
763 void Unparse(const CommonStmt::Block
&x
) {
764 Word("/"), Walk(std::get
<std::optional
<Name
>>(x
.t
)), Word("/");
765 Walk(std::get
<std::list
<CommonBlockObject
>>(x
.t
));
768 void Unparse(const Substring
&x
) { // R908, R909
769 Walk(std::get
<DataRef
>(x
.t
));
770 Put('('), Walk(std::get
<SubstringRange
>(x
.t
)), Put(')');
772 void Unparse(const CharLiteralConstantSubstring
&x
) {
773 Walk(std::get
<CharLiteralConstant
>(x
.t
));
774 Put('('), Walk(std::get
<SubstringRange
>(x
.t
)), Put(')');
776 void Unparse(const SubstringInquiry
&x
) {
778 Put(x
.source
.end()[-1] == 'n' ? "%LEN" : "%KIND");
780 void Unparse(const SubstringRange
&x
) { // R910
783 void Unparse(const PartRef
&x
) { // R912
785 Walk("(", x
.subscripts
, ",", ")");
786 Walk(x
.imageSelector
);
788 void Unparse(const StructureComponent
&x
) { // R913
790 if (structureComponents_
.find(x
.component
.source
) !=
791 structureComponents_
.end()) {
798 void Unparse(const ArrayElement
&x
) { // R917
800 Put('('), Walk(x
.subscripts
, ","), Put(')');
802 void Unparse(const SubscriptTriplet
&x
) { // R921
803 Walk(std::get
<0>(x
.t
)), Put(':'), Walk(std::get
<1>(x
.t
));
804 Walk(":", std::get
<2>(x
.t
));
806 void Unparse(const ImageSelector
&x
) { // R924
807 Put('['), Walk(std::get
<std::list
<Cosubscript
>>(x
.t
), ",");
808 Walk(",", std::get
<std::list
<ImageSelectorSpec
>>(x
.t
), ","), Put(']');
810 void Before(const ImageSelectorSpec::Stat
&) { // R926
813 void Before(const ImageSelectorSpec::Team_Number
&) { Word("TEAM_NUMBER="); }
814 void Before(const ImageSelectorSpec
&x
) {
815 if (std::holds_alternative
<TeamValue
>(x
.u
)) {
819 void Unparse(const AllocateStmt
&x
) { // R927
821 Walk(std::get
<std::optional
<TypeSpec
>>(x
.t
), "::");
822 Walk(std::get
<std::list
<Allocation
>>(x
.t
), ", ");
823 Walk(", ", std::get
<std::list
<AllocOpt
>>(x
.t
), ", "), Put(')');
825 void Before(const AllocOpt
&x
) { // R928, R931
826 common::visit(common::visitors
{
827 [&](const AllocOpt::Mold
&) { Word("MOLD="); },
828 [&](const AllocOpt::Source
&) { Word("SOURCE="); },
829 [&](const AllocOpt::Stream
&) { Word("STREAM="); },
830 [&](const AllocOpt::Pinned
&) { Word("PINNED="); },
831 [](const StatOrErrmsg
&) {},
835 void Unparse(const Allocation
&x
) { // R932
836 Walk(std::get
<AllocateObject
>(x
.t
));
837 Walk("(", std::get
<std::list
<AllocateShapeSpec
>>(x
.t
), ",", ")");
838 Walk("[", std::get
<std::optional
<AllocateCoarraySpec
>>(x
.t
), "]");
840 void Unparse(const AllocateShapeSpec
&x
) { // R934 & R938
841 Walk(std::get
<std::optional
<BoundExpr
>>(x
.t
), ":");
842 Walk(std::get
<BoundExpr
>(x
.t
));
844 void Unparse(const AllocateCoarraySpec
&x
) { // R937
845 Walk(std::get
<std::list
<AllocateCoshapeSpec
>>(x
.t
), ",", ",");
846 Walk(std::get
<std::optional
<BoundExpr
>>(x
.t
), ":"), Put('*');
848 void Unparse(const NullifyStmt
&x
) { // R939
849 Word("NULLIFY("), Walk(x
.v
, ", "), Put(')');
851 void Unparse(const DeallocateStmt
&x
) { // R941
853 Walk(std::get
<std::list
<AllocateObject
>>(x
.t
), ", ");
854 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
856 void Before(const StatOrErrmsg
&x
) { // R942 & R1165
857 common::visit(common::visitors
{
858 [&](const StatVariable
&) { Word("STAT="); },
859 [&](const MsgVariable
&) { Word("ERRMSG="); },
865 void Unparse(const Expr::Parentheses
&x
) { Put('('), Walk(x
.v
), Put(')'); }
866 void Before(const Expr::UnaryPlus
&) { Put("+"); }
867 void Before(const Expr::Negate
&) { Put("-"); }
868 void Before(const Expr::NOT
&) { Word(".NOT."); }
869 void Unparse(const Expr::PercentLoc
&x
) {
870 Word("%LOC("), Walk(x
.v
), Put(')');
872 void Unparse(const Expr::Power
&x
) { Walk(x
.t
, "**"); }
873 void Unparse(const Expr::Multiply
&x
) { Walk(x
.t
, "*"); }
874 void Unparse(const Expr::Divide
&x
) { Walk(x
.t
, "/"); }
875 void Unparse(const Expr::Add
&x
) { Walk(x
.t
, "+"); }
876 void Unparse(const Expr::Subtract
&x
) { Walk(x
.t
, "-"); }
877 void Unparse(const Expr::Concat
&x
) { Walk(x
.t
, "//"); }
878 void Unparse(const Expr::LT
&x
) { Walk(x
.t
, "<"); }
879 void Unparse(const Expr::LE
&x
) { Walk(x
.t
, "<="); }
880 void Unparse(const Expr::EQ
&x
) { Walk(x
.t
, "=="); }
881 void Unparse(const Expr::NE
&x
) { Walk(x
.t
, "/="); }
882 void Unparse(const Expr::GE
&x
) { Walk(x
.t
, ">="); }
883 void Unparse(const Expr::GT
&x
) { Walk(x
.t
, ">"); }
884 void Unparse(const Expr::AND
&x
) { Walk(x
.t
, ".AND."); }
885 void Unparse(const Expr::OR
&x
) { Walk(x
.t
, ".OR."); }
886 void Unparse(const Expr::EQV
&x
) { Walk(x
.t
, ".EQV."); }
887 void Unparse(const Expr::NEQV
&x
) { Walk(x
.t
, ".NEQV."); }
888 void Unparse(const Expr::ComplexConstructor
&x
) {
889 Put('('), Walk(x
.t
, ","), Put(')');
891 void Unparse(const Expr::DefinedBinary
&x
) {
892 Walk(std::get
<1>(x
.t
)); // left
893 Walk(std::get
<DefinedOpName
>(x
.t
));
894 Walk(std::get
<2>(x
.t
)); // right
896 void Unparse(const DefinedOpName
&x
) { // R1003, R1023, R1414, & R1415
899 void Unparse(const AssignmentStmt
&x
) { // R1032
900 if (asFortran_
&& x
.typedAssignment
.get()) {
902 asFortran_
->assignment(out_
, *x
.typedAssignment
);
908 void Unparse(const PointerAssignmentStmt
&x
) { // R1033, R1034, R1038
909 if (asFortran_
&& x
.typedAssignment
.get()) {
911 asFortran_
->assignment(out_
, *x
.typedAssignment
);
914 Walk(std::get
<DataRef
>(x
.t
));
917 [&](const std::list
<BoundsRemapping
> &y
) {
918 Put('('), Walk(y
), Put(')');
920 [&](const std::list
<BoundsSpec
> &y
) { Walk("(", y
, ", ", ")"); },
922 std::get
<PointerAssignmentStmt::Bounds
>(x
.t
).u
);
923 Put(" => "), Walk(std::get
<Expr
>(x
.t
));
926 void Post(const BoundsSpec
&) { // R1035
929 void Unparse(const BoundsRemapping
&x
) { // R1036
932 void Unparse(const WhereStmt
&x
) { // R1041, R1045, R1046
933 Word("WHERE ("), Walk(x
.t
, ") ");
935 void Unparse(const WhereConstructStmt
&x
) { // R1043
936 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
937 Word("WHERE ("), Walk(std::get
<LogicalExpr
>(x
.t
)), Put(')');
940 void Unparse(const MaskedElsewhereStmt
&x
) { // R1047
942 Word("ELSEWHERE ("), Walk(std::get
<LogicalExpr
>(x
.t
)), Put(')');
943 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
));
946 void Unparse(const ElsewhereStmt
&x
) { // R1048
947 Outdent(), Word("ELSEWHERE"), Walk(" ", x
.v
), Indent();
949 void Unparse(const EndWhereStmt
&x
) { // R1049
950 Outdent(), Word("END WHERE"), Walk(" ", x
.v
);
952 void Unparse(const ForallConstructStmt
&x
) { // R1051
953 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
954 Word("FORALL"), Walk(std::get
<common::Indirection
<ConcurrentHeader
>>(x
.t
));
957 void Unparse(const EndForallStmt
&x
) { // R1054
958 Outdent(), Word("END FORALL"), Walk(" ", x
.v
);
960 void Before(const ForallStmt
&) { // R1055
964 void Unparse(const AssociateStmt
&x
) { // R1103
965 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
967 Walk(std::get
<std::list
<Association
>>(x
.t
), ", "), Put(')'), Indent();
969 void Unparse(const Association
&x
) { // R1104
972 void Unparse(const EndAssociateStmt
&x
) { // R1106
973 Outdent(), Word("END ASSOCIATE"), Walk(" ", x
.v
);
975 void Unparse(const BlockStmt
&x
) { // R1108
976 Walk(x
.v
, ": "), Word("BLOCK"), Indent();
978 void Unparse(const EndBlockStmt
&x
) { // R1110
979 Outdent(), Word("END BLOCK"), Walk(" ", x
.v
);
981 void Unparse(const ChangeTeamStmt
&x
) { // R1112
982 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
983 Word("CHANGE TEAM ("), Walk(std::get
<TeamValue
>(x
.t
));
984 Walk(", ", std::get
<std::list
<CoarrayAssociation
>>(x
.t
), ", ");
985 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
988 void Unparse(const CoarrayAssociation
&x
) { // R1113
991 void Unparse(const EndChangeTeamStmt
&x
) { // R1114
992 Outdent(), Word("END TEAM (");
993 Walk(std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
994 Put(')'), Walk(" ", std::get
<std::optional
<Name
>>(x
.t
));
996 void Unparse(const CriticalStmt
&x
) { // R1117
997 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
998 Word("CRITICAL ("), Walk(std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
1001 void Unparse(const EndCriticalStmt
&x
) { // R1118
1002 Outdent(), Word("END CRITICAL"), Walk(" ", x
.v
);
1004 void Unparse(const DoConstruct
&x
) { // R1119, R1120
1005 Walk(std::get
<Statement
<NonLabelDoStmt
>>(x
.t
));
1006 Indent(), Walk(std::get
<Block
>(x
.t
), ""), Outdent();
1007 Walk(std::get
<Statement
<EndDoStmt
>>(x
.t
));
1009 void Unparse(const LabelDoStmt
&x
) { // R1121
1010 Word("DO "), Walk(std::get
<Label
>(x
.t
));
1011 Walk(" ", std::get
<std::optional
<LoopControl
>>(x
.t
));
1013 void Unparse(const NonLabelDoStmt
&x
) { // R1122
1014 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1016 Walk(std::get
<std::optional
<Label
>>(x
.t
), " ");
1017 Walk(std::get
<std::optional
<LoopControl
>>(x
.t
));
1019 void Unparse(const LoopControl
&x
) { // R1123
1020 common::visit(common::visitors
{
1021 [&](const ScalarLogicalExpr
&y
) {
1022 Word("WHILE ("), Walk(y
), Put(')');
1024 [&](const auto &y
) { Walk(y
); },
1028 void Unparse(const ConcurrentHeader
&x
) { // R1125
1029 Put('('), Walk(std::get
<std::optional
<IntegerTypeSpec
>>(x
.t
), "::");
1030 Walk(std::get
<std::list
<ConcurrentControl
>>(x
.t
), ", ");
1031 Walk(", ", std::get
<std::optional
<ScalarLogicalExpr
>>(x
.t
)), Put(')');
1033 void Unparse(const ConcurrentControl
&x
) { // R1126 - R1128
1034 Walk(std::get
<Name
>(x
.t
)), Put('='), Walk(std::get
<1>(x
.t
));
1035 Put(':'), Walk(std::get
<2>(x
.t
));
1036 Walk(":", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
1038 void Before(const LoopControl::Concurrent
&) { // R1129
1041 void Unparse(const LocalitySpec::Local
&x
) {
1042 Word("LOCAL("), Walk(x
.v
, ", "), Put(')');
1044 void Unparse(const LocalitySpec::LocalInit
&x
) {
1045 Word("LOCAL_INIT("), Walk(x
.v
, ", "), Put(')');
1047 void Unparse(const LocalitySpec::Reduce
&x
) {
1048 Word("REDUCE("), Walk(std::get
<parser::ReductionOperator
>(x
.t
));
1049 Walk(":", std::get
<std::list
<parser::Name
>>(x
.t
), ",", ")");
1051 void Unparse(const LocalitySpec::Shared
&x
) {
1052 Word("SHARED("), Walk(x
.v
, ", "), Put(')');
1054 void Post(const LocalitySpec::DefaultNone
&) { Word("DEFAULT(NONE)"); }
1055 void Unparse(const EndDoStmt
&x
) { // R1132
1056 Word("END DO"), Walk(" ", x
.v
);
1058 void Unparse(const CycleStmt
&x
) { // R1133
1059 Word("CYCLE"), Walk(" ", x
.v
);
1061 void Unparse(const IfThenStmt
&x
) { // R1135
1062 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1063 Word("IF ("), Walk(std::get
<ScalarLogicalExpr
>(x
.t
));
1064 Put(") "), Word("THEN"), Indent();
1066 void Unparse(const ElseIfStmt
&x
) { // R1136
1067 Outdent(), Word("ELSE IF (");
1068 Walk(std::get
<ScalarLogicalExpr
>(x
.t
)), Put(") "), Word("THEN");
1069 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1071 void Unparse(const ElseStmt
&x
) { // R1137
1072 Outdent(), Word("ELSE"), Walk(" ", x
.v
), Indent();
1074 void Unparse(const EndIfStmt
&x
) { // R1138
1075 Outdent(), Word("END IF"), Walk(" ", x
.v
);
1077 void Unparse(const IfStmt
&x
) { // R1139
1078 Word("IF ("), Walk(x
.t
, ") ");
1080 void Unparse(const SelectCaseStmt
&x
) { // R1141, R1144
1081 Walk(std::get
<std::optional
<Name
>>(x
.t
), ": ");
1082 Word("SELECT CASE (");
1083 Walk(std::get
<Scalar
<Expr
>>(x
.t
)), Put(')'), Indent();
1085 void Unparse(const CaseStmt
&x
) { // R1142
1086 Outdent(), Word("CASE "), Walk(std::get
<CaseSelector
>(x
.t
));
1087 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1089 void Unparse(const EndSelectStmt
&x
) { // R1143 & R1151 & R1155
1090 Outdent(), Word("END SELECT"), Walk(" ", x
.v
);
1092 void Unparse(const CaseSelector
&x
) { // R1145
1093 common::visit(common::visitors
{
1094 [&](const std::list
<CaseValueRange
> &y
) {
1095 Put('('), Walk(y
), Put(')');
1097 [&](const Default
&) { Word("DEFAULT"); },
1101 void Unparse(const CaseValueRange::Range
&x
) { // R1146
1102 Walk(x
.lower
), Put(':'), Walk(x
.upper
);
1104 void Unparse(const SelectRankStmt
&x
) { // R1149
1105 Walk(std::get
<0>(x
.t
), ": ");
1106 Word("SELECT RANK ("), Walk(std::get
<1>(x
.t
), " => ");
1107 Walk(std::get
<Selector
>(x
.t
)), Put(')'), Indent();
1109 void Unparse(const SelectRankCaseStmt
&x
) { // R1150
1110 Outdent(), Word("RANK ");
1111 common::visit(common::visitors
{
1112 [&](const ScalarIntConstantExpr
&y
) {
1113 Put('('), Walk(y
), Put(')');
1115 [&](const Star
&) { Put("(*)"); },
1116 [&](const Default
&) { Word("DEFAULT"); },
1118 std::get
<SelectRankCaseStmt::Rank
>(x
.t
).u
);
1119 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1121 void Unparse(const SelectTypeStmt
&x
) { // R1153
1122 Walk(std::get
<0>(x
.t
), ": ");
1123 Word("SELECT TYPE ("), Walk(std::get
<1>(x
.t
), " => ");
1124 Walk(std::get
<Selector
>(x
.t
)), Put(')'), Indent();
1126 void Unparse(const TypeGuardStmt
&x
) { // R1154
1127 Outdent(), Walk(std::get
<TypeGuardStmt::Guard
>(x
.t
));
1128 Walk(" ", std::get
<std::optional
<Name
>>(x
.t
)), Indent();
1130 void Unparse(const TypeGuardStmt::Guard
&x
) {
1133 [&](const TypeSpec
&y
) { Word("TYPE IS ("), Walk(y
), Put(')'); },
1134 [&](const DerivedTypeSpec
&y
) {
1135 Word("CLASS IS ("), Walk(y
), Put(')');
1137 [&](const Default
&) { Word("CLASS DEFAULT"); },
1141 void Unparse(const ExitStmt
&x
) { // R1156
1142 Word("EXIT"), Walk(" ", x
.v
);
1144 void Before(const GotoStmt
&) { // R1157
1147 void Unparse(const ComputedGotoStmt
&x
) { // R1158
1148 Word("GO TO ("), Walk(x
.t
, "), ");
1150 void Unparse(const ContinueStmt
&) { // R1159
1153 void Unparse(const StopStmt
&x
) { // R1160, R1161
1154 if (std::get
<StopStmt::Kind
>(x
.t
) == StopStmt::Kind::ErrorStop
) {
1157 Word("STOP"), Walk(" ", std::get
<std::optional
<StopCode
>>(x
.t
));
1158 Walk(", QUIET=", std::get
<std::optional
<ScalarLogicalExpr
>>(x
.t
));
1160 void Unparse(const FailImageStmt
&) { // R1163
1163 void Unparse(const NotifyWaitStmt
&x
) { // F2023: R1166
1164 Word("NOTIFY WAIT ("), Walk(std::get
<Scalar
<Variable
>>(x
.t
));
1165 Walk(", ", std::get
<std::list
<EventWaitSpec
>>(x
.t
), ", ");
1168 void Unparse(const SyncAllStmt
&x
) { // R1164
1169 Word("SYNC ALL ("), Walk(x
.v
, ", "), Put(')');
1171 void Unparse(const SyncImagesStmt
&x
) { // R1166
1172 Word("SYNC IMAGES (");
1173 Walk(std::get
<SyncImagesStmt::ImageSet
>(x
.t
));
1174 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1176 void Unparse(const SyncMemoryStmt
&x
) { // R1168
1177 Word("SYNC MEMORY ("), Walk(x
.v
, ", "), Put(')');
1179 void Unparse(const SyncTeamStmt
&x
) { // R1169
1180 Word("SYNC TEAM ("), Walk(std::get
<TeamValue
>(x
.t
));
1181 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1183 void Unparse(const EventPostStmt
&x
) { // R1170
1184 Word("EVENT POST ("), Walk(std::get
<EventVariable
>(x
.t
));
1185 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", "), Put(')');
1187 void Before(const EventWaitSpec
&x
) { // R1173, R1174
1188 common::visit(common::visitors
{
1189 [&](const ScalarIntExpr
&) { Word("UNTIL_COUNT="); },
1190 [](const StatOrErrmsg
&) {},
1194 void Unparse(const EventWaitStmt
&x
) { // R1170
1195 Word("EVENT WAIT ("), Walk(std::get
<EventVariable
>(x
.t
));
1196 Walk(", ", std::get
<std::list
<EventWaitSpec
>>(x
.t
), ", ");
1199 void Unparse(const FormTeamStmt
&x
) { // R1175, R1177
1200 Word("FORM TEAM ("), Walk(std::get
<ScalarIntExpr
>(x
.t
));
1201 Put(','), Walk(std::get
<TeamVariable
>(x
.t
));
1202 Walk(", ", std::get
<std::list
<FormTeamStmt::FormTeamSpec
>>(x
.t
), ", ");
1205 void Before(const FormTeamStmt::FormTeamSpec
&x
) { // R1176, R1178
1206 common::visit(common::visitors
{
1207 [&](const ScalarIntExpr
&) { Word("NEW_INDEX="); },
1208 [](const StatOrErrmsg
&) {},
1212 void Unparse(const LockStmt
&x
) { // R1179
1213 Word("LOCK ("), Walk(std::get
<LockVariable
>(x
.t
));
1214 Walk(", ", std::get
<std::list
<LockStmt::LockStat
>>(x
.t
), ", ");
1217 void Before(const LockStmt::LockStat
&x
) { // R1180
1220 [&](const ScalarLogicalVariable
&) { Word("ACQUIRED_LOCK="); },
1221 [](const StatOrErrmsg
&) {},
1225 void Unparse(const UnlockStmt
&x
) { // R1181
1226 Word("UNLOCK ("), Walk(std::get
<LockVariable
>(x
.t
));
1227 Walk(", ", std::get
<std::list
<StatOrErrmsg
>>(x
.t
), ", ");
1231 void Unparse(const OpenStmt
&x
) { // R1204
1232 Word("OPEN ("), Walk(x
.v
, ", "), Put(')');
1234 bool Pre(const ConnectSpec
&x
) { // R1205
1235 return common::visit(common::visitors
{
1236 [&](const FileUnitNumber
&) {
1240 [&](const FileNameExpr
&) {
1244 [&](const ConnectSpec::CharExpr
&y
) {
1248 [&](const MsgVariable
&) {
1252 [&](const StatVariable
&) {
1256 [&](const ConnectSpec::Recl
&) {
1260 [&](const ConnectSpec::Newunit
&) {
1264 [&](const ErrLabel
&) {
1268 [&](const StatusExpr
&) {
1275 void Unparse(const CloseStmt
&x
) { // R1208
1276 Word("CLOSE ("), Walk(x
.v
, ", "), Put(')');
1278 void Before(const CloseStmt::CloseSpec
&x
) { // R1209
1279 common::visit(common::visitors
{
1280 [&](const FileUnitNumber
&) { Word("UNIT="); },
1281 [&](const StatVariable
&) { Word("IOSTAT="); },
1282 [&](const MsgVariable
&) { Word("IOMSG="); },
1283 [&](const ErrLabel
&) { Word("ERR="); },
1284 [&](const StatusExpr
&) { Word("STATUS="); },
1288 void Unparse(const ReadStmt
&x
) { // R1210
1291 Put('('), Walk(x
.iounit
);
1293 Put(", "), Walk(x
.format
);
1295 Walk(", ", x
.controls
, ", ");
1297 } else if (x
.format
) {
1299 if (!x
.items
.empty()) {
1303 Put('('), Walk(x
.controls
, ", "), Put(')');
1305 Walk(" ", x
.items
, ", ");
1307 void Unparse(const WriteStmt
&x
) { // R1211
1312 Put(", "), Walk(x
.format
);
1314 Walk(", ", x
.controls
, ", ");
1316 Walk(x
.controls
, ", ");
1318 Put(')'), Walk(" ", x
.items
, ", ");
1320 void Unparse(const PrintStmt
&x
) { // R1212
1321 Word("PRINT "), Walk(std::get
<Format
>(x
.t
));
1322 Walk(", ", std::get
<std::list
<OutputItem
>>(x
.t
), ", ");
1324 bool Pre(const IoControlSpec
&x
) { // R1213
1325 return common::visit(common::visitors
{
1326 [&](const IoUnit
&) {
1330 [&](const Format
&) {
1338 [&](const IoControlSpec::CharExpr
&y
) {
1342 [&](const IoControlSpec::Asynchronous
&) {
1343 Word("ASYNCHRONOUS=");
1346 [&](const EndLabel
&) {
1350 [&](const EorLabel
&) {
1354 [&](const ErrLabel
&) {
1358 [&](const IdVariable
&) {
1362 [&](const MsgVariable
&) {
1366 [&](const StatVariable
&) {
1370 [&](const IoControlSpec::Pos
&) {
1374 [&](const IoControlSpec::Rec
&) {
1378 [&](const IoControlSpec::Size
&) {
1385 void Unparse(const InputImpliedDo
&x
) { // R1218
1386 Put('('), Walk(std::get
<std::list
<InputItem
>>(x
.t
), ", "), Put(", ");
1387 Walk(std::get
<IoImpliedDoControl
>(x
.t
)), Put(')');
1389 void Unparse(const OutputImpliedDo
&x
) { // R1219
1390 Put('('), Walk(std::get
<std::list
<OutputItem
>>(x
.t
), ", "), Put(", ");
1391 Walk(std::get
<IoImpliedDoControl
>(x
.t
)), Put(')');
1393 void Unparse(const WaitStmt
&x
) { // R1222
1394 Word("WAIT ("), Walk(x
.v
, ", "), Put(')');
1396 void Before(const WaitSpec
&x
) { // R1223
1397 common::visit(common::visitors
{
1398 [&](const FileUnitNumber
&) { Word("UNIT="); },
1399 [&](const EndLabel
&) { Word("END="); },
1400 [&](const EorLabel
&) { Word("EOR="); },
1401 [&](const ErrLabel
&) { Word("ERR="); },
1402 [&](const IdExpr
&) { Word("ID="); },
1403 [&](const MsgVariable
&) { Word("IOMSG="); },
1404 [&](const StatVariable
&) { Word("IOSTAT="); },
1408 void Unparse(const BackspaceStmt
&x
) { // R1224
1409 Word("BACKSPACE ("), Walk(x
.v
, ", "), Put(')');
1411 void Unparse(const EndfileStmt
&x
) { // R1225
1412 Word("ENDFILE ("), Walk(x
.v
, ", "), Put(')');
1414 void Unparse(const RewindStmt
&x
) { // R1226
1415 Word("REWIND ("), Walk(x
.v
, ", "), Put(')');
1417 void Before(const PositionOrFlushSpec
&x
) { // R1227 & R1229
1418 common::visit(common::visitors
{
1419 [&](const FileUnitNumber
&) { Word("UNIT="); },
1420 [&](const MsgVariable
&) { Word("IOMSG="); },
1421 [&](const StatVariable
&) { Word("IOSTAT="); },
1422 [&](const ErrLabel
&) { Word("ERR="); },
1426 void Unparse(const FlushStmt
&x
) { // R1228
1427 Word("FLUSH ("), Walk(x
.v
, ", "), Put(')');
1429 void Unparse(const InquireStmt
&x
) { // R1230
1433 [&](const InquireStmt::Iolength
&y
) {
1434 Word("IOLENGTH="), Walk(y
.t
, ") ");
1436 [&](const std::list
<InquireSpec
> &y
) { Walk(y
, ", "), Put(')'); },
1440 bool Pre(const InquireSpec
&x
) { // R1231
1441 return common::visit(common::visitors
{
1442 [&](const FileUnitNumber
&) {
1446 [&](const FileNameExpr
&) {
1450 [&](const InquireSpec::CharVar
&y
) {
1454 [&](const InquireSpec::IntVar
&y
) {
1458 [&](const InquireSpec::LogVar
&y
) {
1462 [&](const IdExpr
&) {
1466 [&](const ErrLabel
&) {
1474 void Before(const FormatStmt
&) { // R1301
1477 void Unparse(const format::FormatSpecification
&x
) { // R1302, R1303, R1305
1478 Put('('), Walk("", x
.items
, ",", x
.unlimitedItems
.empty() ? "" : ",");
1479 Walk("*(", x
.unlimitedItems
, ",", ")"), Put(')');
1481 void Unparse(const format::FormatItem
&x
) { // R1304, R1306, R1321
1482 if (x
.repeatCount
) {
1483 Walk(*x
.repeatCount
);
1485 common::visit(common::visitors
{
1486 [&](const std::string
&y
) { PutNormalized(y
); },
1487 [&](const std::list
<format::FormatItem
> &y
) {
1488 Walk("(", y
, ",", ")");
1490 [&](const auto &y
) { Walk(y
); },
1495 const format::IntrinsicTypeDataEditDesc
&x
) { // R1307(1/2) - R1311
1498 case format::IntrinsicTypeDataEditDesc::Kind::x: \
1516 Walk(x
.width
), Walk(".", x
.digits
), Walk("E", x
.exponentWidth
);
1518 void Unparse(const format::DerivedTypeDataEditDesc
&x
) { // R1307(2/2), R1312
1520 if (!x
.type
.empty()) {
1521 Put('"'), Put(x
.type
), Put('"');
1523 Walk("(", x
.parameters
, ",", ")");
1525 void Unparse(const format::ControlEditDesc
&x
) { // R1313, R1315-R1320
1527 case format::ControlEditDesc::Kind::T
:
1531 case format::ControlEditDesc::Kind::TL
:
1535 case format::ControlEditDesc::Kind::TR
:
1539 case format::ControlEditDesc::Kind::X
:
1545 case format::ControlEditDesc::Kind::Slash
:
1551 case format::ControlEditDesc::Kind::Colon
:
1554 case format::ControlEditDesc::Kind::P
:
1559 case format::ControlEditDesc::Kind::x: \
1576 case format::ControlEditDesc::Kind::Dollar
:
1579 case format::ControlEditDesc::Kind::Backslash
:
1585 void Before(const MainProgram
&x
) { // R1401
1586 if (!std::get
<std::optional
<Statement
<ProgramStmt
>>>(x
.t
)) {
1590 void Before(const ProgramStmt
&) { // R1402
1591 Word("PROGRAM "), Indent();
1593 void Unparse(const EndProgramStmt
&x
) { // R1403
1594 EndSubprogram("PROGRAM", x
.v
);
1596 void Before(const ModuleStmt
&) { // R1405
1597 Word("MODULE "), Indent();
1599 void Unparse(const EndModuleStmt
&x
) { // R1406
1600 EndSubprogram("MODULE", x
.v
);
1602 void Unparse(const UseStmt
&x
) { // R1409
1603 Word("USE"), Walk(", ", x
.nature
), Put(" :: "), Walk(x
.moduleName
);
1606 [&](const std::list
<Rename
> &y
) { Walk(", ", y
, ", "); },
1607 [&](const std::list
<Only
> &y
) { Walk(", ONLY: ", y
, ", "); },
1611 void Unparse(const Rename
&x
) { // R1411
1612 common::visit(common::visitors
{
1613 [&](const Rename::Names
&y
) { Walk(y
.t
, " => "); },
1614 [&](const Rename::Operators
&y
) {
1615 Word("OPERATOR("), Walk(y
.t
, ") => OPERATOR("),
1621 void Unparse(const SubmoduleStmt
&x
) { // R1417
1622 Word("SUBMODULE ("), WalkTupleElements(x
.t
, ")"), Indent();
1624 void Unparse(const ParentIdentifier
&x
) { // R1418
1625 Walk(std::get
<Name
>(x
.t
)), Walk(":", std::get
<std::optional
<Name
>>(x
.t
));
1627 void Unparse(const EndSubmoduleStmt
&x
) { // R1419
1628 EndSubprogram("SUBMODULE", x
.v
);
1630 void Unparse(const BlockDataStmt
&x
) { // R1421
1631 Word("BLOCK DATA"), Walk(" ", x
.v
), Indent();
1633 void Unparse(const EndBlockDataStmt
&x
) { // R1422
1634 EndSubprogram("BLOCK DATA", x
.v
);
1637 void Unparse(const InterfaceStmt
&x
) { // R1503
1638 common::visit(common::visitors
{
1639 [&](const std::optional
<GenericSpec
> &y
) {
1640 Word("INTERFACE"), Walk(" ", y
);
1642 [&](const Abstract
&) { Word("ABSTRACT INTERFACE"); },
1647 void Unparse(const EndInterfaceStmt
&x
) { // R1504
1648 Outdent(), Word("END INTERFACE"), Walk(" ", x
.v
);
1650 void Unparse(const ProcedureStmt
&x
) { // R1506
1651 if (std::get
<ProcedureStmt::Kind
>(x
.t
) ==
1652 ProcedureStmt::Kind::ModuleProcedure
) {
1655 Word("PROCEDURE :: ");
1656 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
1658 void Before(const GenericSpec
&x
) { // R1508, R1509
1661 [&](const DefinedOperator
&) { Word("OPERATOR("); },
1662 [&](const GenericSpec::Assignment
&) { Word("ASSIGNMENT(=)"); },
1663 [&](const GenericSpec::ReadFormatted
&) {
1664 Word("READ(FORMATTED)");
1666 [&](const GenericSpec::ReadUnformatted
&) {
1667 Word("READ(UNFORMATTED)");
1669 [&](const GenericSpec::WriteFormatted
&) {
1670 Word("WRITE(FORMATTED)");
1672 [&](const GenericSpec::WriteUnformatted
&) {
1673 Word("WRITE(UNFORMATTED)");
1675 [](const auto &) {},
1679 void Post(const GenericSpec
&x
) {
1680 common::visit(common::visitors
{
1681 [&](const DefinedOperator
&) { Put(')'); },
1682 [](const auto &) {},
1686 void Unparse(const GenericStmt
&x
) { // R1510
1687 Word("GENERIC"), Walk(", ", std::get
<std::optional
<AccessSpec
>>(x
.t
));
1688 Put(" :: "), Walk(std::get
<GenericSpec
>(x
.t
)), Put(" => ");
1689 Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
1691 void Unparse(const ExternalStmt
&x
) { // R1511
1692 Word("EXTERNAL :: "), Walk(x
.v
, ", ");
1694 void Unparse(const ProcedureDeclarationStmt
&x
) { // R1512
1695 Word("PROCEDURE("), Walk(std::get
<std::optional
<ProcInterface
>>(x
.t
));
1696 Put(')'), Walk(", ", std::get
<std::list
<ProcAttrSpec
>>(x
.t
), ", ");
1697 Put(" :: "), Walk(std::get
<std::list
<ProcDecl
>>(x
.t
), ", ");
1699 void Unparse(const ProcDecl
&x
) { // R1515
1700 Walk(std::get
<Name
>(x
.t
));
1701 Walk(" => ", std::get
<std::optional
<ProcPointerInit
>>(x
.t
));
1703 void Unparse(const IntrinsicStmt
&x
) { // R1519
1704 Word("INTRINSIC :: "), Walk(x
.v
, ", ");
1706 void Unparse(const CallStmt::StarOrExpr
&x
) {
1713 void Unparse(const CallStmt::Chevrons
&x
) { // CUDA
1714 Walk(std::get
<0>(x
.t
)); // grid
1715 Word(","), Walk(std::get
<1>(x
.t
)); // block
1716 Walk(",", std::get
<2>(x
.t
)); // bytes
1717 Walk(",", std::get
<3>(x
.t
)); // stream
1719 void Unparse(const FunctionReference
&x
) { // R1520
1720 Walk(std::get
<ProcedureDesignator
>(x
.v
.t
));
1721 Put('('), Walk(std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
), ", "), Put(')');
1723 void Unparse(const CallStmt
&x
) { // R1521
1724 if (asFortran_
&& x
.typedCall
.get()) {
1726 asFortran_
->call(out_
, *x
.typedCall
);
1729 const auto &pd
{std::get
<ProcedureDesignator
>(x
.call
.t
)};
1730 Word("CALL "), Walk(pd
);
1731 Walk("<<<", x
.chevrons
, ">>>");
1732 const auto &args
{std::get
<std::list
<ActualArgSpec
>>(x
.call
.t
)};
1734 if (std::holds_alternative
<ProcComponentRef
>(pd
.u
)) {
1735 Put("()"); // pgf90 crashes on CALL to tbp without parentheses
1738 Walk("(", args
, ", ", ")");
1742 void Unparse(const ActualArgSpec
&x
) { // R1523
1743 Walk(std::get
<std::optional
<Keyword
>>(x
.t
), "=");
1744 Walk(std::get
<ActualArg
>(x
.t
));
1746 void Unparse(const ActualArg::PercentRef
&x
) { // R1524
1747 Word("%REF("), Walk(x
.v
), Put(')');
1749 void Unparse(const ActualArg::PercentVal
&x
) {
1750 Word("%VAL("), Walk(x
.v
), Put(')');
1752 void Before(const AltReturnSpec
&) { // R1525
1755 void Post(const PrefixSpec::Elemental
) { Word("ELEMENTAL"); } // R1527
1756 void Post(const PrefixSpec::Impure
) { Word("IMPURE"); }
1757 void Post(const PrefixSpec::Module
) { Word("MODULE"); }
1758 void Post(const PrefixSpec::Non_Recursive
) { Word("NON_RECURSIVE"); }
1759 void Post(const PrefixSpec::Pure
) { Word("PURE"); }
1760 void Post(const PrefixSpec::Recursive
) { Word("RECURSIVE"); }
1761 void Unparse(const PrefixSpec::Attributes
&x
) {
1762 Word("ATTRIBUTES("), Walk(x
.v
), Word(")");
1764 void Unparse(const PrefixSpec::Launch_Bounds
&x
) {
1765 Word("LAUNCH_BOUNDS("), Walk(x
.v
), Word(")");
1767 void Unparse(const PrefixSpec::Cluster_Dims
&x
) {
1768 Word("CLUSTER_DIMS("), Walk(x
.v
), Word(")");
1770 void Unparse(const FunctionStmt
&x
) { // R1530
1771 Walk("", std::get
<std::list
<PrefixSpec
>>(x
.t
), " ", " ");
1772 Word("FUNCTION "), Walk(std::get
<Name
>(x
.t
)), Put("(");
1773 Walk(std::get
<std::list
<Name
>>(x
.t
), ", "), Put(')');
1774 Walk(" ", std::get
<std::optional
<Suffix
>>(x
.t
)), Indent();
1776 void Unparse(const Suffix
&x
) { // R1532
1778 Word("RESULT("), Walk(x
.resultName
), Put(')');
1779 Walk(" ", x
.binding
);
1784 void Unparse(const EndFunctionStmt
&x
) { // R1533
1785 EndSubprogram("FUNCTION", x
.v
);
1787 void Unparse(const SubroutineStmt
&x
) { // R1535
1788 Walk("", std::get
<std::list
<PrefixSpec
>>(x
.t
), " ", " ");
1789 Word("SUBROUTINE "), Walk(std::get
<Name
>(x
.t
));
1790 const auto &args
{std::get
<std::list
<DummyArg
>>(x
.t
)};
1791 const auto &bind
{std::get
<std::optional
<LanguageBindingSpec
>>(x
.t
)};
1795 Walk(" (", args
, ", ", ")");
1800 void Unparse(const EndSubroutineStmt
&x
) { // R1537
1801 EndSubprogram("SUBROUTINE", x
.v
);
1803 void Before(const MpSubprogramStmt
&) { // R1539
1804 Word("MODULE PROCEDURE "), Indent();
1806 void Unparse(const EndMpSubprogramStmt
&x
) { // R1540
1807 EndSubprogram("PROCEDURE", x
.v
);
1809 void Unparse(const EntryStmt
&x
) { // R1541
1810 Word("ENTRY "), Walk(std::get
<Name
>(x
.t
)), Put("(");
1811 Walk(std::get
<std::list
<DummyArg
>>(x
.t
), ", "), Put(")");
1812 Walk(" ", std::get
<std::optional
<Suffix
>>(x
.t
));
1814 void Unparse(const ReturnStmt
&x
) { // R1542
1815 Word("RETURN"), Walk(" ", x
.v
);
1817 void Unparse(const ContainsStmt
&) { // R1543
1822 void Unparse(const StmtFunctionStmt
&x
) { // R1544
1823 Walk(std::get
<Name
>(x
.t
)), Put('(');
1824 Walk(std::get
<std::list
<Name
>>(x
.t
), ", "), Put(") = ");
1825 Walk(std::get
<Scalar
<Expr
>>(x
.t
));
1828 // Directives, extensions, and deprecated constructs
1829 void Unparse(const CompilerDirective
&x
) {
1832 [&](const std::list
<CompilerDirective::IgnoreTKR
> &tkr
) {
1833 Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty
1834 Walk(" ", tkr
, ", ");
1836 [&](const CompilerDirective::LoopCount
&lcount
) {
1837 Walk("!DIR$ LOOP COUNT (", lcount
.v
, ", ", ")");
1839 [&](const std::list
<CompilerDirective::AssumeAligned
>
1841 Word("!DIR$ ASSUME_ALIGNED ");
1842 Walk(" ", assumeAligned
, ", ");
1844 [&](const CompilerDirective::VectorAlways
&valways
) {
1845 Word("!DIR$ VECTOR ALWAYS");
1847 [&](const std::list
<CompilerDirective::NameValue
> &names
) {
1848 Walk("!DIR$ ", names
, " ");
1850 [&](const CompilerDirective::Unrecognized
&) {
1852 Word(x
.source
.ToString());
1858 void Unparse(const CompilerDirective::IgnoreTKR
&x
) {
1859 if (const auto &maybeList
{
1860 std::get
<std::optional
<std::list
<const char *>>>(x
.t
)}) {
1862 for (const char *tkr
: *maybeList
) {
1867 Walk(std::get
<Name
>(x
.t
));
1869 void Unparse(const CompilerDirective::NameValue
&x
) {
1870 Walk(std::get
<Name
>(x
.t
));
1871 Walk("=", std::get
<std::optional
<std::uint64_t>>(x
.t
));
1873 void Unparse(const CompilerDirective::AssumeAligned
&x
) {
1874 Walk(std::get
<common::Indirection
<Designator
>>(x
.t
));
1876 Walk(std::get
<uint64_t>(x
.t
));
1879 // OpenACC Directives & Clauses
1880 void Unparse(const AccAtomicCapture
&x
) {
1882 Word("!$ACC CAPTURE");
1885 Walk(std::get
<AccAtomicCapture::Stmt1
>(x
.t
));
1887 Walk(std::get
<AccAtomicCapture::Stmt2
>(x
.t
));
1889 Word("!$ACC END ATOMIC\n");
1892 void Unparse(const AccAtomicRead
&x
) {
1894 Word("!$ACC ATOMIC READ");
1897 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1899 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1902 void Unparse(const AccAtomicWrite
&x
) {
1904 Word("!$ACC ATOMIC WRITE");
1907 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1909 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1912 void Unparse(const AccAtomicUpdate
&x
) {
1914 Word("!$ACC ATOMIC UPDATE");
1917 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
1919 Walk(std::get
<std::optional
<AccEndAtomic
>>(x
.t
), "!$ACC END ATOMIC\n");
1922 void Unparse(const llvm::acc::Directive
&x
) {
1923 Word(llvm::acc::getOpenACCDirectiveName(x
).str());
1925 #define GEN_FLANG_CLAUSE_UNPARSE
1926 #include "llvm/Frontend/OpenACC/ACC.inc"
1927 void Unparse(const AccObjectListWithModifier
&x
) {
1928 Walk(std::get
<std::optional
<AccDataModifier
>>(x
.t
), ":");
1929 Walk(std::get
<AccObjectList
>(x
.t
));
1931 void Unparse(const AccBindClause
&x
) {
1932 common::visit(common::visitors
{
1933 [&](const Name
&y
) { Walk(y
); },
1934 [&](const ScalarDefaultCharExpr
&y
) { Walk(y
); },
1938 void Unparse(const AccDefaultClause
&x
) {
1940 case llvm::acc::DefaultValue::ACC_Default_none
:
1943 case llvm::acc::DefaultValue::ACC_Default_present
:
1948 void Unparse(const AccClauseList
&x
) { Walk(" ", x
.v
, " "); }
1949 void Unparse(const AccGangArgList
&x
) { Walk(x
.v
, ","); }
1950 void Before(const AccSizeExpr
&x
) {
1954 void Before(const AccGangArg
&x
) {
1955 common::visit(common::visitors
{
1956 [&](const AccGangArg::Num
&) { Word("NUM:"); },
1957 [&](const AccGangArg::Dim
&) { Word("DIM:"); },
1958 [&](const AccGangArg::Static
&) { Word("STATIC:"); },
1959 [](const StatOrErrmsg
&) {},
1963 void Unparse(const AccCollapseArg
&x
) {
1964 const auto &force
{std::get
<bool>(x
.t
)};
1965 const auto &collapseValue
{std::get
<parser::ScalarIntConstantExpr
>(x
.t
)};
1969 Walk(collapseValue
);
1971 void Unparse(const OpenACCBlockConstruct
&x
) {
1974 Walk(std::get
<AccBeginBlockDirective
>(x
.t
));
1977 Walk(std::get
<Block
>(x
.t
), "");
1980 Walk(std::get
<AccEndBlockDirective
>(x
.t
));
1984 void Unparse(const OpenACCLoopConstruct
&x
) {
1987 Walk(std::get
<AccBeginLoopDirective
>(x
.t
));
1990 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
1992 void Unparse(const AccBeginLoopDirective
&x
) {
1993 Walk(std::get
<AccLoopDirective
>(x
.t
));
1994 Walk(std::get
<AccClauseList
>(x
.t
));
1996 void Unparse(const OpenACCStandaloneConstruct
&x
) {
1999 Walk(std::get
<AccStandaloneDirective
>(x
.t
));
2000 Walk(std::get
<AccClauseList
>(x
.t
));
2004 void Unparse(const OpenACCStandaloneDeclarativeConstruct
&x
) {
2007 Walk(std::get
<AccDeclarativeDirective
>(x
.t
));
2008 Walk(std::get
<AccClauseList
>(x
.t
));
2012 void Unparse(const OpenACCCombinedConstruct
&x
) {
2015 Walk(std::get
<AccBeginCombinedDirective
>(x
.t
));
2018 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
2020 Walk("!$ACC END ", std::get
<std::optional
<AccEndCombinedDirective
>>(x
.t
),
2024 void Unparse(const OpenACCRoutineConstruct
&x
) {
2026 Word("!$ACC ROUTINE");
2027 Walk("(", std::get
<std::optional
<Name
>>(x
.t
), ")");
2028 Walk(std::get
<AccClauseList
>(x
.t
));
2032 void Unparse(const AccObject
&x
) {
2033 common::visit(common::visitors
{
2034 [&](const Designator
&y
) { Walk(y
); },
2035 [&](const Name
&y
) { Put("/"), Walk(y
), Put("/"); },
2039 void Unparse(const AccObjectList
&x
) { Walk(x
.v
, ","); }
2040 void Unparse(const AccObjectListWithReduction
&x
) {
2041 Walk(std::get
<ReductionOperator
>(x
.t
));
2043 Walk(std::get
<AccObjectList
>(x
.t
));
2045 void Unparse(const OpenACCCacheConstruct
&x
) {
2049 Walk(std::get
<AccObjectListWithModifier
>(x
.t
));
2054 void Unparse(const AccWaitArgument
&x
) {
2055 Walk("DEVNUM:", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
), ":");
2056 Walk(std::get
<std::list
<ScalarIntExpr
>>(x
.t
), ",");
2058 void Unparse(const OpenACCWaitConstruct
&x
) {
2062 Walk(std::get
<std::optional
<AccWaitArgument
>>(x
.t
));
2063 Walk(std::get
<AccClauseList
>(x
.t
));
2069 // OpenMP Clauses & Directives
2070 void Unparse(const OmpObject
&x
) {
2071 common::visit(common::visitors
{
2072 [&](const Designator
&y
) { Walk(y
); },
2073 [&](const Name
&y
) { Put("/"), Walk(y
), Put("/"); },
2077 void Unparse(const OmpIteratorSpecifier
&x
) {
2078 Walk(std::get
<TypeDeclarationStmt
>(x
.t
));
2080 Walk(std::get
<SubscriptTriplet
>(x
.t
));
2082 void Unparse(const OmpIteratorModifier
&x
) {
2087 void Unparse(const OmpLastprivateClause
&x
) {
2089 std::get
<std::optional
<OmpLastprivateClause::LastprivateModifier
>>(x
.t
),
2091 Walk(std::get
<OmpObjectList
>(x
.t
));
2093 void Unparse(const OmpMapClause
&x
) {
2095 std::get
<std::optional
<std::list
<OmpMapClause::TypeModifier
>>>(x
.t
);
2096 auto &iter
= std::get
<std::optional
<std::list
<OmpIteratorModifier
>>>(x
.t
);
2097 auto &type
= std::get
<std::optional
<std::list
<OmpMapClause::Type
>>>(x
.t
);
2098 auto &mapper
= std::get
<OmpMapperIdentifier
>(x
.t
);
2100 // For a given list of items, if the item has a value, then walk it.
2101 // Print commas between items that have values.
2102 // Return 'true' if something did get printed, otherwise 'false'.
2103 bool needComma
{false};
2134 Walk(std::get
<OmpObjectList
>(x
.t
));
2136 void Unparse(const OmpScheduleModifier
&x
) {
2137 Walk(std::get
<OmpScheduleModifier::Modifier1
>(x
.t
));
2138 Walk(",", std::get
<std::optional
<OmpScheduleModifier::Modifier2
>>(x
.t
));
2140 void Unparse(const OmpScheduleClause
&x
) {
2141 Walk(std::get
<std::optional
<OmpScheduleModifier
>>(x
.t
), ":");
2142 Walk(std::get
<OmpScheduleClause::ScheduleType
>(x
.t
));
2143 Walk(",", std::get
<std::optional
<ScalarIntExpr
>>(x
.t
));
2145 void Unparse(const OmpDeviceClause
&x
) {
2146 Walk(std::get
<std::optional
<OmpDeviceClause::DeviceModifier
>>(x
.t
), ":");
2147 Walk(std::get
<ScalarIntExpr
>(x
.t
));
2149 void Unparse(const OmpAffinityClause
&x
) {
2150 Walk(std::get
<std::optional
<OmpIteratorModifier
>>(x
.t
), ":");
2151 Walk(std::get
<OmpObjectList
>(x
.t
));
2153 void Unparse(const OmpAlignedClause
&x
) {
2154 Walk(std::get
<OmpObjectList
>(x
.t
));
2156 Walk(std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
));
2158 void Unparse(const OmpFromClause
&x
) {
2160 std::get
<std::optional
<std::list
<OmpFromClause::Expectation
>>>(x
.t
)};
2161 auto &iter
{std::get
<std::optional
<std::list
<OmpIteratorModifier
>>>(x
.t
)};
2162 bool needComma
{false};
2177 Walk(std::get
<OmpObjectList
>(x
.t
));
2179 void Unparse(const OmpIfClause
&x
) {
2180 Walk(std::get
<std::optional
<OmpIfClause::DirectiveNameModifier
>>(x
.t
), ":");
2181 Walk(std::get
<ScalarLogicalExpr
>(x
.t
));
2183 void Unparse(const OmpLinearClause::WithoutModifier
&x
) {
2184 Walk(x
.names
, ", ");
2187 void Unparse(const OmpLinearClause::WithModifier
&x
) {
2188 Walk(x
.modifier
), Put("("), Walk(x
.names
, ","), Put(")");
2191 void Unparse(const OmpReductionClause
&x
) {
2192 Walk(std::get
<std::optional
<OmpReductionClause::ReductionModifier
>>(x
.t
),
2194 Walk(std::get
<OmpReductionOperator
>(x
.t
));
2196 Walk(std::get
<OmpObjectList
>(x
.t
));
2198 void Unparse(const OmpDetachClause
&x
) { Walk(x
.v
); }
2199 void Unparse(const OmpInReductionClause
&x
) {
2200 Walk(std::get
<OmpReductionOperator
>(x
.t
));
2202 Walk(std::get
<OmpObjectList
>(x
.t
));
2204 void Unparse(const OmpAllocateClause
&x
) {
2206 std::get
<std::optional
<OmpAllocateClause::AllocateModifier
>>(x
.t
), ":");
2207 Walk(std::get
<OmpObjectList
>(x
.t
));
2209 void Unparse(const OmpAllocateClause::AllocateModifier
&x
) {
2212 [&](const OmpAllocateClause::AllocateModifier::Allocator
&y
) {
2215 [&](const OmpAllocateClause::AllocateModifier::ComplexModifier
&y
) {
2217 Walk(std::get
<OmpAllocateClause::AllocateModifier::Allocator
>(
2221 Walk(std::get
<OmpAllocateClause::AllocateModifier::Align
>(y
.t
));
2223 [&](const OmpAllocateClause::AllocateModifier::Align
&y
) {
2229 void Unparse(const OmpAllocateClause::AllocateModifier::Align
&x
) {
2234 void Unparse(const OmpOrderClause
&x
) {
2235 Walk(std::get
<std::optional
<OmpOrderModifier
>>(x
.t
), ":");
2236 Walk(std::get
<OmpOrderClause::Type
>(x
.t
));
2238 void Unparse(const OmpGrainsizeClause
&x
) {
2239 Walk(std::get
<std::optional
<OmpGrainsizeClause::Prescriptiveness
>>(x
.t
),
2241 Walk(std::get
<ScalarIntExpr
>(x
.t
));
2243 void Unparse(const OmpNumTasksClause
&x
) {
2245 std::get
<std::optional
<OmpNumTasksClause::Prescriptiveness
>>(x
.t
), ":");
2246 Walk(std::get
<ScalarIntExpr
>(x
.t
));
2248 void Unparse(const OmpDoacross::Sink
&x
) {
2252 void Unparse(const OmpDoacross::Source
&) { Word("SOURCE"); }
2253 void Unparse(const OmpDependClause::TaskDep
&x
) {
2254 Walk(std::get
<OmpTaskDependenceType
>(x
.t
));
2256 Walk(std::get
<OmpObjectList
>(x
.t
));
2258 void Unparse(const OmpDefaultmapClause
&x
) {
2259 Walk(std::get
<OmpDefaultmapClause::ImplicitBehavior
>(x
.t
));
2261 std::get
<std::optional
<OmpDefaultmapClause::VariableCategory
>>(x
.t
));
2263 void Unparse(const OmpToClause
&x
) {
2265 std::get
<std::optional
<std::list
<OmpToClause::Expectation
>>>(x
.t
)};
2266 auto &iter
{std::get
<std::optional
<std::list
<OmpIteratorModifier
>>>(x
.t
)};
2267 bool needComma
{false};
2282 Walk(std::get
<OmpObjectList
>(x
.t
));
2284 #define GEN_FLANG_CLAUSE_UNPARSE
2285 #include "llvm/Frontend/OpenMP/OMP.inc"
2286 void Unparse(const OmpLoopDirective
&x
) {
2288 case llvm::omp::Directive::OMPD_distribute
:
2289 Word("DISTRIBUTE ");
2291 case llvm::omp::Directive::OMPD_distribute_parallel_do
:
2292 Word("DISTRIBUTE PARALLEL DO ");
2294 case llvm::omp::Directive::OMPD_distribute_parallel_do_simd
:
2295 Word("DISTRIBUTE PARALLEL DO SIMD ");
2297 case llvm::omp::Directive::OMPD_distribute_simd
:
2298 Word("DISTRIBUTE SIMD ");
2300 case llvm::omp::Directive::OMPD_do
:
2303 case llvm::omp::Directive::OMPD_do_simd
:
2306 case llvm::omp::Directive::OMPD_loop
:
2309 case llvm::omp::Directive::OMPD_masked_taskloop_simd
:
2310 Word("MASKED TASKLOOP SIMD");
2312 case llvm::omp::Directive::OMPD_masked_taskloop
:
2313 Word("MASKED TASKLOOP");
2315 case llvm::omp::Directive::OMPD_master_taskloop_simd
:
2316 Word("MASTER TASKLOOP SIMD");
2318 case llvm::omp::Directive::OMPD_master_taskloop
:
2319 Word("MASTER TASKLOOP");
2321 case llvm::omp::Directive::OMPD_parallel_do
:
2322 Word("PARALLEL DO ");
2324 case llvm::omp::Directive::OMPD_parallel_do_simd
:
2325 Word("PARALLEL DO SIMD ");
2327 case llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd
:
2328 Word("PARALLEL MASKED TASKLOOP SIMD");
2330 case llvm::omp::Directive::OMPD_parallel_masked_taskloop
:
2331 Word("PARALLEL MASKED TASKLOOP");
2333 case llvm::omp::Directive::OMPD_parallel_master_taskloop_simd
:
2334 Word("PARALLEL MASTER TASKLOOP SIMD");
2336 case llvm::omp::Directive::OMPD_parallel_master_taskloop
:
2337 Word("PARALLEL MASTER TASKLOOP");
2339 case llvm::omp::Directive::OMPD_simd
:
2342 case llvm::omp::Directive::OMPD_target_loop
:
2343 Word("TARGET LOOP ");
2345 case llvm::omp::Directive::OMPD_target_parallel_do
:
2346 Word("TARGET PARALLEL DO ");
2348 case llvm::omp::Directive::OMPD_target_parallel_do_simd
:
2349 Word("TARGET PARALLEL DO SIMD ");
2351 case llvm::omp::Directive::OMPD_target_parallel_loop
:
2352 Word("TARGET PARALLEL LOOP ");
2354 case llvm::omp::Directive::OMPD_target_teams_distribute
:
2355 Word("TARGET TEAMS DISTRIBUTE ");
2357 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do
:
2358 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO ");
2360 case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd
:
2361 Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2363 case llvm::omp::Directive::OMPD_target_teams_distribute_simd
:
2364 Word("TARGET TEAMS DISTRIBUTE SIMD ");
2366 case llvm::omp::Directive::OMPD_target_teams_loop
:
2367 Word("TARGET TEAMS LOOP ");
2369 case llvm::omp::Directive::OMPD_target_simd
:
2370 Word("TARGET SIMD ");
2372 case llvm::omp::Directive::OMPD_taskloop
:
2375 case llvm::omp::Directive::OMPD_taskloop_simd
:
2376 Word("TASKLOOP SIMD ");
2378 case llvm::omp::Directive::OMPD_teams_distribute
:
2379 Word("TEAMS DISTRIBUTE ");
2381 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do
:
2382 Word("TEAMS DISTRIBUTE PARALLEL DO ");
2384 case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd
:
2385 Word("TEAMS DISTRIBUTE PARALLEL DO SIMD ");
2387 case llvm::omp::Directive::OMPD_teams_distribute_simd
:
2388 Word("TEAMS DISTRIBUTE SIMD ");
2390 case llvm::omp::Directive::OMPD_tile
:
2393 case llvm::omp::Directive::OMPD_unroll
:
2400 void Unparse(const OmpObjectList
&x
) { Walk(x
.v
, ","); }
2401 void Unparse(const OmpSimpleStandaloneDirective
&x
) {
2403 case llvm::omp::Directive::OMPD_barrier
:
2406 case llvm::omp::Directive::OMPD_scan
:
2409 case llvm::omp::Directive::OMPD_taskwait
:
2412 case llvm::omp::Directive::OMPD_taskyield
:
2415 case llvm::omp::Directive::OMPD_target_enter_data
:
2416 Word("TARGET ENTER DATA ");
2418 case llvm::omp::Directive::OMPD_target_exit_data
:
2419 Word("TARGET EXIT DATA ");
2421 case llvm::omp::Directive::OMPD_target_update
:
2422 Word("TARGET UPDATE ");
2424 case llvm::omp::Directive::OMPD_ordered
:
2428 // Nothing to be done
2432 void Unparse(const OmpBlockDirective
&x
) {
2434 case llvm::omp::Directive::OMPD_masked
:
2437 case llvm::omp::Directive::OMPD_master
:
2440 case llvm::omp::Directive::OMPD_ordered
:
2443 case llvm::omp::Directive::OMPD_parallel_masked
:
2444 Word("PARALLEL MASKED");
2446 case llvm::omp::Directive::OMPD_parallel_master
:
2447 Word("PARALLEL MASTER");
2449 case llvm::omp::Directive::OMPD_parallel_workshare
:
2450 Word("PARALLEL WORKSHARE ");
2452 case llvm::omp::Directive::OMPD_parallel
:
2455 case llvm::omp::Directive::OMPD_scope
:
2458 case llvm::omp::Directive::OMPD_single
:
2461 case llvm::omp::Directive::OMPD_target_data
:
2462 Word("TARGET DATA ");
2464 case llvm::omp::Directive::OMPD_target_parallel
:
2465 Word("TARGET PARALLEL ");
2467 case llvm::omp::Directive::OMPD_target_teams
:
2468 Word("TARGET TEAMS ");
2470 case llvm::omp::Directive::OMPD_target
:
2473 case llvm::omp::Directive::OMPD_taskgroup
:
2476 case llvm::omp::Directive::OMPD_task
:
2479 case llvm::omp::Directive::OMPD_teams
:
2482 case llvm::omp::Directive::OMPD_workshare
:
2486 // Nothing to be done
2491 void Unparse(const OmpAtomicDefaultMemOrderClause
&x
) {
2492 Word(ToUpperCaseLetters(common::EnumToString(x
.v
)));
2495 void Unparse(const OmpAtomicClauseList
&x
) { Walk(" ", x
.v
, " "); }
2497 void Unparse(const OmpAtomic
&x
) {
2499 Word("!$OMP ATOMIC");
2500 Walk(std::get
<OmpAtomicClauseList
>(x
.t
));
2503 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2505 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2508 void Unparse(const OmpAtomicCapture
&x
) {
2510 Word("!$OMP ATOMIC");
2511 Walk(std::get
<0>(x
.t
));
2513 Walk(std::get
<2>(x
.t
));
2516 Walk(std::get
<OmpAtomicCapture::Stmt1
>(x
.t
));
2518 Walk(std::get
<OmpAtomicCapture::Stmt2
>(x
.t
));
2520 Word("!$OMP END ATOMIC\n");
2523 void Unparse(const OmpAtomicRead
&x
) {
2525 Word("!$OMP ATOMIC");
2526 Walk(std::get
<0>(x
.t
));
2528 Walk(std::get
<2>(x
.t
));
2531 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2533 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2536 void Unparse(const OmpAtomicUpdate
&x
) {
2538 Word("!$OMP ATOMIC");
2539 Walk(std::get
<0>(x
.t
));
2541 Walk(std::get
<2>(x
.t
));
2544 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2546 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2549 void Unparse(const OmpAtomicWrite
&x
) {
2551 Word("!$OMP ATOMIC");
2552 Walk(std::get
<0>(x
.t
));
2554 Walk(std::get
<2>(x
.t
));
2557 Walk(std::get
<Statement
<AssignmentStmt
>>(x
.t
));
2559 Walk(std::get
<std::optional
<OmpEndAtomic
>>(x
.t
), "!$OMP END ATOMIC\n");
2562 void Unparse(const OpenMPExecutableAllocate
&x
) {
2563 const auto &fields
=
2564 std::get
<std::optional
<std::list
<parser::OpenMPDeclarativeAllocate
>>>(
2567 for (const auto &decl
: *fields
) {
2572 Word("!$OMP ALLOCATE");
2573 Walk(" (", std::get
<std::optional
<OmpObjectList
>>(x
.t
), ")");
2574 Walk(std::get
<OmpClauseList
>(x
.t
));
2577 Walk(std::get
<Statement
<AllocateStmt
>>(x
.t
));
2579 void Unparse(const OpenMPDeclarativeAllocate
&x
) {
2581 Word("!$OMP ALLOCATE");
2583 Walk(std::get
<OmpObjectList
>(x
.t
));
2585 Walk(std::get
<OmpClauseList
>(x
.t
));
2589 void Unparse(const OmpEndAllocators
&x
) {
2591 Word("!$OMP END ALLOCATE");
2595 void Unparse(const OpenMPAllocatorsConstruct
&x
) {
2597 Word("!$OMP ALLOCATE");
2598 Walk(std::get
<OmpClauseList
>(x
.t
));
2601 Walk(std::get
<Statement
<AllocateStmt
>>(x
.t
));
2602 if (const auto &end
= std::get
<std::optional
<OmpEndAllocators
>>(x
.t
)) {
2606 void Unparse(const OmpCriticalDirective
&x
) {
2608 Word("!$OMP CRITICAL");
2609 Walk(" (", std::get
<std::optional
<Name
>>(x
.t
), ")");
2610 Walk(std::get
<OmpClauseList
>(x
.t
));
2614 void Unparse(const OmpEndCriticalDirective
&x
) {
2616 Word("!$OMP END CRITICAL");
2617 Walk(" (", std::get
<std::optional
<Name
>>(x
.t
), ")");
2621 void Unparse(const OpenMPCriticalConstruct
&x
) {
2622 Walk(std::get
<OmpCriticalDirective
>(x
.t
));
2623 Walk(std::get
<Block
>(x
.t
), "");
2624 Walk(std::get
<OmpEndCriticalDirective
>(x
.t
));
2626 void Unparse(const OmpDeclareTargetWithList
&x
) {
2627 Put("("), Walk(x
.v
), Put(")");
2629 void Unparse(const OmpReductionInitializerClause
&x
) {
2630 Word(" INITIALIZER(OMP_PRIV = ");
2634 void Unparse(const OmpReductionCombiner::FunctionCombiner
&x
) {
2635 const auto &pd
= std::get
<ProcedureDesignator
>(x
.v
.t
);
2636 const auto &args
= std::get
<std::list
<ActualArgSpec
>>(x
.v
.t
);
2639 if (std::holds_alternative
<ProcComponentRef
>(pd
.u
)) {
2643 Walk("(", args
, ", ", ")");
2646 void Unparse(const OpenMPDeclareReductionConstruct
&x
) {
2648 Walk(std::get
<OmpReductionOperator
>(x
.t
)), Put(" : ");
2649 Walk(std::get
<std::list
<DeclarationTypeSpec
>>(x
.t
), ","), Put(" : ");
2650 Walk(std::get
<OmpReductionCombiner
>(x
.t
));
2652 Walk(std::get
<std::optional
<OmpReductionInitializerClause
>>(x
.t
));
2654 bool Pre(const OpenMPDeclarativeConstruct
&x
) {
2657 return common::visit(
2659 [&](const OpenMPDeclarativeAllocate
&z
) {
2661 Walk(std::get
<OmpObjectList
>(z
.t
));
2663 Walk(std::get
<OmpClauseList
>(z
.t
));
2668 [&](const OpenMPDeclareMapperConstruct
&z
) {
2669 Word("DECLARE MAPPER (");
2670 const auto &spec
{std::get
<OmpDeclareMapperSpecifier
>(z
.t
)};
2671 if (auto mapname
{std::get
<std::optional
<Name
>>(spec
.t
)}) {
2675 Walk(std::get
<TypeSpec
>(spec
.t
));
2677 Walk(std::get
<Name
>(spec
.t
));
2680 Walk(std::get
<OmpClauseList
>(z
.t
));
2684 [&](const OpenMPDeclareReductionConstruct
&) {
2685 Word("DECLARE REDUCTION ");
2688 [&](const OpenMPDeclareSimdConstruct
&y
) {
2689 Word("DECLARE SIMD ");
2690 Walk("(", std::get
<std::optional
<Name
>>(y
.t
), ")");
2691 Walk(std::get
<OmpClauseList
>(y
.t
));
2696 [&](const OpenMPDeclareTargetConstruct
&) {
2697 Word("DECLARE TARGET ");
2700 [&](const OpenMPRequiresConstruct
&y
) {
2702 Walk(std::get
<OmpClauseList
>(y
.t
));
2707 [&](const OpenMPThreadprivate
&) {
2708 Word("THREADPRIVATE (");
2714 void Post(const OpenMPDeclarativeConstruct
&) {
2718 void Post(const OpenMPThreadprivate
&) {
2722 void Unparse(const OmpSectionsDirective
&x
) {
2724 case llvm::omp::Directive::OMPD_sections
:
2727 case llvm::omp::Directive::OMPD_parallel_sections
:
2728 Word("PARALLEL SECTIONS ");
2734 void Unparse(const OmpSectionBlocks
&x
) {
2735 for (const auto &y
: x
.v
) {
2737 Word("!$OMP SECTION");
2740 // y.u is an OpenMPSectionConstruct
2742 Walk(std::get
<OpenMPSectionConstruct
>(y
.u
).v
, "");
2745 void Unparse(const OpenMPSectionsConstruct
&x
) {
2748 Walk(std::get
<OmpBeginSectionsDirective
>(x
.t
));
2751 Walk(std::get
<OmpSectionBlocks
>(x
.t
));
2754 Walk(std::get
<OmpEndSectionsDirective
>(x
.t
));
2758 void Unparse(const OpenMPCancellationPointConstruct
&x
) {
2760 Word("!$OMP CANCELLATION POINT ");
2761 Walk(std::get
<OmpCancelType
>(x
.t
));
2765 void Unparse(const OpenMPCancelConstruct
&x
) {
2767 Word("!$OMP CANCEL ");
2768 Walk(std::get
<OmpCancelType
>(x
.t
));
2769 Walk(std::get
<std::optional
<OpenMPCancelConstruct::If
>>(x
.t
));
2773 void Unparse(const OmpMemoryOrderClause
&x
) { Walk(x
.v
); }
2774 void Unparse(const OmpAtomicClause
&x
) {
2775 common::visit(common::visitors
{
2776 [&](const OmpMemoryOrderClause
&y
) { Walk(y
); },
2777 [&](const OmpClause
&z
) { Walk(z
); },
2781 void Unparse(const OpenMPDepobjConstruct
&x
) {
2783 Word("!$OMP DEPOBJ");
2785 Walk(std::get
<OmpObject
>(x
.t
));
2787 Walk(std::get
<OmpClause
>(x
.t
));
2791 void Unparse(const OpenMPFlushConstruct
&x
) {
2793 Word("!$OMP FLUSH ");
2794 Walk(std::get
<std::optional
<std::list
<OmpMemoryOrderClause
>>>(x
.t
));
2795 Walk(" (", std::get
<std::optional
<OmpObjectList
>>(x
.t
), ")");
2799 void Unparse(const OmpEndLoopDirective
&x
) {
2802 Walk(std::get
<OmpLoopDirective
>(x
.t
));
2803 Walk(std::get
<OmpClauseList
>(x
.t
));
2807 void Unparse(const OmpClauseList
&x
) { Walk(" ", x
.v
, " "); }
2808 void Unparse(const OpenMPSimpleStandaloneConstruct
&x
) {
2811 Walk(std::get
<OmpSimpleStandaloneDirective
>(x
.t
));
2812 Walk(std::get
<OmpClauseList
>(x
.t
));
2816 void Unparse(const OpenMPBlockConstruct
&x
) {
2819 Walk(std::get
<OmpBeginBlockDirective
>(x
.t
));
2822 Walk(std::get
<Block
>(x
.t
), "");
2825 Walk(std::get
<OmpEndBlockDirective
>(x
.t
));
2829 void Unparse(const OpenMPLoopConstruct
&x
) {
2832 Walk(std::get
<OmpBeginLoopDirective
>(x
.t
));
2835 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
2836 Walk(std::get
<std::optional
<OmpEndLoopDirective
>>(x
.t
));
2838 void Unparse(const BasedPointer
&x
) {
2839 Put('('), Walk(std::get
<0>(x
.t
)), Put(","), Walk(std::get
<1>(x
.t
));
2840 Walk("(", std::get
<std::optional
<ArraySpec
>>(x
.t
), ")"), Put(')');
2842 void Unparse(const BasedPointerStmt
&x
) { Walk("POINTER ", x
.v
, ","); }
2843 void Unparse(const CUDAAttributesStmt
&x
) {
2844 Word("ATTRIBUTES("), Walk(std::get
<common::CUDADataAttr
>(x
.t
));
2845 Word(") "), Walk(std::get
<std::list
<Name
>>(x
.t
), ", ");
2847 void Post(const StructureField
&x
) {
2848 if (const auto *def
{std::get_if
<Statement
<DataComponentDefStmt
>>(&x
.u
)}) {
2849 for (const auto &item
:
2850 std::get
<std::list
<ComponentOrFill
>>(def
->statement
.t
)) {
2851 if (const auto *comp
{std::get_if
<ComponentDecl
>(&item
.u
)}) {
2852 structureComponents_
.insert(std::get
<Name
>(comp
->t
).source
);
2857 void Unparse(const StructureStmt
&x
) {
2859 // The name, if present, includes the /slashes/
2860 Walk(std::get
<std::optional
<Name
>>(x
.t
));
2861 Walk(" ", std::get
<std::list
<EntityDecl
>>(x
.t
), ", ");
2864 void Post(const Union::UnionStmt
&) { Word("UNION"), Indent(); }
2865 void Post(const Union::EndUnionStmt
&) { Outdent(), Word("END UNION"); }
2866 void Post(const Map::MapStmt
&) { Word("MAP"), Indent(); }
2867 void Post(const Map::EndMapStmt
&) { Outdent(), Word("END MAP"); }
2868 void Post(const StructureDef::EndStructureStmt
&) {
2869 Outdent(), Word("END STRUCTURE");
2871 void Unparse(const OldParameterStmt
&x
) {
2872 Word("PARAMETER "), Walk(x
.v
, ", ");
2874 void Unparse(const ArithmeticIfStmt
&x
) {
2875 Word("IF ("), Walk(std::get
<Expr
>(x
.t
)), Put(") ");
2876 Walk(std::get
<1>(x
.t
)), Put(", ");
2877 Walk(std::get
<2>(x
.t
)), Put(", ");
2878 Walk(std::get
<3>(x
.t
));
2880 void Unparse(const AssignStmt
&x
) {
2881 Word("ASSIGN "), Walk(std::get
<Label
>(x
.t
));
2882 Word(" TO "), Walk(std::get
<Name
>(x
.t
));
2884 void Unparse(const AssignedGotoStmt
&x
) {
2885 Word("GO TO "), Walk(std::get
<Name
>(x
.t
));
2886 Walk(", (", std::get
<std::list
<Label
>>(x
.t
), ", ", ")");
2888 void Unparse(const PauseStmt
&x
) { Word("PAUSE"), Walk(" ", x
.v
); }
2890 #define WALK_NESTED_ENUM(CLASS, ENUM) \
2891 void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); }
2892 WALK_NESTED_ENUM(AccDataModifier
, Modifier
)
2893 WALK_NESTED_ENUM(AccessSpec
, Kind
) // R807
2894 WALK_NESTED_ENUM(common
, TypeParamAttr
) // R734
2895 WALK_NESTED_ENUM(common
, CUDADataAttr
) // CUDA
2896 WALK_NESTED_ENUM(common
, CUDASubprogramAttrs
) // CUDA
2897 WALK_NESTED_ENUM(IntentSpec
, Intent
) // R826
2898 WALK_NESTED_ENUM(ImplicitStmt
, ImplicitNoneNameSpec
) // R866
2899 WALK_NESTED_ENUM(ConnectSpec::CharExpr
, Kind
) // R1205
2900 WALK_NESTED_ENUM(IoControlSpec::CharExpr
, Kind
)
2901 WALK_NESTED_ENUM(InquireSpec::CharVar
, Kind
)
2902 WALK_NESTED_ENUM(InquireSpec::IntVar
, Kind
)
2903 WALK_NESTED_ENUM(InquireSpec::LogVar
, Kind
)
2904 WALK_NESTED_ENUM(ProcedureStmt
, Kind
) // R1506
2905 WALK_NESTED_ENUM(UseStmt
, ModuleNature
) // R1410
2906 WALK_NESTED_ENUM(OmpProcBindClause
, Type
) // OMP PROC_BIND
2907 WALK_NESTED_ENUM(OmpDefaultClause
, Type
) // OMP DEFAULT
2908 WALK_NESTED_ENUM(OmpDefaultmapClause
, ImplicitBehavior
) // OMP DEFAULTMAP
2909 WALK_NESTED_ENUM(OmpDefaultmapClause
, VariableCategory
) // OMP DEFAULTMAP
2911 OmpLastprivateClause
, LastprivateModifier
) // OMP lastprivate-modifier
2912 WALK_NESTED_ENUM(OmpScheduleModifierType
, ModType
) // OMP schedule-modifier
2913 WALK_NESTED_ENUM(OmpLinearModifier
, Type
) // OMP linear-modifier
2914 WALK_NESTED_ENUM(OmpTaskDependenceType
, Type
) // OMP task-dependence-type
2915 WALK_NESTED_ENUM(OmpScheduleClause
, ScheduleType
) // OMP schedule-type
2916 WALK_NESTED_ENUM(OmpDeviceClause
, DeviceModifier
) // OMP device modifier
2917 WALK_NESTED_ENUM(OmpDeviceTypeClause
, Type
) // OMP DEVICE_TYPE
2919 OmpReductionClause
, ReductionModifier
) // OMP reduction-modifier
2920 WALK_NESTED_ENUM(OmpFromClause
, Expectation
) // OMP motion-expectation
2921 WALK_NESTED_ENUM(OmpIfClause
, DirectiveNameModifier
) // OMP directive-modifier
2922 WALK_NESTED_ENUM(OmpCancelType
, Type
) // OMP cancel-type
2923 WALK_NESTED_ENUM(OmpOrderClause
, Type
) // OMP order-type
2924 WALK_NESTED_ENUM(OmpOrderModifier
, Kind
) // OMP order-modifier
2926 OmpGrainsizeClause
, Prescriptiveness
) // OMP grainsize-modifier
2927 WALK_NESTED_ENUM(OmpNumTasksClause
, Prescriptiveness
) // OMP numtasks-modifier
2928 WALK_NESTED_ENUM(OmpMapClause
, Type
) // OMP map-type
2929 WALK_NESTED_ENUM(OmpMapClause
, TypeModifier
) // OMP map-type-modifier
2930 #undef WALK_NESTED_ENUM
2931 void Unparse(const ReductionOperator::Operator x
) {
2933 case ReductionOperator::Operator::Plus
:
2936 case ReductionOperator::Operator::Multiply
:
2939 case ReductionOperator::Operator::And
:
2942 case ReductionOperator::Operator::Or
:
2945 case ReductionOperator::Operator::Eqv
:
2948 case ReductionOperator::Operator::Neqv
:
2952 Word(ReductionOperator::EnumToString(x
));
2957 void Unparse(const CUFKernelDoConstruct::StarOrExpr
&x
) {
2964 void Unparse(const CUFKernelDoConstruct::LaunchConfiguration
&x
) {
2966 const auto &grid
{std::get
<0>(x
.t
)};
2969 } else if (grid
.size() == 1) {
2972 Walk("(", grid
, ",", ")");
2975 const auto &block
{std::get
<1>(x
.t
)};
2976 if (block
.empty()) {
2978 } else if (block
.size() == 1) {
2979 Walk(block
.front());
2981 Walk("(", block
, ",", ")");
2983 if (const auto &stream
{std::get
<2>(x
.t
)}) {
2984 Word(",STREAM="), Walk(*stream
);
2988 void Unparse(const CUFKernelDoConstruct::Directive
&x
) {
2989 Word("!$CUF KERNEL DO");
2990 Walk(" (", std::get
<std::optional
<ScalarIntConstantExpr
>>(x
.t
), ")");
2991 Walk(std::get
<std::optional
<CUFKernelDoConstruct::LaunchConfiguration
>>(
2993 Walk(" ", std::get
<std::list
<CUFReduction
>>(x
.t
), " ");
2996 void Unparse(const CUFKernelDoConstruct
&x
) {
2997 Walk(std::get
<CUFKernelDoConstruct::Directive
>(x
.t
));
2998 Walk(std::get
<std::optional
<DoConstruct
>>(x
.t
));
3000 void Unparse(const CUFReduction
&x
) {
3002 Walk(std::get
<CUFReduction::Operator
>(x
.t
));
3003 Walk(":", std::get
<std::list
<Scalar
<Variable
>>>(x
.t
), ",", ")");
3006 void Done() const { CHECK(indent_
== 0); }
3010 void Put(const char *);
3011 void Put(const std::string
&);
3012 void PutNormalized(const std::string
&);
3013 void PutKeywordLetter(char);
3014 void Word(const char *);
3015 void Word(const std::string
&);
3016 void Word(const std::string_view
&);
3017 void Indent() { indent_
+= indentationAmount_
; }
3019 CHECK(indent_
>= indentationAmount_
);
3020 indent_
-= indentationAmount_
;
3022 void BeginOpenMP() { openmpDirective_
= true; }
3023 void EndOpenMP() { openmpDirective_
= false; }
3024 void BeginOpenACC() { openaccDirective_
= true; }
3025 void EndOpenACC() { openaccDirective_
= false; }
3027 // Call back to the traversal framework.
3028 template <typename T
> void Walk(const T
&x
) {
3029 Fortran::parser::Walk(x
, *this);
3032 // Traverse a std::optional<> value. Emit a prefix and/or a suffix string
3033 // only when it contains a value.
3034 template <typename A
>
3036 const char *prefix
, const std::optional
<A
> &x
, const char *suffix
= "") {
3038 Word(prefix
), Walk(*x
), Word(suffix
);
3041 template <typename A
>
3042 void Walk(const std::optional
<A
> &x
, const char *suffix
= "") {
3043 return Walk("", x
, suffix
);
3046 // Traverse a std::list<>. Separate the elements with an optional string.
3047 // Emit a prefix and/or a suffix string only when the list is not empty.
3048 template <typename A
>
3049 void Walk(const char *prefix
, const std::list
<A
> &list
,
3050 const char *comma
= ", ", const char *suffix
= "") {
3051 if (!list
.empty()) {
3052 const char *str
{prefix
};
3053 for (const auto &x
: list
) {
3060 template <typename A
>
3061 void Walk(const std::list
<A
> &list
, const char *comma
= ", ",
3062 const char *suffix
= "") {
3063 return Walk("", list
, comma
, suffix
);
3066 // Traverse a std::tuple<>, with an optional separator.
3067 template <std::size_t J
= 0, typename T
>
3068 void WalkTupleElements(const T
&tuple
, const char *separator
) {
3069 if (J
> 0 && J
< std::tuple_size_v
<T
>) {
3070 Word(separator
); // this usage dodges "unused parameter" warning
3072 if constexpr (J
< std::tuple_size_v
<T
>) {
3073 Walk(std::get
<J
>(tuple
));
3074 WalkTupleElements
<J
+ 1>(tuple
, separator
);
3077 template <typename
... A
>
3078 void Walk(const std::tuple
<A
...> &tuple
, const char *separator
= "") {
3079 WalkTupleElements(tuple
, separator
);
3082 void EndSubprogram(const char *kind
, const std::optional
<Name
> &name
) {
3083 Outdent(), Word("END "), Word(kind
), Walk(" ", name
);
3084 structureComponents_
.clear();
3087 llvm::raw_ostream
&out_
;
3089 const int indentationAmount_
{1};
3091 const int maxColumns_
{80};
3092 std::set
<CharBlock
> structureComponents_
;
3093 Encoding encoding_
{Encoding::UTF_8
};
3094 bool capitalizeKeywords_
{true};
3095 bool openaccDirective_
{false};
3096 bool openmpDirective_
{false};
3097 bool backslashEscapes_
{false};
3098 preStatementType
*preStatement_
{nullptr};
3099 AnalyzedObjectsAsFortran
*asFortran_
{nullptr};
3102 void UnparseVisitor::Put(char ch
) {
3104 if (openmpDirective_
|| openaccDirective_
) {
3111 for (int j
{0}; j
< indent_
; ++j
) {
3114 column_
= indent_
+ 2;
3115 } else if (ch
== '\n') {
3117 } else if (++column_
>= maxColumns_
) {
3119 for (int j
{0}; j
< indent_
; ++j
) {
3122 if (openmpDirective_
) {
3125 } else if (openaccDirective_
) {
3130 column_
= indent_
+ 3;
3134 if (openmpDirective_
|| openaccDirective_
) {
3139 void UnparseVisitor::Put(const char *str
) {
3140 for (; *str
!= '\0'; ++str
) {
3145 void UnparseVisitor::Put(const std::string
&str
) {
3146 for (char ch
: str
) {
3151 void UnparseVisitor::PutNormalized(const std::string
&str
) {
3152 auto decoded
{DecodeString
<std::string
, Encoding::LATIN_1
>(str
, true)};
3153 std::string encoded
{EncodeString
<Encoding::LATIN_1
>(decoded
)};
3154 Put(QuoteCharacterLiteral(encoded
, backslashEscapes_
));
3157 void UnparseVisitor::PutKeywordLetter(char ch
) {
3158 if (capitalizeKeywords_
) {
3159 Put(ToUpperCaseLetter(ch
));
3161 Put(ToLowerCaseLetter(ch
));
3165 void UnparseVisitor::Word(const char *str
) {
3166 for (; *str
!= '\0'; ++str
) {
3167 PutKeywordLetter(*str
);
3171 void UnparseVisitor::Word(const std::string
&str
) { Word(str
.c_str()); }
3173 void UnparseVisitor::Word(const std::string_view
&str
) {
3174 for (std::size_t j
{0}; j
< str
.length(); ++j
) {
3175 PutKeywordLetter(str
[j
]);
3179 template <typename A
>
3180 void Unparse(llvm::raw_ostream
&out
, const A
&root
, Encoding encoding
,
3181 bool capitalizeKeywords
, bool backslashEscapes
,
3182 preStatementType
*preStatement
, AnalyzedObjectsAsFortran
*asFortran
) {
3183 UnparseVisitor visitor
{out
, 1, encoding
, capitalizeKeywords
, backslashEscapes
,
3184 preStatement
, asFortran
};
3185 Walk(root
, visitor
);
3189 template void Unparse
<Program
>(llvm::raw_ostream
&, const Program
&, Encoding
,
3190 bool, bool, preStatementType
*, AnalyzedObjectsAsFortran
*);
3191 template void Unparse
<Expr
>(llvm::raw_ostream
&, const Expr
&, Encoding
, bool,
3192 bool, preStatementType
*, AnalyzedObjectsAsFortran
*);
3193 } // namespace Fortran::parser