1 | //===-- lib/Parser/unparse.cpp --------------------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // Generates Fortran from the content of a parse tree, using the |
10 | // traversal templates in parse-tree-visitor.h. |
11 | |
12 | #include "flang/Parser/unparse.h" |
13 | #include "flang/Common/idioms.h" |
14 | #include "flang/Common/indirection.h" |
15 | #include "flang/Parser/characters.h" |
16 | #include "flang/Parser/parse-tree-visitor.h" |
17 | #include "flang/Parser/parse-tree.h" |
18 | #include "flang/Parser/tools.h" |
19 | #include "flang/Support/Fortran.h" |
20 | #include "flang/Support/LangOptions.h" |
21 | #include "llvm/Support/raw_ostream.h" |
22 | #include <algorithm> |
23 | #include <cinttypes> |
24 | #include <cstddef> |
25 | #include <set> |
26 | |
27 | namespace Fortran::parser { |
28 | |
29 | class UnparseVisitor { |
30 | public: |
31 | UnparseVisitor(llvm::raw_ostream &out, const common::LangOptions &langOpts, |
32 | int indentationAmount, Encoding encoding, bool capitalize, |
33 | bool backslashEscapes, preStatementType *preStatement, |
34 | AnalyzedObjectsAsFortran *asFortran) |
35 | : out_{out}, langOpts_{langOpts}, indentationAmount_{indentationAmount}, |
36 | encoding_{encoding}, capitalizeKeywords_{capitalize}, |
37 | backslashEscapes_{backslashEscapes}, preStatement_{preStatement}, |
38 | asFortran_{asFortran} {} |
39 | |
40 | // In nearly all cases, this code avoids defining Boolean-valued Pre() |
41 | // callbacks for the parse tree walking framework in favor of two void |
42 | // functions, Before() and Unparse(), which imply true and false return |
43 | // values for Pre() respectively. |
44 | template <typename T> void Before(const T &) {} |
45 | template <typename T> double Unparse(const T &); // not void, never used |
46 | |
47 | template <typename T> bool Pre(const T &x) { |
48 | if constexpr (std::is_void_v<decltype(Unparse(x))>) { |
49 | // There is a local definition of Unparse() for this type. It |
50 | // overrides the parse tree walker's default Walk() over the descendents. |
51 | Before(x); |
52 | Unparse(x); |
53 | Post(x); |
54 | return false; // Walk() does not visit descendents |
55 | } else if constexpr (HasTypedExpr<T>::value) { |
56 | // Format the expression representation from semantics |
57 | if (asFortran_ && x.typedExpr) { |
58 | asFortran_->expr(out_, *x.typedExpr); |
59 | return false; |
60 | } else { |
61 | return true; |
62 | } |
63 | } else { |
64 | Before(x); |
65 | return true; // there's no Unparse() defined here, Walk() the descendents |
66 | } |
67 | } |
68 | template <typename T> void Post(const T &) {} |
69 | |
70 | // Emit simple types as-is. |
71 | void Unparse(const std::string &x) { Put(x); } |
72 | void Unparse(int x) { Put(std::to_string(val: x)); } |
73 | void Unparse(unsigned int x) { Put(std::to_string(val: x)); } |
74 | void Unparse(long x) { Put(std::to_string(val: x)); } |
75 | void Unparse(unsigned long x) { Put(std::to_string(val: x)); } |
76 | void Unparse(long long x) { Put(std::to_string(val: x)); } |
77 | void Unparse(unsigned long long x) { Put(std::to_string(val: x)); } |
78 | void Unparse(char x) { Put(x); } |
79 | |
80 | // Statement labels and ends of lines |
81 | template <typename T> void Before(const Statement<T> &x) { |
82 | if (preStatement_) { |
83 | (*preStatement_)(x.source, out_, indent_); |
84 | } |
85 | Walk(x.label, " "); |
86 | } |
87 | template <typename T> void Post(const Statement<T> &) { Put('\n'); } |
88 | |
89 | // The special-case formatting functions for these productions are |
90 | // ordered to correspond roughly to their order of appearance in |
91 | // the Fortran 2018 standard (and parse-tree.h). |
92 | |
93 | void Unparse(const Program &x) { // R501 |
94 | Walk("", x.v, "\n"); // put blank lines between ProgramUnits |
95 | } |
96 | |
97 | void Unparse(const Name &x) { // R603 |
98 | Put(x.ToString()); |
99 | } |
100 | void Unparse(const DefinedOperator::IntrinsicOperator &x) { // R608 |
101 | switch (x) { |
102 | case DefinedOperator::IntrinsicOperator::Power: |
103 | Put("**"); |
104 | break; |
105 | case DefinedOperator::IntrinsicOperator::Multiply: |
106 | Put('*'); |
107 | break; |
108 | case DefinedOperator::IntrinsicOperator::Divide: |
109 | Put('/'); |
110 | break; |
111 | case DefinedOperator::IntrinsicOperator::Add: |
112 | Put('+'); |
113 | break; |
114 | case DefinedOperator::IntrinsicOperator::Subtract: |
115 | Put('-'); |
116 | break; |
117 | case DefinedOperator::IntrinsicOperator::Concat: |
118 | Put("//"); |
119 | break; |
120 | case DefinedOperator::IntrinsicOperator::LT: |
121 | Put('<'); |
122 | break; |
123 | case DefinedOperator::IntrinsicOperator::LE: |
124 | Put("<="); |
125 | break; |
126 | case DefinedOperator::IntrinsicOperator::EQ: |
127 | Put("=="); |
128 | break; |
129 | case DefinedOperator::IntrinsicOperator::NE: |
130 | Put("/="); |
131 | break; |
132 | case DefinedOperator::IntrinsicOperator::GE: |
133 | Put(">="); |
134 | break; |
135 | case DefinedOperator::IntrinsicOperator::GT: |
136 | Put('>'); |
137 | break; |
138 | default: |
139 | Put('.'), Word(DefinedOperator::EnumToString(x)), Put('.'); |
140 | } |
141 | } |
142 | void Post(const Star &) { Put('*'); } // R701 &c. |
143 | void Post(const TypeParamValue::Deferred &) { Put(':'); } // R701 |
144 | void Unparse(const DeclarationTypeSpec::Type &x) { // R703 |
145 | Word("TYPE("), Walk(x.derived), Put(')'); |
146 | } |
147 | void Unparse(const DeclarationTypeSpec::Class &x) { |
148 | Word("CLASS("), Walk(x.derived), Put(')'); |
149 | } |
150 | void Post(const DeclarationTypeSpec::ClassStar &) { Word("CLASS(*)"); } |
151 | void Post(const DeclarationTypeSpec::TypeStar &) { Word("TYPE(*)"); } |
152 | void Unparse(const DeclarationTypeSpec::Record &x) { |
153 | Word("RECORD/"), Walk(x.v), Put('/'); |
154 | } |
155 | void Before(const IntrinsicTypeSpec::Real &) { // R704 |
156 | Word("REAL"); |
157 | } |
158 | void Before(const IntrinsicTypeSpec::Complex &) { Word("COMPLEX"); } |
159 | void Post(const IntrinsicTypeSpec::DoublePrecision &) { |
160 | Word("DOUBLE PRECISION"); |
161 | } |
162 | void Before(const IntrinsicTypeSpec::Character &) { Word("CHARACTER"); } |
163 | void Before(const IntrinsicTypeSpec::Logical &) { Word("LOGICAL"); } |
164 | void Post(const IntrinsicTypeSpec::DoubleComplex &) { |
165 | Word("DOUBLE COMPLEX"); |
166 | } |
167 | void Before(const UnsignedTypeSpec &) { Word("UNSIGNED"); } |
168 | void Before(const IntrinsicVectorTypeSpec &) { Word("VECTOR("); } |
169 | void Post(const IntrinsicVectorTypeSpec &) { Put(')'); } |
170 | void Post(const VectorTypeSpec::PairVectorTypeSpec &) { |
171 | Word("__VECTOR_PAIR"); |
172 | } |
173 | void Post(const VectorTypeSpec::QuadVectorTypeSpec &) { |
174 | Word("__VECTOR_QUAD"); |
175 | } |
176 | void Before(const IntegerTypeSpec &) { // R705 |
177 | Word("INTEGER"); |
178 | } |
179 | void Unparse(const KindSelector &x) { // R706 |
180 | common::visit( |
181 | common::visitors{ |
182 | [&](const ScalarIntConstantExpr &y) { |
183 | Put('('), Word("KIND="), Walk(y), Put(')'); |
184 | }, |
185 | [&](const KindSelector::StarSize &y) { Put('*'), Walk(y.v); }, |
186 | }, |
187 | x.u); |
188 | } |
189 | void Unparse(const SignedIntLiteralConstant &x) { // R707 |
190 | Put(std::get<CharBlock>(x.t).ToString()); |
191 | Walk("_", std::get<std::optional<KindParam>>(x.t)); |
192 | } |
193 | void Unparse(const IntLiteralConstant &x) { // R708 |
194 | Put(std::get<CharBlock>(x.t).ToString()); |
195 | Walk("_", std::get<std::optional<KindParam>>(x.t)); |
196 | } |
197 | void Unparse(const Sign &x) { // R712 |
198 | Put(x == Sign::Negative ? '-' : '+'); |
199 | } |
200 | void Unparse(const RealLiteralConstant &x) { // R714, R715 |
201 | Put(x.real.source.ToString()), Walk("_", x.kind); |
202 | } |
203 | void Unparse(const ComplexLiteralConstant &x) { // R718 - R720 |
204 | Put('('), Walk(x.t, ","), Put(')'); |
205 | } |
206 | void Unparse(const CharSelector::LengthAndKind &x) { // R721 |
207 | Put('('), Word("KIND="), Walk(x.kind); |
208 | Walk(", LEN=", x.length), Put(')'); |
209 | } |
210 | void Unparse(const LengthSelector &x) { // R722 |
211 | common::visit(common::visitors{ |
212 | [&](const TypeParamValue &y) { |
213 | Put('('), Word("LEN="), Walk(y), Put(')'); |
214 | }, |
215 | [&](const CharLength &y) { Put('*'), Walk(y); }, |
216 | }, |
217 | x.u); |
218 | } |
219 | void Unparse(const CharLength &x) { // R723 |
220 | common::visit( |
221 | common::visitors{ |
222 | [&](const TypeParamValue &y) { Put('('), Walk(y), Put(')'); }, |
223 | [&](const std::int64_t &y) { Walk(y); }, |
224 | }, |
225 | x.u); |
226 | } |
227 | void Unparse(const CharLiteralConstant &x) { // R724 |
228 | const auto &str{std::get<std::string>(x.t)}; |
229 | if (const auto &k{std::get<std::optional<KindParam>>(x.t)}) { |
230 | Walk(*k), Put('_'); |
231 | } |
232 | PutNormalized(str); |
233 | } |
234 | void Unparse(const HollerithLiteralConstant &x) { |
235 | auto ucs{DecodeString<std::u32string, Encoding::UTF_8>(x.v, false)}; |
236 | Unparse(ucs.size()); |
237 | Put('H'); |
238 | for (char32_t ch : ucs) { |
239 | EncodedCharacter encoded{EncodeCharacter(encoding_, ch)}; |
240 | for (int j{0}; j < encoded.bytes; ++j) { |
241 | Put(encoded.buffer[j]); |
242 | } |
243 | } |
244 | } |
245 | void Unparse(const LogicalLiteralConstant &x) { // R725 |
246 | Put(std::get<bool>(x.t) ? ".TRUE.": ".FALSE."); |
247 | Walk("_", std::get<std::optional<KindParam>>(x.t)); |
248 | } |
249 | void Unparse(const DerivedTypeStmt &x) { // R727 |
250 | Word("TYPE"), Walk( ", ", std::get<std::list<TypeAttrSpec>>(x.t), ", "); |
251 | Put(" :: "), Walk(std::get<Name>(x.t)); |
252 | Walk("(", std::get<std::list<Name>>(x.t), ", ", ")"); |
253 | Indent(); |
254 | } |
255 | void Unparse(const Abstract &) { // R728, &c. |
256 | Word("ABSTRACT"); |
257 | } |
258 | void Post(const TypeAttrSpec::BindC &) { Word("BIND(C)"); } |
259 | void Unparse(const TypeAttrSpec::Extends &x) { |
260 | Word("EXTENDS("), Walk(x.v), Put(')'); |
261 | } |
262 | void Unparse(const EndTypeStmt &x) { // R730 |
263 | Outdent(), Word("END TYPE"), Walk( " ", x.v); |
264 | } |
265 | void Unparse(const SequenceStmt &) { // R731 |
266 | Word("SEQUENCE"); |
267 | } |
268 | void Unparse(const TypeParamDefStmt &x) { // R732 |
269 | Walk(std::get<IntegerTypeSpec>(x.t)); |
270 | Put(", "), Walk(std::get<common::TypeParamAttr>(x.t)); |
271 | Put(" :: "), Walk(std::get<std::list<TypeParamDecl>>(x.t), ", "); |
272 | } |
273 | void Unparse(const TypeParamDecl &x) { // R733 |
274 | Walk(std::get<Name>(x.t)); |
275 | Walk("=", std::get<std::optional<ScalarIntConstantExpr>>(x.t)); |
276 | } |
277 | void Unparse(const DataComponentDefStmt &x) { // R737 |
278 | const auto &dts{std::get<DeclarationTypeSpec>(x.t)}; |
279 | const auto &attrs{std::get<std::list<ComponentAttrSpec>>(x.t)}; |
280 | const auto &decls{std::get<std::list<ComponentOrFill>>(x.t)}; |
281 | Walk(dts), Walk(", ", attrs, ", "); |
282 | if (!attrs.empty() || |
283 | (!std::holds_alternative<DeclarationTypeSpec::Record>(dts.u) && |
284 | std::none_of( |
285 | decls.begin(), decls.end(), [](const ComponentOrFill &c) { |
286 | return common::visit( |
287 | common::visitors{ |
288 | [](const ComponentDecl &d) { |
289 | const auto &init{ |
290 | std::get<std::optional<Initialization>>(d.t)}; |
291 | return init && |
292 | std::holds_alternative<std::list< |
293 | common::Indirection<DataStmtValue>>>( |
294 | init->u); |
295 | }, |
296 | [](const FillDecl &) { return false; }, |
297 | }, |
298 | c.u); |
299 | }))) { |
300 | Put(" ::"); |
301 | } |
302 | Put(' '), Walk(decls, ", "); |
303 | } |
304 | void Unparse(const Allocatable &) { // R738 |
305 | Word("ALLOCATABLE"); |
306 | } |
307 | void Unparse(const Pointer &) { Word("POINTER"); } |
308 | void Unparse(const Contiguous &) { Word("CONTIGUOUS"); } |
309 | void Before(const ComponentAttrSpec &x) { |
310 | common::visit(common::visitors{ |
311 | [&](const CoarraySpec &) { Word("CODIMENSION["); }, |
312 | [&](const ComponentArraySpec &) { Word("DIMENSION("); }, |
313 | [](const auto &) {}, |
314 | }, |
315 | x.u); |
316 | } |
317 | void Post(const ComponentAttrSpec &x) { |
318 | common::visit(common::visitors{ |
319 | [&](const CoarraySpec &) { Put(']'); }, |
320 | [&](const ComponentArraySpec &) { Put(')'); }, |
321 | [](const auto &) {}, |
322 | }, |
323 | x.u); |
324 | } |
325 | void Unparse(const ComponentDecl &x) { // R739 |
326 | Walk(std::get<ObjectName>(x.t)); |
327 | Walk("(", std::get<std::optional<ComponentArraySpec>>(x.t), ")"); |
328 | Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]"); |
329 | Walk("*", std::get<std::optional<CharLength>>(x.t)); |
330 | Walk(std::get<std::optional<Initialization>>(x.t)); |
331 | } |
332 | void Unparse(const FillDecl &x) { // DEC extension |
333 | Put("%FILL"); |
334 | Walk("(", std::get<std::optional<ComponentArraySpec>>(x.t), ")"); |
335 | Walk("*", std::get<std::optional<CharLength>>(x.t)); |
336 | } |
337 | void Unparse(const ComponentArraySpec &x) { // R740 |
338 | common::visit( |
339 | common::visitors{ |
340 | [&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); }, |
341 | [&](const DeferredShapeSpecList &y) { Walk(y); }, |
342 | }, |
343 | x.u); |
344 | } |
345 | void Unparse(const ProcComponentDefStmt &x) { // R741 |
346 | Word("PROCEDURE("); |
347 | Walk(std::get<std::optional<ProcInterface>>(x.t)), Put(')'); |
348 | Walk(", ", std::get<std::list<ProcComponentAttrSpec>>(x.t), ", "); |
349 | Put(" :: "), Walk(std::get<std::list<ProcDecl>>(x.t), ", "); |
350 | } |
351 | void Unparse(const NoPass &) { // R742 |
352 | Word("NOPASS"); |
353 | } |
354 | void Unparse(const Pass &x) { Word("PASS"), Walk( "(", x.v, ")"); } |
355 | void Unparse(const Initialization &x) { // R743 & R805 |
356 | common::visit( |
357 | common::visitors{ |
358 | [&](const ConstantExpr &y) { Put(" = "), Walk(y); }, |
359 | [&](const NullInit &y) { Put(" => "), Walk(y); }, |
360 | [&](const InitialDataTarget &y) { Put(" => "), Walk(y); }, |
361 | [&](const std::list<common::Indirection<DataStmtValue>> &y) { |
362 | Walk("/", y, ", ", "/"); |
363 | }, |
364 | }, |
365 | x.u); |
366 | } |
367 | void Unparse(const PrivateStmt &) { // R745 |
368 | Word("PRIVATE"); |
369 | } |
370 | void Unparse(const TypeBoundProcedureStmt::WithoutInterface &x) { // R749 |
371 | Word("PROCEDURE"), Walk( ", ", x.attributes, ", "); |
372 | Put(" :: "), Walk(x.declarations, ", "); |
373 | } |
374 | void Unparse(const TypeBoundProcedureStmt::WithInterface &x) { |
375 | Word("PROCEDURE("), Walk(x.interfaceName), Put( "), "); |
376 | Walk(x.attributes); |
377 | Put(" :: "), Walk(x.bindingNames, ", "); |
378 | } |
379 | void Unparse(const TypeBoundProcDecl &x) { // R750 |
380 | Walk(std::get<Name>(x.t)); |
381 | Walk(" => ", std::get<std::optional<Name>>(x.t)); |
382 | } |
383 | void Unparse(const TypeBoundGenericStmt &x) { // R751 |
384 | Word("GENERIC"), Walk( ", ", std::get<std::optional<AccessSpec>>(x.t)); |
385 | Put(" :: "), Walk(std::get<common::Indirection<GenericSpec>>(x.t)); |
386 | Put(" => "), Walk(std::get<std::list<Name>>(x.t), ", "); |
387 | } |
388 | void Post(const BindAttr::Deferred &) { Word("DEFERRED"); } // R752 |
389 | void Post(const BindAttr::Non_Overridable &) { Word("NON_OVERRIDABLE"); } |
390 | void Unparse(const FinalProcedureStmt &x) { // R753 |
391 | Word("FINAL :: "), Walk(x.v, ", "); |
392 | } |
393 | void Unparse(const DerivedTypeSpec &x) { // R754 |
394 | Walk(std::get<Name>(x.t)); |
395 | Walk("(", std::get<std::list<TypeParamSpec>>(x.t), ",", ")"); |
396 | } |
397 | void Unparse(const TypeParamSpec &x) { // R755 |
398 | Walk(std::get<std::optional<Keyword>>(x.t), "="); |
399 | Walk(std::get<TypeParamValue>(x.t)); |
400 | } |
401 | void Unparse(const StructureConstructor &x) { // R756 |
402 | Walk(std::get<DerivedTypeSpec>(x.t)); |
403 | Put('('), Walk(std::get<std::list<ComponentSpec>>(x.t), ", "), Put(')'); |
404 | } |
405 | void Unparse(const ComponentSpec &x) { // R757 |
406 | Walk(std::get<std::optional<Keyword>>(x.t), "="); |
407 | Walk(std::get<ComponentDataSource>(x.t)); |
408 | } |
409 | void Unparse(const EnumDefStmt &) { // R760 |
410 | Word("ENUM, BIND(C)"), Indent(); |
411 | } |
412 | void Unparse(const EnumeratorDefStmt &x) { // R761 |
413 | Word("ENUMERATOR :: "), Walk(x.v, ", "); |
414 | } |
415 | void Unparse(const Enumerator &x) { // R762 |
416 | Walk(std::get<NamedConstant>(x.t)); |
417 | Walk(" = ", std::get<std::optional<ScalarIntConstantExpr>>(x.t)); |
418 | } |
419 | void Post(const EndEnumStmt &) { // R763 |
420 | Outdent(), Word("END ENUM"); |
421 | } |
422 | void Unparse(const BOZLiteralConstant &x) { // R764 - R767 |
423 | Put(x.v); |
424 | } |
425 | void Unparse(const AcValue::Triplet &x) { // R773 |
426 | Walk(std::get<0>(x.t)), Put(':'), Walk(std::get<1>(x.t)); |
427 | Walk(":", std::get<std::optional<ScalarIntExpr>>(x.t)); |
428 | } |
429 | void Unparse(const ArrayConstructor &x) { // R769 |
430 | Put('['), Walk(x.v), Put(']'); |
431 | } |
432 | void Unparse(const AcSpec &x) { // R770 |
433 | Walk(x.type, "::"), Walk(x.values, ", "); |
434 | } |
435 | template <typename A, typename B> void Unparse(const LoopBounds<A, B> &x) { |
436 | Walk(x.name), Put('='), Walk(x.lower), Put(','), Walk(x.upper); |
437 | Walk(",", x.step); |
438 | } |
439 | void Unparse(const AcImpliedDo &x) { // R774 |
440 | Put('('), Walk(std::get<std::list<AcValue>>(x.t), ", "); |
441 | Put(", "), Walk(std::get<AcImpliedDoControl>(x.t)), Put(')'); |
442 | } |
443 | void Unparse(const AcImpliedDoControl &x) { // R775 |
444 | Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::"); |
445 | Walk(std::get<AcImpliedDoControl::Bounds>(x.t)); |
446 | } |
447 | |
448 | void Unparse(const TypeDeclarationStmt &x) { // R801 |
449 | const auto &dts{std::get<DeclarationTypeSpec>(x.t)}; |
450 | const auto &attrs{std::get<std::list<AttrSpec>>(x.t)}; |
451 | const auto &decls{std::get<std::list<EntityDecl>>(x.t)}; |
452 | Walk(dts), Walk(", ", attrs, ", "); |
453 | |
454 | static const auto isInitializerOldStyle{[](const Initialization &i) { |
455 | return std::holds_alternative< |
456 | std::list<common::Indirection<DataStmtValue>>>(i.u); |
457 | }}; |
458 | static const auto hasAssignmentInitializer{[](const EntityDecl &d) { |
459 | // Does a declaration have a new-style =x initializer? |
460 | const auto &init{std::get<std::optional<Initialization>>(d.t)}; |
461 | return init && !isInitializerOldStyle(*init); |
462 | }}; |
463 | static const auto hasSlashDelimitedInitializer{[](const EntityDecl &d) { |
464 | // Does a declaration have an old-style /x/ initializer? |
465 | const auto &init{std::get<std::optional<Initialization>>(d.t)}; |
466 | return init && isInitializerOldStyle(*init); |
467 | }}; |
468 | const auto useDoubledColons{[&]() { |
469 | bool isRecord{std::holds_alternative<DeclarationTypeSpec::Record>(dts.u)}; |
470 | if (!attrs.empty()) { |
471 | // Attributes after the type require :: before the entities. |
472 | CHECK(!isRecord); |
473 | return true; |
474 | } |
475 | if (std::any_of(decls.begin(), decls.end(), hasAssignmentInitializer)) { |
476 | // Always use :: with new style standard initializers (=x), |
477 | // since the standard requires them to appear (even in free form, |
478 | // where mandatory spaces already disambiguate INTEGER J=666). |
479 | CHECK(!isRecord); |
480 | return true; |
481 | } |
482 | if (isRecord) { |
483 | // Never put :: in a legacy extension RECORD// statement. |
484 | return false; |
485 | } |
486 | // The :: is optional for this declaration. Avoid usage that can |
487 | // crash the pgf90 compiler. |
488 | if (std::any_of( |
489 | decls.begin(), decls.end(), hasSlashDelimitedInitializer)) { |
490 | // Don't use :: when a declaration uses legacy DATA-statement-like |
491 | // /x/ initialization. |
492 | return false; |
493 | } |
494 | // Don't use :: with intrinsic types. Otherwise, use it. |
495 | return !std::holds_alternative<IntrinsicTypeSpec>(dts.u); |
496 | }}; |
497 | |
498 | if (useDoubledColons()) { |
499 | Put(" ::"); |
500 | } |
501 | Put(' '), Walk(std::get<std::list<EntityDecl>>(x.t), ", "); |
502 | } |
503 | void Before(const AttrSpec &x) { // R802 |
504 | common::visit(common::visitors{ |
505 | [&](const CoarraySpec &) { Word("CODIMENSION["); }, |
506 | [&](const ArraySpec &) { Word("DIMENSION("); }, |
507 | [](const auto &) {}, |
508 | }, |
509 | x.u); |
510 | } |
511 | void Post(const AttrSpec &x) { |
512 | common::visit(common::visitors{ |
513 | [&](const CoarraySpec &) { Put(']'); }, |
514 | [&](const ArraySpec &) { Put(')'); }, |
515 | [](const auto &) {}, |
516 | }, |
517 | x.u); |
518 | } |
519 | void Unparse(const EntityDecl &x) { // R803 |
520 | Walk(std::get<ObjectName>(x.t)); |
521 | Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"); |
522 | Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]"); |
523 | Walk("*", std::get<std::optional<CharLength>>(x.t)); |
524 | Walk(std::get<std::optional<Initialization>>(x.t)); |
525 | } |
526 | void Unparse(const NullInit &) { // R806 |
527 | Word("NULL()"); |
528 | } |
529 | void Unparse(const LanguageBindingSpec &x) { // R808 & R1528 |
530 | Word("BIND(C"); |
531 | Walk( |
532 | ", NAME=", std::get<std::optional<ScalarDefaultCharConstantExpr>>(x.t)); |
533 | if (std::get<bool>(x.t)) { |
534 | Word(", CDEFINED"); |
535 | } |
536 | Put(')'); |
537 | } |
538 | void Unparse(const CoarraySpec &x) { // R809 |
539 | common::visit(common::visitors{ |
540 | [&](const DeferredCoshapeSpecList &y) { Walk(y); }, |
541 | [&](const ExplicitCoshapeSpec &y) { Walk(y); }, |
542 | }, |
543 | x.u); |
544 | } |
545 | void Unparse(const DeferredCoshapeSpecList &x) { // R810 |
546 | for (auto j{x.v}; j > 0; --j) { |
547 | Put(':'); |
548 | if (j > 1) { |
549 | Put(','); |
550 | } |
551 | } |
552 | } |
553 | void Unparse(const ExplicitCoshapeSpec &x) { // R811 |
554 | Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ","); |
555 | Walk(std::get<std::optional<SpecificationExpr>>(x.t), ":"), Put('*'); |
556 | } |
557 | void Unparse(const ExplicitShapeSpec &x) { // R812 - R813 & R816 - R818 |
558 | Walk(std::get<std::optional<SpecificationExpr>>(x.t), ":"); |
559 | Walk(std::get<SpecificationExpr>(x.t)); |
560 | } |
561 | void Unparse(const ArraySpec &x) { // R815 |
562 | common::visit( |
563 | common::visitors{ |
564 | [&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); }, |
565 | [&](const std::list<AssumedShapeSpec> &y) { Walk(y, ","); }, |
566 | [&](const DeferredShapeSpecList &y) { Walk(y); }, |
567 | [&](const AssumedSizeSpec &y) { Walk(y); }, |
568 | [&](const ImpliedShapeSpec &y) { Walk(y); }, |
569 | [&](const AssumedRankSpec &y) { Walk(y); }, |
570 | }, |
571 | x.u); |
572 | } |
573 | void Post(const AssumedShapeSpec &) { Put(':'); } // R819 |
574 | void Unparse(const DeferredShapeSpecList &x) { // R820 |
575 | for (auto j{x.v}; j > 0; --j) { |
576 | Put(':'); |
577 | if (j > 1) { |
578 | Put(','); |
579 | } |
580 | } |
581 | } |
582 | void Unparse(const AssumedImpliedSpec &x) { // R821 |
583 | Walk(x.v, ":"); |
584 | Put('*'); |
585 | } |
586 | void Unparse(const AssumedSizeSpec &x) { // R822 |
587 | Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ","); |
588 | Walk(std::get<AssumedImpliedSpec>(x.t)); |
589 | } |
590 | void Unparse(const ImpliedShapeSpec &x) { // R823 |
591 | Walk(x.v, ","); |
592 | } |
593 | void Post(const AssumedRankSpec &) { Put(".."); } // R825 |
594 | void Post(const Asynchronous &) { Word("ASYNCHRONOUS"); } |
595 | void Post(const External &) { Word("EXTERNAL"); } |
596 | void Post(const Intrinsic &) { Word("INTRINSIC"); } |
597 | void Post(const Optional &) { Word("OPTIONAL"); } |
598 | void Post(const Parameter &) { Word("PARAMETER"); } |
599 | void Post(const Protected &) { Word("PROTECTED"); } |
600 | void Post(const Save &) { Word("SAVE"); } |
601 | void Post(const Target &) { Word("TARGET"); } |
602 | void Post(const Value &) { Word("VALUE"); } |
603 | void Post(const Volatile &) { Word("VOLATILE"); } |
604 | void Unparse(const IntentSpec &x) { // R826 |
605 | Word("INTENT("), Walk(x.v), Put( ")"); |
606 | } |
607 | void Unparse(const AccessStmt &x) { // R827 |
608 | Walk(std::get<AccessSpec>(x.t)); |
609 | Walk(" :: ", std::get<std::list<AccessId>>(x.t), ", "); |
610 | } |
611 | void Unparse(const AllocatableStmt &x) { // R829 |
612 | Word("ALLOCATABLE :: "), Walk(x.v, ", "); |
613 | } |
614 | void Unparse(const ObjectDecl &x) { // R830 & R860 |
615 | Walk(std::get<ObjectName>(x.t)); |
616 | Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"); |
617 | Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]"); |
618 | } |
619 | void Unparse(const AsynchronousStmt &x) { // R831 |
620 | Word("ASYNCHRONOUS :: "), Walk(x.v, ", "); |
621 | } |
622 | void Unparse(const BindStmt &x) { // R832 |
623 | Walk(x.t, " :: "); |
624 | } |
625 | void Unparse(const BindEntity &x) { // R833 |
626 | bool isCommon{std::get<BindEntity::Kind>(x.t) == BindEntity::Kind::Common}; |
627 | const char *slash{isCommon ? "/": ""}; |
628 | Put(slash), Walk(std::get<Name>(x.t)), Put(slash); |
629 | } |
630 | void Unparse(const CodimensionStmt &x) { // R834 |
631 | Word("CODIMENSION :: "), Walk(x.v, ", "); |
632 | } |
633 | void Unparse(const CodimensionDecl &x) { // R835 |
634 | Walk(std::get<Name>(x.t)); |
635 | Put('['), Walk(std::get<CoarraySpec>(x.t)), Put(']'); |
636 | } |
637 | void Unparse(const ContiguousStmt &x) { // R836 |
638 | Word("CONTIGUOUS :: "), Walk(x.v, ", "); |
639 | } |
640 | void Unparse(const DataStmt &x) { // R837 |
641 | Word("DATA "), Walk(x.v, ", "); |
642 | } |
643 | void Unparse(const DataStmtSet &x) { // R838 |
644 | Walk(std::get<std::list<DataStmtObject>>(x.t), ", "); |
645 | Put('/'), Walk(std::get<std::list<DataStmtValue>>(x.t), ", "), Put('/'); |
646 | } |
647 | void Unparse(const DataImpliedDo &x) { // R840, R842 |
648 | Put('('), Walk(std::get<std::list<DataIDoObject>>(x.t), ", "), Put(','); |
649 | Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::"); |
650 | Walk(std::get<DataImpliedDo::Bounds>(x.t)), Put(')'); |
651 | } |
652 | void Unparse(const DataStmtValue &x) { // R843 |
653 | Walk(std::get<std::optional<DataStmtRepeat>>(x.t), "*"); |
654 | Walk(std::get<DataStmtConstant>(x.t)); |
655 | } |
656 | void Unparse(const DimensionStmt &x) { // R848 |
657 | Word("DIMENSION :: "), Walk(x.v, ", "); |
658 | } |
659 | void Unparse(const DimensionStmt::Declaration &x) { |
660 | Walk(std::get<Name>(x.t)); |
661 | Put('('), Walk(std::get<ArraySpec>(x.t)), Put(')'); |
662 | } |
663 | void Unparse(const IntentStmt &x) { // R849 |
664 | Walk(x.t, " :: "); |
665 | } |
666 | void Unparse(const OptionalStmt &x) { // R850 |
667 | Word("OPTIONAL :: "), Walk(x.v, ", "); |
668 | } |
669 | void Unparse(const ParameterStmt &x) { // R851 |
670 | Word("PARAMETER("), Walk(x.v, ", "), Put(')'); |
671 | } |
672 | void Unparse(const NamedConstantDef &x) { // R852 |
673 | Walk(x.t, "="); |
674 | } |
675 | void Unparse(const PointerStmt &x) { // R853 |
676 | Word("POINTER :: "), Walk(x.v, ", "); |
677 | } |
678 | void Unparse(const PointerDecl &x) { // R854 |
679 | Walk(std::get<Name>(x.t)); |
680 | Walk("(", std::get<std::optional<DeferredShapeSpecList>>(x.t), ")"); |
681 | } |
682 | void Unparse(const ProtectedStmt &x) { // R855 |
683 | Word("PROTECTED :: "), Walk(x.v, ", "); |
684 | } |
685 | void Unparse(const SaveStmt &x) { // R856 |
686 | Word("SAVE"), Walk( " :: ", x.v, ", "); |
687 | } |
688 | void Unparse(const SavedEntity &x) { // R857, R858 |
689 | bool isCommon{ |
690 | std::get<SavedEntity::Kind>(x.t) == SavedEntity::Kind::Common}; |
691 | const char *slash{isCommon ? "/": ""}; |
692 | Put(slash), Walk(std::get<Name>(x.t)), Put(slash); |
693 | } |
694 | void Unparse(const TargetStmt &x) { // R859 |
695 | Word("TARGET :: "), Walk(x.v, ", "); |
696 | } |
697 | void Unparse(const ValueStmt &x) { // R861 |
698 | Word("VALUE :: "), Walk(x.v, ", "); |
699 | } |
700 | void Unparse(const VolatileStmt &x) { // R862 |
701 | Word("VOLATILE :: "), Walk(x.v, ", "); |
702 | } |
703 | void Unparse(const ImplicitStmt &x) { // R863 |
704 | Word("IMPLICIT "); |
705 | common::visit( |
706 | common::visitors{ |
707 | [&](const std::list<ImplicitSpec> &y) { Walk(y, ", "); }, |
708 | [&](const std::list<ImplicitStmt::ImplicitNoneNameSpec> &y) { |
709 | Word("NONE"), Walk( " (", y, ", ", ")"); |
710 | }, |
711 | }, |
712 | x.u); |
713 | } |
714 | void Unparse(const ImplicitSpec &x) { // R864 |
715 | Walk(std::get<DeclarationTypeSpec>(x.t)); |
716 | Put('('), Walk(std::get<std::list<LetterSpec>>(x.t), ", "), Put(')'); |
717 | } |
718 | void Unparse(const LetterSpec &x) { // R865 |
719 | Put(*std::get<const char *>(x.t)); |
720 | auto second{std::get<std::optional<const char *>>(x.t)}; |
721 | if (second) { |
722 | Put('-'), Put(**second); |
723 | } |
724 | } |
725 | void Unparse(const ImportStmt &x) { // R867 |
726 | Word("IMPORT"); |
727 | switch (x.kind) { |
728 | case common::ImportKind::Default: |
729 | Walk(" :: ", x.names, ", "); |
730 | break; |
731 | case common::ImportKind::Only: |
732 | Put(", "), Word( "ONLY: "); |
733 | Walk(x.names, ", "); |
734 | break; |
735 | case common::ImportKind::None: |
736 | Word(", NONE"); |
737 | break; |
738 | case common::ImportKind::All: |
739 | Word(", ALL"); |
740 | break; |
741 | } |
742 | } |
743 | void Unparse(const NamelistStmt &x) { // R868 |
744 | Word("NAMELIST"), Walk(x.v, ", "); |
745 | } |
746 | void Unparse(const NamelistStmt::Group &x) { |
747 | Put('/'), Walk(std::get<Name>(x.t)), Put('/'); |
748 | Walk(std::get<std::list<Name>>(x.t), ", "); |
749 | } |
750 | void Unparse(const EquivalenceStmt &x) { // R870, R871 |
751 | Word("EQUIVALENCE"); |
752 | const char *separator{" "}; |
753 | for (const std::list<EquivalenceObject> &y : x.v) { |
754 | Put(separator), Put('('), Walk(y), Put(')'); |
755 | separator = ", "; |
756 | } |
757 | } |
758 | void Unparse(const CommonStmt &x) { // R873 |
759 | Word("COMMON "); |
760 | Walk(x.blocks); |
761 | } |
762 | void Unparse(const CommonBlockObject &x) { // R874 |
763 | Walk(std::get<Name>(x.t)); |
764 | Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"); |
765 | } |
766 | void Unparse(const CommonStmt::Block &x) { |
767 | Word("/"), Walk(std::get<std::optional<Name>>(x.t)), Word( "/"); |
768 | Walk(std::get<std::list<CommonBlockObject>>(x.t)); |
769 | } |
770 | |
771 | void Unparse(const Substring &x) { // R908, R909 |
772 | Walk(std::get<DataRef>(x.t)); |
773 | Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')'); |
774 | } |
775 | void Unparse(const CharLiteralConstantSubstring &x) { |
776 | Walk(std::get<CharLiteralConstant>(x.t)); |
777 | Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')'); |
778 | } |
779 | void Unparse(const SubstringInquiry &x) { |
780 | Walk(x.v); |
781 | Put(x.source.end()[-1] == 'n' ? "%LEN": "%KIND"); |
782 | } |
783 | void Unparse(const SubstringRange &x) { // R910 |
784 | Walk(x.t, ":"); |
785 | } |
786 | void Unparse(const PartRef &x) { // R912 |
787 | Walk(x.name); |
788 | Walk("(", x.subscripts, ",", ")"); |
789 | Walk(x.imageSelector); |
790 | } |
791 | void Unparse(const StructureComponent &x) { // R913 |
792 | Walk(x.base); |
793 | if (structureComponents_.find(x.component.source) != |
794 | structureComponents_.end()) { |
795 | Put('.'); |
796 | } else { |
797 | Put('%'); |
798 | } |
799 | Walk(x.component); |
800 | } |
801 | void Unparse(const ArrayElement &x) { // R917 |
802 | Walk(x.base); |
803 | Put('('), Walk(x.subscripts, ","), Put(')'); |
804 | } |
805 | void Unparse(const SubscriptTriplet &x) { // R921 |
806 | Walk(std::get<0>(x.t)), Put(':'), Walk(std::get<1>(x.t)); |
807 | Walk(":", std::get<2>(x.t)); |
808 | } |
809 | void Unparse(const ImageSelector &x) { // R924 |
810 | Put('['), Walk(std::get<std::list<Cosubscript>>(x.t), ","); |
811 | Walk(",", std::get<std::list<ImageSelectorSpec>>(x.t), ","), Put(']'); |
812 | } |
813 | void Before(const ImageSelectorSpec::Stat &) { // R926 |
814 | Word("STAT="); |
815 | } |
816 | void Before(const ImageSelectorSpec::Team_Number &) { Word("TEAM_NUMBER="); } |
817 | void Before(const ImageSelectorSpec &x) { |
818 | if (std::holds_alternative<TeamValue>(x.u)) { |
819 | Word("TEAM="); |
820 | } |
821 | } |
822 | void Unparse(const AllocateStmt &x) { // R927 |
823 | Word("ALLOCATE("); |
824 | Walk(std::get<std::optional<TypeSpec>>(x.t), "::"); |
825 | Walk(std::get<std::list<Allocation>>(x.t), ", "); |
826 | Walk(", ", std::get<std::list<AllocOpt>>(x.t), ", "), Put(')'); |
827 | } |
828 | void Before(const AllocOpt &x) { // R928, R931 |
829 | common::visit(common::visitors{ |
830 | [&](const AllocOpt::Mold &) { Word("MOLD="); }, |
831 | [&](const AllocOpt::Source &) { Word("SOURCE="); }, |
832 | [&](const AllocOpt::Stream &) { Word("STREAM="); }, |
833 | [&](const AllocOpt::Pinned &) { Word("PINNED="); }, |
834 | [](const StatOrErrmsg &) {}, |
835 | }, |
836 | x.u); |
837 | } |
838 | void Unparse(const Allocation &x) { // R932 |
839 | Walk(std::get<AllocateObject>(x.t)); |
840 | Walk("(", std::get<std::list<AllocateShapeSpec>>(x.t), ",", ")"); |
841 | Walk("[", std::get<std::optional<AllocateCoarraySpec>>(x.t), "]"); |
842 | } |
843 | void Unparse(const AllocateShapeSpec &x) { // R934 & R938 |
844 | Walk(std::get<std::optional<BoundExpr>>(x.t), ":"); |
845 | Walk(std::get<BoundExpr>(x.t)); |
846 | } |
847 | void Unparse(const AllocateCoarraySpec &x) { // R937 |
848 | Walk(std::get<std::list<AllocateCoshapeSpec>>(x.t), ",", ","); |
849 | Walk(std::get<std::optional<BoundExpr>>(x.t), ":"), Put('*'); |
850 | } |
851 | void Unparse(const NullifyStmt &x) { // R939 |
852 | Word("NULLIFY("), Walk(x.v, ", "), Put(')'); |
853 | } |
854 | void Unparse(const DeallocateStmt &x) { // R941 |
855 | Word("DEALLOCATE("); |
856 | Walk(std::get<std::list<AllocateObject>>(x.t), ", "); |
857 | Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); |
858 | } |
859 | void Before(const StatOrErrmsg &x) { // R942 & R1165 |
860 | common::visit(common::visitors{ |
861 | [&](const StatVariable &) { Word("STAT="); }, |
862 | [&](const MsgVariable &) { Word("ERRMSG="); }, |
863 | }, |
864 | x.u); |
865 | } |
866 | |
867 | // R1001 - R1022 |
868 | void Unparse(const Expr::Parentheses &x) { Put('('), Walk(x.v), Put(')'); } |
869 | void Before(const Expr::UnaryPlus &) { Put("+"); } |
870 | void Before(const Expr::Negate &) { Put("-"); } |
871 | void Before(const Expr::NOT &) { Word(".NOT."); } |
872 | void Unparse(const Expr::PercentLoc &x) { |
873 | Word("%LOC("), Walk(x.v), Put(')'); |
874 | } |
875 | void Unparse(const Expr::Power &x) { Walk(x.t, "**"); } |
876 | void Unparse(const Expr::Multiply &x) { Walk(x.t, "*"); } |
877 | void Unparse(const Expr::Divide &x) { Walk(x.t, "/"); } |
878 | void Unparse(const Expr::Add &x) { Walk(x.t, "+"); } |
879 | void Unparse(const Expr::Subtract &x) { Walk(x.t, "-"); } |
880 | void Unparse(const Expr::Concat &x) { Walk(x.t, "//"); } |
881 | void Unparse(const Expr::LT &x) { Walk(x.t, "<"); } |
882 | void Unparse(const Expr::LE &x) { Walk(x.t, "<="); } |
883 | void Unparse(const Expr::EQ &x) { Walk(x.t, "=="); } |
884 | void Unparse(const Expr::NE &x) { Walk(x.t, "/="); } |
885 | void Unparse(const Expr::GE &x) { Walk(x.t, ">="); } |
886 | void Unparse(const Expr::GT &x) { Walk(x.t, ">"); } |
887 | void Unparse(const Expr::AND &x) { Walk(x.t, ".AND."); } |
888 | void Unparse(const Expr::OR &x) { Walk(x.t, ".OR."); } |
889 | void Unparse(const Expr::EQV &x) { Walk(x.t, ".EQV."); } |
890 | void Unparse(const Expr::NEQV &x) { Walk(x.t, ".NEQV."); } |
891 | void Unparse(const Expr::ComplexConstructor &x) { |
892 | Put('('), Walk(x.t, ","), Put(')'); |
893 | } |
894 | void Unparse(const Expr::DefinedBinary &x) { |
895 | Walk(std::get<1>(x.t)); // left |
896 | Walk(std::get<DefinedOpName>(x.t)); |
897 | Walk(std::get<2>(x.t)); // right |
898 | } |
899 | void Unparse(const DefinedOpName &x) { // R1003, R1023, R1414, & R1415 |
900 | Walk(x.v); |
901 | } |
902 | void Unparse(const AssignmentStmt &x) { // R1032 |
903 | if (asFortran_ && x.typedAssignment.get()) { |
904 | Put(' '); |
905 | asFortran_->assignment(out_, *x.typedAssignment); |
906 | Put('\n'); |
907 | } else { |
908 | Walk(x.t, " = "); |
909 | } |
910 | } |
911 | void Unparse(const PointerAssignmentStmt &x) { // R1033, R1034, R1038 |
912 | if (asFortran_ && x.typedAssignment.get()) { |
913 | Put(' '); |
914 | asFortran_->assignment(out_, *x.typedAssignment); |
915 | Put('\n'); |
916 | } else { |
917 | Walk(std::get<DataRef>(x.t)); |
918 | common::visit( |
919 | common::visitors{ |
920 | [&](const std::list<BoundsRemapping> &y) { |
921 | Put('('), Walk(y), Put(')'); |
922 | }, |
923 | [&](const std::list<BoundsSpec> &y) { Walk("(", y, ", ", ")"); }, |
924 | }, |
925 | std::get<PointerAssignmentStmt::Bounds>(x.t).u); |
926 | Put(" => "), Walk(std::get<Expr>(x.t)); |
927 | } |
928 | } |
929 | void Post(const BoundsSpec &) { // R1035 |
930 | Put(':'); |
931 | } |
932 | void Unparse(const BoundsRemapping &x) { // R1036 |
933 | Walk(x.t, ":"); |
934 | } |
935 | void Unparse(const WhereStmt &x) { // R1041, R1045, R1046 |
936 | Word("WHERE ("), Walk(x.t, ") "); |
937 | } |
938 | void Unparse(const WhereConstructStmt &x) { // R1043 |
939 | Walk(std::get<std::optional<Name>>(x.t), ": "); |
940 | Word("WHERE ("), Walk(std::get<LogicalExpr>(x.t)), Put(')'); |
941 | Indent(); |
942 | } |
943 | void Unparse(const MaskedElsewhereStmt &x) { // R1047 |
944 | Outdent(); |
945 | Word("ELSEWHERE ("), Walk(std::get<LogicalExpr>(x.t)), Put(')'); |
946 | Walk(" ", std::get<std::optional<Name>>(x.t)); |
947 | Indent(); |
948 | } |
949 | void Unparse(const ElsewhereStmt &x) { // R1048 |
950 | Outdent(), Word("ELSEWHERE"), Walk( " ", x.v), Indent(); |
951 | } |
952 | void Unparse(const EndWhereStmt &x) { // R1049 |
953 | Outdent(), Word("END WHERE"), Walk( " ", x.v); |
954 | } |
955 | void Unparse(const ForallConstructStmt &x) { // R1051 |
956 | Walk(std::get<std::optional<Name>>(x.t), ": "); |
957 | Word("FORALL"), Walk(std::get<common::Indirection<ConcurrentHeader>>(x.t)); |
958 | Indent(); |
959 | } |
960 | void Unparse(const EndForallStmt &x) { // R1054 |
961 | Outdent(), Word("END FORALL"), Walk( " ", x.v); |
962 | } |
963 | void Before(const ForallStmt &) { // R1055 |
964 | Word("FORALL"); |
965 | } |
966 | |
967 | void Unparse(const AssociateStmt &x) { // R1103 |
968 | Walk(std::get<std::optional<Name>>(x.t), ": "); |
969 | Word("ASSOCIATE ("); |
970 | Walk(std::get<std::list<Association>>(x.t), ", "), Put(')'), Indent(); |
971 | } |
972 | void Unparse(const Association &x) { // R1104 |
973 | Walk(x.t, " => "); |
974 | } |
975 | void Unparse(const EndAssociateStmt &x) { // R1106 |
976 | Outdent(), Word("END ASSOCIATE"), Walk( " ", x.v); |
977 | } |
978 | void Unparse(const BlockStmt &x) { // R1108 |
979 | Walk(x.v, ": "), Word( "BLOCK"), Indent(); |
980 | } |
981 | void Unparse(const EndBlockStmt &x) { // R1110 |
982 | Outdent(), Word("END BLOCK"), Walk( " ", x.v); |
983 | } |
984 | void Unparse(const ChangeTeamStmt &x) { // R1112 |
985 | Walk(std::get<std::optional<Name>>(x.t), ": "); |
986 | Word("CHANGE TEAM ("), Walk(std::get<TeamValue>(x.t)); |
987 | Walk(", ", std::get<std::list<CoarrayAssociation>>(x.t), ", "); |
988 | Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); |
989 | Indent(); |
990 | } |
991 | void Unparse(const CoarrayAssociation &x) { // R1113 |
992 | Walk(x.t, " => "); |
993 | } |
994 | void Unparse(const EndChangeTeamStmt &x) { // R1114 |
995 | Outdent(), Word("END TEAM ("); |
996 | Walk(std::get<std::list<StatOrErrmsg>>(x.t), ", "); |
997 | Put(')'), Walk(" ", std::get<std::optional<Name>>(x.t)); |
998 | } |
999 | void Unparse(const CriticalStmt &x) { // R1117 |
1000 | Walk(std::get<std::optional<Name>>(x.t), ": "); |
1001 | Word("CRITICAL ("), Walk(std::get<std::list<StatOrErrmsg>>(x.t), ", "); |
1002 | Put(')'), Indent(); |
1003 | } |
1004 | void Unparse(const EndCriticalStmt &x) { // R1118 |
1005 | Outdent(), Word("END CRITICAL"), Walk( " ", x.v); |
1006 | } |
1007 | void Unparse(const DoConstruct &x) { // R1119, R1120 |
1008 | Walk(std::get<Statement<NonLabelDoStmt>>(x.t)); |
1009 | Indent(), Walk(std::get<Block>(x.t), ""), Outdent(); |
1010 | Walk(std::get<Statement<EndDoStmt>>(x.t)); |
1011 | } |
1012 | void Unparse(const LabelDoStmt &x) { // R1121 |
1013 | Word("DO "), Walk(std::get<Label>(x.t)); |
1014 | Walk(" ", std::get<std::optional<LoopControl>>(x.t)); |
1015 | } |
1016 | void Unparse(const NonLabelDoStmt &x) { // R1122 |
1017 | Walk(std::get<std::optional<Name>>(x.t), ": "); |
1018 | Word("DO "); |
1019 | Walk(std::get<std::optional<Label>>(x.t), " "); |
1020 | Walk(std::get<std::optional<LoopControl>>(x.t)); |
1021 | } |
1022 | void Unparse(const LoopControl &x) { // R1123 |
1023 | common::visit(common::visitors{ |
1024 | [&](const ScalarLogicalExpr &y) { |
1025 | Word("WHILE ("), Walk(y), Put(')'); |
1026 | }, |
1027 | [&](const auto &y) { Walk(y); }, |
1028 | }, |
1029 | x.u); |
1030 | } |
1031 | void Unparse(const ConcurrentHeader &x) { // R1125 |
1032 | Put('('), Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::"); |
1033 | Walk(std::get<std::list<ConcurrentControl>>(x.t), ", "); |
1034 | Walk(", ", std::get<std::optional<ScalarLogicalExpr>>(x.t)), Put(')'); |
1035 | } |
1036 | void Unparse(const ConcurrentControl &x) { // R1126 - R1128 |
1037 | Walk(std::get<Name>(x.t)), Put('='), Walk(std::get<1>(x.t)); |
1038 | Put(':'), Walk(std::get<2>(x.t)); |
1039 | Walk(":", std::get<std::optional<ScalarIntExpr>>(x.t)); |
1040 | } |
1041 | void Before(const LoopControl::Concurrent &) { // R1129 |
1042 | Word("CONCURRENT"); |
1043 | } |
1044 | void Unparse(const LocalitySpec::Local &x) { |
1045 | Word("LOCAL("), Walk(x.v, ", "), Put(')'); |
1046 | } |
1047 | void Unparse(const LocalitySpec::LocalInit &x) { |
1048 | Word("LOCAL_INIT("), Walk(x.v, ", "), Put(')'); |
1049 | } |
1050 | void Unparse(const LocalitySpec::Reduce &x) { |
1051 | Word("REDUCE("), Walk(std::get<parser::ReductionOperator>(x.t)); |
1052 | Walk(":", std::get<std::list<parser::Name>>(x.t), ",", ")"); |
1053 | } |
1054 | void Unparse(const LocalitySpec::Shared &x) { |
1055 | Word("SHARED("), Walk(x.v, ", "), Put(')'); |
1056 | } |
1057 | void Post(const LocalitySpec::DefaultNone &) { Word("DEFAULT(NONE)"); } |
1058 | void Unparse(const EndDoStmt &x) { // R1132 |
1059 | Word("END DO"), Walk( " ", x.v); |
1060 | } |
1061 | void Unparse(const CycleStmt &x) { // R1133 |
1062 | Word("CYCLE"), Walk( " ", x.v); |
1063 | } |
1064 | void Unparse(const IfThenStmt &x) { // R1135 |
1065 | Walk(std::get<std::optional<Name>>(x.t), ": "); |
1066 | Word("IF ("), Walk(std::get<ScalarLogicalExpr>(x.t)); |
1067 | Put(") "), Word( "THEN"), Indent(); |
1068 | } |
1069 | void Unparse(const ElseIfStmt &x) { // R1136 |
1070 | Outdent(), Word("ELSE IF ("); |
1071 | Walk(std::get<ScalarLogicalExpr>(x.t)), Put(") "), Word( "THEN"); |
1072 | Walk(" ", std::get<std::optional<Name>>(x.t)), Indent(); |
1073 | } |
1074 | void Unparse(const ElseStmt &x) { // R1137 |
1075 | Outdent(), Word("ELSE"), Walk( " ", x.v), Indent(); |
1076 | } |
1077 | void Unparse(const EndIfStmt &x) { // R1138 |
1078 | Outdent(), Word("END IF"), Walk( " ", x.v); |
1079 | } |
1080 | void Unparse(const IfStmt &x) { // R1139 |
1081 | Word("IF ("), Walk(x.t, ") "); |
1082 | } |
1083 | void Unparse(const SelectCaseStmt &x) { // R1141, R1144 |
1084 | Walk(std::get<std::optional<Name>>(x.t), ": "); |
1085 | Word("SELECT CASE ("); |
1086 | Walk(std::get<Scalar<Expr>>(x.t)), Put(')'), Indent(); |
1087 | } |
1088 | void Unparse(const CaseStmt &x) { // R1142 |
1089 | Outdent(), Word("CASE "), Walk(std::get<CaseSelector>(x.t)); |
1090 | Walk(" ", std::get<std::optional<Name>>(x.t)), Indent(); |
1091 | } |
1092 | void Unparse(const EndSelectStmt &x) { // R1143 & R1151 & R1155 |
1093 | Outdent(), Word("END SELECT"), Walk( " ", x.v); |
1094 | } |
1095 | void Unparse(const CaseSelector &x) { // R1145 |
1096 | common::visit(common::visitors{ |
1097 | [&](const std::list<CaseValueRange> &y) { |
1098 | Put('('), Walk(y), Put(')'); |
1099 | }, |
1100 | [&](const Default &) { Word("DEFAULT"); }, |
1101 | }, |
1102 | x.u); |
1103 | } |
1104 | void Unparse(const CaseValueRange::Range &x) { // R1146 |
1105 | Walk(x.lower), Put(':'), Walk(x.upper); |
1106 | } |
1107 | void Unparse(const SelectRankStmt &x) { // R1149 |
1108 | Walk(std::get<0>(x.t), ": "); |
1109 | Word("SELECT RANK ("), Walk(std::get<1>(x.t), " => "); |
1110 | Walk(std::get<Selector>(x.t)), Put(')'), Indent(); |
1111 | } |
1112 | void Unparse(const SelectRankCaseStmt &x) { // R1150 |
1113 | Outdent(), Word("RANK "); |
1114 | common::visit(common::visitors{ |
1115 | [&](const ScalarIntConstantExpr &y) { |
1116 | Put('('), Walk(y), Put(')'); |
1117 | }, |
1118 | [&](const Star &) { Put("(*)"); }, |
1119 | [&](const Default &) { Word("DEFAULT"); }, |
1120 | }, |
1121 | std::get<SelectRankCaseStmt::Rank>(x.t).u); |
1122 | Walk(" ", std::get<std::optional<Name>>(x.t)), Indent(); |
1123 | } |
1124 | void Unparse(const SelectTypeStmt &x) { // R1153 |
1125 | Walk(std::get<0>(x.t), ": "); |
1126 | Word("SELECT TYPE ("), Walk(std::get<1>(x.t), " => "); |
1127 | Walk(std::get<Selector>(x.t)), Put(')'), Indent(); |
1128 | } |
1129 | void Unparse(const TypeGuardStmt &x) { // R1154 |
1130 | Outdent(), Walk(std::get<TypeGuardStmt::Guard>(x.t)); |
1131 | Walk(" ", std::get<std::optional<Name>>(x.t)), Indent(); |
1132 | } |
1133 | void Unparse(const TypeGuardStmt::Guard &x) { |
1134 | common::visit( |
1135 | common::visitors{ |
1136 | [&](const TypeSpec &y) { Word("TYPE IS ("), Walk(y), Put(')'); }, |
1137 | [&](const DerivedTypeSpec &y) { |
1138 | Word("CLASS IS ("), Walk(y), Put(')'); |
1139 | }, |
1140 | [&](const Default &) { Word("CLASS DEFAULT"); }, |
1141 | }, |
1142 | x.u); |
1143 | } |
1144 | void Unparse(const ExitStmt &x) { // R1156 |
1145 | Word("EXIT"), Walk( " ", x.v); |
1146 | } |
1147 | void Before(const GotoStmt &) { // R1157 |
1148 | Word("GO TO "); |
1149 | } |
1150 | void Unparse(const ComputedGotoStmt &x) { // R1158 |
1151 | Word("GO TO ("), Walk(x.t, "), "); |
1152 | } |
1153 | void Unparse(const ContinueStmt &) { // R1159 |
1154 | Word("CONTINUE"); |
1155 | } |
1156 | void Unparse(const StopStmt &x) { // R1160, R1161 |
1157 | if (std::get<StopStmt::Kind>(x.t) == StopStmt::Kind::ErrorStop) { |
1158 | Word("ERROR "); |
1159 | } |
1160 | Word("STOP"), Walk( " ", std::get<std::optional<StopCode>>(x.t)); |
1161 | Walk(", QUIET=", std::get<std::optional<ScalarLogicalExpr>>(x.t)); |
1162 | } |
1163 | void Unparse(const FailImageStmt &) { // R1163 |
1164 | Word("FAIL IMAGE"); |
1165 | } |
1166 | void Unparse(const NotifyWaitStmt &x) { // F2023: R1166 |
1167 | Word("NOTIFY WAIT ("), Walk(std::get<Scalar<Variable>>(x.t)); |
1168 | Walk(", ", std::get<std::list<EventWaitSpec>>(x.t), ", "); |
1169 | Put(')'); |
1170 | } |
1171 | void Unparse(const SyncAllStmt &x) { // R1164 |
1172 | Word("SYNC ALL ("), Walk(x.v, ", "), Put(')'); |
1173 | } |
1174 | void Unparse(const SyncImagesStmt &x) { // R1166 |
1175 | Word("SYNC IMAGES ("); |
1176 | Walk(std::get<SyncImagesStmt::ImageSet>(x.t)); |
1177 | Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); |
1178 | } |
1179 | void Unparse(const SyncMemoryStmt &x) { // R1168 |
1180 | Word("SYNC MEMORY ("), Walk(x.v, ", "), Put(')'); |
1181 | } |
1182 | void Unparse(const SyncTeamStmt &x) { // R1169 |
1183 | Word("SYNC TEAM ("), Walk(std::get<TeamValue>(x.t)); |
1184 | Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); |
1185 | } |
1186 | void Unparse(const EventPostStmt &x) { // R1170 |
1187 | Word("EVENT POST ("), Walk(std::get<EventVariable>(x.t)); |
1188 | Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')'); |
1189 | } |
1190 | void Before(const EventWaitSpec &x) { // R1173, R1174 |
1191 | common::visit(common::visitors{ |
1192 | [&](const ScalarIntExpr &) { Word("UNTIL_COUNT="); }, |
1193 | [](const StatOrErrmsg &) {}, |
1194 | }, |
1195 | x.u); |
1196 | } |
1197 | void Unparse(const EventWaitStmt &x) { // R1170 |
1198 | Word("EVENT WAIT ("), Walk(std::get<EventVariable>(x.t)); |
1199 | Walk(", ", std::get<std::list<EventWaitSpec>>(x.t), ", "); |
1200 | Put(')'); |
1201 | } |
1202 | void Unparse(const FormTeamStmt &x) { // R1175, R1177 |
1203 | Word("FORM TEAM ("), Walk(std::get<ScalarIntExpr>(x.t)); |
1204 | Put(','), Walk(std::get<TeamVariable>(x.t)); |
1205 | Walk(", ", std::get<std::list<FormTeamStmt::FormTeamSpec>>(x.t), ", "); |
1206 | Put(')'); |
1207 | } |
1208 | void Before(const FormTeamStmt::FormTeamSpec &x) { // R1176, R1178 |
1209 | common::visit(common::visitors{ |
1210 | [&](const ScalarIntExpr &) { Word("NEW_INDEX="); }, |
1211 | [](const StatOrErrmsg &) {}, |
1212 | }, |
1213 | x.u); |
1214 | } |
1215 | void Unparse(const LockStmt &x) { // R1179 |
1216 | Word("LOCK ("), Walk(std::get<LockVariable>(x.t)); |
1217 | Walk(", ", std::get<std::list<LockStmt::LockStat>>(x.t), ", "); |
1218 | Put(')'); |
1219 | } |
1220 | void Before(const LockStmt::LockStat &x) { // R1180 |
1221 | common::visit( |
1222 | common::visitors{ |
1223 | [&](const ScalarLogicalVariable &) { Word("ACQUIRED_LOCK="); }, |
1224 | [](const StatOrErrmsg &) {}, |
1225 | }, |
1226 | x.u); |
1227 | } |
1228 | void Unparse(const UnlockStmt &x) { // R1181 |
1229 | Word("UNLOCK ("), Walk(std::get<LockVariable>(x.t)); |
1230 | Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "); |
1231 | Put(')'); |
1232 | } |
1233 | |
1234 | void Unparse(const OpenStmt &x) { // R1204 |
1235 | Word("OPEN ("), Walk(x.v, ", "), Put(')'); |
1236 | } |
1237 | bool Pre(const ConnectSpec &x) { // R1205 |
1238 | return common::visit(common::visitors{ |
1239 | [&](const FileUnitNumber &) { |
1240 | Word("UNIT="); |
1241 | return true; |
1242 | }, |
1243 | [&](const FileNameExpr &) { |
1244 | Word("FILE="); |
1245 | return true; |
1246 | }, |
1247 | [&](const ConnectSpec::CharExpr &y) { |
1248 | Walk(y.t, "="); |
1249 | return false; |
1250 | }, |
1251 | [&](const MsgVariable &) { |
1252 | Word("IOMSG="); |
1253 | return true; |
1254 | }, |
1255 | [&](const StatVariable &) { |
1256 | Word("IOSTAT="); |
1257 | return true; |
1258 | }, |
1259 | [&](const ConnectSpec::Recl &) { |
1260 | Word("RECL="); |
1261 | return true; |
1262 | }, |
1263 | [&](const ConnectSpec::Newunit &) { |
1264 | Word("NEWUNIT="); |
1265 | return true; |
1266 | }, |
1267 | [&](const ErrLabel &) { |
1268 | Word("ERR="); |
1269 | return true; |
1270 | }, |
1271 | [&](const StatusExpr &) { |
1272 | Word("STATUS="); |
1273 | return true; |
1274 | }, |
1275 | }, |
1276 | x.u); |
1277 | } |
1278 | void Unparse(const CloseStmt &x) { // R1208 |
1279 | Word("CLOSE ("), Walk(x.v, ", "), Put(')'); |
1280 | } |
1281 | void Before(const CloseStmt::CloseSpec &x) { // R1209 |
1282 | common::visit(common::visitors{ |
1283 | [&](const FileUnitNumber &) { Word("UNIT="); }, |
1284 | [&](const StatVariable &) { Word("IOSTAT="); }, |
1285 | [&](const MsgVariable &) { Word("IOMSG="); }, |
1286 | [&](const ErrLabel &) { Word("ERR="); }, |
1287 | [&](const StatusExpr &) { Word("STATUS="); }, |
1288 | }, |
1289 | x.u); |
1290 | } |
1291 | void Unparse(const ReadStmt &x) { // R1210 |
1292 | Word("READ "); |
1293 | if (x.iounit) { |
1294 | Put('('), Walk(x.iounit); |
1295 | if (x.format) { |
1296 | Put(", "), Walk(x.format); |
1297 | } |
1298 | Walk(", ", x.controls, ", "); |
1299 | Put(')'); |
1300 | } else if (x.format) { |
1301 | Walk(x.format); |
1302 | if (!x.items.empty()) { |
1303 | Put(", "); |
1304 | } |
1305 | } else { |
1306 | Put('('), Walk(x.controls, ", "), Put(')'); |
1307 | } |
1308 | Walk(" ", x.items, ", "); |
1309 | } |
1310 | void Unparse(const WriteStmt &x) { // R1211 |
1311 | Word("WRITE ("); |
1312 | if (x.iounit) { |
1313 | Walk(x.iounit); |
1314 | if (x.format) { |
1315 | Put(", "), Walk(x.format); |
1316 | } |
1317 | Walk(", ", x.controls, ", "); |
1318 | } else { |
1319 | Walk(x.controls, ", "); |
1320 | } |
1321 | Put(')'), Walk(" ", x.items, ", "); |
1322 | } |
1323 | void Unparse(const PrintStmt &x) { // R1212 |
1324 | Word("PRINT "), Walk(std::get<Format>(x.t)); |
1325 | Walk(", ", std::get<std::list<OutputItem>>(x.t), ", "); |
1326 | } |
1327 | bool Pre(const IoControlSpec &x) { // R1213 |
1328 | return common::visit(common::visitors{ |
1329 | [&](const IoUnit &) { |
1330 | Word("UNIT="); |
1331 | return true; |
1332 | }, |
1333 | [&](const Format &) { |
1334 | Word("FMT="); |
1335 | return true; |
1336 | }, |
1337 | [&](const Name &) { |
1338 | Word("NML="); |
1339 | return true; |
1340 | }, |
1341 | [&](const IoControlSpec::CharExpr &y) { |
1342 | Walk(y.t, "="); |
1343 | return false; |
1344 | }, |
1345 | [&](const IoControlSpec::Asynchronous &) { |
1346 | Word("ASYNCHRONOUS="); |
1347 | return true; |
1348 | }, |
1349 | [&](const EndLabel &) { |
1350 | Word("END="); |
1351 | return true; |
1352 | }, |
1353 | [&](const EorLabel &) { |
1354 | Word("EOR="); |
1355 | return true; |
1356 | }, |
1357 | [&](const ErrLabel &) { |
1358 | Word("ERR="); |
1359 | return true; |
1360 | }, |
1361 | [&](const IdVariable &) { |
1362 | Word("ID="); |
1363 | return true; |
1364 | }, |
1365 | [&](const MsgVariable &) { |
1366 | Word("IOMSG="); |
1367 | return true; |
1368 | }, |
1369 | [&](const StatVariable &) { |
1370 | Word("IOSTAT="); |
1371 | return true; |
1372 | }, |
1373 | [&](const IoControlSpec::Pos &) { |
1374 | Word("POS="); |
1375 | return true; |
1376 | }, |
1377 | [&](const IoControlSpec::Rec &) { |
1378 | Word("REC="); |
1379 | return true; |
1380 | }, |
1381 | [&](const IoControlSpec::Size &) { |
1382 | Word("SIZE="); |
1383 | return true; |
1384 | }, |
1385 | }, |
1386 | x.u); |
1387 | } |
1388 | void Unparse(const InputImpliedDo &x) { // R1218 |
1389 | Put('('), Walk(std::get<std::list<InputItem>>(x.t), ", "), Put( ", "); |
1390 | Walk(std::get<IoImpliedDoControl>(x.t)), Put(')'); |
1391 | } |
1392 | void Unparse(const OutputImpliedDo &x) { // R1219 |
1393 | Put('('), Walk(std::get<std::list<OutputItem>>(x.t), ", "), Put( ", "); |
1394 | Walk(std::get<IoImpliedDoControl>(x.t)), Put(')'); |
1395 | } |
1396 | void Unparse(const WaitStmt &x) { // R1222 |
1397 | Word("WAIT ("), Walk(x.v, ", "), Put(')'); |
1398 | } |
1399 | void Before(const WaitSpec &x) { // R1223 |
1400 | common::visit(common::visitors{ |
1401 | [&](const FileUnitNumber &) { Word("UNIT="); }, |
1402 | [&](const EndLabel &) { Word("END="); }, |
1403 | [&](const EorLabel &) { Word("EOR="); }, |
1404 | [&](const ErrLabel &) { Word("ERR="); }, |
1405 | [&](const IdExpr &) { Word("ID="); }, |
1406 | [&](const MsgVariable &) { Word("IOMSG="); }, |
1407 | [&](const StatVariable &) { Word("IOSTAT="); }, |
1408 | }, |
1409 | x.u); |
1410 | } |
1411 | void Unparse(const BackspaceStmt &x) { // R1224 |
1412 | Word("BACKSPACE ("), Walk(x.v, ", "), Put(')'); |
1413 | } |
1414 | void Unparse(const EndfileStmt &x) { // R1225 |
1415 | Word("ENDFILE ("), Walk(x.v, ", "), Put(')'); |
1416 | } |
1417 | void Unparse(const RewindStmt &x) { // R1226 |
1418 | Word("REWIND ("), Walk(x.v, ", "), Put(')'); |
1419 | } |
1420 | void Before(const PositionOrFlushSpec &x) { // R1227 & R1229 |
1421 | common::visit(common::visitors{ |
1422 | [&](const FileUnitNumber &) { Word("UNIT="); }, |
1423 | [&](const MsgVariable &) { Word("IOMSG="); }, |
1424 | [&](const StatVariable &) { Word("IOSTAT="); }, |
1425 | [&](const ErrLabel &) { Word("ERR="); }, |
1426 | }, |
1427 | x.u); |
1428 | } |
1429 | void Unparse(const FlushStmt &x) { // R1228 |
1430 | Word("FLUSH ("), Walk(x.v, ", "), Put(')'); |
1431 | } |
1432 | void Unparse(const InquireStmt &x) { // R1230 |
1433 | Word("INQUIRE ("); |
1434 | common::visit( |
1435 | common::visitors{ |
1436 | [&](const InquireStmt::Iolength &y) { |
1437 | Word("IOLENGTH="), Walk(y.t, ") "); |
1438 | }, |
1439 | [&](const std::list<InquireSpec> &y) { Walk(y, ", "), Put(')'); }, |
1440 | }, |
1441 | x.u); |
1442 | } |
1443 | bool Pre(const InquireSpec &x) { // R1231 |
1444 | return common::visit(common::visitors{ |
1445 | [&](const FileUnitNumber &) { |
1446 | Word("UNIT="); |
1447 | return true; |
1448 | }, |
1449 | [&](const FileNameExpr &) { |
1450 | Word("FILE="); |
1451 | return true; |
1452 | }, |
1453 | [&](const InquireSpec::CharVar &y) { |
1454 | Walk(y.t, "="); |
1455 | return false; |
1456 | }, |
1457 | [&](const InquireSpec::IntVar &y) { |
1458 | Walk(y.t, "="); |
1459 | return false; |
1460 | }, |
1461 | [&](const InquireSpec::LogVar &y) { |
1462 | Walk(y.t, "="); |
1463 | return false; |
1464 | }, |
1465 | [&](const IdExpr &) { |
1466 | Word("ID="); |
1467 | return true; |
1468 | }, |
1469 | [&](const ErrLabel &) { |
1470 | Word("ERR="); |
1471 | return true; |
1472 | }, |
1473 | }, |
1474 | x.u); |
1475 | } |
1476 | |
1477 | void Before(const FormatStmt &) { // R1301 |
1478 | Word("FORMAT"); |
1479 | } |
1480 | void Unparse(const format::FormatSpecification &x) { // R1302, R1303, R1305 |
1481 | Put('('), Walk("", x.items, ",", x.unlimitedItems.empty() ? "": ","); |
1482 | Walk("*(", x.unlimitedItems, ",", ")"), Put(')'); |
1483 | } |
1484 | void Unparse(const format::FormatItem &x) { // R1304, R1306, R1321 |
1485 | if (x.repeatCount) { |
1486 | Walk(*x.repeatCount); |
1487 | } |
1488 | common::visit(common::visitors{ |
1489 | [&](const std::string &y) { PutNormalized(y); }, |
1490 | [&](const std::list<format::FormatItem> &y) { |
1491 | Walk("(", y, ",", ")"); |
1492 | }, |
1493 | [&](const auto &y) { Walk(y); }, |
1494 | }, |
1495 | x.u); |
1496 | } |
1497 | void Unparse( |
1498 | const format::IntrinsicTypeDataEditDesc &x) { // R1307(1/2) - R1311 |
1499 | switch (x.kind) { |
1500 | #define FMT(x) \ |
1501 | case format::IntrinsicTypeDataEditDesc::Kind::x: \ |
1502 | Put(#x); \ |
1503 | break |
1504 | FMT(I); |
1505 | FMT(B); |
1506 | FMT(O); |
1507 | FMT(Z); |
1508 | FMT(F); |
1509 | FMT(E); |
1510 | FMT(EN); |
1511 | FMT(ES); |
1512 | FMT(EX); |
1513 | FMT(G); |
1514 | FMT(L); |
1515 | FMT(A); |
1516 | FMT(D); |
1517 | #undef FMT |
1518 | } |
1519 | Walk(x.width), Walk(".", x.digits), Walk( "E", x.exponentWidth); |
1520 | } |
1521 | void Unparse(const format::DerivedTypeDataEditDesc &x) { // R1307(2/2), R1312 |
1522 | Word("DT"); |
1523 | if (!x.type.empty()) { |
1524 | Put('"'), Put(x.type), Put('"'); |
1525 | } |
1526 | Walk("(", x.parameters, ",", ")"); |
1527 | } |
1528 | void Unparse(const format::ControlEditDesc &x) { // R1313, R1315-R1320 |
1529 | switch (x.kind) { |
1530 | case format::ControlEditDesc::Kind::T: |
1531 | Word("T"); |
1532 | Walk(x.count); |
1533 | break; |
1534 | case format::ControlEditDesc::Kind::TL: |
1535 | Word("TL"); |
1536 | Walk(x.count); |
1537 | break; |
1538 | case format::ControlEditDesc::Kind::TR: |
1539 | Word("TR"); |
1540 | Walk(x.count); |
1541 | break; |
1542 | case format::ControlEditDesc::Kind::X: |
1543 | if (x.count != 1) { |
1544 | Walk(x.count); |
1545 | } |
1546 | Word("X"); |
1547 | break; |
1548 | case format::ControlEditDesc::Kind::Slash: |
1549 | if (x.count != 1) { |
1550 | Walk(x.count); |
1551 | } |
1552 | Put('/'); |
1553 | break; |
1554 | case format::ControlEditDesc::Kind::Colon: |
1555 | Put(':'); |
1556 | break; |
1557 | case format::ControlEditDesc::Kind::P: |
1558 | Walk(x.count); |
1559 | Word("P"); |
1560 | break; |
1561 | #define FMT(x) \ |
1562 | case format::ControlEditDesc::Kind::x: \ |
1563 | Put(#x); \ |
1564 | break |
1565 | FMT(SS); |
1566 | FMT(SP); |
1567 | FMT(S); |
1568 | FMT(BN); |
1569 | FMT(BZ); |
1570 | FMT(RU); |
1571 | FMT(RD); |
1572 | FMT(RZ); |
1573 | FMT(RN); |
1574 | FMT(RC); |
1575 | FMT(RP); |
1576 | FMT(DC); |
1577 | FMT(DP); |
1578 | #undef FMT |
1579 | case format::ControlEditDesc::Kind::Dollar: |
1580 | Put('$'); |
1581 | break; |
1582 | case format::ControlEditDesc::Kind::Backslash: |
1583 | Put('\\'); |
1584 | break; |
1585 | } |
1586 | } |
1587 | |
1588 | void Before(const MainProgram &x) { // R1401 |
1589 | if (!std::get<std::optional<Statement<ProgramStmt>>>(x.t)) { |
1590 | Indent(); |
1591 | } |
1592 | } |
1593 | void Before(const ProgramStmt &) { // R1402 |
1594 | Word("PROGRAM "), Indent(); |
1595 | } |
1596 | void Unparse(const EndProgramStmt &x) { // R1403 |
1597 | EndSubprogram("PROGRAM", x.v); |
1598 | } |
1599 | void Before(const ModuleStmt &) { // R1405 |
1600 | Word("MODULE "), Indent(); |
1601 | } |
1602 | void Unparse(const EndModuleStmt &x) { // R1406 |
1603 | EndSubprogram("MODULE", x.v); |
1604 | } |
1605 | void Unparse(const UseStmt &x) { // R1409 |
1606 | Word("USE"), Walk( ", ", x.nature), Put( " :: "), Walk(x.moduleName); |
1607 | common::visit( |
1608 | common::visitors{ |
1609 | [&](const std::list<Rename> &y) { Walk(", ", y, ", "); }, |
1610 | [&](const std::list<Only> &y) { Walk(", ONLY: ", y, ", "); }, |
1611 | }, |
1612 | x.u); |
1613 | } |
1614 | void Unparse(const Rename &x) { // R1411 |
1615 | common::visit(common::visitors{ |
1616 | [&](const Rename::Names &y) { Walk(y.t, " => "); }, |
1617 | [&](const Rename::Operators &y) { |
1618 | Word("OPERATOR("), Walk(y.t, ") => OPERATOR("), |
1619 | Put(")"); |
1620 | }, |
1621 | }, |
1622 | x.u); |
1623 | } |
1624 | void Unparse(const SubmoduleStmt &x) { // R1417 |
1625 | Word("SUBMODULE ("), WalkTupleElements(x.t, ")"), Indent(); |
1626 | } |
1627 | void Unparse(const ParentIdentifier &x) { // R1418 |
1628 | Walk(std::get<Name>(x.t)), Walk(":", std::get<std::optional<Name>>(x.t)); |
1629 | } |
1630 | void Unparse(const EndSubmoduleStmt &x) { // R1419 |
1631 | EndSubprogram("SUBMODULE", x.v); |
1632 | } |
1633 | void Unparse(const BlockDataStmt &x) { // R1421 |
1634 | Word("BLOCK DATA"), Walk( " ", x.v), Indent(); |
1635 | } |
1636 | void Unparse(const EndBlockDataStmt &x) { // R1422 |
1637 | EndSubprogram("BLOCK DATA", x.v); |
1638 | } |
1639 | |
1640 | void Unparse(const InterfaceStmt &x) { // R1503 |
1641 | common::visit(common::visitors{ |
1642 | [&](const std::optional<GenericSpec> &y) { |
1643 | Word("INTERFACE"), Walk( " ", y); |
1644 | }, |
1645 | [&](const Abstract &) { Word("ABSTRACT INTERFACE"); }, |
1646 | }, |
1647 | x.u); |
1648 | Indent(); |
1649 | } |
1650 | void Unparse(const EndInterfaceStmt &x) { // R1504 |
1651 | Outdent(), Word("END INTERFACE"), Walk( " ", x.v); |
1652 | } |
1653 | void Unparse(const ProcedureStmt &x) { // R1506 |
1654 | if (std::get<ProcedureStmt::Kind>(x.t) == |
1655 | ProcedureStmt::Kind::ModuleProcedure) { |
1656 | Word("MODULE "); |
1657 | } |
1658 | Word("PROCEDURE :: "); |
1659 | Walk(std::get<std::list<Name>>(x.t), ", "); |
1660 | } |
1661 | void Before(const GenericSpec &x) { // R1508, R1509 |
1662 | common::visit( |
1663 | common::visitors{ |
1664 | [&](const DefinedOperator &) { Word("OPERATOR("); }, |
1665 | [&](const GenericSpec::Assignment &) { Word("ASSIGNMENT(=)"); }, |
1666 | [&](const GenericSpec::ReadFormatted &) { |
1667 | Word("READ(FORMATTED)"); |
1668 | }, |
1669 | [&](const GenericSpec::ReadUnformatted &) { |
1670 | Word("READ(UNFORMATTED)"); |
1671 | }, |
1672 | [&](const GenericSpec::WriteFormatted &) { |
1673 | Word("WRITE(FORMATTED)"); |
1674 | }, |
1675 | [&](const GenericSpec::WriteUnformatted &) { |
1676 | Word("WRITE(UNFORMATTED)"); |
1677 | }, |
1678 | [](const auto &) {}, |
1679 | }, |
1680 | x.u); |
1681 | } |
1682 | void Post(const GenericSpec &x) { |
1683 | common::visit(common::visitors{ |
1684 | [&](const DefinedOperator &) { Put(')'); }, |
1685 | [](const auto &) {}, |
1686 | }, |
1687 | x.u); |
1688 | } |
1689 | void Unparse(const GenericStmt &x) { // R1510 |
1690 | Word("GENERIC"), Walk( ", ", std::get<std::optional<AccessSpec>>(x.t)); |
1691 | Put(" :: "), Walk(std::get<GenericSpec>(x.t)), Put( " => "); |
1692 | Walk(std::get<std::list<Name>>(x.t), ", "); |
1693 | } |
1694 | void Unparse(const ExternalStmt &x) { // R1511 |
1695 | Word("EXTERNAL :: "), Walk(x.v, ", "); |
1696 | } |
1697 | void Unparse(const ProcedureDeclarationStmt &x) { // R1512 |
1698 | Word("PROCEDURE("), Walk(std::get<std::optional<ProcInterface>>(x.t)); |
1699 | Put(')'), Walk(", ", std::get<std::list<ProcAttrSpec>>(x.t), ", "); |
1700 | Put(" :: "), Walk(std::get<std::list<ProcDecl>>(x.t), ", "); |
1701 | } |
1702 | void Unparse(const ProcDecl &x) { // R1515 |
1703 | Walk(std::get<Name>(x.t)); |
1704 | Walk(" => ", std::get<std::optional<ProcPointerInit>>(x.t)); |
1705 | } |
1706 | void Unparse(const IntrinsicStmt &x) { // R1519 |
1707 | Word("INTRINSIC :: "), Walk(x.v, ", "); |
1708 | } |
1709 | void Unparse(const CallStmt::StarOrExpr &x) { |
1710 | if (x.v) { |
1711 | Walk(*x.v); |
1712 | } else { |
1713 | Word("*"); |
1714 | } |
1715 | } |
1716 | void Unparse(const CallStmt::Chevrons &x) { // CUDA |
1717 | Walk(std::get<0>(x.t)); // grid |
1718 | Word(","), Walk(std::get<1>(x.t)); // block |
1719 | Walk(",", std::get<2>(x.t)); // bytes |
1720 | Walk(",", std::get<3>(x.t)); // stream |
1721 | } |
1722 | void Unparse(const FunctionReference &x) { // R1520 |
1723 | Walk(std::get<ProcedureDesignator>(x.v.t)); |
1724 | Put('('), Walk(std::get<std::list<ActualArgSpec>>(x.v.t), ", "), Put(')'); |
1725 | } |
1726 | void Unparse(const CallStmt &x) { // R1521 |
1727 | if (asFortran_ && x.typedCall.get()) { |
1728 | Put(' '); |
1729 | asFortran_->call(out_, *x.typedCall); |
1730 | Put('\n'); |
1731 | } else { |
1732 | const auto &pd{std::get<ProcedureDesignator>(x.call.t)}; |
1733 | Word("CALL "), Walk(pd); |
1734 | Walk("<<<", x.chevrons, ">>>"); |
1735 | const auto &args{std::get<std::list<ActualArgSpec>>(x.call.t)}; |
1736 | if (args.empty()) { |
1737 | if (std::holds_alternative<ProcComponentRef>(pd.u)) { |
1738 | Put("()"); // pgf90 crashes on CALL to tbp without parentheses |
1739 | } |
1740 | } else { |
1741 | Walk("(", args, ", ", ")"); |
1742 | } |
1743 | } |
1744 | } |
1745 | void Unparse(const ActualArgSpec &x) { // R1523 |
1746 | Walk(std::get<std::optional<Keyword>>(x.t), "="); |
1747 | Walk(std::get<ActualArg>(x.t)); |
1748 | } |
1749 | void Unparse(const ActualArg::PercentRef &x) { // R1524 |
1750 | Word("%REF("), Walk(x.v), Put(')'); |
1751 | } |
1752 | void Unparse(const ActualArg::PercentVal &x) { |
1753 | Word("%VAL("), Walk(x.v), Put(')'); |
1754 | } |
1755 | void Before(const AltReturnSpec &) { // R1525 |
1756 | Put('*'); |
1757 | } |
1758 | void Post(const PrefixSpec::Elemental) { Word("ELEMENTAL"); } // R1527 |
1759 | void Post(const PrefixSpec::Impure) { Word("IMPURE"); } |
1760 | void Post(const PrefixSpec::Module) { Word("MODULE"); } |
1761 | void Post(const PrefixSpec::Non_Recursive) { Word("NON_RECURSIVE"); } |
1762 | void Post(const PrefixSpec::Pure) { Word("PURE"); } |
1763 | void Post(const PrefixSpec::Recursive) { Word("RECURSIVE"); } |
1764 | void Unparse(const PrefixSpec::Attributes &x) { |
1765 | Word("ATTRIBUTES("), Walk(x.v), Word( ")"); |
1766 | } |
1767 | void Unparse(const PrefixSpec::Launch_Bounds &x) { |
1768 | Word("LAUNCH_BOUNDS("), Walk(x.v), Word( ")"); |
1769 | } |
1770 | void Unparse(const PrefixSpec::Cluster_Dims &x) { |
1771 | Word("CLUSTER_DIMS("), Walk(x.v), Word( ")"); |
1772 | } |
1773 | void Unparse(const FunctionStmt &x) { // R1530 |
1774 | Walk("", std::get<std::list<PrefixSpec>>(x.t), " ", " "); |
1775 | Word("FUNCTION "), Walk(std::get<Name>(x.t)), Put( "("); |
1776 | Walk(std::get<std::list<Name>>(x.t), ", "), Put(')'); |
1777 | Walk(" ", std::get<std::optional<Suffix>>(x.t)), Indent(); |
1778 | } |
1779 | void Unparse(const Suffix &x) { // R1532 |
1780 | if (x.resultName) { |
1781 | Word("RESULT("), Walk(x.resultName), Put(')'); |
1782 | Walk(" ", x.binding); |
1783 | } else { |
1784 | Walk(x.binding); |
1785 | } |
1786 | } |
1787 | void Unparse(const EndFunctionStmt &x) { // R1533 |
1788 | EndSubprogram("FUNCTION", x.v); |
1789 | } |
1790 | void Unparse(const SubroutineStmt &x) { // R1535 |
1791 | Walk("", std::get<std::list<PrefixSpec>>(x.t), " ", " "); |
1792 | Word("SUBROUTINE "), Walk(std::get<Name>(x.t)); |
1793 | const auto &args{std::get<std::list<DummyArg>>(x.t)}; |
1794 | const auto &bind{std::get<std::optional<LanguageBindingSpec>>(x.t)}; |
1795 | if (args.empty()) { |
1796 | Walk(" () ", bind); |
1797 | } else { |
1798 | Walk(" (", args, ", ", ")"); |
1799 | Walk(" ", bind); |
1800 | } |
1801 | Indent(); |
1802 | } |
1803 | void Unparse(const EndSubroutineStmt &x) { // R1537 |
1804 | EndSubprogram("SUBROUTINE", x.v); |
1805 | } |
1806 | void Before(const MpSubprogramStmt &) { // R1539 |
1807 | Word("MODULE PROCEDURE "), Indent(); |
1808 | } |
1809 | void Unparse(const EndMpSubprogramStmt &x) { // R1540 |
1810 | EndSubprogram("PROCEDURE", x.v); |
1811 | } |
1812 | void Unparse(const EntryStmt &x) { // R1541 |
1813 | Word("ENTRY "), Walk(std::get<Name>(x.t)), Put( "("); |
1814 | Walk(std::get<std::list<DummyArg>>(x.t), ", "), Put( ")"); |
1815 | Walk(" ", std::get<std::optional<Suffix>>(x.t)); |
1816 | } |
1817 | void Unparse(const ReturnStmt &x) { // R1542 |
1818 | Word("RETURN"), Walk( " ", x.v); |
1819 | } |
1820 | void Unparse(const ContainsStmt &) { // R1543 |
1821 | Outdent(); |
1822 | Word("CONTAINS"); |
1823 | Indent(); |
1824 | } |
1825 | void Unparse(const StmtFunctionStmt &x) { // R1544 |
1826 | Walk(std::get<Name>(x.t)), Put('('); |
1827 | Walk(std::get<std::list<Name>>(x.t), ", "), Put( ") = "); |
1828 | Walk(std::get<Scalar<Expr>>(x.t)); |
1829 | } |
1830 | |
1831 | // Directives, extensions, and deprecated constructs |
1832 | void Unparse(const CompilerDirective &x) { |
1833 | common::visit( |
1834 | common::visitors{ |
1835 | [&](const std::list<CompilerDirective::IgnoreTKR> &tkr) { |
1836 | Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty |
1837 | Walk(" ", tkr, ", "); |
1838 | }, |
1839 | [&](const CompilerDirective::LoopCount &lcount) { |
1840 | Walk("!DIR$ LOOP COUNT (", lcount.v, ", ", ")"); |
1841 | }, |
1842 | [&](const std::list<CompilerDirective::AssumeAligned> |
1843 | &assumeAligned) { |
1844 | Word("!DIR$ ASSUME_ALIGNED "); |
1845 | Walk(" ", assumeAligned, ", "); |
1846 | }, |
1847 | [&](const CompilerDirective::VectorAlways &valways) { |
1848 | Word("!DIR$ VECTOR ALWAYS"); |
1849 | }, |
1850 | [&](const std::list<CompilerDirective::NameValue> &names) { |
1851 | Walk("!DIR$ ", names, " "); |
1852 | }, |
1853 | [&](const CompilerDirective::Unroll &unroll) { |
1854 | Word("!DIR$ UNROLL"); |
1855 | Walk(" ", unroll.v); |
1856 | }, |
1857 | [&](const CompilerDirective::UnrollAndJam &unrollAndJam) { |
1858 | Word("!DIR$ UNROLL_AND_JAM"); |
1859 | Walk(" ", unrollAndJam.v); |
1860 | }, |
1861 | [&](const CompilerDirective::NoVector &) { |
1862 | Word("!DIR$ NOVECTOR"); |
1863 | }, |
1864 | [&](const CompilerDirective::NoUnroll &) { |
1865 | Word("!DIR$ NOUNROLL"); |
1866 | }, |
1867 | [&](const CompilerDirective::NoUnrollAndJam &) { |
1868 | Word("!DIR$ NOUNROLL_AND_JAM"); |
1869 | }, |
1870 | [&](const CompilerDirective::Unrecognized &) { |
1871 | Word("!DIR$ "); |
1872 | Word(x.source.ToString()); |
1873 | }, |
1874 | }, |
1875 | x.u); |
1876 | Put('\n'); |
1877 | } |
1878 | void Unparse(const CompilerDirective::IgnoreTKR &x) { |
1879 | if (const auto &maybeList{ |
1880 | std::get<std::optional<std::list<const char *>>>(x.t)}) { |
1881 | Put("("); |
1882 | for (const char *tkr : *maybeList) { |
1883 | Put(*tkr); |
1884 | } |
1885 | Put(") "); |
1886 | } |
1887 | Walk(std::get<Name>(x.t)); |
1888 | } |
1889 | void Unparse(const CompilerDirective::NameValue &x) { |
1890 | Walk(std::get<Name>(x.t)); |
1891 | Walk("=", std::get<std::optional<std::uint64_t>>(x.t)); |
1892 | } |
1893 | void Unparse(const CompilerDirective::AssumeAligned &x) { |
1894 | Walk(std::get<common::Indirection<Designator>>(x.t)); |
1895 | Put(":"); |
1896 | Walk(std::get<uint64_t>(x.t)); |
1897 | } |
1898 | |
1899 | // OpenACC Directives & Clauses |
1900 | void Unparse(const AccAtomicCapture &x) { |
1901 | BeginOpenACC(); |
1902 | Word("!$ACC CAPTURE"); |
1903 | Put("\n"); |
1904 | EndOpenACC(); |
1905 | Walk(std::get<AccAtomicCapture::Stmt1>(x.t)); |
1906 | Put("\n"); |
1907 | Walk(std::get<AccAtomicCapture::Stmt2>(x.t)); |
1908 | BeginOpenACC(); |
1909 | Word("!$ACC END ATOMIC\n"); |
1910 | EndOpenACC(); |
1911 | } |
1912 | void Unparse(const AccAtomicRead &x) { |
1913 | BeginOpenACC(); |
1914 | Word("!$ACC ATOMIC READ"); |
1915 | Put("\n"); |
1916 | EndOpenACC(); |
1917 | Walk(std::get<Statement<AssignmentStmt>>(x.t)); |
1918 | BeginOpenACC(); |
1919 | Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n"); |
1920 | EndOpenACC(); |
1921 | } |
1922 | void Unparse(const AccAtomicWrite &x) { |
1923 | BeginOpenACC(); |
1924 | Word("!$ACC ATOMIC WRITE"); |
1925 | Put("\n"); |
1926 | EndOpenACC(); |
1927 | Walk(std::get<Statement<AssignmentStmt>>(x.t)); |
1928 | BeginOpenACC(); |
1929 | Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n"); |
1930 | EndOpenACC(); |
1931 | } |
1932 | void Unparse(const AccAtomicUpdate &x) { |
1933 | BeginOpenACC(); |
1934 | Word("!$ACC ATOMIC UPDATE"); |
1935 | Put("\n"); |
1936 | EndOpenACC(); |
1937 | Walk(std::get<Statement<AssignmentStmt>>(x.t)); |
1938 | BeginOpenACC(); |
1939 | Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n"); |
1940 | EndOpenACC(); |
1941 | } |
1942 | void Unparse(const llvm::acc::Directive &x) { |
1943 | Word(llvm::acc::getOpenACCDirectiveName(x).str()); |
1944 | } |
1945 | #define GEN_FLANG_CLAUSE_UNPARSE |
1946 | #include "llvm/Frontend/OpenACC/ACC.inc" |
1947 | void Unparse(const AccObjectListWithModifier &x) { |
1948 | Walk(std::get<std::optional<AccDataModifier>>(x.t), ":"); |
1949 | Walk(std::get<AccObjectList>(x.t)); |
1950 | } |
1951 | void Unparse(const AccBindClause &x) { |
1952 | common::visit(common::visitors{ |
1953 | [&](const Name &y) { Walk(y); }, |
1954 | [&](const ScalarDefaultCharExpr &y) { Walk(y); }, |
1955 | }, |
1956 | x.u); |
1957 | } |
1958 | void Unparse(const AccDefaultClause &x) { |
1959 | switch (x.v) { |
1960 | case llvm::acc::DefaultValue::ACC_Default_none: |
1961 | Put("NONE"); |
1962 | break; |
1963 | case llvm::acc::DefaultValue::ACC_Default_present: |
1964 | Put("PRESENT"); |
1965 | break; |
1966 | } |
1967 | } |
1968 | void Unparse(const AccClauseList &x) { Walk(" ", x.v, " "); } |
1969 | void Unparse(const AccGangArgList &x) { Walk(x.v, ","); } |
1970 | void Before(const AccSizeExpr &x) { |
1971 | if (!x.v) |
1972 | Put("*"); |
1973 | } |
1974 | void Before(const AccGangArg &x) { |
1975 | common::visit(common::visitors{ |
1976 | [&](const AccGangArg::Num &) { Word("NUM:"); }, |
1977 | [&](const AccGangArg::Dim &) { Word("DIM:"); }, |
1978 | [&](const AccGangArg::Static &) { Word("STATIC:"); }, |
1979 | [](const StatOrErrmsg &) {}, |
1980 | }, |
1981 | x.u); |
1982 | } |
1983 | void Unparse(const AccCollapseArg &x) { |
1984 | const auto &force{std::get<bool>(x.t)}; |
1985 | const auto &collapseValue{std::get<parser::ScalarIntConstantExpr>(x.t)}; |
1986 | if (force) { |
1987 | Put("FORCE:"); |
1988 | } |
1989 | Walk(collapseValue); |
1990 | } |
1991 | void Unparse(const OpenACCBlockConstruct &x) { |
1992 | BeginOpenACC(); |
1993 | Word("!$ACC "); |
1994 | Walk(std::get<AccBeginBlockDirective>(x.t)); |
1995 | Put("\n"); |
1996 | EndOpenACC(); |
1997 | Walk(std::get<Block>(x.t), ""); |
1998 | BeginOpenACC(); |
1999 | Word("!$ACC END "); |
2000 | Walk(std::get<AccEndBlockDirective>(x.t)); |
2001 | Put("\n"); |
2002 | EndOpenACC(); |
2003 | } |
2004 | void Unparse(const OpenACCLoopConstruct &x) { |
2005 | BeginOpenACC(); |
2006 | Word("!$ACC "); |
2007 | Walk(std::get<AccBeginLoopDirective>(x.t)); |
2008 | Put("\n"); |
2009 | EndOpenACC(); |
2010 | Walk(std::get<std::optional<DoConstruct>>(x.t)); |
2011 | } |
2012 | void Unparse(const AccBeginLoopDirective &x) { |
2013 | Walk(std::get<AccLoopDirective>(x.t)); |
2014 | Walk(std::get<AccClauseList>(x.t)); |
2015 | } |
2016 | void Unparse(const OpenACCStandaloneConstruct &x) { |
2017 | BeginOpenACC(); |
2018 | Word("!$ACC "); |
2019 | Walk(std::get<AccStandaloneDirective>(x.t)); |
2020 | Walk(std::get<AccClauseList>(x.t)); |
2021 | Put("\n"); |
2022 | EndOpenACC(); |
2023 | } |
2024 | void Unparse(const OpenACCStandaloneDeclarativeConstruct &x) { |
2025 | BeginOpenACC(); |
2026 | Word("!$ACC "); |
2027 | Walk(std::get<AccDeclarativeDirective>(x.t)); |
2028 | Walk(std::get<AccClauseList>(x.t)); |
2029 | Put("\n"); |
2030 | EndOpenACC(); |
2031 | } |
2032 | void Unparse(const OpenACCCombinedConstruct &x) { |
2033 | BeginOpenACC(); |
2034 | Word("!$ACC "); |
2035 | Walk(std::get<AccBeginCombinedDirective>(x.t)); |
2036 | Put("\n"); |
2037 | EndOpenACC(); |
2038 | Walk(std::get<std::optional<DoConstruct>>(x.t)); |
2039 | BeginOpenACC(); |
2040 | Walk("!$ACC END ", std::get<std::optional<AccEndCombinedDirective>>(x.t), |
2041 | "\n"); |
2042 | EndOpenACC(); |
2043 | } |
2044 | void Unparse(const OpenACCRoutineConstruct &x) { |
2045 | BeginOpenACC(); |
2046 | Word("!$ACC ROUTINE"); |
2047 | Walk("(", std::get<std::optional<Name>>(x.t), ")"); |
2048 | Walk(std::get<AccClauseList>(x.t)); |
2049 | Put("\n"); |
2050 | EndOpenACC(); |
2051 | } |
2052 | void Unparse(const AccObject &x) { |
2053 | common::visit(common::visitors{ |
2054 | [&](const Designator &y) { Walk(y); }, |
2055 | [&](const Name &y) { Put("/"), Walk(y), Put( "/"); }, |
2056 | }, |
2057 | x.u); |
2058 | } |
2059 | void Unparse(const AccObjectList &x) { Walk(x.v, ","); } |
2060 | void Unparse(const AccObjectListWithReduction &x) { |
2061 | Walk(std::get<ReductionOperator>(x.t)); |
2062 | Put(":"); |
2063 | Walk(std::get<AccObjectList>(x.t)); |
2064 | } |
2065 | void Unparse(const OpenACCCacheConstruct &x) { |
2066 | BeginOpenACC(); |
2067 | Word("!$ACC "); |
2068 | Word("CACHE("); |
2069 | Walk(std::get<AccObjectListWithModifier>(x.t)); |
2070 | Put(")"); |
2071 | Put("\n"); |
2072 | EndOpenACC(); |
2073 | } |
2074 | void Unparse(const AccWaitArgument &x) { |
2075 | Walk("DEVNUM:", std::get<std::optional<ScalarIntExpr>>(x.t), ":"); |
2076 | Walk(std::get<std::list<ScalarIntExpr>>(x.t), ","); |
2077 | } |
2078 | void Unparse(const OpenACCWaitConstruct &x) { |
2079 | BeginOpenACC(); |
2080 | Word("!$ACC "); |
2081 | Word("WAIT("); |
2082 | Walk(std::get<std::optional<AccWaitArgument>>(x.t)); |
2083 | Walk(std::get<AccClauseList>(x.t)); |
2084 | Put(")"); |
2085 | Put("\n"); |
2086 | EndOpenACC(); |
2087 | } |
2088 | |
2089 | // OpenMP Clauses & Directives |
2090 | void Unparse(const OmpArgumentList &x) { Walk(x.v, ", "); } |
2091 | |
2092 | void Unparse(const OmpTypeNameList &x) { // |
2093 | Walk(x.v, ","); |
2094 | } |
2095 | void Unparse(const OmpMapperSpecifier &x) { |
2096 | const auto &mapperName{std::get<std::string>(x.t)}; |
2097 | if (mapperName.find("omp.default.mapper") == std::string::npos) { |
2098 | Walk(mapperName); |
2099 | Put(":"); |
2100 | } |
2101 | Walk(std::get<TypeSpec>(x.t)); |
2102 | Put("::"); |
2103 | Walk(std::get<Name>(x.t)); |
2104 | } |
2105 | void Unparse(const OmpReductionSpecifier &x) { |
2106 | Walk(std::get<OmpReductionIdentifier>(x.t)); |
2107 | Put(":"); |
2108 | Walk(std::get<OmpTypeNameList>(x.t)); |
2109 | Walk(":", std::get<std::optional<OmpReductionCombiner>>(x.t)); |
2110 | } |
2111 | void Unparse(const llvm::omp::Directive &x) { |
2112 | unsigned ompVersion{langOpts_.OpenMPVersion}; |
2113 | Word(llvm::omp::getOpenMPDirectiveName(x, ompVersion).str()); |
2114 | } |
2115 | void Unparse(const OmpDirectiveSpecification &x) { |
2116 | auto unparseArgs{[&]() { |
2117 | if (auto &args{std::get<std::optional<OmpArgumentList>>(x.t)}) { |
2118 | Put("("); |
2119 | Walk(*args); |
2120 | Put(")"); |
2121 | } |
2122 | }}; |
2123 | auto unparseClauses{[&]() { // |
2124 | Walk(std::get<std::optional<OmpClauseList>>(x.t)); |
2125 | }}; |
2126 | |
2127 | Walk(std::get<OmpDirectiveName>(x.t)); |
2128 | auto flags{std::get<OmpDirectiveSpecification::Flags>(x.t)}; |
2129 | if (flags == OmpDirectiveSpecification::Flags::DeprecatedSyntax) { |
2130 | if (x.DirId() == llvm::omp::Directive::OMPD_flush) { |
2131 | // FLUSH clause arglist |
2132 | unparseClauses(); |
2133 | unparseArgs(); |
2134 | } |
2135 | } else { |
2136 | unparseArgs(); |
2137 | unparseClauses(); |
2138 | } |
2139 | } |
2140 | void Unparse(const OmpTraitScore &x) { |
2141 | Word("SCORE("); |
2142 | Walk(x.v); |
2143 | Put(")"); |
2144 | } |
2145 | void Unparse(const OmpTraitPropertyExtension::Complex &x) { |
2146 | using PropList = std::list<common::Indirection<OmpTraitPropertyExtension>>; |
2147 | Walk(std::get<OmpTraitPropertyName>(x.t)); |
2148 | Put("("); |
2149 | Walk(std::get<PropList>(x.t), ","); |
2150 | Put(")"); |
2151 | } |
2152 | void Unparse(const OmpTraitSelector &x) { |
2153 | Walk(std::get<OmpTraitSelectorName>(x.t)); |
2154 | Walk(std::get<std::optional<OmpTraitSelector::Properties>>(x.t)); |
2155 | } |
2156 | void Unparse(const OmpTraitSelector::Properties &x) { |
2157 | Put("("); |
2158 | Walk(std::get<std::optional<OmpTraitScore>>(x.t), ": "); |
2159 | Walk(std::get<std::list<OmpTraitProperty>>(x.t)); |
2160 | Put(")"); |
2161 | } |
2162 | void Unparse(const OmpTraitSetSelector &x) { |
2163 | Walk(std::get<OmpTraitSetSelectorName>(x.t)); |
2164 | Put("={"); |
2165 | Walk(std::get<std::list<OmpTraitSelector>>(x.t)); |
2166 | Put("}"); |
2167 | } |
2168 | void Unparse(const OmpContextSelectorSpecification &x) { Walk(x.v, ", "); } |
2169 | |
2170 | void Unparse(const OmpObject &x) { |
2171 | common::visit(common::visitors{ |
2172 | [&](const Designator &y) { Walk(y); }, |
2173 | [&](const Name &y) { Put("/"), Walk(y), Put( "/"); }, |
2174 | }, |
2175 | x.u); |
2176 | } |
2177 | void Unparse(const OmpDirectiveNameModifier &x) { |
2178 | unsigned ompVersion{langOpts_.OpenMPVersion}; |
2179 | Word(llvm::omp::getOpenMPDirectiveName(x.v, ompVersion)); |
2180 | } |
2181 | void Unparse(const OmpIteratorSpecifier &x) { |
2182 | Walk(std::get<TypeDeclarationStmt>(x.t)); |
2183 | Put(" = "); |
2184 | Walk(std::get<SubscriptTriplet>(x.t)); |
2185 | } |
2186 | void Unparse(const OmpIterator &x) { |
2187 | Word("ITERATOR("); |
2188 | Walk(x.v); |
2189 | Put(")"); |
2190 | } |
2191 | void Unparse(const OmpMapper &x) { |
2192 | Word("MAPPER("); |
2193 | Walk(x.v); |
2194 | Put(")"); |
2195 | } |
2196 | void Unparse(const OmpLastprivateClause &x) { |
2197 | using Modifier = OmpLastprivateClause::Modifier; |
2198 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2199 | Walk(std::get<OmpObjectList>(x.t)); |
2200 | } |
2201 | void Unparse(const OmpInteropPreference &x) { Walk(x.v, ","); } |
2202 | void Unparse(const OmpInitClause &x) { |
2203 | using Modifier = OmpInitClause::Modifier; |
2204 | auto &modifiers{std::get<std::optional<std::list<Modifier>>>(x.t)}; |
2205 | bool isTypeStart{true}; |
2206 | for (const Modifier &m : *modifiers) { |
2207 | if (auto *interopPreferenceMod{ |
2208 | std::get_if<parser::OmpInteropPreference>(&m.u)}) { |
2209 | Put("PREFER_TYPE("); |
2210 | Walk(*interopPreferenceMod); |
2211 | Put("),"); |
2212 | } else if (auto *interopTypeMod{ |
2213 | std::get_if<parser::OmpInteropType>(&m.u)}) { |
2214 | if (isTypeStart) { |
2215 | isTypeStart = false; |
2216 | } else { |
2217 | Put(","); |
2218 | } |
2219 | Walk(*interopTypeMod); |
2220 | } |
2221 | } |
2222 | Put(": "); |
2223 | Walk(std::get<OmpObject>(x.t)); |
2224 | } |
2225 | void Unparse(const OmpMapClause &x) { |
2226 | using Modifier = OmpMapClause::Modifier; |
2227 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2228 | Walk(std::get<OmpObjectList>(x.t)); |
2229 | } |
2230 | void Unparse(const OmpScheduleClause &x) { |
2231 | using Modifier = OmpScheduleClause::Modifier; |
2232 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ":"); |
2233 | Walk(std::get<OmpScheduleClause::Kind>(x.t)); |
2234 | Walk(",", std::get<std::optional<ScalarIntExpr>>(x.t)); |
2235 | } |
2236 | void Unparse(const OmpDeviceClause &x) { |
2237 | using Modifier = OmpDeviceClause::Modifier; |
2238 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2239 | Walk(std::get<ScalarIntExpr>(x.t)); |
2240 | } |
2241 | void Unparse(const OmpAbsentClause &x) { Walk("", x.v, ","); } |
2242 | void Unparse(const OmpContainsClause &x) { Walk("", x.v, ","); } |
2243 | void Unparse(const OmpAffinityClause &x) { |
2244 | using Modifier = OmpAffinityClause::Modifier; |
2245 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2246 | Walk(std::get<OmpObjectList>(x.t)); |
2247 | } |
2248 | void Unparse(const OmpAlignedClause &x) { |
2249 | using Modifier = OmpAlignedClause::Modifier; |
2250 | Walk(std::get<OmpObjectList>(x.t)); |
2251 | Walk(": ", std::get<std::optional<std::list<Modifier>>>(x.t)); |
2252 | } |
2253 | void Unparse(const OmpFromClause &x) { |
2254 | using Modifier = OmpFromClause::Modifier; |
2255 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2256 | Walk(std::get<OmpObjectList>(x.t)); |
2257 | } |
2258 | void Unparse(const OmpIfClause &x) { |
2259 | using Modifier = OmpIfClause::Modifier; |
2260 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2261 | Walk(std::get<ScalarLogicalExpr>(x.t)); |
2262 | } |
2263 | void Unparse(const OmpStepSimpleModifier &x) { Walk(x.v); } |
2264 | void Unparse(const OmpStepComplexModifier &x) { |
2265 | Word("STEP("); |
2266 | Walk(x.v); |
2267 | Put(")"); |
2268 | } |
2269 | void Unparse(const OmpLinearClause &x) { |
2270 | using Modifier = OmpLinearClause::Modifier; |
2271 | auto &modifiers{std::get<std::optional<std::list<Modifier>>>(x.t)}; |
2272 | if (std::get<bool>(x.t)) { // PostModified |
2273 | Walk(std::get<OmpObjectList>(x.t)); |
2274 | Walk(": ", modifiers); |
2275 | } else { |
2276 | // Unparse using pre-5.2 syntax. |
2277 | bool HasStepModifier{false}, HasLinearModifier{false}; |
2278 | |
2279 | if (modifiers) { |
2280 | bool NeedComma{false}; |
2281 | for (const Modifier &m : *modifiers) { |
2282 | // Print all linear modifiers in case we need to unparse an |
2283 | // incorrect tree. |
2284 | if (auto *lmod{std::get_if<parser::OmpLinearModifier>(&m.u)}) { |
2285 | if (NeedComma) { |
2286 | Put(","); |
2287 | } |
2288 | Walk(*lmod); |
2289 | HasLinearModifier = true; |
2290 | NeedComma = true; |
2291 | } else { |
2292 | // If not linear-modifier, then it has to be step modifier. |
2293 | HasStepModifier = true; |
2294 | } |
2295 | } |
2296 | } |
2297 | |
2298 | if (HasLinearModifier) { |
2299 | Put("("); |
2300 | } |
2301 | Walk(std::get<OmpObjectList>(x.t)); |
2302 | if (HasLinearModifier) { |
2303 | Put(")"); |
2304 | } |
2305 | |
2306 | if (HasStepModifier) { |
2307 | Put(": "); |
2308 | bool NeedComma{false}; |
2309 | for (const Modifier &m : *modifiers) { |
2310 | if (!std::holds_alternative<parser::OmpLinearModifier>(m.u)) { |
2311 | if (NeedComma) { |
2312 | Put(","); |
2313 | } |
2314 | common::visit([&](auto &&s) { Walk(s); }, m.u); |
2315 | NeedComma = true; |
2316 | } |
2317 | } |
2318 | } |
2319 | } |
2320 | } |
2321 | void Unparse(const OmpReductionClause &x) { |
2322 | using Modifier = OmpReductionClause::Modifier; |
2323 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2324 | Walk(std::get<OmpObjectList>(x.t)); |
2325 | } |
2326 | void Unparse(const OmpDetachClause &x) { Walk(x.v); } |
2327 | void Unparse(const OmpInReductionClause &x) { |
2328 | using Modifier = OmpInReductionClause::Modifier; |
2329 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2330 | Walk(std::get<OmpObjectList>(x.t)); |
2331 | } |
2332 | void Unparse(const OmpTaskReductionClause &x) { |
2333 | using Modifier = OmpTaskReductionClause::Modifier; |
2334 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2335 | Walk(std::get<OmpObjectList>(x.t)); |
2336 | } |
2337 | void Unparse(const OmpAllocateClause &x) { |
2338 | using Modifier = OmpAllocateClause::Modifier; |
2339 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2340 | Walk(std::get<OmpObjectList>(x.t)); |
2341 | } |
2342 | void Unparse(const OmpAlignModifier &x) { |
2343 | Word("ALIGN("); |
2344 | Walk(x.v); |
2345 | Put(")"); |
2346 | } |
2347 | void Unparse(const OmpAllocatorSimpleModifier &x) { Walk(x.v); } |
2348 | void Unparse(const OmpAllocatorComplexModifier &x) { |
2349 | Word("ALLOCATOR("); |
2350 | Walk(x.v); |
2351 | Put(")"); |
2352 | } |
2353 | void Unparse(const OmpOrderClause &x) { |
2354 | using Modifier = OmpOrderClause::Modifier; |
2355 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ":"); |
2356 | Walk(std::get<OmpOrderClause::Ordering>(x.t)); |
2357 | } |
2358 | void Unparse(const OmpGrainsizeClause &x) { |
2359 | using Modifier = OmpGrainsizeClause::Modifier; |
2360 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2361 | Walk(std::get<ScalarIntExpr>(x.t)); |
2362 | } |
2363 | void Unparse(const OmpNumTasksClause &x) { |
2364 | using Modifier = OmpNumTasksClause::Modifier; |
2365 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2366 | Walk(std::get<ScalarIntExpr>(x.t)); |
2367 | } |
2368 | void Unparse(const OmpDoacross::Sink &x) { |
2369 | Word("SINK: "); |
2370 | Walk(x.v.v); |
2371 | } |
2372 | void Unparse(const OmpDoacross::Source &) { Word("SOURCE"); } |
2373 | void Unparse(const OmpDependClause::TaskDep &x) { |
2374 | using Modifier = OmpDependClause::TaskDep::Modifier; |
2375 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2376 | Walk(std::get<OmpObjectList>(x.t)); |
2377 | } |
2378 | void Unparse(const OmpDefaultmapClause &x) { |
2379 | using Modifier = OmpDefaultmapClause::Modifier; |
2380 | Walk(std::get<OmpDefaultmapClause::ImplicitBehavior>(x.t)); |
2381 | Walk(":", std::get<std::optional<std::list<Modifier>>>(x.t)); |
2382 | } |
2383 | void Unparse(const OmpToClause &x) { |
2384 | using Modifier = OmpToClause::Modifier; |
2385 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2386 | Walk(std::get<OmpObjectList>(x.t)); |
2387 | } |
2388 | void Unparse(const OmpWhenClause &x) { |
2389 | using Modifier = OmpWhenClause::Modifier; |
2390 | using Directive = common::Indirection<OmpDirectiveSpecification>; |
2391 | Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); |
2392 | Walk(std::get<std::optional<Directive>>(x.t)); |
2393 | } |
2394 | #define GEN_FLANG_CLAUSE_UNPARSE |
2395 | #include "llvm/Frontend/OpenMP/OMP.inc" |
2396 | void Unparse(const OmpLoopDirective &x) { |
2397 | switch (x.v) { |
2398 | case llvm::omp::Directive::OMPD_distribute: |
2399 | Word("DISTRIBUTE "); |
2400 | break; |
2401 | case llvm::omp::Directive::OMPD_distribute_parallel_do: |
2402 | Word("DISTRIBUTE PARALLEL DO "); |
2403 | break; |
2404 | case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: |
2405 | Word("DISTRIBUTE PARALLEL DO SIMD "); |
2406 | break; |
2407 | case llvm::omp::Directive::OMPD_distribute_simd: |
2408 | Word("DISTRIBUTE SIMD "); |
2409 | break; |
2410 | case llvm::omp::Directive::OMPD_do: |
2411 | Word("DO "); |
2412 | break; |
2413 | case llvm::omp::Directive::OMPD_do_simd: |
2414 | Word("DO SIMD "); |
2415 | break; |
2416 | case llvm::omp::Directive::OMPD_loop: |
2417 | Word("LOOP "); |
2418 | break; |
2419 | case llvm::omp::Directive::OMPD_masked_taskloop_simd: |
2420 | Word("MASKED TASKLOOP SIMD"); |
2421 | break; |
2422 | case llvm::omp::Directive::OMPD_masked_taskloop: |
2423 | Word("MASKED TASKLOOP"); |
2424 | break; |
2425 | case llvm::omp::Directive::OMPD_master_taskloop_simd: |
2426 | Word("MASTER TASKLOOP SIMD"); |
2427 | break; |
2428 | case llvm::omp::Directive::OMPD_master_taskloop: |
2429 | Word("MASTER TASKLOOP"); |
2430 | break; |
2431 | case llvm::omp::Directive::OMPD_parallel_do: |
2432 | Word("PARALLEL DO "); |
2433 | break; |
2434 | case llvm::omp::Directive::OMPD_parallel_do_simd: |
2435 | Word("PARALLEL DO SIMD "); |
2436 | break; |
2437 | case llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd: |
2438 | Word("PARALLEL MASKED TASKLOOP SIMD"); |
2439 | break; |
2440 | case llvm::omp::Directive::OMPD_parallel_masked_taskloop: |
2441 | Word("PARALLEL MASKED TASKLOOP"); |
2442 | break; |
2443 | case llvm::omp::Directive::OMPD_parallel_master_taskloop_simd: |
2444 | Word("PARALLEL MASTER TASKLOOP SIMD"); |
2445 | break; |
2446 | case llvm::omp::Directive::OMPD_parallel_master_taskloop: |
2447 | Word("PARALLEL MASTER TASKLOOP"); |
2448 | break; |
2449 | case llvm::omp::Directive::OMPD_simd: |
2450 | Word("SIMD "); |
2451 | break; |
2452 | case llvm::omp::Directive::OMPD_target_loop: |
2453 | Word("TARGET LOOP "); |
2454 | break; |
2455 | case llvm::omp::Directive::OMPD_target_parallel_do: |
2456 | Word("TARGET PARALLEL DO "); |
2457 | break; |
2458 | case llvm::omp::Directive::OMPD_target_parallel_do_simd: |
2459 | Word("TARGET PARALLEL DO SIMD "); |
2460 | break; |
2461 | case llvm::omp::Directive::OMPD_target_parallel_loop: |
2462 | Word("TARGET PARALLEL LOOP "); |
2463 | break; |
2464 | case llvm::omp::Directive::OMPD_target_teams_distribute: |
2465 | Word("TARGET TEAMS DISTRIBUTE "); |
2466 | break; |
2467 | case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do: |
2468 | Word("TARGET TEAMS DISTRIBUTE PARALLEL DO "); |
2469 | break; |
2470 | case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd: |
2471 | Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD "); |
2472 | break; |
2473 | case llvm::omp::Directive::OMPD_target_teams_distribute_simd: |
2474 | Word("TARGET TEAMS DISTRIBUTE SIMD "); |
2475 | break; |
2476 | case llvm::omp::Directive::OMPD_target_teams_loop: |
2477 | Word("TARGET TEAMS LOOP "); |
2478 | break; |
2479 | case llvm::omp::Directive::OMPD_target_simd: |
2480 | Word("TARGET SIMD "); |
2481 | break; |
2482 | case llvm::omp::Directive::OMPD_taskloop: |
2483 | Word("TASKLOOP "); |
2484 | break; |
2485 | case llvm::omp::Directive::OMPD_taskloop_simd: |
2486 | Word("TASKLOOP SIMD "); |
2487 | break; |
2488 | case llvm::omp::Directive::OMPD_teams_distribute: |
2489 | Word("TEAMS DISTRIBUTE "); |
2490 | break; |
2491 | case llvm::omp::Directive::OMPD_teams_distribute_parallel_do: |
2492 | Word("TEAMS DISTRIBUTE PARALLEL DO "); |
2493 | break; |
2494 | case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd: |
2495 | Word("TEAMS DISTRIBUTE PARALLEL DO SIMD "); |
2496 | break; |
2497 | case llvm::omp::Directive::OMPD_teams_distribute_simd: |
2498 | Word("TEAMS DISTRIBUTE SIMD "); |
2499 | break; |
2500 | case llvm::omp::Directive::OMPD_tile: |
2501 | Word("TILE "); |
2502 | break; |
2503 | case llvm::omp::Directive::OMPD_unroll: |
2504 | Word("UNROLL "); |
2505 | break; |
2506 | default: |
2507 | break; |
2508 | } |
2509 | } |
2510 | void Unparse(const OmpObjectList &x) { Walk(x.v, ","); } |
2511 | void Unparse(const OmpBlockDirective &x) { |
2512 | switch (x.v) { |
2513 | case llvm::omp::Directive::OMPD_masked: |
2514 | Word("MASKED"); |
2515 | break; |
2516 | case llvm::omp::Directive::OMPD_master: |
2517 | Word("MASTER"); |
2518 | break; |
2519 | case llvm::omp::Directive::OMPD_ordered: |
2520 | Word("ORDERED "); |
2521 | break; |
2522 | case llvm::omp::Directive::OMPD_parallel_masked: |
2523 | Word("PARALLEL MASKED"); |
2524 | break; |
2525 | case llvm::omp::Directive::OMPD_parallel_master: |
2526 | Word("PARALLEL MASTER"); |
2527 | break; |
2528 | case llvm::omp::Directive::OMPD_parallel_workshare: |
2529 | Word("PARALLEL WORKSHARE "); |
2530 | break; |
2531 | case llvm::omp::Directive::OMPD_parallel: |
2532 | Word("PARALLEL "); |
2533 | break; |
2534 | case llvm::omp::Directive::OMPD_scope: |
2535 | Word("SCOPE "); |
2536 | break; |
2537 | case llvm::omp::Directive::OMPD_single: |
2538 | Word("SINGLE "); |
2539 | break; |
2540 | case llvm::omp::Directive::OMPD_target_data: |
2541 | Word("TARGET DATA "); |
2542 | break; |
2543 | case llvm::omp::Directive::OMPD_target_parallel: |
2544 | Word("TARGET PARALLEL "); |
2545 | break; |
2546 | case llvm::omp::Directive::OMPD_target_teams: |
2547 | Word("TARGET TEAMS "); |
2548 | break; |
2549 | case llvm::omp::Directive::OMPD_target: |
2550 | Word("TARGET "); |
2551 | break; |
2552 | case llvm::omp::Directive::OMPD_taskgroup: |
2553 | Word("TASKGROUP "); |
2554 | break; |
2555 | case llvm::omp::Directive::OMPD_task: |
2556 | Word("TASK "); |
2557 | break; |
2558 | case llvm::omp::Directive::OMPD_teams: |
2559 | Word("TEAMS "); |
2560 | break; |
2561 | case llvm::omp::Directive::OMPD_workshare: |
2562 | Word("WORKSHARE "); |
2563 | break; |
2564 | default: |
2565 | // Nothing to be done |
2566 | break; |
2567 | } |
2568 | } |
2569 | |
2570 | void Unparse(const common::OmpMemoryOrderType &x) { |
2571 | Word(ToUpperCaseLetters(common::EnumToString(x))); |
2572 | } |
2573 | |
2574 | void Unparse(const OpenMPAtomicConstruct &x) { |
2575 | BeginOpenMP(); |
2576 | Word("!$OMP "); |
2577 | Walk(std::get<OmpDirectiveSpecification>(x.t)); |
2578 | Put("\n"); |
2579 | EndOpenMP(); |
2580 | Walk(std::get<Block>(x.t), ""); |
2581 | if (auto &end{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) { |
2582 | BeginOpenMP(); |
2583 | Word("!$OMP END "); |
2584 | Walk(*end); |
2585 | Put("\n"); |
2586 | EndOpenMP(); |
2587 | } |
2588 | } |
2589 | |
2590 | void Unparse(const OpenMPExecutableAllocate &x) { |
2591 | const auto &fields = |
2592 | std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>( |
2593 | x.t); |
2594 | if (fields) { |
2595 | for (const auto &decl : *fields) { |
2596 | Walk(decl); |
2597 | } |
2598 | } |
2599 | BeginOpenMP(); |
2600 | Word("!$OMP ALLOCATE"); |
2601 | Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")"); |
2602 | Walk(std::get<OmpClauseList>(x.t)); |
2603 | Put("\n"); |
2604 | EndOpenMP(); |
2605 | Walk(std::get<Statement<AllocateStmt>>(x.t)); |
2606 | } |
2607 | void Unparse(const OpenMPDeclarativeAllocate &x) { |
2608 | BeginOpenMP(); |
2609 | Word("!$OMP ALLOCATE"); |
2610 | Put(" ("); |
2611 | Walk(std::get<OmpObjectList>(x.t)); |
2612 | Put(")"); |
2613 | Walk(std::get<OmpClauseList>(x.t)); |
2614 | Put("\n"); |
2615 | EndOpenMP(); |
2616 | } |
2617 | void Unparse(const OmpEndAllocators &x) { |
2618 | BeginOpenMP(); |
2619 | Word("!$OMP END ALLOCATE"); |
2620 | Put("\n"); |
2621 | EndOpenMP(); |
2622 | } |
2623 | void Unparse(const OpenMPAllocatorsConstruct &x) { |
2624 | BeginOpenMP(); |
2625 | Word("!$OMP ALLOCATE"); |
2626 | Walk(std::get<OmpClauseList>(x.t)); |
2627 | Put("\n"); |
2628 | EndOpenMP(); |
2629 | Walk(std::get<Statement<AllocateStmt>>(x.t)); |
2630 | if (const auto &end = std::get<std::optional<OmpEndAllocators>>(x.t)) { |
2631 | Walk(*end); |
2632 | } |
2633 | } |
2634 | void Unparse(const OmpAssumeDirective &x) { |
2635 | BeginOpenMP(); |
2636 | Word("!$OMP ASSUME"); |
2637 | Walk(" ", std::get<OmpClauseList>(x.t).v); |
2638 | Put("\n"); |
2639 | EndOpenMP(); |
2640 | } |
2641 | void Unparse(const OmpEndAssumeDirective &x) { |
2642 | BeginOpenMP(); |
2643 | Word("!$OMP END ASSUME\n"); |
2644 | EndOpenMP(); |
2645 | } |
2646 | void Unparse(const OmpCriticalDirective &x) { |
2647 | BeginOpenMP(); |
2648 | Word("!$OMP CRITICAL"); |
2649 | Walk(" (", std::get<std::optional<Name>>(x.t), ")"); |
2650 | Walk(std::get<OmpClauseList>(x.t)); |
2651 | Put("\n"); |
2652 | EndOpenMP(); |
2653 | } |
2654 | void Unparse(const OmpEndCriticalDirective &x) { |
2655 | BeginOpenMP(); |
2656 | Word("!$OMP END CRITICAL"); |
2657 | Walk(" (", std::get<std::optional<Name>>(x.t), ")"); |
2658 | Put("\n"); |
2659 | EndOpenMP(); |
2660 | } |
2661 | void Unparse(const OpenMPCriticalConstruct &x) { |
2662 | Walk(std::get<OmpCriticalDirective>(x.t)); |
2663 | Walk(std::get<Block>(x.t), ""); |
2664 | Walk(std::get<OmpEndCriticalDirective>(x.t)); |
2665 | } |
2666 | void Unparse(const OmpDeclareTargetWithList &x) { |
2667 | Put("("), Walk(x.v), Put( ")"); |
2668 | } |
2669 | void Unparse(const OmpInitializerProc &x) { |
2670 | Walk(std::get<ProcedureDesignator>(x.t)); |
2671 | Put("("); |
2672 | Walk(std::get<std::list<ActualArgSpec>>(x.t)); |
2673 | Put(")"); |
2674 | } |
2675 | void Unparse(const OmpInitializerClause &x) { |
2676 | // Don't let the visitor go to the normal AssignmentStmt Unparse function, |
2677 | // it adds an extra newline that we don't want. |
2678 | if (const auto *assignment{std::get_if<AssignmentStmt>(&x.u)}) { |
2679 | Walk(assignment->t, "="); |
2680 | } else { |
2681 | Walk(x.u); |
2682 | } |
2683 | } |
2684 | void Unparse(const OpenMPDeclareReductionConstruct &x) { |
2685 | BeginOpenMP(); |
2686 | Word("!$OMP DECLARE REDUCTION "); |
2687 | Put("("); |
2688 | Walk(std::get<common::Indirection<OmpReductionSpecifier>>(x.t)); |
2689 | Put(")"); |
2690 | Walk(std::get<std::optional<OmpClauseList>>(x.t)); |
2691 | Put("\n"); |
2692 | EndOpenMP(); |
2693 | } |
2694 | void Unparse(const OmpAppendArgsClause::OmpAppendOp &x) { |
2695 | Put("INTEROP("); |
2696 | Walk(x.v, ","); |
2697 | Put(")"); |
2698 | } |
2699 | void Unparse(const OmpAppendArgsClause &x) { Walk(x.v, ","); } |
2700 | void Unparse(const OmpAdjustArgsClause &x) { |
2701 | Walk(std::get<OmpAdjustArgsClause::OmpAdjustOp>(x.t).v); |
2702 | Put(":"); |
2703 | Walk(std::get<parser::OmpObjectList>(x.t)); |
2704 | } |
2705 | void Unparse(const OmpDeclareVariantDirective &x) { |
2706 | BeginOpenMP(); |
2707 | Word("!$OMP DECLARE VARIANT "); |
2708 | Put("("); |
2709 | Walk(std::get<std::optional<Name>>(x.t), ":"); |
2710 | Walk(std::get<Name>(x.t)); |
2711 | Put(")"); |
2712 | Walk(std::get<OmpClauseList>(x.t)); |
2713 | Put("\n"); |
2714 | EndOpenMP(); |
2715 | } |
2716 | void Unparse(const OpenMPInteropConstruct &x) { |
2717 | BeginOpenMP(); |
2718 | Word("!$OMP INTEROP"); |
2719 | using Flags = OmpDirectiveSpecification::Flags; |
2720 | if (std::get<Flags>(x.v.t) == Flags::DeprecatedSyntax) { |
2721 | Walk("(", std::get<std::optional<OmpArgumentList>>(x.v.t), ")"); |
2722 | Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t)); |
2723 | } else { |
2724 | Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t)); |
2725 | Walk(" (", std::get<std::optional<OmpArgumentList>>(x.v.t), ")"); |
2726 | } |
2727 | Put("\n"); |
2728 | EndOpenMP(); |
2729 | } |
2730 | |
2731 | void Unparse(const OpenMPDeclarativeAssumes &x) { |
2732 | BeginOpenMP(); |
2733 | Word("!$OMP ASSUMES "); |
2734 | Walk(std::get<OmpClauseList>(x.t)); |
2735 | Put("\n"); |
2736 | EndOpenMP(); |
2737 | } |
2738 | void Unparse(const OpenMPDeclareMapperConstruct &z) { |
2739 | BeginOpenMP(); |
2740 | Word("!$OMP DECLARE MAPPER ("); |
2741 | const auto &spec{std::get<OmpMapperSpecifier>(z.t)}; |
2742 | const auto &mapperName{std::get<std::string>(spec.t)}; |
2743 | if (mapperName.find("omp.default.mapper") == std::string::npos) { |
2744 | Walk(mapperName); |
2745 | Put(":"); |
2746 | } |
2747 | Walk(std::get<TypeSpec>(spec.t)); |
2748 | Put("::"); |
2749 | Walk(std::get<Name>(spec.t)); |
2750 | Put(")"); |
2751 | |
2752 | Walk(std::get<OmpClauseList>(z.t)); |
2753 | Put("\n"); |
2754 | EndOpenMP(); |
2755 | } |
2756 | void Unparse(const OpenMPDeclareSimdConstruct &y) { |
2757 | BeginOpenMP(); |
2758 | Word("!$OMP DECLARE SIMD "); |
2759 | Walk("(", std::get<std::optional<Name>>(y.t), ")"); |
2760 | Walk(std::get<OmpClauseList>(y.t)); |
2761 | Put("\n"); |
2762 | EndOpenMP(); |
2763 | } |
2764 | void Unparse(const OpenMPDeclareTargetConstruct &x) { |
2765 | BeginOpenMP(); |
2766 | Word("!$OMP DECLARE TARGET "); |
2767 | Walk(std::get<parser::OmpDeclareTargetSpecifier>(x.t)); |
2768 | Put("\n"); |
2769 | EndOpenMP(); |
2770 | } |
2771 | void Unparse(const OpenMPRequiresConstruct &y) { |
2772 | BeginOpenMP(); |
2773 | Word("!$OMP REQUIRES "); |
2774 | Walk(std::get<OmpClauseList>(y.t)); |
2775 | Put("\n"); |
2776 | EndOpenMP(); |
2777 | } |
2778 | void Unparse(const OpenMPThreadprivate &x) { |
2779 | BeginOpenMP(); |
2780 | Word("!$OMP THREADPRIVATE ("); |
2781 | Walk(std::get<parser::OmpObjectList>(x.t)); |
2782 | Put(")\n"); |
2783 | EndOpenMP(); |
2784 | } |
2785 | |
2786 | bool Pre(const OmpMessageClause &x) { |
2787 | Walk(x.v); |
2788 | return false; |
2789 | } |
2790 | void Unparse(const OmpDispatchDirective &x) { |
2791 | Word("!$OMP DISPATCH"); |
2792 | Walk(x.t); |
2793 | Put("\n"); |
2794 | } |
2795 | void Unparse(const OmpEndDispatchDirective &) { |
2796 | Word("!$OMP END DISPATCH"); |
2797 | Put("\n"); |
2798 | } |
2799 | void Unparse(const OmpErrorDirective &x) { |
2800 | Word("!$OMP ERROR "); |
2801 | Walk(x.t); |
2802 | Put("\n"); |
2803 | } |
2804 | void Unparse(const OmpNothingDirective &x) { |
2805 | Word("!$OMP NOTHING"); |
2806 | Put("\n"); |
2807 | } |
2808 | void Unparse(const OmpSectionsDirective &x) { |
2809 | switch (x.v) { |
2810 | case llvm::omp::Directive::OMPD_sections: |
2811 | Word("SECTIONS "); |
2812 | break; |
2813 | case llvm::omp::Directive::OMPD_parallel_sections: |
2814 | Word("PARALLEL SECTIONS "); |
2815 | break; |
2816 | default: |
2817 | break; |
2818 | } |
2819 | } |
2820 | void Unparse(const OmpSectionBlocks &x) { |
2821 | for (const auto &y : x.v) { |
2822 | BeginOpenMP(); |
2823 | Word("!$OMP SECTION"); |
2824 | Put("\n"); |
2825 | EndOpenMP(); |
2826 | // y.u is an OpenMPSectionConstruct |
2827 | // (y.u).v is Block |
2828 | Walk(std::get<OpenMPSectionConstruct>(y.u).v, ""); |
2829 | } |
2830 | } |
2831 | void Unparse(const OpenMPSectionsConstruct &x) { |
2832 | BeginOpenMP(); |
2833 | Word("!$OMP "); |
2834 | Walk(std::get<OmpBeginSectionsDirective>(x.t)); |
2835 | Put("\n"); |
2836 | EndOpenMP(); |
2837 | Walk(std::get<OmpSectionBlocks>(x.t)); |
2838 | BeginOpenMP(); |
2839 | Word("!$OMP END "); |
2840 | Walk(std::get<OmpEndSectionsDirective>(x.t)); |
2841 | Put("\n"); |
2842 | EndOpenMP(); |
2843 | } |
2844 | // Clause unparsers are usually generated by tablegen in the form |
2845 | // CLAUSE(VALUE). Here we only want to print VALUE so a custom unparser is |
2846 | // needed. |
2847 | void Unparse(const OmpClause::CancellationConstructType &x) { Walk(x.v); } |
2848 | void Unparse(const OpenMPCancellationPointConstruct &x) { |
2849 | BeginOpenMP(); |
2850 | Word("!$OMP "); |
2851 | Walk(x.v); |
2852 | Put("\n"); |
2853 | EndOpenMP(); |
2854 | } |
2855 | void Unparse(const OpenMPCancelConstruct &x) { |
2856 | BeginOpenMP(); |
2857 | Word("!$OMP "); |
2858 | Walk(x.v); |
2859 | Put("\n"); |
2860 | EndOpenMP(); |
2861 | } |
2862 | void Unparse(const OmpFailClause &x) { Walk(x.v); } |
2863 | void Unparse(const OmpMemoryOrderClause &x) { Walk(x.v); } |
2864 | void Unparse(const OmpMetadirectiveDirective &x) { |
2865 | BeginOpenMP(); |
2866 | Word("!$OMP METADIRECTIVE "); |
2867 | Walk(std::get<OmpClauseList>(x.t)); |
2868 | Put("\n"); |
2869 | EndOpenMP(); |
2870 | } |
2871 | void Unparse(const OpenMPDepobjConstruct &x) { |
2872 | BeginOpenMP(); |
2873 | Word("!$OMP "); |
2874 | Walk(x.v); |
2875 | Put("\n"); |
2876 | EndOpenMP(); |
2877 | } |
2878 | void Unparse(const OpenMPFlushConstruct &x) { |
2879 | BeginOpenMP(); |
2880 | Word("!$OMP FLUSH"); |
2881 | using Flags = OmpDirectiveSpecification::Flags; |
2882 | if (std::get<Flags>(x.v.t) == Flags::DeprecatedSyntax) { |
2883 | Walk("(", std::get<std::optional<OmpArgumentList>>(x.v.t), ")"); |
2884 | Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t)); |
2885 | } else { |
2886 | Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t)); |
2887 | Walk(" (", std::get<std::optional<OmpArgumentList>>(x.v.t), ")"); |
2888 | } |
2889 | Put("\n"); |
2890 | EndOpenMP(); |
2891 | } |
2892 | void Unparse(const OmpEndLoopDirective &x) { |
2893 | BeginOpenMP(); |
2894 | Word("!$OMP END "); |
2895 | Walk(std::get<OmpLoopDirective>(x.t)); |
2896 | Walk(std::get<OmpClauseList>(x.t)); |
2897 | Put("\n"); |
2898 | EndOpenMP(); |
2899 | } |
2900 | void Unparse(const OmpClauseList &x, const char *sep = " ") { |
2901 | Walk(" ", x.v, sep); |
2902 | } |
2903 | void Unparse(const OpenMPSimpleStandaloneConstruct &x) { |
2904 | BeginOpenMP(); |
2905 | Word("!$OMP "); |
2906 | Walk(x.v); |
2907 | Put("\n"); |
2908 | EndOpenMP(); |
2909 | } |
2910 | void Unparse(const OpenMPBlockConstruct &x) { |
2911 | BeginOpenMP(); |
2912 | Word("!$OMP "); |
2913 | Walk(std::get<OmpBeginBlockDirective>(x.t)); |
2914 | Put("\n"); |
2915 | EndOpenMP(); |
2916 | Walk(std::get<Block>(x.t), ""); |
2917 | BeginOpenMP(); |
2918 | Word("!$OMP END "); |
2919 | Walk(std::get<OmpEndBlockDirective>(x.t)); |
2920 | Put("\n"); |
2921 | EndOpenMP(); |
2922 | } |
2923 | void Unparse(const OpenMPLoopConstruct &x) { |
2924 | BeginOpenMP(); |
2925 | Word("!$OMP "); |
2926 | Walk(std::get<OmpBeginLoopDirective>(x.t)); |
2927 | Put("\n"); |
2928 | EndOpenMP(); |
2929 | Walk(std::get<std::optional<DoConstruct>>(x.t)); |
2930 | Walk(std::get<std::optional<OmpEndLoopDirective>>(x.t)); |
2931 | } |
2932 | void Unparse(const BasedPointer &x) { |
2933 | Put('('), Walk(std::get<0>(x.t)), Put(","), Walk(std::get<1>(x.t)); |
2934 | Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"), Put(')'); |
2935 | } |
2936 | void Unparse(const BasedPointerStmt &x) { Walk("POINTER ", x.v, ","); } |
2937 | void Unparse(const CUDAAttributesStmt &x) { |
2938 | Word("ATTRIBUTES("), Walk(std::get<common::CUDADataAttr>(x.t)); |
2939 | Word(") "), Walk(std::get<std::list<Name>>(x.t), ", "); |
2940 | } |
2941 | void Post(const StructureField &x) { |
2942 | if (const auto *def{std::get_if<Statement<DataComponentDefStmt>>(&x.u)}) { |
2943 | for (const auto &item : |
2944 | std::get<std::list<ComponentOrFill>>(def->statement.t)) { |
2945 | if (const auto *comp{std::get_if<ComponentDecl>(&item.u)}) { |
2946 | structureComponents_.insert(std::get<Name>(comp->t).source); |
2947 | } |
2948 | } |
2949 | } |
2950 | } |
2951 | void Unparse(const StructureStmt &x) { |
2952 | Word("STRUCTURE "); |
2953 | // The name, if present, includes the /slashes/ |
2954 | Walk(std::get<std::optional<Name>>(x.t)); |
2955 | Walk(" ", std::get<std::list<EntityDecl>>(x.t), ", "); |
2956 | Indent(); |
2957 | } |
2958 | void Post(const Union::UnionStmt &) { Word("UNION"), Indent(); } |
2959 | void Post(const Union::EndUnionStmt &) { Outdent(), Word("END UNION"); } |
2960 | void Post(const Map::MapStmt &) { Word("MAP"), Indent(); } |
2961 | void Post(const Map::EndMapStmt &) { Outdent(), Word("END MAP"); } |
2962 | void Post(const StructureDef::EndStructureStmt &) { |
2963 | Outdent(), Word("END STRUCTURE"); |
2964 | } |
2965 | void Unparse(const OldParameterStmt &x) { |
2966 | Word("PARAMETER "), Walk(x.v, ", "); |
2967 | } |
2968 | void Unparse(const ArithmeticIfStmt &x) { |
2969 | Word("IF ("), Walk(std::get<Expr>(x.t)), Put( ") "); |
2970 | Walk(std::get<1>(x.t)), Put(", "); |
2971 | Walk(std::get<2>(x.t)), Put(", "); |
2972 | Walk(std::get<3>(x.t)); |
2973 | } |
2974 | void Unparse(const AssignStmt &x) { |
2975 | Word("ASSIGN "), Walk(std::get<Label>(x.t)); |
2976 | Word(" TO "), Walk(std::get<Name>(x.t)); |
2977 | } |
2978 | void Unparse(const AssignedGotoStmt &x) { |
2979 | Word("GO TO "), Walk(std::get<Name>(x.t)); |
2980 | Walk(", (", std::get<std::list<Label>>(x.t), ", ", ")"); |
2981 | } |
2982 | void Unparse(const PauseStmt &x) { Word("PAUSE"), Walk( " ", x.v); } |
2983 | |
2984 | #define WALK_NESTED_ENUM(CLASS, ENUM) \ |
2985 | void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); } |
2986 | WALK_NESTED_ENUM(AccDataModifier, Modifier) |
2987 | WALK_NESTED_ENUM(AccessSpec, Kind) // R807 |
2988 | WALK_NESTED_ENUM(common, TypeParamAttr) // R734 |
2989 | WALK_NESTED_ENUM(common, CUDADataAttr) // CUDA |
2990 | WALK_NESTED_ENUM(common, CUDASubprogramAttrs) // CUDA |
2991 | WALK_NESTED_ENUM(IntentSpec, Intent) // R826 |
2992 | WALK_NESTED_ENUM(ImplicitStmt, ImplicitNoneNameSpec) // R866 |
2993 | WALK_NESTED_ENUM(ConnectSpec::CharExpr, Kind) // R1205 |
2994 | WALK_NESTED_ENUM(IoControlSpec::CharExpr, Kind) |
2995 | WALK_NESTED_ENUM(InquireSpec::CharVar, Kind) |
2996 | WALK_NESTED_ENUM(InquireSpec::IntVar, Kind) |
2997 | WALK_NESTED_ENUM(InquireSpec::LogVar, Kind) |
2998 | WALK_NESTED_ENUM(ProcedureStmt, Kind) // R1506 |
2999 | WALK_NESTED_ENUM(UseStmt, ModuleNature) // R1410 |
3000 | WALK_NESTED_ENUM(OmpAdjustArgsClause::OmpAdjustOp, Value) // OMP adjustop |
3001 | WALK_NESTED_ENUM(OmpAtClause, ActionTime) // OMP at |
3002 | WALK_NESTED_ENUM(OmpBindClause, Binding) // OMP bind |
3003 | WALK_NESTED_ENUM(OmpProcBindClause, AffinityPolicy) // OMP proc_bind |
3004 | WALK_NESTED_ENUM(OmpDefaultClause, DataSharingAttribute) // OMP default |
3005 | WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP defaultmap |
3006 | WALK_NESTED_ENUM(OmpVariableCategory, Value) // OMP variable-category |
3007 | WALK_NESTED_ENUM(OmpLastprivateModifier, Value) // OMP lastprivate-modifier |
3008 | WALK_NESTED_ENUM(OmpChunkModifier, Value) // OMP chunk-modifier |
3009 | WALK_NESTED_ENUM(OmpLinearModifier, Value) // OMP linear-modifier |
3010 | WALK_NESTED_ENUM(OmpOrderingModifier, Value) // OMP ordering-modifier |
3011 | WALK_NESTED_ENUM(OmpTaskDependenceType, Value) // OMP task-dependence-type |
3012 | WALK_NESTED_ENUM(OmpScheduleClause, Kind) // OMP schedule-kind |
3013 | WALK_NESTED_ENUM(OmpSeverityClause, Severity) // OMP severity |
3014 | WALK_NESTED_ENUM(OmpDeviceModifier, Value) // OMP device modifier |
3015 | WALK_NESTED_ENUM( |
3016 | OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type |
3017 | WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier |
3018 | WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation |
3019 | WALK_NESTED_ENUM(OmpInteropType, Value) // OMP InteropType |
3020 | WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering |
3021 | WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier |
3022 | WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness |
3023 | WALK_NESTED_ENUM(OmpMapType, Value) // OMP map-type |
3024 | WALK_NESTED_ENUM(OmpMapTypeModifier, Value) // OMP map-type-modifier |
3025 | WALK_NESTED_ENUM(OmpTraitSelectorName, Value) |
3026 | WALK_NESTED_ENUM(OmpTraitSetSelectorName, Value) |
3027 | |
3028 | #undef WALK_NESTED_ENUM |
3029 | void Unparse(const ReductionOperator::Operator x) { |
3030 | switch (x) { |
3031 | case ReductionOperator::Operator::Plus: |
3032 | Word("+"); |
3033 | break; |
3034 | case ReductionOperator::Operator::Multiply: |
3035 | Word("*"); |
3036 | break; |
3037 | case ReductionOperator::Operator::And: |
3038 | Word(".AND."); |
3039 | break; |
3040 | case ReductionOperator::Operator::Or: |
3041 | Word(".OR."); |
3042 | break; |
3043 | case ReductionOperator::Operator::Eqv: |
3044 | Word(".EQV."); |
3045 | break; |
3046 | case ReductionOperator::Operator::Neqv: |
3047 | Word(".NEQV."); |
3048 | break; |
3049 | default: |
3050 | Word(ReductionOperator::EnumToString(x)); |
3051 | break; |
3052 | } |
3053 | } |
3054 | |
3055 | void Unparse(const CUFKernelDoConstruct::StarOrExpr &x) { |
3056 | if (x.v) { |
3057 | Walk(*x.v); |
3058 | } else { |
3059 | Word("*"); |
3060 | } |
3061 | } |
3062 | void Unparse(const CUFKernelDoConstruct::LaunchConfiguration &x) { |
3063 | Word(" <<<"); |
3064 | const auto &grid{std::get<0>(x.t)}; |
3065 | if (grid.empty()) { |
3066 | Word("*"); |
3067 | } else if (grid.size() == 1) { |
3068 | Walk(grid.front()); |
3069 | } else { |
3070 | Walk("(", grid, ",", ")"); |
3071 | } |
3072 | Word(","); |
3073 | const auto &block{std::get<1>(x.t)}; |
3074 | if (block.empty()) { |
3075 | Word("*"); |
3076 | } else if (block.size() == 1) { |
3077 | Walk(block.front()); |
3078 | } else { |
3079 | Walk("(", block, ",", ")"); |
3080 | } |
3081 | if (const auto &stream{std::get<2>(x.t)}) { |
3082 | Word(",STREAM="), Walk(*stream); |
3083 | } |
3084 | Word(">>>"); |
3085 | } |
3086 | void Unparse(const CUFKernelDoConstruct::Directive &x) { |
3087 | Word("!$CUF KERNEL DO"); |
3088 | Walk(" (", std::get<std::optional<ScalarIntConstantExpr>>(x.t), ")"); |
3089 | Walk(std::get<std::optional<CUFKernelDoConstruct::LaunchConfiguration>>( |
3090 | x.t)); |
3091 | Walk(" ", std::get<std::list<CUFReduction>>(x.t), " "); |
3092 | Word("\n"); |
3093 | } |
3094 | void Unparse(const CUFKernelDoConstruct &x) { |
3095 | Walk(std::get<CUFKernelDoConstruct::Directive>(x.t)); |
3096 | Walk(std::get<std::optional<DoConstruct>>(x.t)); |
3097 | } |
3098 | void Unparse(const CUFReduction &x) { |
3099 | Word("REDUCE("); |
3100 | Walk(std::get<CUFReduction::Operator>(x.t)); |
3101 | Walk(":", std::get<std::list<Scalar<Variable>>>(x.t), ",", ")"); |
3102 | } |
3103 | |
3104 | void Done() const { CHECK(indent_ == 0); } |
3105 | |
3106 | private: |
3107 | void Put(char); |
3108 | void Put(const char *); |
3109 | void Put(const std::string &); |
3110 | void PutNormalized(const std::string &); |
3111 | void PutKeywordLetter(char); |
3112 | void Word(const char *); |
3113 | void Word(const std::string &); |
3114 | void Word(const std::string_view &); |
3115 | void Indent() { indent_ += indentationAmount_; } |
3116 | void Outdent() { |
3117 | CHECK(indent_ >= indentationAmount_); |
3118 | indent_ -= indentationAmount_; |
3119 | } |
3120 | void BeginOpenMP() { openmpDirective_ = true; } |
3121 | void EndOpenMP() { openmpDirective_ = false; } |
3122 | void BeginOpenACC() { openaccDirective_ = true; } |
3123 | void EndOpenACC() { openaccDirective_ = false; } |
3124 | |
3125 | // Call back to the traversal framework. |
3126 | template <typename T> void Walk(const T &x) { |
3127 | Fortran::parser::Walk(x, *this); |
3128 | } |
3129 | |
3130 | // Traverse a std::optional<> value. Emit a prefix and/or a suffix string |
3131 | // only when it contains a value. |
3132 | template <typename A> |
3133 | void Walk( |
3134 | const char *prefix, const std::optional<A> &x, const char *suffix = "") { |
3135 | if (x) { |
3136 | Word(prefix), Walk(*x), Word(suffix); |
3137 | } |
3138 | } |
3139 | template <typename A> |
3140 | void Walk(const std::optional<A> &x, const char *suffix = "") { |
3141 | return Walk("", x, suffix); |
3142 | } |
3143 | |
3144 | // Traverse a std::list<>. Separate the elements with an optional string. |
3145 | // Emit a prefix and/or a suffix string only when the list is not empty. |
3146 | template <typename A> |
3147 | void Walk(const char *prefix, const std::list<A> &list, |
3148 | const char *comma = ", ", const char *suffix = "") { |
3149 | if (!list.empty()) { |
3150 | const char *str{prefix}; |
3151 | for (const auto &x : list) { |
3152 | Word(str), Walk(x); |
3153 | str = comma; |
3154 | } |
3155 | Word(suffix); |
3156 | } |
3157 | } |
3158 | template <typename A> |
3159 | void Walk(const std::list<A> &list, const char *comma = ", ", |
3160 | const char *suffix = "") { |
3161 | return Walk("", list, comma, suffix); |
3162 | } |
3163 | |
3164 | // Traverse a std::tuple<>, with an optional separator. |
3165 | template <std::size_t J = 0, typename T> |
3166 | void WalkTupleElements(const T &tuple, const char *separator) { |
3167 | if (J > 0 && J < std::tuple_size_v<T>) { |
3168 | Word(separator); // this usage dodges "unused parameter" warning |
3169 | } |
3170 | if constexpr (J < std::tuple_size_v<T>) { |
3171 | Walk(std::get<J>(tuple)); |
3172 | WalkTupleElements<J + 1>(tuple, separator); |
3173 | } |
3174 | } |
3175 | template <typename... A> |
3176 | void Walk(const std::tuple<A...> &tuple, const char *separator = "") { |
3177 | WalkTupleElements(tuple, separator); |
3178 | } |
3179 | |
3180 | void EndSubprogram(const char *kind, const std::optional<Name> &name) { |
3181 | Outdent(), Word("END "), Word(kind), Walk( " ", name); |
3182 | structureComponents_.clear(); |
3183 | } |
3184 | |
3185 | llvm::raw_ostream &out_; |
3186 | const common::LangOptions &langOpts_; |
3187 | int indent_{0}; |
3188 | const int indentationAmount_{1}; |
3189 | int column_{1}; |
3190 | const int maxColumns_{80}; |
3191 | std::set<CharBlock> structureComponents_; |
3192 | Encoding encoding_{Encoding::UTF_8}; |
3193 | bool capitalizeKeywords_{true}; |
3194 | bool openaccDirective_{false}; |
3195 | bool openmpDirective_{false}; |
3196 | bool backslashEscapes_{false}; |
3197 | preStatementType *preStatement_{nullptr}; |
3198 | AnalyzedObjectsAsFortran *asFortran_{nullptr}; |
3199 | }; |
3200 | |
3201 | void UnparseVisitor::Put(char ch) { |
3202 | int sav = indent_; |
3203 | if (openmpDirective_ || openaccDirective_) { |
3204 | indent_ = 0; |
3205 | } |
3206 | if (column_ <= 1) { |
3207 | if (ch == '\n') { |
3208 | return; |
3209 | } |
3210 | for (int j{0}; j < indent_; ++j) { |
3211 | out_ << ' '; |
3212 | } |
3213 | column_ = indent_ + 2; |
3214 | } else if (ch == '\n') { |
3215 | column_ = 1; |
3216 | } else if (++column_ >= maxColumns_) { |
3217 | out_ << "&\n"; |
3218 | for (int j{0}; j < indent_; ++j) { |
3219 | out_ << ' '; |
3220 | } |
3221 | if (openmpDirective_) { |
3222 | out_ << "!$OMP&"; |
3223 | column_ = 8; |
3224 | } else if (openaccDirective_) { |
3225 | out_ << "!$ACC&"; |
3226 | column_ = 8; |
3227 | } else { |
3228 | out_ << '&'; |
3229 | column_ = indent_ + 3; |
3230 | } |
3231 | } |
3232 | out_ << ch; |
3233 | if (openmpDirective_ || openaccDirective_) { |
3234 | indent_ = sav; |
3235 | } |
3236 | } |
3237 | |
3238 | void UnparseVisitor::Put(const char *str) { |
3239 | for (; *str != '\0'; ++str) { |
3240 | Put(ch: *str); |
3241 | } |
3242 | } |
3243 | |
3244 | void UnparseVisitor::Put(const std::string &str) { |
3245 | for (char ch : str) { |
3246 | Put(ch); |
3247 | } |
3248 | } |
3249 | |
3250 | void UnparseVisitor::PutNormalized(const std::string &str) { |
3251 | auto decoded{DecodeString<std::string, Encoding::LATIN_1>(str, true)}; |
3252 | std::string encoded{EncodeString<Encoding::LATIN_1>(decoded)}; |
3253 | Put(QuoteCharacterLiteral(encoded, backslashEscapes_)); |
3254 | } |
3255 | |
3256 | void UnparseVisitor::PutKeywordLetter(char ch) { |
3257 | if (capitalizeKeywords_) { |
3258 | Put(ToUpperCaseLetter(ch)); |
3259 | } else { |
3260 | Put(ToLowerCaseLetter(ch)); |
3261 | } |
3262 | } |
3263 | |
3264 | void UnparseVisitor::Word(const char *str) { |
3265 | for (; *str != '\0'; ++str) { |
3266 | PutKeywordLetter(ch: *str); |
3267 | } |
3268 | } |
3269 | |
3270 | void UnparseVisitor::Word(const std::string &str) { Word(str: str.c_str()); } |
3271 | |
3272 | void UnparseVisitor::Word(const std::string_view &str) { |
3273 | for (std::size_t j{0}; j < str.length(); ++j) { |
3274 | PutKeywordLetter(ch: str[j]); |
3275 | } |
3276 | } |
3277 | |
3278 | template <typename A> |
3279 | void Unparse(llvm::raw_ostream &out, const A &root, |
3280 | const common::LangOptions &langOpts, Encoding encoding, |
3281 | bool capitalizeKeywords, bool backslashEscapes, |
3282 | preStatementType *preStatement, AnalyzedObjectsAsFortran *asFortran) { |
3283 | UnparseVisitor visitor{out, langOpts, 1, encoding, capitalizeKeywords, |
3284 | backslashEscapes, preStatement, asFortran}; |
3285 | Walk(root, visitor); |
3286 | visitor.Done(); |
3287 | } |
3288 | |
3289 | template void Unparse<Program>(llvm::raw_ostream &, const Program &, |
3290 | const common::LangOptions &, Encoding, bool, bool, preStatementType *, |
3291 | AnalyzedObjectsAsFortran *); |
3292 | template void Unparse<Expr>(llvm::raw_ostream &, const Expr &, |
3293 | const common::LangOptions &, Encoding, bool, bool, preStatementType *, |
3294 | AnalyzedObjectsAsFortran *); |
3295 | |
3296 | template void Unparse<parser::OpenMPDeclareReductionConstruct>( |
3297 | llvm::raw_ostream &, const parser::OpenMPDeclareReductionConstruct &, |
3298 | const common::LangOptions &, Encoding, bool, bool, preStatementType *, |
3299 | AnalyzedObjectsAsFortran *); |
3300 | template void Unparse<parser::OmpMetadirectiveDirective>(llvm::raw_ostream &, |
3301 | const parser::OmpMetadirectiveDirective &, const common::LangOptions &, |
3302 | Encoding, bool, bool, preStatementType *, AnalyzedObjectsAsFortran *); |
3303 | } // namespace Fortran::parser |
3304 |
Definitions
- UnparseVisitor
- UnparseVisitor
- Before
- Pre
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Post
- Unparse
- Unparse
- Unparse
- Post
- Post
- Unparse
- Unparse
- Post
- Post
- Unparse
- Before
- Before
- Post
- Before
- Before
- Post
- Before
- Before
- Post
- Post
- Post
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Post
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Post
- Post
- Post
- Post
- Post
- Post
- Post
- Post
- Post
- Post
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Before
- Before
- Unparse
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Unparse
- Before
- Before
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Unparse
- Unparse
- Before
- Unparse
- Before
- Unparse
- Unparse
- Pre
- Unparse
- Before
- Unparse
- Unparse
- Unparse
- Pre
- Unparse
- Unparse
- Unparse
- Before
- Unparse
- Unparse
- Unparse
- Before
- Unparse
- Unparse
- Pre
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Before
- Unparse
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Post
- Post
- Post
- Post
- Post
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Before
- Before
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Pre
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Post
- Unparse
- Post
- Post
- Post
- Post
- Post
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Unparse
- Done
- Indent
- Outdent
- BeginOpenMP
- EndOpenMP
- BeginOpenACC
- EndOpenACC
- Walk
- Walk
- Walk
- Walk
- Walk
- WalkTupleElements
- Walk
- EndSubprogram
- Put
- Put
- Put
- PutNormalized
- PutKeywordLetter
- Word
- Word
- Word
Improve your Profiling and Debugging skills
Find out more