0c78d8bd9b
Original-commit: flang-compiler/f18@14aa5198f3 Reviewed-on: https://github.com/flang-compiler/f18/pull/346
2629 lines
86 KiB
C++
2629 lines
86 KiB
C++
// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Generates Fortran from the content of a parse tree, using the
|
|
// traversal templates in parse-tree-visitor.h.
|
|
|
|
#include "unparse.h"
|
|
#include "characters.h"
|
|
#include "parse-tree-visitor.h"
|
|
#include "parse-tree.h"
|
|
#include "../common/Fortran.h"
|
|
#include "../common/idioms.h"
|
|
#include "../common/indirection.h"
|
|
#include <algorithm>
|
|
#include <cinttypes>
|
|
#include <cstddef>
|
|
#include <set>
|
|
|
|
namespace Fortran::parser {
|
|
|
|
class UnparseVisitor {
|
|
public:
|
|
UnparseVisitor(std::ostream &out, int indentationAmount, Encoding encoding,
|
|
bool capitalize, bool backslashEscapes, preStatementType *preStatement)
|
|
: out_{out}, indentationAmount_{indentationAmount}, encoding_{encoding},
|
|
capitalizeKeywords_{capitalize}, backslashEscapes_{backslashEscapes},
|
|
preStatement_{preStatement} {}
|
|
|
|
// In nearly all cases, this code avoids defining Boolean-valued Pre()
|
|
// callbacks for the parse tree walking framework in favor of two void
|
|
// functions, Before() and Unparse(), which imply true and false return
|
|
// values for Pre() respectively.
|
|
template<typename T> void Before(const T &) {}
|
|
template<typename T> double Unparse(const T &); // not void, never used
|
|
|
|
template<typename T> bool Pre(const T &x) {
|
|
if constexpr (std::is_void_v<decltype(Unparse(x))>) {
|
|
// There is a local definition of Unparse() for this type. It
|
|
// overrides the parse tree walker's default Walk() over the descendents.
|
|
Before(x);
|
|
Unparse(x);
|
|
Post(x);
|
|
return false; // Walk() does not visit descendents
|
|
} else {
|
|
Before(x);
|
|
return true; // there's no Unparse() defined here, Walk() the descendents
|
|
}
|
|
}
|
|
template<typename T> void Post(const T &) {}
|
|
|
|
// Emit simple types as-is.
|
|
void Unparse(const std::string &x) { Put(x); }
|
|
void Unparse(int x) { Put(std::to_string(x)); }
|
|
void Unparse(unsigned int x) { Put(std::to_string(x)); }
|
|
void Unparse(long x) { Put(std::to_string(x)); }
|
|
void Unparse(unsigned long x) { Put(std::to_string(x)); }
|
|
void Unparse(long long x) { Put(std::to_string(x)); }
|
|
void Unparse(unsigned long long x) { Put(std::to_string(x)); }
|
|
void Unparse(char x) { Put(x); }
|
|
|
|
// Statement labels and ends of lines
|
|
template<typename T> void Before(const Statement<T> &x) {
|
|
if (preStatement_) {
|
|
(*preStatement_)(x.source, out_, indent_);
|
|
}
|
|
Walk(x.label, " ");
|
|
}
|
|
template<typename T> void Post(const Statement<T> &) { Put('\n'); }
|
|
|
|
// The special-case formatting functions for these productions are
|
|
// ordered to correspond roughly to their order of appearance in
|
|
// the Fortran 2018 standard (and parse-tree.h).
|
|
|
|
void Unparse(const Program &x) { // R501
|
|
Walk("", x.v, "\n"); // put blank lines between ProgramUnits
|
|
}
|
|
|
|
void Unparse(const Name &x) { // R603
|
|
Put(x.ToString());
|
|
}
|
|
void Unparse(const DefinedOperator::IntrinsicOperator &x) { // R608
|
|
switch (x) {
|
|
case DefinedOperator::IntrinsicOperator::Power: Put("**"); break;
|
|
case DefinedOperator::IntrinsicOperator::Multiply: Put('*'); break;
|
|
case DefinedOperator::IntrinsicOperator::Divide: Put('/'); break;
|
|
case DefinedOperator::IntrinsicOperator::Add: Put('+'); break;
|
|
case DefinedOperator::IntrinsicOperator::Subtract: Put('-'); break;
|
|
case DefinedOperator::IntrinsicOperator::Concat: Put("//"); break;
|
|
case DefinedOperator::IntrinsicOperator::LT: Put('<'); break;
|
|
case DefinedOperator::IntrinsicOperator::LE: Put("<="); break;
|
|
case DefinedOperator::IntrinsicOperator::EQ: Put("=="); break;
|
|
case DefinedOperator::IntrinsicOperator::NE: Put("/="); break;
|
|
case DefinedOperator::IntrinsicOperator::GE: Put(">="); break;
|
|
case DefinedOperator::IntrinsicOperator::GT: Put('>'); break;
|
|
default: Put('.'), Word(DefinedOperator::EnumToString(x)), Put('.');
|
|
}
|
|
}
|
|
void Post(const Star &) { Put('*'); } // R701 &c.
|
|
void Post(const TypeParamValue::Deferred &) { Put(':'); } // R701
|
|
void Unparse(const DeclarationTypeSpec::Type &x) { // R703
|
|
Word("TYPE("), Walk(x.derived), Put(')');
|
|
}
|
|
void Unparse(const DeclarationTypeSpec::Class &x) {
|
|
Word("CLASS("), Walk(x.derived), Put(')');
|
|
}
|
|
void Post(const DeclarationTypeSpec::ClassStar &) { Word("CLASS(*)"); }
|
|
void Post(const DeclarationTypeSpec::TypeStar &) { Word("TYPE(*)"); }
|
|
void Unparse(const DeclarationTypeSpec::Record &x) {
|
|
Word("RECORD/"), Walk(x.v), Put('/');
|
|
}
|
|
void Before(const IntrinsicTypeSpec::Real &x) { // R704
|
|
Word("REAL");
|
|
}
|
|
void Before(const IntrinsicTypeSpec::Complex &x) { Word("COMPLEX"); }
|
|
void Post(const IntrinsicTypeSpec::DoublePrecision &) {
|
|
Word("DOUBLE PRECISION");
|
|
}
|
|
void Before(const IntrinsicTypeSpec::Character &x) { Word("CHARACTER"); }
|
|
void Before(const IntrinsicTypeSpec::Logical &x) { Word("LOGICAL"); }
|
|
void Post(const IntrinsicTypeSpec::DoubleComplex &) {
|
|
Word("DOUBLE COMPLEX");
|
|
}
|
|
void Before(const IntrinsicTypeSpec::NCharacter &x) { Word("NCHARACTER"); }
|
|
void Before(const IntegerTypeSpec &x) { // R705
|
|
Word("INTEGER");
|
|
}
|
|
void Unparse(const KindSelector &x) { // R706
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const ScalarIntConstantExpr &y) {
|
|
Put('('), Word("KIND="), Walk(y), Put(')');
|
|
},
|
|
[&](const KindSelector::StarSize &y) { Put('*'), Walk(y.v); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const SignedIntLiteralConstant &x) { // R707
|
|
Walk(std::get<std::int64_t>(x.t));
|
|
Walk("_", std::get<std::optional<KindParam>>(x.t));
|
|
}
|
|
void Unparse(const IntLiteralConstant &x) { // R708
|
|
Walk(std::get<std::uint64_t>(x.t));
|
|
Walk("_", std::get<std::optional<KindParam>>(x.t));
|
|
}
|
|
void Unparse(const Sign &x) { // R712
|
|
Put(x == Sign::Negative ? '-' : '+');
|
|
}
|
|
void Unparse(const RealLiteralConstant &x) { // R714, R715
|
|
Put(x.real.source.ToString()), Walk("_", x.kind);
|
|
}
|
|
void Unparse(const ComplexLiteralConstant &x) { // R718 - R720
|
|
Put('('), Walk(x.t, ","), Put(')');
|
|
}
|
|
void Unparse(const CharSelector::LengthAndKind &x) { // R721
|
|
Put('('), Word("KIND="), Walk(x.kind);
|
|
Walk(", LEN=", x.length), Put(')');
|
|
}
|
|
void Unparse(const LengthSelector &x) { // R722
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const TypeParamValue &y) {
|
|
Put('('), Word("LEN="), Walk(y), Put(')');
|
|
},
|
|
[&](const CharLength &y) { Put('*'), Walk(y); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const CharLength &x) { // R723
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const TypeParamValue &y) { Put('('), Walk(y), Put(')'); },
|
|
[&](const std::int64_t &y) { Walk(y); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const CharLiteralConstant &x) { // R724
|
|
if (const auto &k{std::get<std::optional<KindParam>>(x.t)}) {
|
|
if (std::holds_alternative<KindParam::Kanji>(k->u)) {
|
|
Word("NC");
|
|
} else {
|
|
Walk(*k), Put('_');
|
|
}
|
|
}
|
|
Put(QuoteCharacterLiteral(
|
|
std::get<std::string>(x.t), true, backslashEscapes_));
|
|
}
|
|
void Before(const HollerithLiteralConstant &x) {
|
|
std::optional<std::size_t> chars{CountCharacters(x.v.data(), x.v.size(),
|
|
encoding_ == Encoding::EUC_JP ? EUC_JPCharacterBytes
|
|
: UTF8CharacterBytes)};
|
|
if (chars.has_value()) {
|
|
Unparse(*chars);
|
|
} else {
|
|
Unparse(x.v.size());
|
|
}
|
|
Put('H');
|
|
}
|
|
void Unparse(const LogicalLiteralConstant &x) { // R725
|
|
Put(std::get<bool>(x.t) ? ".TRUE." : ".FALSE.");
|
|
Walk("_", std::get<std::optional<KindParam>>(x.t));
|
|
}
|
|
void Unparse(const DerivedTypeStmt &x) { // R727
|
|
Word("TYPE"), Walk(", ", std::get<std::list<TypeAttrSpec>>(x.t), ", ");
|
|
Put(" :: "), Walk(std::get<Name>(x.t));
|
|
Walk("(", std::get<std::list<Name>>(x.t), ", ", ")");
|
|
Indent();
|
|
}
|
|
void Unparse(const Abstract &x) { // R728, &c.
|
|
Word("ABSTRACT");
|
|
}
|
|
void Post(const TypeAttrSpec::BindC &) { Word("BIND(C)"); }
|
|
void Unparse(const TypeAttrSpec::Extends &x) {
|
|
Word("EXTENDS("), Walk(x.v), Put(')');
|
|
}
|
|
void Unparse(const EndTypeStmt &x) { // R730
|
|
Outdent(), Word("END TYPE"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const SequenceStmt &x) { // R731
|
|
Word("SEQUENCE");
|
|
}
|
|
void Unparse(const TypeParamDefStmt &x) { // R732
|
|
Walk(std::get<IntegerTypeSpec>(x.t));
|
|
Put(", "), Walk(std::get<common::TypeParamAttr>(x.t));
|
|
Put(" :: "), Walk(std::get<std::list<TypeParamDecl>>(x.t), ", ");
|
|
}
|
|
void Unparse(const TypeParamDecl &x) { // R733
|
|
Walk(std::get<Name>(x.t));
|
|
Walk("=", std::get<std::optional<ScalarIntConstantExpr>>(x.t));
|
|
}
|
|
void Unparse(const DataComponentDefStmt &x) { // R737
|
|
const auto &dts{std::get<DeclarationTypeSpec>(x.t)};
|
|
const auto &attrs{std::get<std::list<ComponentAttrSpec>>(x.t)};
|
|
const auto &decls{std::get<std::list<ComponentDecl>>(x.t)};
|
|
Walk(dts), Walk(", ", attrs, ", ");
|
|
if (!attrs.empty() ||
|
|
(!std::holds_alternative<DeclarationTypeSpec::Record>(dts.u) &&
|
|
std::none_of(
|
|
decls.begin(), decls.end(), [](const ComponentDecl &d) {
|
|
const auto &init{
|
|
std::get<std::optional<Initialization>>(d.t)};
|
|
return init.has_value() &&
|
|
std::holds_alternative<
|
|
std::list<common::Indirection<DataStmtValue>>>(
|
|
init->u);
|
|
}))) {
|
|
Put(" ::");
|
|
}
|
|
Put(' '), Walk(decls, ", ");
|
|
}
|
|
void Unparse(const Allocatable &x) { // R738
|
|
Word("ALLOCATABLE");
|
|
}
|
|
void Unparse(const Pointer &x) { Word("POINTER"); }
|
|
void Unparse(const Contiguous &x) { Word("CONTIGUOUS"); }
|
|
void Before(const ComponentAttrSpec &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const CoarraySpec &) { Word("CODIMENSION["); },
|
|
[&](const ComponentArraySpec &) { Word("DIMENSION("); },
|
|
[](const auto &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Post(const ComponentAttrSpec &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const CoarraySpec &) { Put(']'); },
|
|
[&](const ComponentArraySpec &) { Put(')'); },
|
|
[](const auto &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const ComponentDecl &x) { // R739
|
|
Walk(std::get<ObjectName>(x.t));
|
|
Walk("(", std::get<std::optional<ComponentArraySpec>>(x.t), ")");
|
|
Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]");
|
|
Walk("*", std::get<std::optional<CharLength>>(x.t));
|
|
Walk(std::get<std::optional<Initialization>>(x.t));
|
|
}
|
|
void Unparse(const ComponentArraySpec &x) { // R740
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
|
|
[&](const DeferredShapeSpecList &y) { Walk(y); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const ProcComponentDefStmt &x) { // R741
|
|
Word("PROCEDURE(");
|
|
Walk(std::get<std::optional<ProcInterface>>(x.t)), Put(')');
|
|
Walk(", ", std::get<std::list<ProcComponentAttrSpec>>(x.t), ", ");
|
|
Put(" :: "), Walk(std::get<std::list<ProcDecl>>(x.t), ", ");
|
|
}
|
|
void Unparse(const NoPass &x) { // R742
|
|
Word("NOPASS");
|
|
}
|
|
void Unparse(const Pass &x) { Word("PASS"), Walk("(", x.v, ")"); }
|
|
void Unparse(const Initialization &x) { // R743 & R805
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const ConstantExpr &y) { Put(" = "), Walk(y); },
|
|
[&](const NullInit &y) { Put(" => "), Walk(y); },
|
|
[&](const InitialDataTarget &y) { Put(" => "), Walk(y); },
|
|
[&](const std::list<common::Indirection<DataStmtValue>> &y) {
|
|
Walk("/", y, ", ", "/");
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const PrivateStmt &x) { // R745
|
|
Word("PRIVATE");
|
|
}
|
|
void Unparse(const TypeBoundProcedureStmt::WithoutInterface &x) { // R749
|
|
Word("PROCEDURE"), Walk(", ", x.attributes, ", ");
|
|
Put(" :: "), Walk(x.declarations, ", ");
|
|
}
|
|
void Unparse(const TypeBoundProcedureStmt::WithInterface &x) {
|
|
Word("PROCEDURE("), Walk(x.interfaceName), Put("), ");
|
|
Walk(x.attributes);
|
|
Put(" :: "), Walk(x.bindingNames, ", ");
|
|
}
|
|
void Unparse(const TypeBoundProcDecl &x) { // R750
|
|
Walk(std::get<Name>(x.t));
|
|
Walk(" => ", std::get<std::optional<Name>>(x.t));
|
|
}
|
|
void Unparse(const TypeBoundGenericStmt &x) { // R751
|
|
Word("GENERIC"), Walk(", ", std::get<std::optional<AccessSpec>>(x.t));
|
|
Put(" :: "), Walk(std::get<common::Indirection<GenericSpec>>(x.t));
|
|
Put(" => "), Walk(std::get<std::list<Name>>(x.t), ", ");
|
|
}
|
|
void Post(const BindAttr::Deferred &) { Word("DEFERRED"); } // R752
|
|
void Post(const BindAttr::Non_Overridable &) { Word("NON_OVERRIDABLE"); }
|
|
void Unparse(const FinalProcedureStmt &x) { // R753
|
|
Word("FINAL :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const DerivedTypeSpec &x) { // R754
|
|
Walk(std::get<Name>(x.t));
|
|
Walk("(", std::get<std::list<TypeParamSpec>>(x.t), ",", ")");
|
|
}
|
|
void Unparse(const TypeParamSpec &x) { // R755
|
|
Walk(std::get<std::optional<Keyword>>(x.t), "=");
|
|
Walk(std::get<TypeParamValue>(x.t));
|
|
}
|
|
void Unparse(const StructureConstructor &x) { // R756
|
|
Walk(std::get<DerivedTypeSpec>(x.t));
|
|
Put('('), Walk(std::get<std::list<ComponentSpec>>(x.t), ", "), Put(')');
|
|
}
|
|
void Unparse(const ComponentSpec &x) { // R757
|
|
Walk(std::get<std::optional<Keyword>>(x.t), "=");
|
|
Walk(std::get<ComponentDataSource>(x.t));
|
|
}
|
|
void Unparse(const EnumDefStmt &) { // R760
|
|
Word("ENUM, BIND(C)"), Indent();
|
|
}
|
|
void Unparse(const EnumeratorDefStmt &x) { // R761
|
|
Word("ENUMERATOR :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const Enumerator &x) { // R762
|
|
Walk(std::get<NamedConstant>(x.t));
|
|
Walk(" = ", std::get<std::optional<ScalarIntConstantExpr>>(x.t));
|
|
}
|
|
void Post(const EndEnumStmt &) { // R763
|
|
Outdent(), Word("END ENUM");
|
|
}
|
|
void Unparse(const BOZLiteralConstant &x) { // R764 - R767
|
|
Put(x.v);
|
|
}
|
|
void Unparse(const AcValue::Triplet &x) { // R773
|
|
Walk(std::get<0>(x.t)), Put(':'), Walk(std::get<1>(x.t));
|
|
Walk(":", std::get<std::optional<ScalarIntExpr>>(x.t));
|
|
}
|
|
void Unparse(const ArrayConstructor &x) { // R769
|
|
Put('['), Walk(x.v), Put(']');
|
|
}
|
|
void Unparse(const AcSpec &x) { // R770
|
|
Walk(x.type, "::"), Walk(x.values, ", ");
|
|
}
|
|
template<typename A> void Unparse(const LoopBounds<A> &x) {
|
|
Walk(x.name), Put('='), Walk(x.lower), Put(','), Walk(x.upper);
|
|
Walk(",", x.step);
|
|
}
|
|
void Unparse(const AcImpliedDo &x) { // R774
|
|
Put('('), Walk(std::get<std::list<AcValue>>(x.t), ", ");
|
|
Put(", "), Walk(std::get<AcImpliedDoControl>(x.t)), Put(')');
|
|
}
|
|
void Unparse(const AcImpliedDoControl &x) { // R775
|
|
Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::");
|
|
Walk(std::get<LoopBounds<ScalarIntExpr>>(x.t));
|
|
}
|
|
|
|
void Unparse(const TypeDeclarationStmt &x) { // R801
|
|
const auto &dts{std::get<DeclarationTypeSpec>(x.t)};
|
|
const auto &attrs{std::get<std::list<AttrSpec>>(x.t)};
|
|
const auto &decls{std::get<std::list<EntityDecl>>(x.t)};
|
|
Walk(dts), Walk(", ", attrs, ", ");
|
|
|
|
static const auto isInitializerOldStyle{[](const Initialization &i) {
|
|
return std::holds_alternative<
|
|
std::list<common::Indirection<DataStmtValue>>>(i.u);
|
|
}};
|
|
static const auto hasAssignmentInitializer{[](const EntityDecl &d) {
|
|
// Does a declaration have a new-style =x initializer?
|
|
const auto &init{std::get<std::optional<Initialization>>(d.t)};
|
|
return init.has_value() && !isInitializerOldStyle(*init);
|
|
}};
|
|
static const auto hasSlashDelimitedInitializer{[](const EntityDecl &d) {
|
|
// Does a declaration have an old-style /x/ initializer?
|
|
const auto &init{std::get<std::optional<Initialization>>(d.t)};
|
|
return init.has_value() && isInitializerOldStyle(*init);
|
|
}};
|
|
const auto useDoubledColons{[&]() {
|
|
bool isRecord{std::holds_alternative<DeclarationTypeSpec::Record>(dts.u)};
|
|
if (!attrs.empty()) {
|
|
// Attributes after the type require :: before the entities.
|
|
CHECK(!isRecord);
|
|
return true;
|
|
}
|
|
if (std::any_of(decls.begin(), decls.end(), hasAssignmentInitializer)) {
|
|
// Always use :: with new style standard initializers (=x),
|
|
// since the standard requires them to appear (even in free form,
|
|
// where mandatory spaces already disambiguate INTEGER J=666).
|
|
CHECK(!isRecord);
|
|
return true;
|
|
}
|
|
if (isRecord) {
|
|
// Never put :: in a legacy extension RECORD// statement.
|
|
return false;
|
|
}
|
|
// The :: is optional for this declaration. Avoid usage that can
|
|
// crash the pgf90 compiler.
|
|
if (std::any_of(
|
|
decls.begin(), decls.end(), hasSlashDelimitedInitializer)) {
|
|
// Don't use :: when a declaration uses legacy DATA-statement-like
|
|
// /x/ initialization.
|
|
return false;
|
|
}
|
|
// Don't use :: with intrinsic types. Otherwise, use it.
|
|
return !std::holds_alternative<IntrinsicTypeSpec>(dts.u);
|
|
}};
|
|
|
|
if (useDoubledColons()) {
|
|
Put(" ::");
|
|
}
|
|
Put(' '), Walk(std::get<std::list<EntityDecl>>(x.t), ", ");
|
|
}
|
|
void Before(const AttrSpec &x) { // R802
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const CoarraySpec &y) { Word("CODIMENSION["); },
|
|
[&](const ArraySpec &y) { Word("DIMENSION("); },
|
|
[](const auto &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Post(const AttrSpec &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const CoarraySpec &y) { Put(']'); },
|
|
[&](const ArraySpec &y) { Put(')'); },
|
|
[](const auto &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const EntityDecl &x) { // R803
|
|
Walk(std::get<ObjectName>(x.t));
|
|
Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")");
|
|
Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]");
|
|
Walk("*", std::get<std::optional<CharLength>>(x.t));
|
|
Walk(std::get<std::optional<Initialization>>(x.t));
|
|
}
|
|
void Unparse(const NullInit &x) { // R806
|
|
Word("NULL()");
|
|
}
|
|
void Unparse(const LanguageBindingSpec &x) { // R808 & R1528
|
|
Word("BIND(C"), Walk(", NAME=", x.v), Put(')');
|
|
}
|
|
void Unparse(const CoarraySpec &x) { // R809
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const DeferredCoshapeSpecList &y) { Walk(y); },
|
|
[&](const ExplicitCoshapeSpec &y) { Walk(y); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const DeferredCoshapeSpecList &x) { // R810
|
|
for (auto j{x.v}; j > 0; --j) {
|
|
Put(':');
|
|
if (j > 1) {
|
|
Put(',');
|
|
}
|
|
}
|
|
}
|
|
void Unparse(const ExplicitCoshapeSpec &x) { // R811
|
|
Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ",");
|
|
Walk(std::get<std::optional<SpecificationExpr>>(x.t), ":"), Put('*');
|
|
}
|
|
void Unparse(const ExplicitShapeSpec &x) { // R812 - R813 & R816 - R818
|
|
Walk(std::get<std::optional<SpecificationExpr>>(x.t), ":");
|
|
Walk(std::get<SpecificationExpr>(x.t));
|
|
}
|
|
void Unparse(const ArraySpec &x) { // R815
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
|
|
[&](const std::list<AssumedShapeSpec> &y) { Walk(y, ","); },
|
|
[&](const DeferredShapeSpecList &y) { Walk(y); },
|
|
[&](const AssumedSizeSpec &y) { Walk(y); },
|
|
[&](const ImpliedShapeSpec &y) { Walk(y); },
|
|
[&](const AssumedRankSpec &y) { Walk(y); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Post(const AssumedShapeSpec &) { Put(':'); } // R819
|
|
void Unparse(const DeferredShapeSpecList &x) { // R820
|
|
for (auto j{x.v}; j > 0; --j) {
|
|
Put(':');
|
|
if (j > 1) {
|
|
Put(',');
|
|
}
|
|
}
|
|
}
|
|
void Unparse(const AssumedImpliedSpec &x) { // R821
|
|
Walk(x.v, ":");
|
|
Put('*');
|
|
}
|
|
void Unparse(const AssumedSizeSpec &x) { // R822
|
|
Walk(std::get<std::list<ExplicitShapeSpec>>(x.t), ",", ",");
|
|
Walk(std::get<AssumedImpliedSpec>(x.t));
|
|
}
|
|
void Unparse(const ImpliedShapeSpec &x) { // R823
|
|
Walk(x.v, ",");
|
|
}
|
|
void Post(const AssumedRankSpec &) { Put(".."); } // R825
|
|
void Post(const Asynchronous &) { Word("ASYNCHRONOUS"); }
|
|
void Post(const External &) { Word("EXTERNAL"); }
|
|
void Post(const Intrinsic &) { Word("INTRINSIC"); }
|
|
void Post(const Optional &) { Word("OPTIONAL"); }
|
|
void Post(const Parameter &) { Word("PARAMETER"); }
|
|
void Post(const Protected &) { Word("PROTECTED"); }
|
|
void Post(const Save &) { Word("SAVE"); }
|
|
void Post(const Target &) { Word("TARGET"); }
|
|
void Post(const Value &) { Word("VALUE"); }
|
|
void Post(const Volatile &) { Word("VOLATILE"); }
|
|
void Unparse(const IntentSpec &x) { // R826
|
|
Word("INTENT("), Walk(x.v), Put(")");
|
|
}
|
|
void Unparse(const AccessStmt &x) { // R827
|
|
Walk(std::get<AccessSpec>(x.t));
|
|
Walk(" :: ", std::get<std::list<AccessId>>(x.t), ", ");
|
|
}
|
|
void Unparse(const AllocatableStmt &x) { // R829
|
|
Word("ALLOCATABLE :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const ObjectDecl &x) { // R830 & R860
|
|
Walk(std::get<ObjectName>(x.t));
|
|
Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")");
|
|
Walk("[", std::get<std::optional<CoarraySpec>>(x.t), "]");
|
|
}
|
|
void Unparse(const AsynchronousStmt &x) { // R831
|
|
Word("ASYNCHRONOUS :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const BindStmt &x) { // R832
|
|
Walk(x.t, " :: ");
|
|
}
|
|
void Unparse(const BindEntity &x) { // R833
|
|
bool isCommon{std::get<BindEntity::Kind>(x.t) == BindEntity::Kind::Common};
|
|
const char *slash{isCommon ? "/" : ""};
|
|
Put(slash), Walk(std::get<Name>(x.t)), Put(slash);
|
|
}
|
|
void Unparse(const CodimensionStmt &x) { // R834
|
|
Word("CODIMENSION :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const CodimensionDecl &x) { // R835
|
|
Walk(std::get<Name>(x.t));
|
|
Put('['), Walk(std::get<CoarraySpec>(x.t)), Put(']');
|
|
}
|
|
void Unparse(const ContiguousStmt &x) { // R836
|
|
Word("CONTIGUOUS :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const DataStmt &x) { // R837
|
|
Word("DATA "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const DataStmtSet &x) { // R838
|
|
Walk(std::get<std::list<DataStmtObject>>(x.t), ", ");
|
|
Put('/'), Walk(std::get<std::list<DataStmtValue>>(x.t), ", "), Put('/');
|
|
}
|
|
void Unparse(const DataImpliedDo &x) { // R840, R842
|
|
Put('('), Walk(std::get<std::list<DataIDoObject>>(x.t), ", "), Put(',');
|
|
Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::");
|
|
Walk(std::get<LoopBounds<ScalarIntConstantExpr>>(x.t)), Put(')');
|
|
}
|
|
void Unparse(const DataStmtValue &x) { // R843
|
|
Walk(std::get<std::optional<DataStmtRepeat>>(x.t), "*");
|
|
Walk(std::get<DataStmtConstant>(x.t));
|
|
}
|
|
void Unparse(const DimensionStmt &x) { // R848
|
|
Word("DIMENSION :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const DimensionStmt::Declaration &x) {
|
|
Walk(std::get<Name>(x.t));
|
|
Put('('), Walk(std::get<ArraySpec>(x.t)), Put(')');
|
|
}
|
|
void Unparse(const IntentStmt &x) { // R849
|
|
Walk(x.t, " :: ");
|
|
}
|
|
void Unparse(const OptionalStmt &x) { // R850
|
|
Word("OPTIONAL :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const ParameterStmt &x) { // R851
|
|
Word("PARAMETER("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const NamedConstantDef &x) { // R852
|
|
Walk(x.t, "=");
|
|
}
|
|
void Unparse(const PointerStmt &x) { // R853
|
|
Word("POINTER :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const PointerDecl &x) { // R854
|
|
Walk(std::get<Name>(x.t));
|
|
Walk("(", std::get<std::optional<DeferredShapeSpecList>>(x.t), ")");
|
|
}
|
|
void Unparse(const ProtectedStmt &x) { // R855
|
|
Word("PROTECTED :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const SaveStmt &x) { // R856
|
|
Word("SAVE"), Walk(" :: ", x.v, ", ");
|
|
}
|
|
void Unparse(const SavedEntity &x) { // R857, R858
|
|
bool isCommon{
|
|
std::get<SavedEntity::Kind>(x.t) == SavedEntity::Kind::Common};
|
|
const char *slash{isCommon ? "/" : ""};
|
|
Put(slash), Walk(std::get<Name>(x.t)), Put(slash);
|
|
}
|
|
void Unparse(const TargetStmt &x) { // R859
|
|
Word("TARGET :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const ValueStmt &x) { // R861
|
|
Word("VALUE :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const VolatileStmt &x) { // R862
|
|
Word("VOLATILE :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const ImplicitStmt &x) { // R863
|
|
Word("IMPLICIT ");
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::list<ImplicitSpec> &y) { Walk(y, ", "); },
|
|
[&](const std::list<ImplicitStmt::ImplicitNoneNameSpec> &y) {
|
|
Word("NONE"), Walk(" (", y, ", ", ")");
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const ImplicitSpec &x) { // R864
|
|
Walk(std::get<DeclarationTypeSpec>(x.t));
|
|
Put('('), Walk(std::get<std::list<LetterSpec>>(x.t), ", "), Put(')');
|
|
}
|
|
void Unparse(const LetterSpec &x) { // R865
|
|
Put(*std::get<const char *>(x.t));
|
|
auto second{std::get<std::optional<const char *>>(x.t)};
|
|
if (second.has_value()) {
|
|
Put('-'), Put(**second);
|
|
}
|
|
}
|
|
void Unparse(const ImportStmt &x) { // R867
|
|
Word("IMPORT");
|
|
switch (x.kind) {
|
|
case common::ImportKind::Default: Walk(" :: ", x.names, ", "); break;
|
|
case common::ImportKind::Only:
|
|
Put(", "), Word("ONLY: ");
|
|
Walk(x.names, ", ");
|
|
break;
|
|
case common::ImportKind::None: Word(", NONE"); break;
|
|
case common::ImportKind::All: Word(", ALL"); break;
|
|
default: CRASH_NO_CASE;
|
|
}
|
|
}
|
|
void Unparse(const NamelistStmt &x) { // R868
|
|
Word("NAMELIST"), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const NamelistStmt::Group &x) {
|
|
Put('/'), Walk(std::get<Name>(x.t)), Put('/');
|
|
Walk(std::get<std::list<Name>>(x.t), ", ");
|
|
}
|
|
void Unparse(const EquivalenceStmt &x) { // R870, R871
|
|
Word("EQUIVALENCE");
|
|
const char *separator{" "};
|
|
for (const std::list<EquivalenceObject> &y : x.v) {
|
|
Put(separator), Put('('), Walk(y), Put(')');
|
|
separator = ", ";
|
|
}
|
|
}
|
|
void Unparse(const CommonStmt &x) { // R873
|
|
Word("COMMON ");
|
|
Walk(x.blocks);
|
|
}
|
|
void Unparse(const CommonBlockObject &x) { // R874
|
|
Walk(std::get<Name>(x.t));
|
|
Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")");
|
|
}
|
|
void Unparse(const CommonStmt::Block &x) {
|
|
Walk("/", std::get<std::optional<Name>>(x.t), "/");
|
|
Walk(std::get<std::list<CommonBlockObject>>(x.t));
|
|
}
|
|
|
|
void Unparse(const Substring &x) { // R908, R909
|
|
Walk(std::get<DataRef>(x.t));
|
|
Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')');
|
|
}
|
|
void Unparse(const CharLiteralConstantSubstring &x) {
|
|
Walk(std::get<CharLiteralConstant>(x.t));
|
|
Put('('), Walk(std::get<SubstringRange>(x.t)), Put(')');
|
|
}
|
|
void Unparse(const SubstringRange &x) { // R910
|
|
Walk(x.t, ":");
|
|
}
|
|
void Unparse(const PartRef &x) { // R912
|
|
Walk(x.name);
|
|
Walk("(", x.subscripts, ",", ")");
|
|
Walk(x.imageSelector);
|
|
}
|
|
void Unparse(const StructureComponent &x) { // R913
|
|
Walk(x.base);
|
|
if (structureComponents_.find(x.component.source) !=
|
|
structureComponents_.end()) {
|
|
Put('.');
|
|
} else {
|
|
Put('%');
|
|
}
|
|
Walk(x.component);
|
|
}
|
|
void Unparse(const ArrayElement &x) { // R917
|
|
Walk(x.base);
|
|
Put('('), Walk(x.subscripts, ","), Put(')');
|
|
}
|
|
void Unparse(const SubscriptTriplet &x) { // R921
|
|
Walk(std::get<0>(x.t)), Put(':'), Walk(std::get<1>(x.t));
|
|
Walk(":", std::get<2>(x.t));
|
|
}
|
|
void Unparse(const ImageSelector &x) { // R924
|
|
Put('['), Walk(std::get<std::list<Cosubscript>>(x.t), ",");
|
|
Walk(",", std::get<std::list<ImageSelectorSpec>>(x.t), ","), Put(']');
|
|
}
|
|
void Before(const ImageSelectorSpec::Stat &) { // R926
|
|
Word("STAT=");
|
|
}
|
|
void Before(const ImageSelectorSpec::Team &) { Word("TEAM="); }
|
|
void Before(const ImageSelectorSpec::Team_Number &) { Word("TEAM_NUMBER="); }
|
|
void Unparse(const AllocateStmt &x) { // R927
|
|
Word("ALLOCATE(");
|
|
Walk(std::get<std::optional<TypeSpec>>(x.t), "::");
|
|
Walk(std::get<std::list<Allocation>>(x.t), ", ");
|
|
Walk(", ", std::get<std::list<AllocOpt>>(x.t), ", "), Put(')');
|
|
}
|
|
void Before(const AllocOpt &x) { // R928, R931
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const AllocOpt::Mold &) { Word("MOLD="); },
|
|
[&](const AllocOpt::Source &) { Word("SOURCE="); },
|
|
[](const StatOrErrmsg &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const Allocation &x) { // R932
|
|
Walk(std::get<AllocateObject>(x.t));
|
|
Walk("(", std::get<std::list<AllocateShapeSpec>>(x.t), ",", ")");
|
|
Walk("[", std::get<std::optional<AllocateCoarraySpec>>(x.t), "]");
|
|
}
|
|
void Unparse(const AllocateShapeSpec &x) { // R934 & R938
|
|
Walk(std::get<std::optional<BoundExpr>>(x.t), ":");
|
|
Walk(std::get<BoundExpr>(x.t));
|
|
}
|
|
void Unparse(const AllocateCoarraySpec &x) { // R937
|
|
Walk(std::get<std::list<AllocateCoshapeSpec>>(x.t), ",", ",");
|
|
Walk(std::get<std::optional<BoundExpr>>(x.t), ":"), Put('*');
|
|
}
|
|
void Unparse(const NullifyStmt &x) { // R939
|
|
Word("NULLIFY("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const DeallocateStmt &x) { // R941
|
|
Word("DEALLOCATE(");
|
|
Walk(std::get<std::list<AllocateObject>>(x.t), ", ");
|
|
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
|
|
}
|
|
void Before(const StatOrErrmsg &x) { // R942 & R1165
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const StatVariable &) { Word("STAT="); },
|
|
[&](const MsgVariable &) { Word("ERRMSG="); },
|
|
},
|
|
x.u);
|
|
}
|
|
|
|
// R1001 - R1022
|
|
void Unparse(const Expr::Parentheses &x) { Put('('), Walk(x.v), Put(')'); }
|
|
void Before(const Expr::UnaryPlus &x) { Put("+"); }
|
|
void Before(const Expr::Negate &x) { Put("-"); }
|
|
void Before(const Expr::NOT &x) { Word(".NOT."); }
|
|
void Unparse(const Expr::PercentLoc &x) {
|
|
Word("%LOC("), Walk(x.v), Put(')');
|
|
}
|
|
void Unparse(const Expr::Power &x) { Walk(x.t, "**"); }
|
|
void Unparse(const Expr::Multiply &x) { Walk(x.t, "*"); }
|
|
void Unparse(const Expr::Divide &x) { Walk(x.t, "/"); }
|
|
void Unparse(const Expr::Add &x) { Walk(x.t, "+"); }
|
|
void Unparse(const Expr::Subtract &x) { Walk(x.t, "-"); }
|
|
void Unparse(const Expr::Concat &x) { Walk(x.t, "//"); }
|
|
void Unparse(const Expr::LT &x) { Walk(x.t, "<"); }
|
|
void Unparse(const Expr::LE &x) { Walk(x.t, "<="); }
|
|
void Unparse(const Expr::EQ &x) { Walk(x.t, "=="); }
|
|
void Unparse(const Expr::NE &x) { Walk(x.t, "/="); }
|
|
void Unparse(const Expr::GE &x) { Walk(x.t, ">="); }
|
|
void Unparse(const Expr::GT &x) { Walk(x.t, ">"); }
|
|
void Unparse(const Expr::AND &x) { Walk(x.t, ".AND."); }
|
|
void Unparse(const Expr::OR &x) { Walk(x.t, ".OR."); }
|
|
void Unparse(const Expr::EQV &x) { Walk(x.t, ".EQV."); }
|
|
void Unparse(const Expr::NEQV &x) { Walk(x.t, ".NEQV."); }
|
|
void Unparse(const Expr::XOR &x) { Walk(x.t, ".XOR."); }
|
|
void Unparse(const Expr::ComplexConstructor &x) {
|
|
Put('('), Walk(x.t, ","), Put(')');
|
|
}
|
|
void Unparse(const Expr::DefinedBinary &x) {
|
|
Walk(std::get<1>(x.t)); // left
|
|
Walk(std::get<DefinedOpName>(x.t));
|
|
Walk(std::get<2>(x.t)); // right
|
|
}
|
|
void Unparse(const DefinedOpName &x) { // R1003, R1023, R1414, & R1415
|
|
Walk(x.v);
|
|
}
|
|
void Unparse(const AssignmentStmt &x) { // R1032
|
|
Walk(x.t, " = ");
|
|
}
|
|
void Unparse(const PointerAssignmentStmt &x) { // R1033, R1034, R1038
|
|
Walk(std::get<DataRef>(x.t));
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::list<BoundsRemapping> &y) {
|
|
Put('('), Walk(y), Put(')');
|
|
},
|
|
[&](const std::list<BoundsSpec> &y) { Walk("(", y, ", ", ")"); },
|
|
},
|
|
std::get<PointerAssignmentStmt::Bounds>(x.t).u);
|
|
Put(" => "), Walk(std::get<Expr>(x.t));
|
|
}
|
|
void Post(const BoundsSpec &) { // R1035
|
|
Put(':');
|
|
}
|
|
void Unparse(const BoundsRemapping &x) { // R1036
|
|
Walk(x.t, ":");
|
|
}
|
|
void Unparse(const WhereStmt &x) { // R1041, R1045, R1046
|
|
Word("WHERE ("), Walk(x.t, ") ");
|
|
}
|
|
void Unparse(const WhereConstructStmt &x) { // R1043
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("WHERE ("), Walk(std::get<LogicalExpr>(x.t)), Put(')');
|
|
Indent();
|
|
}
|
|
void Unparse(const MaskedElsewhereStmt &x) { // R1047
|
|
Outdent();
|
|
Word("ELSEWHERE ("), Walk(std::get<LogicalExpr>(x.t)), Put(')');
|
|
Walk(" ", std::get<std::optional<Name>>(x.t));
|
|
Indent();
|
|
}
|
|
void Unparse(const ElsewhereStmt &x) { // R1048
|
|
Outdent(), Word("ELSEWHERE"), Walk(" ", x.v), Indent();
|
|
}
|
|
void Unparse(const EndWhereStmt &x) { // R1049
|
|
Outdent(), Word("END WHERE"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const ForallConstructStmt &x) { // R1051
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("FORALL"), Walk(std::get<common::Indirection<ConcurrentHeader>>(x.t));
|
|
Indent();
|
|
}
|
|
void Unparse(const EndForallStmt &x) { // R1054
|
|
Outdent(), Word("END FORALL"), Walk(" ", x.v);
|
|
}
|
|
void Before(const ForallStmt &) { // R1055
|
|
Word("FORALL");
|
|
}
|
|
|
|
void Unparse(const AssociateStmt &x) { // R1103
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("ASSOCIATE (");
|
|
Walk(std::get<std::list<Association>>(x.t), ", "), Put(')'), Indent();
|
|
}
|
|
void Unparse(const Association &x) { // R1104
|
|
Walk(x.t, " => ");
|
|
}
|
|
void Unparse(const EndAssociateStmt &x) { // R1106
|
|
Outdent(), Word("END ASSOCIATE"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const BlockStmt &x) { // R1108
|
|
Walk(x.v, ": "), Word("BLOCK"), Indent();
|
|
}
|
|
void Unparse(const EndBlockStmt &x) { // R1110
|
|
Outdent(), Word("END BLOCK"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const ChangeTeamStmt &x) { // R1112
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("CHANGE TEAM ("), Walk(std::get<TeamVariable>(x.t));
|
|
Walk(", ", std::get<std::list<CoarrayAssociation>>(x.t), ", ");
|
|
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
|
|
Indent();
|
|
}
|
|
void Unparse(const CoarrayAssociation &x) { // R1113
|
|
Walk(x.t, " => ");
|
|
}
|
|
void Unparse(const EndChangeTeamStmt &x) { // R1114
|
|
Outdent(), Word("END TEAM (");
|
|
Walk(std::get<std::list<StatOrErrmsg>>(x.t), ", ");
|
|
Put(')'), Walk(" ", std::get<std::optional<Name>>(x.t));
|
|
}
|
|
void Unparse(const CriticalStmt &x) { // R1117
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("CRITICAL ("), Walk(std::get<std::list<StatOrErrmsg>>(x.t), ", ");
|
|
Put(')'), Indent();
|
|
}
|
|
void Unparse(const EndCriticalStmt &x) { // R1118
|
|
Outdent(), Word("END CRITICAL"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const DoConstruct &x) { // R1119, R1120
|
|
Walk(std::get<Statement<NonLabelDoStmt>>(x.t));
|
|
Indent(), Walk(std::get<Block>(x.t), ""), Outdent();
|
|
Walk(std::get<Statement<EndDoStmt>>(x.t));
|
|
}
|
|
void Unparse(const LabelDoStmt &x) { // R1121
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("DO "), Walk(std::get<Label>(x.t));
|
|
Walk(" ", std::get<std::optional<LoopControl>>(x.t));
|
|
}
|
|
void Unparse(const NonLabelDoStmt &x) { // R1122
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("DO "), Walk(std::get<std::optional<LoopControl>>(x.t));
|
|
}
|
|
void Unparse(const LoopControl &x) { // R1123
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const ScalarLogicalExpr &y) {
|
|
Word("WHILE ("), Walk(y), Put(')');
|
|
},
|
|
[&](const auto &y) { Walk(y); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const ConcurrentHeader &x) { // R1125
|
|
Put('('), Walk(std::get<std::optional<IntegerTypeSpec>>(x.t), "::");
|
|
Walk(std::get<std::list<ConcurrentControl>>(x.t), ", ");
|
|
Walk(", ", std::get<std::optional<ScalarLogicalExpr>>(x.t)), Put(')');
|
|
}
|
|
void Unparse(const ConcurrentControl &x) { // R1126 - R1128
|
|
Walk(std::get<Name>(x.t)), Put('='), Walk(std::get<1>(x.t));
|
|
Put(':'), Walk(std::get<2>(x.t));
|
|
Walk(":", std::get<std::optional<ScalarIntExpr>>(x.t));
|
|
}
|
|
void Before(const LoopControl::Concurrent &x) { // R1129
|
|
Word("CONCURRENT");
|
|
}
|
|
void Unparse(const LocalitySpec::Local &x) {
|
|
Word("LOCAL("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const LocalitySpec::LocalInit &x) {
|
|
Word("LOCAL_INIT("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const LocalitySpec::Shared &x) {
|
|
Word("SHARED("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Post(const LocalitySpec::DefaultNone &x) { Word("DEFAULT(NONE)"); }
|
|
void Unparse(const EndDoStmt &x) { // R1132
|
|
Word("END DO"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const CycleStmt &x) { // R1133
|
|
Word("CYCLE"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const IfThenStmt &x) { // R1135
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("IF ("), Walk(std::get<ScalarLogicalExpr>(x.t));
|
|
Put(") "), Word("THEN"), Indent();
|
|
}
|
|
void Unparse(const ElseIfStmt &x) { // R1136
|
|
Outdent(), Word("ELSE IF (");
|
|
Walk(std::get<ScalarLogicalExpr>(x.t)), Put(") "), Word("THEN");
|
|
Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
|
|
}
|
|
void Unparse(const ElseStmt &x) { // R1137
|
|
Outdent(), Word("ELSE"), Walk(" ", x.v), Indent();
|
|
}
|
|
void Unparse(const EndIfStmt &x) { // R1138
|
|
Outdent(), Word("END IF"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const IfStmt &x) { // R1139
|
|
Word("IF ("), Walk(x.t, ") ");
|
|
}
|
|
void Unparse(const SelectCaseStmt &x) { // R1141, R1144
|
|
Walk(std::get<std::optional<Name>>(x.t), ": ");
|
|
Word("SELECT CASE (");
|
|
Walk(std::get<Scalar<Expr>>(x.t)), Put(')'), Indent();
|
|
}
|
|
void Unparse(const CaseStmt &x) { // R1142
|
|
Outdent(), Word("CASE "), Walk(std::get<CaseSelector>(x.t));
|
|
Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
|
|
}
|
|
void Unparse(const EndSelectStmt &x) { // R1143 & R1151 & R1155
|
|
Outdent(), Word("END SELECT"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const CaseSelector &x) { // R1145
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::list<CaseValueRange> &y) {
|
|
Put('('), Walk(y), Put(')');
|
|
},
|
|
[&](const Default &) { Word("DEFAULT"); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const CaseValueRange::Range &x) { // R1146
|
|
Walk(x.lower), Put(':'), Walk(x.upper);
|
|
}
|
|
void Unparse(const SelectRankStmt &x) { // R1149
|
|
Walk(std::get<0>(x.t), ": ");
|
|
Word("SELECT RANK ("), Walk(std::get<1>(x.t), " => ");
|
|
Walk(std::get<Selector>(x.t)), Put(')'), Indent();
|
|
}
|
|
void Unparse(const SelectRankCaseStmt &x) { // R1150
|
|
Outdent(), Word("RANK ");
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const ScalarIntConstantExpr &y) {
|
|
Put('('), Walk(y), Put(')');
|
|
},
|
|
[&](const Star &) { Put("(*)"); },
|
|
[&](const Default &) { Word("DEFAULT"); },
|
|
},
|
|
std::get<SelectRankCaseStmt::Rank>(x.t).u);
|
|
Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
|
|
}
|
|
void Unparse(const SelectTypeStmt &x) { // R1153
|
|
Walk(std::get<0>(x.t), ": ");
|
|
Word("SELECT TYPE ("), Walk(std::get<1>(x.t), " => ");
|
|
Walk(std::get<Selector>(x.t)), Put(')'), Indent();
|
|
}
|
|
void Unparse(const TypeGuardStmt &x) { // R1154
|
|
Outdent(), Walk(std::get<TypeGuardStmt::Guard>(x.t));
|
|
Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
|
|
}
|
|
void Unparse(const TypeGuardStmt::Guard &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const TypeSpec &y) { Word("TYPE IS ("), Walk(y), Put(')'); },
|
|
[&](const DerivedTypeSpec &y) {
|
|
Word("CLASS IS ("), Walk(y), Put(')');
|
|
},
|
|
[&](const Default &) { Word("CLASS DEFAULT"); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const ExitStmt &x) { // R1156
|
|
Word("EXIT"), Walk(" ", x.v);
|
|
}
|
|
void Before(const GotoStmt &x) { // R1157
|
|
Word("GO TO ");
|
|
}
|
|
void Unparse(const ComputedGotoStmt &x) { // R1158
|
|
Word("GO TO ("), Walk(x.t, "), ");
|
|
}
|
|
void Unparse(const ContinueStmt &x) { // R1159
|
|
Word("CONTINUE");
|
|
}
|
|
void Unparse(const StopStmt &x) { // R1160, R1161
|
|
if (std::get<StopStmt::Kind>(x.t) == StopStmt::Kind::ErrorStop) {
|
|
Word("ERROR ");
|
|
}
|
|
Word("STOP"), Walk(" ", std::get<std::optional<StopCode>>(x.t));
|
|
Walk(", QUIET=", std::get<std::optional<ScalarLogicalExpr>>(x.t));
|
|
}
|
|
void Unparse(const FailImageStmt &x) { // R1163
|
|
Word("FAIL IMAGE");
|
|
}
|
|
void Unparse(const SyncAllStmt &x) { // R1164
|
|
Word("SYNC ALL ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const SyncImagesStmt &x) { // R1166
|
|
Word("SYNC IMAGES (");
|
|
Walk(std::get<SyncImagesStmt::ImageSet>(x.t));
|
|
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
|
|
}
|
|
void Unparse(const SyncMemoryStmt &x) { // R1168
|
|
Word("SYNC MEMORY ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const SyncTeamStmt &x) { // R1169
|
|
Word("SYNC TEAM ("), Walk(std::get<TeamVariable>(x.t));
|
|
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
|
|
}
|
|
void Unparse(const EventPostStmt &x) { // R1170
|
|
Word("EVENT POST ("), Walk(std::get<EventVariable>(x.t));
|
|
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
|
|
}
|
|
void Before(const EventWaitStmt::EventWaitSpec &x) { // R1173, R1174
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const ScalarIntExpr &x) { Word("UNTIL_COUNT="); },
|
|
[](const StatOrErrmsg &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const EventWaitStmt &x) { // R1170
|
|
Word("EVENT WAIT ("), Walk(std::get<EventVariable>(x.t));
|
|
Walk(", ", std::get<std::list<EventWaitStmt::EventWaitSpec>>(x.t), ", ");
|
|
Put(')');
|
|
}
|
|
void Unparse(const FormTeamStmt &x) { // R1175
|
|
Word("FORM TEAM ("), Walk(std::get<ScalarIntExpr>(x.t));
|
|
Put(','), Walk(std::get<TeamVariable>(x.t));
|
|
Walk(", ", std::get<std::list<FormTeamStmt::FormTeamSpec>>(x.t), ", ");
|
|
Put(')');
|
|
}
|
|
void Before(const FormTeamStmt::FormTeamSpec &x) { // R1176, R1177
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const ScalarIntExpr &x) { Word("NEW_INDEX="); },
|
|
[](const StatOrErrmsg &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const LockStmt &x) { // R1178
|
|
Word("LOCK ("), Walk(std::get<LockVariable>(x.t));
|
|
Walk(", ", std::get<std::list<LockStmt::LockStat>>(x.t), ", ");
|
|
Put(')');
|
|
}
|
|
void Before(const LockStmt::LockStat &x) { // R1179
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const ScalarLogicalVariable &) { Word("ACQUIRED_LOCK="); },
|
|
[](const StatOrErrmsg &y) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const UnlockStmt &x) { // R1180
|
|
Word("UNLOCK ("), Walk(std::get<LockVariable>(x.t));
|
|
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", ");
|
|
Put(')');
|
|
}
|
|
|
|
void Unparse(const OpenStmt &x) { // R1204
|
|
Word("OPEN ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
bool Pre(const ConnectSpec &x) { // R1205
|
|
return std::visit(
|
|
common::visitors{
|
|
[&](const FileUnitNumber &) {
|
|
Word("UNIT=");
|
|
return true;
|
|
},
|
|
[&](const FileNameExpr &) {
|
|
Word("FILE=");
|
|
return true;
|
|
},
|
|
[&](const ConnectSpec::CharExpr &y) {
|
|
Walk(y.t, "=");
|
|
return false;
|
|
},
|
|
[&](const MsgVariable &) {
|
|
Word("IOMSG=");
|
|
return true;
|
|
},
|
|
[&](const StatVariable &) {
|
|
Word("IOSTAT=");
|
|
return true;
|
|
},
|
|
[&](const ConnectSpec::Recl &) {
|
|
Word("RECL=");
|
|
return true;
|
|
},
|
|
[&](const ConnectSpec::Newunit &) {
|
|
Word("NEWUNIT=");
|
|
return true;
|
|
},
|
|
[&](const ErrLabel &) {
|
|
Word("ERR=");
|
|
return true;
|
|
},
|
|
[&](const StatusExpr &) {
|
|
Word("STATUS=");
|
|
return true;
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const CloseStmt &x) { // R1208
|
|
Word("CLOSE ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Before(const CloseStmt::CloseSpec &x) { // R1209
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const FileUnitNumber &) { Word("UNIT="); },
|
|
[&](const StatVariable &) { Word("IOSTAT="); },
|
|
[&](const MsgVariable &) { Word("IOMSG="); },
|
|
[&](const ErrLabel &) { Word("ERR="); },
|
|
[&](const StatusExpr &) { Word("STATUS="); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const ReadStmt &x) { // R1210
|
|
Word("READ ");
|
|
if (x.iounit) {
|
|
Put('('), Walk(x.iounit);
|
|
if (x.format) {
|
|
Put(", "), Walk(x.format);
|
|
}
|
|
Walk(", ", x.controls, ", ");
|
|
Put(')');
|
|
} else if (x.format) {
|
|
Walk(x.format);
|
|
if (!x.items.empty()) {
|
|
Put(", ");
|
|
}
|
|
} else {
|
|
Put('('), Walk(x.controls, ", "), Put(')');
|
|
}
|
|
Walk(" ", x.items, ", ");
|
|
}
|
|
void Unparse(const WriteStmt &x) { // R1211
|
|
Word("WRITE (");
|
|
if (x.iounit) {
|
|
Walk(x.iounit);
|
|
if (x.format) {
|
|
Put(", "), Walk(x.format);
|
|
}
|
|
Walk(", ", x.controls, ", ");
|
|
} else {
|
|
Walk(x.controls, ", ");
|
|
}
|
|
Put(')'), Walk(" ", x.items, ", ");
|
|
}
|
|
void Unparse(const PrintStmt &x) { // R1212
|
|
Word("PRINT "), Walk(std::get<Format>(x.t));
|
|
Walk(", ", std::get<std::list<OutputItem>>(x.t), ", ");
|
|
}
|
|
bool Pre(const IoControlSpec &x) { // R1213
|
|
return std::visit(
|
|
common::visitors{
|
|
[&](const IoUnit &) {
|
|
Word("UNIT=");
|
|
return true;
|
|
},
|
|
[&](const Format &) {
|
|
Word("FMT=");
|
|
return true;
|
|
},
|
|
[&](const Name &) {
|
|
Word("NML=");
|
|
return true;
|
|
},
|
|
[&](const IoControlSpec::CharExpr &y) {
|
|
Walk(y.t, "=");
|
|
return false;
|
|
},
|
|
[&](const IoControlSpec::Asynchronous &) {
|
|
Word("ASYNCHRONOUS=");
|
|
return true;
|
|
},
|
|
[&](const EndLabel &) {
|
|
Word("END=");
|
|
return true;
|
|
},
|
|
[&](const EorLabel &) {
|
|
Word("EOR=");
|
|
return true;
|
|
},
|
|
[&](const ErrLabel &) {
|
|
Word("ERR=");
|
|
return true;
|
|
},
|
|
[&](const IdVariable &) {
|
|
Word("ID=");
|
|
return true;
|
|
},
|
|
[&](const MsgVariable &) {
|
|
Word("IOMSG=");
|
|
return true;
|
|
},
|
|
[&](const StatVariable &) {
|
|
Word("IOSTAT=");
|
|
return true;
|
|
},
|
|
[&](const IoControlSpec::Pos &) {
|
|
Word("POS=");
|
|
return true;
|
|
},
|
|
[&](const IoControlSpec::Rec &) {
|
|
Word("REC=");
|
|
return true;
|
|
},
|
|
[&](const IoControlSpec::Size &) {
|
|
Word("SIZE=");
|
|
return true;
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const InputImpliedDo &x) { // R1218
|
|
Put('('), Walk(std::get<std::list<InputItem>>(x.t), ", "), Put(", ");
|
|
Walk(std::get<IoImpliedDoControl>(x.t)), Put(')');
|
|
}
|
|
void Unparse(const OutputImpliedDo &x) { // R1219
|
|
Put('('), Walk(std::get<std::list<OutputItem>>(x.t), ", "), Put(", ");
|
|
Walk(std::get<IoImpliedDoControl>(x.t)), Put(')');
|
|
}
|
|
void Unparse(const WaitStmt &x) { // R1222
|
|
Word("WAIT ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Before(const WaitSpec &x) { // R1223
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const FileUnitNumber &) { Word("UNIT="); },
|
|
[&](const EndLabel &) { Word("END="); },
|
|
[&](const EorLabel &) { Word("EOR="); },
|
|
[&](const ErrLabel &) { Word("ERR="); },
|
|
[&](const IdExpr &) { Word("ID="); },
|
|
[&](const MsgVariable &) { Word("IOMSG="); },
|
|
[&](const StatVariable &) { Word("IOSTAT="); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const BackspaceStmt &x) { // R1224
|
|
Word("BACKSPACE ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const EndfileStmt &x) { // R1225
|
|
Word("ENDFILE ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const RewindStmt &x) { // R1226
|
|
Word("REWIND ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Before(const PositionOrFlushSpec &x) { // R1227 & R1229
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const FileUnitNumber &) { Word("UNIT="); },
|
|
[&](const MsgVariable &) { Word("IOMSG="); },
|
|
[&](const StatVariable &) { Word("IOSTAT="); },
|
|
[&](const ErrLabel &) { Word("ERR="); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const FlushStmt &x) { // R1228
|
|
Word("FLUSH ("), Walk(x.v, ", "), Put(')');
|
|
}
|
|
void Unparse(const InquireStmt &x) { // R1230
|
|
Word("INQUIRE (");
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const InquireStmt::Iolength &y) {
|
|
Word("IOLENGTH="), Walk(y.t, ") ");
|
|
},
|
|
[&](const std::list<InquireSpec> &y) { Walk(y, ", "), Put(')'); },
|
|
},
|
|
x.u);
|
|
}
|
|
bool Pre(const InquireSpec &x) { // R1231
|
|
return std::visit(
|
|
common::visitors{
|
|
[&](const FileUnitNumber &) {
|
|
Word("UNIT=");
|
|
return true;
|
|
},
|
|
[&](const FileNameExpr &) {
|
|
Word("FILE=");
|
|
return true;
|
|
},
|
|
[&](const InquireSpec::CharVar &y) {
|
|
Walk(y.t, "=");
|
|
return false;
|
|
},
|
|
[&](const InquireSpec::IntVar &y) {
|
|
Walk(y.t, "=");
|
|
return false;
|
|
},
|
|
[&](const InquireSpec::LogVar &y) {
|
|
Walk(y.t, "=");
|
|
return false;
|
|
},
|
|
[&](const IdExpr &) {
|
|
Word("ID=");
|
|
return true;
|
|
},
|
|
[&](const ErrLabel &) {
|
|
Word("ERR=");
|
|
return true;
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
|
|
void Before(const FormatStmt &) { // R1301
|
|
Word("FORMAT");
|
|
}
|
|
void Unparse(const format::FormatSpecification &x) { // R1302, R1303, R1305
|
|
Put('('), Walk("", x.items, ",", x.unlimitedItems.empty() ? "" : ",");
|
|
Walk("*(", x.unlimitedItems, ",", ")"), Put(')');
|
|
}
|
|
void Unparse(const format::FormatItem &x) { // R1304, R1306, R1321
|
|
if (x.repeatCount.has_value()) {
|
|
Walk(*x.repeatCount);
|
|
}
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::string &y) {
|
|
Put(QuoteCharacterLiteral(y, true, backslashEscapes_));
|
|
},
|
|
[&](const std::list<format::FormatItem> &y) {
|
|
Walk("(", y, ",", ")");
|
|
},
|
|
[&](const auto &y) { Walk(y); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(
|
|
const format::IntrinsicTypeDataEditDesc &x) { // R1307(1/2) - R1311
|
|
switch (x.kind) {
|
|
#define FMT(x) \
|
|
case format::IntrinsicTypeDataEditDesc::Kind::x: Put(#x); break
|
|
FMT(I);
|
|
FMT(B);
|
|
FMT(O);
|
|
FMT(Z);
|
|
FMT(F);
|
|
FMT(E);
|
|
FMT(EN);
|
|
FMT(ES);
|
|
FMT(EX);
|
|
FMT(G);
|
|
FMT(L);
|
|
FMT(A);
|
|
FMT(D);
|
|
#undef FMT
|
|
default: CRASH_NO_CASE;
|
|
}
|
|
Walk(x.width), Walk(".", x.digits), Walk("E", x.exponentWidth);
|
|
}
|
|
void Unparse(const format::DerivedTypeDataEditDesc &x) { // R1307(2/2), R1312
|
|
Word("DT");
|
|
if (!x.type.empty()) {
|
|
Put('"'), Put(x.type), Put('"');
|
|
}
|
|
Walk("(", x.parameters, ",", ")");
|
|
}
|
|
void Unparse(const format::ControlEditDesc &x) { // R1313, R1315-R1320
|
|
switch (x.kind) {
|
|
case format::ControlEditDesc::Kind::T:
|
|
Word("T");
|
|
Walk(x.count);
|
|
break;
|
|
case format::ControlEditDesc::Kind::TL:
|
|
Word("TL");
|
|
Walk(x.count);
|
|
break;
|
|
case format::ControlEditDesc::Kind::TR:
|
|
Word("TR");
|
|
Walk(x.count);
|
|
break;
|
|
case format::ControlEditDesc::Kind::X:
|
|
if (x.count != 1) {
|
|
Walk(x.count);
|
|
}
|
|
Word("X");
|
|
break;
|
|
case format::ControlEditDesc::Kind::Slash:
|
|
if (x.count != 1) {
|
|
Walk(x.count);
|
|
}
|
|
Put('/');
|
|
break;
|
|
case format::ControlEditDesc::Kind::Colon: Put(':'); break;
|
|
case format::ControlEditDesc::Kind::P:
|
|
Walk(x.count);
|
|
Word("P");
|
|
break;
|
|
#define FMT(x) \
|
|
case format::ControlEditDesc::Kind::x: Put(#x); break
|
|
FMT(SS);
|
|
FMT(SP);
|
|
FMT(S);
|
|
FMT(BN);
|
|
FMT(BZ);
|
|
FMT(RU);
|
|
FMT(RD);
|
|
FMT(RZ);
|
|
FMT(RN);
|
|
FMT(RC);
|
|
FMT(RP);
|
|
FMT(DC);
|
|
FMT(DP);
|
|
#undef FMT
|
|
default: CRASH_NO_CASE;
|
|
}
|
|
}
|
|
|
|
void Before(const MainProgram &x) { // R1401
|
|
if (!std::get<std::optional<Statement<ProgramStmt>>>(x.t)) {
|
|
Indent();
|
|
}
|
|
}
|
|
void Before(const ProgramStmt &x) { // R1402
|
|
Word("PROGRAM "), Indent();
|
|
}
|
|
void Unparse(const EndProgramStmt &x) { // R1403
|
|
EndSubprogram("PROGRAM", x.v);
|
|
}
|
|
void Before(const ModuleStmt &) { // R1405
|
|
Word("MODULE "), Indent();
|
|
}
|
|
void Unparse(const EndModuleStmt &x) { // R1406
|
|
EndSubprogram("MODULE", x.v);
|
|
}
|
|
void Unparse(const UseStmt &x) { // R1409
|
|
Word("USE"), Walk(", ", x.nature), Put(" :: "), Walk(x.moduleName);
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::list<Rename> &y) { Walk(", ", y, ", "); },
|
|
[&](const std::list<Only> &y) { Walk(", ONLY: ", y, ", "); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const Rename &x) { // R1411
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const Rename::Names &y) { Walk(y.t, " => "); },
|
|
[&](const Rename::Operators &y) {
|
|
Word("OPERATOR("), Walk(y.t, ") => OPERATOR("), Put(")");
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const SubmoduleStmt &x) { // R1417
|
|
Word("SUBMODULE ("), WalkTupleElements(x.t, ")"), Indent();
|
|
}
|
|
void Unparse(const ParentIdentifier &x) { // R1418
|
|
Walk(std::get<Name>(x.t)), Walk(":", std::get<std::optional<Name>>(x.t));
|
|
}
|
|
void Unparse(const EndSubmoduleStmt &x) { // R1419
|
|
EndSubprogram("SUBMODULE", x.v);
|
|
}
|
|
void Unparse(const BlockDataStmt &x) { // R1421
|
|
Word("BLOCK DATA"), Walk(" ", x.v), Indent();
|
|
}
|
|
void Unparse(const EndBlockDataStmt &x) { // R1422
|
|
EndSubprogram("BLOCK DATA", x.v);
|
|
}
|
|
|
|
void Unparse(const InterfaceStmt &x) { // R1503
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::optional<GenericSpec> &y) {
|
|
Word("INTERFACE"), Walk(" ", y);
|
|
},
|
|
[&](const Abstract &) { Word("ABSTRACT INTERFACE"); },
|
|
},
|
|
x.u);
|
|
Indent();
|
|
}
|
|
void Unparse(const EndInterfaceStmt &x) { // R1504
|
|
Outdent(), Word("END INTERFACE"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const ProcedureStmt &x) { // R1506
|
|
if (std::get<ProcedureStmt::Kind>(x.t) ==
|
|
ProcedureStmt::Kind::ModuleProcedure) {
|
|
Word("MODULE ");
|
|
}
|
|
Word("PROCEDURE :: ");
|
|
Walk(std::get<std::list<Name>>(x.t), ", ");
|
|
}
|
|
void Before(const GenericSpec &x) { // R1508, R1509
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const DefinedOperator &x) { Word("OPERATOR("); },
|
|
[&](const GenericSpec::Assignment &) { Word("ASSIGNMENT(=)"); },
|
|
[&](const GenericSpec::ReadFormatted &) {
|
|
Word("READ(FORMATTED)");
|
|
},
|
|
[&](const GenericSpec::ReadUnformatted &) {
|
|
Word("READ(UNFORMATTED)");
|
|
},
|
|
[&](const GenericSpec::WriteFormatted &) {
|
|
Word("WRITE(FORMATTED)");
|
|
},
|
|
[&](const GenericSpec::WriteUnformatted &) {
|
|
Word("WRITE(UNFORMATTED)");
|
|
},
|
|
[](const auto &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Post(const GenericSpec &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const DefinedOperator &x) { Put(')'); },
|
|
[](const auto &) {},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const GenericStmt &x) { // R1510
|
|
Word("GENERIC"), Walk(", ", std::get<std::optional<AccessSpec>>(x.t));
|
|
Put(" :: "), Walk(std::get<GenericSpec>(x.t)), Put(" => ");
|
|
Walk(std::get<std::list<Name>>(x.t), ", ");
|
|
}
|
|
void Unparse(const ExternalStmt &x) { // R1511
|
|
Word("EXTERNAL :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const ProcedureDeclarationStmt &x) { // R1512
|
|
Word("PROCEDURE ("), Walk(std::get<std::optional<ProcInterface>>(x.t));
|
|
Put(')'), Walk(", ", std::get<std::list<ProcAttrSpec>>(x.t), ", ");
|
|
Put(" :: "), Walk(std::get<std::list<ProcDecl>>(x.t), ", ");
|
|
}
|
|
void Unparse(const ProcInterface &x) { // R1513
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const DeclarationTypeSpec &d) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const IntrinsicTypeSpec &t) {
|
|
// Emit TYPE(REAL) to ensure no conflict with a symbol
|
|
// REAL
|
|
Word("TYPE("), Walk(t), Word(")");
|
|
},
|
|
[&](const auto &t) { Walk(t); },
|
|
},
|
|
d.u);
|
|
},
|
|
[&](const Name &n) { Walk(n); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const ProcDecl &x) { // R1515
|
|
Walk(std::get<Name>(x.t));
|
|
Walk(" => ", std::get<std::optional<ProcPointerInit>>(x.t));
|
|
}
|
|
void Unparse(const IntrinsicStmt &x) { // R1519
|
|
Word("INTRINSIC :: "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const FunctionReference &x) { // R1520
|
|
Walk(std::get<ProcedureDesignator>(x.v.t));
|
|
Put('('), Walk(std::get<std::list<ActualArgSpec>>(x.v.t), ", "), Put(')');
|
|
}
|
|
void Unparse(const CallStmt &x) { // R1521
|
|
const auto &pd{std::get<ProcedureDesignator>(x.v.t)};
|
|
const auto &args{std::get<std::list<ActualArgSpec>>(x.v.t)};
|
|
Word("CALL "), Walk(pd);
|
|
if (args.empty()) {
|
|
if (std::holds_alternative<ProcComponentRef>(pd.u)) {
|
|
Put("()"); // pgf90 crashes on CALL to tbp without parentheses
|
|
}
|
|
} else {
|
|
Walk("(", args, ", ", ")");
|
|
}
|
|
}
|
|
void Unparse(const ActualArgSpec &x) { // R1523
|
|
Walk(std::get<std::optional<Keyword>>(x.t), "=");
|
|
Walk(std::get<ActualArg>(x.t));
|
|
}
|
|
void Unparse(const ActualArg::PercentRef &x) { // R1524
|
|
Word("%REF("), Walk(x.v), Put(')');
|
|
}
|
|
void Unparse(const ActualArg::PercentVal &x) {
|
|
Word("%VAL("), Walk(x.v), Put(')');
|
|
}
|
|
void Before(const AltReturnSpec &) { // R1525
|
|
Put('*');
|
|
}
|
|
void Post(const PrefixSpec::Elemental) { Word("ELEMENTAL"); } // R1527
|
|
void Post(const PrefixSpec::Impure) { Word("IMPURE"); }
|
|
void Post(const PrefixSpec::Module) { Word("MODULE"); }
|
|
void Post(const PrefixSpec::Non_Recursive) { Word("NON_RECURSIVE"); }
|
|
void Post(const PrefixSpec::Pure) { Word("PURE"); }
|
|
void Post(const PrefixSpec::Recursive) { Word("RECURSIVE"); }
|
|
void Unparse(const FunctionStmt &x) { // R1530
|
|
Walk("", std::get<std::list<PrefixSpec>>(x.t), " ", " ");
|
|
Word("FUNCTION "), Walk(std::get<Name>(x.t)), Put("(");
|
|
Walk(std::get<std::list<Name>>(x.t), ", "), Put(')');
|
|
Walk(" ", std::get<std::optional<Suffix>>(x.t)), Indent();
|
|
}
|
|
void Unparse(const Suffix &x) { // R1532
|
|
if (x.resultName) {
|
|
Word("RESULT("), Walk(x.resultName), Put(')');
|
|
Walk(" ", x.binding);
|
|
} else {
|
|
Walk(x.binding);
|
|
}
|
|
}
|
|
void Unparse(const EndFunctionStmt &x) { // R1533
|
|
EndSubprogram("FUNCTION", x.v);
|
|
}
|
|
void Unparse(const SubroutineStmt &x) { // R1535
|
|
Walk("", std::get<std::list<PrefixSpec>>(x.t), " ", " ");
|
|
Word("SUBROUTINE "), Walk(std::get<Name>(x.t));
|
|
const auto &args{std::get<std::list<DummyArg>>(x.t)};
|
|
const auto &bind{std::get<std::optional<LanguageBindingSpec>>(x.t)};
|
|
if (args.empty()) {
|
|
Walk(" () ", bind);
|
|
} else {
|
|
Walk(" (", args, ", ", ")");
|
|
Walk(" ", bind);
|
|
}
|
|
Indent();
|
|
}
|
|
void Unparse(const EndSubroutineStmt &x) { // R1537
|
|
EndSubprogram("SUBROUTINE", x.v);
|
|
}
|
|
void Before(const MpSubprogramStmt &) { // R1539
|
|
Word("MODULE PROCEDURE "), Indent();
|
|
}
|
|
void Unparse(const EndMpSubprogramStmt &x) { // R1540
|
|
EndSubprogram("PROCEDURE", x.v);
|
|
}
|
|
void Unparse(const EntryStmt &x) { // R1541
|
|
Word("ENTRY "), Walk(std::get<Name>(x.t)), Put("(");
|
|
Walk(std::get<std::list<DummyArg>>(x.t), ", "), Put(")");
|
|
Walk(" ", std::get<std::optional<Suffix>>(x.t));
|
|
}
|
|
void Unparse(const ReturnStmt &x) { // R1542
|
|
Word("RETURN"), Walk(" ", x.v);
|
|
}
|
|
void Unparse(const ContainsStmt &x) { // R1543
|
|
Outdent();
|
|
Word("CONTAINS");
|
|
Indent();
|
|
}
|
|
void Unparse(const StmtFunctionStmt &x) { // R1544
|
|
Walk(std::get<Name>(x.t)), Put('(');
|
|
Walk(std::get<std::list<Name>>(x.t), ", "), Put(") = ");
|
|
Walk(std::get<Scalar<Expr>>(x.t));
|
|
}
|
|
|
|
// Directives, extensions, and deprecated constructs
|
|
void Unparse(const CompilerDirective &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const std::list<CompilerDirective::IgnoreTKR> &tkr) {
|
|
Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty
|
|
Walk(" ", tkr, ", ");
|
|
},
|
|
[&](const std::list<Name> &names) { Walk("!DIR$ ", names, " "); },
|
|
},
|
|
x.u);
|
|
Put('\n');
|
|
}
|
|
void Unparse(const CompilerDirective::IgnoreTKR &x) {
|
|
const auto &list{std::get<std::list<const char *>>(x.t)};
|
|
if (!list.empty()) {
|
|
Put("(");
|
|
for (const char *tkr : list) {
|
|
Put(*tkr);
|
|
}
|
|
Put(") ");
|
|
}
|
|
Walk(std::get<Name>(x.t));
|
|
}
|
|
// OpenMP Clauses & Directives
|
|
void Unparse(const OmpObject &x) {
|
|
bool isCommon{std::get<OmpObject::Kind>(x.t) == OmpObject::Kind::Common};
|
|
const char *slash{isCommon ? "/" : ""};
|
|
Put(slash), Walk(std::get<Designator>(x.t)), Put(slash);
|
|
}
|
|
void Unparse(const OmpMapType::Always &x) { Word("ALWAYS,"); }
|
|
void Unparse(const OmpMapClause &x) {
|
|
Word("MAP(");
|
|
Walk(std::get<std::optional<OmpMapType>>(x.t), ":");
|
|
Walk(std::get<OmpObjectList>(x.t));
|
|
Put(") ");
|
|
}
|
|
void Unparse(const OmpScheduleModifier &x) {
|
|
Walk(std::get<OmpScheduleModifier::Modifier1>(x.t));
|
|
Walk(",", std::get<std::optional<OmpScheduleModifier::Modifier2>>(x.t));
|
|
}
|
|
void Unparse(const OmpScheduleClause &x) {
|
|
Word("SCHEDULE(");
|
|
Walk(std::get<std::optional<OmpScheduleModifier>>(x.t));
|
|
Walk(std::get<OmpScheduleClause::ScheduleType>(x.t));
|
|
Walk(",", std::get<std::optional<ScalarIntExpr>>(x.t));
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpAlignedClause &x) {
|
|
Word("ALIGNED("), Walk(std::get<std::list<Name>>(x.t), ",");
|
|
Walk(std::get<std::optional<ScalarIntConstantExpr>>(x.t));
|
|
Put(") ");
|
|
}
|
|
void Unparse(const OmpIfClause &x) {
|
|
Word("IF("),
|
|
Walk(std::get<std::optional<OmpIfClause::DirectiveNameModifier>>(x.t),
|
|
":");
|
|
Walk(std::get<ScalarLogicalExpr>(x.t));
|
|
Put(") ");
|
|
}
|
|
void Unparse(const OmpLinearClause::WithoutModifier &x) {
|
|
Word("LINEAR("), Walk(x.names, ", ");
|
|
Walk(":", x.step);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpLinearClause::WithModifier &x) {
|
|
Word("LINEAR("), Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")");
|
|
Walk(":", x.step);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpReductionClause &x) {
|
|
Word("REDUCTION(");
|
|
Walk(std::get<OmpReductionOperator>(x.t));
|
|
Put(":");
|
|
Walk(std::get<std::list<Designator>>(x.t), ",");
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpDependSinkVecLength &x) {
|
|
Walk(std::get<common::Indirection<DefinedOperator>>(x.t));
|
|
Walk(std::get<ScalarIntConstantExpr>(x.t));
|
|
}
|
|
void Unparse(const OmpDependSinkVec &x) {
|
|
Walk(std::get<Name>(x.t));
|
|
Walk(std::get<std::optional<OmpDependSinkVecLength>>(x.t));
|
|
}
|
|
void Unparse(const OmpDependClause::InOut &x) {
|
|
Put("(");
|
|
Walk(std::get<OmpDependenceType>(x.t));
|
|
Put(":");
|
|
Walk(std::get<std::list<Designator>>(x.t), ",");
|
|
Put(")");
|
|
}
|
|
bool Pre(const OmpDependClause &x) {
|
|
return std::visit(
|
|
common::visitors{
|
|
[&](const OmpDependClause::Source &y) {
|
|
Word("DEPEND(SOURCE)");
|
|
return false;
|
|
},
|
|
[&](const OmpDependClause::Sink &y) {
|
|
Word("DEPEND(SINK:");
|
|
Walk(y.v);
|
|
Put(")");
|
|
return false;
|
|
},
|
|
[&](const OmpDependClause::InOut &y) {
|
|
Word("DEPEND");
|
|
return true;
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
bool Pre(const OmpDefaultClause &x) {
|
|
Word("DEFAULT(");
|
|
return true;
|
|
}
|
|
void Post(const OmpDefaultClause &x) { Put(")"); }
|
|
bool Pre(const OmpProcBindClause &x) {
|
|
Word("PROC_BIND(");
|
|
return true;
|
|
}
|
|
void Post(const OmpProcBindClause &x) { Put(")"); }
|
|
void Before(const OmpClause::Defaultmap &x) {
|
|
Word("DEFAULTMAP(TOFROM:SCALAR)");
|
|
}
|
|
void Before(const OmpClause::Inbranch &x) { Word("INBRANCH"); }
|
|
void Before(const OmpClause::Mergeable &x) { Word("MERGEABLE"); }
|
|
void Before(const OmpClause::Nogroup &x) { Word("NOGROUP"); }
|
|
void Before(const OmpClause::Notinbranch &x) { Word("NOTINBRANCH"); }
|
|
void Before(const OmpClause::Untied &x) { Word("UNTIED"); }
|
|
void Unparse(const OmpNowait &) { Word("NOWAIT"); }
|
|
void Unparse(const OmpClause::Collapse &x) {
|
|
Word("COLLAPSE(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Copyin &x) {
|
|
Word("COPYIN(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Copyprivate &x) {
|
|
Word("COPYPRIVATE(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Device &x) {
|
|
Word("DEVICE(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::DistSchedule &x) {
|
|
Word("DIST_SCHEDULE(STATIC,");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Final &x) {
|
|
Word("FINAL(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Firstprivate &x) {
|
|
Word("FIRSTPRIVATE(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::From &x) {
|
|
Word("FROM(");
|
|
Walk(x.v, ",");
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Grainsize &x) {
|
|
Word("GRAINSIZE(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Lastprivate &x) {
|
|
Word("LASTPRIVATE(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::NumTasks &x) {
|
|
Word("NUM_TASKS(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::NumTeams &x) {
|
|
Word("NUM_TEAMS(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::NumThreads &x) {
|
|
Word("NUM_THREADS(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Ordered &x) {
|
|
Word("ORDERED");
|
|
Walk("(", x.v, ")");
|
|
}
|
|
void Unparse(const OmpClause::Priority &x) {
|
|
Word("PRIORITY(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Private &x) {
|
|
Word("PRIVATE(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Safelen &x) {
|
|
Word("SAFELEN(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Simdlen &x) {
|
|
Word("SIMDLEN(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::ThreadLimit &x) {
|
|
Word("THREADLIMIT(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Shared &x) {
|
|
Word("SHARED(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::To &x) {
|
|
Word("TO(");
|
|
Walk(x.v, ",");
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::Uniform &x) {
|
|
Word("UNIFORM(");
|
|
Walk(x.v, ",");
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpClause::UseDevicePtr &x) {
|
|
Word("USE_DEVICE_PTR(");
|
|
Walk(x.v, ",");
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpLoopDirective &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const OmpLoopDirective::DistributeParallelDoSimd &) {
|
|
Word("DISTRIBUTE PARALLEL DO SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::DistributeParallelDo &) {
|
|
Word("DISTRIBUTE PARALLEL DO ");
|
|
},
|
|
[&](const OmpLoopDirective::DistributeSimd &) {
|
|
Word("DISTRIBUTE SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::Distribute &) { Word("DISTRIBUTE "); },
|
|
[&](const OmpLoopDirective::ParallelDoSimd &) {
|
|
Word("PARALLEL DO SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::ParallelDo &) { Word("PARALLEL DO "); },
|
|
[&](const OmpLoopDirective::Do &) { Word("DO "); },
|
|
[&](const OmpLoopDirective::DoSimd &) { Word("Do SIMD "); },
|
|
[&](const OmpLoopDirective::Simd &) { Word("SIMD "); },
|
|
[&](const OmpLoopDirective::TargetParallelDoSimd &) {
|
|
Word("TARGET PARALLEL DO SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::TargetParallelDo &) {
|
|
Word("TARGET PARALLEL DO ");
|
|
},
|
|
[&](const OmpLoopDirective::TargetTeamsDistributeParallelDoSimd &) {
|
|
Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::TargetTeamsDistributeParallelDo &) {
|
|
Word("TARGET TEAMS DISTRIBUTE PARALLEL DO ");
|
|
},
|
|
[&](const OmpLoopDirective::TargetTeamsDistributeSimd &) {
|
|
Word("TARGET TEAMS DISTRIBUTE SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::TargetTeamsDistribute &) {
|
|
Word("TARGET TEAMS DISTRIBUTE ");
|
|
},
|
|
[&](const OmpLoopDirective::TargetSimd &) { Word("TARGET SIMD "); },
|
|
[&](const OmpLoopDirective::TaskloopSimd &) {
|
|
Word("TASKLOOP SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::Taskloop &) { Word("TASKLOOP "); },
|
|
[&](const OmpLoopDirective::TeamsDistributeParallelDoSimd &) {
|
|
Word("TEAMS DISTRIBUTE PARALLEL DO SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::TeamsDistributeParallelDo &) {
|
|
Word("TEAMS DISTRIBUTE PARALLEL DO ");
|
|
},
|
|
[&](const OmpLoopDirective::TeamsDistributeSimd &) {
|
|
Word("TEAMS DISTRIBUTE SIMD ");
|
|
},
|
|
[&](const OmpLoopDirective::TeamsDistribute &) {
|
|
Word("TEAMS DISTRIBUTE ");
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const OmpObjectList &x) { Walk(x.v, ","); }
|
|
void Unparse(const OmpStandaloneDirective &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const OmpStandaloneDirective::TargetEnterData &) {
|
|
Word("TARGET ENTER DATA ");
|
|
},
|
|
[&](const OmpStandaloneDirective::TargetExitData &) {
|
|
Word("TARGET EXIT DATA ");
|
|
},
|
|
[&](const OmpStandaloneDirective::TargetUpdate &) {
|
|
Word("TARGET UPDATE ");
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const OmpBlockDirective &x) {
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const OmpBlockDirective::Master &y) { Word("MASTER"); },
|
|
[&](const OmpBlockDirective::Ordered &) { Word("ORDERED "); },
|
|
[&](const OmpBlockDirective::ParallelWorkshare &) {
|
|
Word("PARALLEL WORKSHARE ");
|
|
},
|
|
[&](const OmpBlockDirective::Parallel &) { Word("PARALLEL "); },
|
|
[&](const OmpBlockDirective::TargetData &) {
|
|
Word("TARGET DATA ");
|
|
},
|
|
[&](const OmpBlockDirective::TargetParallel &) {
|
|
Word("TARGET PARALLEL ");
|
|
},
|
|
[&](const OmpBlockDirective::TargetTeams &) {
|
|
Word("TARGET TEAMS ");
|
|
},
|
|
[&](const OmpBlockDirective::Target &) { Word("TARGET "); },
|
|
[&](const OmpBlockDirective::Taskgroup &) { Word("TASKGROUP "); },
|
|
[&](const OmpBlockDirective::Task &) { Word("TASK "); },
|
|
[&](const OmpBlockDirective::Teams &) { Word("TEAMS "); },
|
|
},
|
|
x.u);
|
|
}
|
|
void Unparse(const OmpAtomic &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ATOMIC");
|
|
Walk(std::get<std::optional<OmpAtomic::SeqCst>>(x.t), " SEQ_CST");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Statement<AssignmentStmt>>(x.t));
|
|
BeginOpenMP();
|
|
Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpAtomicCapture &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ATOMIC");
|
|
Walk(std::get<std::optional<OmpAtomicCapture::SeqCst1>>(x.t), " SEQ_CST,");
|
|
Word(" CAPTURE");
|
|
Walk(std::get<std::optional<OmpAtomicCapture::SeqCst2>>(x.t), " ,SEQ_CST");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<OmpAtomicCapture::Stmt1>(x.t));
|
|
Put("\n");
|
|
Walk(std::get<OmpAtomicCapture::Stmt2>(x.t));
|
|
BeginOpenMP();
|
|
Word("!$OMP END ATOMIC\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpAtomicRead &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ATOMIC");
|
|
Walk(std::get<std::optional<OmpAtomicRead::SeqCst1>>(x.t), " SEQ_CST,");
|
|
Word(" READ");
|
|
Walk(std::get<std::optional<OmpAtomicRead::SeqCst2>>(x.t), " ,SEQ_CST");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Statement<AssignmentStmt>>(x.t));
|
|
BeginOpenMP();
|
|
Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpAtomicUpdate &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ATOMIC");
|
|
Walk(std::get<std::optional<OmpAtomicUpdate::SeqCst1>>(x.t), " SEQ_CST,");
|
|
Word(" UPDATE");
|
|
Walk(std::get<std::optional<OmpAtomicUpdate::SeqCst2>>(x.t), " ,SEQ_CST");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Statement<AssignmentStmt>>(x.t));
|
|
BeginOpenMP();
|
|
Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpAtomicWrite &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ATOMIC");
|
|
Walk(std::get<std::optional<OmpAtomicWrite::SeqCst1>>(x.t), " SEQ_CST,");
|
|
Word(" WRITE");
|
|
Walk(std::get<std::optional<OmpAtomicWrite::SeqCst2>>(x.t), " ,SEQ_CST");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Statement<AssignmentStmt>>(x.t));
|
|
BeginOpenMP();
|
|
Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpEndCritical &x) {
|
|
Walk(" (", x.v, ")");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPCriticalConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP CRITICAL");
|
|
Walk(" (", std::get<std::optional<Name>>(x.t), ")");
|
|
Walk(" HINT(", std::get<std::optional<OpenMPCriticalConstruct::Hint>>(x.t),
|
|
")");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Block>(x.t), "");
|
|
BeginOpenMP();
|
|
Word("!$OMP END CRITICAL");
|
|
Walk(std::get<OmpEndCritical>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPDeclareTargetConstruct::WithClause &x) {
|
|
Walk(x.maptype), Put("("), Walk(x.names), Put(")");
|
|
}
|
|
void Unparse(const OpenMPDeclareTargetConstruct::WithExtendedList &x) {
|
|
Put("("), Walk(x.names), Put(")");
|
|
}
|
|
void Unparse(const OmpReductionInitializerClause &x) {
|
|
Word(" INITIALIZER(OMP_PRIV = ");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
void Unparse(const OmpReductionCombiner::FunctionCombiner &x) {
|
|
const auto &pd = std::get<ProcedureDesignator>(x.v.t);
|
|
const auto &args = std::get<std::list<ActualArgSpec>>(x.v.t);
|
|
Walk(pd);
|
|
if (args.empty()) {
|
|
if (std::holds_alternative<ProcComponentRef>(pd.u)) {
|
|
Put("()");
|
|
}
|
|
} else {
|
|
Walk("(", args, ", ", ")");
|
|
}
|
|
}
|
|
void Unparse(const OpenMPDeclareReductionConstruct &x) {
|
|
Put("(");
|
|
Walk(std::get<OmpReductionOperator>(x.t)), Put(" : ");
|
|
Walk(std::get<std::list<DeclarationTypeSpec>>(x.t), ","), Put(" : ");
|
|
Walk(std::get<OmpReductionCombiner>(x.t));
|
|
Put(")");
|
|
Walk(std::get<std::optional<OmpReductionInitializerClause>>(x.t));
|
|
}
|
|
bool Pre(const OpenMPDeclarativeConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ");
|
|
return std::visit(
|
|
common::visitors{
|
|
[&](const OpenMPDeclareReductionConstruct &y) {
|
|
Word("DECLARE REDUCTION ");
|
|
return true;
|
|
},
|
|
[&](const OpenMPDeclareSimdConstruct &y) {
|
|
Word("DECLARE SIMD ");
|
|
Walk("(", std::get<std::optional<Name>>(y.t), ")");
|
|
Walk(std::get<OmpClauseList>(y.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
return false;
|
|
},
|
|
[&](const OpenMPDeclareTargetConstruct &y) {
|
|
Word("DECLARE TARGET ");
|
|
return true;
|
|
},
|
|
[&](const OpenMPDeclarativeConstruct::Threadprivate &y) {
|
|
Word("THREADPRIVATE (");
|
|
return true;
|
|
},
|
|
},
|
|
x.u);
|
|
}
|
|
void Post(const OpenMPDeclarativeConstruct &x) {
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Post(const OpenMPDeclarativeConstruct::Threadprivate &x) {
|
|
Put(")\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpEndDoSimd &x) {
|
|
BeginOpenMP();
|
|
Word("DO SIMD ");
|
|
Walk(x.v);
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpEndDo &x) {
|
|
BeginOpenMP();
|
|
Word("DO ");
|
|
Walk(x.v);
|
|
EndOpenMP();
|
|
}
|
|
bool Pre(const OpenMPBarrierConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP BARRIER");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
return false;
|
|
}
|
|
void Unparse(const OpenMPSingleConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP SINGLE");
|
|
Walk(std::get<OmpClauseList>(x.t));
|
|
EndOpenMP();
|
|
Put("\n");
|
|
Walk(std::get<Block>(x.t), "");
|
|
BeginOpenMP();
|
|
Word("!$OMP END SINGLE ");
|
|
Walk(std::get<OmpEndSingle>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpSection &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP SECTION");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPSectionsConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP SECTIONS");
|
|
Walk(std::get<OmpClauseList>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Block>(x.t), "");
|
|
BeginOpenMP();
|
|
Word("!$OMP END SECTIONS");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPParallelSectionsConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP PARALLEL SECTIONS");
|
|
Walk(std::get<OmpClauseList>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Block>(x.t), "");
|
|
BeginOpenMP();
|
|
Word("!$OMP END PARALLEL SECTIONS");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPWorkshareConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP WORKSHARE");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Block>(x.t), "");
|
|
BeginOpenMP();
|
|
Word("!$OMP END WORKSHARE ");
|
|
Walk(std::get<std::optional<OmpNowait>>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
bool Pre(const OpenMPTaskyieldConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP TASKYIELD");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
return false;
|
|
}
|
|
bool Pre(const OpenMPTaskwaitConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP TASKWAIT");
|
|
Put("\n");
|
|
EndOpenMP();
|
|
return false;
|
|
}
|
|
void Unparse(const OpenMPCancellationPointConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP CANCELLATION POINT ");
|
|
Walk(x.v);
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPCancelConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP CANCEL ");
|
|
Walk(std::get<OmpCancelType>(x.t));
|
|
Walk(std::get<std::optional<OpenMPCancelConstruct::If>>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPFlushConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP FLUSH");
|
|
if ((x.v).has_value()) {
|
|
Put("(");
|
|
Walk(x.v);
|
|
Put(")");
|
|
}
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
bool Pre(const OpenMPEndLoopDirective &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP END ");
|
|
return true;
|
|
}
|
|
void Post(const OpenMPEndLoopDirective &x) {
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); }
|
|
void Unparse(const OpenMPStandaloneConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ");
|
|
Walk(std::get<OmpStandaloneDirective>(x.t));
|
|
Walk(std::get<OmpClauseList>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPBlockConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ");
|
|
Walk(std::get<OmpBlockDirective>(x.t));
|
|
Walk(std::get<OmpClauseList>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
Walk(std::get<Block>(x.t), "");
|
|
BeginOpenMP();
|
|
Word("!$OMP END ");
|
|
Walk(std::get<OmpEndBlockDirective>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const OpenMPLoopConstruct &x) {
|
|
BeginOpenMP();
|
|
Word("!$OMP ");
|
|
Walk(std::get<OmpLoopDirective>(x.t));
|
|
Walk(std::get<OmpClauseList>(x.t));
|
|
Put("\n");
|
|
EndOpenMP();
|
|
}
|
|
void Unparse(const BasedPointerStmt &x) {
|
|
Word("POINTER ("), Walk(std::get<0>(x.t)), Put(", ");
|
|
Walk(std::get<1>(x.t));
|
|
Walk("(", std::get<std::optional<ArraySpec>>(x.t), ")"), Put(')');
|
|
}
|
|
void Post(const StructureField &x) {
|
|
if (const auto *def{std::get_if<Statement<DataComponentDefStmt>>(&x.u)}) {
|
|
for (const auto &decl :
|
|
std::get<std::list<ComponentDecl>>(def->statement.t)) {
|
|
structureComponents_.insert(std::get<Name>(decl.t).source);
|
|
}
|
|
}
|
|
}
|
|
void Unparse(const StructureStmt &x) {
|
|
Word("STRUCTURE ");
|
|
if (std::get<bool>(x.t)) { // slashes around name
|
|
Put('/'), Walk(std::get<Name>(x.t)), Put('/');
|
|
Walk(" ", std::get<std::list<EntityDecl>>(x.t), ", ");
|
|
} else {
|
|
CHECK(std::get<std::list<EntityDecl>>(x.t).empty());
|
|
Walk(std::get<Name>(x.t));
|
|
}
|
|
Indent();
|
|
}
|
|
void Post(const Union::UnionStmt &) { Word("UNION"), Indent(); }
|
|
void Post(const Union::EndUnionStmt &) { Outdent(), Word("END UNION"); }
|
|
void Post(const Map::MapStmt &) { Word("MAP"), Indent(); }
|
|
void Post(const Map::EndMapStmt &) { Outdent(), Word("END MAP"); }
|
|
void Post(const StructureDef::EndStructureStmt &) {
|
|
Outdent(), Word("END STRUCTURE");
|
|
}
|
|
void Unparse(const OldParameterStmt &x) {
|
|
Word("PARAMETER "), Walk(x.v, ", ");
|
|
}
|
|
void Unparse(const ArithmeticIfStmt &x) {
|
|
Word("IF ("), Walk(std::get<Expr>(x.t)), Put(") ");
|
|
Walk(std::get<1>(x.t)), Put(", ");
|
|
Walk(std::get<2>(x.t)), Put(", ");
|
|
Walk(std::get<3>(x.t));
|
|
}
|
|
void Unparse(const AssignStmt &x) {
|
|
Word("ASSIGN "), Walk(std::get<Label>(x.t));
|
|
Word(" TO "), Walk(std::get<Name>(x.t));
|
|
}
|
|
void Unparse(const AssignedGotoStmt &x) {
|
|
Word("GO TO "), Walk(std::get<Name>(x.t));
|
|
Walk(", (", std::get<std::list<Label>>(x.t), ", ", ")");
|
|
}
|
|
void Unparse(const PauseStmt &x) { Word("PAUSE"), Walk(" ", x.v); }
|
|
|
|
#define WALK_NESTED_ENUM(CLASS, ENUM) \
|
|
void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); }
|
|
WALK_NESTED_ENUM(AccessSpec, Kind) // R807
|
|
WALK_NESTED_ENUM(common, TypeParamAttr) // R734
|
|
WALK_NESTED_ENUM(IntentSpec, Intent) // R826
|
|
WALK_NESTED_ENUM(ImplicitStmt, ImplicitNoneNameSpec) // R866
|
|
WALK_NESTED_ENUM(ConnectSpec::CharExpr, Kind) // R1205
|
|
WALK_NESTED_ENUM(IoControlSpec::CharExpr, Kind)
|
|
WALK_NESTED_ENUM(InquireSpec::CharVar, Kind)
|
|
WALK_NESTED_ENUM(InquireSpec::IntVar, Kind)
|
|
WALK_NESTED_ENUM(InquireSpec::LogVar, Kind)
|
|
WALK_NESTED_ENUM(ProcedureStmt, Kind) // R1506
|
|
WALK_NESTED_ENUM(UseStmt, ModuleNature) // R1410
|
|
WALK_NESTED_ENUM(OmpProcBindClause, Type) // OMP PROC_BIND
|
|
WALK_NESTED_ENUM(OmpDefaultClause, Type) // OMP DEFAULT
|
|
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
|
|
WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
|
|
WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type
|
|
WALK_NESTED_ENUM(OmpMapType, Type) // OMP map-type
|
|
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
|
|
WALK_NESTED_ENUM(
|
|
OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
|
|
WALK_NESTED_ENUM(OmpDeclareTargetMapType, Type) // OMP DeclareTarget map-type
|
|
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
|
|
#undef WALK_NESTED_ENUM
|
|
|
|
void Done() const { CHECK(indent_ == 0); }
|
|
|
|
private:
|
|
void Put(char);
|
|
void Put(const char *);
|
|
void Put(const std::string &);
|
|
void PutKeywordLetter(char);
|
|
void Word(const char *);
|
|
void Word(const std::string &);
|
|
void Indent() { indent_ += indentationAmount_; }
|
|
void Outdent() {
|
|
CHECK(indent_ >= indentationAmount_);
|
|
indent_ -= indentationAmount_;
|
|
}
|
|
void BeginOpenMP() { openmpDirective_ = true; }
|
|
void EndOpenMP() { openmpDirective_ = false; }
|
|
|
|
// Call back to the traversal framework.
|
|
template<typename T> void Walk(const T &x) {
|
|
Fortran::parser::Walk(x, *this);
|
|
}
|
|
|
|
// Traverse a std::optional<> value. Emit a prefix and/or a suffix string
|
|
// only when it contains a value.
|
|
template<typename A>
|
|
void Walk(
|
|
const char *prefix, const std::optional<A> &x, const char *suffix = "") {
|
|
if (x.has_value()) {
|
|
Word(prefix), Walk(*x), Word(suffix);
|
|
}
|
|
}
|
|
template<typename A>
|
|
void Walk(const std::optional<A> &x, const char *suffix = "") {
|
|
return Walk("", x, suffix);
|
|
}
|
|
|
|
// Traverse a std::list<>. Separate the elements with an optional string.
|
|
// Emit a prefix and/or a suffix string only when the list is not empty.
|
|
template<typename A>
|
|
void Walk(const char *prefix, const std::list<A> &list,
|
|
const char *comma = ", ", const char *suffix = "") {
|
|
if (!list.empty()) {
|
|
const char *str{prefix};
|
|
for (const auto &x : list) {
|
|
Word(str), Walk(x);
|
|
str = comma;
|
|
}
|
|
Word(suffix);
|
|
}
|
|
}
|
|
template<typename A>
|
|
void Walk(const std::list<A> &list, const char *comma = ", ",
|
|
const char *suffix = "") {
|
|
return Walk("", list, comma, suffix);
|
|
}
|
|
|
|
// Traverse a std::tuple<>, with an optional separator.
|
|
template<std::size_t J = 0, typename T>
|
|
void WalkTupleElements(const T &tuple, const char *separator) {
|
|
if constexpr (J < std::tuple_size_v<T>) {
|
|
if (J > 0) {
|
|
Word(separator);
|
|
}
|
|
Walk(std::get<J>(tuple));
|
|
WalkTupleElements<J + 1>(tuple, separator);
|
|
}
|
|
}
|
|
template<typename... A>
|
|
void Walk(const std::tuple<A...> &tuple, const char *separator = "") {
|
|
WalkTupleElements(tuple, separator);
|
|
}
|
|
|
|
void EndSubprogram(const char *kind, const std::optional<Name> &name) {
|
|
Outdent(), Word("END "), Word(kind), Walk(" ", name);
|
|
structureComponents_.clear();
|
|
}
|
|
|
|
std::ostream &out_;
|
|
int indent_{0};
|
|
const int indentationAmount_{1};
|
|
int column_{1};
|
|
const int maxColumns_{80};
|
|
std::set<CharBlock> structureComponents_;
|
|
Encoding encoding_{Encoding::UTF8};
|
|
bool capitalizeKeywords_{true};
|
|
bool openmpDirective_{false};
|
|
bool backslashEscapes_{false};
|
|
preStatementType *preStatement_{nullptr};
|
|
};
|
|
|
|
void UnparseVisitor::Put(char ch) {
|
|
int sav = indent_;
|
|
if (openmpDirective_) {
|
|
indent_ = 0;
|
|
}
|
|
if (column_ <= 1) {
|
|
if (ch == '\n') {
|
|
return;
|
|
}
|
|
for (int j{0}; j < indent_; ++j) {
|
|
out_ << ' ';
|
|
}
|
|
column_ = indent_ + 2;
|
|
} else if (ch == '\n') {
|
|
column_ = 1;
|
|
} else if (++column_ >= maxColumns_) {
|
|
out_ << "&\n";
|
|
for (int j{0}; j < indent_; ++j) {
|
|
out_ << ' ';
|
|
}
|
|
if (openmpDirective_) {
|
|
out_ << "!$OMP&";
|
|
column_ = 8;
|
|
} else {
|
|
out_ << '&';
|
|
column_ = indent_ + 3;
|
|
}
|
|
}
|
|
out_ << ch;
|
|
if (openmpDirective_) {
|
|
indent_ = sav;
|
|
}
|
|
}
|
|
|
|
void UnparseVisitor::Put(const char *str) {
|
|
for (; *str != '\0'; ++str) {
|
|
Put(*str);
|
|
}
|
|
}
|
|
|
|
void UnparseVisitor::Put(const std::string &str) {
|
|
for (char ch : str) {
|
|
Put(ch);
|
|
}
|
|
}
|
|
|
|
void UnparseVisitor::PutKeywordLetter(char ch) {
|
|
if (capitalizeKeywords_) {
|
|
Put(ToUpperCaseLetter(ch));
|
|
} else {
|
|
Put(ToLowerCaseLetter(ch));
|
|
}
|
|
}
|
|
|
|
void UnparseVisitor::Word(const char *str) {
|
|
for (; *str != '\0'; ++str) {
|
|
PutKeywordLetter(*str);
|
|
}
|
|
}
|
|
|
|
void UnparseVisitor::Word(const std::string &str) { Word(str.c_str()); }
|
|
|
|
void Unparse(std::ostream &out, const Program &program, Encoding encoding,
|
|
bool capitalizeKeywords, bool backslashEscapes,
|
|
preStatementType *preStatement) {
|
|
UnparseVisitor visitor{
|
|
out, 1, encoding, capitalizeKeywords, backslashEscapes, preStatement};
|
|
Walk(program, visitor);
|
|
visitor.Done();
|
|
}
|
|
}
|