blob: 58e6fc70df45b5090c7cd12f62b9989db7aacf15 [file] [log] [blame]
peter klausler67f13ef2019-01-07 18:55:091// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
peter klausler42b33da2018-09-29 00:02:112//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "intrinsics.h"
peter klausler146e13c2019-04-18 21:11:1516#include "common.h"
peter klauslera62636f2018-10-08 22:35:1917#include "expression.h"
peter klauslerfe3acf5f2019-01-07 18:15:2718#include "fold.h"
peter klauslerb65572d2019-04-03 23:04:1319#include "shape.h"
peter klauslerabac2282018-10-26 22:10:2420#include "tools.h"
peter klausler42b33da2018-09-29 00:02:1121#include "type.h"
peter klauslerab74d1a2019-02-28 18:48:4122#include "../common/Fortran.h"
peter klausler42b33da2018-09-29 00:02:1123#include "../common/enum-set.h"
peter klauslera70f5962018-10-04 20:43:3324#include "../common/idioms.h"
peter klausler84ea49d2018-10-18 17:50:5525#include <algorithm>
peter klauslera70f5962018-10-04 20:43:3326#include <map>
peter klausler7bda1b32018-10-12 23:01:5527#include <ostream>
28#include <sstream>
peter klauslera70f5962018-10-04 20:43:3329#include <string>
30#include <utility>
peter klausler42b33da2018-09-29 00:02:1131
peter klauslercb308d32018-10-05 18:32:5432using namespace Fortran::parser::literals;
33
peter klausler42b33da2018-09-29 00:02:1134namespace Fortran::evaluate {
35
peter klausler146e13c2019-04-18 21:11:1536class FoldingContext;
peter klausler42b33da2018-09-29 00:02:1137
peter klauslera70f5962018-10-04 20:43:3338// This file defines the supported intrinsic procedures and implements
39// their recognition and validation. It is largely table-driven. See
40// documentation/intrinsics.md and section 16 of the Fortran 2018 standard
41// for full details on each of the intrinsics. Be advised, they have
42// complicated details, and the design of these tables has to accommodate
43// that complexity.
44
peter klausler42b33da2018-09-29 00:02:1145// Dummy arguments to generic intrinsic procedures are each specified by
peter klauslera70f5962018-10-04 20:43:3346// their keyword name (rarely used, but always defined), allowable type
peter klauslercb308d32018-10-05 18:32:5447// categories, a kind pattern, a rank pattern, and information about
48// optionality and defaults. The kind and rank patterns are represented
49// here with code values that are significant to the matching/validation engine.
peter klausler42b33da2018-09-29 00:02:1150
peter klauslera70f5962018-10-04 20:43:3351// These are small bit-sets of type category enumerators.
52// Note that typeless (BOZ literal) values don't have a distinct type category.
53// These typeless arguments are represented in the tables as if they were
54// INTEGER with a special "typeless" kind code. Arguments of intrinsic types
peter klausler25e6f032019-05-03 18:29:1555// that can also be typeless values are encoded with an "elementalOrBOZ"
peter klauslercb308d32018-10-05 18:32:5456// rank pattern.
peter klausler146e13c2019-04-18 21:11:1557// Assumed-type (TYPE(*)) dummy arguments can be forwarded along to some
58// intrinsic functions that accept AnyType + Rank::anyOrAssumedRank.
peter klauslera70f5962018-10-04 20:43:3359using CategorySet = common::EnumSet<TypeCategory, 8>;
peter klausler51b09b62018-10-15 19:17:3060static constexpr CategorySet IntType{TypeCategory::Integer};
61static constexpr CategorySet RealType{TypeCategory::Real};
62static constexpr CategorySet ComplexType{TypeCategory::Complex};
63static constexpr CategorySet CharType{TypeCategory::Character};
64static constexpr CategorySet LogicalType{TypeCategory::Logical};
65static constexpr CategorySet IntOrRealType{IntType | RealType};
66static constexpr CategorySet FloatingType{RealType | ComplexType};
67static constexpr CategorySet NumericType{IntType | RealType | ComplexType};
68static constexpr CategorySet RelatableType{IntType | RealType | CharType};
peter klauslera70f5962018-10-04 20:43:3369static constexpr CategorySet IntrinsicType{
peter klausler51b09b62018-10-15 19:17:3070 IntType | RealType | ComplexType | CharType | LogicalType};
peter klauslera70f5962018-10-04 20:43:3371static constexpr CategorySet AnyType{
72 IntrinsicType | CategorySet{TypeCategory::Derived}};
peter klausler42b33da2018-09-29 00:02:1173
peter klausler7bda1b32018-10-12 23:01:5574ENUM_CLASS(KindCode, none, defaultIntegerKind,
75 defaultRealKind, // is also the default COMPLEX kind
76 doublePrecision, defaultCharKind, defaultLogicalKind,
77 any, // matches any kind value; each instance is independent
peter klausler146e13c2019-04-18 21:11:1578 same, // match any kind, but all "same" kinds must be equal
peter klausler7bda1b32018-10-12 23:01:5579 typeless, // BOZ literals are INTEGER with this kind
80 teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
81 kindArg, // this argument is KIND=
82 effectiveKind, // for function results: same "kindArg", possibly defaulted
83 dimArg, // this argument is DIM=
peter klausler7bda1b32018-10-12 23:01:5584 likeMultiply, // for DOT_PRODUCT and MATMUL
85)
peter klausler42b33da2018-09-29 00:02:1186
87struct TypePattern {
88 CategorySet categorySet;
peter klauslerb22d4942018-10-01 18:27:4589 KindCode kindCode{KindCode::none};
peter klausler7bda1b32018-10-12 23:01:5590 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:1191};
92
peter klauslera70f5962018-10-04 20:43:3393// Abbreviations for argument and result patterns in the intrinsic prototypes:
94
95// Match specific kinds of intrinsic types
peter klausler7c402d92018-10-16 21:42:2296static constexpr TypePattern DefaultInt{IntType, KindCode::defaultIntegerKind};
97static constexpr TypePattern DefaultReal{RealType, KindCode::defaultRealKind};
98static constexpr TypePattern DefaultComplex{
99 ComplexType, KindCode::defaultRealKind};
100static constexpr TypePattern DefaultChar{CharType, KindCode::defaultCharKind};
101static constexpr TypePattern DefaultLogical{
peter klausler51b09b62018-10-15 19:17:30102 LogicalType, KindCode::defaultLogicalKind};
103static constexpr TypePattern BOZ{IntType, KindCode::typeless};
104static constexpr TypePattern TEAM_TYPE{IntType, KindCode::teamType};
105static constexpr TypePattern DoublePrecision{
106 RealType, KindCode::doublePrecision};
peter klauslera0e50522019-06-21 21:04:40107static constexpr TypePattern DoublePrecisionComplex{
108 ComplexType, KindCode::doublePrecision};
peter klauslera70f5962018-10-04 20:43:33109
110// Match any kind of some intrinsic or derived types
peter klausler51b09b62018-10-15 19:17:30111static constexpr TypePattern AnyInt{IntType, KindCode::any};
112static constexpr TypePattern AnyReal{RealType, KindCode::any};
113static constexpr TypePattern AnyIntOrReal{IntOrRealType, KindCode::any};
114static constexpr TypePattern AnyComplex{ComplexType, KindCode::any};
peter klauslerf4b12092019-05-29 22:38:33115static constexpr TypePattern AnyFloating{FloatingType, KindCode::any};
peter klausler51b09b62018-10-15 19:17:30116static constexpr TypePattern AnyNumeric{NumericType, KindCode::any};
117static constexpr TypePattern AnyChar{CharType, KindCode::any};
118static constexpr TypePattern AnyLogical{LogicalType, KindCode::any};
119static constexpr TypePattern AnyRelatable{RelatableType, KindCode::any};
peter klauslerbe3b7652018-12-04 18:55:32120static constexpr TypePattern AnyIntrinsic{IntrinsicType, KindCode::any};
peter klauslerf7f2a732018-10-09 19:07:29121static constexpr TypePattern Anything{AnyType, KindCode::any};
peter klauslera70f5962018-10-04 20:43:33122
123// Match some kind of some intrinsic type(s); all "Same" values must match,
124// even when not in the same category (e.g., SameComplex and SameReal).
125// Can be used to specify a result so long as at least one argument is
126// a "Same".
peter klausler51b09b62018-10-15 19:17:30127static constexpr TypePattern SameInt{IntType, KindCode::same};
128static constexpr TypePattern SameReal{RealType, KindCode::same};
129static constexpr TypePattern SameIntOrReal{IntOrRealType, KindCode::same};
130static constexpr TypePattern SameComplex{ComplexType, KindCode::same};
131static constexpr TypePattern SameFloating{FloatingType, KindCode::same};
132static constexpr TypePattern SameNumeric{NumericType, KindCode::same};
133static constexpr TypePattern SameChar{CharType, KindCode::same};
134static constexpr TypePattern SameLogical{LogicalType, KindCode::same};
135static constexpr TypePattern SameRelatable{RelatableType, KindCode::same};
peter klauslera70f5962018-10-04 20:43:33136static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
137static constexpr TypePattern SameDerivedType{
138 CategorySet{TypeCategory::Derived}, KindCode::same};
139static constexpr TypePattern SameType{AnyType, KindCode::same};
140
peter klauslerf7f2a732018-10-09 19:07:29141// For DOT_PRODUCT and MATMUL, the result type depends on the arguments
peter klausler51b09b62018-10-15 19:17:30142static constexpr TypePattern ResultLogical{LogicalType, KindCode::likeMultiply};
143static constexpr TypePattern ResultNumeric{NumericType, KindCode::likeMultiply};
peter klauslerf7f2a732018-10-09 19:07:29144
peter klauslera70f5962018-10-04 20:43:33145// Result types with known category and KIND=
peter klausler51b09b62018-10-15 19:17:30146static constexpr TypePattern KINDInt{IntType, KindCode::effectiveKind};
147static constexpr TypePattern KINDReal{RealType, KindCode::effectiveKind};
148static constexpr TypePattern KINDComplex{ComplexType, KindCode::effectiveKind};
149static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind};
150static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11151
152// The default rank pattern for dummy arguments and function results is
153// "elemental".
peter klausler7bda1b32018-10-12 23:01:55154ENUM_CLASS(Rank,
155 elemental, // scalar, or array that conforms with other array arguments
156 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
157 scalar, vector,
158 shape, // INTEGER vector of known length and no negative element
159 matrix,
160 array, // not scalar, rank is known and greater than zero
161 known, // rank is known and can be scalar
peter klausler146e13c2019-04-18 21:11:15162 anyOrAssumedRank, // rank can be unknown; assumed-type TYPE(*) allowed
peter klausler7bda1b32018-10-12 23:01:55163 conformable, // scalar, or array of same rank & shape as "array" argument
164 reduceOperation, // a pure function with constraints for REDUCE
165 dimReduced, // scalar if no DIM= argument, else rank(array)-1
166 dimRemoved, // scalar, or rank(array)-1
167 rankPlus1, // rank(known)+1
168 shaped, // rank is length of SHAPE vector
169)
peter klausler42b33da2018-09-29 00:02:11170
peter klausler7bda1b32018-10-12 23:01:55171ENUM_CLASS(Optionality, required, optional,
172 defaultsToSameKind, // for MatchingDefaultKIND
173 defaultsToDefaultForResult, // for DefaultingKIND
peter klausler7c402d92018-10-16 21:42:22174 defaultsToSubscriptKind, // for SubscriptDefaultKIND
peter klausler7bda1b32018-10-12 23:01:55175 repeats, // for MAX/MIN and their several variants
176)
peter klausler42b33da2018-09-29 00:02:11177
178struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45179 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11180 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33181 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54182 Optionality optionality{Optionality::required};
peter klausler7bda1b32018-10-12 23:01:55183 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11184};
185
peter klauslera70f5962018-10-04 20:43:33186// constexpr abbreviations for popular arguments:
187// DefaultingKIND is a KIND= argument whose default value is the appropriate
188// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54189static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30190 {IntType, KindCode::kindArg}, Rank::scalar,
peter klauslercb308d32018-10-05 18:32:54191 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33192// MatchingDefaultKIND is a KIND= argument whose default value is the
193// kind of any "Same" function argument (viz., the one whose kind pattern is
194// "same").
peter klauslercb308d32018-10-05 18:32:54195static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30196 {IntType, KindCode::kindArg}, Rank::scalar,
197 Optionality::defaultsToSameKind};
peter klausler7c402d92018-10-16 21:42:22198// SubscriptDefaultKind is a KIND= argument whose default value is
199// the kind of INTEGER used for address calculations.
200static constexpr IntrinsicDummyArgument SubscriptDefaultKIND{"kind",
201 {IntType, KindCode::kindArg}, Rank::scalar,
202 Optionality::defaultsToSubscriptKind};
peter klausler00e128e2019-06-25 20:07:32203static constexpr IntrinsicDummyArgument RequiredDIM{
peter klausler28c03d32019-06-27 16:57:48204 "dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::required};
peter klauslera70f5962018-10-04 20:43:33205static constexpr IntrinsicDummyArgument OptionalDIM{
peter klausler51b09b62018-10-15 19:17:30206 "dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33207static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54208 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11209
210struct IntrinsicInterface {
peter klausler84ea49d2018-10-18 17:50:55211 static constexpr int maxArguments{7}; // if not a MAX/MIN(...)
peter klauslerb22d4942018-10-01 18:27:45212 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11213 IntrinsicDummyArgument dummy[maxArguments];
214 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33215 Rank rank{Rank::elemental};
peter klausleref9dd9d2018-10-17 22:09:48216 std::optional<SpecificCall> Match(const CallCharacteristics &,
peter klauslerf9d6c0a2019-01-18 20:40:47217 const common::IntrinsicTypeDefaultKinds &, ActualArguments &,
peter klausler146e13c2019-04-18 21:11:15218 FoldingContext &context) const;
peter klauslerba56b912019-02-22 23:45:30219 int CountArguments() const;
peter klausler7bda1b32018-10-12 23:01:55220 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11221};
222
peter klauslerba56b912019-02-22 23:45:30223int IntrinsicInterface::CountArguments() const {
224 int n{0};
225 while (n < maxArguments && dummy[n].keyword != nullptr) {
226 ++n;
227 }
228 return n;
229}
230
peter klausler94041d72018-10-15 20:39:51231// GENERIC INTRINSIC FUNCTION INTERFACES
232// Each entry in this table defines a pattern. Some intrinsic
233// functions have more than one such pattern. Besides the name
234// of the intrinsic function, each pattern has specifications for
235// the dummy arguments and for the result of the function.
peter klausler59342b02019-05-13 16:33:18236// The dummy argument patterns each have a name (these are from the
peter klausler94041d72018-10-15 20:39:51237// standard, but rarely appear in actual code), a type and kind
238// pattern, allowable ranks, and optionality indicators.
239// Be advised, the default rank pattern is "elemental".
peter klauslerb22d4942018-10-01 18:27:45240static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33241 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
242 {"abs", {{"a", SameComplex}}, SameReal},
peter klauslerad9aede2018-10-11 21:51:14243 {"achar", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
peter klauslera70f5962018-10-04 20:43:33244 {"acos", {{"x", SameFloating}}, SameFloating},
245 {"acosh", {{"x", SameFloating}}, SameFloating},
246 {"adjustl", {{"string", SameChar}}, SameChar},
247 {"adjustr", {{"string", SameChar}}, SameChar},
248 {"aimag", {{"x", SameComplex}}, SameReal},
249 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
250 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
251 Rank::dimReduced},
peter klausler4f2c8fa2019-06-19 18:50:07252 {"allocated", {{"array", Anything, Rank::array}}, DefaultLogical},
253 {"allocated", {{"scalar", Anything, Rank::scalar}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33254 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
255 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
256 Rank::dimReduced},
257 {"asin", {{"x", SameFloating}}, SameFloating},
258 {"asinh", {{"x", SameFloating}}, SameFloating},
peter klauslera0e50522019-06-21 21:04:40259 {"associated",
260 {{"pointer", Anything, Rank::known},
261 {"target", Anything, Rank::known, Optionality::optional}},
262 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33263 {"atan", {{"x", SameFloating}}, SameFloating},
264 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
265 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
266 {"atanh", {{"x", SameFloating}}, SameFloating},
267 {"bessel_j0", {{"x", SameReal}}, SameReal},
268 {"bessel_j1", {{"x", SameReal}}, SameReal},
269 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29270 {"bessel_jn",
271 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
272 {"x", SameReal, Rank::scalar}},
273 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33274 {"bessel_y0", {{"x", SameReal}}, SameReal},
275 {"bessel_y1", {{"x", SameReal}}, SameReal},
276 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29277 {"bessel_yn",
278 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
279 {"x", SameReal, Rank::scalar}},
280 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33281 {"bge",
peter klauslercb308d32018-10-05 18:32:54282 {{"i", AnyInt, Rank::elementalOrBOZ},
283 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22284 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33285 {"bgt",
peter klauslercb308d32018-10-05 18:32:54286 {{"i", AnyInt, Rank::elementalOrBOZ},
287 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22288 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33289 {"ble",
peter klauslercb308d32018-10-05 18:32:54290 {{"i", AnyInt, Rank::elementalOrBOZ},
291 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22292 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33293 {"blt",
peter klauslercb308d32018-10-05 18:32:54294 {{"i", AnyInt, Rank::elementalOrBOZ},
295 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22296 DefaultLogical},
297 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33298 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
299 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
300 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11301 {"cmplx",
peter klausler5774f0a2019-06-04 17:50:34302 {{"x", AnyIntOrReal, Rank::elementalOrBOZ},
303 {"y", AnyIntOrReal, Rank::elementalOrBOZ, Optionality::optional},
peter klausler25e6f032019-05-03 18:29:15304 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33305 KINDComplex},
peter klausler7c402d92018-10-16 21:42:22306 {"command_argument_count", {}, DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33307 {"conjg", {{"z", SameComplex}}, SameComplex},
308 {"cos", {{"x", SameFloating}}, SameFloating},
309 {"cosh", {{"x", SameFloating}}, SameFloating},
310 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
311 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11312 {"cshift",
peter klauslera70f5962018-10-04 20:43:33313 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
314 OptionalDIM},
peter klauslerd29530e2019-05-21 23:58:46315 SameType, Rank::conformable},
peter klausleref9dd9d2018-10-17 22:09:48316 {"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33317 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
peter klauslerf7f2a732018-10-09 19:07:29318 {"dot_product",
319 {{"vector_a", AnyLogical, Rank::vector},
320 {"vector_b", AnyLogical, Rank::vector}},
321 ResultLogical, Rank::scalar},
322 {"dot_product",
323 {{"vector_a", AnyComplex, Rank::vector},
324 {"vector_b", AnyNumeric, Rank::vector}},
325 ResultNumeric, Rank::scalar}, // conjugates vector_a
326 {"dot_product",
327 {{"vector_a", AnyIntOrReal, Rank::vector},
328 {"vector_b", AnyNumeric, Rank::vector}},
329 ResultNumeric, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22330 {"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33331 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54332 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33333 {"shift", AnyInt}},
334 SameInt},
335 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
336 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54337 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33338 {"shift", AnyInt}},
339 SameInt},
340 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11341 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33342 {{"array", SameIntrinsic, Rank::array},
343 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54344 {"boundary", SameIntrinsic, Rank::dimRemoved,
345 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33346 OptionalDIM},
peter klauslerd29530e2019-05-21 23:58:46347 SameIntrinsic, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11348 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33349 {{"array", SameDerivedType, Rank::array},
350 {"shift", AnyInt, Rank::dimRemoved},
351 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
peter klauslerd29530e2019-05-21 23:58:46352 SameDerivedType, Rank::conformable},
peter klauslera70f5962018-10-04 20:43:33353 {"erf", {{"x", SameReal}}, SameReal},
354 {"erfc", {{"x", SameReal}}, SameReal},
355 {"erfc_scaled", {{"x", SameReal}}, SameReal},
356 {"exp", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22357 {"exponent", {{"x", AnyReal}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11358 {"findloc",
peter klauslerad9aede2018-10-11 21:51:14359 {{"array", AnyNumeric, Rank::array},
peter klausler00e128e2019-06-25 20:07:32360 {"value", AnyNumeric, Rank::scalar}, RequiredDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22361 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54362 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klausler00e128e2019-06-25 20:07:32363 KINDInt, Rank::dimRemoved},
364 {"findloc",
365 {{"array", AnyNumeric, Rank::array},
366 {"value", AnyNumeric, Rank::scalar}, OptionalMASK,
367 SubscriptDefaultKIND,
368 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
369 KINDInt, Rank::vector},
peter klausler42b33da2018-09-29 00:02:11370 {"findloc",
peter klauslera70f5962018-10-04 20:43:33371 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
peter klausler00e128e2019-06-25 20:07:32372 RequiredDIM, OptionalMASK, SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54373 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klausler00e128e2019-06-25 20:07:32374 KINDInt, Rank::dimRemoved},
375 {"findloc",
376 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
377 OptionalMASK, SubscriptDefaultKIND,
378 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
379 KINDInt, Rank::vector},
peter klausler42b33da2018-09-29 00:02:11380 {"findloc",
peter klauslera70f5962018-10-04 20:43:33381 {{"array", AnyLogical, Rank::array},
peter klausler00e128e2019-06-25 20:07:32382 {"value", AnyLogical, Rank::scalar}, RequiredDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22383 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54384 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klausler00e128e2019-06-25 20:07:32385 KINDInt, Rank::dimRemoved},
386 {"findloc",
387 {{"array", AnyLogical, Rank::array},
388 {"value", AnyLogical, Rank::scalar}, OptionalMASK,
389 SubscriptDefaultKIND,
390 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
391 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33392 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
393 {"fraction", {{"x", SameReal}}, SameReal},
394 {"gamma", {{"x", SameReal}}, SameReal},
395 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
396 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
397 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
398 SameInt, Rank::dimReduced},
399 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
400 SameInt, Rank::dimReduced},
401 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
402 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54403 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33404 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
405 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
406 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
407 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
408 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54409 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33410 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
411 {"image_status",
peter klauslercb308d32018-10-05 18:32:54412 {{"image", SameInt},
413 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22414 DefaultInt},
peter klausler42b33da2018-09-29 00:02:11415 {"index",
peter klauslera70f5962018-10-04 20:43:33416 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54417 {"back", AnyLogical, Rank::scalar, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22418 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33419 KINDInt},
peter klauslercb308d32018-10-05 18:32:54420 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
421 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33422 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
423 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
424 {"ishftc",
425 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54426 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33427 SameInt},
peter klausler7c402d92018-10-16 21:42:22428 {"is_iostat_end", {{"i", AnyInt}}, DefaultLogical},
429 {"is_iostat_eor", {{"i", AnyInt}}, DefaultLogical},
peter klauslerbe3b7652018-12-04 18:55:32430 {"kind", {{"x", AnyIntrinsic}}, DefaultInt},
peter klausler7c402d92018-10-16 21:42:22431 {"lbound",
peter klausler00e128e2019-06-25 20:07:32432 {{"array", Anything, Rank::anyOrAssumedRank}, RequiredDIM,
peter klausler7c402d92018-10-16 21:42:22433 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29434 KINDInt, Rank::scalar},
peter klauslerd29530e2019-05-21 23:58:46435 {"lbound",
436 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
437 KINDInt, Rank::vector},
peter klausler7c402d92018-10-16 21:42:22438 {"leadz", {{"i", AnyInt}}, DefaultInt},
peter klauslerfb1fcbb2019-06-04 17:09:54439 {"len", {{"string", AnyChar, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klausler5774f0a2019-06-04 17:50:34440 KINDInt, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22441 {"len_trim", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
442 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
443 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
444 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
445 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33446 {"log", {{"x", SameFloating}}, SameFloating},
447 {"log10", {{"x", SameReal}}, SameReal},
448 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
449 {"log_gamma", {{"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29450 {"matmul",
451 {{"array_a", AnyLogical, Rank::vector},
452 {"array_b", AnyLogical, Rank::matrix}},
453 ResultLogical, Rank::vector},
454 {"matmul",
455 {{"array_a", AnyLogical, Rank::matrix},
456 {"array_b", AnyLogical, Rank::vector}},
457 ResultLogical, Rank::vector},
458 {"matmul",
459 {{"array_a", AnyLogical, Rank::matrix},
460 {"array_b", AnyLogical, Rank::matrix}},
461 ResultLogical, Rank::matrix},
462 {"matmul",
463 {{"array_a", AnyNumeric, Rank::vector},
464 {"array_b", AnyNumeric, Rank::matrix}},
465 ResultNumeric, Rank::vector},
466 {"matmul",
467 {{"array_a", AnyNumeric, Rank::matrix},
468 {"array_b", AnyNumeric, Rank::vector}},
469 ResultNumeric, Rank::vector},
470 {"matmul",
471 {{"array_a", AnyNumeric, Rank::matrix},
472 {"array_b", AnyNumeric, Rank::matrix}},
473 ResultNumeric, Rank::matrix},
peter klauslera70f5962018-10-04 20:43:33474 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
475 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klauslerad9aede2018-10-11 21:51:14476 {"max",
477 {{"a1", SameRelatable}, {"a2", SameRelatable},
478 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
479 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11480 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33481 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22482 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54483 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33484 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11485 {"maxval",
peter klauslera70f5962018-10-04 20:43:33486 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
487 SameRelatable, Rank::dimReduced},
peter klauslerad9aede2018-10-11 21:51:14488 {"merge",
489 {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
490 SameType},
peter klausler42b33da2018-09-29 00:02:11491 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54492 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
493 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33494 SameInt},
495 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54496 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33497 SameInt},
peter klauslerad9aede2018-10-11 21:51:14498 {"min",
499 {{"a1", SameRelatable}, {"a2", SameRelatable},
500 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
501 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11502 {"minloc",
peter klauslera70f5962018-10-04 20:43:33503 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22504 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54505 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33506 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11507 {"minval",
peter klauslera70f5962018-10-04 20:43:33508 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
509 SameRelatable, Rank::dimReduced},
510 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
511 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
512 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
513 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
514 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
515 Rank::dimReduced},
516 {"not", {{"i", SameInt}}, SameInt},
peter klausler8efb8972018-10-10 17:48:12517 // NULL() is a special case handled in Probe() below
peter klausler42b33da2018-09-29 00:02:11518 {"out_of_range",
peter klauslerad9aede2018-10-11 21:51:14519 {{"x", AnyIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22520 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33521 {"out_of_range",
522 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54523 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22524 DefaultLogical},
525 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DefaultLogical},
peter klausler42b33da2018-09-29 00:02:11526 {"pack",
peter klauslera70f5962018-10-04 20:43:33527 {{"array", SameType, Rank::array},
528 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54529 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33530 SameType, Rank::vector},
531 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
532 Rank::dimReduced},
peter klausler7c402d92018-10-16 21:42:22533 {"popcnt", {{"i", AnyInt}}, DefaultInt},
534 {"poppar", {{"i", AnyInt}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11535 {"product",
peter klauslera70f5962018-10-04 20:43:33536 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
537 SameNumeric, Rank::dimReduced},
peter klauslerf4b12092019-05-29 22:38:33538 {"precision", {{"x", AnyFloating, Rank::anyOrAssumedRank}}, DefaultInt},
peter klausler59342b02019-05-13 16:33:18539 {"present", {{"a", Anything, Rank::anyOrAssumedRank}}, DefaultLogical},
peter klauslerd49aa3c2019-05-29 23:00:31540 {"radix", {{"x", AnyNumeric, Rank::anyOrAssumedRank}}, DefaultInt},
541 {"range", {{"x", AnyNumeric, Rank::anyOrAssumedRank}}, DefaultInt},
peter klausler28184c42019-04-04 20:58:46542 {"rank", {{"a", Anything, Rank::anyOrAssumedRank}}, DefaultInt},
peter klauslercb308d32018-10-05 18:32:54543 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33544 KINDReal},
peter klauslerad9aede2018-10-11 21:51:14545 {"reduce",
546 {{"array", SameType, Rank::array},
547 {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
548 OptionalMASK, {"identity", SameType, Rank::scalar},
549 {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
550 SameType, Rank::dimReduced},
peter klausler24379cc2018-10-10 23:45:17551 {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
552 SameChar, Rank::scalar},
peter klausler42b33da2018-09-29 00:02:11553 {"reshape",
peter klauslera70f5962018-10-04 20:43:33554 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54555 {"pad", SameType, Rank::array, Optionality::optional},
556 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33557 SameType, Rank::shaped},
558 {"rrspacing", {{"x", SameReal}}, SameReal},
559 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11560 {"scan",
peter klauslera70f5962018-10-04 20:43:33561 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54562 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22563 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33564 KINDInt},
peter klausler7c402d92018-10-16 21:42:22565 {"selected_char_kind", {{"name", DefaultChar, Rank::scalar}}, DefaultInt,
peter klausler24379cc2018-10-10 23:45:17566 Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22567 {"selected_int_kind", {{"r", AnyInt, Rank::scalar}}, DefaultInt,
568 Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14569 {"selected_real_kind",
570 {{"p", AnyInt, Rank::scalar},
571 {"r", AnyInt, Rank::scalar, Optionality::optional},
572 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22573 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14574 {"selected_real_kind",
575 {{"p", AnyInt, Rank::scalar, Optionality::optional},
576 {"r", AnyInt, Rank::scalar},
577 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22578 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14579 {"selected_real_kind",
580 {{"p", AnyInt, Rank::scalar, Optionality::optional},
581 {"r", AnyInt, Rank::scalar, Optionality::optional},
582 {"radix", AnyInt, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22583 DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33584 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler7c402d92018-10-16 21:42:22585 {"shape",
586 {{"source", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klausler24379cc2018-10-10 23:45:17587 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33588 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
589 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
590 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
591 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
592 {"sin", {{"x", SameFloating}}, SameFloating},
593 {"sinh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22594 {"size",
peter klauslerfe3acf5f2019-01-07 18:15:27595 {{"array", Anything, Rank::anyOrAssumedRank}, OptionalDIM,
peter klausler7c402d92018-10-16 21:42:22596 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29597 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33598 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11599 {"spread",
peter klausler00e128e2019-06-25 20:07:32600 {{"source", SameType, Rank::known}, RequiredDIM,
peter klauslera70f5962018-10-04 20:43:33601 {"ncopies", AnyInt, Rank::scalar}},
602 SameType, Rank::rankPlus1},
603 {"sqrt", {{"x", SameFloating}}, SameFloating},
604 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
605 SameNumeric, Rank::dimReduced},
606 {"tan", {{"x", SameFloating}}, SameFloating},
607 {"tanh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22608 {"trailz", {{"i", AnyInt}}, DefaultInt},
peter klauslerf7f2a732018-10-09 19:07:29609 {"transfer",
610 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::scalar}},
611 SameType, Rank::scalar},
612 {"transfer",
613 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::array}},
614 SameType, Rank::vector},
615 {"transfer",
peter klausler8b580e42018-12-14 19:23:14616 {{"source", Anything, Rank::anyOrAssumedRank},
617 {"mold", SameType, Rank::anyOrAssumedRank},
peter klauslerf7f2a732018-10-09 19:07:29618 {"size", AnyInt, Rank::scalar}},
619 SameType, Rank::vector},
620 {"transpose", {{"matrix", SameType, Rank::matrix}}, SameType, Rank::matrix},
peter klauslerad9aede2018-10-11 21:51:14621 {"trim", {{"string", SameChar, Rank::scalar}}, SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22622 {"ubound",
peter klausler00e128e2019-06-25 20:07:32623 {{"array", Anything, Rank::anyOrAssumedRank}, RequiredDIM,
peter klausler7c402d92018-10-16 21:42:22624 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29625 KINDInt, Rank::scalar},
peter klauslerd29530e2019-05-21 23:58:46626 {"ubound",
627 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
628 KINDInt, Rank::vector},
peter klauslerf7f2a732018-10-09 19:07:29629 {"unpack",
630 {{"vector", SameType, Rank::vector}, {"mask", AnyLogical, Rank::array},
631 {"field", SameType, Rank::conformable}},
632 SameType, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11633 {"verify",
peter klauslera70f5962018-10-04 20:43:33634 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54635 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22636 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33637 KINDInt},
peter klausler42b33da2018-09-29 00:02:11638};
639
peter klausler8efb8972018-10-10 17:48:12640// TODO: Coarray intrinsic functions
peter klauslerad9aede2018-10-11 21:51:14641// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
642// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
643// COSHAPE
peter klausler8efb8972018-10-10 17:48:12644// TODO: Object characteristic inquiry functions
peter klausler4f2c8fa2019-06-19 18:50:07645// ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS,
peter klausler59342b02019-05-13 16:33:18646// SAME_TYPE, STORAGE_SIZE
peter klauslerad9aede2018-10-11 21:51:14647// TODO: Type inquiry intrinsic functions - these return constants
648// BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT,
peter klauslerf4b12092019-05-29 22:38:33649// NEW_LINE, TINY
peter klauslerad9aede2018-10-11 21:51:14650// TODO: Non-standard intrinsic functions
651// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
652// COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL,
653// DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC,
654// QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM,
655// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
656// MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
657// IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
658// EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
659// probably more (these are PGI + Intel, possibly incomplete)
peter klausler42b33da2018-09-29 00:02:11660
peter klauslerba56b912019-02-22 23:45:30661// The following table contains the intrinsic functions listed in
662// Tables 16.2 and 16.3 in Fortran 2018. The "unrestricted" functions
663// in Table 16.2 can be used as actual arguments, PROCEDURE() interfaces,
664// and procedure pointer targets.
peter klausler42b33da2018-09-29 00:02:11665struct SpecificIntrinsicInterface : public IntrinsicInterface {
666 const char *generic{nullptr};
peter klauslerba56b912019-02-22 23:45:30667 bool isRestrictedSpecific{false};
peter klausler8a326cb2019-06-05 22:40:59668 bool forceResultType{false};
peter klausler42b33da2018-09-29 00:02:11669};
670
peter klauslerb22d4942018-10-01 18:27:45671static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klausler7c402d92018-10-16 21:42:22672 {{"abs", {{"a", DefaultReal}}, DefaultReal}},
673 {{"acos", {{"x", DefaultReal}}, DefaultReal}},
674 {{"aimag", {{"z", DefaultComplex}}, DefaultReal}},
675 {{"aint", {{"a", DefaultReal}}, DefaultReal}},
676 {{"alog", {{"x", DefaultReal}}, DefaultReal}, "log"},
677 {{"alog10", {{"x", DefaultReal}}, DefaultReal}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14678 {{"amax0",
peter klausler7c402d92018-10-16 21:42:22679 {{"a1", DefaultInt}, {"a2", DefaultInt},
680 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
681 DefaultReal},
peter klausler8a326cb2019-06-05 22:40:59682 "max", true, true},
peter klauslerad9aede2018-10-11 21:51:14683 {{"amax1",
peter klausler7c402d92018-10-16 21:42:22684 {{"a1", DefaultReal}, {"a2", DefaultReal},
685 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
686 DefaultReal},
peter klausler8a326cb2019-06-05 22:40:59687 "max", true, true},
peter klauslerad9aede2018-10-11 21:51:14688 {{"amin0",
peter klausler7c402d92018-10-16 21:42:22689 {{"a1", DefaultInt}, {"a2", DefaultInt},
690 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
691 DefaultReal},
peter klausler8a326cb2019-06-05 22:40:59692 "min", true, true},
peter klauslerad9aede2018-10-11 21:51:14693 {{"amin1",
peter klausler7c402d92018-10-16 21:42:22694 {{"a1", DefaultReal}, {"a2", DefaultReal},
695 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
696 DefaultReal},
peter klausler8a326cb2019-06-05 22:40:59697 "min", true, true},
peter klausler7c402d92018-10-16 21:42:22698 {{"amod", {{"a", DefaultReal}, {"p", DefaultReal}}, DefaultReal}, "mod"},
699 {{"anint", {{"a", DefaultReal}}, DefaultReal}},
700 {{"asin", {{"x", DefaultReal}}, DefaultReal}},
701 {{"atan", {{"x", DefaultReal}}, DefaultReal}},
702 {{"atan2", {{"y", DefaultReal}, {"x", DefaultReal}}, DefaultReal}},
703 {{"cabs", {{"a", DefaultComplex}}, DefaultReal}, "abs"},
704 {{"ccos", {{"a", DefaultComplex}}, DefaultComplex}, "cos"},
peter klauslera0e50522019-06-21 21:04:40705 {{"cdabs", {{"a", DoublePrecisionComplex}}, DoublePrecision}, "abs"},
706 {{"cdcos", {{"a", DoublePrecisionComplex}}, DoublePrecisionComplex}, "cos"},
707 {{"cdexp", {{"a", DoublePrecisionComplex}}, DoublePrecisionComplex}, "exp"},
708 {{"cdlog", {{"a", DoublePrecisionComplex}}, DoublePrecisionComplex}, "log"},
709 {{"cdsin", {{"a", DoublePrecisionComplex}}, DoublePrecisionComplex}, "sin"},
710 {{"cdsqrt", {{"a", DoublePrecisionComplex}}, DoublePrecisionComplex},
711 "sqrt"},
peter klausler7c402d92018-10-16 21:42:22712 {{"cexp", {{"a", DefaultComplex}}, DefaultComplex}, "exp"},
713 {{"clog", {{"a", DefaultComplex}}, DefaultComplex}, "log"},
714 {{"conjg", {{"a", DefaultComplex}}, DefaultComplex}},
715 {{"cos", {{"x", DefaultReal}}, DefaultReal}},
716 {{"csin", {{"a", DefaultComplex}}, DefaultComplex}, "sin"},
717 {{"csqrt", {{"a", DefaultComplex}}, DefaultComplex}, "sqrt"},
718 {{"ctan", {{"a", DefaultComplex}}, DefaultComplex}, "tan"},
peter klauslera70f5962018-10-04 20:43:33719 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
720 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
721 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
722 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
723 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
724 DoublePrecision},
725 "atan2"},
peter klauslera0e50522019-06-21 21:04:40726 {{"dconjg", {{"a", DoublePrecisionComplex}}, DoublePrecisionComplex},
727 "conjg"},
peter klauslera70f5962018-10-04 20:43:33728 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
729 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
730 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
731 DoublePrecision},
732 "dim"},
733 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
peter klausler7c402d92018-10-16 21:42:22734 {{"dim", {{"x", DefaultReal}, {"y", DefaultReal}}, DefaultReal}},
peter klauslera70f5962018-10-04 20:43:33735 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
736 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
737 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14738 {{"dmax1",
739 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
740 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
741 DoublePrecision},
742 "max", true},
743 {{"dmin1",
744 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
745 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
746 DoublePrecision},
747 "min", true},
peter klauslera70f5962018-10-04 20:43:33748 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
749 DoublePrecision},
750 "mod"},
751 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
peter klausler7c402d92018-10-16 21:42:22752 {{"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision}},
peter klauslera70f5962018-10-04 20:43:33753 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
754 DoublePrecision},
755 "sign"},
756 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
757 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
758 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
759 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
760 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
peter klausler7c402d92018-10-16 21:42:22761 {{"exp", {{"x", DefaultReal}}, DefaultReal}},
762 {{"float", {{"i", DefaultInt}}, DefaultReal}, "real", true},
763 {{"iabs", {{"a", DefaultInt}}, DefaultInt}, "abs"},
764 {{"idim", {{"x", DefaultInt}, {"y", DefaultInt}}, DefaultInt}, "dim"},
765 {{"idint", {{"a", DoublePrecision}}, DefaultInt}, "int", true},
766 {{"idnint", {{"a", DoublePrecision}}, DefaultInt}, "nint"},
767 {{"ifix", {{"a", DefaultReal}}, DefaultInt}, "int", true},
768 {{"index", {{"string", DefaultChar}, {"substring", DefaultChar}},
769 DefaultInt}},
770 {{"isign", {{"a", DefaultInt}, {"b", DefaultInt}}, DefaultInt}, "sign"},
peter klausler5774f0a2019-06-04 17:50:34771 {{"len", {{"string", DefaultChar, Rank::anyOrAssumedRank}}, DefaultInt,
772 Rank::scalar}},
peter klausler8a326cb2019-06-05 22:40:59773 {{"lge", {{"string_a", DefaultChar}, {"string_b", DefaultChar}},
774 DefaultLogical}},
775 {{"lgt", {{"string_a", DefaultChar}, {"string_b", DefaultChar}},
776 DefaultLogical}},
777 {{"lle", {{"string_a", DefaultChar}, {"string_b", DefaultChar}},
778 DefaultLogical}},
779 {{"llt", {{"string_a", DefaultChar}, {"string_b", DefaultChar}},
780 DefaultLogical}},
peter klausler7c402d92018-10-16 21:42:22781 {{"log", {{"x", DefaultReal}}, DefaultReal}},
782 {{"log10", {{"x", DefaultReal}}, DefaultReal}},
peter klauslerad9aede2018-10-11 21:51:14783 {{"max0",
peter klausler7c402d92018-10-16 21:42:22784 {{"a1", DefaultInt}, {"a2", DefaultInt},
785 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
786 DefaultInt},
peter klausler8a326cb2019-06-05 22:40:59787 "max", true, true},
peter klauslerad9aede2018-10-11 21:51:14788 {{"max1",
peter klausler7c402d92018-10-16 21:42:22789 {{"a1", DefaultReal}, {"a2", DefaultReal},
790 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
791 DefaultInt},
peter klausler8a326cb2019-06-05 22:40:59792 "max", true, true},
peter klauslerad9aede2018-10-11 21:51:14793 {{"min0",
peter klausler7c402d92018-10-16 21:42:22794 {{"a1", DefaultInt}, {"a2", DefaultInt},
795 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
796 DefaultInt},
peter klausler8a326cb2019-06-05 22:40:59797 "min", true, true},
peter klauslerad9aede2018-10-11 21:51:14798 {{"min1",
peter klausler7c402d92018-10-16 21:42:22799 {{"a1", DefaultReal}, {"a2", DefaultReal},
800 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
801 DefaultInt},
peter klausler8a326cb2019-06-05 22:40:59802 "min", true, true},
peter klausler7c402d92018-10-16 21:42:22803 {{"mod", {{"a", DefaultInt}, {"p", DefaultInt}}, DefaultInt}},
804 {{"nint", {{"a", DefaultReal}}, DefaultInt}},
805 {{"sign", {{"a", DefaultReal}, {"b", DefaultReal}}, DefaultReal}},
806 {{"sin", {{"x", DefaultReal}}, DefaultReal}},
807 {{"sinh", {{"x", DefaultReal}}, DefaultReal}},
808 {{"sngl", {{"a", DoublePrecision}}, DefaultReal}, "real", true},
809 {{"sqrt", {{"x", DefaultReal}}, DefaultReal}},
810 {{"tan", {{"x", DefaultReal}}, DefaultReal}},
811 {{"tanh", {{"x", DefaultReal}}, DefaultReal}},
peter klausler42b33da2018-09-29 00:02:11812};
813
peter klauslerad9aede2018-10-11 21:51:14814// TODO: Intrinsic subroutines
815// MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY,
816// EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT,
817// GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER,
818// RANDOM_SEED, SYSTEM_CLOCK
819// TODO: Atomic intrinsic subroutines: ATOMIC_ADD &al.
820// TODO: Collective intrinsic subroutines: CO_BROADCAST &al.
peter klausler42b33da2018-09-29 00:02:11821
peter klauslera70f5962018-10-04 20:43:33822// Intrinsic interface matching against the arguments of a particular
823// procedure reference.
peter klausleref9dd9d2018-10-17 22:09:48824std::optional<SpecificCall> IntrinsicInterface::Match(
peter klauslerbf339f82018-10-15 22:28:47825 const CallCharacteristics &call,
peter klauslerf9d6c0a2019-01-18 20:40:47826 const common::IntrinsicTypeDefaultKinds &defaults,
peter klausler146e13c2019-04-18 21:11:15827 ActualArguments &arguments, FoldingContext &context) const {
828 auto &messages{context.messages()};
peter klauslera70f5962018-10-04 20:43:33829 // Attempt to construct a 1-1 correspondence between the dummy arguments in
830 // a particular intrinsic procedure's generic interface and the actual
831 // arguments in a procedure reference.
peter klausler84ea49d2018-10-18 17:50:55832 std::size_t dummyArgPatterns{0};
833 for (; dummyArgPatterns < maxArguments &&
834 dummy[dummyArgPatterns].keyword != nullptr;
835 ++dummyArgPatterns) {
peter klauslera70f5962018-10-04 20:43:33836 }
peter klausler84ea49d2018-10-18 17:50:55837 std::vector<ActualArgument *> actualForDummy(dummyArgPatterns, nullptr);
838 // MAX and MIN (and others that map to them) allow their last argument to
839 // be repeated indefinitely. The actualForDummy vector is sized
840 // and null-initialized to the non-repeated dummy argument count,
841 // but additional actual argument pointers can be pushed on it
842 // when this flag is set.
843 bool repeatLastDummy{dummyArgPatterns > 0 &&
844 dummy[dummyArgPatterns - 1].optionality == Optionality::repeats};
845 int missingActualArguments{0};
peter klausleref9dd9d2018-10-17 22:09:48846 for (std::optional<ActualArgument> &arg : arguments) {
peter klausler84ea49d2018-10-18 17:50:55847 if (!arg.has_value()) {
848 ++missingActualArguments;
849 } else {
peter klausleref9dd9d2018-10-17 22:09:48850 if (arg->isAlternateReturn) {
851 messages.Say(
852 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
853 name);
854 return std::nullopt;
855 }
856 bool found{false};
peter klausler84ea49d2018-10-18 17:50:55857 int slot{missingActualArguments};
858 for (std::size_t j{0}; j < dummyArgPatterns && !found; ++j) {
859 if (arg->keyword.has_value()) {
860 found = *arg->keyword == dummy[j].keyword;
861 if (found) {
862 if (const auto *previous{actualForDummy[j]}) {
863 if (previous->keyword.has_value()) {
864 messages.Say(*arg->keyword,
865 "repeated keyword argument to intrinsic '%s'"_err_en_US,
866 name);
867 } else {
868 messages.Say(*arg->keyword,
869 "keyword argument to intrinsic '%s' was supplied "
870 "positionally by an earlier actual argument"_err_en_US,
871 name);
872 }
873 return std::nullopt;
874 }
peter klausleref9dd9d2018-10-17 22:09:48875 }
peter klausler84ea49d2018-10-18 17:50:55876 } else {
877 found = actualForDummy[j] == nullptr && slot-- == 0;
878 }
879 if (found) {
880 actualForDummy[j] = &*arg;
peter klauslera70f5962018-10-04 20:43:33881 }
882 }
peter klausleref9dd9d2018-10-17 22:09:48883 if (!found) {
peter klausler84ea49d2018-10-18 17:50:55884 if (repeatLastDummy && !arg->keyword.has_value()) {
885 // MAX/MIN argument after the 2nd
886 actualForDummy.push_back(&*arg);
peter klausleref9dd9d2018-10-17 22:09:48887 } else {
peter klausler84ea49d2018-10-18 17:50:55888 if (arg->keyword.has_value()) {
889 messages.Say(*arg->keyword,
890 "unknown keyword argument to intrinsic '%s'"_err_en_US, name);
891 } else {
892 messages.Say(
893 "too many actual arguments for intrinsic '%s'"_err_en_US, name);
894 }
895 return std::nullopt;
peter klausleref9dd9d2018-10-17 22:09:48896 }
peter klauslera70f5962018-10-04 20:43:33897 }
898 }
899 }
900
peter klausler84ea49d2018-10-18 17:50:55901 std::size_t dummies{actualForDummy.size()};
902
peter klauslera70f5962018-10-04 20:43:33903 // Check types and kinds of the actual arguments against the intrinsic's
904 // interface. Ensure that two or more arguments that have to have the same
905 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19906 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33907 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19908 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33909 bool hasDimArg{false};
peter klausler84ea49d2018-10-18 17:50:55910 for (std::size_t j{0}; j < dummies; ++j) {
911 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
peter klauslera70f5962018-10-04 20:43:33912 if (d.typePattern.kindCode == KindCode::kindArg) {
913 CHECK(kindDummyArg == nullptr);
914 kindDummyArg = &d;
915 }
peter klausler84ea49d2018-10-18 17:50:55916 const ActualArgument *arg{actualForDummy[j]};
peter klauslera70f5962018-10-04 20:43:33917 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54918 if (d.optionality == Optionality::required) {
peter klausler7bda1b32018-10-12 23:01:55919 messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33920 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54921 } else {
922 continue;
peter klauslera70f5962018-10-04 20:43:33923 }
924 }
peter klausler146e13c2019-04-18 21:11:15925 if (arg->GetAssumedTypeDummy()) {
926 // TYPE(*) assumed-type dummy argument forwarded to intrinsic
927 if (d.typePattern.categorySet == AnyType &&
928 d.typePattern.kindCode == KindCode::any &&
929 d.rank == Rank::anyOrAssumedRank) {
930 continue;
peter klausler25e6f032019-05-03 18:29:15931 } else {
932 messages.Say("Assumed type TYPE(*) dummy argument not allowed "
933 "for '%s=' intrinsic argument"_err_en_US,
934 d.keyword);
935 return std::nullopt;
peter klausler146e13c2019-04-18 21:11:15936 }
peter klausler146e13c2019-04-18 21:11:15937 }
peter klauslera62636f2018-10-08 22:35:19938 std::optional<DynamicType> type{arg->GetType()};
939 if (!type.has_value()) {
940 CHECK(arg->Rank() == 0);
peter klauslerd29530e2019-05-21 23:58:46941 const Expr<SomeType> *expr{arg->UnwrapExpr()};
peter klausler25e6f032019-05-03 18:29:15942 CHECK(expr != nullptr);
943 if (std::holds_alternative<BOZLiteralConstant>(expr->u)) {
944 if (d.typePattern.kindCode == KindCode::typeless ||
945 d.rank == Rank::elementalOrBOZ) {
946 continue;
947 } else {
948 messages.Say(
949 "Typeless (BOZ) not allowed for '%s=' argument"_err_en_US,
950 d.keyword);
951 }
952 } else {
953 // NULL(), pointer to subroutine, &c.
954 messages.Say("Typeless item not allowed for '%s=' argument"_err_en_US,
955 d.keyword);
peter klauslera70f5962018-10-04 20:43:33956 }
peter klauslercb308d32018-10-05 18:32:54957 return std::nullopt;
peter klausler59342b02019-05-13 16:33:18958 } else if (!d.typePattern.categorySet.test(type->category())) {
peter klausler25e6f032019-05-03 18:29:15959 messages.Say("Actual argument for '%s=' has bad type '%s'"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:45960 d.keyword, type->AsFortran());
peter klauslera70f5962018-10-04 20:43:33961 return std::nullopt; // argument has invalid type category
962 }
963 bool argOk{false};
964 switch (d.typePattern.kindCode) {
965 case KindCode::none:
966 case KindCode::typeless:
967 case KindCode::teamType: // TODO: TEAM_TYPE
968 argOk = false;
969 break;
970 case KindCode::defaultIntegerKind:
peter klausler59342b02019-05-13 16:33:18971 argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33972 break;
973 case KindCode::defaultRealKind:
peter klausler59342b02019-05-13 16:33:18974 argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Real);
peter klauslera70f5962018-10-04 20:43:33975 break;
976 case KindCode::doublePrecision:
peter klausler59342b02019-05-13 16:33:18977 argOk = type->kind() == defaults.doublePrecisionKind();
peter klauslera70f5962018-10-04 20:43:33978 break;
979 case KindCode::defaultCharKind:
peter klausler59342b02019-05-13 16:33:18980 argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Character);
peter klauslera70f5962018-10-04 20:43:33981 break;
982 case KindCode::defaultLogicalKind:
peter klausler59342b02019-05-13 16:33:18983 argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Logical);
peter klauslera70f5962018-10-04 20:43:33984 break;
985 case KindCode::any: argOk = true; break;
986 case KindCode::kindArg:
peter klausler59342b02019-05-13 16:33:18987 CHECK(type->category() == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33988 CHECK(kindArg == nullptr);
989 kindArg = arg;
peter klauslerf7f2a732018-10-09 19:07:29990 argOk = true;
peter klauslera70f5962018-10-04 20:43:33991 break;
992 case KindCode::dimArg:
peter klausler59342b02019-05-13 16:33:18993 CHECK(type->category() == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33994 hasDimArg = true;
995 argOk = true;
996 break;
997 case KindCode::same:
998 if (sameArg == nullptr) {
999 sameArg = arg;
1000 }
peter klausler1b1f60f2018-12-05 21:03:391001 argOk = type.value() == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:331002 break;
1003 case KindCode::effectiveKind:
1004 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
1005 "for intrinsic '%s'",
1006 d.keyword, name);
1007 break;
1008 default: CRASH_NO_CASE;
1009 }
1010 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:541011 messages.Say(
peter klausler5774f0a2019-06-04 17:50:341012 "Actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451013 d.keyword, type->AsFortran());
peter klauslera70f5962018-10-04 20:43:331014 return std::nullopt;
1015 }
1016 }
1017
1018 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:191019 const ActualArgument *arrayArg{nullptr};
1020 const ActualArgument *knownArg{nullptr};
peter klauslerb65572d2019-04-03 23:04:131021 std::optional<int> shapeArgSize;
peter klauslera70f5962018-10-04 20:43:331022 int elementalRank{0};
peter klausler84ea49d2018-10-18 17:50:551023 for (std::size_t j{0}; j < dummies; ++j) {
1024 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
1025 if (const ActualArgument * arg{actualForDummy[j]}) {
peter klausler146e13c2019-04-18 21:11:151026 if (IsAssumedRank(*arg) && d.rank != Rank::anyOrAssumedRank) {
peter klausler5774f0a2019-06-04 17:50:341027 messages.Say("Assumed-rank array cannot be forwarded to "
peter klausler03618fd2018-10-29 22:25:351028 "'%s=' argument"_err_en_US,
peter klauslercb308d32018-10-05 18:32:541029 d.keyword);
peter klauslera70f5962018-10-04 20:43:331030 return std::nullopt;
1031 }
peter klauslera62636f2018-10-08 22:35:191032 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:331033 bool argOk{false};
1034 switch (d.rank) {
1035 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:541036 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331037 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:191038 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:331039 }
peter klauslera62636f2018-10-08 22:35:191040 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:331041 break;
peter klauslera62636f2018-10-08 22:35:191042 case Rank::scalar: argOk = rank == 0; break;
1043 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:331044 case Rank::shape:
peter klauslerb65572d2019-04-03 23:04:131045 CHECK(!shapeArgSize.has_value());
1046 if (rank == 1) {
peter klausler146e13c2019-04-18 21:11:151047 if (auto shape{GetShape(context, *arg)}) {
peter klausler28184c42019-04-04 20:58:461048 if (auto constShape{AsConstantShape(*shape)}) {
peter klausler59342b02019-05-13 16:33:181049 shapeArgSize = constShape->At(ConstantSubscripts{1}).ToInt64();
peter klausler28184c42019-04-04 20:58:461050 CHECK(shapeArgSize >= 0);
1051 argOk = true;
peter klauslerb65572d2019-04-03 23:04:131052 }
1053 }
1054 }
1055 if (!argOk) {
1056 messages.Say(
1057 "'shape=' argument must be a vector of known size"_err_en_US);
1058 return std::nullopt;
1059 }
peter klauslera70f5962018-10-04 20:43:331060 break;
peter klauslera62636f2018-10-08 22:35:191061 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:331062 case Rank::array:
peter klauslera62636f2018-10-08 22:35:191063 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:331064 if (!arrayArg) {
1065 arrayArg = arg;
1066 } else {
peter klauslera62636f2018-10-08 22:35:191067 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:331068 }
1069 break;
1070 case Rank::known:
1071 CHECK(knownArg == nullptr);
1072 knownArg = arg;
1073 argOk = true;
1074 break;
1075 case Rank::anyOrAssumedRank: argOk = true; break;
1076 case Rank::conformable:
1077 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191078 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:331079 break;
1080 case Rank::dimRemoved:
1081 CHECK(arrayArg != nullptr);
1082 if (hasDimArg) {
peter klauslerc3ce68c2019-05-30 23:14:241083 argOk = rank == 0 || rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:331084 } else {
peter klauslera62636f2018-10-08 22:35:191085 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:331086 }
1087 break;
peter klauslerad9aede2018-10-11 21:51:141088 case Rank::reduceOperation:
1089 // TODO: Confirm that the argument is a pure function
1090 // of two arguments with several constraints
1091 CHECK(arrayArg != nullptr);
1092 argOk = rank == 0;
1093 break;
peter klauslera70f5962018-10-04 20:43:331094 case Rank::dimReduced:
1095 case Rank::rankPlus1:
1096 case Rank::shaped:
1097 common::die("INTERNAL: result-only rank code appears on argument '%s' "
1098 "for intrinsic '%s'",
1099 d.keyword, name);
1100 default: CRASH_NO_CASE;
1101 }
1102 if (!argOk) {
peter klausler7bda1b32018-10-12 23:01:551103 messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:191104 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:331105 return std::nullopt;
1106 }
1107 }
1108 }
1109
peter klauslera70f5962018-10-04 20:43:331110 // Calculate the characteristics of the function result, if any
peter klausleref9dd9d2018-10-17 22:09:481111 std::optional<DynamicType> resultType;
peter klausler25e6f032019-05-03 18:29:151112 if (auto category{result.categorySet.LeastElement()}) {
1113 // The intrinsic is not a subroutine.
peter klausleref9dd9d2018-10-17 22:09:481114 if (call.isSubroutineCall) {
1115 return std::nullopt;
1116 }
peter klausleref9dd9d2018-10-17 22:09:481117 switch (result.kindCode) {
1118 case KindCode::defaultIntegerKind:
1119 CHECK(result.categorySet == IntType);
peter klausler25e6f032019-05-03 18:29:151120 CHECK(*category == TypeCategory::Integer);
1121 resultType = DynamicType{TypeCategory::Integer,
1122 defaults.GetDefaultKind(TypeCategory::Integer)};
peter klausleref9dd9d2018-10-17 22:09:481123 break;
1124 case KindCode::defaultRealKind:
peter klausler25e6f032019-05-03 18:29:151125 CHECK(result.categorySet == CategorySet{*category});
1126 CHECK(FloatingType.test(*category));
1127 resultType =
1128 DynamicType{*category, defaults.GetDefaultKind(TypeCategory::Real)};
peter klausleref9dd9d2018-10-17 22:09:481129 break;
1130 case KindCode::doublePrecision:
1131 CHECK(result.categorySet == RealType);
peter klausler25e6f032019-05-03 18:29:151132 CHECK(*category == TypeCategory::Real);
1133 resultType =
1134 DynamicType{TypeCategory::Real, defaults.doublePrecisionKind()};
peter klausleref9dd9d2018-10-17 22:09:481135 break;
1136 case KindCode::defaultCharKind:
1137 CHECK(result.categorySet == CharType);
peter klausler25e6f032019-05-03 18:29:151138 CHECK(*category == TypeCategory::Character);
1139 resultType = DynamicType{TypeCategory::Character,
1140 defaults.GetDefaultKind(TypeCategory::Character)};
peter klausleref9dd9d2018-10-17 22:09:481141 break;
1142 case KindCode::defaultLogicalKind:
1143 CHECK(result.categorySet == LogicalType);
peter klausler25e6f032019-05-03 18:29:151144 CHECK(*category == TypeCategory::Logical);
1145 resultType = DynamicType{TypeCategory::Logical,
1146 defaults.GetDefaultKind(TypeCategory::Logical)};
peter klausleref9dd9d2018-10-17 22:09:481147 break;
1148 case KindCode::same:
1149 CHECK(sameArg != nullptr);
1150 if (std::optional<DynamicType> aType{sameArg->GetType()}) {
peter klausler59342b02019-05-13 16:33:181151 if (result.categorySet.test(aType->category())) {
peter klausleref9dd9d2018-10-17 22:09:481152 resultType = *aType;
1153 } else {
peter klausler59342b02019-05-13 16:33:181154 resultType = DynamicType{*category, aType->kind()};
peter klausleref9dd9d2018-10-17 22:09:481155 }
1156 }
1157 break;
1158 case KindCode::effectiveKind:
1159 CHECK(kindDummyArg != nullptr);
peter klausler25e6f032019-05-03 18:29:151160 CHECK(result.categorySet == CategorySet{*category});
peter klausleref9dd9d2018-10-17 22:09:481161 if (kindArg != nullptr) {
peter klauslerd29530e2019-05-21 23:58:461162 if (auto *expr{kindArg->UnwrapExpr()}) {
peter klausler146e13c2019-04-18 21:11:151163 CHECK(expr->Rank() == 0);
1164 if (auto code{ToInt64(*expr)}) {
peter klausler25e6f032019-05-03 18:29:151165 if (IsValidKindOfIntrinsicType(*category, *code)) {
1166 resultType = DynamicType{*category, static_cast<int>(*code)};
peter klausler146e13c2019-04-18 21:11:151167 break;
1168 }
peter klauslerf7f2a732018-10-09 19:07:291169 }
1170 }
peter klausleref9dd9d2018-10-17 22:09:481171 messages.Say("'kind=' argument must be a constant scalar integer "
1172 "whose value is a supported kind for the "
1173 "intrinsic result type"_err_en_US);
1174 return std::nullopt;
1175 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
1176 CHECK(sameArg != nullptr);
1177 resultType = *sameArg->GetType();
1178 } else if (kindDummyArg->optionality ==
1179 Optionality::defaultsToSubscriptKind) {
peter klausler25e6f032019-05-03 18:29:151180 CHECK(*category == TypeCategory::Integer);
1181 resultType =
1182 DynamicType{TypeCategory::Integer, defaults.subscriptIntegerKind()};
peter klausleref9dd9d2018-10-17 22:09:481183 } else {
1184 CHECK(kindDummyArg->optionality ==
1185 Optionality::defaultsToDefaultForResult);
peter klausler25e6f032019-05-03 18:29:151186 resultType = DynamicType{*category, defaults.GetDefaultKind(*category)};
peter klauslerf7f2a732018-10-09 19:07:291187 }
peter klausleref9dd9d2018-10-17 22:09:481188 break;
1189 case KindCode::likeMultiply:
1190 CHECK(dummies >= 2);
1191 CHECK(actualForDummy[0] != nullptr);
1192 CHECK(actualForDummy[1] != nullptr);
1193 resultType = actualForDummy[0]->GetType()->ResultTypeForMultiply(
1194 *actualForDummy[1]->GetType());
1195 break;
1196 case KindCode::typeless:
1197 case KindCode::teamType:
1198 case KindCode::any:
1199 case KindCode::kindArg:
1200 case KindCode::dimArg:
1201 common::die(
1202 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
1203 break;
1204 default: CRASH_NO_CASE;
peter klauslera70f5962018-10-04 20:43:331205 }
peter klausler25e6f032019-05-03 18:29:151206 } else {
1207 if (!call.isSubroutineCall) {
1208 return std::nullopt;
1209 }
1210 CHECK(result.kindCode == KindCode::none);
peter klauslera70f5962018-10-04 20:43:331211 }
1212
peter klauslerf7f2a732018-10-09 19:07:291213 // At this point, the call is acceptable.
peter klauslera70f5962018-10-04 20:43:331214 // Determine the rank of the function result.
1215 int resultRank{0};
1216 switch (rank) {
1217 case Rank::elemental: resultRank = elementalRank; break;
1218 case Rank::scalar: resultRank = 0; break;
1219 case Rank::vector: resultRank = 1; break;
1220 case Rank::matrix: resultRank = 2; break;
peter klauslerf7f2a732018-10-09 19:07:291221 case Rank::conformable:
1222 CHECK(arrayArg != nullptr);
1223 resultRank = arrayArg->Rank();
1224 break;
peter klauslera70f5962018-10-04 20:43:331225 case Rank::dimReduced:
1226 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191227 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:331228 break;
peter klausler00e128e2019-06-25 20:07:321229 case Rank::dimRemoved:
1230 CHECK(arrayArg != nullptr);
1231 resultRank = arrayArg->Rank() - 1;
1232 break;
peter klauslera70f5962018-10-04 20:43:331233 case Rank::rankPlus1:
1234 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191235 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:331236 break;
1237 case Rank::shaped:
peter klauslerb65572d2019-04-03 23:04:131238 CHECK(shapeArgSize.has_value());
1239 resultRank = *shapeArgSize;
peter klauslera70f5962018-10-04 20:43:331240 break;
peter klauslercb308d32018-10-05 18:32:541241 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331242 case Rank::shape:
1243 case Rank::array:
1244 case Rank::known:
1245 case Rank::anyOrAssumedRank:
peter klauslerad9aede2018-10-11 21:51:141246 case Rank::reduceOperation:
peter klauslera70f5962018-10-04 20:43:331247 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
1248 break;
1249 default: CRASH_NO_CASE;
1250 }
1251 CHECK(resultRank >= 0);
1252
peter klausleref9dd9d2018-10-17 22:09:481253 // Rearrange the actual arguments into dummy argument order.
1254 ActualArguments rearranged(dummies);
peter klausler84ea49d2018-10-18 17:50:551255 for (std::size_t j{0}; j < dummies; ++j) {
peter klausleref9dd9d2018-10-17 22:09:481256 if (ActualArgument * arg{actualForDummy[j]}) {
peter klausler84ea49d2018-10-18 17:50:551257 rearranged[j] = std::move(*arg);
peter klausleref9dd9d2018-10-17 22:09:481258 }
1259 }
1260
peter klausler25e6f032019-05-03 18:29:151261 // Characterize the specific intrinsic function.
1262 characteristics::TypeAndShape typeAndShape{resultType.value(), resultRank};
1263 characteristics::FunctionResult funcResult{std::move(typeAndShape)};
1264 characteristics::DummyArguments dummyArgs;
1265 std::optional<int> sameDummyArg;
1266 for (std::size_t j{0}; j < dummies; ++j) {
1267 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
1268 if (const auto &arg{rearranged[j]}) {
peter klauslerd29530e2019-05-21 23:58:461269 const Expr<SomeType> *expr{arg->UnwrapExpr()};
peter klausler25e6f032019-05-03 18:29:151270 CHECK(expr != nullptr);
1271 std::optional<characteristics::TypeAndShape> typeAndShape;
1272 if (auto type{expr->GetType()}) {
1273 if (auto shape{GetShape(context, *expr)}) {
1274 typeAndShape.emplace(*type, std::move(*shape));
1275 } else {
1276 typeAndShape.emplace(*type);
1277 }
1278 } else {
1279 typeAndShape.emplace(DynamicType::TypelessIntrinsicArgument());
1280 }
1281 dummyArgs.emplace_back(
1282 characteristics::DummyDataObject{std::move(typeAndShape.value())});
1283 if (d.typePattern.kindCode == KindCode::same &&
1284 !sameDummyArg.has_value()) {
1285 sameDummyArg = j;
1286 }
1287 } else {
1288 // optional argument is absent
1289 CHECK(d.optionality != Optionality::required);
1290 if (d.typePattern.kindCode == KindCode::same) {
1291 dummyArgs.emplace_back(dummyArgs[sameDummyArg.value()]);
1292 } else {
1293 auto category{d.typePattern.categorySet.LeastElement().value()};
1294 characteristics::TypeAndShape typeAndShape{
1295 DynamicType{category, defaults.GetDefaultKind(category)}};
1296 dummyArgs.emplace_back(
1297 characteristics::DummyDataObject{std::move(typeAndShape)});
1298 }
1299 std::get<characteristics::DummyDataObject>(dummyArgs.back())
1300 .attrs.set(characteristics::DummyDataObject::Attr::Optional);
1301 }
1302 }
1303 characteristics::Procedure::Attrs attrs;
1304 if (elementalRank > 0) {
1305 attrs.set(characteristics::Procedure::Attr::Elemental);
1306 }
1307 characteristics::Procedure chars{
1308 std::move(funcResult), std::move(dummyArgs), attrs};
1309
1310 return SpecificCall{
1311 SpecificIntrinsic{name, std::move(chars)}, std::move(rearranged)};
peter klauslera70f5962018-10-04 20:43:331312}
1313
peter klauslerba56b912019-02-22 23:45:301314class IntrinsicProcTable::Implementation {
1315public:
peter klauslerf9d6c0a2019-01-18 20:40:471316 explicit Implementation(const common::IntrinsicTypeDefaultKinds &dfts)
peter klauslerba56b912019-02-22 23:45:301317 : defaults_{dfts} {
peter klauslera70f5962018-10-04 20:43:331318 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
peter klauslerba56b912019-02-22 23:45:301319 genericFuncs_.insert(std::make_pair(std::string{f.name}, &f));
peter klauslera70f5962018-10-04 20:43:331320 }
1321 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
peter klauslerba56b912019-02-22 23:45:301322 specificFuncs_.insert(std::make_pair(std::string{f.name}, &f));
peter klauslera70f5962018-10-04 20:43:331323 }
1324 }
peter klausler42b33da2018-09-29 00:02:111325
peter klauslerf9535832019-02-26 22:26:281326 bool IsIntrinsic(const std::string &) const;
1327
peter klausler25e6f032019-05-03 18:29:151328 std::optional<SpecificCall> Probe(const CallCharacteristics &,
1329 ActualArguments &, FoldingContext &, const IntrinsicProcTable &) const;
peter klausler75a32092018-10-05 16:57:531330
peter klauslerba56b912019-02-22 23:45:301331 std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1332 IsUnrestrictedSpecificIntrinsicFunction(const std::string &) const;
1333
peter klausler7bda1b32018-10-12 23:01:551334 std::ostream &Dump(std::ostream &) const;
peter klauslerba56b912019-02-22 23:45:301335
1336private:
peter klausler25e6f032019-05-03 18:29:151337 DynamicType GetSpecificType(const TypePattern &) const;
1338 SpecificCall HandleNull(
1339 ActualArguments &, FoldingContext &, const IntrinsicProcTable &) const;
1340
peter klauslerba56b912019-02-22 23:45:301341 common::IntrinsicTypeDefaultKinds defaults_;
1342 std::multimap<std::string, const IntrinsicInterface *> genericFuncs_;
1343 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs_;
peter klausler42b33da2018-09-29 00:02:111344};
1345
peter klauslerf9535832019-02-26 22:26:281346bool IntrinsicProcTable::Implementation::IsIntrinsic(
1347 const std::string &name) const {
1348 auto specificRange{specificFuncs_.equal_range(name)};
1349 if (specificRange.first != specificRange.second) {
1350 return true;
1351 }
1352 auto genericRange{genericFuncs_.equal_range(name)};
1353 if (genericRange.first != genericRange.second) {
1354 return true;
1355 }
1356 // special cases
1357 return name == "null"; // TODO more
1358}
1359
peter klausler25e6f032019-05-03 18:29:151360// The NULL() intrinsic is a special case.
1361SpecificCall IntrinsicProcTable::Implementation::HandleNull(
1362 ActualArguments &arguments, FoldingContext &context,
1363 const IntrinsicProcTable &intrinsics) const {
1364 if (!arguments.empty()) {
1365 if (arguments.size() > 1) {
1366 context.messages().Say("Too many arguments to NULL()"_err_en_US);
1367 } else if (arguments[0].has_value() && arguments[0]->keyword.has_value() &&
1368 arguments[0]->keyword->ToString() != "mold") {
1369 context.messages().Say("Unknown argument '%s' to NULL()"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451370 arguments[0]->keyword->ToString());
peter klausler25e6f032019-05-03 18:29:151371 } else {
peter klauslerd29530e2019-05-21 23:58:461372 if (Expr<SomeType> * mold{arguments[0]->UnwrapExpr()}) {
peter klausler25e6f032019-05-03 18:29:151373 if (IsAllocatableOrPointer(*mold)) {
1374 characteristics::DummyArguments args;
1375 std::optional<characteristics::FunctionResult> fResult;
1376 if (IsProcedurePointer(*mold)) {
1377 // MOLD= procedure pointer
1378 const Symbol *last{GetLastSymbol(*mold)};
1379 CHECK(last != nullptr);
1380 auto procPointer{
1381 characteristics::Procedure::Characterize(*last, intrinsics)};
1382 characteristics::DummyProcedure dp{
1383 common::Clone(procPointer.value())};
1384 args.emplace_back(std::move(dp));
1385 fResult.emplace(std::move(procPointer.value()));
1386 } else if (auto type{mold->GetType()}) {
1387 // MOLD= object pointer
1388 std::optional<characteristics::TypeAndShape> typeAndShape;
1389 if (auto shape{GetShape(context, *mold)}) {
1390 typeAndShape.emplace(*type, std::move(*shape));
1391 } else {
1392 typeAndShape.emplace(*type);
1393 }
1394 characteristics::DummyDataObject ddo{typeAndShape.value()};
1395 args.emplace_back(std::move(ddo));
1396 fResult.emplace(std::move(*typeAndShape));
1397 } else {
1398 context.messages().Say(
1399 "MOLD= argument to NULL() lacks type"_err_en_US);
1400 }
1401 fResult->attrs.set(characteristics::FunctionResult::Attr::Pointer);
1402 characteristics::Procedure::Attrs attrs;
1403 attrs.set(characteristics::Procedure::Attr::NullPointer);
1404 characteristics::Procedure chars{
1405 std::move(*fResult), std::move(args), attrs};
1406 return SpecificCall{SpecificIntrinsic{"null"s, std::move(chars)},
1407 std::move(arguments)};
1408 }
1409 }
1410 context.messages().Say(
1411 "MOLD= argument to NULL() must be a pointer or allocatable"_err_en_US);
1412 }
1413 }
1414 characteristics::Procedure::Attrs attrs;
1415 attrs.set(characteristics::Procedure::Attr::NullPointer);
1416 arguments.clear();
1417 return SpecificCall{
1418 SpecificIntrinsic{"null"s,
1419 characteristics::Procedure{characteristics::DummyArguments{}, attrs}},
1420 std::move(arguments)};
1421}
1422
peter klausler4f2c8fa2019-06-19 18:50:071423// Applies any semantic checks peculiar to an intrinsic.
1424static bool ApplySpecificChecks(
1425 SpecificCall &call, parser::ContextualMessages &messages) {
1426 bool ok{true};
1427 const std::string &name{call.specificIntrinsic.name};
1428 if (name == "allocated") {
1429 if (const auto &arg{call.arguments[0]}) {
1430 if (const auto *expr{arg->UnwrapExpr()}) {
1431 if (const Symbol * symbol{GetLastSymbol(*expr)}) {
1432 ok = symbol->has<semantics::ObjectEntityDetails>() &&
1433 symbol->attrs().test(semantics::Attr::ALLOCATABLE);
1434 }
1435 }
1436 }
1437 if (!ok) {
1438 messages.Say(
1439 "Argument of ALLOCATED() must be an ALLOCATABLE object or component"_err_en_US);
1440 }
peter klauslera0e50522019-06-21 21:04:401441 } else if (name == "associated") {
1442 if (const auto &arg{call.arguments[0]}) {
1443 if (const auto *expr{arg->UnwrapExpr()}) {
1444 if (const Symbol * symbol{GetLastSymbol(*expr)}) {
1445 ok = symbol->attrs().test(semantics::Attr::POINTER);
1446 // TODO: validate the TARGET= argument vs. the pointer
1447 }
1448 }
1449 }
1450 if (!ok) {
1451 messages.Say(
1452 "Arguments of ASSOCIATED() must be a POINTER and an optional valid target"_err_en_US);
1453 }
peter klausler4f2c8fa2019-06-19 18:50:071454 } else if (name == "present") {
1455 if (const auto &arg{call.arguments[0]}) {
1456 if (const auto *expr{arg->UnwrapExpr()}) {
1457 if (const Symbol * symbol{UnwrapWholeSymbolDataRef(*expr)}) {
1458 ok = symbol->attrs().test(semantics::Attr::OPTIONAL);
1459 }
1460 }
1461 }
1462 if (!ok) {
1463 messages.Say(
1464 "Argument of PRESENT() must be the name of an OPTIONAL dummy argument"_err_en_US);
1465 }
1466 }
1467 return ok;
peter klauslercedf98c2019-06-19 19:37:491468}
peter klausler4f2c8fa2019-06-19 18:50:071469
peter klauslercb308d32018-10-05 18:32:541470// Probe the configured intrinsic procedure pattern tables in search of a
1471// match for a given procedure reference.
peter klausleref9dd9d2018-10-17 22:09:481472std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
1473 const CallCharacteristics &call, ActualArguments &arguments,
peter klausler25e6f032019-05-03 18:29:151474 FoldingContext &context, const IntrinsicProcTable &intrinsics) const {
peter klausler75a32092018-10-05 16:57:531475 if (call.isSubroutineCall) {
1476 return std::nullopt; // TODO
1477 }
peter klausler146e13c2019-04-18 21:11:151478 parser::Messages *finalBuffer{context.messages().messages()};
peter klausler25e6f032019-05-03 18:29:151479 // Special case: NULL()
peter klausler737fe292019-06-26 22:30:531480 // All special cases handled here before the table probes below must
1481 // also be caught as special names in IsIntrinsic().
peter klausler59342b02019-05-13 16:33:181482 if (call.name == "null") {
peter klausler25e6f032019-05-03 18:29:151483 parser::Messages nullBuffer;
1484 parser::ContextualMessages nullErrors{
1485 call.name, finalBuffer ? &nullBuffer : nullptr};
1486 FoldingContext nullContext{context, nullErrors};
1487 auto result{HandleNull(arguments, nullContext, intrinsics)};
1488 if (finalBuffer != nullptr) {
1489 finalBuffer->Annex(std::move(nullBuffer));
1490 }
1491 return result;
1492 }
peter klausler8a326cb2019-06-05 22:40:591493 // Probe the generic intrinsic function table first.
1494 parser::Messages localBuffer;
peter klausler59342b02019-05-13 16:33:181495 parser::ContextualMessages localMessages{
1496 call.name, finalBuffer ? &localBuffer : nullptr};
1497 FoldingContext localContext{context, localMessages};
peter klausler75a32092018-10-05 16:57:531498 std::string name{call.name.ToString()};
peter klausler62425d62018-10-12 00:01:311499 parser::Messages genericBuffer;
peter klauslerba56b912019-02-22 23:45:301500 auto genericRange{genericFuncs_.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531501 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klausler5774f0a2019-06-04 17:50:341502 CHECK(localBuffer.empty());
peter klausleref9dd9d2018-10-17 22:09:481503 if (auto specificCall{
peter klausler59342b02019-05-13 16:33:181504 iter->second->Match(call, defaults_, arguments, localContext)}) {
peter klausler4f2c8fa2019-06-19 18:50:071505 ApplySpecificChecks(*specificCall, localMessages);
peter klausler59342b02019-05-13 16:33:181506 if (finalBuffer != nullptr) {
1507 finalBuffer->Annex(std::move(localBuffer));
1508 }
peter klausleref9dd9d2018-10-17 22:09:481509 return specificCall;
peter klausler59342b02019-05-13 16:33:181510 } else {
1511 genericBuffer.Annex(std::move(localBuffer));
peter klausler75a32092018-10-05 16:57:531512 }
1513 }
peter klausler8a326cb2019-06-05 22:40:591514 // Probe the specific intrinsic function table next.
1515 // Each specific intrinsic maps to a generic intrinsic.
1516 parser::Messages specificBuffer;
1517 auto specificRange{specificFuncs_.equal_range(name)};
1518 for (auto specIter{specificRange.first}; specIter != specificRange.second;
1519 ++specIter) {
1520 // We only need to check the cases with distinct generic names.
1521 if (const char *genericName{specIter->second->generic}) {
1522 auto genericRange{genericFuncs_.equal_range(genericName)};
1523 for (auto genIter{genericRange.first}; genIter != genericRange.second;
1524 ++genIter) {
1525 CHECK(localBuffer.empty());
1526 if (auto specificCall{genIter->second->Match(
1527 call, defaults_, arguments, localContext)}) {
1528 specificCall->specificIntrinsic.name = genericName;
1529 specificCall->specificIntrinsic.isRestrictedSpecific =
1530 specIter->second->isRestrictedSpecific;
1531 if (finalBuffer != nullptr) {
1532 finalBuffer->Annex(std::move(localBuffer));
1533 }
1534 if (specIter->second->forceResultType) {
1535 // Force the result type on AMAX0/1, MIN0/1, &c.
1536 TypeCategory category{TypeCategory::Integer};
1537 switch (specIter->second->result.kindCode) {
1538 case KindCode::defaultIntegerKind: break;
1539 case KindCode::defaultRealKind:
1540 category = TypeCategory::Real;
1541 break;
1542 default: CRASH_NO_CASE;
1543 }
1544 DynamicType newType{category, defaults_.GetDefaultKind(category)};
1545 specificCall->specificIntrinsic.characteristics.value()
1546 .functionResult.value()
1547 .SetType(newType);
1548 }
peter klauslera0e50522019-06-21 21:04:401549 // TODO test feature AdditionalIntrinsics, warn on nonstandard
1550 // specifics with DoublePrecisionComplex arguments.
peter klausler8a326cb2019-06-05 22:40:591551 return specificCall;
1552 } else {
1553 specificBuffer.Annex(std::move(localBuffer));
1554 }
1555 }
1556 }
1557 }
peter klausler25e6f032019-05-03 18:29:151558 // No match; report the right errors, if any
peter klausler146e13c2019-04-18 21:11:151559 if (finalBuffer != nullptr) {
peter klausler8a326cb2019-06-05 22:40:591560 if (specificBuffer.empty()) {
peter klausler7bda1b32018-10-12 23:01:551561 finalBuffer->Annex(std::move(genericBuffer));
peter klausler8a326cb2019-06-05 22:40:591562 } else {
1563 finalBuffer->Annex(std::move(specificBuffer));
peter klausler62425d62018-10-12 00:01:311564 }
peter klauslercb308d32018-10-05 18:32:541565 }
peter klausler75a32092018-10-05 16:57:531566 return std::nullopt;
1567}
1568
peter klauslerba56b912019-02-22 23:45:301569std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1570IntrinsicProcTable::Implementation::IsUnrestrictedSpecificIntrinsicFunction(
1571 const std::string &name) const {
1572 auto specificRange{specificFuncs_.equal_range(name)};
1573 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
1574 const SpecificIntrinsicInterface &specific{*iter->second};
1575 if (!specific.isRestrictedSpecific) {
peter klausler25e6f032019-05-03 18:29:151576 std::string genericName{name};
peter klauslerba56b912019-02-22 23:45:301577 if (specific.generic != nullptr) {
peter klausler25e6f032019-05-03 18:29:151578 genericName = std::string(specific.generic);
peter klauslerba56b912019-02-22 23:45:301579 }
peter klausler25e6f032019-05-03 18:29:151580 characteristics::FunctionResult fResult{GetSpecificType(specific.result)};
1581 characteristics::DummyArguments args;
peter klauslerf9535832019-02-26 22:26:281582 int dummies{specific.CountArguments()};
1583 for (int j{0}; j < dummies; ++j) {
1584 characteristics::DummyDataObject dummy{
1585 GetSpecificType(specific.dummy[j].typePattern)};
1586 dummy.intent = common::Intent::In;
peter klausler25e6f032019-05-03 18:29:151587 args.emplace_back(std::move(dummy));
peter klauslerf9535832019-02-26 22:26:281588 }
peter klausler25e6f032019-05-03 18:29:151589 characteristics::Procedure::Attrs attrs;
1590 attrs.set(characteristics::Procedure::Attr::Pure)
1591 .set(characteristics::Procedure::Attr::Elemental);
1592 characteristics::Procedure chars{
1593 std::move(fResult), std::move(args), attrs};
1594 return UnrestrictedSpecificIntrinsicFunctionInterface{
1595 std::move(chars), genericName};
peter klauslerba56b912019-02-22 23:45:301596 }
1597 }
1598 return std::nullopt;
1599}
1600
1601DynamicType IntrinsicProcTable::Implementation::GetSpecificType(
1602 const TypePattern &pattern) const {
1603 const CategorySet &set{pattern.categorySet};
1604 CHECK(set.count() == 1);
1605 TypeCategory category{set.LeastElement().value()};
1606 return DynamicType{category, defaults_.GetDefaultKind(category)};
1607}
1608
peter klauslera62636f2018-10-08 22:35:191609IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:541610 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:111611 delete impl_;
1612 impl_ = nullptr;
1613}
1614
peter klauslera62636f2018-10-08 22:35:191615IntrinsicProcTable IntrinsicProcTable::Configure(
peter klauslerf9d6c0a2019-01-18 20:40:471616 const common::IntrinsicTypeDefaultKinds &defaults) {
peter klauslera62636f2018-10-08 22:35:191617 IntrinsicProcTable result;
1618 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:111619 return result;
1620}
1621
peter klauslerf9535832019-02-26 22:26:281622bool IntrinsicProcTable::IsIntrinsic(const std::string &name) const {
1623 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
1624 return impl_->IsIntrinsic(name);
1625}
1626
peter klausleref9dd9d2018-10-17 22:09:481627std::optional<SpecificCall> IntrinsicProcTable::Probe(
1628 const CallCharacteristics &call, ActualArguments &arguments,
peter klausler146e13c2019-04-18 21:11:151629 FoldingContext &context) const {
peter klauslera62636f2018-10-08 22:35:191630 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klausler25e6f032019-05-03 18:29:151631 return impl_->Probe(call, arguments, context, *this);
peter klausler42b33da2018-09-29 00:02:111632}
peter klauslerad9aede2018-10-11 21:51:141633
peter klauslerba56b912019-02-22 23:45:301634std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1635IntrinsicProcTable::IsUnrestrictedSpecificIntrinsicFunction(
1636 const std::string &name) const {
1637 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
1638 return impl_->IsUnrestrictedSpecificIntrinsicFunction(name);
1639}
1640
peter klausler7bda1b32018-10-12 23:01:551641std::ostream &TypePattern::Dump(std::ostream &o) const {
1642 if (categorySet == AnyType) {
1643 o << "any type";
1644 } else {
1645 const char *sep = "";
1646 auto set{categorySet};
1647 while (auto least{set.LeastElement()}) {
1648 o << sep << EnumToString(*least);
1649 sep = " or ";
1650 set.reset(*least);
1651 }
1652 }
1653 o << '(' << EnumToString(kindCode) << ')';
1654 return o;
1655}
1656
1657std::ostream &IntrinsicDummyArgument::Dump(std::ostream &o) const {
1658 if (keyword) {
1659 o << keyword << '=';
1660 }
1661 return typePattern.Dump(o)
1662 << ' ' << EnumToString(rank) << ' ' << EnumToString(optionality);
1663}
1664
1665std::ostream &IntrinsicInterface::Dump(std::ostream &o) const {
1666 o << name;
1667 char sep{'('};
1668 for (const auto &d : dummy) {
1669 if (d.typePattern.kindCode == KindCode::none) {
1670 break;
1671 }
1672 d.Dump(o << sep);
1673 sep = ',';
1674 }
1675 if (sep == '(') {
1676 o << "()";
1677 }
1678 return result.Dump(o << " -> ") << ' ' << EnumToString(rank);
1679}
1680
1681std::ostream &IntrinsicProcTable::Implementation::Dump(std::ostream &o) const {
1682 o << "generic intrinsic functions:\n";
peter klauslerba56b912019-02-22 23:45:301683 for (const auto &iter : genericFuncs_) {
peter klausler7bda1b32018-10-12 23:01:551684 iter.second->Dump(o << iter.first << ": ") << '\n';
1685 }
1686 o << "specific intrinsic functions:\n";
peter klauslerba56b912019-02-22 23:45:301687 for (const auto &iter : specificFuncs_) {
peter klausler7bda1b32018-10-12 23:01:551688 iter.second->Dump(o << iter.first << ": ");
1689 if (const char *g{iter.second->generic}) {
1690 o << " -> " << g;
1691 }
1692 o << '\n';
1693 }
1694 return o;
1695}
1696
1697std::ostream &IntrinsicProcTable::Dump(std::ostream &o) const {
1698 return impl_->Dump(o);
1699}
Jean Perierf7e7cb32018-10-25 12:55:231700}