2018-06-27 00:18:53 +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.
|
|
|
|
|
|
|
|
#ifndef FORTRAN_EVALUATE_VARIABLE_H_
|
|
|
|
#define FORTRAN_EVALUATE_VARIABLE_H_
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// Defines data structures to represent data access and function calls
|
|
|
|
// for use in expressions and assignment statements. Both copy and move
|
|
|
|
// semantics are supported. The representation adheres closely to the
|
|
|
|
// Fortran 2018 language standard (q.v.) and uses strong typing to ensure
|
|
|
|
// that only admissable combinations can be constructed.
|
|
|
|
|
2018-10-10 19:48:12 +02:00
|
|
|
#include "call.h"
|
2018-07-07 00:12:33 +02:00
|
|
|
#include "common.h"
|
2018-07-11 23:50:08 +02:00
|
|
|
#include "intrinsics.h"
|
2018-08-14 23:35:51 +02:00
|
|
|
#include "type.h"
|
2018-07-07 00:12:33 +02:00
|
|
|
#include "../common/idioms.h"
|
2018-09-15 00:48:40 +02:00
|
|
|
#include "../lib/common/template.h"
|
2018-07-07 00:12:33 +02:00
|
|
|
#include "../semantics/symbol.h"
|
2018-06-27 00:18:53 +02:00
|
|
|
#include <optional>
|
2018-07-07 00:12:33 +02:00
|
|
|
#include <ostream>
|
2018-06-27 00:18:53 +02:00
|
|
|
#include <variant>
|
2018-07-04 00:14:48 +02:00
|
|
|
#include <vector>
|
2018-06-27 00:18:53 +02:00
|
|
|
|
|
|
|
namespace Fortran::evaluate {
|
|
|
|
|
2018-07-04 00:14:48 +02:00
|
|
|
using semantics::Symbol;
|
2018-06-27 00:18:53 +02:00
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// Forward declarations
|
2018-09-15 00:48:40 +02:00
|
|
|
struct DataRef;
|
2018-09-20 21:34:29 +02:00
|
|
|
template<typename A> struct Variable;
|
2018-07-09 21:46:51 +02:00
|
|
|
|
|
|
|
// Subscript and cosubscript expressions are of a kind that matches the
|
|
|
|
// address size, at least at the top level.
|
2018-08-14 22:39:59 +02:00
|
|
|
using IndirectSubscriptIntegerExpr =
|
|
|
|
CopyableIndirection<Expr<SubscriptInteger>>;
|
2018-07-09 21:46:51 +02:00
|
|
|
|
|
|
|
// R913 structure-component & C920: Defined to be a multi-part
|
|
|
|
// data-ref whose last part has no subscripts (or image-selector, although
|
|
|
|
// that isn't explicit in the document). Pointer and allocatable components
|
2018-09-18 18:34:59 +02:00
|
|
|
// are not explicitly indirected in this representation (TODO: yet?)
|
2018-07-09 21:46:51 +02:00
|
|
|
// Complex components (%RE, %IM) are isolated below in ComplexPart.
|
2018-07-12 18:40:18 +02:00
|
|
|
class Component {
|
|
|
|
public:
|
2018-07-07 00:12:33 +02:00
|
|
|
CLASS_BOILERPLATE(Component)
|
2018-07-12 18:40:18 +02:00
|
|
|
Component(const DataRef &b, const Symbol &c) : base_{b}, symbol_{&c} {}
|
|
|
|
Component(DataRef &&b, const Symbol &c) : base_{std::move(b)}, symbol_{&c} {}
|
2018-07-10 01:23:12 +02:00
|
|
|
Component(CopyableIndirection<DataRef> &&b, const Symbol &c)
|
2018-07-12 18:40:18 +02:00
|
|
|
: base_{std::move(b)}, symbol_{&c} {}
|
2018-09-15 00:48:40 +02:00
|
|
|
|
2018-07-12 18:40:18 +02:00
|
|
|
const DataRef &base() const { return *base_; }
|
|
|
|
DataRef &base() { return *base_; }
|
|
|
|
const Symbol &symbol() const { return *symbol_; }
|
2018-09-18 18:34:59 +02:00
|
|
|
int Rank() const;
|
2018-09-19 23:27:13 +02:00
|
|
|
const Symbol *GetSymbol(bool first) const;
|
2018-08-14 22:39:59 +02:00
|
|
|
Expr<SubscriptInteger> LEN() const;
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-13 01:58:21 +02:00
|
|
|
|
2018-07-12 18:40:18 +02:00
|
|
|
private:
|
|
|
|
CopyableIndirection<DataRef> base_;
|
|
|
|
const Symbol *symbol_;
|
2018-06-27 00:18:53 +02:00
|
|
|
};
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// R921 subscript-triplet
|
2018-07-13 01:07:43 +02:00
|
|
|
class Triplet {
|
|
|
|
public:
|
2018-09-15 02:01:55 +02:00
|
|
|
Triplet() {}
|
|
|
|
DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(Triplet)
|
2018-08-14 22:39:59 +02:00
|
|
|
Triplet(std::optional<Expr<SubscriptInteger>> &&,
|
|
|
|
std::optional<Expr<SubscriptInteger>> &&,
|
|
|
|
std::optional<Expr<SubscriptInteger>> &&);
|
|
|
|
std::optional<Expr<SubscriptInteger>> lower() const;
|
|
|
|
std::optional<Expr<SubscriptInteger>> upper() const;
|
|
|
|
std::optional<Expr<SubscriptInteger>> stride() const;
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-13 01:58:21 +02:00
|
|
|
|
2018-07-13 01:07:43 +02:00
|
|
|
private:
|
|
|
|
std::optional<IndirectSubscriptIntegerExpr> lower_, upper_, stride_;
|
2018-06-27 00:18:53 +02:00
|
|
|
};
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// R919 subscript when rank 0, R923 vector-subscript when rank 1
|
2018-09-15 00:48:40 +02:00
|
|
|
struct Subscript {
|
|
|
|
EVALUATE_UNION_CLASS_BOILERPLATE(Subscript)
|
2018-08-14 22:39:59 +02:00
|
|
|
explicit Subscript(Expr<SubscriptInteger> &&s)
|
2018-09-15 00:48:40 +02:00
|
|
|
: u{IndirectSubscriptIntegerExpr::Make(std::move(s))} {}
|
2018-09-18 18:34:59 +02:00
|
|
|
int Rank() const;
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-09-15 00:48:40 +02:00
|
|
|
std::variant<IndirectSubscriptIntegerExpr, Triplet> u;
|
2018-06-27 00:18:53 +02:00
|
|
|
};
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// R917 array-element, R918 array-section; however, the case of an
|
|
|
|
// array-section that is a complex-part-designator is represented here
|
|
|
|
// as a ComplexPart instead. C919 & C925 require that at most one set of
|
|
|
|
// subscripts have rank greater than 0, but that is not explicit in
|
|
|
|
// these types.
|
2018-09-15 00:48:40 +02:00
|
|
|
struct ArrayRef {
|
2018-07-07 00:12:33 +02:00
|
|
|
CLASS_BOILERPLATE(ArrayRef)
|
|
|
|
ArrayRef(const Symbol &n, std::vector<Subscript> &&ss)
|
2018-09-15 00:48:40 +02:00
|
|
|
: u{&n}, subscript(std::move(ss)) {}
|
2018-07-07 00:12:33 +02:00
|
|
|
ArrayRef(Component &&c, std::vector<Subscript> &&ss)
|
2018-09-15 00:48:40 +02:00
|
|
|
: u{std::move(c)}, subscript(std::move(ss)) {}
|
2018-09-18 18:34:59 +02:00
|
|
|
|
|
|
|
int Rank() const;
|
2018-09-19 23:27:13 +02:00
|
|
|
const Symbol *GetSymbol(bool first) const;
|
2018-08-14 22:39:59 +02:00
|
|
|
Expr<SubscriptInteger> LEN() const;
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-13 01:58:21 +02:00
|
|
|
|
2018-09-15 00:48:40 +02:00
|
|
|
std::variant<const Symbol *, Component> u;
|
|
|
|
std::vector<Subscript> subscript;
|
2018-06-27 00:18:53 +02:00
|
|
|
};
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// R914 coindexed-named-object
|
|
|
|
// R924 image-selector, R926 image-selector-spec.
|
|
|
|
// C824 severely limits the usage of derived types with coarray ultimate
|
|
|
|
// components: they can't be pointers, allocatables, arrays, coarrays, or
|
|
|
|
// function results. They can be components of other derived types.
|
|
|
|
// C930 precludes having both TEAM= and TEAM_NUMBER=.
|
|
|
|
// TODO C931 prohibits the use of a coindexed object as a stat-variable.
|
2018-07-13 01:07:43 +02:00
|
|
|
class CoarrayRef {
|
|
|
|
public:
|
2018-07-07 00:12:33 +02:00
|
|
|
CLASS_BOILERPLATE(CoarrayRef)
|
2018-07-11 23:50:08 +02:00
|
|
|
CoarrayRef(std::vector<const Symbol *> &&,
|
2018-08-14 22:39:59 +02:00
|
|
|
std::vector<Expr<SubscriptInteger>> &&,
|
2018-10-16 22:24:57 +02:00
|
|
|
std::vector<Expr<SubscriptInteger>> &&);
|
|
|
|
// These integral expressions for STAT= and TEAM= must be variables
|
|
|
|
// (i.e., Designator or pointer-valued FunctionRef).
|
|
|
|
CoarrayRef &set_stat(Expr<SomeInteger> &&);
|
|
|
|
CoarrayRef &set_team(Expr<SomeInteger> &&, bool isTeamNumber = false);
|
2018-09-19 23:27:13 +02:00
|
|
|
|
2018-09-18 18:34:59 +02:00
|
|
|
int Rank() const;
|
2018-09-19 23:27:13 +02:00
|
|
|
const Symbol *GetSymbol(bool first) const {
|
|
|
|
if (first) {
|
|
|
|
return base_.front();
|
|
|
|
} else {
|
|
|
|
return base_.back();
|
|
|
|
}
|
|
|
|
}
|
2018-08-14 22:39:59 +02:00
|
|
|
Expr<SubscriptInteger> LEN() const;
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-13 01:58:21 +02:00
|
|
|
|
2018-07-13 01:07:43 +02:00
|
|
|
private:
|
|
|
|
std::vector<const Symbol *> base_;
|
2018-08-14 22:39:59 +02:00
|
|
|
std::vector<Expr<SubscriptInteger>> subscript_, cosubscript_;
|
2018-10-16 22:24:57 +02:00
|
|
|
std::optional<CopyableIndirection<Expr<SomeInteger>>> stat_, team_;
|
2018-07-13 01:07:43 +02:00
|
|
|
bool teamIsTeamNumber_{false}; // false: TEAM=, true: TEAM_NUMBER=
|
2018-07-04 00:14:48 +02:00
|
|
|
};
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// R911 data-ref is defined syntactically as a series of part-refs, which
|
2018-07-11 23:50:08 +02:00
|
|
|
// would be far too expressive if the constraints were ignored. Here, the
|
|
|
|
// possible outcomes are spelled out. Note that a data-ref cannot include
|
|
|
|
// a terminal substring range or complex component designator; use
|
|
|
|
// R901 designator for that.
|
2018-09-15 00:48:40 +02:00
|
|
|
struct DataRef {
|
|
|
|
EVALUATE_UNION_CLASS_BOILERPLATE(DataRef)
|
|
|
|
explicit DataRef(const Symbol &n) : u{&n} {}
|
2018-09-18 18:34:59 +02:00
|
|
|
|
|
|
|
int Rank() const;
|
2018-09-19 23:27:13 +02:00
|
|
|
const Symbol *GetSymbol(bool first) const;
|
2018-08-14 22:39:59 +02:00
|
|
|
Expr<SubscriptInteger> LEN() const;
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-13 01:58:21 +02:00
|
|
|
|
2018-09-15 00:48:40 +02:00
|
|
|
std::variant<const Symbol *, Component, ArrayRef, CoarrayRef> u;
|
2018-07-04 00:14:48 +02:00
|
|
|
};
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// R908 substring, R909 parent-string, R910 substring-range.
|
|
|
|
// The base object of a substring can be a literal.
|
|
|
|
// In the F2018 standard, substrings of array sections are parsed as
|
|
|
|
// variants of sections instead.
|
2018-07-13 01:58:21 +02:00
|
|
|
class Substring {
|
|
|
|
public:
|
2018-08-29 00:15:18 +02:00
|
|
|
using IsFoldableTrait = std::true_type;
|
2018-07-07 00:12:33 +02:00
|
|
|
CLASS_BOILERPLATE(Substring)
|
2018-08-14 22:39:59 +02:00
|
|
|
Substring(DataRef &&, std::optional<Expr<SubscriptInteger>> &&,
|
|
|
|
std::optional<Expr<SubscriptInteger>> &&);
|
|
|
|
Substring(std::string &&, std::optional<Expr<SubscriptInteger>> &&,
|
|
|
|
std::optional<Expr<SubscriptInteger>> &&);
|
|
|
|
|
|
|
|
Expr<SubscriptInteger> first() const;
|
|
|
|
Expr<SubscriptInteger> last() const;
|
2018-09-18 18:34:59 +02:00
|
|
|
int Rank() const;
|
2018-09-19 23:27:13 +02:00
|
|
|
const Symbol *GetSymbol(bool first) const;
|
2018-08-14 22:39:59 +02:00
|
|
|
Expr<SubscriptInteger> LEN() const;
|
2018-08-08 20:29:05 +02:00
|
|
|
std::optional<std::string> Fold(FoldingContext &);
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-11 23:50:08 +02:00
|
|
|
|
2018-07-13 01:58:21 +02:00
|
|
|
private:
|
2018-09-08 01:54:33 +02:00
|
|
|
// TODO: character kinds > 1
|
2018-07-13 01:58:21 +02:00
|
|
|
std::variant<DataRef, std::string> u_;
|
|
|
|
std::optional<IndirectSubscriptIntegerExpr> first_, last_;
|
2018-07-04 00:14:48 +02:00
|
|
|
};
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// R915 complex-part-designator
|
|
|
|
// In the F2018 standard, complex parts of array sections are parsed as
|
|
|
|
// variants of sections instead.
|
2018-07-13 01:58:21 +02:00
|
|
|
class ComplexPart {
|
|
|
|
public:
|
2018-07-07 00:12:33 +02:00
|
|
|
ENUM_CLASS(Part, RE, IM)
|
|
|
|
CLASS_BOILERPLATE(ComplexPart)
|
2018-07-13 01:58:21 +02:00
|
|
|
ComplexPart(DataRef &&z, Part p) : complex_{std::move(z)}, part_{p} {}
|
|
|
|
const DataRef &complex() const { return complex_; }
|
|
|
|
Part part() const { return part_; }
|
2018-09-18 18:34:59 +02:00
|
|
|
int Rank() const;
|
2018-09-19 23:27:13 +02:00
|
|
|
const Symbol *GetSymbol(bool first) const {
|
|
|
|
return complex_.GetSymbol(first);
|
|
|
|
}
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-13 01:58:21 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
DataRef complex_;
|
|
|
|
Part part_;
|
2018-06-27 00:18:53 +02:00
|
|
|
};
|
|
|
|
|
2018-07-09 21:46:51 +02:00
|
|
|
// R901 designator is the most general data reference object, apart from
|
2018-09-15 00:48:40 +02:00
|
|
|
// calls to pointer-valued functions. Its variant holds everything that
|
2018-10-09 00:35:19 +02:00
|
|
|
// a DataRef can, and possibly either a substring reference or a complex
|
|
|
|
// part (%RE/%IM) reference.
|
2018-09-15 00:48:40 +02:00
|
|
|
template<typename A> class Designator {
|
|
|
|
using DataRefs = decltype(DataRef::u);
|
|
|
|
using MaybeSubstring =
|
|
|
|
std::conditional_t<A::category == TypeCategory::Character,
|
|
|
|
std::variant<Substring>, std::variant<>>;
|
|
|
|
using MaybeComplexPart = std::conditional_t<A::category == TypeCategory::Real,
|
|
|
|
std::variant<ComplexPart>, std::variant<>>;
|
|
|
|
using Variant =
|
|
|
|
common::CombineVariants<DataRefs, MaybeSubstring, MaybeComplexPart>;
|
|
|
|
|
2018-07-13 01:58:21 +02:00
|
|
|
public:
|
2018-09-15 00:48:40 +02:00
|
|
|
using Result = A;
|
2018-10-09 21:07:29 +02:00
|
|
|
static_assert(Result::isSpecificIntrinsicType ||
|
|
|
|
std::is_same_v<Result, SomeKind<TypeCategory::Derived>>);
|
2018-09-15 00:48:40 +02:00
|
|
|
EVALUATE_UNION_CLASS_BOILERPLATE(Designator)
|
2018-10-09 00:35:19 +02:00
|
|
|
Designator(const DataRef &that) : u{common::MoveVariant<Variant>(that.u)} {}
|
|
|
|
Designator(DataRef &&that)
|
2018-09-15 00:48:40 +02:00
|
|
|
: u{common::MoveVariant<Variant>(std::move(that.u))} {}
|
2018-10-09 00:35:19 +02:00
|
|
|
|
|
|
|
std::optional<DynamicType> GetType() const {
|
|
|
|
if constexpr (std::is_same_v<Result, SomeDerived>) {
|
|
|
|
if (const Symbol * sym{GetSymbol(false)}) {
|
|
|
|
return GetSymbolType(*sym);
|
|
|
|
} else {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Result::GetType();
|
|
|
|
}
|
2018-09-15 00:48:40 +02:00
|
|
|
}
|
2018-07-13 01:58:21 +02:00
|
|
|
|
2018-09-18 18:34:59 +02:00
|
|
|
int Rank() const {
|
|
|
|
return std::visit(
|
|
|
|
common::visitors{[](const Symbol *sym) { return sym->Rank(); },
|
|
|
|
[](const auto &x) { return x.Rank(); }},
|
|
|
|
u);
|
|
|
|
}
|
|
|
|
|
2018-09-19 23:27:13 +02:00
|
|
|
const Symbol *GetSymbol(bool first) const {
|
|
|
|
return std::visit(common::visitors{[](const Symbol *sym) { return sym; },
|
|
|
|
[=](const auto &x) { return x.GetSymbol(first); }},
|
|
|
|
u);
|
|
|
|
}
|
|
|
|
|
2018-09-15 00:48:40 +02:00
|
|
|
Expr<SubscriptInteger> LEN() const;
|
2018-09-18 18:34:59 +02:00
|
|
|
|
2018-09-15 00:48:40 +02:00
|
|
|
std::ostream &Dump(std::ostream &o) const {
|
|
|
|
std::visit(common::visitors{[&](const Symbol *sym) {
|
|
|
|
o << sym->name().ToString();
|
|
|
|
},
|
|
|
|
[&](const auto &x) { x.Dump(o); }},
|
|
|
|
u);
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
Variant u;
|
2018-06-27 00:18:53 +02:00
|
|
|
};
|
|
|
|
|
2018-10-10 19:48:12 +02:00
|
|
|
FOR_EACH_CHARACTER_KIND(extern template class Designator)
|
|
|
|
|
2018-09-15 00:48:40 +02:00
|
|
|
struct ProcedureDesignator {
|
|
|
|
EVALUATE_UNION_CLASS_BOILERPLATE(ProcedureDesignator)
|
2018-10-11 23:51:14 +02:00
|
|
|
explicit ProcedureDesignator(SpecificIntrinsic &&i) : u{std::move(i)} {}
|
2018-09-15 00:48:40 +02:00
|
|
|
explicit ProcedureDesignator(const Symbol &n) : u{&n} {}
|
2018-10-11 23:51:14 +02:00
|
|
|
std::optional<DynamicType> GetType() const;
|
2018-09-20 21:34:29 +02:00
|
|
|
int Rank() const;
|
2018-10-11 23:51:14 +02:00
|
|
|
bool IsElemental() const;
|
|
|
|
Expr<SubscriptInteger> LEN() const;
|
2018-09-20 21:34:29 +02:00
|
|
|
const Symbol *GetSymbol() const;
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-13 01:58:21 +02:00
|
|
|
|
2018-10-11 23:51:14 +02:00
|
|
|
std::variant<SpecificIntrinsic, const Symbol *, Component> u;
|
2018-07-04 00:14:48 +02:00
|
|
|
};
|
|
|
|
|
2018-09-20 21:34:29 +02:00
|
|
|
class UntypedFunctionRef {
|
2018-07-13 01:58:21 +02:00
|
|
|
public:
|
2018-09-20 21:34:29 +02:00
|
|
|
CLASS_BOILERPLATE(UntypedFunctionRef)
|
2018-10-18 00:09:48 +02:00
|
|
|
UntypedFunctionRef(ProcedureDesignator &&p, ActualArguments &&a)
|
2018-09-20 21:34:29 +02:00
|
|
|
: proc_{std::move(p)}, arguments_(std::move(a)) {}
|
|
|
|
|
2018-07-13 01:58:21 +02:00
|
|
|
const ProcedureDesignator &proc() const { return proc_; }
|
2018-10-18 00:09:48 +02:00
|
|
|
const ActualArguments &arguments() const { return arguments_; }
|
2018-09-20 21:34:29 +02:00
|
|
|
|
|
|
|
Expr<SubscriptInteger> LEN() const;
|
2018-10-11 23:51:14 +02:00
|
|
|
int Rank() const { return proc_.Rank(); }
|
|
|
|
bool IsElemental() const { return proc_.IsElemental(); }
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-13 01:58:21 +02:00
|
|
|
|
2018-09-20 21:34:29 +02:00
|
|
|
protected:
|
2018-07-13 01:58:21 +02:00
|
|
|
ProcedureDesignator proc_;
|
2018-10-18 00:09:48 +02:00
|
|
|
ActualArguments arguments_;
|
2018-06-27 00:18:53 +02:00
|
|
|
};
|
|
|
|
|
2018-09-20 21:34:29 +02:00
|
|
|
template<typename A> struct FunctionRef : public UntypedFunctionRef {
|
|
|
|
using Result = A;
|
2018-10-09 21:07:29 +02:00
|
|
|
static_assert(Result::isSpecificIntrinsicType ||
|
|
|
|
std::is_same_v<Result, SomeKind<TypeCategory::Derived>>);
|
2018-09-20 21:34:29 +02:00
|
|
|
CLASS_BOILERPLATE(FunctionRef)
|
2018-10-09 00:35:19 +02:00
|
|
|
FunctionRef(UntypedFunctionRef &&ufr) : UntypedFunctionRef{std::move(ufr)} {}
|
2018-10-18 00:09:48 +02:00
|
|
|
FunctionRef(ProcedureDesignator &&p, ActualArguments &&a)
|
2018-10-11 23:51:14 +02:00
|
|
|
: UntypedFunctionRef{std::move(p), std::move(a)} {}
|
2018-10-09 00:35:19 +02:00
|
|
|
std::optional<DynamicType> GetType() const {
|
|
|
|
if constexpr (std::is_same_v<Result, SomeDerived>) {
|
|
|
|
if (const Symbol * symbol{proc_.GetSymbol()}) {
|
|
|
|
return GetSymbolType(*symbol);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Result::GetType();
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
2018-10-11 23:51:14 +02:00
|
|
|
std::optional<Constant<Result>> Fold(FoldingContext &); // for intrinsics
|
2018-09-20 21:34:29 +02:00
|
|
|
};
|
2018-07-07 01:59:05 +02:00
|
|
|
|
2018-10-10 19:48:12 +02:00
|
|
|
FOR_EACH_SPECIFIC_TYPE(extern template struct FunctionRef)
|
|
|
|
|
2018-09-20 21:34:29 +02:00
|
|
|
template<typename A> struct Variable {
|
|
|
|
using Result = A;
|
2018-10-09 21:07:29 +02:00
|
|
|
static_assert(Result::isSpecificIntrinsicType ||
|
|
|
|
std::is_same_v<Result, SomeKind<TypeCategory::Derived>>);
|
2018-09-15 00:48:40 +02:00
|
|
|
EVALUATE_UNION_CLASS_BOILERPLATE(Variable)
|
2018-10-09 00:35:19 +02:00
|
|
|
std::optional<DynamicType> GetType() const {
|
|
|
|
return std::visit([](const auto &x) { return x.GetType(); }, u);
|
|
|
|
}
|
2018-09-20 21:34:29 +02:00
|
|
|
int Rank() const {
|
|
|
|
return std::visit([](const auto &x) { return x.Rank(); }, u);
|
|
|
|
}
|
|
|
|
std::ostream &Dump(std::ostream &o) const {
|
|
|
|
std::visit([&](const auto &x) { x.Dump(o); }, u);
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
std::variant<Designator<Result>, FunctionRef<Result>> u;
|
2018-07-07 01:59:05 +02:00
|
|
|
};
|
|
|
|
|
2018-07-07 00:12:33 +02:00
|
|
|
struct Label { // TODO: this is a placeholder
|
|
|
|
CLASS_BOILERPLATE(Label)
|
|
|
|
explicit Label(int lab) : label{lab} {}
|
|
|
|
int label;
|
2018-08-17 18:50:32 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-07-07 00:12:33 +02:00
|
|
|
};
|
|
|
|
|
2018-09-20 21:34:29 +02:00
|
|
|
class SubroutineCall {
|
|
|
|
public:
|
|
|
|
CLASS_BOILERPLATE(SubroutineCall)
|
2018-10-18 00:09:48 +02:00
|
|
|
SubroutineCall(ProcedureDesignator &&p, ActualArguments &&a)
|
2018-09-20 21:34:29 +02:00
|
|
|
: proc_{std::move(p)}, arguments_(std::move(a)) {}
|
|
|
|
const ProcedureDesignator &proc() const { return proc_; }
|
2018-10-18 00:09:48 +02:00
|
|
|
const ActualArguments &arguments() const { return arguments_; }
|
2018-09-20 21:34:29 +02:00
|
|
|
int Rank() const { return 0; } // TODO: elemental subroutine representation
|
|
|
|
std::ostream &Dump(std::ostream &) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
ProcedureDesignator proc_;
|
2018-10-18 00:09:48 +02:00
|
|
|
ActualArguments arguments_;
|
2018-09-20 21:34:29 +02:00
|
|
|
};
|
2018-10-25 14:55:23 +02:00
|
|
|
}
|
2018-06-27 00:18:53 +02:00
|
|
|
#endif // FORTRAN_EVALUATE_VARIABLE_H_
|