blob: 14de420a3b43e07df17e655dc6a8415d5dd9294a [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 klauslerabac2282018-10-26 22:10:2418#include "tools.h"
peter klausler42b33da2018-09-29 00:02:1119#include "type.h"
peter klauslerab74d1a2019-02-28 18:48:4120#include "../common/Fortran.h"
peter klausler42b33da2018-09-29 00:02:1121#include "../common/enum-set.h"
peter klauslera70f5962018-10-04 20:43:3322#include "../common/idioms.h"
peter klausler84ea49d2018-10-18 17:50:5523#include <algorithm>
peter klauslera70f5962018-10-04 20:43:3324#include <map>
peter klausler7bda1b32018-10-12 23:01:5525#include <ostream>
26#include <sstream>
peter klauslera70f5962018-10-04 20:43:3327#include <string>
28#include <utility>
peter klausler42b33da2018-09-29 00:02:1129
peter klauslercb308d32018-10-05 18:32:5430using namespace Fortran::parser::literals;
31
peter klausler42b33da2018-09-29 00:02:1132namespace Fortran::evaluate {
33
34using common::TypeCategory;
35
peter klauslera70f5962018-10-04 20:43:3336// This file defines the supported intrinsic procedures and implements
37// their recognition and validation. It is largely table-driven. See
38// documentation/intrinsics.md and section 16 of the Fortran 2018 standard
39// for full details on each of the intrinsics. Be advised, they have
40// complicated details, and the design of these tables has to accommodate
41// that complexity.
42
peter klausler42b33da2018-09-29 00:02:1143// Dummy arguments to generic intrinsic procedures are each specified by
peter klauslera70f5962018-10-04 20:43:3344// their keyword name (rarely used, but always defined), allowable type
peter klauslercb308d32018-10-05 18:32:5445// categories, a kind pattern, a rank pattern, and information about
46// optionality and defaults. The kind and rank patterns are represented
47// here with code values that are significant to the matching/validation engine.
peter klausler42b33da2018-09-29 00:02:1148
peter klauslera70f5962018-10-04 20:43:3349// These are small bit-sets of type category enumerators.
50// Note that typeless (BOZ literal) values don't have a distinct type category.
51// These typeless arguments are represented in the tables as if they were
52// INTEGER with a special "typeless" kind code. Arguments of intrinsic types
peter klauslercb308d32018-10-05 18:32:5453// that can also be be typeless values are encoded with an "elementalOrBOZ"
54// rank pattern.
peter klauslera70f5962018-10-04 20:43:3355using CategorySet = common::EnumSet<TypeCategory, 8>;
peter klausler51b09b62018-10-15 19:17:3056static constexpr CategorySet IntType{TypeCategory::Integer};
57static constexpr CategorySet RealType{TypeCategory::Real};
58static constexpr CategorySet ComplexType{TypeCategory::Complex};
59static constexpr CategorySet CharType{TypeCategory::Character};
60static constexpr CategorySet LogicalType{TypeCategory::Logical};
61static constexpr CategorySet IntOrRealType{IntType | RealType};
62static constexpr CategorySet FloatingType{RealType | ComplexType};
63static constexpr CategorySet NumericType{IntType | RealType | ComplexType};
64static constexpr CategorySet RelatableType{IntType | RealType | CharType};
peter klauslera70f5962018-10-04 20:43:3365static constexpr CategorySet IntrinsicType{
peter klausler51b09b62018-10-15 19:17:3066 IntType | RealType | ComplexType | CharType | LogicalType};
peter klauslera70f5962018-10-04 20:43:3367static constexpr CategorySet AnyType{
68 IntrinsicType | CategorySet{TypeCategory::Derived}};
peter klausler42b33da2018-09-29 00:02:1169
peter klausler7bda1b32018-10-12 23:01:5570ENUM_CLASS(KindCode, none, defaultIntegerKind,
71 defaultRealKind, // is also the default COMPLEX kind
72 doublePrecision, defaultCharKind, defaultLogicalKind,
73 any, // matches any kind value; each instance is independent
74 typeless, // BOZ literals are INTEGER with this kind
75 teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
76 kindArg, // this argument is KIND=
77 effectiveKind, // for function results: same "kindArg", possibly defaulted
78 dimArg, // this argument is DIM=
79 same, // match any kind; all "same" kinds must be equal
80 likeMultiply, // for DOT_PRODUCT and MATMUL
81)
peter klausler42b33da2018-09-29 00:02:1182
83struct TypePattern {
84 CategorySet categorySet;
peter klauslerb22d4942018-10-01 18:27:4585 KindCode kindCode{KindCode::none};
peter klausler7bda1b32018-10-12 23:01:5586 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:1187};
88
peter klauslera70f5962018-10-04 20:43:3389// Abbreviations for argument and result patterns in the intrinsic prototypes:
90
91// Match specific kinds of intrinsic types
peter klausler7c402d92018-10-16 21:42:2292static constexpr TypePattern DefaultInt{IntType, KindCode::defaultIntegerKind};
93static constexpr TypePattern DefaultReal{RealType, KindCode::defaultRealKind};
94static constexpr TypePattern DefaultComplex{
95 ComplexType, KindCode::defaultRealKind};
96static constexpr TypePattern DefaultChar{CharType, KindCode::defaultCharKind};
97static constexpr TypePattern DefaultLogical{
peter klausler51b09b62018-10-15 19:17:3098 LogicalType, KindCode::defaultLogicalKind};
99static constexpr TypePattern BOZ{IntType, KindCode::typeless};
100static constexpr TypePattern TEAM_TYPE{IntType, KindCode::teamType};
101static constexpr TypePattern DoublePrecision{
102 RealType, KindCode::doublePrecision};
peter klauslera70f5962018-10-04 20:43:33103
104// Match any kind of some intrinsic or derived types
peter klausler51b09b62018-10-15 19:17:30105static constexpr TypePattern AnyInt{IntType, KindCode::any};
106static constexpr TypePattern AnyReal{RealType, KindCode::any};
107static constexpr TypePattern AnyIntOrReal{IntOrRealType, KindCode::any};
108static constexpr TypePattern AnyComplex{ComplexType, KindCode::any};
109static constexpr TypePattern AnyNumeric{NumericType, KindCode::any};
110static constexpr TypePattern AnyChar{CharType, KindCode::any};
111static constexpr TypePattern AnyLogical{LogicalType, KindCode::any};
112static constexpr TypePattern AnyRelatable{RelatableType, KindCode::any};
peter klauslerbe3b7652018-12-04 18:55:32113static constexpr TypePattern AnyIntrinsic{IntrinsicType, KindCode::any};
peter klauslerf7f2a732018-10-09 19:07:29114static constexpr TypePattern Anything{AnyType, KindCode::any};
peter klauslera70f5962018-10-04 20:43:33115
116// Match some kind of some intrinsic type(s); all "Same" values must match,
117// even when not in the same category (e.g., SameComplex and SameReal).
118// Can be used to specify a result so long as at least one argument is
119// a "Same".
peter klausler51b09b62018-10-15 19:17:30120static constexpr TypePattern SameInt{IntType, KindCode::same};
121static constexpr TypePattern SameReal{RealType, KindCode::same};
122static constexpr TypePattern SameIntOrReal{IntOrRealType, KindCode::same};
123static constexpr TypePattern SameComplex{ComplexType, KindCode::same};
124static constexpr TypePattern SameFloating{FloatingType, KindCode::same};
125static constexpr TypePattern SameNumeric{NumericType, KindCode::same};
126static constexpr TypePattern SameChar{CharType, KindCode::same};
127static constexpr TypePattern SameLogical{LogicalType, KindCode::same};
128static constexpr TypePattern SameRelatable{RelatableType, KindCode::same};
peter klauslera70f5962018-10-04 20:43:33129static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
130static constexpr TypePattern SameDerivedType{
131 CategorySet{TypeCategory::Derived}, KindCode::same};
132static constexpr TypePattern SameType{AnyType, KindCode::same};
133
peter klauslerf7f2a732018-10-09 19:07:29134// For DOT_PRODUCT and MATMUL, the result type depends on the arguments
peter klausler51b09b62018-10-15 19:17:30135static constexpr TypePattern ResultLogical{LogicalType, KindCode::likeMultiply};
136static constexpr TypePattern ResultNumeric{NumericType, KindCode::likeMultiply};
peter klauslerf7f2a732018-10-09 19:07:29137
peter klauslera70f5962018-10-04 20:43:33138// Result types with known category and KIND=
peter klausler51b09b62018-10-15 19:17:30139static constexpr TypePattern KINDInt{IntType, KindCode::effectiveKind};
140static constexpr TypePattern KINDReal{RealType, KindCode::effectiveKind};
141static constexpr TypePattern KINDComplex{ComplexType, KindCode::effectiveKind};
142static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind};
143static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11144
145// The default rank pattern for dummy arguments and function results is
146// "elemental".
peter klausler7bda1b32018-10-12 23:01:55147ENUM_CLASS(Rank,
148 elemental, // scalar, or array that conforms with other array arguments
149 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
150 scalar, vector,
151 shape, // INTEGER vector of known length and no negative element
152 matrix,
153 array, // not scalar, rank is known and greater than zero
154 known, // rank is known and can be scalar
155 anyOrAssumedRank, // rank can be unknown
156 conformable, // scalar, or array of same rank & shape as "array" argument
157 reduceOperation, // a pure function with constraints for REDUCE
158 dimReduced, // scalar if no DIM= argument, else rank(array)-1
159 dimRemoved, // scalar, or rank(array)-1
160 rankPlus1, // rank(known)+1
161 shaped, // rank is length of SHAPE vector
162)
peter klausler42b33da2018-09-29 00:02:11163
peter klausler7bda1b32018-10-12 23:01:55164ENUM_CLASS(Optionality, required, optional,
165 defaultsToSameKind, // for MatchingDefaultKIND
166 defaultsToDefaultForResult, // for DefaultingKIND
peter klausler7c402d92018-10-16 21:42:22167 defaultsToSubscriptKind, // for SubscriptDefaultKIND
peter klausler7bda1b32018-10-12 23:01:55168 repeats, // for MAX/MIN and their several variants
169)
peter klausler42b33da2018-09-29 00:02:11170
171struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45172 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11173 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33174 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54175 Optionality optionality{Optionality::required};
peter klausler7bda1b32018-10-12 23:01:55176 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11177};
178
peter klauslera70f5962018-10-04 20:43:33179// constexpr abbreviations for popular arguments:
180// DefaultingKIND is a KIND= argument whose default value is the appropriate
181// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54182static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30183 {IntType, KindCode::kindArg}, Rank::scalar,
peter klauslercb308d32018-10-05 18:32:54184 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33185// MatchingDefaultKIND is a KIND= argument whose default value is the
186// kind of any "Same" function argument (viz., the one whose kind pattern is
187// "same").
peter klauslercb308d32018-10-05 18:32:54188static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30189 {IntType, KindCode::kindArg}, Rank::scalar,
190 Optionality::defaultsToSameKind};
peter klausler7c402d92018-10-16 21:42:22191// SubscriptDefaultKind is a KIND= argument whose default value is
192// the kind of INTEGER used for address calculations.
193static constexpr IntrinsicDummyArgument SubscriptDefaultKIND{"kind",
194 {IntType, KindCode::kindArg}, Rank::scalar,
195 Optionality::defaultsToSubscriptKind};
peter klauslera70f5962018-10-04 20:43:33196static constexpr IntrinsicDummyArgument OptionalDIM{
peter klausler51b09b62018-10-15 19:17:30197 "dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33198static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54199 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11200
201struct IntrinsicInterface {
peter klausler84ea49d2018-10-18 17:50:55202 static constexpr int maxArguments{7}; // if not a MAX/MIN(...)
peter klauslerb22d4942018-10-01 18:27:45203 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11204 IntrinsicDummyArgument dummy[maxArguments];
205 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33206 Rank rank{Rank::elemental};
peter klausleref9dd9d2018-10-17 22:09:48207 std::optional<SpecificCall> Match(const CallCharacteristics &,
peter klauslerf9d6c0a2019-01-18 20:40:47208 const common::IntrinsicTypeDefaultKinds &, ActualArguments &,
peter klauslercb308d32018-10-05 18:32:54209 parser::ContextualMessages &messages) const;
peter klauslerba56b912019-02-22 23:45:30210 int CountArguments() const;
peter klausler7bda1b32018-10-12 23:01:55211 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11212};
213
peter klauslerba56b912019-02-22 23:45:30214int IntrinsicInterface::CountArguments() const {
215 int n{0};
216 while (n < maxArguments && dummy[n].keyword != nullptr) {
217 ++n;
218 }
219 return n;
220}
221
peter klausler94041d72018-10-15 20:39:51222// GENERIC INTRINSIC FUNCTION INTERFACES
223// Each entry in this table defines a pattern. Some intrinsic
224// functions have more than one such pattern. Besides the name
225// of the intrinsic function, each pattern has specifications for
226// the dummy arguments and for the result of the function.
227// The dummy argument patterns each have a name (this are from the
228// standard, but rarely appear in actual code), a type and kind
229// pattern, allowable ranks, and optionality indicators.
230// Be advised, the default rank pattern is "elemental".
peter klauslerb22d4942018-10-01 18:27:45231static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33232 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
233 {"abs", {{"a", SameComplex}}, SameReal},
peter klauslerad9aede2018-10-11 21:51:14234 {"achar", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
peter klauslera70f5962018-10-04 20:43:33235 {"acos", {{"x", SameFloating}}, SameFloating},
236 {"acosh", {{"x", SameFloating}}, SameFloating},
237 {"adjustl", {{"string", SameChar}}, SameChar},
238 {"adjustr", {{"string", SameChar}}, SameChar},
239 {"aimag", {{"x", SameComplex}}, SameReal},
240 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
241 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
242 Rank::dimReduced},
243 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
244 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
245 Rank::dimReduced},
246 {"asin", {{"x", SameFloating}}, SameFloating},
247 {"asinh", {{"x", SameFloating}}, SameFloating},
248 {"atan", {{"x", SameFloating}}, SameFloating},
249 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
250 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
251 {"atanh", {{"x", SameFloating}}, SameFloating},
252 {"bessel_j0", {{"x", SameReal}}, SameReal},
253 {"bessel_j1", {{"x", SameReal}}, SameReal},
254 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29255 {"bessel_jn",
256 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
257 {"x", SameReal, Rank::scalar}},
258 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33259 {"bessel_y0", {{"x", SameReal}}, SameReal},
260 {"bessel_y1", {{"x", SameReal}}, SameReal},
261 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29262 {"bessel_yn",
263 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
264 {"x", SameReal, Rank::scalar}},
265 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33266 {"bge",
peter klauslercb308d32018-10-05 18:32:54267 {{"i", AnyInt, Rank::elementalOrBOZ},
268 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22269 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33270 {"bgt",
peter klauslercb308d32018-10-05 18:32:54271 {{"i", AnyInt, Rank::elementalOrBOZ},
272 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22273 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33274 {"ble",
peter klauslercb308d32018-10-05 18:32:54275 {{"i", AnyInt, Rank::elementalOrBOZ},
276 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22277 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33278 {"blt",
peter klauslercb308d32018-10-05 18:32:54279 {{"i", AnyInt, Rank::elementalOrBOZ},
280 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22281 DefaultLogical},
282 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33283 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
284 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
285 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11286 {"cmplx",
peter klauslercb308d32018-10-05 18:32:54287 {{"x", SameIntOrReal, Rank::elementalOrBOZ},
288 {"y", SameIntOrReal, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33289 KINDComplex},
peter klausler7c402d92018-10-16 21:42:22290 {"command_argument_count", {}, DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33291 {"conjg", {{"z", SameComplex}}, SameComplex},
292 {"cos", {{"x", SameFloating}}, SameFloating},
293 {"cosh", {{"x", SameFloating}}, SameFloating},
294 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
295 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11296 {"cshift",
peter klauslera70f5962018-10-04 20:43:33297 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
298 OptionalDIM},
299 SameType, Rank::array},
peter klausleref9dd9d2018-10-17 22:09:48300 {"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33301 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
peter klauslerf7f2a732018-10-09 19:07:29302 {"dot_product",
303 {{"vector_a", AnyLogical, Rank::vector},
304 {"vector_b", AnyLogical, Rank::vector}},
305 ResultLogical, Rank::scalar},
306 {"dot_product",
307 {{"vector_a", AnyComplex, Rank::vector},
308 {"vector_b", AnyNumeric, Rank::vector}},
309 ResultNumeric, Rank::scalar}, // conjugates vector_a
310 {"dot_product",
311 {{"vector_a", AnyIntOrReal, Rank::vector},
312 {"vector_b", AnyNumeric, Rank::vector}},
313 ResultNumeric, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22314 {"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33315 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54316 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33317 {"shift", AnyInt}},
318 SameInt},
319 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
320 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54321 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33322 {"shift", AnyInt}},
323 SameInt},
324 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11325 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33326 {{"array", SameIntrinsic, Rank::array},
327 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54328 {"boundary", SameIntrinsic, Rank::dimRemoved,
329 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33330 OptionalDIM},
331 SameIntrinsic, Rank::array},
peter klausler42b33da2018-09-29 00:02:11332 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33333 {{"array", SameDerivedType, Rank::array},
334 {"shift", AnyInt, Rank::dimRemoved},
335 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
336 SameDerivedType, Rank::array},
337 {"erf", {{"x", SameReal}}, SameReal},
338 {"erfc", {{"x", SameReal}}, SameReal},
339 {"erfc_scaled", {{"x", SameReal}}, SameReal},
340 {"exp", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22341 {"exponent", {{"x", AnyReal}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11342 {"findloc",
peter klauslerad9aede2018-10-11 21:51:14343 {{"array", AnyNumeric, Rank::array},
344 {"value", AnyNumeric, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22345 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54346 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33347 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11348 {"findloc",
peter klauslera70f5962018-10-04 20:43:33349 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22350 OptionalDIM, OptionalMASK, SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54351 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33352 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11353 {"findloc",
peter klauslera70f5962018-10-04 20:43:33354 {{"array", AnyLogical, Rank::array},
355 {"value", AnyLogical, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22356 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54357 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33358 KINDInt, Rank::dimReduced},
359 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
360 {"fraction", {{"x", SameReal}}, SameReal},
361 {"gamma", {{"x", SameReal}}, SameReal},
362 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
363 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
364 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
365 SameInt, Rank::dimReduced},
366 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
367 SameInt, Rank::dimReduced},
368 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
369 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54370 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33371 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
372 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
373 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
374 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
375 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54376 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33377 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
378 {"image_status",
peter klauslercb308d32018-10-05 18:32:54379 {{"image", SameInt},
380 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22381 DefaultInt},
peter klausler42b33da2018-09-29 00:02:11382 {"index",
peter klauslera70f5962018-10-04 20:43:33383 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54384 {"back", AnyLogical, Rank::scalar, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22385 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33386 KINDInt},
peter klauslercb308d32018-10-05 18:32:54387 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
388 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33389 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
390 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
391 {"ishftc",
392 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54393 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33394 SameInt},
peter klausler7c402d92018-10-16 21:42:22395 {"is_iostat_end", {{"i", AnyInt}}, DefaultLogical},
396 {"is_iostat_eor", {{"i", AnyInt}}, DefaultLogical},
peter klauslerbe3b7652018-12-04 18:55:32397 {"kind", {{"x", AnyIntrinsic}}, DefaultInt},
peter klausler7c402d92018-10-16 21:42:22398 {"lbound",
399 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29400 KINDInt, Rank::vector},
401 {"lbound",
402 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22403 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
404 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29405 KINDInt, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22406 {"leadz", {{"i", AnyInt}}, DefaultInt},
407 {"len", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
408 {"len_trim", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
409 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
410 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
411 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
412 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33413 {"log", {{"x", SameFloating}}, SameFloating},
414 {"log10", {{"x", SameReal}}, SameReal},
415 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
416 {"log_gamma", {{"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29417 {"matmul",
418 {{"array_a", AnyLogical, Rank::vector},
419 {"array_b", AnyLogical, Rank::matrix}},
420 ResultLogical, Rank::vector},
421 {"matmul",
422 {{"array_a", AnyLogical, Rank::matrix},
423 {"array_b", AnyLogical, Rank::vector}},
424 ResultLogical, Rank::vector},
425 {"matmul",
426 {{"array_a", AnyLogical, Rank::matrix},
427 {"array_b", AnyLogical, Rank::matrix}},
428 ResultLogical, Rank::matrix},
429 {"matmul",
430 {{"array_a", AnyNumeric, Rank::vector},
431 {"array_b", AnyNumeric, Rank::matrix}},
432 ResultNumeric, Rank::vector},
433 {"matmul",
434 {{"array_a", AnyNumeric, Rank::matrix},
435 {"array_b", AnyNumeric, Rank::vector}},
436 ResultNumeric, Rank::vector},
437 {"matmul",
438 {{"array_a", AnyNumeric, Rank::matrix},
439 {"array_b", AnyNumeric, Rank::matrix}},
440 ResultNumeric, Rank::matrix},
peter klauslera70f5962018-10-04 20:43:33441 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
442 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klauslerad9aede2018-10-11 21:51:14443 {"max",
444 {{"a1", SameRelatable}, {"a2", SameRelatable},
445 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
446 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11447 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33448 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22449 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54450 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33451 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11452 {"maxval",
peter klauslera70f5962018-10-04 20:43:33453 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
454 SameRelatable, Rank::dimReduced},
peter klauslerad9aede2018-10-11 21:51:14455 {"merge",
456 {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
457 SameType},
peter klausler42b33da2018-09-29 00:02:11458 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54459 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
460 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33461 SameInt},
462 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54463 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33464 SameInt},
peter klauslerad9aede2018-10-11 21:51:14465 {"min",
466 {{"a1", SameRelatable}, {"a2", SameRelatable},
467 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
468 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11469 {"minloc",
peter klauslera70f5962018-10-04 20:43:33470 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22471 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54472 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33473 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11474 {"minval",
peter klauslera70f5962018-10-04 20:43:33475 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
476 SameRelatable, Rank::dimReduced},
477 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
478 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
479 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
480 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
481 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
482 Rank::dimReduced},
483 {"not", {{"i", SameInt}}, SameInt},
peter klausler8efb8972018-10-10 17:48:12484 // NULL() is a special case handled in Probe() below
peter klausler42b33da2018-09-29 00:02:11485 {"out_of_range",
peter klauslerad9aede2018-10-11 21:51:14486 {{"x", AnyIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22487 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33488 {"out_of_range",
489 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54490 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22491 DefaultLogical},
492 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DefaultLogical},
peter klausler42b33da2018-09-29 00:02:11493 {"pack",
peter klauslera70f5962018-10-04 20:43:33494 {{"array", SameType, Rank::array},
495 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54496 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33497 SameType, Rank::vector},
498 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
499 Rank::dimReduced},
peter klausler7c402d92018-10-16 21:42:22500 {"popcnt", {{"i", AnyInt}}, DefaultInt},
501 {"poppar", {{"i", AnyInt}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11502 {"product",
peter klauslera70f5962018-10-04 20:43:33503 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
504 SameNumeric, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54505 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33506 KINDReal},
peter klauslerad9aede2018-10-11 21:51:14507 {"reduce",
508 {{"array", SameType, Rank::array},
509 {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
510 OptionalMASK, {"identity", SameType, Rank::scalar},
511 {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
512 SameType, Rank::dimReduced},
peter klausler24379cc2018-10-10 23:45:17513 {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
514 SameChar, Rank::scalar},
peter klausler42b33da2018-09-29 00:02:11515 {"reshape",
peter klauslera70f5962018-10-04 20:43:33516 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54517 {"pad", SameType, Rank::array, Optionality::optional},
518 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33519 SameType, Rank::shaped},
520 {"rrspacing", {{"x", SameReal}}, SameReal},
521 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11522 {"scan",
peter klauslera70f5962018-10-04 20:43:33523 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54524 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22525 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33526 KINDInt},
peter klausler7c402d92018-10-16 21:42:22527 {"selected_char_kind", {{"name", DefaultChar, Rank::scalar}}, DefaultInt,
peter klausler24379cc2018-10-10 23:45:17528 Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22529 {"selected_int_kind", {{"r", AnyInt, Rank::scalar}}, DefaultInt,
530 Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14531 {"selected_real_kind",
532 {{"p", AnyInt, Rank::scalar},
533 {"r", AnyInt, Rank::scalar, Optionality::optional},
534 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22535 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14536 {"selected_real_kind",
537 {{"p", AnyInt, Rank::scalar, Optionality::optional},
538 {"r", AnyInt, Rank::scalar},
539 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22540 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14541 {"selected_real_kind",
542 {{"p", AnyInt, Rank::scalar, Optionality::optional},
543 {"r", AnyInt, Rank::scalar, Optionality::optional},
544 {"radix", AnyInt, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22545 DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33546 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler7c402d92018-10-16 21:42:22547 {"shape",
548 {{"source", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klausler24379cc2018-10-10 23:45:17549 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33550 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
551 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
552 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
553 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
554 {"sin", {{"x", SameFloating}}, SameFloating},
555 {"sinh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22556 {"size",
peter klauslerfe3acf5f2019-01-07 18:15:27557 {{"array", Anything, Rank::anyOrAssumedRank}, OptionalDIM,
peter klausler7c402d92018-10-16 21:42:22558 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29559 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33560 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11561 {"spread",
peter klauslera70f5962018-10-04 20:43:33562 {{"source", SameType, Rank::known},
peter klausler51b09b62018-10-15 19:17:30563 {"dim", {IntType, KindCode::dimArg}, Rank::scalar /*not optional*/},
peter klauslera70f5962018-10-04 20:43:33564 {"ncopies", AnyInt, Rank::scalar}},
565 SameType, Rank::rankPlus1},
566 {"sqrt", {{"x", SameFloating}}, SameFloating},
567 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
568 SameNumeric, Rank::dimReduced},
569 {"tan", {{"x", SameFloating}}, SameFloating},
570 {"tanh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22571 {"trailz", {{"i", AnyInt}}, DefaultInt},
peter klauslerf7f2a732018-10-09 19:07:29572 {"transfer",
573 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::scalar}},
574 SameType, Rank::scalar},
575 {"transfer",
576 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::array}},
577 SameType, Rank::vector},
578 {"transfer",
peter klausler8b580e42018-12-14 19:23:14579 {{"source", Anything, Rank::anyOrAssumedRank},
580 {"mold", SameType, Rank::anyOrAssumedRank},
peter klauslerf7f2a732018-10-09 19:07:29581 {"size", AnyInt, Rank::scalar}},
582 SameType, Rank::vector},
583 {"transpose", {{"matrix", SameType, Rank::matrix}}, SameType, Rank::matrix},
peter klauslerad9aede2018-10-11 21:51:14584 {"trim", {{"string", SameChar, Rank::scalar}}, SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22585 {"ubound",
586 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29587 KINDInt, Rank::vector},
588 {"ubound",
589 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22590 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
591 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29592 KINDInt, Rank::scalar},
593 {"unpack",
594 {{"vector", SameType, Rank::vector}, {"mask", AnyLogical, Rank::array},
595 {"field", SameType, Rank::conformable}},
596 SameType, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11597 {"verify",
peter klauslera70f5962018-10-04 20:43:33598 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54599 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22600 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33601 KINDInt},
peter klausler42b33da2018-09-29 00:02:11602};
603
peter klausler8efb8972018-10-10 17:48:12604// TODO: Coarray intrinsic functions
peter klauslerad9aede2018-10-11 21:51:14605// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
606// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
607// COSHAPE
peter klausler8efb8972018-10-10 17:48:12608// TODO: Object characteristic inquiry functions
peter klauslerad9aede2018-10-11 21:51:14609// ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS,
610// PRESENT, RANK, SAME_TYPE, STORAGE_SIZE
611// TODO: Type inquiry intrinsic functions - these return constants
612// BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT,
613// NEW_LINE, PRECISION, RADIX, RANGE, TINY
614// TODO: Non-standard intrinsic functions
615// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
616// COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL,
617// DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC,
618// QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM,
619// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
620// MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
621// IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
622// EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
623// probably more (these are PGI + Intel, possibly incomplete)
peter klausler42b33da2018-09-29 00:02:11624
peter klauslerba56b912019-02-22 23:45:30625// The following table contains the intrinsic functions listed in
626// Tables 16.2 and 16.3 in Fortran 2018. The "unrestricted" functions
627// in Table 16.2 can be used as actual arguments, PROCEDURE() interfaces,
628// and procedure pointer targets.
peter klausler42b33da2018-09-29 00:02:11629struct SpecificIntrinsicInterface : public IntrinsicInterface {
630 const char *generic{nullptr};
peter klauslerba56b912019-02-22 23:45:30631 bool isRestrictedSpecific{false};
peter klausler42b33da2018-09-29 00:02:11632};
633
peter klauslerb22d4942018-10-01 18:27:45634static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klausler7c402d92018-10-16 21:42:22635 {{"abs", {{"a", DefaultReal}}, DefaultReal}},
636 {{"acos", {{"x", DefaultReal}}, DefaultReal}},
637 {{"aimag", {{"z", DefaultComplex}}, DefaultReal}},
638 {{"aint", {{"a", DefaultReal}}, DefaultReal}},
639 {{"alog", {{"x", DefaultReal}}, DefaultReal}, "log"},
640 {{"alog10", {{"x", DefaultReal}}, DefaultReal}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14641 {{"amax0",
peter klausler7c402d92018-10-16 21:42:22642 {{"a1", DefaultInt}, {"a2", DefaultInt},
643 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
644 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14645 "max", true},
646 {{"amax1",
peter klausler7c402d92018-10-16 21:42:22647 {{"a1", DefaultReal}, {"a2", DefaultReal},
648 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
649 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14650 "max", true},
651 {{"amin0",
peter klausler7c402d92018-10-16 21:42:22652 {{"a1", DefaultInt}, {"a2", DefaultInt},
653 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
654 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14655 "min", true},
656 {{"amin1",
peter klausler7c402d92018-10-16 21:42:22657 {{"a1", DefaultReal}, {"a2", DefaultReal},
658 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
659 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14660 "min", true},
peter klausler7c402d92018-10-16 21:42:22661 {{"amod", {{"a", DefaultReal}, {"p", DefaultReal}}, DefaultReal}, "mod"},
662 {{"anint", {{"a", DefaultReal}}, DefaultReal}},
663 {{"asin", {{"x", DefaultReal}}, DefaultReal}},
664 {{"atan", {{"x", DefaultReal}}, DefaultReal}},
665 {{"atan2", {{"y", DefaultReal}, {"x", DefaultReal}}, DefaultReal}},
666 {{"cabs", {{"a", DefaultComplex}}, DefaultReal}, "abs"},
667 {{"ccos", {{"a", DefaultComplex}}, DefaultComplex}, "cos"},
668 {{"cexp", {{"a", DefaultComplex}}, DefaultComplex}, "exp"},
669 {{"clog", {{"a", DefaultComplex}}, DefaultComplex}, "log"},
670 {{"conjg", {{"a", DefaultComplex}}, DefaultComplex}},
671 {{"cos", {{"x", DefaultReal}}, DefaultReal}},
672 {{"csin", {{"a", DefaultComplex}}, DefaultComplex}, "sin"},
673 {{"csqrt", {{"a", DefaultComplex}}, DefaultComplex}, "sqrt"},
674 {{"ctan", {{"a", DefaultComplex}}, DefaultComplex}, "tan"},
peter klauslera70f5962018-10-04 20:43:33675 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
676 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
677 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
678 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
679 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
680 DoublePrecision},
681 "atan2"},
peter klauslera70f5962018-10-04 20:43:33682 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
683 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
684 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
685 DoublePrecision},
686 "dim"},
687 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
peter klausler7c402d92018-10-16 21:42:22688 {{"dim", {{"x", DefaultReal}, {"y", DefaultReal}}, DefaultReal}},
peter klauslera70f5962018-10-04 20:43:33689 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
690 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
691 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14692 {{"dmax1",
693 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
694 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
695 DoublePrecision},
696 "max", true},
697 {{"dmin1",
698 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
699 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
700 DoublePrecision},
701 "min", true},
peter klauslera70f5962018-10-04 20:43:33702 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
703 DoublePrecision},
704 "mod"},
705 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
peter klausler7c402d92018-10-16 21:42:22706 {{"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision}},
peter klauslera70f5962018-10-04 20:43:33707 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
708 DoublePrecision},
709 "sign"},
710 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
711 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
712 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
713 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
714 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
peter klausler7c402d92018-10-16 21:42:22715 {{"exp", {{"x", DefaultReal}}, DefaultReal}},
716 {{"float", {{"i", DefaultInt}}, DefaultReal}, "real", true},
717 {{"iabs", {{"a", DefaultInt}}, DefaultInt}, "abs"},
718 {{"idim", {{"x", DefaultInt}, {"y", DefaultInt}}, DefaultInt}, "dim"},
719 {{"idint", {{"a", DoublePrecision}}, DefaultInt}, "int", true},
720 {{"idnint", {{"a", DoublePrecision}}, DefaultInt}, "nint"},
721 {{"ifix", {{"a", DefaultReal}}, DefaultInt}, "int", true},
722 {{"index", {{"string", DefaultChar}, {"substring", DefaultChar}},
723 DefaultInt}},
724 {{"isign", {{"a", DefaultInt}, {"b", DefaultInt}}, DefaultInt}, "sign"},
725 {{"len", {{"string", DefaultChar}}, DefaultInt}},
726 {{"log", {{"x", DefaultReal}}, DefaultReal}},
727 {{"log10", {{"x", DefaultReal}}, DefaultReal}},
peter klauslerad9aede2018-10-11 21:51:14728 {{"max0",
peter klausler7c402d92018-10-16 21:42:22729 {{"a1", DefaultInt}, {"a2", DefaultInt},
730 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
731 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14732 "max", true},
733 {{"max1",
peter klausler7c402d92018-10-16 21:42:22734 {{"a1", DefaultReal}, {"a2", DefaultReal},
735 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
736 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14737 "max", true},
738 {{"min0",
peter klausler7c402d92018-10-16 21:42:22739 {{"a1", DefaultInt}, {"a2", DefaultInt},
740 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
741 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14742 "min", true},
743 {{"min1",
peter klausler7c402d92018-10-16 21:42:22744 {{"a1", DefaultReal}, {"a2", DefaultReal},
745 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
746 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14747 "min", true},
peter klausler7c402d92018-10-16 21:42:22748 {{"mod", {{"a", DefaultInt}, {"p", DefaultInt}}, DefaultInt}},
749 {{"nint", {{"a", DefaultReal}}, DefaultInt}},
750 {{"sign", {{"a", DefaultReal}, {"b", DefaultReal}}, DefaultReal}},
751 {{"sin", {{"x", DefaultReal}}, DefaultReal}},
752 {{"sinh", {{"x", DefaultReal}}, DefaultReal}},
753 {{"sngl", {{"a", DoublePrecision}}, DefaultReal}, "real", true},
754 {{"sqrt", {{"x", DefaultReal}}, DefaultReal}},
755 {{"tan", {{"x", DefaultReal}}, DefaultReal}},
756 {{"tanh", {{"x", DefaultReal}}, DefaultReal}},
peter klausler42b33da2018-09-29 00:02:11757};
758
peter klauslerad9aede2018-10-11 21:51:14759// TODO: Intrinsic subroutines
760// MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY,
761// EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT,
762// GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER,
763// RANDOM_SEED, SYSTEM_CLOCK
764// TODO: Atomic intrinsic subroutines: ATOMIC_ADD &al.
765// TODO: Collective intrinsic subroutines: CO_BROADCAST &al.
peter klausler42b33da2018-09-29 00:02:11766
peter klauslera70f5962018-10-04 20:43:33767// Intrinsic interface matching against the arguments of a particular
768// procedure reference.
peter klausleref9dd9d2018-10-17 22:09:48769std::optional<SpecificCall> IntrinsicInterface::Match(
peter klauslerbf339f82018-10-15 22:28:47770 const CallCharacteristics &call,
peter klauslerf9d6c0a2019-01-18 20:40:47771 const common::IntrinsicTypeDefaultKinds &defaults,
peter klausleref9dd9d2018-10-17 22:09:48772 ActualArguments &arguments, parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33773 // Attempt to construct a 1-1 correspondence between the dummy arguments in
774 // a particular intrinsic procedure's generic interface and the actual
775 // arguments in a procedure reference.
peter klausler84ea49d2018-10-18 17:50:55776 std::size_t dummyArgPatterns{0};
777 for (; dummyArgPatterns < maxArguments &&
778 dummy[dummyArgPatterns].keyword != nullptr;
779 ++dummyArgPatterns) {
peter klauslera70f5962018-10-04 20:43:33780 }
peter klausler84ea49d2018-10-18 17:50:55781 std::vector<ActualArgument *> actualForDummy(dummyArgPatterns, nullptr);
782 // MAX and MIN (and others that map to them) allow their last argument to
783 // be repeated indefinitely. The actualForDummy vector is sized
784 // and null-initialized to the non-repeated dummy argument count,
785 // but additional actual argument pointers can be pushed on it
786 // when this flag is set.
787 bool repeatLastDummy{dummyArgPatterns > 0 &&
788 dummy[dummyArgPatterns - 1].optionality == Optionality::repeats};
789 int missingActualArguments{0};
peter klausleref9dd9d2018-10-17 22:09:48790 for (std::optional<ActualArgument> &arg : arguments) {
peter klausler84ea49d2018-10-18 17:50:55791 if (!arg.has_value()) {
792 ++missingActualArguments;
793 } else {
peter klausleref9dd9d2018-10-17 22:09:48794 if (arg->isAlternateReturn) {
795 messages.Say(
796 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
797 name);
798 return std::nullopt;
799 }
800 bool found{false};
peter klausler84ea49d2018-10-18 17:50:55801 int slot{missingActualArguments};
802 for (std::size_t j{0}; j < dummyArgPatterns && !found; ++j) {
803 if (arg->keyword.has_value()) {
804 found = *arg->keyword == dummy[j].keyword;
805 if (found) {
806 if (const auto *previous{actualForDummy[j]}) {
807 if (previous->keyword.has_value()) {
808 messages.Say(*arg->keyword,
809 "repeated keyword argument to intrinsic '%s'"_err_en_US,
810 name);
811 } else {
812 messages.Say(*arg->keyword,
813 "keyword argument to intrinsic '%s' was supplied "
814 "positionally by an earlier actual argument"_err_en_US,
815 name);
816 }
817 return std::nullopt;
818 }
peter klausleref9dd9d2018-10-17 22:09:48819 }
peter klausler84ea49d2018-10-18 17:50:55820 } else {
821 found = actualForDummy[j] == nullptr && slot-- == 0;
822 }
823 if (found) {
824 actualForDummy[j] = &*arg;
peter klauslera70f5962018-10-04 20:43:33825 }
826 }
peter klausleref9dd9d2018-10-17 22:09:48827 if (!found) {
peter klausler84ea49d2018-10-18 17:50:55828 if (repeatLastDummy && !arg->keyword.has_value()) {
829 // MAX/MIN argument after the 2nd
830 actualForDummy.push_back(&*arg);
peter klausleref9dd9d2018-10-17 22:09:48831 } else {
peter klausler84ea49d2018-10-18 17:50:55832 if (arg->keyword.has_value()) {
833 messages.Say(*arg->keyword,
834 "unknown keyword argument to intrinsic '%s'"_err_en_US, name);
835 } else {
836 messages.Say(
837 "too many actual arguments for intrinsic '%s'"_err_en_US, name);
838 }
839 return std::nullopt;
peter klausleref9dd9d2018-10-17 22:09:48840 }
peter klauslera70f5962018-10-04 20:43:33841 }
842 }
843 }
844
peter klausler84ea49d2018-10-18 17:50:55845 std::size_t dummies{actualForDummy.size()};
846
peter klauslera70f5962018-10-04 20:43:33847 // Check types and kinds of the actual arguments against the intrinsic's
848 // interface. Ensure that two or more arguments that have to have the same
849 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19850 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33851 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19852 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33853 bool hasDimArg{false};
peter klausler84ea49d2018-10-18 17:50:55854 for (std::size_t j{0}; j < dummies; ++j) {
855 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
peter klauslera70f5962018-10-04 20:43:33856 if (d.typePattern.kindCode == KindCode::kindArg) {
857 CHECK(kindDummyArg == nullptr);
858 kindDummyArg = &d;
859 }
peter klausler84ea49d2018-10-18 17:50:55860 const ActualArgument *arg{actualForDummy[j]};
peter klauslera70f5962018-10-04 20:43:33861 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54862 if (d.optionality == Optionality::required) {
peter klausler7bda1b32018-10-12 23:01:55863 messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33864 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54865 } else {
866 continue;
peter klauslera70f5962018-10-04 20:43:33867 }
868 }
peter klauslera62636f2018-10-08 22:35:19869 std::optional<DynamicType> type{arg->GetType()};
870 if (!type.has_value()) {
871 CHECK(arg->Rank() == 0);
peter klauslercb308d32018-10-05 18:32:54872 if (d.typePattern.kindCode == KindCode::typeless ||
873 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33874 continue;
875 }
peter klausler7bda1b32018-10-12 23:01:55876 messages.Say(
877 "typeless (BOZ) not allowed for '%s=' argument"_err_en_US, d.keyword);
peter klauslercb308d32018-10-05 18:32:54878 return std::nullopt;
peter klauslera62636f2018-10-08 22:35:19879 } else if (!d.typePattern.categorySet.test(type->category)) {
peter klausler7bda1b32018-10-12 23:01:55880 messages.Say("actual argument for '%s=' has bad type '%s'"_err_en_US,
peter klausler4f6275a2018-11-05 23:02:37881 d.keyword, type->AsFortran().data());
peter klauslera70f5962018-10-04 20:43:33882 return std::nullopt; // argument has invalid type category
883 }
884 bool argOk{false};
885 switch (d.typePattern.kindCode) {
886 case KindCode::none:
887 case KindCode::typeless:
888 case KindCode::teamType: // TODO: TEAM_TYPE
889 argOk = false;
890 break;
891 case KindCode::defaultIntegerKind:
peter klauslerbf339f82018-10-15 22:28:47892 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33893 break;
894 case KindCode::defaultRealKind:
peter klauslerbf339f82018-10-15 22:28:47895 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Real);
peter klauslera70f5962018-10-04 20:43:33896 break;
897 case KindCode::doublePrecision:
peter klauslerbf339f82018-10-15 22:28:47898 argOk = type->kind == defaults.doublePrecisionKind();
peter klauslera70f5962018-10-04 20:43:33899 break;
900 case KindCode::defaultCharKind:
peter klauslerbf339f82018-10-15 22:28:47901 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Character);
peter klauslera70f5962018-10-04 20:43:33902 break;
903 case KindCode::defaultLogicalKind:
peter klauslerbf339f82018-10-15 22:28:47904 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Logical);
peter klauslera70f5962018-10-04 20:43:33905 break;
906 case KindCode::any: argOk = true; break;
907 case KindCode::kindArg:
peter klauslerf7f2a732018-10-09 19:07:29908 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33909 CHECK(kindArg == nullptr);
910 kindArg = arg;
peter klauslerf7f2a732018-10-09 19:07:29911 argOk = true;
peter klauslera70f5962018-10-04 20:43:33912 break;
913 case KindCode::dimArg:
peter klauslerf7f2a732018-10-09 19:07:29914 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33915 hasDimArg = true;
916 argOk = true;
917 break;
918 case KindCode::same:
919 if (sameArg == nullptr) {
920 sameArg = arg;
921 }
peter klausler1b1f60f2018-12-05 21:03:39922 argOk = type.value() == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33923 break;
924 case KindCode::effectiveKind:
925 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
926 "for intrinsic '%s'",
927 d.keyword, name);
928 break;
929 default: CRASH_NO_CASE;
930 }
931 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54932 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55933 "actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
peter klausler4f6275a2018-11-05 23:02:37934 d.keyword, type->AsFortran().data());
peter klauslera70f5962018-10-04 20:43:33935 return std::nullopt;
936 }
937 }
938
939 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:19940 const ActualArgument *arrayArg{nullptr};
941 const ActualArgument *knownArg{nullptr};
942 const ActualArgument *shapeArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33943 int elementalRank{0};
peter klausler84ea49d2018-10-18 17:50:55944 for (std::size_t j{0}; j < dummies; ++j) {
945 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
946 if (const ActualArgument * arg{actualForDummy[j]}) {
peter klausler03618fd2018-10-29 22:25:35947 if (IsAssumedRank(*arg->value) && d.rank != Rank::anyOrAssumedRank) {
948 messages.Say("assumed-rank array cannot be forwarded to "
949 "'%s=' argument"_err_en_US,
peter klauslercb308d32018-10-05 18:32:54950 d.keyword);
peter klauslera70f5962018-10-04 20:43:33951 return std::nullopt;
952 }
peter klauslera62636f2018-10-08 22:35:19953 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:33954 bool argOk{false};
955 switch (d.rank) {
956 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54957 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33958 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:19959 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:33960 }
peter klauslera62636f2018-10-08 22:35:19961 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:33962 break;
peter klauslera62636f2018-10-08 22:35:19963 case Rank::scalar: argOk = rank == 0; break;
964 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:33965 case Rank::shape:
966 CHECK(shapeArg == nullptr);
967 shapeArg = arg;
peter klauslerad9aede2018-10-11 21:51:14968 argOk = rank == 1 && arg->VectorSize().has_value();
peter klauslera70f5962018-10-04 20:43:33969 break;
peter klauslera62636f2018-10-08 22:35:19970 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:33971 case Rank::array:
peter klauslera62636f2018-10-08 22:35:19972 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:33973 if (!arrayArg) {
974 arrayArg = arg;
975 } else {
peter klauslera62636f2018-10-08 22:35:19976 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33977 }
978 break;
979 case Rank::known:
980 CHECK(knownArg == nullptr);
981 knownArg = arg;
982 argOk = true;
983 break;
984 case Rank::anyOrAssumedRank: argOk = true; break;
985 case Rank::conformable:
986 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19987 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33988 break;
989 case Rank::dimRemoved:
990 CHECK(arrayArg != nullptr);
991 if (hasDimArg) {
peter klauslera62636f2018-10-08 22:35:19992 argOk = rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33993 } else {
peter klauslera62636f2018-10-08 22:35:19994 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:33995 }
996 break;
peter klauslerad9aede2018-10-11 21:51:14997 case Rank::reduceOperation:
998 // TODO: Confirm that the argument is a pure function
999 // of two arguments with several constraints
1000 CHECK(arrayArg != nullptr);
1001 argOk = rank == 0;
1002 break;
peter klauslera70f5962018-10-04 20:43:331003 case Rank::dimReduced:
1004 case Rank::rankPlus1:
1005 case Rank::shaped:
1006 common::die("INTERNAL: result-only rank code appears on argument '%s' "
1007 "for intrinsic '%s'",
1008 d.keyword, name);
1009 default: CRASH_NO_CASE;
1010 }
1011 if (!argOk) {
peter klausler7bda1b32018-10-12 23:01:551012 messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:191013 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:331014 return std::nullopt;
1015 }
1016 }
1017 }
1018
peter klauslera70f5962018-10-04 20:43:331019 // Calculate the characteristics of the function result, if any
peter klausleref9dd9d2018-10-17 22:09:481020 std::optional<DynamicType> resultType;
peter klauslera70f5962018-10-04 20:43:331021 if (result.categorySet.empty()) {
peter klausleref9dd9d2018-10-17 22:09:481022 if (!call.isSubroutineCall) {
1023 return std::nullopt;
peter klausler55df4a72018-10-12 23:25:391024 }
peter klausleref9dd9d2018-10-17 22:09:481025 CHECK(result.kindCode == KindCode::none);
1026 } else {
1027 // Determine the result type.
1028 if (call.isSubroutineCall) {
1029 return std::nullopt;
1030 }
peter klausler1b1f60f2018-12-05 21:03:391031 resultType = DynamicType{result.categorySet.LeastElement().value(), 0};
peter klausleref9dd9d2018-10-17 22:09:481032 switch (result.kindCode) {
1033 case KindCode::defaultIntegerKind:
1034 CHECK(result.categorySet == IntType);
1035 CHECK(resultType->category == TypeCategory::Integer);
1036 resultType->kind = defaults.GetDefaultKind(TypeCategory::Integer);
1037 break;
1038 case KindCode::defaultRealKind:
1039 CHECK(result.categorySet == CategorySet{resultType->category});
1040 CHECK(FloatingType.test(resultType->category));
1041 resultType->kind = defaults.GetDefaultKind(TypeCategory::Real);
1042 break;
1043 case KindCode::doublePrecision:
1044 CHECK(result.categorySet == RealType);
1045 CHECK(resultType->category == TypeCategory::Real);
1046 resultType->kind = defaults.doublePrecisionKind();
1047 break;
1048 case KindCode::defaultCharKind:
1049 CHECK(result.categorySet == CharType);
1050 CHECK(resultType->category == TypeCategory::Character);
1051 resultType->kind = defaults.GetDefaultKind(TypeCategory::Character);
1052 break;
1053 case KindCode::defaultLogicalKind:
1054 CHECK(result.categorySet == LogicalType);
1055 CHECK(resultType->category == TypeCategory::Logical);
1056 resultType->kind = defaults.GetDefaultKind(TypeCategory::Logical);
1057 break;
1058 case KindCode::same:
1059 CHECK(sameArg != nullptr);
1060 if (std::optional<DynamicType> aType{sameArg->GetType()}) {
1061 if (result.categorySet.test(aType->category)) {
1062 resultType = *aType;
1063 } else {
1064 resultType->kind = aType->kind;
1065 }
1066 }
1067 break;
1068 case KindCode::effectiveKind:
1069 CHECK(kindDummyArg != nullptr);
1070 CHECK(result.categorySet == CategorySet{resultType->category});
1071 if (kindArg != nullptr) {
peter klauslerabac2282018-10-26 22:10:241072 auto &expr{*kindArg->value};
1073 CHECK(expr.Rank() == 0);
1074 if (auto code{ToInt64(expr)}) {
1075 if (IsValidKindOfIntrinsicType(resultType->category, *code)) {
1076 resultType->kind = *code;
1077 break;
peter klauslerf7f2a732018-10-09 19:07:291078 }
1079 }
peter klausleref9dd9d2018-10-17 22:09:481080 messages.Say("'kind=' argument must be a constant scalar integer "
1081 "whose value is a supported kind for the "
1082 "intrinsic result type"_err_en_US);
1083 return std::nullopt;
1084 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
1085 CHECK(sameArg != nullptr);
1086 resultType = *sameArg->GetType();
1087 } else if (kindDummyArg->optionality ==
1088 Optionality::defaultsToSubscriptKind) {
1089 CHECK(resultType->category == TypeCategory::Integer);
1090 resultType->kind = defaults.subscriptIntegerKind();
1091 } else {
1092 CHECK(kindDummyArg->optionality ==
1093 Optionality::defaultsToDefaultForResult);
1094 resultType->kind = defaults.GetDefaultKind(resultType->category);
peter klauslerf7f2a732018-10-09 19:07:291095 }
peter klausleref9dd9d2018-10-17 22:09:481096 break;
1097 case KindCode::likeMultiply:
1098 CHECK(dummies >= 2);
1099 CHECK(actualForDummy[0] != nullptr);
1100 CHECK(actualForDummy[1] != nullptr);
1101 resultType = actualForDummy[0]->GetType()->ResultTypeForMultiply(
1102 *actualForDummy[1]->GetType());
1103 break;
1104 case KindCode::typeless:
1105 case KindCode::teamType:
1106 case KindCode::any:
1107 case KindCode::kindArg:
1108 case KindCode::dimArg:
1109 common::die(
1110 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
1111 break;
1112 default: CRASH_NO_CASE;
peter klauslera70f5962018-10-04 20:43:331113 }
peter klauslera70f5962018-10-04 20:43:331114 }
1115
peter klauslerf7f2a732018-10-09 19:07:291116 // At this point, the call is acceptable.
peter klauslera70f5962018-10-04 20:43:331117 // Determine the rank of the function result.
1118 int resultRank{0};
1119 switch (rank) {
1120 case Rank::elemental: resultRank = elementalRank; break;
1121 case Rank::scalar: resultRank = 0; break;
1122 case Rank::vector: resultRank = 1; break;
1123 case Rank::matrix: resultRank = 2; break;
peter klauslerf7f2a732018-10-09 19:07:291124 case Rank::conformable:
1125 CHECK(arrayArg != nullptr);
1126 resultRank = arrayArg->Rank();
1127 break;
peter klauslera70f5962018-10-04 20:43:331128 case Rank::dimReduced:
1129 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191130 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:331131 break;
1132 case Rank::rankPlus1:
1133 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191134 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:331135 break;
1136 case Rank::shaped:
1137 CHECK(shapeArg != nullptr);
peter klausler1b1f60f2018-12-05 21:03:391138 resultRank = shapeArg->VectorSize().value();
peter klauslera70f5962018-10-04 20:43:331139 break;
peter klauslercb308d32018-10-05 18:32:541140 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331141 case Rank::shape:
1142 case Rank::array:
1143 case Rank::known:
1144 case Rank::anyOrAssumedRank:
peter klauslera70f5962018-10-04 20:43:331145 case Rank::dimRemoved:
peter klauslerad9aede2018-10-11 21:51:141146 case Rank::reduceOperation:
peter klauslera70f5962018-10-04 20:43:331147 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
1148 break;
1149 default: CRASH_NO_CASE;
1150 }
1151 CHECK(resultRank >= 0);
1152
peter klauslerfdd3a2a2018-10-16 23:36:431153 semantics::Attrs attrs;
1154 if (elementalRank > 0) {
1155 attrs.set(semantics::Attr::ELEMENTAL);
1156 }
1157
peter klausleref9dd9d2018-10-17 22:09:481158 // Rearrange the actual arguments into dummy argument order.
1159 ActualArguments rearranged(dummies);
peter klausler84ea49d2018-10-18 17:50:551160 for (std::size_t j{0}; j < dummies; ++j) {
peter klausleref9dd9d2018-10-17 22:09:481161 if (ActualArgument * arg{actualForDummy[j]}) {
peter klausler84ea49d2018-10-18 17:50:551162 rearranged[j] = std::move(*arg);
peter klausleref9dd9d2018-10-17 22:09:481163 }
1164 }
1165
1166 return {SpecificCall{
1167 SpecificIntrinsic{name, std::move(resultType), resultRank, attrs},
1168 std::move(rearranged)}};
peter klauslera70f5962018-10-04 20:43:331169}
1170
peter klauslerba56b912019-02-22 23:45:301171class IntrinsicProcTable::Implementation {
1172public:
peter klauslerf9d6c0a2019-01-18 20:40:471173 explicit Implementation(const common::IntrinsicTypeDefaultKinds &dfts)
peter klauslerba56b912019-02-22 23:45:301174 : defaults_{dfts} {
peter klauslera70f5962018-10-04 20:43:331175 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
peter klauslerba56b912019-02-22 23:45:301176 genericFuncs_.insert(std::make_pair(std::string{f.name}, &f));
peter klauslera70f5962018-10-04 20:43:331177 }
1178 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
peter klauslerba56b912019-02-22 23:45:301179 specificFuncs_.insert(std::make_pair(std::string{f.name}, &f));
peter klauslera70f5962018-10-04 20:43:331180 }
1181 }
peter klausler42b33da2018-09-29 00:02:111182
peter klauslerf9535832019-02-26 22:26:281183 bool IsIntrinsic(const std::string &) const;
1184
peter klausleref9dd9d2018-10-17 22:09:481185 std::optional<SpecificCall> Probe(const CallCharacteristics &,
1186 ActualArguments &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:531187
peter klauslerba56b912019-02-22 23:45:301188 std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1189 IsUnrestrictedSpecificIntrinsicFunction(const std::string &) const;
1190
peter klausler7bda1b32018-10-12 23:01:551191 std::ostream &Dump(std::ostream &) const;
peter klauslerba56b912019-02-22 23:45:301192
1193private:
1194 common::IntrinsicTypeDefaultKinds defaults_;
1195 std::multimap<std::string, const IntrinsicInterface *> genericFuncs_;
1196 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs_;
1197
1198 DynamicType GetSpecificType(const TypePattern &) const;
peter klausler42b33da2018-09-29 00:02:111199};
1200
peter klauslerf9535832019-02-26 22:26:281201bool IntrinsicProcTable::Implementation::IsIntrinsic(
1202 const std::string &name) const {
1203 auto specificRange{specificFuncs_.equal_range(name)};
1204 if (specificRange.first != specificRange.second) {
1205 return true;
1206 }
1207 auto genericRange{genericFuncs_.equal_range(name)};
1208 if (genericRange.first != genericRange.second) {
1209 return true;
1210 }
1211 // special cases
1212 return name == "null"; // TODO more
1213}
1214
peter klauslercb308d32018-10-05 18:32:541215// Probe the configured intrinsic procedure pattern tables in search of a
1216// match for a given procedure reference.
peter klausleref9dd9d2018-10-17 22:09:481217std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
1218 const CallCharacteristics &call, ActualArguments &arguments,
peter klauslercb308d32018-10-05 18:32:541219 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:531220 if (call.isSubroutineCall) {
1221 return std::nullopt; // TODO
1222 }
peter klausler7bda1b32018-10-12 23:01:551223 parser::Messages *finalBuffer{messages ? messages->messages() : nullptr};
peter klausler62425d62018-10-12 00:01:311224 // Probe the specific intrinsic function table first.
1225 parser::Messages specificBuffer;
1226 parser::ContextualMessages specificErrors{
1227 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551228 finalBuffer ? &specificBuffer : nullptr};
peter klausler75a32092018-10-05 16:57:531229 std::string name{call.name.ToString()};
peter klauslerba56b912019-02-22 23:45:301230 auto specificRange{specificFuncs_.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531231 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klausleref9dd9d2018-10-17 22:09:481232 if (auto specificCall{
peter klauslerba56b912019-02-22 23:45:301233 iter->second->Match(call, defaults_, arguments, specificErrors)}) {
peter klauslerad9aede2018-10-11 21:51:141234 if (const char *genericName{iter->second->generic}) {
peter klausleref9dd9d2018-10-17 22:09:481235 specificCall->specificIntrinsic.name = genericName;
peter klauslerad9aede2018-10-11 21:51:141236 }
peter klausleref9dd9d2018-10-17 22:09:481237 specificCall->specificIntrinsic.isRestrictedSpecific =
1238 iter->second->isRestrictedSpecific;
1239 return specificCall;
peter klausler75a32092018-10-05 16:57:531240 }
1241 }
peter klausler62425d62018-10-12 00:01:311242 // Probe the generic intrinsic function table next.
1243 parser::Messages genericBuffer;
1244 parser::ContextualMessages genericErrors{
1245 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551246 finalBuffer ? &genericBuffer : nullptr};
peter klauslerba56b912019-02-22 23:45:301247 auto genericRange{genericFuncs_.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531248 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klausleref9dd9d2018-10-17 22:09:481249 if (auto specificCall{
peter klauslerba56b912019-02-22 23:45:301250 iter->second->Match(call, defaults_, arguments, genericErrors)}) {
peter klausleref9dd9d2018-10-17 22:09:481251 return specificCall;
peter klausler75a32092018-10-05 16:57:531252 }
1253 }
peter klauslerad9aede2018-10-11 21:51:141254 // Special cases of intrinsic functions
peter klausler8efb8972018-10-10 17:48:121255 if (call.name.ToString() == "null") {
peter klausleref9dd9d2018-10-17 22:09:481256 if (arguments.size() == 0) {
peter klausler8efb8972018-10-10 17:48:121257 // TODO: NULL() result type is determined by context
1258 // Can pass that context in, or return a token distinguishing
1259 // NULL, or represent NULL as a new kind of top-level expression
peter klausleref9dd9d2018-10-17 22:09:481260 } else if (arguments.size() > 1) {
peter klausler62425d62018-10-12 00:01:311261 genericErrors.Say("too many arguments to NULL()"_err_en_US);
peter klausleref9dd9d2018-10-17 22:09:481262 } else if (arguments[0].has_value() && arguments[0]->keyword.has_value() &&
1263 arguments[0]->keyword->ToString() != "mold") {
peter klausler62425d62018-10-12 00:01:311264 genericErrors.Say("unknown argument '%s' to NULL()"_err_en_US,
peter klausleref9dd9d2018-10-17 22:09:481265 arguments[0]->keyword->ToString().data());
peter klausler8efb8972018-10-10 17:48:121266 } else {
1267 // TODO: Argument must be pointer, procedure pointer, or allocatable.
1268 // Characteristics, including dynamic length type parameter values,
1269 // must be taken from the MOLD argument.
peter klauslerfdd3a2a2018-10-16 23:36:431270 // TODO: set Attr::POINTER on NULL result
peter klausler8efb8972018-10-10 17:48:121271 }
1272 }
1273 // No match
peter klausler7bda1b32018-10-12 23:01:551274 if (finalBuffer) {
peter klausler62425d62018-10-12 00:01:311275 if (genericBuffer.empty()) {
peter klausler7bda1b32018-10-12 23:01:551276 finalBuffer->Annex(std::move(specificBuffer));
peter klausler62425d62018-10-12 00:01:311277 } else {
peter klausler7bda1b32018-10-12 23:01:551278 finalBuffer->Annex(std::move(genericBuffer));
peter klausler62425d62018-10-12 00:01:311279 }
peter klauslercb308d32018-10-05 18:32:541280 }
peter klausler75a32092018-10-05 16:57:531281 return std::nullopt;
1282}
1283
peter klauslerba56b912019-02-22 23:45:301284std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1285IntrinsicProcTable::Implementation::IsUnrestrictedSpecificIntrinsicFunction(
1286 const std::string &name) const {
1287 auto specificRange{specificFuncs_.equal_range(name)};
1288 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
1289 const SpecificIntrinsicInterface &specific{*iter->second};
1290 if (!specific.isRestrictedSpecific) {
1291 UnrestrictedSpecificIntrinsicFunctionInterface result;
1292 if (specific.generic != nullptr) {
1293 result.genericName = std::string(specific.generic);
1294 } else {
1295 result.genericName = name;
1296 }
peter klauslerf9535832019-02-26 22:26:281297 result.attrs.set(characteristics::Procedure::Attr::Pure);
1298 result.attrs.set(characteristics::Procedure::Attr::Elemental);
1299 int dummies{specific.CountArguments()};
1300 for (int j{0}; j < dummies; ++j) {
1301 characteristics::DummyDataObject dummy{
1302 GetSpecificType(specific.dummy[j].typePattern)};
1303 dummy.intent = common::Intent::In;
1304 result.dummyArguments.emplace_back(std::move(dummy));
1305 }
1306 result.functionResult.emplace(
1307 characteristics::FunctionResult{GetSpecificType(specific.result)});
peter klauslerba56b912019-02-22 23:45:301308 return result;
1309 }
1310 }
1311 return std::nullopt;
1312}
1313
1314DynamicType IntrinsicProcTable::Implementation::GetSpecificType(
1315 const TypePattern &pattern) const {
1316 const CategorySet &set{pattern.categorySet};
1317 CHECK(set.count() == 1);
1318 TypeCategory category{set.LeastElement().value()};
1319 return DynamicType{category, defaults_.GetDefaultKind(category)};
1320}
1321
peter klauslera62636f2018-10-08 22:35:191322IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:541323 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:111324 delete impl_;
1325 impl_ = nullptr;
1326}
1327
peter klauslera62636f2018-10-08 22:35:191328IntrinsicProcTable IntrinsicProcTable::Configure(
peter klauslerf9d6c0a2019-01-18 20:40:471329 const common::IntrinsicTypeDefaultKinds &defaults) {
peter klauslera62636f2018-10-08 22:35:191330 IntrinsicProcTable result;
1331 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:111332 return result;
1333}
1334
peter klauslerf9535832019-02-26 22:26:281335bool IntrinsicProcTable::IsIntrinsic(const std::string &name) const {
1336 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
1337 return impl_->IsIntrinsic(name);
1338}
1339
peter klausleref9dd9d2018-10-17 22:09:481340std::optional<SpecificCall> IntrinsicProcTable::Probe(
1341 const CallCharacteristics &call, ActualArguments &arguments,
peter klauslercb308d32018-10-05 18:32:541342 parser::ContextualMessages *messages) const {
peter klauslera62636f2018-10-08 22:35:191343 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klausleref9dd9d2018-10-17 22:09:481344 return impl_->Probe(call, arguments, messages);
peter klausler42b33da2018-09-29 00:02:111345}
peter klauslerad9aede2018-10-11 21:51:141346
peter klauslerba56b912019-02-22 23:45:301347std::optional<UnrestrictedSpecificIntrinsicFunctionInterface>
1348IntrinsicProcTable::IsUnrestrictedSpecificIntrinsicFunction(
1349 const std::string &name) const {
1350 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
1351 return impl_->IsUnrestrictedSpecificIntrinsicFunction(name);
1352}
1353
peter klausler7bda1b32018-10-12 23:01:551354std::ostream &TypePattern::Dump(std::ostream &o) const {
1355 if (categorySet == AnyType) {
1356 o << "any type";
1357 } else {
1358 const char *sep = "";
1359 auto set{categorySet};
1360 while (auto least{set.LeastElement()}) {
1361 o << sep << EnumToString(*least);
1362 sep = " or ";
1363 set.reset(*least);
1364 }
1365 }
1366 o << '(' << EnumToString(kindCode) << ')';
1367 return o;
1368}
1369
1370std::ostream &IntrinsicDummyArgument::Dump(std::ostream &o) const {
1371 if (keyword) {
1372 o << keyword << '=';
1373 }
1374 return typePattern.Dump(o)
1375 << ' ' << EnumToString(rank) << ' ' << EnumToString(optionality);
1376}
1377
1378std::ostream &IntrinsicInterface::Dump(std::ostream &o) const {
1379 o << name;
1380 char sep{'('};
1381 for (const auto &d : dummy) {
1382 if (d.typePattern.kindCode == KindCode::none) {
1383 break;
1384 }
1385 d.Dump(o << sep);
1386 sep = ',';
1387 }
1388 if (sep == '(') {
1389 o << "()";
1390 }
1391 return result.Dump(o << " -> ") << ' ' << EnumToString(rank);
1392}
1393
1394std::ostream &IntrinsicProcTable::Implementation::Dump(std::ostream &o) const {
1395 o << "generic intrinsic functions:\n";
peter klauslerba56b912019-02-22 23:45:301396 for (const auto &iter : genericFuncs_) {
peter klausler7bda1b32018-10-12 23:01:551397 iter.second->Dump(o << iter.first << ": ") << '\n';
1398 }
1399 o << "specific intrinsic functions:\n";
peter klauslerba56b912019-02-22 23:45:301400 for (const auto &iter : specificFuncs_) {
peter klausler7bda1b32018-10-12 23:01:551401 iter.second->Dump(o << iter.first << ": ");
1402 if (const char *g{iter.second->generic}) {
1403 o << " -> " << g;
1404 }
1405 o << '\n';
1406 }
1407 return o;
1408}
1409
1410std::ostream &IntrinsicProcTable::Dump(std::ostream &o) const {
1411 return impl_->Dump(o);
1412}
Jean Perierf7e7cb32018-10-25 12:55:231413}