2020-02-25 23:11:52 +08:00
|
|
|
//===-- lib/Parser/parse-tree.cpp -----------------------------------------===//
|
2018-05-02 03:50:34 +08:00
|
|
|
//
|
2019-12-21 04:52:07 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2018-05-02 03:50:34 +08:00
|
|
|
//
|
2020-01-11 04:12:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2018-05-02 03:50:34 +08:00
|
|
|
|
2020-02-25 23:11:52 +08:00
|
|
|
#include "flang/Parser/parse-tree.h"
|
|
|
|
#include "flang/Common/idioms.h"
|
|
|
|
#include "flang/Common/indirection.h"
|
2020-02-26 09:13:56 +08:00
|
|
|
#include "flang/Parser/tools.h"
|
2020-02-25 23:11:52 +08:00
|
|
|
#include "flang/Parser/user-state.h"
|
2020-02-28 23:11:03 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2018-01-31 03:54:04 +08:00
|
|
|
#include <algorithm>
|
|
|
|
|
2018-05-03 04:48:12 +08:00
|
|
|
namespace Fortran::parser {
|
2018-01-31 03:54:04 +08:00
|
|
|
|
|
|
|
// R867
|
2018-08-24 02:45:49 +08:00
|
|
|
ImportStmt::ImportStmt(common::ImportKind &&k, std::list<Name> &&n)
|
2020-03-29 12:00:16 +08:00
|
|
|
: kind{k}, names(std::move(n)) {
|
2018-08-24 02:45:49 +08:00
|
|
|
CHECK(kind == common::ImportKind::Default ||
|
|
|
|
kind == common::ImportKind::Only || names.empty());
|
2018-01-31 03:54:04 +08:00
|
|
|
}
|
|
|
|
|
2019-02-13 08:13:58 +08:00
|
|
|
// R873
|
|
|
|
CommonStmt::CommonStmt(std::optional<Name> &&name,
|
|
|
|
std::list<CommonBlockObject> &&objects, std::list<Block> &&others) {
|
|
|
|
blocks.emplace_front(std::move(name), std::move(objects));
|
|
|
|
blocks.splice(blocks.end(), std::move(others));
|
|
|
|
}
|
|
|
|
|
2018-01-31 03:54:04 +08:00
|
|
|
// R901 designator
|
|
|
|
bool Designator::EndsInBareName() const {
|
2018-02-06 06:29:26 +08:00
|
|
|
return std::visit(
|
2018-11-30 01:27:34 +08:00
|
|
|
common::visitors{
|
2018-04-14 05:21:13 +08:00
|
|
|
[](const DataRef &dr) {
|
2018-02-06 06:29:26 +08:00
|
|
|
return std::holds_alternative<Name>(dr.u) ||
|
2018-06-19 02:03:43 +08:00
|
|
|
std::holds_alternative<common::Indirection<StructureComponent>>(
|
|
|
|
dr.u);
|
2018-02-06 06:29:26 +08:00
|
|
|
},
|
2018-11-30 01:27:34 +08:00
|
|
|
[](const Substring &) { return false; },
|
|
|
|
},
|
2018-02-06 06:29:26 +08:00
|
|
|
u);
|
2018-01-31 03:54:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// R911 data-ref -> part-ref [% part-ref]...
|
2018-04-14 05:21:13 +08:00
|
|
|
DataRef::DataRef(std::list<PartRef> &&prl) : u{std::move(prl.front().name)} {
|
2018-01-31 03:54:04 +08:00
|
|
|
for (bool first{true}; !prl.empty(); first = false, prl.pop_front()) {
|
|
|
|
PartRef &pr{prl.front()};
|
|
|
|
if (!first) {
|
2018-07-07 06:12:33 +08:00
|
|
|
u = common::Indirection<StructureComponent>::Make(
|
|
|
|
std::move(*this), std::move(pr.name));
|
2018-01-31 03:54:04 +08:00
|
|
|
}
|
|
|
|
if (!pr.subscripts.empty()) {
|
2018-07-07 06:12:33 +08:00
|
|
|
u = common::Indirection<ArrayElement>::Make(
|
|
|
|
std::move(*this), std::move(pr.subscripts));
|
2018-01-31 03:54:04 +08:00
|
|
|
}
|
2019-11-10 01:29:31 +08:00
|
|
|
if (pr.imageSelector) {
|
2018-07-07 06:12:33 +08:00
|
|
|
u = common::Indirection<CoindexedNamedObject>::Make(
|
|
|
|
std::move(*this), std::move(*pr.imageSelector));
|
2018-01-31 03:54:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// R1001 - R1022 expression
|
2018-07-07 06:12:33 +08:00
|
|
|
Expr::Expr(Designator &&x)
|
2020-03-29 12:00:16 +08:00
|
|
|
: u{common::Indirection<Designator>::Make(std::move(x))} {}
|
2018-01-31 03:54:04 +08:00
|
|
|
Expr::Expr(FunctionReference &&x)
|
2020-03-29 12:00:16 +08:00
|
|
|
: u{common::Indirection<FunctionReference>::Make(std::move(x))} {}
|
2018-04-19 22:07:47 +08:00
|
|
|
|
2019-06-05 06:14:34 +08:00
|
|
|
const std::optional<LoopControl> &DoConstruct::GetLoopControl() const {
|
2019-06-06 02:57:09 +08:00
|
|
|
const NonLabelDoStmt &doStmt{
|
2019-06-05 06:14:34 +08:00
|
|
|
std::get<Statement<NonLabelDoStmt>>(t).statement};
|
2019-06-06 02:57:09 +08:00
|
|
|
const std::optional<LoopControl> &control{
|
2019-06-05 06:14:34 +08:00
|
|
|
std::get<std::optional<LoopControl>>(doStmt.t)};
|
|
|
|
return control;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DoConstruct::IsDoNormal() const {
|
2019-06-06 02:57:09 +08:00
|
|
|
const std::optional<LoopControl> &control{GetLoopControl()};
|
2019-06-05 06:14:34 +08:00
|
|
|
return control && std::holds_alternative<LoopControl::Bounds>(control->u);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DoConstruct::IsDoWhile() const {
|
2019-06-06 02:57:09 +08:00
|
|
|
const std::optional<LoopControl> &control{GetLoopControl()};
|
2019-06-05 06:14:34 +08:00
|
|
|
return control && std::holds_alternative<ScalarLogicalExpr>(control->u);
|
|
|
|
}
|
|
|
|
|
2018-10-18 22:55:48 +08:00
|
|
|
bool DoConstruct::IsDoConcurrent() const {
|
2019-06-06 02:57:09 +08:00
|
|
|
const std::optional<LoopControl> &control{GetLoopControl()};
|
2018-10-18 22:55:48 +08:00
|
|
|
return control && std::holds_alternative<LoopControl::Concurrent>(control->u);
|
|
|
|
}
|
|
|
|
|
2019-04-29 22:32:59 +08:00
|
|
|
static Designator MakeArrayElementRef(
|
|
|
|
const Name &name, std::list<Expr> &&subscripts) {
|
2019-04-09 07:57:30 +08:00
|
|
|
ArrayElement arrayElement{DataRef{Name{name}}, std::list<SectionSubscript>{}};
|
2018-04-24 03:33:10 +08:00
|
|
|
for (Expr &expr : subscripts) {
|
2019-05-14 00:33:18 +08:00
|
|
|
arrayElement.subscripts.push_back(
|
|
|
|
SectionSubscript{Integer{common::Indirection{std::move(expr)}}});
|
2018-04-24 03:33:10 +08:00
|
|
|
}
|
2019-04-29 22:32:59 +08:00
|
|
|
return Designator{DataRef{common::Indirection{std::move(arrayElement)}}};
|
2018-04-24 03:33:10 +08:00
|
|
|
}
|
|
|
|
|
2019-05-30 04:22:35 +08:00
|
|
|
static Designator MakeArrayElementRef(
|
|
|
|
StructureComponent &&sc, std::list<Expr> &&subscripts) {
|
|
|
|
ArrayElement arrayElement{DataRef{common::Indirection{std::move(sc)}},
|
|
|
|
std::list<SectionSubscript>{}};
|
|
|
|
for (Expr &expr : subscripts) {
|
|
|
|
arrayElement.subscripts.push_back(
|
|
|
|
SectionSubscript{Integer{common::Indirection{std::move(expr)}}});
|
|
|
|
}
|
|
|
|
return Designator{DataRef{common::Indirection{std::move(arrayElement)}}};
|
|
|
|
}
|
|
|
|
|
2019-04-29 22:32:59 +08:00
|
|
|
// Set source in any type of node that has it.
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T> T WithSource(CharBlock source, T &&x) {
|
2019-04-29 22:32:59 +08:00
|
|
|
x.source = source;
|
|
|
|
return std::move(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Expr ActualArgToExpr(ActualArgSpec &arg) {
|
2019-03-09 04:55:57 +08:00
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
2019-04-29 22:32:59 +08:00
|
|
|
[&](common::Indirection<Expr> &y) { return std::move(y.value()); },
|
2019-03-09 04:55:57 +08:00
|
|
|
[&](common::Indirection<Variable> &y) {
|
|
|
|
return std::visit(
|
2019-04-29 22:32:59 +08:00
|
|
|
common::visitors{
|
|
|
|
[&](common::Indirection<Designator> &z) {
|
|
|
|
return WithSource(
|
|
|
|
z.value().source, Expr{std::move(z.value())});
|
|
|
|
},
|
|
|
|
[&](common::Indirection<FunctionReference> &z) {
|
|
|
|
return WithSource(
|
|
|
|
z.value().v.source, Expr{std::move(z.value())});
|
|
|
|
},
|
2019-03-09 04:55:57 +08:00
|
|
|
},
|
|
|
|
y.value().u);
|
|
|
|
},
|
2019-04-29 22:32:59 +08:00
|
|
|
[&](auto &) -> Expr { common::die("unexpected type"); },
|
2019-03-09 04:55:57 +08:00
|
|
|
},
|
|
|
|
std::get<ActualArg>(arg.t).u);
|
|
|
|
}
|
|
|
|
|
2018-04-24 03:33:10 +08:00
|
|
|
Designator FunctionReference::ConvertToArrayElementRef() {
|
|
|
|
std::list<Expr> args;
|
|
|
|
for (auto &arg : std::get<std::list<ActualArgSpec>>(v.t)) {
|
2019-04-29 22:32:59 +08:00
|
|
|
args.emplace_back(ActualArgToExpr(arg));
|
2018-04-24 03:33:10 +08:00
|
|
|
}
|
2019-05-30 04:22:35 +08:00
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
|
|
|
[&](const Name &name) {
|
|
|
|
return WithSource(
|
|
|
|
v.source, MakeArrayElementRef(name, std::move(args)));
|
|
|
|
},
|
|
|
|
[&](ProcComponentRef &pcr) {
|
|
|
|
return WithSource(v.source,
|
|
|
|
MakeArrayElementRef(std::move(pcr.v.thing), std::move(args)));
|
|
|
|
},
|
|
|
|
},
|
|
|
|
std::get<ProcedureDesignator>(v.t).u);
|
2018-04-24 03:33:10 +08:00
|
|
|
}
|
|
|
|
|
2019-03-09 07:16:30 +08:00
|
|
|
StructureConstructor FunctionReference::ConvertToStructureConstructor(
|
|
|
|
const semantics::DerivedTypeSpec &derived) {
|
2019-03-09 04:55:57 +08:00
|
|
|
Name name{std::get<parser::Name>(std::get<ProcedureDesignator>(v.t).u)};
|
|
|
|
std::list<ComponentSpec> components;
|
|
|
|
for (auto &arg : std::get<std::list<ActualArgSpec>>(v.t)) {
|
|
|
|
std::optional<Keyword> keyword;
|
|
|
|
if (auto &kw{std::get<std::optional<Keyword>>(arg.t)}) {
|
|
|
|
keyword.emplace(Keyword{Name{kw->v}});
|
|
|
|
}
|
2019-04-29 22:32:59 +08:00
|
|
|
components.emplace_back(
|
|
|
|
std::move(keyword), ComponentDataSource{ActualArgToExpr(arg)});
|
2019-03-09 04:55:57 +08:00
|
|
|
}
|
2019-03-09 07:16:30 +08:00
|
|
|
DerivedTypeSpec spec{std::move(name), std::list<TypeParamSpec>{}};
|
|
|
|
spec.derivedTypeSpec = &derived;
|
|
|
|
return StructureConstructor{std::move(spec), std::move(components)};
|
2019-03-09 04:55:57 +08:00
|
|
|
}
|
|
|
|
|
2020-02-26 09:13:56 +08:00
|
|
|
StructureConstructor ArrayElement::ConvertToStructureConstructor(
|
|
|
|
const semantics::DerivedTypeSpec &derived) {
|
|
|
|
Name name{std::get<parser::Name>(base.u)};
|
|
|
|
std::list<ComponentSpec> components;
|
|
|
|
for (auto &subscript : subscripts) {
|
|
|
|
components.emplace_back(std::optional<Keyword>{},
|
|
|
|
ComponentDataSource{std::move(*Unwrap<Expr>(subscript))});
|
|
|
|
}
|
|
|
|
DerivedTypeSpec spec{std::move(name), std::list<TypeParamSpec>{}};
|
|
|
|
spec.derivedTypeSpec = &derived;
|
|
|
|
return StructureConstructor{std::move(spec), std::move(components)};
|
|
|
|
}
|
|
|
|
|
2019-03-09 08:35:39 +08:00
|
|
|
Substring ArrayElement::ConvertToSubstring() {
|
|
|
|
auto iter{subscripts.begin()};
|
|
|
|
CHECK(iter != subscripts.end());
|
|
|
|
auto &triplet{std::get<SubscriptTriplet>(iter->u)};
|
2019-11-10 01:29:31 +08:00
|
|
|
CHECK(!std::get<2>(triplet.t));
|
2019-03-09 08:35:39 +08:00
|
|
|
CHECK(++iter == subscripts.end());
|
2019-06-19 06:15:22 +08:00
|
|
|
return Substring{std::move(base),
|
|
|
|
SubstringRange{std::get<0>(std::move(triplet.t)),
|
|
|
|
std::get<1>(std::move(triplet.t))}};
|
2019-03-09 08:35:39 +08:00
|
|
|
}
|
|
|
|
|
2018-04-19 22:07:47 +08:00
|
|
|
// R1544 stmt-function-stmt
|
|
|
|
// Convert this stmt-function-stmt to an array element assignment statement.
|
|
|
|
Statement<ActionStmt> StmtFunctionStmt::ConvertToAssignment() {
|
2018-07-11 08:09:07 +08:00
|
|
|
auto &funcName{std::get<Name>(t)};
|
|
|
|
auto &funcArgs{std::get<std::list<Name>>(t)};
|
|
|
|
auto &funcExpr{std::get<Scalar<Expr>>(t).thing};
|
2019-04-29 22:32:59 +08:00
|
|
|
CharBlock source{funcName.source};
|
2018-04-24 03:33:10 +08:00
|
|
|
std::list<Expr> subscripts;
|
2018-04-19 22:07:47 +08:00
|
|
|
for (Name &arg : funcArgs) {
|
2019-04-29 22:32:59 +08:00
|
|
|
subscripts.push_back(WithSource(arg.source,
|
|
|
|
Expr{common::Indirection{
|
|
|
|
WithSource(arg.source, Designator{DataRef{Name{arg}}})}}));
|
|
|
|
source.ExtendToCover(arg.source);
|
2018-04-19 22:07:47 +08:00
|
|
|
}
|
2019-04-29 22:32:59 +08:00
|
|
|
// extend source to include closing paren
|
2019-07-04 04:04:56 +08:00
|
|
|
if (funcArgs.empty()) {
|
|
|
|
CHECK(*source.end() == '(');
|
|
|
|
source = CharBlock{source.begin(), source.end() + 1};
|
|
|
|
}
|
2019-04-29 22:32:59 +08:00
|
|
|
CHECK(*source.end() == ')');
|
|
|
|
source = CharBlock{source.begin(), source.end() + 1};
|
|
|
|
auto variable{Variable{common::Indirection{WithSource(
|
|
|
|
source, MakeArrayElementRef(funcName, std::move(subscripts)))}}};
|
2018-04-19 22:07:47 +08:00
|
|
|
return Statement{std::nullopt,
|
2018-06-19 02:03:43 +08:00
|
|
|
ActionStmt{common::Indirection{
|
2018-04-19 22:07:47 +08:00
|
|
|
AssignmentStmt{std::move(variable), std::move(funcExpr)}}}};
|
|
|
|
}
|
|
|
|
|
2019-06-07 05:34:54 +08:00
|
|
|
CharBlock Variable::GetSource() const {
|
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
|
|
|
[&](const common::Indirection<Designator> &des) {
|
|
|
|
return des.value().source;
|
|
|
|
},
|
|
|
|
[&](const common::Indirection<parser::FunctionReference> &call) {
|
|
|
|
return call.value().v.source;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
u);
|
|
|
|
}
|
|
|
|
|
2020-02-28 23:11:03 +08:00
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) {
|
2018-06-12 06:40:31 +08:00
|
|
|
return os << x.ToString();
|
|
|
|
}
|
2020-03-29 12:00:16 +08:00
|
|
|
} // namespace Fortran::parser
|