2018-02-08 01:27:36 +01:00
|
|
|
#include "parse-tree.h"
|
2018-01-30 20:54:04 +01:00
|
|
|
#include "idioms.h"
|
|
|
|
#include "indirection.h"
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
namespace Fortran {
|
2018-02-07 21:04:42 +01:00
|
|
|
namespace parser {
|
2018-01-30 20:54:04 +01:00
|
|
|
|
|
|
|
// R867
|
|
|
|
ImportStmt::ImportStmt(Kind &&k, std::list<Name> &&n)
|
2018-02-05 23:29:26 +01:00
|
|
|
: kind{k}, names(std::move(n)) {
|
2018-01-30 20:54:04 +01:00
|
|
|
CHECK(kind == Kind::Default || kind == Kind::Only || names.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
// R901 designator
|
|
|
|
bool Designator::EndsInBareName() const {
|
2018-02-05 23:29:26 +01:00
|
|
|
return std::visit(
|
|
|
|
visitors{[](const ObjectName &) { return true; },
|
|
|
|
[](const DataReference &dr) {
|
|
|
|
return std::holds_alternative<Name>(dr.u) ||
|
|
|
|
std::holds_alternative<Indirection<StructureComponent>>(dr.u);
|
|
|
|
},
|
|
|
|
[](const Substring &) { return false; }},
|
|
|
|
u);
|
2018-01-30 20:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ProcedureDesignator Designator::ConvertToProcedureDesignator() {
|
2018-02-05 23:29:26 +01:00
|
|
|
return std::visit(
|
|
|
|
visitors{
|
|
|
|
[](ObjectName &n) -> ProcedureDesignator { return {std::move(n)}; },
|
|
|
|
[](DataReference &dr) -> ProcedureDesignator {
|
|
|
|
if (Name *n = std::get_if<Name>(&dr.u)) {
|
|
|
|
return {std::move(*n)};
|
|
|
|
}
|
|
|
|
StructureComponent &sc{
|
|
|
|
*std::get<Indirection<StructureComponent>>(dr.u)};
|
|
|
|
return {ProcComponentRef{
|
|
|
|
Scalar<Variable>{Indirection<Designator>{std::move(sc.base)}},
|
|
|
|
std::move(sc.component)}};
|
|
|
|
},
|
|
|
|
[](Substring &) -> ProcedureDesignator {
|
|
|
|
CHECK(!"can't get here");
|
2018-03-20 18:59:07 +01:00
|
|
|
return {Name{}};
|
2018-02-05 23:29:26 +01:00
|
|
|
}},
|
|
|
|
u);
|
2018-01-30 20:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<Call> Designator::ConvertToCall() {
|
2018-02-05 23:29:26 +01:00
|
|
|
return std::visit(
|
|
|
|
visitors{[](ObjectName &n) -> std::optional<Call> {
|
2018-02-09 23:04:11 +01:00
|
|
|
return {Call{ProcedureDesignator{std::move(n)},
|
2018-01-30 20:54:04 +01:00
|
|
|
std::list<ActualArgSpec>{}}};
|
2018-02-05 23:29:26 +01:00
|
|
|
},
|
|
|
|
[this](DataReference &dr) -> std::optional<Call> {
|
|
|
|
if (std::holds_alternative<Indirection<CoindexedNamedObject>>(
|
|
|
|
dr.u)) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
if (Name *n = std::get_if<Name>(&dr.u)) {
|
|
|
|
return {Call{ProcedureDesignator{std::move(*n)},
|
|
|
|
std::list<ActualArgSpec>{}}};
|
|
|
|
}
|
|
|
|
if (auto *isc =
|
|
|
|
std::get_if<Indirection<StructureComponent>>(&dr.u)) {
|
|
|
|
StructureComponent &sc{**isc};
|
|
|
|
Variable var{Indirection<Designator>{std::move(sc.base)}};
|
|
|
|
ProcComponentRef pcr{
|
|
|
|
Scalar<Variable>{std::move(var)}, std::move(sc.component)};
|
|
|
|
return {Call{ProcedureDesignator{std::move(pcr)},
|
|
|
|
std::list<ActualArgSpec>{}}};
|
|
|
|
}
|
|
|
|
ArrayElement &ae{*std::get<Indirection<ArrayElement>>(dr.u)};
|
|
|
|
if (std::any_of(ae.subscripts.begin(), ae.subscripts.end(),
|
|
|
|
[](const SectionSubscript &ss) {
|
|
|
|
return !ss.CanConvertToActualArgument();
|
|
|
|
})) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
std::list<ActualArgSpec> args;
|
|
|
|
for (auto &ss : ae.subscripts) {
|
|
|
|
args.emplace_back(
|
|
|
|
std::optional<Keyword>{}, ss.ConvertToActualArgument());
|
|
|
|
}
|
|
|
|
if (Name * n{std::get_if<Name>(&ae.base.u)}) {
|
|
|
|
return {
|
|
|
|
Call{ProcedureDesignator{std::move(*n)}, std::move(args)}};
|
|
|
|
}
|
|
|
|
StructureComponent &bsc{
|
|
|
|
*std::get<Indirection<StructureComponent>>(ae.base.u)};
|
|
|
|
Variable var{Indirection<Designator>{std::move(bsc.base)}};
|
|
|
|
ProcComponentRef pcr{
|
|
|
|
Scalar<Variable>{std::move(var)}, std::move(bsc.component)};
|
|
|
|
return {Call{ProcedureDesignator{std::move(pcr)}, std::move(args)}};
|
|
|
|
},
|
|
|
|
[](const Substring &) -> std::optional<Call> { return {}; }},
|
|
|
|
u);
|
2018-01-30 20:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// R911 data-ref -> part-ref [% part-ref]...
|
|
|
|
DataReference::DataReference(std::list<PartRef> &&prl)
|
2018-02-05 23:29:26 +01:00
|
|
|
: u{std::move(prl.front().name)} {
|
2018-01-30 20:54:04 +01:00
|
|
|
for (bool first{true}; !prl.empty(); first = false, prl.pop_front()) {
|
|
|
|
PartRef &pr{prl.front()};
|
|
|
|
if (!first) {
|
2018-02-05 23:29:26 +01:00
|
|
|
u = Indirection<StructureComponent>{std::move(*this), std::move(pr.name)};
|
2018-01-30 20:54:04 +01:00
|
|
|
}
|
|
|
|
if (!pr.subscripts.empty()) {
|
2018-02-05 23:29:26 +01:00
|
|
|
u = Indirection<ArrayElement>{std::move(*this), std::move(pr.subscripts)};
|
2018-01-30 20:54:04 +01:00
|
|
|
}
|
|
|
|
if (pr.imageSelector.has_value()) {
|
|
|
|
u = Indirection<CoindexedNamedObject>{
|
2018-02-05 23:29:26 +01:00
|
|
|
std::move(*this), std::move(*pr.imageSelector)};
|
2018-01-30 20:54:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// R920 section-subscript
|
|
|
|
bool SectionSubscript::CanConvertToActualArgument() const {
|
2018-02-05 23:29:26 +01:00
|
|
|
return std::visit(visitors{[](const VectorSubscript &) { return true; },
|
|
|
|
[](const ScalarIntExpr &) { return true; },
|
|
|
|
[](const SubscriptTriplet &) { return false; }},
|
|
|
|
u);
|
2018-01-30 20:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ActualArg SectionSubscript::ConvertToActualArgument() {
|
2018-02-05 23:29:26 +01:00
|
|
|
return std::visit(visitors{[](VectorSubscript &vs) -> ActualArg {
|
|
|
|
return vs.thing->ConvertToActualArgument();
|
|
|
|
},
|
|
|
|
[](ScalarIntExpr &vs) -> ActualArg {
|
|
|
|
return vs.thing.thing->ConvertToActualArgument();
|
|
|
|
},
|
|
|
|
[](SubscriptTriplet &) -> ActualArg {
|
|
|
|
CHECK(!"can't happen");
|
2018-03-20 18:59:07 +01:00
|
|
|
return {Name{}};
|
2018-02-05 23:29:26 +01:00
|
|
|
}},
|
|
|
|
u);
|
2018-01-30 20:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// R1001 - R1022 expression
|
|
|
|
Expr::Expr(Designator &&x) : u{Indirection<Designator>(std::move(x))} {}
|
|
|
|
Expr::Expr(FunctionReference &&x)
|
|
|
|
: u{Indirection<FunctionReference>(std::move(x))} {}
|
|
|
|
|
|
|
|
std::optional<Variable> Expr::ConvertToVariable() {
|
|
|
|
if (Indirection<Designator> *id = std::get_if<Indirection<Designator>>(&u)) {
|
|
|
|
return {Variable{std::move(*id)}};
|
|
|
|
}
|
|
|
|
if (Indirection<FunctionReference> *ifr =
|
2018-02-05 23:29:26 +01:00
|
|
|
std::get_if<Indirection<FunctionReference>>(&u)) {
|
2018-01-30 20:54:04 +01:00
|
|
|
return {Variable{std::move(*ifr)}};
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
ActualArg Expr::ConvertToActualArgument() {
|
|
|
|
if (std::optional<Variable> var{ConvertToVariable()}) {
|
|
|
|
return {std::move(var.value())};
|
|
|
|
}
|
|
|
|
return {std::move(*this)};
|
|
|
|
}
|
2018-02-07 21:04:42 +01:00
|
|
|
} // namespace parser
|
2018-01-30 20:54:04 +01:00
|
|
|
} // namespace Fortran
|