2019-02-11 19:58:20 +01:00
|
|
|
// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
2018-05-01 21:50:34 +02:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2018-04-19 00:06:35 +02:00
|
|
|
#include "rewrite-parse-tree.h"
|
|
|
|
#include "scope.h"
|
2018-10-22 16:37:38 +02:00
|
|
|
#include "semantics.h"
|
2018-04-19 00:06:35 +02:00
|
|
|
#include "symbol.h"
|
2018-06-18 20:03:43 +02:00
|
|
|
#include "../common/indirection.h"
|
2018-04-19 01:49:42 +02:00
|
|
|
#include "../parser/parse-tree-visitor.h"
|
2018-04-19 00:06:35 +02:00
|
|
|
#include "../parser/parse-tree.h"
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
namespace Fortran::semantics {
|
|
|
|
|
2018-08-29 20:38:12 +02:00
|
|
|
using namespace parser::literals;
|
|
|
|
|
2018-04-19 00:50:36 +02:00
|
|
|
/// Convert mis-identified statement functions to array element assignments.
|
2018-04-19 00:06:35 +02:00
|
|
|
class RewriteMutator {
|
|
|
|
public:
|
2018-11-16 21:43:08 +01:00
|
|
|
RewriteMutator(parser::Messages &messages) : messages_{messages} {}
|
2018-08-29 20:38:12 +02:00
|
|
|
|
2018-04-19 00:06:35 +02:00
|
|
|
// Default action for a parse tree node is to visit children.
|
|
|
|
template<typename T> bool Pre(T &) { return true; }
|
|
|
|
template<typename T> void Post(T &) {}
|
|
|
|
|
2018-09-06 22:44:21 +02:00
|
|
|
void Post(parser::Name &);
|
|
|
|
void Post(parser::SpecificationPart &);
|
|
|
|
bool Pre(parser::ExecutionPart &);
|
2018-04-23 21:33:10 +02:00
|
|
|
|
2018-10-11 01:20:46 +02:00
|
|
|
// Name resolution yet implemented:
|
|
|
|
bool Pre(parser::EquivalenceStmt &) { return false; }
|
|
|
|
bool Pre(parser::Keyword &) { return false; }
|
|
|
|
bool Pre(parser::EntryStmt &) { return false; }
|
2019-02-18 20:39:46 +01:00
|
|
|
bool Pre(parser::CompilerDirective &) { return false; }
|
2018-10-11 01:20:46 +02:00
|
|
|
|
2018-08-29 20:38:12 +02:00
|
|
|
// Don't bother resolving names in end statements.
|
|
|
|
bool Pre(parser::EndBlockDataStmt &) { return false; }
|
|
|
|
bool Pre(parser::EndFunctionStmt &) { return false; }
|
|
|
|
bool Pre(parser::EndModuleStmt &) { return false; }
|
|
|
|
bool Pre(parser::EndMpSubprogramStmt &) { return false; }
|
|
|
|
bool Pre(parser::EndProgramStmt &) { return false; }
|
|
|
|
bool Pre(parser::EndSubmoduleStmt &) { return false; }
|
|
|
|
bool Pre(parser::EndSubroutineStmt &) { return false; }
|
|
|
|
bool Pre(parser::EndTypeStmt &) { return false; }
|
|
|
|
|
2018-04-19 00:06:35 +02:00
|
|
|
private:
|
2018-09-06 22:44:21 +02:00
|
|
|
using stmtFuncType =
|
|
|
|
parser::Statement<common::Indirection<parser::StmtFunctionStmt>>;
|
2018-08-29 20:38:12 +02:00
|
|
|
bool errorOnUnresolvedName_{true};
|
2018-09-15 00:04:50 +02:00
|
|
|
parser::Messages &messages_;
|
2018-09-06 22:44:21 +02:00
|
|
|
std::list<stmtFuncType> stmtFuncsToConvert_;
|
2018-04-19 00:06:35 +02:00
|
|
|
};
|
|
|
|
|
2018-11-16 21:43:08 +01:00
|
|
|
// Check that name has been resolved to a symbol
|
2018-09-06 22:44:21 +02:00
|
|
|
void RewriteMutator::Post(parser::Name &name) {
|
2018-11-16 21:43:08 +01:00
|
|
|
if (name.symbol == nullptr && errorOnUnresolvedName_) {
|
2019-02-11 19:58:20 +01:00
|
|
|
messages_.Say(name.source, "Internal: no symbol found for '%s'"_err_en_US,
|
2018-09-06 22:44:21 +02:00
|
|
|
name.ToString().c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find mis-parsed statement functions and move to stmtFuncsToConvert_ list.
|
|
|
|
void RewriteMutator::Post(parser::SpecificationPart &x) {
|
|
|
|
auto &list{std::get<std::list<parser::DeclarationConstruct>>(x.t)};
|
|
|
|
for (auto it{list.begin()}; it != list.end();) {
|
|
|
|
if (auto stmt{std::get_if<stmtFuncType>(&it->u)}) {
|
2019-03-05 21:28:08 +01:00
|
|
|
Symbol *symbol{std::get<parser::Name>(stmt->statement.value().t).symbol};
|
2018-09-06 22:44:21 +02:00
|
|
|
if (symbol && symbol->has<ObjectEntityDetails>()) {
|
|
|
|
// not a stmt func: remove it here and add to ones to convert
|
|
|
|
stmtFuncsToConvert_.push_back(std::move(*stmt));
|
|
|
|
it = list.erase(it);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert converted assignments at start of ExecutionPart.
|
|
|
|
bool RewriteMutator::Pre(parser::ExecutionPart &x) {
|
|
|
|
auto origFirst{x.v.begin()}; // insert each elem before origFirst
|
|
|
|
for (stmtFuncType &sf : stmtFuncsToConvert_) {
|
2019-03-05 21:28:08 +01:00
|
|
|
auto &&stmt = sf.statement.value().ConvertToAssignment();
|
2018-09-06 22:44:21 +02:00
|
|
|
stmt.source = sf.source;
|
|
|
|
x.v.insert(origFirst,
|
|
|
|
parser::ExecutionPartConstruct{parser::ExecutableConstruct{stmt}});
|
|
|
|
}
|
|
|
|
stmtFuncsToConvert_.clear();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-07 02:07:25 +01:00
|
|
|
bool RewriteParseTree(SemanticsContext &context, parser::Program &program) {
|
2018-11-16 21:43:08 +01:00
|
|
|
RewriteMutator mutator{context.messages()};
|
2018-04-19 00:06:35 +02:00
|
|
|
parser::Walk(program, mutator);
|
2019-03-07 02:07:25 +01:00
|
|
|
return !context.AnyFatalError();
|
2018-04-19 00:06:35 +02:00
|
|
|
}
|
2019-03-07 02:07:25 +01:00
|
|
|
|
2018-10-25 14:55:23 +02:00
|
|
|
}
|