164ab3302SCarolineConcatto //===-- lib/Parser/parse-tree.cpp -----------------------------------------===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto
964ab3302SCarolineConcatto #include "flang/Parser/parse-tree.h"
1064ab3302SCarolineConcatto #include "flang/Common/idioms.h"
1164ab3302SCarolineConcatto #include "flang/Common/indirection.h"
12914a91c1STim Keith #include "flang/Parser/tools.h"
1364ab3302SCarolineConcatto #include "flang/Parser/user-state.h"
148670e499SCaroline Concatto #include "llvm/Support/raw_ostream.h"
1564ab3302SCarolineConcatto #include <algorithm>
1664ab3302SCarolineConcatto
1764ab3302SCarolineConcatto namespace Fortran::parser {
1864ab3302SCarolineConcatto
1964ab3302SCarolineConcatto // R867
ImportStmt(common::ImportKind && k,std::list<Name> && n)2064ab3302SCarolineConcatto ImportStmt::ImportStmt(common::ImportKind &&k, std::list<Name> &&n)
2164ab3302SCarolineConcatto : kind{k}, names(std::move(n)) {
2264ab3302SCarolineConcatto CHECK(kind == common::ImportKind::Default ||
2364ab3302SCarolineConcatto kind == common::ImportKind::Only || names.empty());
2464ab3302SCarolineConcatto }
2564ab3302SCarolineConcatto
2664ab3302SCarolineConcatto // R873
CommonStmt(std::optional<Name> && name,std::list<CommonBlockObject> && objects,std::list<Block> && others)2764ab3302SCarolineConcatto CommonStmt::CommonStmt(std::optional<Name> &&name,
2864ab3302SCarolineConcatto std::list<CommonBlockObject> &&objects, std::list<Block> &&others) {
2964ab3302SCarolineConcatto blocks.emplace_front(std::move(name), std::move(objects));
3064ab3302SCarolineConcatto blocks.splice(blocks.end(), std::move(others));
3164ab3302SCarolineConcatto }
3264ab3302SCarolineConcatto
3364ab3302SCarolineConcatto // R901 designator
EndsInBareName() const3464ab3302SCarolineConcatto bool Designator::EndsInBareName() const {
35cd03e96fSPeter Klausler return common::visit(
3664ab3302SCarolineConcatto common::visitors{
3764ab3302SCarolineConcatto [](const DataRef &dr) {
3864ab3302SCarolineConcatto return std::holds_alternative<Name>(dr.u) ||
3964ab3302SCarolineConcatto std::holds_alternative<common::Indirection<StructureComponent>>(
4064ab3302SCarolineConcatto dr.u);
4164ab3302SCarolineConcatto },
4264ab3302SCarolineConcatto [](const Substring &) { return false; },
4364ab3302SCarolineConcatto },
4464ab3302SCarolineConcatto u);
4564ab3302SCarolineConcatto }
4664ab3302SCarolineConcatto
4764ab3302SCarolineConcatto // R911 data-ref -> part-ref [% part-ref]...
DataRef(std::list<PartRef> && prl)4864ab3302SCarolineConcatto DataRef::DataRef(std::list<PartRef> &&prl) : u{std::move(prl.front().name)} {
4964ab3302SCarolineConcatto for (bool first{true}; !prl.empty(); first = false, prl.pop_front()) {
5064ab3302SCarolineConcatto PartRef &pr{prl.front()};
5164ab3302SCarolineConcatto if (!first) {
5264ab3302SCarolineConcatto u = common::Indirection<StructureComponent>::Make(
5364ab3302SCarolineConcatto std::move(*this), std::move(pr.name));
5464ab3302SCarolineConcatto }
5564ab3302SCarolineConcatto if (!pr.subscripts.empty()) {
5664ab3302SCarolineConcatto u = common::Indirection<ArrayElement>::Make(
5764ab3302SCarolineConcatto std::move(*this), std::move(pr.subscripts));
5864ab3302SCarolineConcatto }
5964ab3302SCarolineConcatto if (pr.imageSelector) {
6064ab3302SCarolineConcatto u = common::Indirection<CoindexedNamedObject>::Make(
6164ab3302SCarolineConcatto std::move(*this), std::move(*pr.imageSelector));
6264ab3302SCarolineConcatto }
6364ab3302SCarolineConcatto }
6464ab3302SCarolineConcatto }
6564ab3302SCarolineConcatto
6664ab3302SCarolineConcatto // R1001 - R1022 expression
Expr(Designator && x)6764ab3302SCarolineConcatto Expr::Expr(Designator &&x)
6864ab3302SCarolineConcatto : u{common::Indirection<Designator>::Make(std::move(x))} {}
Expr(FunctionReference && x)6964ab3302SCarolineConcatto Expr::Expr(FunctionReference &&x)
7064ab3302SCarolineConcatto : u{common::Indirection<FunctionReference>::Make(std::move(x))} {}
7164ab3302SCarolineConcatto
GetLoopControl() const7264ab3302SCarolineConcatto const std::optional<LoopControl> &DoConstruct::GetLoopControl() const {
7364ab3302SCarolineConcatto const NonLabelDoStmt &doStmt{
7464ab3302SCarolineConcatto std::get<Statement<NonLabelDoStmt>>(t).statement};
7564ab3302SCarolineConcatto const std::optional<LoopControl> &control{
7664ab3302SCarolineConcatto std::get<std::optional<LoopControl>>(doStmt.t)};
7764ab3302SCarolineConcatto return control;
7864ab3302SCarolineConcatto }
7964ab3302SCarolineConcatto
IsDoNormal() const8064ab3302SCarolineConcatto bool DoConstruct::IsDoNormal() const {
8164ab3302SCarolineConcatto const std::optional<LoopControl> &control{GetLoopControl()};
8264ab3302SCarolineConcatto return control && std::holds_alternative<LoopControl::Bounds>(control->u);
8364ab3302SCarolineConcatto }
8464ab3302SCarolineConcatto
IsDoWhile() const8564ab3302SCarolineConcatto bool DoConstruct::IsDoWhile() const {
8664ab3302SCarolineConcatto const std::optional<LoopControl> &control{GetLoopControl()};
8764ab3302SCarolineConcatto return control && std::holds_alternative<ScalarLogicalExpr>(control->u);
8864ab3302SCarolineConcatto }
8964ab3302SCarolineConcatto
IsDoConcurrent() const9064ab3302SCarolineConcatto bool DoConstruct::IsDoConcurrent() const {
9164ab3302SCarolineConcatto const std::optional<LoopControl> &control{GetLoopControl()};
9264ab3302SCarolineConcatto return control && std::holds_alternative<LoopControl::Concurrent>(control->u);
9364ab3302SCarolineConcatto }
9464ab3302SCarolineConcatto
MakeArrayElementRef(const Name & name,std::list<Expr> && subscripts)9564ab3302SCarolineConcatto static Designator MakeArrayElementRef(
9664ab3302SCarolineConcatto const Name &name, std::list<Expr> &&subscripts) {
9764ab3302SCarolineConcatto ArrayElement arrayElement{DataRef{Name{name}}, std::list<SectionSubscript>{}};
9864ab3302SCarolineConcatto for (Expr &expr : subscripts) {
9964ab3302SCarolineConcatto arrayElement.subscripts.push_back(
10064ab3302SCarolineConcatto SectionSubscript{Integer{common::Indirection{std::move(expr)}}});
10164ab3302SCarolineConcatto }
10264ab3302SCarolineConcatto return Designator{DataRef{common::Indirection{std::move(arrayElement)}}};
10364ab3302SCarolineConcatto }
10464ab3302SCarolineConcatto
MakeArrayElementRef(StructureComponent && sc,std::list<Expr> && subscripts)10564ab3302SCarolineConcatto static Designator MakeArrayElementRef(
10664ab3302SCarolineConcatto StructureComponent &&sc, std::list<Expr> &&subscripts) {
10764ab3302SCarolineConcatto ArrayElement arrayElement{DataRef{common::Indirection{std::move(sc)}},
10864ab3302SCarolineConcatto std::list<SectionSubscript>{}};
10964ab3302SCarolineConcatto for (Expr &expr : subscripts) {
11064ab3302SCarolineConcatto arrayElement.subscripts.push_back(
11164ab3302SCarolineConcatto SectionSubscript{Integer{common::Indirection{std::move(expr)}}});
11264ab3302SCarolineConcatto }
11364ab3302SCarolineConcatto return Designator{DataRef{common::Indirection{std::move(arrayElement)}}};
11464ab3302SCarolineConcatto }
11564ab3302SCarolineConcatto
11664ab3302SCarolineConcatto // Set source in any type of node that has it.
WithSource(CharBlock source,T && x)11764ab3302SCarolineConcatto template <typename T> T WithSource(CharBlock source, T &&x) {
11864ab3302SCarolineConcatto x.source = source;
11964ab3302SCarolineConcatto return std::move(x);
12064ab3302SCarolineConcatto }
12164ab3302SCarolineConcatto
ActualArgToExpr(ActualArgSpec & arg)12264ab3302SCarolineConcatto static Expr ActualArgToExpr(ActualArgSpec &arg) {
123cd03e96fSPeter Klausler return common::visit(
12464ab3302SCarolineConcatto common::visitors{
12564ab3302SCarolineConcatto [&](common::Indirection<Expr> &y) { return std::move(y.value()); },
12664ab3302SCarolineConcatto [&](common::Indirection<Variable> &y) {
127cd03e96fSPeter Klausler return common::visit(
12864ab3302SCarolineConcatto common::visitors{
12964ab3302SCarolineConcatto [&](common::Indirection<Designator> &z) {
13064ab3302SCarolineConcatto return WithSource(
13164ab3302SCarolineConcatto z.value().source, Expr{std::move(z.value())});
13264ab3302SCarolineConcatto },
13364ab3302SCarolineConcatto [&](common::Indirection<FunctionReference> &z) {
13464ab3302SCarolineConcatto return WithSource(
13564ab3302SCarolineConcatto z.value().v.source, Expr{std::move(z.value())});
13664ab3302SCarolineConcatto },
13764ab3302SCarolineConcatto },
13864ab3302SCarolineConcatto y.value().u);
13964ab3302SCarolineConcatto },
14064ab3302SCarolineConcatto [&](auto &) -> Expr { common::die("unexpected type"); },
14164ab3302SCarolineConcatto },
14264ab3302SCarolineConcatto std::get<ActualArg>(arg.t).u);
14364ab3302SCarolineConcatto }
14464ab3302SCarolineConcatto
ConvertToArrayElementRef()14564ab3302SCarolineConcatto Designator FunctionReference::ConvertToArrayElementRef() {
14664ab3302SCarolineConcatto std::list<Expr> args;
14764ab3302SCarolineConcatto for (auto &arg : std::get<std::list<ActualArgSpec>>(v.t)) {
14864ab3302SCarolineConcatto args.emplace_back(ActualArgToExpr(arg));
14964ab3302SCarolineConcatto }
150cd03e96fSPeter Klausler return common::visit(
15164ab3302SCarolineConcatto common::visitors{
15264ab3302SCarolineConcatto [&](const Name &name) {
15364ab3302SCarolineConcatto return WithSource(
15464ab3302SCarolineConcatto v.source, MakeArrayElementRef(name, std::move(args)));
15564ab3302SCarolineConcatto },
15664ab3302SCarolineConcatto [&](ProcComponentRef &pcr) {
15764ab3302SCarolineConcatto return WithSource(v.source,
15864ab3302SCarolineConcatto MakeArrayElementRef(std::move(pcr.v.thing), std::move(args)));
15964ab3302SCarolineConcatto },
16064ab3302SCarolineConcatto },
16164ab3302SCarolineConcatto std::get<ProcedureDesignator>(v.t).u);
16264ab3302SCarolineConcatto }
16364ab3302SCarolineConcatto
ConvertToStructureConstructor(const semantics::DerivedTypeSpec & derived)16464ab3302SCarolineConcatto StructureConstructor FunctionReference::ConvertToStructureConstructor(
16564ab3302SCarolineConcatto const semantics::DerivedTypeSpec &derived) {
16664ab3302SCarolineConcatto Name name{std::get<parser::Name>(std::get<ProcedureDesignator>(v.t).u)};
16764ab3302SCarolineConcatto std::list<ComponentSpec> components;
16864ab3302SCarolineConcatto for (auto &arg : std::get<std::list<ActualArgSpec>>(v.t)) {
16964ab3302SCarolineConcatto std::optional<Keyword> keyword;
17064ab3302SCarolineConcatto if (auto &kw{std::get<std::optional<Keyword>>(arg.t)}) {
17164ab3302SCarolineConcatto keyword.emplace(Keyword{Name{kw->v}});
17264ab3302SCarolineConcatto }
17364ab3302SCarolineConcatto components.emplace_back(
17464ab3302SCarolineConcatto std::move(keyword), ComponentDataSource{ActualArgToExpr(arg)});
17564ab3302SCarolineConcatto }
17664ab3302SCarolineConcatto DerivedTypeSpec spec{std::move(name), std::list<TypeParamSpec>{}};
17764ab3302SCarolineConcatto spec.derivedTypeSpec = &derived;
17864ab3302SCarolineConcatto return StructureConstructor{std::move(spec), std::move(components)};
17964ab3302SCarolineConcatto }
18064ab3302SCarolineConcatto
ConvertToStructureConstructor(const semantics::DerivedTypeSpec & derived)181914a91c1STim Keith StructureConstructor ArrayElement::ConvertToStructureConstructor(
182914a91c1STim Keith const semantics::DerivedTypeSpec &derived) {
183914a91c1STim Keith Name name{std::get<parser::Name>(base.u)};
184914a91c1STim Keith std::list<ComponentSpec> components;
185914a91c1STim Keith for (auto &subscript : subscripts) {
186914a91c1STim Keith components.emplace_back(std::optional<Keyword>{},
187914a91c1STim Keith ComponentDataSource{std::move(*Unwrap<Expr>(subscript))});
188914a91c1STim Keith }
189914a91c1STim Keith DerivedTypeSpec spec{std::move(name), std::list<TypeParamSpec>{}};
190914a91c1STim Keith spec.derivedTypeSpec = &derived;
191914a91c1STim Keith return StructureConstructor{std::move(spec), std::move(components)};
192914a91c1STim Keith }
193914a91c1STim Keith
ConvertToSubstring()19464ab3302SCarolineConcatto Substring ArrayElement::ConvertToSubstring() {
19564ab3302SCarolineConcatto auto iter{subscripts.begin()};
19664ab3302SCarolineConcatto CHECK(iter != subscripts.end());
19764ab3302SCarolineConcatto auto &triplet{std::get<SubscriptTriplet>(iter->u)};
19864ab3302SCarolineConcatto CHECK(!std::get<2>(triplet.t));
19964ab3302SCarolineConcatto CHECK(++iter == subscripts.end());
20064ab3302SCarolineConcatto return Substring{std::move(base),
20164ab3302SCarolineConcatto SubstringRange{std::get<0>(std::move(triplet.t)),
20264ab3302SCarolineConcatto std::get<1>(std::move(triplet.t))}};
20364ab3302SCarolineConcatto }
20464ab3302SCarolineConcatto
20564ab3302SCarolineConcatto // R1544 stmt-function-stmt
206*149d3e43SPeter Klausler // Convert this stmt-function-stmt to an assignment to the result of a
207*149d3e43SPeter Klausler // pointer-valued function call -- which itself will be converted to a
208*149d3e43SPeter Klausler // much more likely array element assignment statement if it needs
209*149d3e43SPeter Klausler // to be.
ConvertToAssignment()21064ab3302SCarolineConcatto Statement<ActionStmt> StmtFunctionStmt::ConvertToAssignment() {
21164ab3302SCarolineConcatto auto &funcName{std::get<Name>(t)};
21264ab3302SCarolineConcatto auto &funcArgs{std::get<std::list<Name>>(t)};
21364ab3302SCarolineConcatto auto &funcExpr{std::get<Scalar<Expr>>(t).thing};
21464ab3302SCarolineConcatto CharBlock source{funcName.source};
215*149d3e43SPeter Klausler // Extend source to include closing parenthesis
21664ab3302SCarolineConcatto if (funcArgs.empty()) {
21764ab3302SCarolineConcatto CHECK(*source.end() == '(');
21864ab3302SCarolineConcatto source = CharBlock{source.begin(), source.end() + 1};
21964ab3302SCarolineConcatto }
220*149d3e43SPeter Klausler std::list<ActualArgSpec> actuals;
221*149d3e43SPeter Klausler for (const Name &arg : funcArgs) {
222*149d3e43SPeter Klausler actuals.emplace_back(std::optional<Keyword>{},
223*149d3e43SPeter Klausler ActualArg{Expr{WithSource(
224*149d3e43SPeter Klausler arg.source, Designator{DataRef{Name{arg.source, arg.symbol}}})}});
225*149d3e43SPeter Klausler source.ExtendToCover(arg.source);
226*149d3e43SPeter Klausler }
22764ab3302SCarolineConcatto CHECK(*source.end() == ')');
22864ab3302SCarolineConcatto source = CharBlock{source.begin(), source.end() + 1};
229*149d3e43SPeter Klausler FunctionReference funcRef{WithSource(source,
230*149d3e43SPeter Klausler Call{ProcedureDesignator{Name{funcName.source, funcName.symbol}},
231*149d3e43SPeter Klausler std::move(actuals)})};
232*149d3e43SPeter Klausler auto variable{Variable{common::Indirection{std::move(funcRef)}}};
23364ab3302SCarolineConcatto return Statement{std::nullopt,
23464ab3302SCarolineConcatto ActionStmt{common::Indirection{
23564ab3302SCarolineConcatto AssignmentStmt{std::move(variable), std::move(funcExpr)}}}};
23664ab3302SCarolineConcatto }
23764ab3302SCarolineConcatto
GetSource() const23864ab3302SCarolineConcatto CharBlock Variable::GetSource() const {
239cd03e96fSPeter Klausler return common::visit(
24064ab3302SCarolineConcatto common::visitors{
24164ab3302SCarolineConcatto [&](const common::Indirection<Designator> &des) {
24264ab3302SCarolineConcatto return des.value().source;
24364ab3302SCarolineConcatto },
24464ab3302SCarolineConcatto [&](const common::Indirection<parser::FunctionReference> &call) {
24564ab3302SCarolineConcatto return call.value().v.source;
24664ab3302SCarolineConcatto },
24764ab3302SCarolineConcatto },
24864ab3302SCarolineConcatto u);
24964ab3302SCarolineConcatto }
25064ab3302SCarolineConcatto
operator <<(llvm::raw_ostream & os,const Name & x)2518670e499SCaroline Concatto llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) {
25264ab3302SCarolineConcatto return os << x.ToString();
25364ab3302SCarolineConcatto }
2541f879005STim Keith } // namespace Fortran::parser
255