2018-07-14 01:55:11 +02:00
|
|
|
// Copyright (c) 2018, 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.
|
|
|
|
|
|
|
|
#include "expression.h"
|
|
|
|
#include "../common/idioms.h"
|
|
|
|
|
|
|
|
using namespace Fortran::parser::literals;
|
|
|
|
|
|
|
|
namespace Fortran::semantics {
|
|
|
|
|
2018-07-19 18:53:42 +02:00
|
|
|
template<typename A>
|
2018-07-19 19:12:25 +02:00
|
|
|
std::optional<evaluate::GenericExpr> AnalyzeHelper(
|
|
|
|
ExpressionAnalyzer &ea, const A &tree) {
|
2018-07-19 18:53:42 +02:00
|
|
|
return ea.Analyze(tree);
|
2018-07-14 01:55:11 +02:00
|
|
|
}
|
|
|
|
|
2018-07-19 18:53:42 +02:00
|
|
|
template<typename A>
|
2018-07-19 19:12:25 +02:00
|
|
|
std::optional<evaluate::GenericExpr> AnalyzeHelper(
|
|
|
|
ExpressionAnalyzer &ea, const parser::Scalar<A> &tree) {
|
2018-07-19 18:53:42 +02:00
|
|
|
std::optional<evaluate::GenericExpr> result{AnalyzeHelper(ea, tree.thing)};
|
|
|
|
if (result.has_value()) {
|
|
|
|
if (result->Rank() > 1) {
|
|
|
|
ea.Say("must be scalar"_err_en_US);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename A>
|
2018-07-19 19:12:25 +02:00
|
|
|
std::optional<evaluate::GenericExpr> AnalyzeHelper(
|
|
|
|
ExpressionAnalyzer &ea, const parser::Constant<A> &tree) {
|
2018-07-19 18:53:42 +02:00
|
|
|
std::optional<evaluate::GenericExpr> result{AnalyzeHelper(ea, tree.thing)};
|
|
|
|
if (result.has_value()) {
|
|
|
|
result->Fold(ea.context());
|
|
|
|
if (!result->ConstantValue().has_value()) {
|
|
|
|
ea.Say("must be constant"_err_en_US);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename A>
|
2018-07-19 19:12:25 +02:00
|
|
|
std::optional<evaluate::GenericExpr> AnalyzeHelper(
|
|
|
|
ExpressionAnalyzer &ea, const parser::Integer<A> &tree) {
|
2018-07-19 18:53:42 +02:00
|
|
|
std::optional<evaluate::GenericExpr> result{AnalyzeHelper(ea, tree.thing)};
|
2018-07-19 19:12:25 +02:00
|
|
|
if (result.has_value() &&
|
|
|
|
!std::holds_alternative<evaluate::GenericIntegerExpr>(result->u)) {
|
2018-07-19 18:53:42 +02:00
|
|
|
ea.Say("must be integer"_err_en_US);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-07-19 19:12:25 +02:00
|
|
|
template<>
|
|
|
|
std::optional<evaluate::GenericExpr> AnalyzeHelper(
|
|
|
|
ExpressionAnalyzer &ea, const parser::Name &n) {
|
2018-07-19 18:53:42 +02:00
|
|
|
// TODO
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2018-07-19 19:12:25 +02:00
|
|
|
ExpressionAnalyzer::KindParam ExpressionAnalyzer::Analyze(
|
|
|
|
const std::optional<parser::KindParam> &kindParam, KindParam defaultKind,
|
|
|
|
KindParam kanjiKind) {
|
2018-07-19 18:53:42 +02:00
|
|
|
if (!kindParam.has_value()) {
|
|
|
|
return defaultKind;
|
2018-07-14 01:55:11 +02:00
|
|
|
}
|
2018-07-19 19:12:25 +02:00
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
|
|
|
[](std::uint64_t k) { return static_cast<KindParam>(k); },
|
|
|
|
[&](const parser::Scalar<
|
|
|
|
parser::Integer<parser::Constant<parser::Name>>> &n) {
|
|
|
|
if (std::optional<evaluate::GenericExpr> oge{
|
|
|
|
AnalyzeHelper(*this, n)}) {
|
|
|
|
if (std::optional<evaluate::GenericConstant> ogc{
|
|
|
|
oge->ConstantValue()}) {
|
|
|
|
// TODO pmk more here next
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return defaultKind;
|
|
|
|
},
|
|
|
|
[&](parser::KindParam::Kanji) {
|
|
|
|
if (kanjiKind >= 0) {
|
|
|
|
return kanjiKind;
|
|
|
|
}
|
|
|
|
Say("Kanji not allowed here"_err_en_US);
|
|
|
|
return defaultKind;
|
|
|
|
}},
|
|
|
|
kindParam->u);
|
2018-07-19 18:53:42 +02:00
|
|
|
}
|
|
|
|
|
2018-07-19 19:12:25 +02:00
|
|
|
template<>
|
|
|
|
std::optional<evaluate::GenericExpr> AnalyzeHelper(
|
|
|
|
ExpressionAnalyzer &ea, const parser::IntLiteralConstant &x) {
|
2018-07-19 18:53:42 +02:00
|
|
|
auto kind{ea.Analyze(std::get<std::optional<parser::KindParam>>(x.t),
|
2018-07-19 19:12:25 +02:00
|
|
|
ea.defaultIntegerKind())};
|
2018-07-14 01:55:11 +02:00
|
|
|
std::uint64_t value{std::get<std::uint64_t>(x.t)};
|
|
|
|
switch (kind) {
|
2018-07-19 19:12:25 +02:00
|
|
|
#define CASE(k) \
|
|
|
|
case k: \
|
|
|
|
return {evaluate::GenericExpr{ \
|
|
|
|
evaluate::GenericIntegerExpr{evaluate::IntegerExpr<k>{value}}}};
|
|
|
|
FOR_EACH_INTEGER_KIND(CASE, )
|
2018-07-19 18:53:42 +02:00
|
|
|
#undef CASE
|
2018-07-14 01:55:11 +02:00
|
|
|
default:
|
2018-07-19 18:53:42 +02:00
|
|
|
ea.Say(parser::MessageFormattedText{
|
2018-07-19 19:12:25 +02:00
|
|
|
"unimplemented INTEGER kind (%ju)"_err_en_US,
|
|
|
|
static_cast<std::uintmax_t>(kind)});
|
2018-07-14 01:55:11 +02:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-19 19:12:25 +02:00
|
|
|
template<>
|
|
|
|
std::optional<evaluate::GenericExpr> AnalyzeHelper(
|
|
|
|
ExpressionAnalyzer &ea, const parser::LiteralConstant &x) {
|
2018-07-14 01:55:11 +02:00
|
|
|
return std::visit(
|
2018-07-19 19:12:25 +02:00
|
|
|
common::visitors{[&](const parser::IntLiteralConstant &c) {
|
|
|
|
return AnalyzeHelper(ea, c);
|
|
|
|
},
|
|
|
|
// TODO next [&](const parser::RealLiteralConstant &c) { return
|
|
|
|
// AnalyzeHelper(ea, c); },
|
2018-07-19 18:53:42 +02:00
|
|
|
// TODO: remaining cases
|
|
|
|
[&](const auto &) { return std::optional<evaluate::GenericExpr>{}; }},
|
|
|
|
x.u);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<evaluate::GenericExpr> ExpressionAnalyzer::Analyze(
|
|
|
|
const parser::Expr &x) {
|
|
|
|
return std::visit(
|
2018-07-19 19:12:25 +02:00
|
|
|
common::visitors{[&](const parser::LiteralConstant &c) {
|
|
|
|
return AnalyzeHelper(*this, c);
|
|
|
|
},
|
2018-07-19 18:53:42 +02:00
|
|
|
// TODO: remaining cases
|
2018-07-14 01:55:11 +02:00
|
|
|
[&](const auto &) { return std::optional<evaluate::GenericExpr>{}; }},
|
|
|
|
x.u);
|
|
|
|
}
|
|
|
|
} // namespace Fortran::semantics
|