blob: 73fb8e623a90c886c365b28009b35a6c0bfe0850 [file] [log] [blame]
peter klausler79d044e2018-03-01 00:56:101// Generates Fortran from the content of a parse tree, using the
2// traversal templates in parse-tree-visitor.h.
3
Tim Keith2af29bc2018-02-26 22:28:324#include "unparse.h"
peter klausler79d044e2018-03-01 00:56:105#include "characters.h"
Tim Keith2af29bc2018-02-26 22:28:326#include "idioms.h"
7#include "indirection.h"
8#include "parse-tree-visitor.h"
9#include "parse-tree.h"
peter klausler79d044e2018-03-01 00:56:1010#include <algorithm>
Tim Keith2af29bc2018-02-26 22:28:3211
12namespace Fortran {
13namespace parser {
14
15class UnparseVisitor {
16public:
peter klauslerb7cf5122018-03-14 22:31:1617 UnparseVisitor(std::ostream &out, int indentationAmount, Encoding encoding,
18 bool capitalize)
19 : out_{out}, indentationAmount_{indentationAmount}, encoding_{encoding},
20 capitalizeKeywords_{capitalize} {}
Tim Keith2af29bc2018-02-26 22:28:3221
peter klausler79d044e2018-03-01 00:56:1022 // Default actions: just traverse the children
Tim Keith2af29bc2018-02-26 22:28:3223 template<typename T> bool Pre(const T &x) { return true; }
Tim Keith2af29bc2018-02-26 22:28:3224 template<typename T> void Post(const T &) {}
25
Tim Keith2af29bc2018-02-26 22:28:3226 // Emit simple types as-is.
27 bool Pre(const std::string &x) {
28 Put(x);
29 return false;
30 }
31 bool Pre(int x) {
32 Put(std::to_string(x));
33 return false;
34 }
35 bool Pre(std::uint64_t x) {
36 Put(std::to_string(x));
37 return false;
38 }
39 bool Pre(std::int64_t x) {
40 Put(std::to_string(x));
41 return false;
42 }
43 bool Pre(char x) {
44 Put(x);
45 return false;
46 }
47
peter klausler79d044e2018-03-01 00:56:1048 // Statement labels and ends of lines
49 template<typename T> bool Pre(const Statement<T> &x) {
50 Walk(x.label, " ");
51 return true;
Tim Keith2af29bc2018-02-26 22:28:3252 }
peter klausler79d044e2018-03-01 00:56:1053 template<typename T> void Post(const Statement<T> &) { Put('\n'); }
54
55 // The special-case formatting functions for these productions are
56 // ordered to correspond roughly to their order of appearance in
57 // the Fortran 2018 standard (and parse-tree.h).
58
59 void Post(const ProgramUnit &x) { // R502, R503
60 out_ << '\n'; // blank line after each ProgramUnit
Tim Keith2af29bc2018-02-26 22:28:3261 }
peter klausler79d044e2018-03-01 00:56:1062 bool Pre(const DefinedOperator::IntrinsicOperator &x) { // R608
63 switch (x) {
64 case DefinedOperator::IntrinsicOperator::Power: Put("**"); break;
65 case DefinedOperator::IntrinsicOperator::Multiply: Put('*'); break;
66 case DefinedOperator::IntrinsicOperator::Divide: Put('/'); break;
67 case DefinedOperator::IntrinsicOperator::Add: Put('+'); break;
68 case DefinedOperator::IntrinsicOperator::Subtract: Put('-'); break;
69 case DefinedOperator::IntrinsicOperator::Concat: Put("//"); break;
70 case DefinedOperator::IntrinsicOperator::LT: Put('<'); break;
71 case DefinedOperator::IntrinsicOperator::LE: Put("<="); break;
72 case DefinedOperator::IntrinsicOperator::EQ: Put("=="); break;
73 case DefinedOperator::IntrinsicOperator::NE: Put("/="); break;
74 case DefinedOperator::IntrinsicOperator::GE: Put(">="); break;
75 case DefinedOperator::IntrinsicOperator::GT: Put('>'); break;
76 default:
peter klausler62d9cdd2018-03-15 00:02:2177 Put('.');
peter klausler79d044e2018-03-01 00:56:1078 PutEnum(static_cast<int>(x), DefinedOperator::IntrinsicOperatorAsString);
peter klausler62d9cdd2018-03-15 00:02:2179 Put('.');
Tim Keith2af29bc2018-02-26 22:28:3280 }
81 return false;
82 }
peter klausler79d044e2018-03-01 00:56:1083 void Post(const Star &) { Put('*'); } // R701 &c.
84 void Post(const TypeParamValue::Deferred &) { Put(':'); } // R701
85 bool Pre(const DeclarationTypeSpec::Type &x) { // R703
peter klauslerb7cf5122018-03-14 22:31:1686 Word("TYPE("), Walk(x.derived), Put(')');
Tim Keith2af29bc2018-02-26 22:28:3287 return false;
88 }
peter klausler79d044e2018-03-01 00:56:1089 bool Pre(const DeclarationTypeSpec::Class &x) {
peter klauslerb7cf5122018-03-14 22:31:1690 Word("CLASS("), Walk(x.derived), Put(')');
Tim Keith2af29bc2018-02-26 22:28:3291 return false;
92 }
peter klauslerb7cf5122018-03-14 22:31:1693 void Post(const DeclarationTypeSpec::ClassStar &) { Word("CLASS(*)"); }
94 void Post(const DeclarationTypeSpec::TypeStar &) { Word("TYPE(*)"); }
peter klausler79d044e2018-03-01 00:56:1095 bool Pre(const DeclarationTypeSpec::Record &x) {
peter klauslerb7cf5122018-03-14 22:31:1696 Word("RECORD/"), Walk(x.v), Put('/');
Tim Keith2af29bc2018-02-26 22:28:3297 return false;
98 }
peter klausler79d044e2018-03-01 00:56:1099 bool Pre(const IntrinsicTypeSpec::Real &x) { // R704
peter klauslerb7cf5122018-03-14 22:31:16100 Word("REAL");
Tim Keith2af29bc2018-02-26 22:28:32101 return true;
102 }
103 bool Pre(const IntrinsicTypeSpec::Complex &x) {
peter klauslerb7cf5122018-03-14 22:31:16104 Word("COMPLEX");
Tim Keith2af29bc2018-02-26 22:28:32105 return true;
106 }
peter klausler79d044e2018-03-01 00:56:10107 void Post(const IntrinsicTypeSpec::DoublePrecision &) {
peter klauslerb7cf5122018-03-14 22:31:16108 Word("DOUBLE PRECISION");
peter klausler79d044e2018-03-01 00:56:10109 }
110 bool Pre(const IntrinsicTypeSpec::Character &x) {
peter klauslerb7cf5122018-03-14 22:31:16111 Word("CHARACTER");
Tim Keith2af29bc2018-02-26 22:28:32112 return true;
113 }
114 bool Pre(const IntrinsicTypeSpec::Logical &x) {
peter klauslerb7cf5122018-03-14 22:31:16115 Word("LOGICAL");
Tim Keith2af29bc2018-02-26 22:28:32116 return true;
117 }
peter klauslerb7cf5122018-03-14 22:31:16118 void Post(const IntrinsicTypeSpec::DoubleComplex &) {
119 Word("DOUBLE COMPLEX");
120 }
Tim Keith2af29bc2018-02-26 22:28:32121 bool Pre(const IntrinsicTypeSpec::NCharacter &x) {
peter klauslerb7cf5122018-03-14 22:31:16122 Word("NCHARACTER");
Tim Keith2af29bc2018-02-26 22:28:32123 return true;
124 }
peter klausler79d044e2018-03-01 00:56:10125 bool Pre(const IntegerTypeSpec &x) { // R705
peter klauslerb7cf5122018-03-14 22:31:16126 Word("INTEGER");
Tim Keith2af29bc2018-02-26 22:28:32127 return true;
128 }
peter klausler79d044e2018-03-01 00:56:10129 bool Pre(const KindSelector &x) { // R706
130 std::visit(
131 visitors{[&](const ScalarIntConstantExpr &y) {
peter klauslerb7cf5122018-03-14 22:31:16132 Put('('), Word("KIND="), Walk(y), Put(')');
peter klausler79d044e2018-03-01 00:56:10133 },
134 [&](const KindSelector::StarSize &y) { Put('*'), Walk(y.v); }},
135 x.u);
136 return false;
137 }
138 bool Pre(const SignedIntLiteralConstant &x) { // R707
139 Walk(std::get<std::int64_t>(x.t));
140 Walk("_", std::get<std::optional<KindParam>>(x.t));
141 return false;
142 }
143 bool Pre(const IntLiteralConstant &x) { // R708
144 Walk(std::get<std::uint64_t>(x.t));
145 Walk("_", std::get<std::optional<KindParam>>(x.t));
146 return false;
147 }
148 bool Pre(const Sign &x) { // R712
149 Put(x == Sign::Negative ? '-' : '+');
150 return false;
151 }
152 bool Pre(const RealLiteralConstant &x) { // R714, R715
153 Put(x.intPart), Put('.'), Put(x.fraction), Walk(x.exponent);
154 Walk("_", x.kind);
155 return false;
156 }
157 bool Pre(const ComplexLiteralConstant &x) { // R718 - R720
158 Put('('), Walk(x.t, ","), Put(')');
159 return false;
160 }
161 bool Pre(const CharSelector::LengthAndKind &x) { // R721
peter klauslerb7cf5122018-03-14 22:31:16162 Put('('), Word("KIND="), Walk(x.kind);
163 Walk(", LEN=", x.length), Put(')');
peter klausler79d044e2018-03-01 00:56:10164 return false;
165 }
166 bool Pre(const LengthSelector &x) { // R722
167 std::visit(visitors{[&](const TypeParamValue &y) {
peter klauslerb7cf5122018-03-14 22:31:16168 Put('('), Word("LEN="), Walk(y), Put(')');
peter klausler79d044e2018-03-01 00:56:10169 },
170 [&](const CharLength &y) { Put('*'), Walk(y); }},
171 x.u);
172 return false;
173 }
174 bool Pre(const CharLength &x) { // R723
175 std::visit(
176 visitors{[&](const TypeParamValue &y) { Put('('), Walk(y), Put(')'); },
177 [&](const std::int64_t &y) { Walk(y); }},
178 x.u);
179 return false;
180 }
181 bool Pre(const CharLiteralConstant &x) { // R724
182 if (const auto &k = std::get<std::optional<KindParam>>(x.t)) {
183 if (std::holds_alternative<KindParam::Kanji>(k->u)) {
peter klauslerb7cf5122018-03-14 22:31:16184 Word("NC");
peter klausler79d044e2018-03-01 00:56:10185 } else {
186 Walk(*k), Put('_');
187 }
188 }
189 PutQuoted(std::get<std::string>(x.t));
190 return false;
191 }
192 bool Pre(const HollerithLiteralConstant &x) {
193 std::optional<size_t> chars{CountCharacters(x.v.data(), x.v.size(),
194 encoding_ == Encoding::EUC_JP ? EUC_JPCharacterBytes
195 : UTF8CharacterBytes)};
196 if (chars.has_value()) {
197 Pre(*chars);
198 } else {
199 Pre(x.v.size());
200 }
201 Put('H');
Tim Keith2af29bc2018-02-26 22:28:32202 return true;
203 }
peter klausler79d044e2018-03-01 00:56:10204 bool Pre(const LogicalLiteralConstant &x) { // R725
peter klausler42b72c42018-03-15 17:59:46205 Put(std::get<bool>(x.t) ? ".TRUE." : ".FALSE.");
206 Walk("_", std::get<std::optional<KindParam>>(x.t));
Tim Keith2af29bc2018-02-26 22:28:32207 return false;
208 }
peter klausler79d044e2018-03-01 00:56:10209 bool Pre(const DerivedTypeStmt &x) { // R727
peter klauslerb7cf5122018-03-14 22:31:16210 Word("TYPE"), Walk(", ", std::get<std::list<TypeAttrSpec>>(x.t), ", ");
peter klausler79d044e2018-03-01 00:56:10211 Put(" :: "), Put(std::get<Name>(x.t));
212 Walk("(", std::get<std::list<Name>>(x.t), ", ", ")");
Tim Keith2af29bc2018-02-26 22:28:32213 Indent();
214 return false;
215 }
peter klausler79d044e2018-03-01 00:56:10216 bool Pre(const Abstract &x) { // R728, &c.
peter klauslerb7cf5122018-03-14 22:31:16217 Word("ABSTRACT");
Tim Keith2af29bc2018-02-26 22:28:32218 return false;
219 }
peter klauslerd71f3cf2018-03-14 23:31:41220 void Post(const TypeAttrSpec::BindC &) { Word("BIND(C)"); }
Tim Keith2af29bc2018-02-26 22:28:32221 bool Pre(const TypeAttrSpec::Extends &x) {
peter klauslerb7cf5122018-03-14 22:31:16222 Word("EXTENDS("), Walk(x.v), Put(')');
Tim Keith2af29bc2018-02-26 22:28:32223 return false;
224 }
peter klausler46c35382018-03-14 00:11:26225 bool Pre(const EndTypeStmt &x) { // R730
peter klauslerb7cf5122018-03-14 22:31:16226 Outdent(), Word("END TYPE"), Walk(" ", x.v);
peter klausler46c35382018-03-14 00:11:26227 return false;
peter klausler79d044e2018-03-01 00:56:10228 }
229 bool Pre(const SequenceStmt &x) { // R731
peter klauslerb7cf5122018-03-14 22:31:16230 Word("SEQUENCE");
Tim Keith2af29bc2018-02-26 22:28:32231 return false;
232 }
peter klausler79d044e2018-03-01 00:56:10233 bool Pre(const TypeParamDefStmt &x) { // R732
234 Walk(std::get<IntegerTypeSpec>(x.t));
235 Put(", "), Walk(std::get<TypeParamDefStmt::KindOrLen>(x.t));
236 Put(" :: "), Walk(std::get<std::list<TypeParamDecl>>(x.t), ", ");
Tim Keith2af29bc2018-02-26 22:28:32237 return false;
238 }
peter klausler79d044e2018-03-01 00:56:10239 bool Pre(const TypeParamDecl &x) { // R733
240 Put(std::get<Name>(x.t));
241 Walk("=", std::get<std::optional<ScalarIntConstantExpr>>(x.t));
Tim Keith2af29bc2018-02-26 22:28:32242 return false;
243 }
peter klausler79d044e2018-03-01 00:56:10244 bool Pre(const DataComponentDefStmt &x) { // R737
245 const auto &dts = std::get<DeclarationTypeSpec>(x.t);
246 const auto &attrs = std::get<std::list<ComponentAttrSpec>>(x.t);
247 const auto &decls = std::get<std::list<ComponentDecl>>(x.t);
248 Walk(dts), Walk(", ", attrs, ", ");
249 if (!attrs.empty() ||
250 (!std::holds_alternative<DeclarationTypeSpec::Record>(dts.u) &&
251 std::none_of(
252 decls.begin(), decls.end(), [](const ComponentDecl &d) {
253 const auto &init =
254 std::get<std::optional<Initialization>>(d.t);
255 return init.has_value() &&
256 std::holds_alternative<
257 std::list<Indirection<DataStmtValue>>>(init->u);
258 }))) {
259 Put(" ::");
260 }
261 Put(' '), Walk(decls, ", ");
Tim Keith2af29bc2018-02-26 22:28:32262 return false;
263 }
peter klausler79d044e2018-03-01 00:56:10264 bool Pre(const Allocatable &x) { // R738
peter klauslerb7cf5122018-03-14 22:31:16265 Word("ALLOCATABLE");
Tim Keith2af29bc2018-02-26 22:28:32266 return false;
267 }
268 bool Pre(const Pointer &x) {
peter klauslerb7cf5122018-03-14 22:31:16269 Word("POINTER");
Tim Keith2af29bc2018-02-26 22:28:32270 return false;
271 }
peter klausler79d044e2018-03-01 00:56:10272 bool Pre(const Contiguous &x) {
peter klauslerb7cf5122018-03-14 22:31:16273 Word("CONTIGUOUS");
peter klausler79d044e2018-03-01 00:56:10274 return false;
275 }
276 bool Pre(const ComponentAttrSpec &x) {
peter klauslerb7cf5122018-03-14 22:31:16277 std::visit(visitors{[&](const CoarraySpec &) { Word("CODIMENSION["); },
278 [&](const ComponentArraySpec &) { Word("DIMENSION("); },
peter klauslerd71f3cf2018-03-14 23:31:41279 [](const auto &) {}},
peter klausler79d044e2018-03-01 00:56:10280 x.u);
Tim Keith2af29bc2018-02-26 22:28:32281 return true;
282 }
peter klausler79d044e2018-03-01 00:56:10283 void Post(const ComponentAttrSpec &x) {
peter klauslerd71f3cf2018-03-14 23:31:41284 std::visit(
285 visitors{[&](const CoarraySpec &) { Put(']'); },
286 [&](const ComponentArraySpec &) { Put(')'); }, [](const auto &) {}},
peter klausler79d044e2018-03-01 00:56:10287 x.u);
288 }
289 bool Pre(const ComponentDecl &x) { // R739
290 Walk(std::get<ObjectName>(x.t));
291 Walk("(", std::get<std::optional<ComponentArraySpec>>(x.t), ")");
292 Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]");
293 Walk("*", std::get<std::optional<CharLength>>(x.t));
294 Walk(std::get<std::optional<Initialization>>(x.t));
295 return false;
296 }
297 bool Pre(const ComponentArraySpec &x) { // R740
298 std::visit(
299 visitors{[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
300 [&](const DeferredShapeSpecList &y) { Walk(y); }},
301 x.u);
302 return false;
303 }
304 bool Pre(const ProcComponentDefStmt &x) { // R741
peter klauslerb7cf5122018-03-14 22:31:16305 Word("PROCEDURE(");
peter klausler79d044e2018-03-01 00:56:10306 Walk(std::get<std::optional<ProcInterface>>(x.t)), Put(')');
307 Walk(", ", std::get<std::list<ProcComponentAttrSpec>>(x.t), ", ");
308 Put(" :: "), Walk(std::get<std::list<ProcDecl>>(x.t), ", ");
309 return false;
310 }
311 bool Pre(const NoPass &x) { // R742
peter klauslerb7cf5122018-03-14 22:31:16312 Word("NOPASS");
peter klausler79d044e2018-03-01 00:56:10313 return false;
314 }
315 bool Pre(const Pass &x) {
peter klauslerb7cf5122018-03-14 22:31:16316 Word("PASS"), Walk("(", x.v, ")");
peter klausler79d044e2018-03-01 00:56:10317 return false;
318 }
319 bool Pre(const Initialization &x) { // R743 & R805
320 std::visit(visitors{[&](const ConstantExpr &y) { Put(" = "), Walk(y); },
321 [&](const NullInit &y) { Put(" => "), Walk(y); },
322 [&](const InitialDataTarget &y) { Put(" => "), Walk(y); },
323 [&](const std::list<Indirection<DataStmtValue>> &y) {
324 Walk("/", y, ", ", "/");
325 }},
326 x.u);
327 return false;
328 }
329 bool Pre(const PrivateStmt &x) { // R745
peter klauslerb7cf5122018-03-14 22:31:16330 Word("PRIVATE");
peter klausler79d044e2018-03-01 00:56:10331 return false;
332 }
333 bool Pre(const TypeBoundProcedureStmt::WithoutInterface &x) { // R749
peter klauslerb7cf5122018-03-14 22:31:16334 Word("PROCEDURE"), Walk(", ", x.attributes, ", ");
peter klauslerdcd09422018-03-15 23:03:28335 Put(" :: "), Walk(x.declarations, ", ");
peter klausler79d044e2018-03-01 00:56:10336 return false;
337 }
338 bool Pre(const TypeBoundProcedureStmt::WithInterface &x) {
peter klauslerb7cf5122018-03-14 22:31:16339 Word("PROCEDURE("), Walk(x.interfaceName), Put("), ");
peter klausler79d044e2018-03-01 00:56:10340 Walk(x.attributes);
peter klauslerdcd09422018-03-15 23:03:28341 Put(" :: "), Walk(x.bindingNames, ", ");
peter klausler79d044e2018-03-01 00:56:10342 return false;
343 }
344 bool Pre(const TypeBoundProcDecl &x) { // R750
345 Walk(std::get<Name>(x.t));
346 Walk(" => ", std::get<std::optional<Name>>(x.t));
347 return false;
348 }
349 bool Pre(const TypeBoundGenericStmt &x) { // R751
peter klauslerb7cf5122018-03-14 22:31:16350 Word("GENERIC"), Walk(", ", std::get<std::optional<AccessSpec>>(x.t));
peter klausler79d044e2018-03-01 00:56:10351 Put(" :: "), Walk(std::get<Indirection<GenericSpec>>(x.t));
352 Put(" => "), Walk(std::get<std::list<Name>>(x.t), ", ");
353 return false;
354 }
peter klauslerb7cf5122018-03-14 22:31:16355 void Post(const BindAttr::Deferred &) { Word("DEFERRED"); } // R752
356 void Post(const BindAttr::Non_Overridable &) { Word("NON_OVERRIDABLE"); }
peter klausler62d9cdd2018-03-15 00:02:21357 bool Pre(const FinalProcedureStmt &x) { // R753
358 Word("FINAL :: "), Walk(x.v, ", ");
359 return false;
peter klauslerb7cf5122018-03-14 22:31:16360 }
peter klausler79d044e2018-03-01 00:56:10361 bool Pre(const DerivedTypeSpec &x) { // R754
362 Walk(std::get<Name>(x.t));
363 Walk("(", std::get<std::list<TypeParamSpec>>(x.t), ",", ")");
364 return false;
365 }
366 bool Pre(const TypeParamSpec &x) { // R755
367 Walk(std::get<std::optional<Keyword>>(x.t), "=");
368 Walk(std::get<TypeParamValue>(x.t));
369 return false;
370 }
371 bool Pre(const StructureConstructor &x) { // R756
372 Walk(std::get<DerivedTypeSpec>(x.t));
373 Put('('), Walk(std::get<std::list<ComponentSpec>>(x.t), ", "), Put(')');
374 return false;
375 }
376 bool Pre(const ComponentSpec &x) { // R757
377 Walk(std::get<std::optional<Keyword>>(x.t), "=");
378 Walk(std::get<ComponentDataSource>(x.t));
379 return false;
380 }
381 bool Pre(const EnumDefStmt &) { // R760
peter klausler62d9cdd2018-03-15 00:02:21382 Word("ENUM, BIND(C)"), Indent();
peter klausler79d044e2018-03-01 00:56:10383 return false;
384 }
peter klausler62d9cdd2018-03-15 00:02:21385 bool Pre(const EnumeratorDefStmt &x) { // R761
386 Word("ENUMERATOR :: "), Walk(x.v, ", ");
387 return false;
peter klausler79d044e2018-03-01 00:56:10388 }
389 bool Pre(const Enumerator &x) { // R762
390 Walk(std::get<NamedConstant>(x.t));
391 Walk(" = ", std::get<std::optional<ScalarIntConstantExpr>>(x.t));
392 return false;
393 }
394 void Post(const EndEnumStmt &) { // R763
peter klausler62d9cdd2018-03-15 00:02:21395 Outdent(), Word("END ENUM");
peter klausler79d044e2018-03-01 00:56:10396 }
397 bool Pre(const BOZLiteralConstant &x) { // R764 - R767
398 Put("Z'");
399 out_ << std::hex << x.v << std::dec << '\'';
400 return false;
401 }
402 bool Pre(const AcValue::Triplet &x) { // R773
403 Walk(std::get<0>(x.t)), Put(':'), Walk(std::get<1>(x.t));
404 Walk(":", std::get<std::optional<ScalarIntExpr>>(x.t));
405 return false;
406 }
407 bool Pre(const ArrayConstructor &x) { // R769
408 Put('['), Walk(x.v), Put(']');
409 return false;
410 }
411 bool Pre(const AcSpec &x) { // R770
412 Walk(x.type, "::"), Walk(x.values, ", ");
413 return false;
414 }
415 template<typename A> bool Pre(const LoopBounds<A> &x) {
416 Walk(x.name), Put('='), Walk(x.lower), Put(','), Walk(x.upper);
417 Walk(",", x.step);
418 return false;
419 }
peter klausler46c35382018-03-14 00:11:26420 bool Pre(const AcImpliedDo &x) { // R774
421 Put('('), Walk(std::get<std::list<AcValue>>(x.t), ", ");
422 Put(", "), Walk(std::get<AcImpliedDoControl>(x.t)), Put(')');
423 return false;
424 }
peter klausler79d044e2018-03-01 00:56:10425 bool Pre(const AcImpliedDoControl &x) { // R775
426 Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::");
427 Walk(std::get<LoopBounds<ScalarIntExpr>>(x.t));
Tim Keith2af29bc2018-02-26 22:28:32428 return false;
429 }
430
peter klausler79d044e2018-03-01 00:56:10431 bool Pre(const TypeDeclarationStmt &x) { // R801
432 const auto &dts = std::get<DeclarationTypeSpec>(x.t);
433 const auto &attrs = std::get<std::list<AttrSpec>>(x.t);
434 const auto &decls = std::get<std::list<EntityDecl>>(x.t);
435 Walk(dts), Walk(", ", attrs, ", ");
peter klauslerdcd09422018-03-15 23:03:28436 if (!std::holds_alternative<DeclarationTypeSpec::Record>(dts.u) &&
peter klausler2e5300c2018-03-15 23:22:38437 std::none_of(decls.begin(), decls.end(),
438 [](const EntityDecl &d) {
439 return std::get<std::optional<Initialization>>(d.t).has_value();
440 }) &&
441 (!attrs.empty() || !std::holds_alternative<IntrinsicTypeSpec>(dts.u) ||
442 std::any_of(decls.begin(), decls.end(), [](const EntityDecl &d) {
443 return std::get<std::optional<Initialization>>(d.t).has_value();
444 }))) {
peter klauslerdcd09422018-03-15 23:03:28445 Put(" ::"); // N.B. don't emit some needless ::, pgf90 can crash on them
Tim Keith2af29bc2018-02-26 22:28:32446 }
peter klausler79d044e2018-03-01 00:56:10447 Put(' '), Walk(std::get<std::list<EntityDecl>>(x.t), ", ");
448 return false;
449 }
peter klauslerd39a33f2018-03-13 23:59:30450 bool Pre(const AttrSpec &x) { // R802
peter klauslerb7cf5122018-03-14 22:31:16451 std::visit(visitors{[&](const CoarraySpec &y) { Word("CODIMENSION["); },
452 [&](const ArraySpec &y) { Word("DIMENSION("); },
peter klauslerd71f3cf2018-03-14 23:31:41453 [](const auto &) {}},
peter klauslerd39a33f2018-03-13 23:59:30454 x.u);
455 return true;
456 }
457 void Post(const AttrSpec &x) {
458 std::visit(visitors{[&](const CoarraySpec &y) { Put(']'); },
peter klauslerd71f3cf2018-03-14 23:31:41459 [&](const ArraySpec &y) { Put(')'); }, [](const auto &) {}},
peter klauslerd39a33f2018-03-13 23:59:30460 x.u);
461 }
peter klausler79d044e2018-03-01 00:56:10462 bool Pre(const EntityDecl &x) { // R803
463 Walk(std::get<ObjectName>(x.t));
464 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")");
465 Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]");
466 Walk("*", std::get<std::optional<CharLength>>(x.t));
467 Walk(std::get<std::optional<Initialization>>(x.t));
468 return false;
469 }
470 bool Pre(const NullInit &x) { // R806
peter klauslerb7cf5122018-03-14 22:31:16471 Word("NULL()");
peter klausler79d044e2018-03-01 00:56:10472 return false;
473 }
474 bool Pre(const LanguageBindingSpec &x) { // R808 & R1528
peter klauslerb7cf5122018-03-14 22:31:16475 Word("BIND(C"), Walk(", NAME=", x.v), Put(')');
peter klausler79d044e2018-03-01 00:56:10476 return false;
477 }
478 bool Pre(const CoarraySpec &x) { // R809
479 std::visit(visitors{[&](const DeferredCoshapeSpecList &y) { Walk(y); },
480 [&](const ExplicitCoshapeSpec &y) { Walk(y); }},
481 x.u);
482 return false;
483 }
peter klauslerb7cf5122018-03-14 22:31:16484 bool Pre(const DeferredCoshapeSpecList &x) { // R810
peter klausler79d044e2018-03-01 00:56:10485 for (auto j = x.v; j > 0; --j) {
486 Put(':');
487 if (j > 1) {
488 Put(',');
Tim Keith2af29bc2018-02-26 22:28:32489 }
490 }
peter klausler79d044e2018-03-01 00:56:10491 return false;
Tim Keith2af29bc2018-02-26 22:28:32492 }
peter klausler79d044e2018-03-01 00:56:10493 bool Pre(const ExplicitCoshapeSpec &x) { // R811
494 Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ",");
495 Walk(std::get<std::optional<SpecificationExpr>>(x.t), ":"), Put('*');
496 return false;
Tim Keith2af29bc2018-02-26 22:28:32497 }
peter klausler79d044e2018-03-01 00:56:10498 bool Pre(const ExplicitShapeSpec &x) { // R812 - R813 & R816 - R818
499 Walk(std::get<std::optional<SpecificationExpr>>(x.t), ":");
500 Walk(std::get<SpecificationExpr>(x.t));
501 return false;
502 }
503 bool Pre(const ArraySpec &x) { // R815
504 std::visit(
505 visitors{[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
506 [&](const std::list<AssumedShapeSpec> &y) { Walk(y, ","); },
507 [&](const DeferredShapeSpecList &y) { Walk(y); },
508 [&](const AssumedSizeSpec &y) { Walk(y); },
509 [&](const ImpliedShapeSpec &y) { Walk(y); },
510 [&](const AssumedRankSpec &y) { Walk(y); }},
511 x.u);
512 return false;
513 }
514 void Post(const AssumedShapeSpec &) { Put(':'); } // R819
peter klauslerb7cf5122018-03-14 22:31:16515 bool Pre(const DeferredShapeSpecList &x) { // R820
peter klausler79d044e2018-03-01 00:56:10516 for (auto j = x.v; j > 0; --j) {
517 Put(':');
518 if (j > 1) {
519 Put(',');
520 }
521 }
522 return false;
523 }
524 bool Pre(const AssumedImpliedSpec &x) { // R821
525 Walk(x.v, ":");
526 Put('*');
527 return false;
528 }
529 bool Pre(const AssumedSizeSpec &x) { // R822
530 Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ",");
531 Walk(std::get<AssumedImpliedSpec>(x.t));
532 return false;
533 }
534 bool Pre(const ImpliedShapeSpec &x) { // R823
535 Walk(x.v, ",");
536 return false;
537 }
538 void Post(const AssumedRankSpec &) { Put(".."); } // R825
peter klauslerb7cf5122018-03-14 22:31:16539 void Post(const Asynchronous &) { Word("ASYNCHRONOUS"); }
540 void Post(const External &) { Word("EXTERNAL"); }
541 void Post(const Intrinsic &) { Word("INTRINSIC"); }
542 void Post(const Optional &) { Word("OPTIONAL"); }
543 void Post(const Parameter &) { Word("PARAMETER"); }
544 void Post(const Protected &) { Word("PROTECTED"); }
545 void Post(const Save &) { Word("SAVE"); }
546 void Post(const Target &) { Word("TARGET"); }
547 void Post(const Value &) { Word("VALUE"); }
548 void Post(const Volatile &) { Word("VOLATILE"); }
peter klausler79d044e2018-03-01 00:56:10549 bool Pre(const IntentSpec &x) { // R826
peter klauslerb7cf5122018-03-14 22:31:16550 Word("INTENT("), Walk(x.v), Put(")");
peter klausler79d044e2018-03-01 00:56:10551 return false;
552 }
553 bool Pre(const AccessStmt &x) { // R827
554 Walk(std::get<AccessSpec>(x.t));
555 Walk(" :: ", std::get<std::list<AccessId>>(x.t), ", ");
556 return false;
557 }
558 bool Pre(const AllocatableStmt &x) { // R829
peter klauslerb7cf5122018-03-14 22:31:16559 Word("ALLOCATABLE :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10560 return false;
561 }
562 bool Pre(const ObjectDecl &x) { // R830 & R860
563 Walk(std::get<ObjectName>(x.t));
564 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")");
565 Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]");
566 return false;
567 }
568 bool Pre(const AsynchronousStmt &x) { // R831
peter klauslerb7cf5122018-03-14 22:31:16569 Word("ASYNCHRONOUS :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10570 return false;
571 }
572 bool Pre(const BindStmt &x) { // R832
573 Walk(x.t, " :: ");
574 return false;
575 }
576 bool Pre(const BindEntity &x) { // R833
577 bool isCommon{std::get<BindEntity::Kind>(x.t) == BindEntity::Kind::Common};
578 const char *slash{isCommon ? "/" : ""};
579 Put(slash), Walk(std::get<Name>(x.t)), Put(slash);
580 return false;
581 }
582 bool Pre(const CodimensionStmt &x) { // R834
peter klauslerb7cf5122018-03-14 22:31:16583 Word("CODIMENSION :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10584 return false;
585 }
586 bool Pre(const CodimensionDecl &x) { // R835
587 Walk(std::get<Name>(x.t));
588 Put('['), Walk(std::get<CoarraySpec>(x.t)), Put(']');
589 return false;
590 }
591 bool Pre(const ContiguousStmt &x) { // R836
peter klauslerb7cf5122018-03-14 22:31:16592 Word("CONTIGUOUS :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10593 return false;
594 }
peter klauslerb7cf5122018-03-14 22:31:16595 bool Pre(const DataStmt &x) { // R837
596 Word("DATA "), Walk(x.v, ", ");
597 return false;
peter klausler79d044e2018-03-01 00:56:10598 }
599 bool Pre(const DataStmtSet &x) { // R838
600 Walk(std::get<std::list<DataStmtObject>>(x.t), ", ");
601 Put('/'), Walk(std::get<std::list<DataStmtValue>>(x.t), ", "), Put('/');
602 return false;
603 }
604 bool Pre(const DataImpliedDo &x) { // R840, R842
peter klauslerb7cf5122018-03-14 22:31:16605 Put('('), Walk(std::get<std::list<DataIDoObject>>(x.t), ", "), Put(',');
peter klausler79d044e2018-03-01 00:56:10606 Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::");
607 Walk(std::get<LoopBounds<ScalarIntConstantExpr>>(x.t)), Put(')');
608 return false;
609 }
610 bool Pre(const DataStmtValue &x) { // R843
611 Walk(std::get<std::optional<DataStmtRepeat>>(x.t), "*");
612 Walk(std::get<DataStmtConstant>(x.t));
613 return false;
614 }
615 bool Pre(const DimensionStmt &x) { // R848
peter klauslerb7cf5122018-03-14 22:31:16616 Word("DIMENSION :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10617 return false;
618 }
619 bool Pre(const DimensionStmt::Declaration &x) {
620 Walk(std::get<Name>(x.t));
621 Put('('), Walk(std::get<ArraySpec>(x.t)), Put(')');
622 return false;
623 }
624 bool Pre(const IntentStmt &x) { // R849
625 Walk(x.t, " :: ");
626 return false;
627 }
628 bool Pre(const OptionalStmt &x) { // R850
peter klauslerb7cf5122018-03-14 22:31:16629 Word("OPTIONAL :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10630 return false;
631 }
632 bool Pre(const ParameterStmt &x) { // R851
peter klauslerb7cf5122018-03-14 22:31:16633 Word("PARAMETER("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:10634 return false;
635 }
636 bool Pre(const NamedConstantDef &x) { // R852
637 Walk(x.t, "=");
638 return false;
639 }
640 bool Pre(const PointerStmt &x) { // R853
peter klauslerdcd09422018-03-15 23:03:28641 Word("POINTER"), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10642 return false;
643 }
644 bool Pre(const ProtectedStmt &x) { // R855
peter klauslerb7cf5122018-03-14 22:31:16645 Word("PROTECTED :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10646 return false;
647 }
648 bool Pre(const SaveStmt &x) { // R856
peter klauslerb7cf5122018-03-14 22:31:16649 Word("SAVE"), Walk(" :: ", x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10650 return false;
651 }
652 bool Pre(const SavedEntity &x) { // R857, R858
653 bool isCommon{
654 std::get<SavedEntity::Kind>(x.t) == SavedEntity::Kind::Common};
655 const char *slash{isCommon ? "/" : ""};
656 Put(slash), Walk(std::get<Name>(x.t)), Put(slash);
657 return false;
658 }
659 bool Pre(const TargetStmt &x) { // R859
peter klauslerb7cf5122018-03-14 22:31:16660 Word("TARGET :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10661 return false;
662 }
663 bool Pre(const ValueStmt &x) { // R861
peter klauslerb7cf5122018-03-14 22:31:16664 Word("VALUE :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10665 return false;
666 }
667 bool Pre(const VolatileStmt &x) { // R862
peter klauslerb7cf5122018-03-14 22:31:16668 Word("VOLATILE :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10669 return false;
670 }
671 bool Pre(const ImplicitStmt &x) { // R863
peter klauslerb7cf5122018-03-14 22:31:16672 Word("IMPLICIT ");
peter klausler79d044e2018-03-01 00:56:10673 std::visit(
674 visitors{[&](const std::list<ImplicitSpec> &y) { Walk(y, ", "); },
675 [&](const std::list<ImplicitStmt::ImplicitNoneNameSpec> &y) {
peter klauslerb7cf5122018-03-14 22:31:16676 Word("NONE"), Walk(" (", y, ", ", ")");
peter klausler79d044e2018-03-01 00:56:10677 }},
678 x.u);
679 return false;
680 }
681 bool Pre(const ImplicitSpec &x) { // R864
682 Walk(std::get<DeclarationTypeSpec>(x.t));
683 Put('('), Walk(std::get<std::list<LetterSpec>>(x.t), ", "), Put(')');
684 return false;
685 }
686 bool Pre(const LetterSpec &x) { // R865
687 Put(std::get<char>(x.t)), Walk("-", std::get<std::optional<char>>(x.t));
688 return false;
689 }
690 bool Pre(const ImportStmt &x) { // R867
peter klauslerb7cf5122018-03-14 22:31:16691 Word("IMPORT");
peter klausler79d044e2018-03-01 00:56:10692 switch (x.kind) {
peter klausler2e5300c2018-03-15 23:22:38693 case ImportStmt::Kind::Default: Walk(" :: ", x.names, ", "); break;
peter klausler79d044e2018-03-01 00:56:10694 case ImportStmt::Kind::Only:
peter klauslerb7cf5122018-03-14 22:31:16695 Put(", "), Word("ONLY: ");
peter klauslerdcd09422018-03-15 23:03:28696 Walk(x.names, ", ");
peter klausler79d044e2018-03-01 00:56:10697 break;
peter klauslerb7cf5122018-03-14 22:31:16698 case ImportStmt::Kind::None: Word(", NONE"); break;
699 case ImportStmt::Kind::All: Word(", ALL"); break;
peter klausler79d044e2018-03-01 00:56:10700 default: CRASH_NO_CASE;
701 }
702 return false;
703 }
704 bool Pre(const NamelistStmt &x) { // R868
peter klauslerb7cf5122018-03-14 22:31:16705 Word("NAMELIST"), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:10706 return false;
707 }
708 bool Pre(const NamelistStmt::Group &x) {
709 Put('/'), Put(std::get<Name>(x.t)), Put('/');
710 Walk(std::get<std::list<Name>>(x.t), ", ");
711 return false;
712 }
713 bool Pre(const EquivalenceStmt &x) { // R870, R871
peter klauslerb7cf5122018-03-14 22:31:16714 Word("EQUIVALENCE");
peter klausler79d044e2018-03-01 00:56:10715 const char *separator{" "};
716 for (const std::list<EquivalenceObject> &y : x.v) {
717 Put(separator), Put('('), Walk(y), Put(')');
718 separator = ", ";
719 }
720 return false;
721 }
722 bool Pre(const CommonStmt &x) { // R873
peter klauslerb7cf5122018-03-14 22:31:16723 Word("COMMON ");
peter klausler79d044e2018-03-01 00:56:10724 Walk("/", std::get<std::optional<std::optional<Name>>>(x.t), "/");
725 Walk(std::get<std::list<CommonBlockObject>>(x.t), ", ");
726 Walk(", ", std::get<std::list<CommonStmt::Block>>(x.t), ", ");
727 return false;
728 }
729 bool Pre(const CommonBlockObject &x) { // R874
730 Walk(std::get<Name>(x.t));
731 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")");
732 return false;
733 }
734 bool Pre(const CommonStmt::Block &x) {
735 Walk("/", std::get<std::optional<Name>>(x.t), "/");
736 Walk(std::get<std::list<CommonBlockObject>>(x.t));
737 return false;
738 }
Tim Keith2af29bc2018-02-26 22:28:32739
peter klausler79d044e2018-03-01 00:56:10740 bool Pre(const Substring &x) { // R908, R909
741 Walk(std::get<DataReference>(x.t));
742 Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')');
743 return false;
744 }
745 bool Pre(const CharLiteralConstantSubstring &x) {
746 Walk(std::get<CharLiteralConstant>(x.t));
747 Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')');
748 return false;
749 }
750 bool Pre(const SubstringRange &x) { // R910
751 Walk(x.t, ":");
752 return false;
753 }
754 bool Pre(const PartRef &x) { // R912
755 Walk(x.name);
756 Walk("(", x.subscripts, ",", ")");
757 Walk(x.imageSelector);
758 return false;
759 }
760 bool Pre(const StructureComponent &x) { // R913
761 Walk(x.base), Put(percentOrDot_), Walk(x.component);
762 return false;
763 }
764 bool Pre(const ArrayElement &x) { // R917
765 Walk(x.base);
766 Put('('), Walk(x.subscripts, ","), Put(')');
767 return false;
768 }
769 bool Pre(const SubscriptTriplet &x) { // R921
770 Walk(std::get<0>(x.t)), Put(':'), Walk(std::get<1>(x.t));
771 Walk(":", std::get<2>(x.t));
772 return false;
773 }
774 bool Pre(const ImageSelector &x) { // R924
775 Put('['), Walk(std::get<std::list<Cosubscript>>(x.t), ",");
776 Walk(",", std::get<std::list<ImageSelectorSpec>>(x.t), ","), Put(']');
777 return false;
778 }
peter klausler62d9cdd2018-03-15 00:02:21779 bool Pre(const ImageSelectorSpec::Stat &) { // R926
peter klauslerb7cf5122018-03-14 22:31:16780 Word("STAT=");
peter klausler79d044e2018-03-01 00:56:10781 return true;
782 }
783 bool Pre(const ImageSelectorSpec::Team &) {
peter klauslerb7cf5122018-03-14 22:31:16784 Word("TEAM=");
peter klausler79d044e2018-03-01 00:56:10785 return true;
786 }
787 bool Pre(const ImageSelectorSpec::Team_Number &) {
peter klauslerb7cf5122018-03-14 22:31:16788 Word("TEAM_NUMBER=");
peter klausler79d044e2018-03-01 00:56:10789 return true;
790 }
791 bool Pre(const AllocateStmt &x) { // R927
peter klauslerb7cf5122018-03-14 22:31:16792 Word("ALLOCATE(");
793 Walk(std::get<std::optional<TypeSpec>>(x.t), "::");
peter klausler79d044e2018-03-01 00:56:10794 Walk(std::get<std::list<Allocation>>(x.t), ", ");
795 Walk(", ", std::get<std::list<AllocOpt>>(x.t), ", "), Put(')');
796 return false;
797 }
798 bool Pre(const AllocOpt &x) { // R928, R931
peter klauslerb7cf5122018-03-14 22:31:16799 std::visit(visitors{[&](const AllocOpt::Mold &) { Word("MOLD="); },
800 [&](const AllocOpt::Source &) { Word("SOURCE="); },
peter klauslered5a6c92018-03-15 00:07:15801 [](const StatOrErrmsg &) {}},
peter klausler79d044e2018-03-01 00:56:10802 x.u);
803 return true;
804 }
805 bool Pre(const Allocation &x) { // R932
806 Walk(std::get<AllocateObject>(x.t));
807 Walk("(", std::get<std::list<AllocateShapeSpec>>(x.t), ",", ")");
808 Walk("[", std::get<std::optional<AllocateCoarraySpec>>(x.t), "]");
809 return false;
810 }
811 bool Pre(const AllocateShapeSpec &x) { // R934 & R938
812 Walk(std::get<std::optional<BoundExpr>>(x.t), ":");
813 Walk(std::get<BoundExpr>(x.t));
814 return false;
815 }
816 bool Pre(const AllocateCoarraySpec &x) { // R937
817 Walk(std::get<std::list<AllocateCoshapeSpec>>(x.t), ",", ",");
818 Walk(std::get<std::optional<BoundExpr>>(x.t), ":"), Put('*');
819 return false;
820 }
821 bool Pre(const NullifyStmt &x) { // R939
peter klauslerb7cf5122018-03-14 22:31:16822 Word("NULLIFY("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:10823 return false;
824 }
825 bool Pre(const DeallocateStmt &x) { // R941
peter klauslerb7cf5122018-03-14 22:31:16826 Word("DEALLOCATE(");
827 Walk(std::get<std::list<AllocateObject>>(x.t), ", ");
peter klausler79d044e2018-03-01 00:56:10828 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
829 return false;
830 }
831 bool Pre(const StatOrErrmsg &x) { // R942 & R1165
peter klauslerb7cf5122018-03-14 22:31:16832 std::visit(visitors{[&](const StatVariable &) { Word("STAT="); },
833 [&](const MsgVariable &) { Word("ERRMSG="); }},
peter klausler79d044e2018-03-01 00:56:10834 x.u);
835 return true;
836 }
837
838 // R1001 - R1022
839 bool Pre(const Expr::Parentheses &x) {
840 Put('('), Walk(x.v), Put(')');
841 return false;
842 }
843 bool Pre(const Expr::UnaryPlus &x) {
844 Put("+");
845 return true;
846 }
847 bool Pre(const Expr::Negate &x) {
848 Put("-");
849 return true;
850 }
851 bool Pre(const Expr::NOT &x) {
peter klauslerb7cf5122018-03-14 22:31:16852 Word(".NOT.");
peter klausler79d044e2018-03-01 00:56:10853 return true;
854 }
855 bool Pre(const Expr::PercentLoc &x) {
peter klauslerb7cf5122018-03-14 22:31:16856 Word("%LOC("), Walk(x.v), Put(')');
peter klausler79d044e2018-03-01 00:56:10857 return false;
858 }
peter klausler79d044e2018-03-01 00:56:10859 bool Pre(const Expr::Power &x) {
860 Walk(x.t, "**");
861 return false;
862 }
863 bool Pre(const Expr::Multiply &x) {
864 Walk(x.t, "*");
865 return false;
866 }
867 bool Pre(const Expr::Divide &x) {
868 Walk(x.t, "/");
869 return false;
870 }
871 bool Pre(const Expr::Add &x) {
872 Walk(x.t, "+");
873 return false;
874 }
875 bool Pre(const Expr::Subtract &x) {
876 Walk(x.t, "-");
877 return false;
878 }
879 bool Pre(const Expr::Concat &x) {
880 Walk(x.t, "//");
881 return false;
882 }
883 bool Pre(const Expr::LT &x) {
884 Walk(x.t, "<");
885 return false;
886 }
887 bool Pre(const Expr::LE &x) {
888 Walk(x.t, "<=");
889 return false;
890 }
891 bool Pre(const Expr::EQ &x) {
892 Walk(x.t, "==");
893 return false;
894 }
895 bool Pre(const Expr::NE &x) {
896 Walk(x.t, "/=");
897 return false;
898 }
899 bool Pre(const Expr::GE &x) {
900 Walk(x.t, ">=");
901 return false;
902 }
903 bool Pre(const Expr::GT &x) {
904 Walk(x.t, ">");
905 return false;
906 }
907 bool Pre(const Expr::AND &x) {
908 Walk(x.t, ".AND.");
909 return false;
910 }
911 bool Pre(const Expr::OR &x) {
912 Walk(x.t, ".OR.");
913 return false;
914 }
915 bool Pre(const Expr::EQV &x) {
916 Walk(x.t, ".EQV.");
917 return false;
918 }
919 bool Pre(const Expr::NEQV &x) {
920 Walk(x.t, ".NEQV.");
921 return false;
922 }
923 bool Pre(const Expr::ComplexConstructor &x) {
924 Put('('), Walk(x.t, ","), Put(')');
925 return false;
926 }
927 bool Pre(const Expr::DefinedBinary &x) {
928 Walk(std::get<1>(x.t)); // left
929 Walk(std::get<DefinedOpName>(x.t));
930 Walk(std::get<2>(x.t)); // right
931 return false;
932 }
933 bool Pre(const DefinedOpName &x) { // R1003, R1023, R1414, & R1415
934 Put('.'), Put(x.v), Put('.');
935 return false;
936 }
937 bool Pre(const AssignmentStmt &x) { // R1032
938 Walk(x.t, " = ");
939 return false;
940 }
941 bool Pre(const PointerAssignmentStmt &x) { // R1033, R1034, R1038
942 Walk(std::get<Variable>(x.t));
943 std::visit(
944 visitors{[&](const std::list<BoundsRemapping> &y) {
945 Put('('), Walk(y), Put(')');
946 },
947 [&](const std::list<BoundsSpec> &y) { Walk("(", y, ", ", ")"); }},
948 std::get<PointerAssignmentStmt::Bounds>(x.t).u);
949 Put(" => "), Walk(std::get<Expr>(x.t));
950 return false;
951 }
952 void Post(const BoundsSpec &) { // R1035
953 Put(':');
954 }
955 bool Pre(const BoundsRemapping &x) { // R1036
956 Walk(x.t, ":");
957 return false;
958 }
959 bool Pre(const ProcComponentRef &x) { // R1039
960 Walk(std::get<Scalar<Variable>>(x.t)), Put(percentOrDot_);
961 Walk(std::get<Name>(x.t));
962 return false;
963 }
964 bool Pre(const WhereStmt &x) { // R1041, R1045, R1046
peter klauslerb7cf5122018-03-14 22:31:16965 Word("WHERE ("), Walk(x.t, ") ");
peter klausler79d044e2018-03-01 00:56:10966 return false;
967 }
968 bool Pre(const WhereConstructStmt &x) { // R1043
969 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:16970 Word("WHERE ("), Walk(std::get<LogicalExpr>(x.t)), Put(')');
peter klausler79d044e2018-03-01 00:56:10971 Indent();
972 return false;
973 }
974 bool Pre(const MaskedElsewhereStmt &x) { // R1047
975 Outdent();
peter klauslerb7cf5122018-03-14 22:31:16976 Word("ELSEWHERE ("), Walk(std::get<LogicalExpr>(x.t)), Put(')');
peter klausler79d044e2018-03-01 00:56:10977 Walk(" ", std::get<std::optional<Name>>(x.t));
978 Indent();
979 return false;
980 }
981 bool Pre(const ElsewhereStmt &x) { // R1048
peter klauslerb7cf5122018-03-14 22:31:16982 Outdent(), Word("ELSEWHERE"), Walk(" ", x.v), Indent();
peter klausler79d044e2018-03-01 00:56:10983 return false;
984 }
985 bool Pre(const EndWhereStmt &x) { // R1049
peter klauslerb7cf5122018-03-14 22:31:16986 Outdent(), Word("END WHERE"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:10987 return false;
988 }
989 bool Pre(const ForallConstructStmt &x) { // R1051
990 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:16991 Word("FORALL"), Walk(std::get<Indirection<ConcurrentHeader>>(x.t));
peter klausler79d044e2018-03-01 00:56:10992 Indent();
993 return false;
994 }
995 bool Pre(const EndForallStmt &x) { // R1054
peter klauslerb7cf5122018-03-14 22:31:16996 Outdent(), Word("END FORALL"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:10997 return false;
998 }
999 bool Pre(const ForallStmt &) { // R1055
peter klauslerb7cf5122018-03-14 22:31:161000 Word("FORALL");
peter klausler79d044e2018-03-01 00:56:101001 return true;
1002 }
1003
1004 bool Pre(const AssociateStmt &x) { // R1103
1005 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161006 Word("ASSOCIATE (");
1007 Walk(std::get<std::list<Association>>(x.t), ", "), Put(')'), Indent();
peter klausler79d044e2018-03-01 00:56:101008 return false;
1009 }
1010 bool Pre(const Association &x) { // R1104
1011 Walk(x.t, " => ");
1012 return false;
1013 }
1014 bool Pre(const EndAssociateStmt &x) { // R1106
peter klauslerb7cf5122018-03-14 22:31:161015 Outdent(), Word("END ASSOCIATE"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101016 return false;
1017 }
1018 bool Pre(const BlockStmt &x) { // R1108
peter klauslerb7cf5122018-03-14 22:31:161019 Walk(x.v, ": "), Word("BLOCK"), Indent();
peter klausler79d044e2018-03-01 00:56:101020 return false;
1021 }
1022 bool Pre(const EndBlockStmt &x) { // R1110
peter klauslerb7cf5122018-03-14 22:31:161023 Outdent(), Word("END BLOCK"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101024 return false;
1025 }
1026 bool Pre(const ChangeTeamStmt &x) { // R1112
1027 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161028 Word("CHANGE TEAM ("), Walk(std::get<TeamVariable>(x.t));
peter klausler79d044e2018-03-01 00:56:101029 Walk(", ", std::get<std::list<CoarrayAssociation>>(x.t), ", ");
1030 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
1031 Indent();
1032 return false;
1033 }
1034 bool Pre(const CoarrayAssociation &x) { // R1113
1035 Walk(x.t, " => ");
1036 return false;
1037 }
1038 bool Pre(const EndChangeTeamStmt &x) { // R1114
peter klauslerb7cf5122018-03-14 22:31:161039 Outdent(), Word("END TEAM (");
peter klausler79d044e2018-03-01 00:56:101040 Walk(std::get<std::list<StatOrErrmsg>>(x.t), ", ");
1041 Put(')'), Walk(" ", std::get<std::optional<Name>>(x.t));
1042 return false;
1043 }
1044 bool Pre(const CriticalStmt &x) { // R1117
1045 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161046 Word("CRITICAL ("), Walk(std::get<std::list<StatOrErrmsg>>(x.t), ", ");
peter klausler79d044e2018-03-01 00:56:101047 Put(')'), Indent();
1048 return false;
1049 }
1050 bool Pre(const EndCriticalStmt &x) { // R1118
peter klauslerb7cf5122018-03-14 22:31:161051 Outdent(), Word("END CRITICAL"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101052 return false;
1053 }
1054 bool Pre(const DoConstruct &x) { // R1119, R1120
1055 Walk(std::get<Statement<NonLabelDoStmt>>(x.t));
1056 Indent(), Walk(std::get<Block>(x.t), ""), Outdent();
1057 Walk(std::get<Statement<EndDoStmt>>(x.t));
1058 return false;
1059 }
1060 bool Pre(const LabelDoStmt &x) { // R1121
1061 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161062 Word("DO "), Walk(std::get<Label>(x.t));
peter klausler79d044e2018-03-01 00:56:101063 Walk(" ", std::get<std::optional<LoopControl>>(x.t));
1064 return false;
1065 }
1066 bool Pre(const NonLabelDoStmt &x) { // R1122
1067 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161068 Word("DO "), Walk(std::get<std::optional<LoopControl>>(x.t));
peter klausler79d044e2018-03-01 00:56:101069 return false;
1070 }
1071 bool Pre(const LoopControl &x) { // R1123
1072 std::visit(visitors{[&](const ScalarLogicalExpr &y) {
peter klauslerb7cf5122018-03-14 22:31:161073 Word("WHILE ("), Walk(y), Put(')');
peter klausler79d044e2018-03-01 00:56:101074 },
1075 [&](const auto &y) { Walk(y); }},
1076 x.u);
1077 return false;
1078 }
1079 bool Pre(const ConcurrentHeader &x) { // R1125
1080 Put('('), Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::");
1081 Walk(std::get<std::list<ConcurrentControl>>(x.t), ", ");
1082 Walk(", ", std::get<std::optional<ScalarLogicalExpr>>(x.t)), Put(')');
1083 return false;
1084 }
1085 bool Pre(const ConcurrentControl &x) { // R1126 - R1128
1086 Walk(std::get<Name>(x.t)), Put('='), Walk(std::get<1>(x.t));
1087 Put(':'), Walk(std::get<2>(x.t));
1088 Walk(":", std::get<std::optional<ScalarIntExpr>>(x.t));
1089 return false;
1090 }
1091 bool Pre(const LoopControl::Concurrent &x) { // R1129
peter klauslerb7cf5122018-03-14 22:31:161092 Word("CONCURRENT");
peter klausler79d044e2018-03-01 00:56:101093 return true;
1094 }
1095 bool Pre(const LocalitySpec::Local &x) {
peter klauslerb7cf5122018-03-14 22:31:161096 Word("LOCAL("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101097 return false;
1098 }
1099 bool Pre(const LocalitySpec::LocalInit &x) {
peter klauslerb7cf5122018-03-14 22:31:161100 Word("LOCAL INIT("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101101 return false;
1102 }
1103 bool Pre(const LocalitySpec::Shared &x) {
peter klauslerb7cf5122018-03-14 22:31:161104 Word("SHARED("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101105 return false;
1106 }
peter klauslerb7cf5122018-03-14 22:31:161107 void Post(const LocalitySpec::DefaultNone &x) { Word("DEFAULT(NONE)"); }
peter klausler79d044e2018-03-01 00:56:101108 bool Pre(const EndDoStmt &x) { // R1132
peter klauslerb7cf5122018-03-14 22:31:161109 Word("END DO"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101110 return false;
1111 }
1112 bool Pre(const CycleStmt &x) { // R1133
peter klauslerb7cf5122018-03-14 22:31:161113 Word("CYCLE"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101114 return false;
1115 }
1116 bool Pre(const IfThenStmt &x) { // R1135
1117 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161118 Word("IF ("), Walk(std::get<ScalarLogicalExpr>(x.t));
1119 Put(") "), Word("THEN"), Indent();
peter klausler79d044e2018-03-01 00:56:101120 return false;
1121 }
1122 bool Pre(const ElseIfStmt &x) { // R1136
peter klauslerb7cf5122018-03-14 22:31:161123 Outdent(), Word("ELSE IF (");
1124 Walk(std::get<ScalarLogicalExpr>(x.t)), Put(") "), Word("THEN");
1125 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
peter klausler79d044e2018-03-01 00:56:101126 return false;
1127 }
1128 bool Pre(const ElseStmt &x) { // R1137
peter klauslerb7cf5122018-03-14 22:31:161129 Outdent(), Word("ELSE"), Walk(" ", x.v), Indent();
peter klausler79d044e2018-03-01 00:56:101130 return false;
1131 }
1132 bool Pre(const EndIfStmt &x) { // R1138
peter klauslerb7cf5122018-03-14 22:31:161133 Outdent(), Word("END IF"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101134 return false;
1135 }
1136 bool Pre(const IfStmt &x) { // R1139
peter klauslerb7cf5122018-03-14 22:31:161137 Word("IF ("), Walk(x.t, ") ");
peter klausler79d044e2018-03-01 00:56:101138 return false;
1139 }
1140 bool Pre(const SelectCaseStmt &x) { // R1141, R1144
1141 Walk(std::get<std::optional<Name>>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161142 Word("SELECT CASE (");
1143 Walk(std::get<Scalar<Expr>>(x.t)), Put(')'), Indent();
peter klausler79d044e2018-03-01 00:56:101144 return false;
1145 }
1146 bool Pre(const CaseStmt &x) { // R1142
peter klauslerb7cf5122018-03-14 22:31:161147 Outdent(), Word("CASE "), Walk(std::get<CaseSelector>(x.t));
peter klausler79d044e2018-03-01 00:56:101148 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
1149 return false;
1150 }
1151 bool Pre(const EndSelectStmt &x) { // R1143 & R1151 & R1155
peter klauslerb7cf5122018-03-14 22:31:161152 Outdent(), Word("END SELECT"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101153 return false;
1154 }
1155 bool Pre(const CaseSelector &x) { // R1145
1156 std::visit(visitors{[&](const std::list<CaseValueRange> &y) {
1157 Put('('), Walk(y), Put(')');
1158 },
peter klauslerb7cf5122018-03-14 22:31:161159 [&](const Default &) { Word("DEFAULT"); }},
peter klausler79d044e2018-03-01 00:56:101160 x.u);
1161 return false;
1162 }
1163 bool Pre(const CaseValueRange::Range &x) { // R1146
1164 Walk(x.lower), Put(':'), Walk(x.upper);
1165 return false;
1166 }
1167 bool Pre(const SelectRankStmt &x) { // R1149
1168 Walk(std::get<0>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161169 Word("SELECT RANK ("), Walk(std::get<1>(x.t), " => ");
peter klausler79d044e2018-03-01 00:56:101170 Walk(std::get<Selector>(x.t)), Put(')'), Indent();
1171 return false;
1172 }
1173 bool Pre(const SelectRankCaseStmt &x) { // R1150
peter klauslerb7cf5122018-03-14 22:31:161174 Outdent(), Word("RANK ");
peter klausler79d044e2018-03-01 00:56:101175 std::visit(visitors{[&](const ScalarIntConstantExpr &y) {
1176 Put('('), Walk(y), Put(')');
1177 },
1178 [&](const Star &) { Put("(*)"); },
peter klauslerb7cf5122018-03-14 22:31:161179 [&](const Default &) { Word("DEFAULT"); }},
peter klausler79d044e2018-03-01 00:56:101180 std::get<SelectRankCaseStmt::Rank>(x.t).u);
1181 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
1182 return false;
1183 }
1184 bool Pre(const SelectTypeStmt &x) { // R1153
1185 Walk(std::get<0>(x.t), ": ");
peter klauslerb7cf5122018-03-14 22:31:161186 Word("SELECT TYPE ("), Walk(std::get<1>(x.t), " => ");
peter klausler79d044e2018-03-01 00:56:101187 Walk(std::get<Selector>(x.t)), Put(')'), Indent();
1188 return false;
1189 }
1190 bool Pre(const TypeGuardStmt &x) { // R1154
1191 Outdent(), Walk(std::get<TypeGuardStmt::Guard>(x.t));
1192 Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
1193 return false;
1194 }
1195 bool Pre(const TypeGuardStmt::Guard &x) {
1196 std::visit(visitors{[&](const TypeSpec &y) {
peter klauslerb7cf5122018-03-14 22:31:161197 Word("TYPE IS ("), Walk(y), Put(')');
peter klausler79d044e2018-03-01 00:56:101198 },
1199 [&](const DerivedTypeSpec &y) {
peter klauslerb7cf5122018-03-14 22:31:161200 Word("CLASS IS ("), Walk(y), Put(')');
peter klausler79d044e2018-03-01 00:56:101201 },
peter klauslerb7cf5122018-03-14 22:31:161202 [&](const Default &) { Word("CLASS DEFAULT"); }},
peter klausler79d044e2018-03-01 00:56:101203 x.u);
1204 return false;
1205 }
1206 bool Pre(const ExitStmt &x) { // R1156
peter klauslerb7cf5122018-03-14 22:31:161207 Word("EXIT"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101208 return false;
1209 }
1210 bool Pre(const GotoStmt &x) { // R1157
peter klauslerb7cf5122018-03-14 22:31:161211 Word("GO TO ");
peter klausler79d044e2018-03-01 00:56:101212 return true;
1213 }
1214 bool Pre(const ComputedGotoStmt &x) { // R1158
peter klauslerb7cf5122018-03-14 22:31:161215 Word("GO TO ("), Walk(x.t, "), ");
peter klausler79d044e2018-03-01 00:56:101216 return false;
1217 }
1218 bool Pre(const ContinueStmt &x) { // R1159
peter klauslerb7cf5122018-03-14 22:31:161219 Word("CONTINUE");
peter klausler79d044e2018-03-01 00:56:101220 return false;
1221 }
1222 bool Pre(const StopStmt &x) { // R1160, R1161
1223 if (std::get<StopStmt::Kind>(x.t) == StopStmt::Kind::ErrorStop) {
peter klauslerb7cf5122018-03-14 22:31:161224 Word("ERROR ");
peter klausler79d044e2018-03-01 00:56:101225 }
peter klauslerb7cf5122018-03-14 22:31:161226 Word("STOP"), Walk(" ", std::get<std::optional<StopCode>>(x.t));
peter klausler79d044e2018-03-01 00:56:101227 Walk(", QUIET=", std::get<std::optional<ScalarLogicalExpr>>(x.t));
1228 return false;
1229 }
1230 bool Pre(const FailImageStmt &x) { // R1163
peter klauslerb7cf5122018-03-14 22:31:161231 Word("FAIL IMAGE");
peter klausler79d044e2018-03-01 00:56:101232 return false;
1233 }
1234 bool Pre(const SyncAllStmt &x) { // R1164
peter klauslerb7cf5122018-03-14 22:31:161235 Word("SYNC ALL ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101236 return false;
1237 }
1238 bool Pre(const SyncImagesStmt &x) { // R1166
peter klauslerb7cf5122018-03-14 22:31:161239 Word("SYNC IMAGES (");
1240 Walk(std::get<SyncImagesStmt::ImageSet>(x.t));
peter klausler79d044e2018-03-01 00:56:101241 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
1242 return false;
1243 }
1244 bool Pre(const SyncMemoryStmt &x) { // R1168
peter klauslerb7cf5122018-03-14 22:31:161245 Word("SYNC MEMORY ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101246 return false;
1247 }
1248 bool Pre(const SyncTeamStmt &x) { // R1169
peter klauslerb7cf5122018-03-14 22:31:161249 Word("SYNC TEAM ("), Walk(std::get<TeamVariable>(x.t));
peter klausler79d044e2018-03-01 00:56:101250 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
1251 return false;
1252 }
1253 bool Pre(const EventPostStmt &x) { // R1170
peter klauslerb7cf5122018-03-14 22:31:161254 Word("EVENT POST ("), Walk(std::get<EventVariable>(x.t));
peter klausler79d044e2018-03-01 00:56:101255 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
1256 return false;
1257 }
1258 bool Pre(const EventWaitStmt::EventWaitSpec &x) { // R1173, R1174
peter klausler62d9cdd2018-03-15 00:02:211259 std::visit(visitors{[&](const ScalarIntExpr &x) { Word("UNTIL_COUNT="); },
peter klauslered5a6c92018-03-15 00:07:151260 [](const StatOrErrmsg &) {}},
peter klausler79d044e2018-03-01 00:56:101261 x.u);
1262 return true;
1263 }
1264 bool Pre(const EventWaitStmt &x) { // R1170
peter klauslerb7cf5122018-03-14 22:31:161265 Word("EVENT WAIT ("), Walk(std::get<EventVariable>(x.t));
peter klausler79d044e2018-03-01 00:56:101266 Walk(", ", std::get<std::list<EventWaitStmt::EventWaitSpec>>(x.t), ", ");
1267 Put(')');
1268 return false;
1269 }
1270 bool Pre(const FormTeamStmt &x) { // R1175
peter klauslerb7cf5122018-03-14 22:31:161271 Word("FORM TEAM ("), Walk(std::get<ScalarIntExpr>(x.t));
peter klausler79d044e2018-03-01 00:56:101272 Put(','), Walk(std::get<TeamVariable>(x.t));
1273 Walk(", ", std::get<std::list<FormTeamStmt::FormTeamSpec>>(x.t), ", ");
1274 Put(')');
1275 return false;
1276 }
1277 bool Pre(const FormTeamStmt::FormTeamSpec &x) { // R1176, R1177
peter klausler62d9cdd2018-03-15 00:02:211278 std::visit(visitors{[&](const ScalarIntExpr &x) { Word("NEW_INDEX="); },
peter klauslered5a6c92018-03-15 00:07:151279 [](const StatOrErrmsg &) {}},
peter klausler79d044e2018-03-01 00:56:101280 x.u);
1281 return true;
1282 }
1283 bool Pre(const LockStmt &x) { // R1178
peter klauslerb7cf5122018-03-14 22:31:161284 Word("LOCK ("), Walk(std::get<LockVariable>(x.t));
peter klausler79d044e2018-03-01 00:56:101285 Walk(", ", std::get<std::list<LockStmt::LockStat>>(x.t), ", ");
1286 Put(')');
1287 return false;
1288 }
1289 bool Pre(const LockStmt::LockStat &x) { // R1179
peter klausler62d9cdd2018-03-15 00:02:211290 std::visit(
1291 visitors{[&](const ScalarLogicalVariable &) { Word("ACQUIRED_LOCK="); },
peter klauslered5a6c92018-03-15 00:07:151292 [](const StatOrErrmsg &y) {}},
peter klausler79d044e2018-03-01 00:56:101293 x.u);
1294 return true;
1295 }
1296 bool Pre(const UnlockStmt &x) { // R1180
peter klauslerb7cf5122018-03-14 22:31:161297 Word("UNLOCK ("), Walk(std::get<LockVariable>(x.t));
peter klausler79d044e2018-03-01 00:56:101298 Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", ");
1299 Put(')');
1300 return false;
1301 }
1302
1303 bool Pre(const OpenStmt &x) { // R1204
peter klauslerb7cf5122018-03-14 22:31:161304 Word("OPEN ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101305 return false;
1306 }
1307 bool Pre(const ConnectSpec &x) { // R1205
1308 return std::visit(visitors{[&](const FileUnitNumber &) {
peter klauslerb7cf5122018-03-14 22:31:161309 Word("UNIT=");
peter klausler79d044e2018-03-01 00:56:101310 return true;
1311 },
1312 [&](const FileNameExpr &) {
peter klauslerb7cf5122018-03-14 22:31:161313 Word("FILE=");
peter klausler79d044e2018-03-01 00:56:101314 return true;
1315 },
1316 [&](const ConnectSpec::CharExpr &y) {
1317 Walk(y.t, "=");
1318 return false;
1319 },
1320 [&](const MsgVariable &) {
peter klauslerb7cf5122018-03-14 22:31:161321 Word("IOMSG=");
peter klausler79d044e2018-03-01 00:56:101322 return true;
1323 },
1324 [&](const StatVariable &) {
peter klauslerb7cf5122018-03-14 22:31:161325 Word("IOSTAT=");
peter klausler79d044e2018-03-01 00:56:101326 return true;
1327 },
1328 [&](const ConnectSpec::Recl &) {
peter klauslerb7cf5122018-03-14 22:31:161329 Word("RECL=");
peter klausler79d044e2018-03-01 00:56:101330 return true;
1331 },
1332 [&](const ConnectSpec::Newunit &) {
peter klauslerb7cf5122018-03-14 22:31:161333 Word("NEWUNIT=");
peter klausler79d044e2018-03-01 00:56:101334 return true;
1335 },
1336 [&](const ErrLabel &) {
peter klauslerb7cf5122018-03-14 22:31:161337 Word("ERR=");
peter klausler79d044e2018-03-01 00:56:101338 return true;
1339 },
1340 [&](const StatusExpr &) {
peter klauslerb7cf5122018-03-14 22:31:161341 Word("STATUS=");
peter klausler79d044e2018-03-01 00:56:101342 return true;
1343 }},
1344 x.u);
1345 }
1346 bool Pre(const CloseStmt &x) { // R1208
peter klauslerb7cf5122018-03-14 22:31:161347 Word("CLOSE ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101348 return false;
1349 }
1350 bool Pre(const CloseStmt::CloseSpec &x) { // R1209
peter klauslerb7cf5122018-03-14 22:31:161351 std::visit(visitors{[&](const FileUnitNumber &) { Word("UNIT="); },
1352 [&](const StatVariable &) { Word("IOSTAT="); },
1353 [&](const MsgVariable &) { Word("IOMSG="); },
1354 [&](const ErrLabel &) { Word("ERR="); },
1355 [&](const StatusExpr &) { Word("STATUS="); }},
peter klausler79d044e2018-03-01 00:56:101356 x.u);
1357 return true;
1358 }
1359 bool Pre(const ReadStmt &x) { // R1210
peter klauslerb7cf5122018-03-14 22:31:161360 Word("READ ");
peter klausler79d044e2018-03-01 00:56:101361 if (x.iounit) {
1362 Put('('), Walk(x.iounit);
1363 if (x.format) {
1364 Put(", "), Walk(x.format);
1365 }
peter klauslerdcd09422018-03-15 23:03:281366 Walk(", ", x.controls, ", ");
peter klausler79d044e2018-03-01 00:56:101367 Put(')');
1368 } else if (x.format) {
1369 Walk(x.format);
1370 if (!x.items.empty()) {
1371 Put(", ");
1372 }
1373 } else {
peter klauslerdcd09422018-03-15 23:03:281374 Put('('), Walk(x.controls, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101375 }
1376 Walk(" ", x.items, ", ");
1377 return false;
1378 }
1379 bool Pre(const WriteStmt &x) { // R1211
peter klauslerb7cf5122018-03-14 22:31:161380 Word("WRITE (");
peter klausler79d044e2018-03-01 00:56:101381 if (x.iounit) {
1382 Walk(x.iounit);
1383 if (x.format) {
1384 Put(", "), Walk(x.format);
1385 }
peter klauslerdcd09422018-03-15 23:03:281386 Walk(", ", x.controls, ", ");
peter klausler79d044e2018-03-01 00:56:101387 } else {
peter klauslerdcd09422018-03-15 23:03:281388 Walk(x.controls, ", ");
peter klausler79d044e2018-03-01 00:56:101389 }
1390 Put(')'), Walk(" ", x.items, ", ");
1391 return false;
1392 }
1393 bool Pre(const PrintStmt &x) { // R1212
peter klauslerb7cf5122018-03-14 22:31:161394 Word("PRINT "), Walk(std::get<Format>(x.t));
peter klausler79d044e2018-03-01 00:56:101395 Walk(", ", std::get<std::list<OutputItem>>(x.t), ", ");
1396 return false;
1397 }
1398 bool Pre(const IoControlSpec &x) { // R1213
1399 return std::visit(visitors{[&](const IoUnit &) {
peter klauslerb7cf5122018-03-14 22:31:161400 Word("UNIT=");
peter klausler79d044e2018-03-01 00:56:101401 return true;
1402 },
1403 [&](const Format &) {
peter klauslerb7cf5122018-03-14 22:31:161404 Word("FMT=");
peter klausler79d044e2018-03-01 00:56:101405 return true;
1406 },
1407 [&](const Name &) {
peter klauslerb7cf5122018-03-14 22:31:161408 Word("NML=");
peter klausler79d044e2018-03-01 00:56:101409 return true;
1410 },
1411 [&](const IoControlSpec::CharExpr &y) {
1412 Walk(y.t, "=");
1413 return false;
1414 },
1415 [&](const IoControlSpec::Asynchronous &) {
peter klauslerb7cf5122018-03-14 22:31:161416 Word("ASYNCHRONOUS=");
peter klausler79d044e2018-03-01 00:56:101417 return true;
1418 },
1419 [&](const EndLabel &) {
peter klauslerb7cf5122018-03-14 22:31:161420 Word("END=");
peter klausler79d044e2018-03-01 00:56:101421 return true;
1422 },
1423 [&](const EorLabel &) {
peter klauslerb7cf5122018-03-14 22:31:161424 Word("EOR=");
peter klausler79d044e2018-03-01 00:56:101425 return true;
1426 },
1427 [&](const ErrLabel &) {
peter klauslerb7cf5122018-03-14 22:31:161428 Word("ERR=");
peter klausler79d044e2018-03-01 00:56:101429 return true;
1430 },
1431 [&](const IdVariable &) {
peter klauslerb7cf5122018-03-14 22:31:161432 Word("ID=");
peter klausler79d044e2018-03-01 00:56:101433 return true;
1434 },
1435 [&](const MsgVariable &) {
peter klauslerb7cf5122018-03-14 22:31:161436 Word("IOMSG=");
peter klausler79d044e2018-03-01 00:56:101437 return true;
1438 },
1439 [&](const StatVariable &) {
peter klauslerb7cf5122018-03-14 22:31:161440 Word("IOSTAT=");
peter klausler79d044e2018-03-01 00:56:101441 return true;
1442 },
1443 [&](const IoControlSpec::Pos &) {
peter klauslerb7cf5122018-03-14 22:31:161444 Word("POS=");
peter klausler79d044e2018-03-01 00:56:101445 return true;
1446 },
1447 [&](const IoControlSpec::Rec &) {
peter klauslerb7cf5122018-03-14 22:31:161448 Word("REC=");
peter klausler79d044e2018-03-01 00:56:101449 return true;
1450 },
1451 [&](const IoControlSpec::Size &) {
peter klauslerb7cf5122018-03-14 22:31:161452 Word("SIZE=");
peter klausler79d044e2018-03-01 00:56:101453 return true;
1454 }},
1455 x.u);
1456 }
1457 bool Pre(const InputImpliedDo &x) { // R1218
1458 Put('('), Walk(std::get<std::list<InputItem>>(x.t), ", "), Put(", ");
1459 Walk(std::get<IoImpliedDoControl>(x.t)), Put(')');
1460 return false;
1461 }
1462 bool Pre(const OutputImpliedDo &x) { // R1219
1463 Put('('), Walk(std::get<std::list<OutputItem>>(x.t), ", "), Put(", ");
1464 Walk(std::get<IoImpliedDoControl>(x.t)), Put(')');
1465 return false;
1466 }
1467 bool Pre(const WaitStmt &x) { // R1222
peter klauslerb7cf5122018-03-14 22:31:161468 Word("WAIT ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101469 return false;
1470 }
1471 bool Pre(const WaitSpec &x) { // R1223
peter klauslerb7cf5122018-03-14 22:31:161472 std::visit(visitors{[&](const FileUnitNumber &) { Word("UNIT="); },
1473 [&](const EndLabel &) { Word("END="); },
1474 [&](const EorLabel &) { Word("EOR="); },
1475 [&](const ErrLabel &) { Word("ERR="); },
1476 [&](const IdExpr &) { Word("ID="); },
1477 [&](const MsgVariable &) { Word("IOMSG="); },
1478 [&](const StatVariable &) { Word("IOSTAT="); }},
peter klausler79d044e2018-03-01 00:56:101479 x.u);
1480 return true;
1481 }
1482 bool Pre(const BackspaceStmt &x) { // R1224
peter klauslerb7cf5122018-03-14 22:31:161483 Word("BACKSPACE ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101484 return false;
1485 }
1486 bool Pre(const EndfileStmt &x) { // R1225
peter klauslerb7cf5122018-03-14 22:31:161487 Word("ENDFILE ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101488 return false;
1489 }
1490 bool Pre(const RewindStmt &x) { // R1226
peter klauslerb7cf5122018-03-14 22:31:161491 Word("REWIND ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101492 return false;
1493 }
1494 bool Pre(const FlushStmt &x) { // R1228
peter klauslerb7cf5122018-03-14 22:31:161495 Word("FLUSH ("), Walk(x.v, ", "), Put(')');
peter klausler79d044e2018-03-01 00:56:101496 return false;
1497 }
1498 bool Pre(const InquireStmt &x) { // R1230
peter klauslerb7cf5122018-03-14 22:31:161499 Word("INQUIRE (");
peter klausler79d044e2018-03-01 00:56:101500 std::visit(
1501 visitors{[&](const InquireStmt::Iolength &y) {
peter klauslerb7cf5122018-03-14 22:31:161502 Word("IOLENGTH="), Walk(y.t, ") ");
peter klausler79d044e2018-03-01 00:56:101503 },
1504 [&](const std::list<InquireSpec> &y) { Walk(y, ", "), Put(')'); }},
1505 x.u);
1506 return false;
1507 }
1508 bool Pre(const InquireSpec &x) { // R1231
1509 return std::visit(visitors{[&](const FileUnitNumber &) {
peter klauslerb7cf5122018-03-14 22:31:161510 Word("UNIT=");
peter klausler79d044e2018-03-01 00:56:101511 return true;
1512 },
1513 [&](const FileNameExpr &) {
peter klauslerb7cf5122018-03-14 22:31:161514 Word("FILE=");
peter klausler79d044e2018-03-01 00:56:101515 return true;
1516 },
1517 [&](const InquireSpec::CharVar &y) {
1518 Walk(y.t, "=");
1519 return false;
1520 },
1521 [&](const InquireSpec::IntVar &y) {
1522 Walk(y.t, "=");
1523 return false;
1524 },
1525 [&](const InquireSpec::LogVar &y) {
1526 Walk(y.t, "=");
1527 return false;
1528 },
1529 [&](const IdExpr &) {
peter klauslerb7cf5122018-03-14 22:31:161530 Word("ID=");
peter klausler79d044e2018-03-01 00:56:101531 return true;
1532 },
1533 [&](const ErrLabel &) {
peter klauslerb7cf5122018-03-14 22:31:161534 Word("ERR=");
peter klausler79d044e2018-03-01 00:56:101535 return true;
1536 }},
1537 x.u);
1538 }
1539
1540 bool Pre(const FormatStmt &) { // R1301
peter klauslerb7cf5122018-03-14 22:31:161541 Word("FORMAT");
peter klausler79d044e2018-03-01 00:56:101542 return true;
1543 }
1544 bool Pre(const format::FormatSpecification &x) { // R1302, R1303, R1305
1545 Put('('), Walk("", x.items, ",", x.unlimitedItems.empty() ? "" : ",");
1546 Walk("*(", x.unlimitedItems, ",", ")"), Put(')');
1547 return false;
1548 }
1549 bool Pre(const format::FormatItem &x) { // R1304, R1306, R1321
1550 if (x.repeatCount.has_value()) {
1551 Walk(*x.repeatCount);
1552 }
1553 std::visit(visitors{[&](const std::string &y) { PutQuoted(y); },
1554 [&](const std::list<format::FormatItem> &y) {
1555 Walk("(", y, ",", ")");
1556 },
1557 [&](const auto &y) { Walk(y); }},
1558 x.u);
1559 return false;
1560 }
1561 bool Pre(const format::IntrinsicTypeDataEditDesc &x) { // R1307(1/2) - R1311
1562 switch (x.kind) {
1563#define FMT(x) \
1564 case format::IntrinsicTypeDataEditDesc::Kind::x: Put(#x); break
1565 FMT(I);
1566 FMT(B);
1567 FMT(O);
1568 FMT(Z);
1569 FMT(F);
1570 FMT(E);
1571 FMT(EN);
1572 FMT(ES);
1573 FMT(EX);
1574 FMT(G);
1575 FMT(L);
1576 FMT(A);
1577 FMT(D);
1578#undef FMT
1579 default: CRASH_NO_CASE;
1580 }
1581 Walk(x.width), Walk(".", x.digits), Walk("E", x.exponentWidth);
1582 return false;
1583 }
1584 bool Pre(const format::DerivedTypeDataEditDesc &x) { // R1307(2/2), R1312
peter klauslerb7cf5122018-03-14 22:31:161585 Word("DT");
peter klausler79d044e2018-03-01 00:56:101586 if (!x.type.empty()) {
1587 Put('"'), Put(x.type), Put('"');
1588 }
1589 Walk("(", x.parameters, ",", ")");
1590 return false;
1591 }
1592 bool Pre(const format::ControlEditDesc &x) { // R1313, R1315-R1320
1593 switch (x.kind) {
1594 case format::ControlEditDesc::Kind::T:
peter klauslerb7cf5122018-03-14 22:31:161595 Word("T");
peter klausler79d044e2018-03-01 00:56:101596 Walk(x.count);
1597 break;
1598 case format::ControlEditDesc::Kind::TL:
peter klauslerb7cf5122018-03-14 22:31:161599 Word("TL");
peter klausler79d044e2018-03-01 00:56:101600 Walk(x.count);
1601 break;
1602 case format::ControlEditDesc::Kind::TR:
peter klauslerb7cf5122018-03-14 22:31:161603 Word("TR");
peter klausler79d044e2018-03-01 00:56:101604 Walk(x.count);
1605 break;
1606 case format::ControlEditDesc::Kind::X:
1607 if (x.count != 1) {
1608 Walk(x.count);
1609 }
peter klauslerb7cf5122018-03-14 22:31:161610 Word("X");
peter klausler79d044e2018-03-01 00:56:101611 break;
1612 case format::ControlEditDesc::Kind::Slash:
1613 if (x.count != 1) {
1614 Walk(x.count);
1615 }
1616 Put('/');
1617 break;
1618 case format::ControlEditDesc::Kind::Colon: Put(':'); break;
1619 case format::ControlEditDesc::Kind::P:
1620 Walk(x.count);
peter klauslerb7cf5122018-03-14 22:31:161621 Word("P");
peter klausler79d044e2018-03-01 00:56:101622 break;
1623#define FMT(x) \
1624 case format::ControlEditDesc::Kind::x: Put(#x); break
1625 FMT(SS);
1626 FMT(SP);
1627 FMT(S);
1628 FMT(BN);
1629 FMT(BZ);
1630 FMT(RU);
1631 FMT(RD);
1632 FMT(RZ);
1633 FMT(RN);
1634 FMT(RC);
1635 FMT(RP);
1636 FMT(DC);
1637 FMT(DP);
1638#undef FMT
1639 default: CRASH_NO_CASE;
1640 }
1641 return false;
1642 }
1643
1644 bool Pre(const MainProgram &x) { // R1401
1645 if (!std::get<std::optional<Statement<ProgramStmt>>>(x.t)) {
1646 Indent();
1647 }
1648 return true;
1649 }
1650 bool Pre(const ProgramStmt &x) { // R1402
peter klauslerb7cf5122018-03-14 22:31:161651 Word("PROGRAM "), Indent();
peter klausler79d044e2018-03-01 00:56:101652 return true;
1653 }
1654 bool Pre(const EndProgramStmt &x) { // R1403
peter klauslerb7cf5122018-03-14 22:31:161655 Outdent(), Word("END PROGRAM"), Walk(" ", x.v);
peter klausler47dbbda2018-03-13 23:47:481656 return false;
peter klausler79d044e2018-03-01 00:56:101657 }
1658 bool Pre(const ModuleStmt &) { // R1405
peter klauslerb7cf5122018-03-14 22:31:161659 Word("MODULE "), Indent();
peter klausler79d044e2018-03-01 00:56:101660 return true;
1661 }
peter klausler47dbbda2018-03-13 23:47:481662 bool Pre(const EndModuleStmt &x) { // R1406
peter klauslerb7cf5122018-03-14 22:31:161663 Outdent(), Word("END MODULE"), Walk(" ", x.v);
peter klausler47dbbda2018-03-13 23:47:481664 return false;
peter klausler79d044e2018-03-01 00:56:101665 }
1666 bool Pre(const UseStmt &x) { // R1409
peter klauslerb7cf5122018-03-14 22:31:161667 Word("USE"), Walk(", ", x.nature), Put(" :: "), Walk(x.moduleName);
peter klausler79d044e2018-03-01 00:56:101668 std::visit(
1669 visitors{[&](const std::list<Rename> &y) { Walk(", ", y, ", "); },
1670 [&](const std::list<Only> &y) { Walk(", ONLY: ", y, ", "); }},
1671 x.u);
1672 return false;
1673 }
1674 bool Pre(const Rename &x) { // R1411
1675 std::visit(visitors{[&](const Rename::Names &y) { Walk(y.t, " => "); },
1676 [&](const Rename::Operators &y) {
peter klauslerd71f3cf2018-03-14 23:31:411677 Word("OPERATOR(."), Walk(y.t, ".) => OPERATOR(."),
1678 Put(".)");
peter klausler79d044e2018-03-01 00:56:101679 }},
1680 x.u);
1681 return false;
1682 }
1683 bool Pre(const SubmoduleStmt &x) { // R1417
peter klauslerb7cf5122018-03-14 22:31:161684 Word("SUBMODULE "), Indent();
peter klausler79d044e2018-03-01 00:56:101685 return true;
1686 }
1687 bool Pre(const ParentIdentifier &x) { // R1418
1688 Walk(std::get<Name>(x.t)), Walk(":", std::get<std::optional<Name>>(x.t));
1689 return false;
1690 }
peter klausler47dbbda2018-03-13 23:47:481691 bool Pre(const EndSubmoduleStmt &x) { // R1419
peter klauslerb7cf5122018-03-14 22:31:161692 Outdent(), Word("END SUBMODULE"), Walk(" ", x.v);
peter klausler47dbbda2018-03-13 23:47:481693 return false;
peter klausler79d044e2018-03-01 00:56:101694 }
1695 bool Pre(const BlockDataStmt &x) { // R1421
peter klauslerb7cf5122018-03-14 22:31:161696 Word("BLOCK DATA"), Walk(" ", x.v), Indent();
peter klausler79d044e2018-03-01 00:56:101697 return false;
1698 }
1699 bool Pre(const EndBlockDataStmt &x) { // R1422
peter klauslerb7cf5122018-03-14 22:31:161700 Outdent(), Word("END BLOCK DATA"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101701 return false;
1702 }
1703
1704 bool Pre(const InterfaceStmt &x) { // R1503
1705 std::visit(visitors{[&](const std::optional<GenericSpec> &y) {
peter klauslerb7cf5122018-03-14 22:31:161706 Word("INTERFACE"), Walk(" ", y);
peter klausler79d044e2018-03-01 00:56:101707 },
peter klauslerb7cf5122018-03-14 22:31:161708 [&](const Abstract &) { Word("ABSTRACT INTERFACE"); }},
peter klausler79d044e2018-03-01 00:56:101709 x.u);
1710 Indent();
1711 return false;
1712 }
1713 bool Pre(const EndInterfaceStmt &x) { // R1504
peter klauslerb7cf5122018-03-14 22:31:161714 Outdent(), Word("END INTERFACE"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101715 return false;
1716 }
1717 bool Pre(const ProcedureStmt &x) { // R1506
1718 if (std::get<ProcedureStmt::Kind>(x.t) ==
1719 ProcedureStmt::Kind::ModuleProcedure) {
peter klauslerb7cf5122018-03-14 22:31:161720 Word("MODULE ");
peter klausler79d044e2018-03-01 00:56:101721 }
peter klauslerb7cf5122018-03-14 22:31:161722 Word("PROCEDURE :: ");
peter klausler79d044e2018-03-01 00:56:101723 Walk(std::get<std::list<Name>>(x.t), ", ");
1724 return false;
1725 }
1726 bool Pre(const GenericSpec &x) { // R1508, R1509
peter klauslerd71f3cf2018-03-14 23:31:411727 std::visit(
1728 visitors{[&](const DefinedOperator &x) { Word("OPERATOR("); },
1729 [&](const GenericSpec::Assignment &) { Word("ASSIGNMENT(=)"); },
1730 [&](const GenericSpec::ReadFormatted &) {
1731 Word("READ(FORMATTED)");
1732 },
1733 [&](const GenericSpec::ReadUnformatted &) {
1734 Word("READ(UNFORMATTED)");
1735 },
1736 [&](const GenericSpec::WriteFormatted &) {
1737 Word("WRITE(FORMATTED)");
1738 },
1739 [&](const GenericSpec::WriteUnformatted &) {
1740 Word("WRITE(UNFORMATTED)");
1741 },
1742 [](const auto &) {}},
peter klausler79d044e2018-03-01 00:56:101743 x.u);
1744 return true;
1745 }
peter klauslerd71f3cf2018-03-14 23:31:411746 void Post(const GenericSpec &x) {
1747 std::visit(visitors{[&](const DefinedOperator &x) { Put(')'); },
1748 [](const auto &) {}},
1749 x.u);
1750 }
peter klausler79d044e2018-03-01 00:56:101751 bool Pre(const GenericStmt &x) { // R1510
peter klauslerb7cf5122018-03-14 22:31:161752 Word("GENERIC"), Walk(", ", std::get<std::optional<AccessSpec>>(x.t));
peter klausler79d044e2018-03-01 00:56:101753 Put(" :: "), Walk(std::get<GenericSpec>(x.t)), Put(" => ");
1754 Walk(std::get<std::list<Name>>(x.t), ", ");
1755 return false;
1756 }
1757 bool Pre(const ExternalStmt &x) { // R1511
peter klauslerb7cf5122018-03-14 22:31:161758 Word("EXTERNAL :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:101759 return false;
1760 }
1761 bool Pre(const ProcedureDeclarationStmt &x) { // R1512
peter klauslerb7cf5122018-03-14 22:31:161762 Word("PROCEDURE ("), Walk(std::get<std::optional<ProcInterface>>(x.t));
peter klausler79d044e2018-03-01 00:56:101763 Put(')'), Walk(", ", std::get<std::list<ProcAttrSpec>>(x.t), ", ");
1764 Put(" :: "), Walk(std::get<std::list<ProcDecl>>(x.t), ", ");
1765 return false;
1766 }
1767 bool Pre(const ProcDecl &x) { // R1515
1768 Walk(std::get<Name>(x.t));
1769 Walk(" => ", std::get<std::optional<ProcPointerInit>>(x.t));
1770 return false;
1771 }
1772 bool Pre(const IntrinsicStmt &x) { // R1519
peter klauslerb7cf5122018-03-14 22:31:161773 Word("INTRINSIC :: "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:101774 return false;
1775 }
1776 bool Pre(const FunctionReference &x) { // R1520
1777 Walk(std::get<ProcedureDesignator>(x.v.t));
1778 Put('('), Walk(std::get<std::list<ActualArgSpec>>(x.v.t), ", "), Put(')');
1779 return false;
1780 }
1781 bool Pre(const CallStmt &x) { // R1521
peter klauslerb7cf5122018-03-14 22:31:161782 Word("CALL "), Walk(std::get<ProcedureDesignator>(x.v.t));
peter klausler62d9cdd2018-03-15 00:02:211783 Walk("(", std::get<std::list<ActualArgSpec>>(x.v.t), ", ", ")");
peter klausler79d044e2018-03-01 00:56:101784 return false;
1785 }
1786 bool Pre(const ActualArgSpec &x) { // R1523
1787 Walk(std::get<std::optional<Keyword>>(x.t), "=");
1788 Walk(std::get<ActualArg>(x.t));
1789 return false;
1790 }
1791 bool Pre(const ActualArg::PercentRef &x) { // R1524
peter klauslerb7cf5122018-03-14 22:31:161792 Word("%REF("), Walk(x.v), Put(')');
peter klausler79d044e2018-03-01 00:56:101793 return false;
1794 }
1795 bool Pre(const ActualArg::PercentVal &x) {
peter klauslerb7cf5122018-03-14 22:31:161796 Word("%VAL("), Walk(x.v), Put(')');
peter klausler79d044e2018-03-01 00:56:101797 return false;
1798 }
1799 bool Pre(const AltReturnSpec &) { // R1525
peter klauslerb7cf5122018-03-14 22:31:161800 Put('*');
peter klausler79d044e2018-03-01 00:56:101801 return true;
1802 }
peter klauslerd71f3cf2018-03-14 23:31:411803 void Post(const PrefixSpec::Elemental) { Word("ELEMENTAL"); } // R1527
1804 void Post(const PrefixSpec::Impure) { Word("IMPURE"); }
1805 void Post(const PrefixSpec::Module) { Word("MODULE"); }
1806 void Post(const PrefixSpec::Non_Recursive) { Word("NON_RECURSIVE"); }
1807 void Post(const PrefixSpec::Pure) { Word("PURE"); }
1808 void Post(const PrefixSpec::Recursive) { Word("RECURSIVE"); }
peter klausler79d044e2018-03-01 00:56:101809 bool Pre(const FunctionStmt &x) { // R1530
1810 Walk("", std::get<std::list<PrefixSpec>>(x.t), " ", " ");
peter klausler62d9cdd2018-03-15 00:02:211811 Word("FUNCTION "), Walk(std::get<Name>(x.t)), Put("(");
peter klausler79d044e2018-03-01 00:56:101812 Walk(std::get<std::list<Name>>(x.t), ", "), Put(')');
1813 Walk(" ", std::get<std::optional<Suffix>>(x.t)), Indent();
1814 return false;
1815 }
1816 bool Pre(const Suffix &x) { // R1532
1817 if (x.resultName) {
peter klauslerb7cf5122018-03-14 22:31:161818 Word("RESULT("), Walk(x.resultName), Put(')');
peter klausler79d044e2018-03-01 00:56:101819 Walk(" ", x.binding);
1820 } else {
1821 Walk(x.binding);
1822 }
1823 return false;
1824 }
1825 bool Pre(const EndFunctionStmt &x) { // R1533
peter klauslerb7cf5122018-03-14 22:31:161826 Outdent(), Word("END FUNCTION"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101827 return false;
1828 }
1829 bool Pre(const SubroutineStmt &x) { // R1535
1830 Walk("", std::get<std::list<PrefixSpec>>(x.t), " ", " ");
peter klauslerb7cf5122018-03-14 22:31:161831 Word("SUBROUTINE "), Walk(std::get<Name>(x.t));
peter klauslerd71f3cf2018-03-14 23:31:411832 const auto &args = std::get<std::list<DummyArg>>(x.t);
1833 const auto &bind = std::get<std::optional<LanguageBindingSpec>>(x.t);
1834 if (args.empty()) {
1835 Walk(" () ", bind);
1836 } else {
1837 Walk(" (", args, ", ", ")");
1838 Walk(" ", bind);
1839 }
peter klausler79d044e2018-03-01 00:56:101840 Indent();
1841 return false;
1842 }
1843 bool Pre(const EndSubroutineStmt &x) { // R1537
peter klauslerb7cf5122018-03-14 22:31:161844 Outdent(), Word("END SUBROUTINE"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101845 return false;
1846 }
1847 bool Pre(const MpSubprogramStmt &) { // R1539
peter klauslerb7cf5122018-03-14 22:31:161848 Word("MODULE PROCEDURE "), Indent();
peter klausler79d044e2018-03-01 00:56:101849 return true;
1850 }
1851 bool Pre(const EndMpSubprogramStmt &x) { // R1540
peter klauslerb7cf5122018-03-14 22:31:161852 Outdent(), Word("END PROCEDURE"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101853 return false;
1854 }
1855 bool Pre(const EntryStmt &x) { // R1541
peter klauslerb7cf5122018-03-14 22:31:161856 Word("ENTRY "), Walk(std::get<Name>(x.t));
peter klausler62d9cdd2018-03-15 00:02:211857 Walk("(", std::get<std::list<DummyArg>>(x.t), ", ", ")");
peter klausler79d044e2018-03-01 00:56:101858 Walk(" ", std::get<std::optional<Suffix>>(x.t));
1859 return false;
1860 }
1861 bool Pre(const ReturnStmt &x) { // R1542
peter klauslerb7cf5122018-03-14 22:31:161862 Word("RETURN"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101863 return false;
1864 }
1865 bool Pre(const ContainsStmt &x) { // R1543
1866 Outdent();
peter klauslerb7cf5122018-03-14 22:31:161867 Word("CONTAINS");
peter klausler79d044e2018-03-01 00:56:101868 Indent();
1869 return false;
1870 }
1871 bool Pre(const StmtFunctionStmt &x) { // R1544
1872 Walk(std::get<Name>(x.t)), Put('(');
1873 Walk(std::get<std::list<Name>>(x.t), ", "), Put(") = ");
1874 Walk(std::get<Scalar<Expr>>(x.t));
1875 return false;
1876 }
1877
1878 // Extensions and deprecated constructs
1879 bool Pre(const BasedPointerStmt &x) {
peter klauslerb7cf5122018-03-14 22:31:161880 Word("POINTER ("), Walk(std::get<0>(x.t)), Put(", ");
1881 Walk(std::get<1>(x.t));
peter klausler79d044e2018-03-01 00:56:101882 Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"), Put(')');
1883 return false;
1884 }
1885 bool Pre(const StructureStmt &x) {
peter klauslerb7cf5122018-03-14 22:31:161886 Word("STRUCTURE ");
peter klausler79d044e2018-03-01 00:56:101887 if (std::get<bool>(x.t)) { // slashes around name
1888 Put('/'), Walk(std::get<Name>(x.t)), Put('/');
1889 Walk(" ", std::get<std::list<EntityDecl>>(x.t), ", ");
1890 } else {
1891 CHECK(std::get<std::list<EntityDecl>>(x.t).empty());
1892 Walk(std::get<Name>(x.t));
1893 }
1894 Indent();
1895 percentOrDot_ = '.'; // TODO: this is so lame
1896 return false;
1897 }
peter klauslerb7cf5122018-03-14 22:31:161898 void Post(const Union::UnionStmt &) { Word("UNION"), Indent(); }
1899 void Post(const Union::EndUnionStmt &) { Outdent(), Word("END UNION"); }
1900 void Post(const Map::MapStmt &) { Word("MAP"), Indent(); }
1901 void Post(const Map::EndMapStmt &) { Outdent(), Word("END MAP"); }
peter klausler79d044e2018-03-01 00:56:101902 void Post(const StructureDef::EndStructureStmt &) {
peter klauslerb7cf5122018-03-14 22:31:161903 Outdent(), Word("END STRUCTURE");
peter klausler79d044e2018-03-01 00:56:101904 }
1905 bool Pre(const OldParameterStmt &x) {
peter klauslerb7cf5122018-03-14 22:31:161906 Word("PARAMETER "), Walk(x.v, ", ");
peter klausler79d044e2018-03-01 00:56:101907 return false;
1908 }
1909 bool Pre(const ArithmeticIfStmt &x) {
peter klauslerb7cf5122018-03-14 22:31:161910 Word("IF ("), Walk(std::get<Expr>(x.t)), Put(") ");
peter klausler79d044e2018-03-01 00:56:101911 Walk(std::get<1>(x.t)), Put(", ");
1912 Walk(std::get<2>(x.t)), Put(", ");
1913 Walk(std::get<3>(x.t));
1914 return false;
1915 }
1916 bool Pre(const AssignStmt &x) {
peter klauslerb7cf5122018-03-14 22:31:161917 Word("ASSIGN "), Walk(std::get<Label>(x.t));
1918 Word(" TO "), Walk(std::get<Name>(x.t));
peter klausler79d044e2018-03-01 00:56:101919 return false;
1920 }
1921 bool Pre(const AssignedGotoStmt &x) {
peter klauslerb7cf5122018-03-14 22:31:161922 Word("GO TO "), Walk(std::get<Name>(x.t));
peter klausler79d044e2018-03-01 00:56:101923 Walk(", (", std::get<std::list<Label>>(x.t), ", ", ")");
1924 return false;
1925 }
1926 bool Pre(const PauseStmt &x) {
peter klauslerb7cf5122018-03-14 22:31:161927 Word("PAUSE"), Walk(" ", x.v);
peter klausler79d044e2018-03-01 00:56:101928 return false;
1929 }
1930
1931#define WALK_NESTED_ENUM(ENUMTYPE) \
1932 bool Pre(const ENUMTYPE &x) { \
1933 PutEnum(static_cast<int>(x), ENUMTYPE##AsString); \
1934 return false; \
1935 }
1936 WALK_NESTED_ENUM(AccessSpec::Kind) // R807
1937 WALK_NESTED_ENUM(TypeParamDefStmt::KindOrLen) // R734
1938 WALK_NESTED_ENUM(IntentSpec::Intent) // R826
1939 WALK_NESTED_ENUM(ImplicitStmt::ImplicitNoneNameSpec) // R866
1940 WALK_NESTED_ENUM(ConnectSpec::CharExpr::Kind) // R1205
1941 WALK_NESTED_ENUM(IoControlSpec::CharExpr::Kind)
1942 WALK_NESTED_ENUM(InquireSpec::CharVar::Kind)
1943 WALK_NESTED_ENUM(InquireSpec::IntVar::Kind)
1944 WALK_NESTED_ENUM(InquireSpec::LogVar::Kind)
1945 WALK_NESTED_ENUM(ProcedureStmt::Kind) // R1506
1946 WALK_NESTED_ENUM(UseStmt::ModuleNature) // R1410
1947#undef WALK_NESTED_ENUM
1948
1949 void Done() const { CHECK(indent_ == 0); }
1950
1951private:
1952 void Put(char);
1953 void Put(const char *);
1954 void Put(const std::string &);
peter klauslerb7cf5122018-03-14 22:31:161955 void PutKeywordLetter(char);
peter klausler79d044e2018-03-01 00:56:101956 void PutQuoted(const std::string &);
1957 void PutEnum(int, const char *);
peter klauslerb7cf5122018-03-14 22:31:161958 void Word(const char *);
peter klausler79d044e2018-03-01 00:56:101959 void Indent() { indent_ += indentationAmount_; }
1960 void Outdent() {
1961 CHECK(indent_ >= indentationAmount_);
1962 indent_ -= indentationAmount_;
1963 }
1964
1965 // Call back to the traversal framework.
Tim Keith2af29bc2018-02-26 22:28:321966 template<typename T> void Walk(const T &x) {
1967 Fortran::parser::Walk(x, *this);
1968 }
1969
peter klausler79d044e2018-03-01 00:56:101970 // Traverse a std::optional<> value. Emit a prefix and/or a suffix string
1971 // only when it contains a value.
1972 template<typename A>
1973 void Walk(
1974 const char *prefix, const std::optional<A> &x, const char *suffix = "") {
1975 if (x.has_value()) {
peter klauslerb7cf5122018-03-14 22:31:161976 Word(prefix), Walk(*x), Word(suffix);
Tim Keith2af29bc2018-02-26 22:28:321977 }
1978 }
peter klausler79d044e2018-03-01 00:56:101979 template<typename A>
1980 void Walk(const std::optional<A> &x, const char *suffix = "") {
1981 return Walk("", x, suffix);
1982 }
1983
1984 // Traverse a std::list<>. Separate the elements with an optional string.
1985 // Emit a prefix and/or a suffix string only when the list is not empty.
1986 template<typename A>
1987 void Walk(const char *prefix, const std::list<A> &list,
1988 const char *comma = ", ", const char *suffix = "") {
1989 if (!list.empty()) {
1990 const char *str{prefix};
1991 for (const auto &x : list) {
peter klauslerb7cf5122018-03-14 22:31:161992 Word(str), Walk(x);
peter klausler79d044e2018-03-01 00:56:101993 str = comma;
1994 }
peter klauslerb7cf5122018-03-14 22:31:161995 Word(suffix);
peter klausler79d044e2018-03-01 00:56:101996 }
1997 }
1998 template<typename A>
1999 void Walk(const std::list<A> &list, const char *comma = ", ",
2000 const char *suffix = "") {
2001 return Walk("", list, comma, suffix);
2002 }
2003
2004 // Traverse a std::tuple<>, with an optional separator.
2005 template<size_t J = 0, typename T>
2006 void WalkTupleElements(const T &tuple, const char *separator) {
2007 if constexpr (J < std::tuple_size_v<T>) {
2008 if (J > 0) {
peter klauslerb7cf5122018-03-14 22:31:162009 Word(separator);
peter klausler79d044e2018-03-01 00:56:102010 }
2011 Walk(std::get<J>(tuple));
2012 WalkTupleElements<J + 1>(tuple, separator);
2013 }
2014 }
2015 template<typename... A>
2016 void Walk(const std::tuple<A...> &tuple, const char *separator = "") {
2017 WalkTupleElements(tuple, separator);
2018 }
2019
2020 std::ostream &out_;
2021 int indent_{0};
2022 const int indentationAmount_{1};
2023 int column_{1};
2024 const int maxColumns_{80};
2025 char percentOrDot_{'%'};
2026 Encoding encoding_{Encoding::UTF8};
peter klauslerb7cf5122018-03-14 22:31:162027 bool capitalizeKeywords_{true};
Tim Keith2af29bc2018-02-26 22:28:322028};
2029
peter klausler79d044e2018-03-01 00:56:102030void UnparseVisitor::Put(char ch) {
2031 if (column_ <= 1) {
2032 if (ch == '\n') {
2033 return;
2034 }
2035 for (int j{0}; j < indent_; ++j) {
2036 out_ << ' ';
2037 }
2038 column_ = indent_ + 2;
2039 } else if (ch == '\n') {
2040 column_ = 1;
2041 } else if (++column_ >= maxColumns_) {
2042 out_ << "&\n";
2043 for (int j{0}; j < indent_; ++j) {
2044 out_ << ' ';
2045 }
2046 out_ << '&';
2047 column_ = indent_ + 3;
2048 }
2049 out_ << ch;
Tim Keith2af29bc2018-02-26 22:28:322050}
2051
peter klausler79d044e2018-03-01 00:56:102052void UnparseVisitor::Put(const char *str) {
2053 for (; *str != '\0'; ++str) {
2054 Put(*str);
2055 }
2056}
2057
2058void UnparseVisitor::Put(const std::string &str) {
2059 for (char ch : str) {
2060 Put(ch);
2061 }
2062}
2063
peter klauslerb7cf5122018-03-14 22:31:162064void UnparseVisitor::PutKeywordLetter(char ch) {
2065 if (capitalizeKeywords_) {
peter klausler79d044e2018-03-01 00:56:102066 Put(ToUpperCaseLetter(ch));
peter klauslerb7cf5122018-03-14 22:31:162067 } else {
2068 Put(ToLowerCaseLetter(ch));
peter klausler79d044e2018-03-01 00:56:102069 }
2070}
2071
2072void UnparseVisitor::PutQuoted(const std::string &str) {
2073 Put('"');
2074 const auto emit = [&](char ch) { Put(ch); };
2075 for (char ch : str) {
2076 EmitQuotedChar(ch, emit, emit);
2077 }
2078 Put('"');
2079}
2080
2081void UnparseVisitor::PutEnum(int n, const char *enumNames) {
2082 const char *p{enumNames};
2083 for (; n > 0; --n, ++p) {
2084 for (; *p && *p != ','; ++p) {
2085 }
2086 }
2087 while (*p == ' ') {
2088 ++p;
2089 }
2090 CHECK(*p != '\0');
2091 for (; *p && *p != ' ' && *p != ','; ++p) {
peter klauslerb7cf5122018-03-14 22:31:162092 PutKeywordLetter(*p);
peter klausler79d044e2018-03-01 00:56:102093 }
2094}
2095
peter klauslerb7cf5122018-03-14 22:31:162096void UnparseVisitor::Word(const char *str) {
2097 for (; *str != '\0'; ++str) {
2098 PutKeywordLetter(*str);
2099 }
2100}
2101
2102void Unparse(std::ostream &out, const Program &program, Encoding encoding,
2103 bool capitalizeKeywords) {
2104 UnparseVisitor visitor{out, 1, encoding, capitalizeKeywords};
peter klausler79d044e2018-03-01 00:56:102105 Walk(program, visitor);
2106 visitor.Done();
2107}
Tim Keith2af29bc2018-02-26 22:28:322108} // namespace parser
2109} // namespace Fortran