blob: 5c65f75c94a390e3f3fa4fef4057d9fd13f25d80 [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 klauslera62636f2018-10-08 22:35:1916#include "expression.h"
peter klauslerfe3acf5f2019-01-07 18:15:2717#include "fold.h"
peter klauslerb65572d2019-04-03 23:04:1318#include "shape.h"
peter klauslerabac2282018-10-26 22:10:2419#include "tools.h"
peter klausler42b33da2018-09-29 00:02:1120#include "type.h"
peter klauslerab74d1a2019-02-28 18:48:4121#include "../common/Fortran.h"
peter klausler42b33da2018-09-29 00:02:1122#include "../common/enum-set.h"
peter klauslera70f5962018-10-04 20:43:3323#include "../common/idioms.h"
peter klausler84ea49d2018-10-18 17:50:5524#include <algorithm>
peter klauslera70f5962018-10-04 20:43:3325#include <map>
peter klausler7bda1b32018-10-12 23:01:5526#include <ostream>
27#include <sstream>
peter klauslera70f5962018-10-04 20:43:3328#include <string>
29#include <utility>
peter klausler42b33da2018-09-29 00:02:1130
peter klauslercb308d32018-10-05 18:32:5431using namespace Fortran::parser::literals;
32
peter klausler42b33da2018-09-29 00:02:1133namespace Fortran::evaluate {
34
35using common::TypeCategory;
36
peter klauslera70f5962018-10-04 20:43:3337// This file defines the supported intrinsic procedures and implements
38// their recognition and validation. It is largely table-driven. See
39// documentation/intrinsics.md and section 16 of the Fortran 2018 standard
40// for full details on each of the intrinsics. Be advised, they have
41// complicated details, and the design of these tables has to accommodate
42// that complexity.
43
peter klausler42b33da2018-09-29 00:02:1144// Dummy arguments to generic intrinsic procedures are each specified by
peter klauslera70f5962018-10-04 20:43:3345// their keyword name (rarely used, but always defined), allowable type
peter klauslercb308d32018-10-05 18:32:5446// categories, a kind pattern, a rank pattern, and information about
47// optionality and defaults. The kind and rank patterns are represented
48// here with code values that are significant to the matching/validation engine.
peter klausler42b33da2018-09-29 00:02:1149
peter klauslera70f5962018-10-04 20:43:3350// These are small bit-sets of type category enumerators.
51// Note that typeless (BOZ literal) values don't have a distinct type category.
52// These typeless arguments are represented in the tables as if they were
53// INTEGER with a special "typeless" kind code. Arguments of intrinsic types
peter klauslercb308d32018-10-05 18:32:5454// that can also be be typeless values are encoded with an "elementalOrBOZ"
55// rank pattern.
peter klauslera70f5962018-10-04 20:43:3356using CategorySet = common::EnumSet<TypeCategory, 8>;
peter klausler51b09b62018-10-15 19:17:3057static constexpr CategorySet IntType{TypeCategory::Integer};
58static constexpr CategorySet RealType{TypeCategory::Real};
59static constexpr CategorySet ComplexType{TypeCategory::Complex};
60static constexpr CategorySet CharType{TypeCategory::Character};
61static constexpr CategorySet LogicalType{TypeCategory::Logical};
62static constexpr CategorySet IntOrRealType{IntType | RealType};
63static constexpr CategorySet FloatingType{RealType | ComplexType};
64static constexpr CategorySet NumericType{IntType | RealType | ComplexType};
65static constexpr CategorySet RelatableType{IntType | RealType | CharType};
peter klauslera70f5962018-10-04 20:43:3366static constexpr CategorySet IntrinsicType{
peter klausler51b09b62018-10-15 19:17:3067 IntType | RealType | ComplexType | CharType | LogicalType};
peter klauslera70f5962018-10-04 20:43:3368static constexpr CategorySet AnyType{
69 IntrinsicType | CategorySet{TypeCategory::Derived}};
peter klausler42b33da2018-09-29 00:02:1170
peter klausler7bda1b32018-10-12 23:01:5571ENUM_CLASS(KindCode, none, defaultIntegerKind,
72 defaultRealKind, // is also the default COMPLEX kind
73 doublePrecision, defaultCharKind, defaultLogicalKind,
74 any, // matches any kind value; each instance is independent
75 typeless, // BOZ literals are INTEGER with this kind
76 teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
77 kindArg, // this argument is KIND=
78 effectiveKind, // for function results: same "kindArg", possibly defaulted
79 dimArg, // this argument is DIM=
80 same, // match any kind; all "same" kinds must be equal
81 likeMultiply, // for DOT_PRODUCT and MATMUL
82)
peter klausler42b33da2018-09-29 00:02:1183
84struct TypePattern {
85 CategorySet categorySet;
peter klauslerb22d4942018-10-01 18:27:4586 KindCode kindCode{KindCode::none};
peter klausler7bda1b32018-10-12 23:01:5587 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:1188};
89
peter klauslera70f5962018-10-04 20:43:3390// Abbreviations for argument and result patterns in the intrinsic prototypes:
91
92// Match specific kinds of intrinsic types
peter klausler7c402d92018-10-16 21:42:2293static constexpr TypePattern DefaultInt{IntType, KindCode::defaultIntegerKind};
94static constexpr TypePattern DefaultReal{RealType, KindCode::defaultRealKind};
95static constexpr TypePattern DefaultComplex{
96 ComplexType, KindCode::defaultRealKind};
97static constexpr TypePattern DefaultChar{CharType, KindCode::defaultCharKind};
98static constexpr TypePattern DefaultLogical{
peter klausler51b09b62018-10-15 19:17:3099 LogicalType, KindCode::defaultLogicalKind};
100static constexpr TypePattern BOZ{IntType, KindCode::typeless};
101static constexpr TypePattern TEAM_TYPE{IntType, KindCode::teamType};
102static constexpr TypePattern DoublePrecision{
103 RealType, KindCode::doublePrecision};
peter klauslera70f5962018-10-04 20:43:33104
105// Match any kind of some intrinsic or derived types
peter klausler51b09b62018-10-15 19:17:30106static constexpr TypePattern AnyInt{IntType, KindCode::any};
107static constexpr TypePattern AnyReal{RealType, KindCode::any};
108static constexpr TypePattern AnyIntOrReal{IntOrRealType, KindCode::any};
109static constexpr TypePattern AnyComplex{ComplexType, KindCode::any};
110static constexpr TypePattern AnyNumeric{NumericType, KindCode::any};
111static constexpr TypePattern AnyChar{CharType, KindCode::any};
112static constexpr TypePattern AnyLogical{LogicalType, KindCode::any};
113static constexpr TypePattern AnyRelatable{RelatableType, KindCode::any};
peter klauslerbe3b7652018-12-04 18:55:32114static constexpr TypePattern AnyIntrinsic{IntrinsicType, KindCode::any};
peter klauslerf7f2a732018-10-09 19:07:29115static constexpr TypePattern Anything{AnyType, KindCode::any};
peter klauslera70f5962018-10-04 20:43:33116
117// Match some kind of some intrinsic type(s); all "Same" values must match,
118// even when not in the same category (e.g., SameComplex and SameReal).
119// Can be used to specify a result so long as at least one argument is
120// a "Same".
peter klausler51b09b62018-10-15 19:17:30121static constexpr TypePattern SameInt{IntType, KindCode::same};
122static constexpr TypePattern SameReal{RealType, KindCode::same};
123static constexpr TypePattern SameIntOrReal{IntOrRealType, KindCode::same};
124static constexpr TypePattern SameComplex{ComplexType, KindCode::same};
125static constexpr TypePattern SameFloating{FloatingType, KindCode::same};
126static constexpr TypePattern SameNumeric{NumericType, KindCode::same};
127static constexpr TypePattern SameChar{CharType, KindCode::same};
128static constexpr TypePattern SameLogical{LogicalType, KindCode::same};
129static constexpr TypePattern SameRelatable{RelatableType, KindCode::same};
peter klauslera70f5962018-10-04 20:43:33130static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
131static constexpr TypePattern SameDerivedType{
132 CategorySet{TypeCategory::Derived}, KindCode::same};
133static constexpr TypePattern SameType{AnyType, KindCode::same};
134
peter klauslerf7f2a732018-10-09 19:07:29135// For DOT_PRODUCT and MATMUL, the result type depends on the arguments
peter klausler51b09b62018-10-15 19:17:30136static constexpr TypePattern ResultLogical{LogicalType, KindCode::likeMultiply};
137static constexpr TypePattern ResultNumeric{NumericType, KindCode::likeMultiply};
peter klauslerf7f2a732018-10-09 19:07:29138
peter klauslera70f5962018-10-04 20:43:33139// Result types with known category and KIND=
peter klausler51b09b62018-10-15 19:17:30140static constexpr TypePattern KINDInt{IntType, KindCode::effectiveKind};
141static constexpr TypePattern KINDReal{RealType, KindCode::effectiveKind};
142static constexpr TypePattern KINDComplex{ComplexType, KindCode::effectiveKind};
143static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind};
144static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11145
146// The default rank pattern for dummy arguments and function results is
147// "elemental".
peter klausler7bda1b32018-10-12 23:01:55148ENUM_CLASS(Rank,
149 elemental, // scalar, or array that conforms with other array arguments
150 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
151 scalar, vector,
152 shape, // INTEGER vector of known length and no negative element
153 matrix,
154 array, // not scalar, rank is known and greater than zero
155 known, // rank is known and can be scalar
156 anyOrAssumedRank, // rank can be unknown
157 conformable, // scalar, or array of same rank & shape as "array" argument
158 reduceOperation, // a pure function with constraints for REDUCE
159 dimReduced, // scalar if no DIM= argument, else rank(array)-1
160 dimRemoved, // scalar, or rank(array)-1
161 rankPlus1, // rank(known)+1
162 shaped, // rank is length of SHAPE vector
163)
peter klausler42b33da2018-09-29 00:02:11164
peter klausler7bda1b32018-10-12 23:01:55165ENUM_CLASS(Optionality, required, optional,
166 defaultsToSameKind, // for MatchingDefaultKIND
167 defaultsToDefaultForResult, // for DefaultingKIND
peter klausler7c402d92018-10-16 21:42:22168 defaultsToSubscriptKind, // for SubscriptDefaultKIND
peter klausler7bda1b32018-10-12 23:01:55169 repeats, // for MAX/MIN and their several variants
170)
peter klausler42b33da2018-09-29 00:02:11171
172struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45173 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11174 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33175 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54176 Optionality optionality{Optionality::required};
peter klausler7bda1b32018-10-12 23:01:55177 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11178};
179
peter klauslera70f5962018-10-04 20:43:33180// constexpr abbreviations for popular arguments:
181// DefaultingKIND is a KIND= argument whose default value is the appropriate
182// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54183static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30184 {IntType, KindCode::kindArg}, Rank::scalar,
peter klauslercb308d32018-10-05 18:32:54185 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33186// MatchingDefaultKIND is a KIND= argument whose default value is the
187// kind of any "Same" function argument (viz., the one whose kind pattern is
188// "same").
peter klauslercb308d32018-10-05 18:32:54189static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30190 {IntType, KindCode::kindArg}, Rank::scalar,
191 Optionality::defaultsToSameKind};
peter klausler7c402d92018-10-16 21:42:22192// SubscriptDefaultKind is a KIND= argument whose default value is
193// the kind of INTEGER used for address calculations.
194static constexpr IntrinsicDummyArgument SubscriptDefaultKIND{"kind",
195 {IntType, KindCode::kindArg}, Rank::scalar,
196 Optionality::defaultsToSubscriptKind};
peter klauslera70f5962018-10-04 20:43:33197static constexpr IntrinsicDummyArgument OptionalDIM{
peter klausler51b09b62018-10-15 19:17:30198 "dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33199static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54200 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11201
202struct IntrinsicInterface {
peter klausler84ea49d2018-10-18 17:50:55203 static constexpr int maxArguments{7}; // if not a MAX/MIN(...)
peter klauslerb22d4942018-10-01 18:27:45204 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11205 IntrinsicDummyArgument dummy[maxArguments];
206 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33207 Rank rank{Rank::elemental};
peter klausleref9dd9d2018-10-17 22:09:48208 std::optional<SpecificCall> Match(const CallCharacteristics &,
peter klauslerf9d6c0a2019-01-18 20:40:47209 const common::IntrinsicTypeDefaultKinds &, ActualArguments &,
peter klauslercb308d32018-10-05 18:32:54210 parser::ContextualMessages &messages) const;
peter klauslerba56b912019-02-22 23:45:30211 int CountArguments() const;
peter klausler7bda1b32018-10-12 23:01:55212 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11213};
214
peter klauslerba56b912019-02-22 23:45:30215int IntrinsicInterface::CountArguments() const {
216 int n{0};
217 while (n < maxArguments && dummy[n].keyword != nullptr) {
218 ++n;
219 }
220 return n;
221}
222
peter klausler94041d72018-10-15 20:39:51223// GENERIC INTRINSIC FUNCTION INTERFACES
224// Each entry in this table defines a pattern. Some intrinsic
225// functions have more than one such pattern. Besides the name
226// of the intrinsic function, each pattern has specifications for
227// the dummy arguments and for the result of the function.
228// The dummy argument patterns each have a name (this are from the
229// standard, but rarely appear in actual code), a type and kind
230// pattern, allowable ranks, and optionality indicators.
231// Be advised, the default rank pattern is "elemental".
peter klauslerb22d4942018-10-01 18:27:45232static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33233 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
234 {"abs", {{"a", SameComplex}}, SameReal},
peter klauslerad9aede2018-10-11 21:51:14235 {"achar", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
peter klauslera70f5962018-10-04 20:43:33236 {"acos", {{"x", SameFloating}}, SameFloating},
237 {"acosh", {{"x", SameFloating}}, SameFloating},
238 {"adjustl", {{"string", SameChar}}, SameChar},
239 {"adjustr", {{"string", SameChar}}, SameChar},
240 {"aimag", {{"x", SameComplex}}, SameReal},
241 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
242 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
243 Rank::dimReduced},
244 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
245 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
246 Rank::dimReduced},
247 {"asin", {{"x", SameFloating}}, SameFloating},
248 {"asinh", {{"x", SameFloating}}, SameFloating},
249 {"atan", {{"x", SameFloating}}, SameFloating},
250 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
251 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
252 {"atanh", {{"x", SameFloating}}, SameFloating},
253 {"bessel_j0", {{"x", SameReal}}, SameReal},
254 {"bessel_j1", {{"x", SameReal}}, SameReal},
255 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29256 {"bessel_jn",
257 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
258 {"x", SameReal, Rank::scalar}},
259 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33260 {"bessel_y0", {{"x", SameReal}}, SameReal},
261 {"bessel_y1", {{"x", SameReal}}, SameReal},
262 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29263 {"bessel_yn",
264 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
265 {"x", SameReal, Rank::scalar}},
266 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33267 {"bge",
peter klauslercb308d32018-10-05 18:32:54268 {{"i", AnyInt, Rank::elementalOrBOZ},
269 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22270 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33271 {"bgt",
peter klauslercb308d32018-10-05 18:32:54272 {{"i", AnyInt, Rank::elementalOrBOZ},
273 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22274 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33275 {"ble",
peter klauslercb308d32018-10-05 18:32:54276 {{"i", AnyInt, Rank::elementalOrBOZ},
277 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22278 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33279 {"blt",
peter klauslercb308d32018-10-05 18:32:54280 {{"i", AnyInt, Rank::elementalOrBOZ},
281 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22282 DefaultLogical},
283 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33284 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
285 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
286 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11287 {"cmplx",
peter klauslercb308d32018-10-05 18:32:54288 {{"x", SameIntOrReal, Rank::elementalOrBOZ},
289 {"y", SameIntOrReal, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33290 KINDComplex},
peter klausler7c402d92018-10-16 21:42:22291 {"command_argument_count", {}, DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33292 {"conjg", {{"z", SameComplex}}, SameComplex},
293 {"cos", {{"x", SameFloating}}, SameFloating},
294 {"cosh", {{"x", SameFloating}}, SameFloating},
295 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
296 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11297 {"cshift",
peter klauslera70f5962018-10-04 20:43:33298 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
299 OptionalDIM},
300 SameType, Rank::array},
peter klausleref9dd9d2018-10-17 22:09:48301 {"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33302 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
peter klauslerf7f2a732018-10-09 19:07:29303 {"dot_product",
304 {{"vector_a", AnyLogical, Rank::vector},
305 {"vector_b", AnyLogical, Rank::vector}},
306 ResultLogical, Rank::scalar},
307 {"dot_product",
308 {{"vector_a", AnyComplex, Rank::vector},
309 {"vector_b", AnyNumeric, Rank::vector}},
310 ResultNumeric, Rank::scalar}, // conjugates vector_a
311 {"dot_product",
312 {{"vector_a", AnyIntOrReal, Rank::vector},
313 {"vector_b", AnyNumeric, Rank::vector}},
314 ResultNumeric, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22315 {"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33316 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54317 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33318 {"shift", AnyInt}},
319 SameInt},
320 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
321 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54322 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33323 {"shift", AnyInt}},
324 SameInt},
325 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11326 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33327 {{"array", SameIntrinsic, Rank::array},
328 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54329 {"boundary", SameIntrinsic, Rank::dimRemoved,
330 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33331 OptionalDIM},
332 SameIntrinsic, Rank::array},
peter klausler42b33da2018-09-29 00:02:11333 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33334 {{"array", SameDerivedType, Rank::array},
335 {"shift", AnyInt, Rank::dimRemoved},
336 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
337 SameDerivedType, Rank::array},
338 {"erf", {{"x", SameReal}}, SameReal},
339 {"erfc", {{"x", SameReal}}, SameReal},
340 {"erfc_scaled", {{"x", SameReal}}, SameReal},
341 {"exp", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22342 {"exponent", {{"x", AnyReal}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11343 {"findloc",
peter klauslerad9aede2018-10-11 21:51:14344 {{"array", AnyNumeric, Rank::array},
345 {"value", AnyNumeric, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22346 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54347 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33348 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11349 {"findloc",
peter klauslera70f5962018-10-04 20:43:33350 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22351 OptionalDIM, OptionalMASK, SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54352 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33353 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11354 {"findloc",
peter klauslera70f5962018-10-04 20:43:33355 {{"array", AnyLogical, Rank::array},
356 {"value", AnyLogical, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22357 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54358 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33359 KINDInt, Rank::dimReduced},
360 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
361 {"fraction", {{"x", SameReal}}, SameReal},
362 {"gamma", {{"x", SameReal}}, SameReal},
363 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
364 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
365 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
366 SameInt, Rank::dimReduced},
367 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
368 SameInt, Rank::dimReduced},
369 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
370 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54371 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33372 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
373 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
374 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
375 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
376 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54377 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33378 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
379 {"image_status",
peter klauslercb308d32018-10-05 18:32:54380 {{"image", SameInt},
381 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22382 DefaultInt},
peter klausler42b33da2018-09-29 00:02:11383 {"index",
peter klauslera70f5962018-10-04 20:43:33384 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54385 {"back", AnyLogical, Rank::scalar, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22386 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33387 KINDInt},
peter klauslercb308d32018-10-05 18:32:54388 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
389 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33390 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
391 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
392 {"ishftc",
393 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54394 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33395 SameInt},
peter klausler7c402d92018-10-16 21:42:22396 {"is_iostat_end", {{"i", AnyInt}}, DefaultLogical},
397 {"is_iostat_eor", {{"i", AnyInt}}, DefaultLogical},
peter klauslerbe3b7652018-12-04 18:55:32398 {"kind", {{"x", AnyIntrinsic}}, DefaultInt},
peter klausler7c402d92018-10-16 21:42:22399 {"lbound",
400 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29401 KINDInt, Rank::vector},
402 {"lbound",
403 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22404 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
405 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29406 KINDInt, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22407 {"leadz", {{"i", AnyInt}}, DefaultInt},
408 {"len", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
409 {"len_trim", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
410 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
411 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
412 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
413 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33414 {"log", {{"x", SameFloating}}, SameFloating},
415 {"log10", {{"x", SameReal}}, SameReal},
416 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
417 {"log_gamma", {{"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29418 {"matmul",
419 {{"array_a", AnyLogical, Rank::vector},
420 {"array_b", AnyLogical, Rank::matrix}},
421 ResultLogical, Rank::vector},
422 {"matmul",
423 {{"array_a", AnyLogical, Rank::matrix},
424 {"array_b", AnyLogical, Rank::vector}},
425 ResultLogical, Rank::vector},
426 {"matmul",
427 {{"array_a", AnyLogical, Rank::matrix},
428 {"array_b", AnyLogical, Rank::matrix}},
429 ResultLogical, Rank::matrix},
430 {"matmul",
431 {{"array_a", AnyNumeric, Rank::vector},
432 {"array_b", AnyNumeric, Rank::matrix}},
433 ResultNumeric, Rank::vector},
434 {"matmul",
435 {{"array_a", AnyNumeric, Rank::matrix},
436 {"array_b", AnyNumeric, Rank::vector}},
437 ResultNumeric, Rank::vector},
438 {"matmul",
439 {{"array_a", AnyNumeric, Rank::matrix},
440 {"array_b", AnyNumeric, Rank::matrix}},
441 ResultNumeric, Rank::matrix},
peter klauslera70f5962018-10-04 20:43:33442 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
443 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klauslerad9aede2018-10-11 21:51:14444 {"max",
445 {{"a1", SameRelatable}, {"a2", SameRelatable},
446 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
447 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11448 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33449 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22450 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54451 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33452 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11453 {"maxval",
peter klauslera70f5962018-10-04 20:43:33454 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
455 SameRelatable, Rank::dimReduced},
peter klauslerad9aede2018-10-11 21:51:14456 {"merge",
457 {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
458 SameType},
peter klausler42b33da2018-09-29 00:02:11459 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54460 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
461 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33462 SameInt},
463 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54464 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33465 SameInt},
peter klauslerad9aede2018-10-11 21:51:14466 {"min",
467 {{"a1", SameRelatable}, {"a2", SameRelatable},
468 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
469 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11470 {"minloc",
peter klauslera70f5962018-10-04 20:43:33471 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22472 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54473 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33474 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11475 {"minval",
peter klauslera70f5962018-10-04 20:43:33476 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
477 SameRelatable, Rank::dimReduced},
478 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
479 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
480 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
481 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
482 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
483 Rank::dimReduced},
484 {"not", {{"i", SameInt}}, SameInt},
peter klausler8efb8972018-10-10 17:48:12485 // NULL() is a special case handled in Probe() below
peter klausler42b33da2018-09-29 00:02:11486 {"out_of_range",
peter klauslerad9aede2018-10-11 21:51:14487 {{"x", AnyIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22488 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33489 {"out_of_range",
490 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54491 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22492 DefaultLogical},
493 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DefaultLogical},
peter klausler42b33da2018-09-29 00:02:11494 {"pack",
peter klauslera70f5962018-10-04 20:43:33495 {{"array", SameType, Rank::array},
496 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54497 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33498 SameType, Rank::vector},
499 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
500 Rank::dimReduced},
peter klausler7c402d92018-10-16 21:42:22501 {"popcnt", {{"i", AnyInt}}, DefaultInt},
502 {"poppar", {{"i", AnyInt}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11503 {"product",
peter klauslera70f5962018-10-04 20:43:33504 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
505 SameNumeric, Rank::dimReduced},
peter klausler28184c42019-04-04 20:58:46506 {"rank", {{"a", Anything, Rank::anyOrAssumedRank}}, DefaultInt},
peter klauslercb308d32018-10-05 18:32:54507 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33508 KINDReal},
peter klauslerad9aede2018-10-11 21:51:14509 {"reduce",
510 {{"array", SameType, Rank::array},
511 {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
512 OptionalMASK, {"identity", SameType, Rank::scalar},
513 {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
514 SameType, Rank::dimReduced},
peter klausler24379cc2018-10-10 23:45:17515 {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
516 SameChar, Rank::scalar},
peter klausler42b33da2018-09-29 00:02:11517 {"reshape",
peter klauslera70f5962018-10-04 20:43:33518 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54519 {"pad", SameType, Rank::array, Optionality::optional},
520 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33521 SameType, Rank::shaped},
522 {"rrspacing", {{"x", SameReal}}, SameReal},
523 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11524 {"scan",
peter klauslera70f5962018-10-04 20:43:33525 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54526 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22527 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33528 KINDInt},
peter klausler7c402d92018-10-16 21:42:22529 {"selected_char_kind", {{"name", DefaultChar, Rank::scalar}}, DefaultInt,
peter klausler24379cc2018-10-10 23:45:17530 Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22531 {"selected_int_kind", {{"r", AnyInt, Rank::scalar}}, DefaultInt,
532 Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14533 {"selected_real_kind",
534 {{"p", AnyInt, Rank::scalar},
535 {"r", AnyInt, Rank::scalar, Optionality::optional},
536 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22537 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14538 {"selected_real_kind",
539 {{"p", AnyInt, Rank::scalar, Optionality::optional},
540 {"r", AnyInt, Rank::scalar},
541 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22542 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14543 {"selected_real_kind",
544 {{"p", AnyInt, Rank::scalar, Optionality::optional},
545 {"r", AnyInt, Rank::scalar, Optionality::optional},
546 {"radix", AnyInt, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22547 DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33548 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler7c402d92018-10-16 21:42:22549 {"shape",
550 {{"source", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klausler24379cc2018-10-10 23:45:17551 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33552 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
553 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
554 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
555 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
556 {"sin", {{"x", SameFloating}}, SameFloating},
557 {"sinh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22558 {"size",
peter klauslerfe3acf5f2019-01-07 18:15:27559 {{"array", Anything, Rank::anyOrAssumedRank}, OptionalDIM,
peter klausler7c402d92018-10-16 21:42:22560 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29561 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33562 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11563 {"spread",
peter klauslera70f5962018-10-04 20:43:33564 {{"source", SameType, Rank::known},
peter klausler51b09b62018-10-15 19:17:30565 {"dim", {IntType, KindCode::dimArg}, Rank::scalar /*not optional*/},
peter klauslera70f5962018-10-04 20:43:33566 {"ncopies", AnyInt, Rank::scalar}},
567 SameType, Rank::rankPlus1},
568 {"sqrt", {{"x", SameFloating}}, SameFloating},
569 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
570 SameNumeric, Rank::dimReduced},
571 {"tan", {{"x", SameFloating}}, SameFloating},
572 {"tanh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22573 {"trailz", {{"i", AnyInt}}, DefaultInt},
peter klauslerf7f2a732018-10-09 19:07:29574 {"transfer",
575 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::scalar}},
576 SameType, Rank::scalar},
577 {"transfer",
578 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::array}},
579 SameType, Rank::vector},
580 {"transfer",
peter klausler8b580e42018-12-14 19:23:14581 {{"source", Anything, Rank::anyOrAssumedRank},
582 {"mold", SameType, Rank::anyOrAssumedRank},
peter klauslerf7f2a732018-10-09 19:07:29583 {"size", AnyInt, Rank::scalar}},
584 SameType, Rank::vector},
585 {"transpose", {{"matrix", SameType, Rank::matrix}}, SameType, Rank::matrix},
peter klauslerad9aede2018-10-11 21:51:14586 {"trim", {{"string", SameChar, Rank::scalar}}, SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22587 {"ubound",
588 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29589 KINDInt, Rank::vector},
590 {"ubound",
591 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22592 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
593 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29594 KINDInt, Rank::scalar},
595 {"unpack",
596 {{"vector", SameType, Rank::vector}, {"mask", AnyLogical, Rank::array},
597 {"field", SameType, Rank::conformable}},
598 SameType, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11599 {"verify",
peter klauslera70f5962018-10-04 20:43:33600 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54601 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22602 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33603 KINDInt},
peter klausler42b33da2018-09-29 00:02:11604};
605
peter klausler8efb8972018-10-10 17:48:12606// TODO: Coarray intrinsic functions
peter klauslerad9aede2018-10-11 21:51:14607// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
608// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
609// COSHAPE
peter klausler8efb8972018-10-10 17:48:12610// TODO: Object characteristic inquiry functions
peter klauslerad9aede2018-10-11 21:51:14611// ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS,
peter klauslerb65572d2019-04-03 23:04:13612// PRESENT, SAME_TYPE, STORAGE_SIZE
peter klauslerad9aede2018-10-11 21:51:14613// TODO: Type inquiry intrinsic functions - these return constants
614// BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT,
615// NEW_LINE, PRECISION, RADIX, RANGE, TINY
616// TODO: Non-standard intrinsic functions
617// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
618// COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL,
619// DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC,
620// QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM,
621// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
622// MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
623// IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
624// EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
625// probably more (these are PGI + Intel, possibly incomplete)
peter klausler42b33da2018-09-29 00:02:11626
peter klauslerba56b912019-02-22 23:45:30627// The following table contains the intrinsic functions listed in
628// Tables 16.2 and 16.3 in Fortran 2018. The "unrestricted" functions
629// in Table 16.2 can be used as actual arguments, PROCEDURE() interfaces,
630// and procedure pointer targets.
peter klausler42b33da2018-09-29 00:02:11631struct SpecificIntrinsicInterface : public IntrinsicInterface {
632 const char *generic{nullptr};
peter klauslerba56b912019-02-22 23:45:30633 bool isRestrictedSpecific{false};
peter klausler42b33da2018-09-29 00:02:11634};
635
peter klauslerb22d4942018-10-01 18:27:45636static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klausler7c402d92018-10-16 21:42:22637 {{"abs", {{"a", DefaultReal}}, DefaultReal}},
638 {{"acos", {{"x", DefaultReal}}, DefaultReal}},
639 {{"aimag", {{"z", DefaultComplex}}, DefaultReal}},
640 {{"aint", {{"a", DefaultReal}}, DefaultReal}},
641 {{"alog", {{"x", DefaultReal}}, DefaultReal}, "log"},
642 {{"alog10", {{"x", DefaultReal}}, DefaultReal}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14643 {{"amax0",
peter klausler7c402d92018-10-16 21:42:22644 {{"a1", DefaultInt}, {"a2", DefaultInt},
645 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
646 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14647 "max", true},
648 {{"amax1",
peter klausler7c402d92018-10-16 21:42:22649 {{"a1", DefaultReal}, {"a2", DefaultReal},
650 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
651 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14652 "max", true},
653 {{"amin0",
peter klausler7c402d92018-10-16 21:42:22654 {{"a1", DefaultInt}, {"a2", DefaultInt},
655 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
656 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14657 "min", true},
658 {{"amin1",
peter klausler7c402d92018-10-16 21:42:22659 {{"a1", DefaultReal}, {"a2", DefaultReal},
660 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
661 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14662 "min", true},
peter klausler7c402d92018-10-16 21:42:22663 {{"amod", {{"a", DefaultReal}, {"p", DefaultReal}}, DefaultReal}, "mod"},
664 {{"anint", {{"a", DefaultReal}}, DefaultReal}},
665 {{"asin", {{"x", DefaultReal}}, DefaultReal}},
666 {{"atan", {{"x", DefaultReal}}, DefaultReal}},
667 {{"atan2", {{"y", DefaultReal}, {"x", DefaultReal}}, DefaultReal}},
668 {{"cabs", {{"a", DefaultComplex}}, DefaultReal}, "abs"},
669 {{"ccos", {{"a", DefaultComplex}}, DefaultComplex}, "cos"},
670 {{"cexp", {{"a", DefaultComplex}}, DefaultComplex}, "exp"},
671 {{"clog", {{"a", DefaultComplex}}, DefaultComplex}, "log"},
672 {{"conjg", {{"a", DefaultComplex}}, DefaultComplex}},
673 {{"cos", {{"x", DefaultReal}}, DefaultReal}},
674 {{"csin", {{"a", DefaultComplex}}, DefaultComplex}, "sin"},
675 {{"csqrt", {{"a", DefaultComplex}}, DefaultComplex}, "sqrt"},
676 {{"ctan", {{"a", DefaultComplex}}, DefaultComplex}, "tan"},
peter klauslera70f5962018-10-04 20:43:33677 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
678 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
679 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
680 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
681 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
682 DoublePrecision},
683 "atan2"},
peter klauslera70f5962018-10-04 20:43:33684 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
685 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
686 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
687 DoublePrecision},
688 "dim"},
689 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
peter klausler7c402d92018-10-16 21:42:22690 {{"dim", {{"x", DefaultReal}, {"y", DefaultReal}}, DefaultReal}},
peter klauslera70f5962018-10-04 20:43:33691 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
692 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
693 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14694 {{"dmax1",
695 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
696 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
697 DoublePrecision},
698 "max", true},
699 {{"dmin1",
700 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
701 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
702 DoublePrecision},
703 "min", true},
peter klauslera70f5962018-10-04 20:43:33704 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
705 DoublePrecision},
706 "mod"},
707 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
peter klausler7c402d92018-10-16 21:42:22708 {{"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision}},
peter klauslera70f5962018-10-04 20:43:33709 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
710 DoublePrecision},
711 "sign"},
712 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
713 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
714 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
715 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
716 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
peter klausler7c402d92018-10-16 21:42:22717 {{"exp", {{"x", DefaultReal}}, DefaultReal}},
718 {{"float", {{"i", DefaultInt}}, DefaultReal}, "real", true},
719 {{"iabs", {{"a", DefaultInt}}, DefaultInt}, "abs"},
720 {{"idim", {{"x", DefaultInt}, {"y", DefaultInt}}, DefaultInt}, "dim"},
721 {{"idint", {{"a", DoublePrecision}}, DefaultInt}, "int", true},
722 {{"idnint", {{"a", DoublePrecision}}, DefaultInt}, "nint"},
723 {{"ifix", {{"a", DefaultReal}}, DefaultInt}, "int", true},
724 {{"index", {{"string", DefaultChar}, {"substring", DefaultChar}},
725 DefaultInt}},
726 {{"isign", {{"a", DefaultInt}, {"b", DefaultInt}}, DefaultInt}, "sign"},
727 {{"len", {{"string", DefaultChar}}, DefaultInt}},
728 {{"log", {{"x", DefaultReal}}, DefaultReal}},
729 {{"log10", {{"x", DefaultReal}}, DefaultReal}},
peter klauslerad9aede2018-10-11 21:51:14730 {{"max0",
peter klausler7c402d92018-10-16 21:42:22731 {{"a1", DefaultInt}, {"a2", DefaultInt},
732 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
733 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14734 "max", true},
735 {{"max1",
peter klausler7c402d92018-10-16 21:42:22736 {{"a1", DefaultReal}, {"a2", DefaultReal},
737 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
738 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14739 "max", true},
740 {{"min0",
peter klausler7c402d92018-10-16 21:42:22741 {{"a1", DefaultInt}, {"a2", DefaultInt},
742 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
743 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14744 "min", true},
745 {{"min1",
peter klausler7c402d92018-10-16 21:42:22746 {{"a1", DefaultReal}, {"a2", DefaultReal},
747 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
748 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14749 "min", true},
peter klausler7c402d92018-10-16 21:42:22750 {{"mod", {{"a", DefaultInt}, {"p", DefaultInt}}, DefaultInt}},
751 {{"nint", {{"a", DefaultReal}}, DefaultInt}},
752 {{"sign", {{"a", DefaultReal}, {"b", DefaultReal}}, DefaultReal}},
753 {{"sin", {{"x", DefaultReal}}, DefaultReal}},
754 {{"sinh", {{"x", DefaultReal}}, DefaultReal}},
755 {{"sngl", {{"a", DoublePrecision}}, DefaultReal}, "real", true},
756 {{"sqrt", {{"x", DefaultReal}}, DefaultReal}},
757 {{"tan", {{"x", DefaultReal}}, DefaultReal}},
758 {{"tanh", {{"x", DefaultReal}}, DefaultReal}},
peter klausler42b33da2018-09-29 00:02:11759};
760
peter klauslerad9aede2018-10-11 21:51:14761// TODO: Intrinsic subroutines
762// MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY,
763// EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT,
764// GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER,
765// RANDOM_SEED, SYSTEM_CLOCK
766// TODO: Atomic intrinsic subroutines: ATOMIC_ADD &al.
767// TODO: Collective intrinsic subroutines: CO_BROADCAST &al.
peter klausler42b33da2018-09-29 00:02:11768
peter klauslera70f5962018-10-04 20:43:33769// Intrinsic interface matching against the arguments of a particular
770// procedure reference.
peter klausleref9dd9d2018-10-17 22:09:48771std::optional<SpecificCall> IntrinsicInterface::Match(
peter klauslerbf339f82018-10-15 22:28:47772 const CallCharacteristics &call,
peter klauslerf9d6c0a2019-01-18 20:40:47773 const common::IntrinsicTypeDefaultKinds &defaults,
peter klausleref9dd9d2018-10-17 22:09:48774 ActualArguments &arguments, parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33775 // Attempt to construct a 1-1 correspondence between the dummy arguments in
776 // a particular intrinsic procedure's generic interface and the actual
777 // arguments in a procedure reference.
peter klausler84ea49d2018-10-18 17:50:55778 std::size_t dummyArgPatterns{0};
779 for (; dummyArgPatterns < maxArguments &&
780 dummy[dummyArgPatterns].keyword != nullptr;
781 ++dummyArgPatterns) {
peter klauslera70f5962018-10-04 20:43:33782 }
peter klausler84ea49d2018-10-18 17:50:55783 std::vector<ActualArgument *> actualForDummy(dummyArgPatterns, nullptr);
784 // MAX and MIN (and others that map to them) allow their last argument to
785 // be repeated indefinitely. The actualForDummy vector is sized
786 // and null-initialized to the non-repeated dummy argument count,
787 // but additional actual argument pointers can be pushed on it
788 // when this flag is set.
789 bool repeatLastDummy{dummyArgPatterns > 0 &&
790 dummy[dummyArgPatterns - 1].optionality == Optionality::repeats};
791 int missingActualArguments{0};
peter klausleref9dd9d2018-10-17 22:09:48792 for (std::optional<ActualArgument> &arg : arguments) {
peter klausler84ea49d2018-10-18 17:50:55793 if (!arg.has_value()) {
794 ++missingActualArguments;
795 } else {
peter klausleref9dd9d2018-10-17 22:09:48796 if (arg->isAlternateReturn) {
797 messages.Say(
798 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
799 name);
800 return std::nullopt;
801 }
802 bool found{false};
peter klausler84ea49d2018-10-18 17:50:55803 int slot{missingActualArguments};
804 for (std::size_t j{0}; j < dummyArgPatterns && !found; ++j) {
805 if (arg->keyword.has_value()) {
806 found = *arg->keyword == dummy[j].keyword;
807 if (found) {
808 if (const auto *previous{actualForDummy[j]}) {
809 if (previous->keyword.has_value()) {
810 messages.Say(*arg->keyword,
811 "repeated keyword argument to intrinsic '%s'"_err_en_US,
812 name);
813 } else {
814 messages.Say(*arg->keyword,
815 "keyword argument to intrinsic '%s' was supplied "
816 "positionally by an earlier actual argument"_err_en_US,
817 name);
818 }
819 return std::nullopt;
820 }
peter klausleref9dd9d2018-10-17 22:09:48821 }
peter klausler84ea49d2018-10-18 17:50:55822 } else {
823 found = actualForDummy[j] == nullptr && slot-- == 0;
824 }
825 if (found) {
826 actualForDummy[j] = &*arg;
peter klauslera70f5962018-10-04 20:43:33827 }
828 }
peter klausleref9dd9d2018-10-17 22:09:48829 if (!found) {
peter klausler84ea49d2018-10-18 17:50:55830 if (repeatLastDummy && !arg->keyword.has_value()) {
831 // MAX/MIN argument after the 2nd
832 actualForDummy.push_back(&*arg);
peter klausleref9dd9d2018-10-17 22:09:48833 } else {
peter klausler84ea49d2018-10-18 17:50:55834 if (arg->keyword.has_value()) {
835 messages.Say(*arg->keyword,
836 "unknown keyword argument to intrinsic '%s'"_err_en_US, name);
837 } else {
838 messages.Say(
839 "too many actual arguments for intrinsic '%s'"_err_en_US, name);
840 }
841 return std::nullopt;
peter klausleref9dd9d2018-10-17 22:09:48842 }
peter klauslera70f5962018-10-04 20:43:33843 }
844 }
845 }
846
peter klausler84ea49d2018-10-18 17:50:55847 std::size_t dummies{actualForDummy.size()};
848
peter klauslera70f5962018-10-04 20:43:33849 // Check types and kinds of the actual arguments against the intrinsic's
850 // interface. Ensure that two or more arguments that have to have the same
851 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19852 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33853 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19854 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33855 bool hasDimArg{false};
peter klausler84ea49d2018-10-18 17:50:55856 for (std::size_t j{0}; j < dummies; ++j) {
857 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
peter klauslera70f5962018-10-04 20:43:33858 if (d.typePattern.kindCode == KindCode::kindArg) {
859 CHECK(kindDummyArg == nullptr);
860 kindDummyArg = &d;
861 }
peter klausler84ea49d2018-10-18 17:50:55862 const ActualArgument *arg{actualForDummy[j]};
peter klauslera70f5962018-10-04 20:43:33863 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54864 if (d.optionality == Optionality::required) {
peter klausler7bda1b32018-10-12 23:01:55865 messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33866 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54867 } else {
868 continue;
peter klauslera70f5962018-10-04 20:43:33869 }
870 }
peter klauslera62636f2018-10-08 22:35:19871 std::optional<DynamicType> type{arg->GetType()};
872 if (!type.has_value()) {
873 CHECK(arg->Rank() == 0);
peter klauslercb308d32018-10-05 18:32:54874 if (d.typePattern.kindCode == KindCode::typeless ||
875 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33876 continue;
877 }
peter klausler7bda1b32018-10-12 23:01:55878 messages.Say(
879 "typeless (BOZ) not allowed for '%s=' argument"_err_en_US, d.keyword);
peter klauslercb308d32018-10-05 18:32:54880 return std::nullopt;
peter klauslera62636f2018-10-08 22:35:19881 } else if (!d.typePattern.categorySet.test(type->category)) {
peter klausler7bda1b32018-10-12 23:01:55882 messages.Say("actual argument for '%s=' has bad type '%s'"_err_en_US,
peter klausler4f6275a2018-11-05 23:02:37883 d.keyword, type->AsFortran().data());
peter klauslera70f5962018-10-04 20:43:33884 return std::nullopt; // argument has invalid type category
885 }
886 bool argOk{false};
887 switch (d.typePattern.kindCode) {
888 case KindCode::none:
889 case KindCode::typeless:
890 case KindCode::teamType: // TODO: TEAM_TYPE
891 argOk = false;
892 break;
893 case KindCode::defaultIntegerKind:
peter klauslerbf339f82018-10-15 22:28:47894 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33895 break;
896 case KindCode::defaultRealKind:
peter klauslerbf339f82018-10-15 22:28:47897 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Real);
peter klauslera70f5962018-10-04 20:43:33898 break;
899 case KindCode::doublePrecision:
peter klauslerbf339f82018-10-15 22:28:47900 argOk = type->kind == defaults.doublePrecisionKind();
peter klauslera70f5962018-10-04 20:43:33901 break;
902 case KindCode::defaultCharKind:
peter klauslerbf339f82018-10-15 22:28:47903 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Character);
peter klauslera70f5962018-10-04 20:43:33904 break;
905 case KindCode::defaultLogicalKind:
peter klauslerbf339f82018-10-15 22:28:47906 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Logical);
peter klauslera70f5962018-10-04 20:43:33907 break;
908 case KindCode::any: argOk = true; break;
909 case KindCode::kindArg:
peter klauslerf7f2a732018-10-09 19:07:29910 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33911 CHECK(kindArg == nullptr);
912 kindArg = arg;
peter klauslerf7f2a732018-10-09 19:07:29913 argOk = true;
peter klauslera70f5962018-10-04 20:43:33914 break;
915 case KindCode::dimArg:
peter klauslerf7f2a732018-10-09 19:07:29916 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33917 hasDimArg = true;
918 argOk = true;
919 break;
920 case KindCode::same:
921 if (sameArg == nullptr) {
922 sameArg = arg;
923 }
peter klausler1b1f60f2018-12-05 21:03:39924 argOk = type.value() == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33925 break;
926 case KindCode::effectiveKind:
927 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
928 "for intrinsic '%s'",
929 d.keyword, name);
930 break;
931 default: CRASH_NO_CASE;
932 }
933 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54934 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55935 "actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
peter klausler4f6275a2018-11-05 23:02:37936 d.keyword, type->AsFortran().data());
peter klauslera70f5962018-10-04 20:43:33937 return std::nullopt;
938 }
939 }
940
941 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:19942 const ActualArgument *arrayArg{nullptr};
943 const ActualArgument *knownArg{nullptr};
peter klauslerb65572d2019-04-03 23:04:13944 std::optional<int> shapeArgSize;
peter klauslera70f5962018-10-04 20:43:33945 int elementalRank{0};
peter klausler84ea49d2018-10-18 17:50:55946 for (std::size_t j{0}; j < dummies; ++j) {
947 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
948 if (const ActualArgument * arg{actualForDummy[j]}) {
peter klausler6a0f9472019-03-05 20:28:08949 if (IsAssumedRank(arg->value()) && d.rank != Rank::anyOrAssumedRank) {
peter klausler03618fd2018-10-29 22:25:35950 messages.Say("assumed-rank array cannot be forwarded to "
951 "'%s=' argument"_err_en_US,
peter klauslercb308d32018-10-05 18:32:54952 d.keyword);
peter klauslera70f5962018-10-04 20:43:33953 return std::nullopt;
954 }
peter klauslera62636f2018-10-08 22:35:19955 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:33956 bool argOk{false};
957 switch (d.rank) {
958 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54959 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33960 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:19961 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:33962 }
peter klauslera62636f2018-10-08 22:35:19963 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:33964 break;
peter klauslera62636f2018-10-08 22:35:19965 case Rank::scalar: argOk = rank == 0; break;
966 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:33967 case Rank::shape:
peter klauslerb65572d2019-04-03 23:04:13968 CHECK(!shapeArgSize.has_value());
969 if (rank == 1) {
970 if (auto shape{GetShape(*arg)}) {
peter klausler28184c42019-04-04 20:58:46971 if (auto constShape{AsConstantShape(*shape)}) {
972 shapeArgSize = (**constShape).ToInt64();
973 CHECK(shapeArgSize >= 0);
974 argOk = true;
peter klauslerb65572d2019-04-03 23:04:13975 }
976 }
977 }
978 if (!argOk) {
979 messages.Say(
980 "'shape=' argument must be a vector of known size"_err_en_US);
981 return std::nullopt;
982 }
peter klauslera70f5962018-10-04 20:43:33983 break;
peter klauslera62636f2018-10-08 22:35:19984 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:33985 case Rank::array:
peter klauslera62636f2018-10-08 22:35:19986 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:33987 if (!arrayArg) {
988 arrayArg = arg;
989 } else {
peter klauslera62636f2018-10-08 22:35:19990 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33991 }
992 break;
993 case Rank::known:
994 CHECK(knownArg == nullptr);
995 knownArg = arg;
996 argOk = true;
997 break;
998 case Rank::anyOrAssumedRank: argOk = true; break;
999 case Rank::conformable:
1000 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191001 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:331002 break;
1003 case Rank::dimRemoved:
1004 CHECK(arrayArg != nullptr);
1005 if (hasDimArg) {
peter klauslera62636f2018-10-08 22:35:191006 argOk = rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:331007 } else {
peter klauslera62636f2018-10-08 22:35:191008 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:331009 }
1010 break;
peter klauslerad9aede2018-10-11 21:51:141011 case Rank::reduceOperation:
1012 // TODO: Confirm that the argument is a pure function
1013 // of two arguments with several constraints
1014 CHECK(arrayArg != nullptr);
1015 argOk = rank == 0;
1016 break;
peter klauslera70f5962018-10-04 20:43:331017 case Rank::dimReduced:
1018 case Rank::rankPlus1:
1019 case Rank::shaped:
1020 common::die("INTERNAL: result-only rank code appears on argument '%s' "
1021 "for intrinsic '%s'",
1022 d.keyword, name);
1023 default: CRASH_NO_CASE;
1024 }
1025 if (!argOk) {
peter klausler7bda1b32018-10-12 23:01:551026 messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:191027 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:331028 return std::nullopt;
1029 }
1030 }
1031 }
1032
peter klauslera70f5962018-10-04 20:43:331033 // Calculate the characteristics of the function result, if any
peter klausleref9dd9d2018-10-17 22:09:481034 std::optional<DynamicType> resultType;
peter klauslera70f5962018-10-04 20:43:331035 if (result.categorySet.empty()) {
peter klausleref9dd9d2018-10-17 22:09:481036 if (!call.isSubroutineCall) {
1037 return std::nullopt;
peter klausler55df4a72018-10-12 23:25:391038 }
peter klausleref9dd9d2018-10-17 22:09:481039 CHECK(result.kindCode == KindCode::none);
1040 } else {
1041 // Determine the result type.
1042 if (call.isSubroutineCall) {
1043 return std::nullopt;
1044 }
peter klausler1b1f60f2018-12-05 21:03:391045 resultType = DynamicType{result.categorySet.LeastElement().value(), 0};
peter klausleref9dd9d2018-10-17 22:09:481046 switch (result.kindCode) {
1047 case KindCode::defaultIntegerKind:
1048 CHECK(result.categorySet == IntType);
1049 CHECK(resultType->category == TypeCategory::Integer);
1050 resultType->kind = defaults.GetDefaultKind(TypeCategory::Integer);
1051 break;
1052 case KindCode::defaultRealKind:
1053 CHECK(result.categorySet == CategorySet{resultType->category});
1054 CHECK(FloatingType.test(resultType->category));
1055 resultType->kind = defaults.GetDefaultKind(TypeCategory::Real);
1056 break;
1057 case KindCode::doublePrecision:
1058 CHECK(result.categorySet == RealType);
1059 CHECK(resultType->category == TypeCategory::Real);
1060 resultType->kind = defaults.doublePrecisionKind();
1061 break;
1062 case KindCode::defaultCharKind:
1063 CHECK(result.categorySet == CharType);
1064 CHECK(resultType->category == TypeCategory::Character);
1065 resultType->kind = defaults.GetDefaultKind(TypeCategory::Character);
1066 break;
1067 case KindCode::defaultLogicalKind:
1068 CHECK(result.categorySet == LogicalType);
1069 CHECK(resultType->category == TypeCategory::Logical);
1070 resultType->kind = defaults.GetDefaultKind(TypeCategory::Logical);
1071 break;
1072 case KindCode::same:
1073 CHECK(sameArg != nullptr);
1074 if (std::optional<DynamicType> aType{sameArg->GetType()}) {
1075 if (result.categorySet.test(aType->category)) {
1076 resultType = *aType;
1077 } else {
1078 resultType->kind = aType->kind;
1079 }
1080 }
1081 break;
1082 case KindCode::effectiveKind:
1083 CHECK(kindDummyArg != nullptr);
1084 CHECK(result.categorySet == CategorySet{resultType->category});
1085 if (kindArg != nullptr) {
peter klausler6a0f9472019-03-05 20:28:081086 auto &expr{kindArg->value()};
peter klauslerabac2282018-10-26 22:10:241087 CHECK(expr.Rank() == 0);
1088 if (auto code{ToInt64(expr)}) {
1089 if (IsValidKindOfIntrinsicType(resultType->category, *code)) {
1090 resultType->kind = *code;
1091 break;
peter klauslerf7f2a732018-10-09 19:07:291092 }
1093 }
peter klausleref9dd9d2018-10-17 22:09:481094 messages.Say("'kind=' argument must be a constant scalar integer "
1095 "whose value is a supported kind for the "
1096 "intrinsic result type"_err_en_US);
1097 return std::nullopt;
1098 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
1099 CHECK(sameArg != nullptr);
1100 resultType = *sameArg->GetType();
1101 } else if (kindDummyArg->optionality ==
1102 Optionality::defaultsToSubscriptKind) {
1103 CHECK(resultType->category == TypeCategory::Integer);
1104 resultType->kind = defaults.subscriptIntegerKind();
1105 } else {
1106 CHECK(kindDummyArg->optionality ==
1107 Optionality::defaultsToDefaultForResult);
1108 resultType->kind = defaults.GetDefaultKind(resultType->category);
peter klauslerf7f2a732018-10-09 19:07:291109 }
peter klausleref9dd9d2018-10-17 22:09:481110 break;
1111 case KindCode::likeMultiply:
1112 CHECK(dummies >= 2);
1113 CHECK(actualForDummy[0] != nullptr);
1114 CHECK(actualForDummy[1] != nullptr);
1115 resultType = actualForDummy[0]->GetType()->ResultTypeForMultiply(
1116 *actualForDummy[1]->GetType());
1117 break;
1118 case KindCode::typeless:
1119 case KindCode::teamType:
1120 case KindCode::any:
1121 case KindCode::kindArg:
1122 case KindCode::dimArg:
1123 common::die(
1124 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
1125 break;
1126 default: CRASH_NO_CASE;
peter klauslera70f5962018-10-04 20:43:331127 }
peter klauslera70f5962018-10-04 20:43:331128 }
1129
peter klauslerf7f2a732018-10-09 19:07:291130 // At this point, the call is acceptable.
peter klauslera70f5962018-10-04 20:43:331131 // Determine the rank of the function result.
1132 int resultRank{0};
1133 switch (rank) {
1134 case Rank::elemental: resultRank = elementalRank; break;
1135 case Rank::scalar: resultRank = 0; break;
1136 case Rank::vector: resultRank = 1; break;
1137 case Rank::matrix: resultRank = 2; break;
peter klauslerf7f2a732018-10-09 19:07:291138 case Rank::conformable:
1139 CHECK(arrayArg != nullptr);
1140 resultRank = arrayArg->Rank();
1141 break;
peter klauslera70f5962018-10-04 20:43:331142 case Rank::dimReduced:
1143 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191144 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:331145 break;
1146 case Rank::rankPlus1:
1147 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191148 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:331149 break;
1150 case Rank::shaped:
peter klauslerb65572d2019-04-03 23:04:131151 CHECK(shapeArgSize.has_value());
1152 resultRank = *shapeArgSize;
peter klauslera70f5962018-10-04 20:43:331153 break;
peter klauslercb308d32018-10-05 18:32:541154 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331155 case Rank::shape:
1156 case Rank::array:
1157 case Rank::known:
1158 case Rank::anyOrAssumedRank:
peter klauslera70f5962018-10-04 20:43:331159 case Rank::dimRemoved:
peter klauslerad9aede2018-10-11 21:51:141160 case Rank::reduceOperation:
peter klauslera70f5962018-10-04 20:43:331161 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
1162 break;
1163 default: CRASH_NO_CASE;
1164 }
1165 CHECK(resultRank >= 0);
1166
peter klauslerfdd3a2a2018-10-16 23:36:431167 semantics::Attrs attrs;
1168 if (elementalRank > 0) {
1169 attrs.set(semantics::Attr::ELEMENTAL);
1170 }
1171
peter klausleref9dd9d2018-10-17 22:09:481172 // Rearrange the actual arguments into dummy argument order.
1173 ActualArguments rearranged(dummies);
peter klausler84ea49d2018-10-18 17:50:551174 for (std::size_t j{0}; j < dummies; ++j) {
peter klausleref9dd9d2018-10-17 22:09:481175 if (ActualArgument * arg{actualForDummy[j]}) {
peter klausler84ea49d2018-10-18 17:50:551176 rearranged[j] = std::move(*arg);
peter klausleref9dd9d2018-10-17 22:09:481177 }
1178 }
1179
peter klausler402cc8c2019-02-20 01:06:281180 return std::make_optional<SpecificCall>(
peter klausleref9dd9d2018-10-17 22:09:481181 SpecificIntrinsic{name, std::move(resultType), resultRank, attrs},
peter klausler402cc8c2019-02-20 01:06:281182 std::move(rearranged));
peter klauslera70f5962018-10-04 20:43:331183}
1184
peter klauslerba56b912019-02-22 23:45:301185class IntrinsicProcTable::Implementation {
1186public:
peter klauslerf9d6c0a2019-01-18 20:40:471187 explicit Implementation(const common::IntrinsicTypeDefaultKinds &dfts)
peter klauslerba56b912019-02-22 23:45:301188 : defaults_{dfts} {
peter klauslera70f5962018-10-04 20:43:331189 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
peter klauslerba56b912019-02-22 23:45:301190 genericFuncs_.insert(std::make_pair(std::string{f.name}, &f));
peter klauslera70f5962018-10-04 20:43:331191 }
1192 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
peter klauslerba56b912019-02-22 23:45:301193 specificFuncs_.insert(std::make_pair(std::string{f.name}, &f));
peter klauslera70f5962018-10-04 20:43:331194 }
1195 }
peter klausler42b33da2018-09-29 00:02:111196
peter klauslerf9535832019-02-26 22:26:281197 bool IsIntrinsic(const std::string &) const;
1198
peter klausleref9dd9d2018-10-17 22:09:481199 std::optional<SpecificCall> Probe(const CallCharacteristics &,
1200 ActualArguments &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:531201
peter klauslerba56b912019-02-22 23:45:301202 std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1203 IsUnrestrictedSpecificIntrinsicFunction(const std::string &) const;
1204
peter klausler7bda1b32018-10-12 23:01:551205 std::ostream &Dump(std::ostream &) const;
peter klauslerba56b912019-02-22 23:45:301206
1207private:
1208 common::IntrinsicTypeDefaultKinds defaults_;
1209 std::multimap<std::string, const IntrinsicInterface *> genericFuncs_;
1210 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs_;
1211
1212 DynamicType GetSpecificType(const TypePattern &) const;
peter klausler42b33da2018-09-29 00:02:111213};
1214
peter klauslerf9535832019-02-26 22:26:281215bool IntrinsicProcTable::Implementation::IsIntrinsic(
1216 const std::string &name) const {
1217 auto specificRange{specificFuncs_.equal_range(name)};
1218 if (specificRange.first != specificRange.second) {
1219 return true;
1220 }
1221 auto genericRange{genericFuncs_.equal_range(name)};
1222 if (genericRange.first != genericRange.second) {
1223 return true;
1224 }
1225 // special cases
1226 return name == "null"; // TODO more
1227}
1228
peter klauslercb308d32018-10-05 18:32:541229// Probe the configured intrinsic procedure pattern tables in search of a
1230// match for a given procedure reference.
peter klausleref9dd9d2018-10-17 22:09:481231std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
1232 const CallCharacteristics &call, ActualArguments &arguments,
peter klauslercb308d32018-10-05 18:32:541233 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:531234 if (call.isSubroutineCall) {
1235 return std::nullopt; // TODO
1236 }
peter klausler7bda1b32018-10-12 23:01:551237 parser::Messages *finalBuffer{messages ? messages->messages() : nullptr};
peter klausler62425d62018-10-12 00:01:311238 // Probe the specific intrinsic function table first.
1239 parser::Messages specificBuffer;
1240 parser::ContextualMessages specificErrors{
1241 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551242 finalBuffer ? &specificBuffer : nullptr};
peter klausler75a32092018-10-05 16:57:531243 std::string name{call.name.ToString()};
peter klauslerba56b912019-02-22 23:45:301244 auto specificRange{specificFuncs_.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531245 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klausleref9dd9d2018-10-17 22:09:481246 if (auto specificCall{
peter klauslerba56b912019-02-22 23:45:301247 iter->second->Match(call, defaults_, arguments, specificErrors)}) {
peter klauslerad9aede2018-10-11 21:51:141248 if (const char *genericName{iter->second->generic}) {
peter klausleref9dd9d2018-10-17 22:09:481249 specificCall->specificIntrinsic.name = genericName;
peter klauslerad9aede2018-10-11 21:51:141250 }
peter klausleref9dd9d2018-10-17 22:09:481251 specificCall->specificIntrinsic.isRestrictedSpecific =
1252 iter->second->isRestrictedSpecific;
1253 return specificCall;
peter klausler75a32092018-10-05 16:57:531254 }
1255 }
peter klausler62425d62018-10-12 00:01:311256 // Probe the generic intrinsic function table next.
1257 parser::Messages genericBuffer;
1258 parser::ContextualMessages genericErrors{
1259 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551260 finalBuffer ? &genericBuffer : nullptr};
peter klauslerba56b912019-02-22 23:45:301261 auto genericRange{genericFuncs_.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531262 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klausleref9dd9d2018-10-17 22:09:481263 if (auto specificCall{
peter klauslerba56b912019-02-22 23:45:301264 iter->second->Match(call, defaults_, arguments, genericErrors)}) {
peter klausleref9dd9d2018-10-17 22:09:481265 return specificCall;
peter klausler75a32092018-10-05 16:57:531266 }
1267 }
peter klauslerad9aede2018-10-11 21:51:141268 // Special cases of intrinsic functions
peter klausler8efb8972018-10-10 17:48:121269 if (call.name.ToString() == "null") {
peter klausleref9dd9d2018-10-17 22:09:481270 if (arguments.size() == 0) {
peter klausler402cc8c2019-02-20 01:06:281271 return std::make_optional<SpecificCall>(
1272 SpecificIntrinsic{"null"s}, std::move(arguments));
peter klausleref9dd9d2018-10-17 22:09:481273 } else if (arguments.size() > 1) {
peter klausler62425d62018-10-12 00:01:311274 genericErrors.Say("too many arguments to NULL()"_err_en_US);
peter klausleref9dd9d2018-10-17 22:09:481275 } else if (arguments[0].has_value() && arguments[0]->keyword.has_value() &&
1276 arguments[0]->keyword->ToString() != "mold") {
peter klausler62425d62018-10-12 00:01:311277 genericErrors.Say("unknown argument '%s' to NULL()"_err_en_US,
peter klausleref9dd9d2018-10-17 22:09:481278 arguments[0]->keyword->ToString().data());
peter klausler8efb8972018-10-10 17:48:121279 } else {
peter klausler6a0f9472019-03-05 20:28:081280 Expr<SomeType> &mold{arguments[0]->value()};
peter klausler402cc8c2019-02-20 01:06:281281 if (IsPointerOrAllocatable(mold)) {
1282 return std::make_optional<SpecificCall>(
1283 SpecificIntrinsic{"null"s, mold.GetType(), mold.Rank(),
1284 semantics::Attrs{semantics::Attr::POINTER}},
1285 std::move(arguments));
1286 } else {
1287 genericErrors.Say("MOLD argument to NULL() must be a pointer "
1288 "or allocatable"_err_en_US);
1289 }
peter klausler8efb8972018-10-10 17:48:121290 }
1291 }
1292 // No match
peter klausler7bda1b32018-10-12 23:01:551293 if (finalBuffer) {
peter klausler62425d62018-10-12 00:01:311294 if (genericBuffer.empty()) {
peter klausler7bda1b32018-10-12 23:01:551295 finalBuffer->Annex(std::move(specificBuffer));
peter klausler62425d62018-10-12 00:01:311296 } else {
peter klausler7bda1b32018-10-12 23:01:551297 finalBuffer->Annex(std::move(genericBuffer));
peter klausler62425d62018-10-12 00:01:311298 }
peter klauslercb308d32018-10-05 18:32:541299 }
peter klausler75a32092018-10-05 16:57:531300 return std::nullopt;
1301}
1302
peter klauslerba56b912019-02-22 23:45:301303std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1304IntrinsicProcTable::Implementation::IsUnrestrictedSpecificIntrinsicFunction(
1305 const std::string &name) const {
1306 auto specificRange{specificFuncs_.equal_range(name)};
1307 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
1308 const SpecificIntrinsicInterface &specific{*iter->second};
1309 if (!specific.isRestrictedSpecific) {
1310 UnrestrictedSpecificIntrinsicFunctionInterface result;
1311 if (specific.generic != nullptr) {
1312 result.genericName = std::string(specific.generic);
1313 } else {
1314 result.genericName = name;
1315 }
peter klauslerf9535832019-02-26 22:26:281316 result.attrs.set(characteristics::Procedure::Attr::Pure);
1317 result.attrs.set(characteristics::Procedure::Attr::Elemental);
1318 int dummies{specific.CountArguments()};
1319 for (int j{0}; j < dummies; ++j) {
1320 characteristics::DummyDataObject dummy{
1321 GetSpecificType(specific.dummy[j].typePattern)};
1322 dummy.intent = common::Intent::In;
1323 result.dummyArguments.emplace_back(std::move(dummy));
1324 }
1325 result.functionResult.emplace(
1326 characteristics::FunctionResult{GetSpecificType(specific.result)});
peter klauslerba56b912019-02-22 23:45:301327 return result;
1328 }
1329 }
1330 return std::nullopt;
1331}
1332
1333DynamicType IntrinsicProcTable::Implementation::GetSpecificType(
1334 const TypePattern &pattern) const {
1335 const CategorySet &set{pattern.categorySet};
1336 CHECK(set.count() == 1);
1337 TypeCategory category{set.LeastElement().value()};
1338 return DynamicType{category, defaults_.GetDefaultKind(category)};
1339}
1340
peter klauslera62636f2018-10-08 22:35:191341IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:541342 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:111343 delete impl_;
1344 impl_ = nullptr;
1345}
1346
peter klauslera62636f2018-10-08 22:35:191347IntrinsicProcTable IntrinsicProcTable::Configure(
peter klauslerf9d6c0a2019-01-18 20:40:471348 const common::IntrinsicTypeDefaultKinds &defaults) {
peter klauslera62636f2018-10-08 22:35:191349 IntrinsicProcTable result;
1350 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:111351 return result;
1352}
1353
peter klauslerf9535832019-02-26 22:26:281354bool IntrinsicProcTable::IsIntrinsic(const std::string &name) const {
1355 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
1356 return impl_->IsIntrinsic(name);
1357}
1358
peter klausleref9dd9d2018-10-17 22:09:481359std::optional<SpecificCall> IntrinsicProcTable::Probe(
1360 const CallCharacteristics &call, ActualArguments &arguments,
peter klauslercb308d32018-10-05 18:32:541361 parser::ContextualMessages *messages) const {
peter klauslera62636f2018-10-08 22:35:191362 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klausleref9dd9d2018-10-17 22:09:481363 return impl_->Probe(call, arguments, messages);
peter klausler42b33da2018-09-29 00:02:111364}
peter klauslerad9aede2018-10-11 21:51:141365
peter klauslerba56b912019-02-22 23:45:301366std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1367IntrinsicProcTable::IsUnrestrictedSpecificIntrinsicFunction(
1368 const std::string &name) const {
1369 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
1370 return impl_->IsUnrestrictedSpecificIntrinsicFunction(name);
1371}
1372
peter klausler7bda1b32018-10-12 23:01:551373std::ostream &TypePattern::Dump(std::ostream &o) const {
1374 if (categorySet == AnyType) {
1375 o << "any type";
1376 } else {
1377 const char *sep = "";
1378 auto set{categorySet};
1379 while (auto least{set.LeastElement()}) {
1380 o << sep << EnumToString(*least);
1381 sep = " or ";
1382 set.reset(*least);
1383 }
1384 }
1385 o << '(' << EnumToString(kindCode) << ')';
1386 return o;
1387}
1388
1389std::ostream &IntrinsicDummyArgument::Dump(std::ostream &o) const {
1390 if (keyword) {
1391 o << keyword << '=';
1392 }
1393 return typePattern.Dump(o)
1394 << ' ' << EnumToString(rank) << ' ' << EnumToString(optionality);
1395}
1396
1397std::ostream &IntrinsicInterface::Dump(std::ostream &o) const {
1398 o << name;
1399 char sep{'('};
1400 for (const auto &d : dummy) {
1401 if (d.typePattern.kindCode == KindCode::none) {
1402 break;
1403 }
1404 d.Dump(o << sep);
1405 sep = ',';
1406 }
1407 if (sep == '(') {
1408 o << "()";
1409 }
1410 return result.Dump(o << " -> ") << ' ' << EnumToString(rank);
1411}
1412
1413std::ostream &IntrinsicProcTable::Implementation::Dump(std::ostream &o) const {
1414 o << "generic intrinsic functions:\n";
peter klauslerba56b912019-02-22 23:45:301415 for (const auto &iter : genericFuncs_) {
peter klausler7bda1b32018-10-12 23:01:551416 iter.second->Dump(o << iter.first << ": ") << '\n';
1417 }
1418 o << "specific intrinsic functions:\n";
peter klauslerba56b912019-02-22 23:45:301419 for (const auto &iter : specificFuncs_) {
peter klausler7bda1b32018-10-12 23:01:551420 iter.second->Dump(o << iter.first << ": ");
1421 if (const char *g{iter.second->generic}) {
1422 o << " -> " << g;
1423 }
1424 o << '\n';
1425 }
1426 return o;
1427}
1428
1429std::ostream &IntrinsicProcTable::Dump(std::ostream &o) const {
1430 return impl_->Dump(o);
1431}
Jean Perierf7e7cb32018-10-25 12:55:231432}