blob: 89de6e5a4e260ad13d458403acb0deb318952e3b [file] [log] [blame]
peter klausler42b33da2018-09-29 00:02:111// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
2//
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 klausler42b33da2018-09-29 00:02:1117#include "type.h"
18#include "../common/enum-set.h"
19#include "../common/fortran.h"
peter klauslera70f5962018-10-04 20:43:3320#include "../common/idioms.h"
peter klauslera70f5962018-10-04 20:43:3321#include <map>
22#include <string>
23#include <utility>
peter klausler42b33da2018-09-29 00:02:1124
peter klauslercb308d32018-10-05 18:32:5425using namespace Fortran::parser::literals;
26
peter klausler42b33da2018-09-29 00:02:1127namespace Fortran::evaluate {
28
29using common::TypeCategory;
30
peter klauslera70f5962018-10-04 20:43:3331// This file defines the supported intrinsic procedures and implements
32// their recognition and validation. It is largely table-driven. See
33// documentation/intrinsics.md and section 16 of the Fortran 2018 standard
34// for full details on each of the intrinsics. Be advised, they have
35// complicated details, and the design of these tables has to accommodate
36// that complexity.
37
peter klausler42b33da2018-09-29 00:02:1138// Dummy arguments to generic intrinsic procedures are each specified by
peter klauslera70f5962018-10-04 20:43:3339// their keyword name (rarely used, but always defined), allowable type
peter klauslercb308d32018-10-05 18:32:5440// categories, a kind pattern, a rank pattern, and information about
41// optionality and defaults. The kind and rank patterns are represented
42// here with code values that are significant to the matching/validation engine.
peter klausler42b33da2018-09-29 00:02:1143
peter klauslera70f5962018-10-04 20:43:3344// These are small bit-sets of type category enumerators.
45// Note that typeless (BOZ literal) values don't have a distinct type category.
46// These typeless arguments are represented in the tables as if they were
47// INTEGER with a special "typeless" kind code. Arguments of intrinsic types
peter klauslercb308d32018-10-05 18:32:5448// that can also be be typeless values are encoded with an "elementalOrBOZ"
49// rank pattern.
peter klauslera70f5962018-10-04 20:43:3350using CategorySet = common::EnumSet<TypeCategory, 8>;
51static constexpr CategorySet Int{TypeCategory::Integer};
52static constexpr CategorySet Real{TypeCategory::Real};
53static constexpr CategorySet Complex{TypeCategory::Complex};
54static constexpr CategorySet Char{TypeCategory::Character};
55static constexpr CategorySet Logical{TypeCategory::Logical};
56static constexpr CategorySet IntOrReal{Int | Real};
57static constexpr CategorySet Floating{Real | Complex};
58static constexpr CategorySet Numeric{Int | Real | Complex};
59static constexpr CategorySet Relatable{Int | Real | Char};
60static constexpr CategorySet IntrinsicType{
61 Int | Real | Complex | Char | Logical};
62static constexpr CategorySet AnyType{
63 IntrinsicType | CategorySet{TypeCategory::Derived}};
peter klausler42b33da2018-09-29 00:02:1164
65enum class KindCode {
peter klauslerb22d4942018-10-01 18:27:4566 none,
peter klausler42b33da2018-09-29 00:02:1167 defaultIntegerKind,
peter klauslera70f5962018-10-04 20:43:3368 defaultRealKind, // is also the default COMPLEX kind
peter klausler42b33da2018-09-29 00:02:1169 doublePrecision,
peter klauslera70f5962018-10-04 20:43:3370 defaultCharKind,
peter klausler42b33da2018-09-29 00:02:1171 defaultLogicalKind,
peter klauslera70f5962018-10-04 20:43:3372 any, // matches any kind value; each instance is independent
73 typeless, // BOZ literals are INTEGER with this kind
74 teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
75 kindArg, // this argument is KIND=
76 effectiveKind, // for function results: same "kindArg", possibly defaulted
77 dimArg, // this argument is DIM=
78 same, // match any kind; all "same" kinds must be equal
peter klausler42b33da2018-09-29 00:02:1179};
80
81struct TypePattern {
82 CategorySet categorySet;
peter klauslerb22d4942018-10-01 18:27:4583 KindCode kindCode{KindCode::none};
peter klausler42b33da2018-09-29 00:02:1184};
85
peter klauslera70f5962018-10-04 20:43:3386// Abbreviations for argument and result patterns in the intrinsic prototypes:
87
88// Match specific kinds of intrinsic types
89static constexpr TypePattern DftInt{Int, KindCode::defaultIntegerKind};
90static constexpr TypePattern DftReal{Real, KindCode::defaultRealKind};
91static constexpr TypePattern DftComplex{Complex, KindCode::defaultRealKind};
92static constexpr TypePattern DftChar{Char, KindCode::defaultCharKind};
93static constexpr TypePattern DftLogical{Logical, KindCode::defaultLogicalKind};
94static constexpr TypePattern BOZ{Int, KindCode::typeless};
95static constexpr TypePattern TEAM_TYPE{Int, KindCode::teamType};
96static constexpr TypePattern DoublePrecision{Real, KindCode::doublePrecision};
97
98// Match any kind of some intrinsic or derived types
99static constexpr TypePattern AnyInt{Int, KindCode::any};
100static constexpr TypePattern AnyReal{Real, KindCode::any};
101static constexpr TypePattern AnyIntOrReal{IntOrReal, KindCode::any};
102static constexpr TypePattern AnyComplex{Complex, KindCode::any};
103static constexpr TypePattern AnyNumeric{Numeric, KindCode::any};
104static constexpr TypePattern AnyChar{Char, KindCode::any};
105static constexpr TypePattern AnyLogical{Logical, KindCode::any};
106static constexpr TypePattern AnyRelatable{Relatable, KindCode::any};
107
108// Match some kind of some intrinsic type(s); all "Same" values must match,
109// even when not in the same category (e.g., SameComplex and SameReal).
110// Can be used to specify a result so long as at least one argument is
111// a "Same".
112static constexpr TypePattern SameInt{Int, KindCode::same};
113static constexpr TypePattern SameReal{Real, KindCode::same};
114static constexpr TypePattern SameIntOrReal{IntOrReal, KindCode::same};
115static constexpr TypePattern SameComplex{Complex, KindCode::same};
116static constexpr TypePattern SameFloating{Floating, KindCode::same};
117static constexpr TypePattern SameNumeric{Numeric, KindCode::same};
118static constexpr TypePattern SameChar{Char, KindCode::same};
119static constexpr TypePattern SameLogical{Logical, KindCode::same};
120static constexpr TypePattern SameRelatable{Relatable, KindCode::same};
121static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
122static constexpr TypePattern SameDerivedType{
123 CategorySet{TypeCategory::Derived}, KindCode::same};
124static constexpr TypePattern SameType{AnyType, KindCode::same};
125
126// Result types with known category and KIND=
127static constexpr TypePattern KINDInt{Int, KindCode::effectiveKind};
128static constexpr TypePattern KINDReal{Real, KindCode::effectiveKind};
129static constexpr TypePattern KINDComplex{Complex, KindCode::effectiveKind};
130static constexpr TypePattern KINDChar{Char, KindCode::effectiveKind};
131static constexpr TypePattern KINDLogical{Logical, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11132
133// The default rank pattern for dummy arguments and function results is
134// "elemental".
peter klauslera70f5962018-10-04 20:43:33135enum class Rank {
136 elemental, // scalar, or array that conforms with other array arguments
peter klauslercb308d32018-10-05 18:32:54137 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
peter klausler42b33da2018-09-29 00:02:11138 scalar,
139 vector,
peter klauslera70f5962018-10-04 20:43:33140 shape, // INTEGER vector of known length and no negative element
peter klausler42b33da2018-09-29 00:02:11141 matrix,
142 array, // not scalar, rank is known and greater than zero
143 known, // rank is known and can be scalar
144 anyOrAssumedRank, // rank can be unknown
145 conformable, // scalar, or array of same rank & shape as "array" argument
146 dimReduced, // scalar if no DIM= argument, else rank(array)-1
147 dimRemoved, // scalar, or rank(array)-1
148 rankPlus1, // rank(known)+1
149 shaped, // rank is length of SHAPE vector
150};
151
peter klauslercb308d32018-10-05 18:32:54152enum class Optionality {
153 required,
peter klausler42b33da2018-09-29 00:02:11154 optional,
peter klauslercb308d32018-10-05 18:32:54155 defaultsToSameKind, // for MatchingDefaultKIND
156 defaultsToDefaultForResult, // for DefaultingKIND
peter klausler42b33da2018-09-29 00:02:11157};
158
159struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45160 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11161 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33162 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54163 Optionality optionality{Optionality::required};
peter klausler42b33da2018-09-29 00:02:11164};
165
peter klauslera70f5962018-10-04 20:43:33166// constexpr abbreviations for popular arguments:
167// DefaultingKIND is a KIND= argument whose default value is the appropriate
168// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54169static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
170 {Int, KindCode::kindArg}, Rank::scalar,
171 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33172// MatchingDefaultKIND is a KIND= argument whose default value is the
173// kind of any "Same" function argument (viz., the one whose kind pattern is
174// "same").
peter klauslercb308d32018-10-05 18:32:54175static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
176 {Int, KindCode::kindArg}, Rank::scalar, Optionality::defaultsToSameKind};
peter klauslera70f5962018-10-04 20:43:33177static constexpr IntrinsicDummyArgument OptionalDIM{
peter klauslercb308d32018-10-05 18:32:54178 "dim", {Int, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33179static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54180 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11181
182struct IntrinsicInterface {
183 static constexpr int maxArguments{7};
peter klauslerb22d4942018-10-01 18:27:45184 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11185 IntrinsicDummyArgument dummy[maxArguments];
186 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33187 Rank rank{Rank::elemental};
188 std::optional<SpecificIntrinsic> Match(const CallCharacteristics &,
peter klauslera62636f2018-10-08 22:35:19189 const IntrinsicTypeDefaultKinds &,
peter klauslercb308d32018-10-05 18:32:54190 parser::ContextualMessages &messages) const;
peter klausler42b33da2018-09-29 00:02:11191};
192
peter klauslerb22d4942018-10-01 18:27:45193static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33194 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
195 {"abs", {{"a", SameComplex}}, SameReal},
196 {"achar", {{"i", SameInt}, DefaultingKIND}, KINDChar},
197 {"acos", {{"x", SameFloating}}, SameFloating},
198 {"acosh", {{"x", SameFloating}}, SameFloating},
199 {"adjustl", {{"string", SameChar}}, SameChar},
200 {"adjustr", {{"string", SameChar}}, SameChar},
201 {"aimag", {{"x", SameComplex}}, SameReal},
202 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
203 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
204 Rank::dimReduced},
205 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
206 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
207 Rank::dimReduced},
208 {"asin", {{"x", SameFloating}}, SameFloating},
209 {"asinh", {{"x", SameFloating}}, SameFloating},
210 {"atan", {{"x", SameFloating}}, SameFloating},
211 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
212 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
213 {"atanh", {{"x", SameFloating}}, SameFloating},
214 {"bessel_j0", {{"x", SameReal}}, SameReal},
215 {"bessel_j1", {{"x", SameReal}}, SameReal},
216 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
217 {"bessel_y0", {{"x", SameReal}}, SameReal},
218 {"bessel_y1", {{"x", SameReal}}, SameReal},
219 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
220 {"bge",
peter klauslercb308d32018-10-05 18:32:54221 {{"i", AnyInt, Rank::elementalOrBOZ},
222 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33223 DftLogical},
224 {"bgt",
peter klauslercb308d32018-10-05 18:32:54225 {{"i", AnyInt, Rank::elementalOrBOZ},
226 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33227 DftLogical},
228 {"ble",
peter klauslercb308d32018-10-05 18:32:54229 {{"i", AnyInt, Rank::elementalOrBOZ},
230 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33231 DftLogical},
232 {"blt",
peter klauslercb308d32018-10-05 18:32:54233 {{"i", AnyInt, Rank::elementalOrBOZ},
234 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33235 DftLogical},
236 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DftLogical},
237 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
238 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
239 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11240 {"cmplx",
peter klauslercb308d32018-10-05 18:32:54241 {{"x", SameIntOrReal, Rank::elementalOrBOZ},
242 {"y", SameIntOrReal, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33243 KINDComplex},
244 {"conjg", {{"z", SameComplex}}, SameComplex},
245 {"cos", {{"x", SameFloating}}, SameFloating},
246 {"cosh", {{"x", SameFloating}}, SameFloating},
247 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
248 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11249 {"cshift",
peter klauslera70f5962018-10-04 20:43:33250 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
251 OptionalDIM},
252 SameType, Rank::array},
253 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
254 {"dprod", {{"x", DftReal}, {"y", DftReal}}, DoublePrecision},
255 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54256 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33257 {"shift", AnyInt}},
258 SameInt},
259 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
260 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54261 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33262 {"shift", AnyInt}},
263 SameInt},
264 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11265 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33266 {{"array", SameIntrinsic, Rank::array},
267 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54268 {"boundary", SameIntrinsic, Rank::dimRemoved,
269 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33270 OptionalDIM},
271 SameIntrinsic, Rank::array},
peter klausler42b33da2018-09-29 00:02:11272 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33273 {{"array", SameDerivedType, Rank::array},
274 {"shift", AnyInt, Rank::dimRemoved},
275 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
276 SameDerivedType, Rank::array},
277 {"erf", {{"x", SameReal}}, SameReal},
278 {"erfc", {{"x", SameReal}}, SameReal},
279 {"erfc_scaled", {{"x", SameReal}}, SameReal},
280 {"exp", {{"x", SameFloating}}, SameFloating},
281 {"exponent", {{"x", AnyReal}}, DftInt},
peter klausler42b33da2018-09-29 00:02:11282 {"findloc",
peter klauslera70f5962018-10-04 20:43:33283 {{"array", SameNumeric, Rank::array},
284 {"value", SameNumeric, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54285 DefaultingKIND,
286 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33287 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11288 {"findloc",
peter klauslera70f5962018-10-04 20:43:33289 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
290 OptionalDIM, OptionalMASK, DefaultingKIND,
peter klauslercb308d32018-10-05 18:32:54291 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33292 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11293 {"findloc",
peter klauslera70f5962018-10-04 20:43:33294 {{"array", AnyLogical, Rank::array},
295 {"value", AnyLogical, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54296 DefaultingKIND,
297 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33298 KINDInt, Rank::dimReduced},
299 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
300 {"fraction", {{"x", SameReal}}, SameReal},
301 {"gamma", {{"x", SameReal}}, SameReal},
302 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
303 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
304 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
305 SameInt, Rank::dimReduced},
306 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
307 SameInt, Rank::dimReduced},
308 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
309 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54310 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33311 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
312 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
313 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
314 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
315 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54316 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33317 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
318 {"image_status",
peter klauslercb308d32018-10-05 18:32:54319 {{"image", SameInt},
320 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33321 DftInt},
peter klausler42b33da2018-09-29 00:02:11322 {"index",
peter klauslera70f5962018-10-04 20:43:33323 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54324 {"back", AnyLogical, Rank::scalar, Optionality::optional},
325 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33326 KINDInt},
peter klauslercb308d32018-10-05 18:32:54327 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
328 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33329 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
330 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
331 {"ishftc",
332 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54333 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33334 SameInt},
335 {"is_iostat_end", {{"i", AnyInt}}, DftLogical},
336 {"is_iostat_eor", {{"i", AnyInt}}, DftLogical},
337 {"leadz", {{"i", AnyInt}}, DftInt},
338 {"len", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
339 {"len_trim", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
340 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
341 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
342 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
343 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
344 {"log", {{"x", SameFloating}}, SameFloating},
345 {"log10", {{"x", SameReal}}, SameReal},
346 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
347 {"log_gamma", {{"x", SameReal}}, SameReal},
348 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
349 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klausler42b33da2018-09-29 00:02:11350 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33351 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54352 DefaultingKIND,
353 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33354 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11355 {"maxval",
peter klauslera70f5962018-10-04 20:43:33356 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
357 SameRelatable, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11358 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54359 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
360 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33361 SameInt},
362 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54363 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33364 SameInt},
peter klausler42b33da2018-09-29 00:02:11365 {"minloc",
peter klauslera70f5962018-10-04 20:43:33366 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54367 DefaultingKIND,
368 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33369 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11370 {"minval",
peter klauslera70f5962018-10-04 20:43:33371 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
372 SameRelatable, Rank::dimReduced},
373 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
374 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
375 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
376 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
377 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
378 Rank::dimReduced},
379 {"not", {{"i", SameInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11380 {"out_of_range",
peter klauslera70f5962018-10-04 20:43:33381 {{"x", SameIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
382 DftLogical},
383 {"out_of_range",
384 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54385 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33386 DftLogical},
387 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DftLogical},
peter klausler42b33da2018-09-29 00:02:11388 {"pack",
peter klauslera70f5962018-10-04 20:43:33389 {{"array", SameType, Rank::array},
390 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54391 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33392 SameType, Rank::vector},
393 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
394 Rank::dimReduced},
395 {"popcnt", {{"i", AnyInt}}, DftInt},
396 {"poppar", {{"i", AnyInt}}, DftInt},
peter klausler42b33da2018-09-29 00:02:11397 {"product",
peter klauslera70f5962018-10-04 20:43:33398 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
399 SameNumeric, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54400 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33401 KINDReal},
peter klausler42b33da2018-09-29 00:02:11402 {"reshape",
peter klauslera70f5962018-10-04 20:43:33403 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54404 {"pad", SameType, Rank::array, Optionality::optional},
405 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33406 SameType, Rank::shaped},
407 {"rrspacing", {{"x", SameReal}}, SameReal},
408 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11409 {"scan",
peter klauslera70f5962018-10-04 20:43:33410 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54411 {"back", AnyLogical, Rank::elemental, Optionality::optional},
412 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33413 KINDInt},
414 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
415 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
416 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
417 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
418 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
419 {"sin", {{"x", SameFloating}}, SameFloating},
420 {"sinh", {{"x", SameFloating}}, SameFloating},
421 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11422 {"spread",
peter klauslera70f5962018-10-04 20:43:33423 {{"source", SameType, Rank::known},
424 {"dim", {Int, KindCode::dimArg}, Rank::scalar /*not optional*/},
425 {"ncopies", AnyInt, Rank::scalar}},
426 SameType, Rank::rankPlus1},
427 {"sqrt", {{"x", SameFloating}}, SameFloating},
428 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
429 SameNumeric, Rank::dimReduced},
430 {"tan", {{"x", SameFloating}}, SameFloating},
431 {"tanh", {{"x", SameFloating}}, SameFloating},
432 {"trailz", {{"i", AnyInt}}, DftInt},
433 // TODO: pmk: continue here with TRANSFER
peter klausler42b33da2018-09-29 00:02:11434 {"verify",
peter klauslera70f5962018-10-04 20:43:33435 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54436 {"back", AnyLogical, Rank::elemental, Optionality::optional},
437 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33438 KINDInt},
peter klausler42b33da2018-09-29 00:02:11439};
440
441// Not covered by the table above:
442// MAX, MIN, MERGE
443
444struct SpecificIntrinsicInterface : public IntrinsicInterface {
445 const char *generic{nullptr};
446};
447
peter klauslerb22d4942018-10-01 18:27:45448static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33449 {{"abs", {{"a", DftReal}}, DftReal}},
450 {{"acos", {{"x", DftReal}}, DftReal}},
451 {{"aimag", {{"z", DftComplex}}, DftReal}},
452 {{"aint", {{"a", DftReal}}, DftReal}},
453 {{"alog", {{"x", DftReal}}, DftReal}, "log"},
454 {{"alog10", {{"x", DftReal}}, DftReal}, "log10"},
455 {{"amod", {{"a", DftReal}, {"p", DftReal}}, DftReal}, "mod"},
456 {{"anint", {{"a", DftReal}}, DftReal}},
457 {{"asin", {{"x", DftReal}}, DftReal}},
458 {{"atan", {{"x", DftReal}}, DftReal}},
459 {{"atan2", {{"y", DftReal}, {"x", DftReal}}, DftReal}},
460 {{"cabs", {{"a", DftComplex}}, DftReal}, "abs"},
461 {{"ccos", {{"a", DftComplex}}, DftComplex}, "cos"},
462 {{"cexp", {{"a", DftComplex}}, DftComplex}, "exp"},
463 {{"clog", {{"a", DftComplex}}, DftComplex}, "log"},
464 {{"conjg", {{"a", DftComplex}}, DftComplex}},
465 {{"cos", {{"x", DftReal}}, DftReal}},
466 {{"csin", {{"a", DftComplex}}, DftComplex}, "sin"},
467 {{"csqrt", {{"a", DftComplex}}, DftComplex}, "sqrt"},
468 {{"ctan", {{"a", DftComplex}}, DftComplex}, "tan"},
469 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
470 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
471 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
472 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
473 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
474 DoublePrecision},
475 "atan2"},
476 {{"dble", {{"a", DftReal}, DefaultingKIND}, DoublePrecision}, "real"},
477 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
478 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
479 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
480 DoublePrecision},
481 "dim"},
482 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
483 {{"dim", {{"x", DftReal}, {"y", DftReal}}, DftReal}},
484 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
485 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
486 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
487 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
488 DoublePrecision},
489 "mod"},
490 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
491 {{"dprod", {{"x", DftReal}, {"y", DftReal}}, DoublePrecision}},
492 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
493 DoublePrecision},
494 "sign"},
495 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
496 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
497 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
498 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
499 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
500 {{"exp", {{"x", DftReal}}, DftReal}},
501 {{"float", {{"i", DftInt}}, DftReal}, "real"},
502 {{"iabs", {{"a", DftInt}}, DftInt}, "abs"},
503 {{"idim", {{"x", DftInt}, {"y", DftInt}}, DftInt}, "dim"},
504 {{"idint", {{"a", DoublePrecision}}, DftInt}, "int"},
505 {{"idnint", {{"a", DoublePrecision}}, DftInt}, "nint"},
506 {{"ifix", {{"a", DftReal}}, DftInt}, "int"},
507 {{"index", {{"string", DftChar}, {"substring", DftChar}}, DftInt}},
508 {{"isign", {{"a", DftInt}, {"b", DftInt}}, DftInt}, "sign"},
509 {{"len", {{"string", DftChar}}, DftInt}},
510 {{"log", {{"x", DftReal}}, DftReal}},
511 {{"log10", {{"x", DftReal}}, DftReal}},
512 {{"mod", {{"a", DftInt}, {"p", DftInt}}, DftInt}},
513 {{"nint", {{"a", DftReal}}, DftInt}},
514 {{"sign", {{"a", DftReal}, {"b", DftReal}}, DftReal}},
515 {{"sin", {{"x", DftReal}}, DftReal}},
516 {{"sinh", {{"x", DftReal}}, DftReal}},
517 {{"sngl", {{"a", DoublePrecision}}, DftReal}, "real"},
518 {{"sqrt", {{"x", DftReal}}, DftReal}},
519 {{"tan", {{"x", DftReal}}, DftReal}},
520 {{"tanh", {{"x", DftReal}}, DftReal}},
peter klausler42b33da2018-09-29 00:02:11521};
522
523// Some entries in the table above are "restricted" specifics:
524// DBLE, FLOAT, IDINT, IFIX, SNGL
525// Additional "restricted" specifics not covered by the table above:
526// AMAX0, AMAX1, AMIN0, AMIN1, DMAX1, DMIN1, MAX0, MAX1, MIN0, MIN1
527
peter klauslera70f5962018-10-04 20:43:33528// Intrinsic interface matching against the arguments of a particular
529// procedure reference.
peter klauslera70f5962018-10-04 20:43:33530std::optional<SpecificIntrinsic> IntrinsicInterface::Match(
peter klauslera62636f2018-10-08 22:35:19531 const CallCharacteristics &call, const IntrinsicTypeDefaultKinds &defaults,
peter klauslercb308d32018-10-05 18:32:54532 parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33533 // Attempt to construct a 1-1 correspondence between the dummy arguments in
534 // a particular intrinsic procedure's generic interface and the actual
535 // arguments in a procedure reference.
peter klauslera62636f2018-10-08 22:35:19536 const ActualArgument *actualForDummy[maxArguments];
peter klauslera70f5962018-10-04 20:43:33537 int dummies{0};
538 for (; dummies < maxArguments && dummy[dummies].keyword != nullptr;
539 ++dummies) {
540 actualForDummy[dummies] = nullptr;
541 }
peter klauslera62636f2018-10-08 22:35:19542 for (const ActualArgument &arg : call.argument) {
543 if (arg.isAlternateReturn) {
544 messages.Say(
545 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
546 call.name.ToString().data());
547 return std::nullopt;
548 }
peter klauslera70f5962018-10-04 20:43:33549 bool found{false};
550 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
551 if (actualForDummy[dummyArgIndex] == nullptr) {
552 if (!arg.keyword.has_value() ||
553 *arg.keyword == dummy[dummyArgIndex].keyword) {
554 actualForDummy[dummyArgIndex] = &arg;
555 found = true;
556 break;
557 }
558 }
559 if (!found) {
peter klauslercb308d32018-10-05 18:32:54560 if (arg.keyword.has_value()) {
561 messages.Say(*arg.keyword,
562 "unknown keyword argument to intrinsic '%'"_err_en_US,
563 call.name.ToString().data());
564 } else {
565 messages.Say("too many actual arguments"_err_en_US);
566 }
peter klauslera70f5962018-10-04 20:43:33567 return std::nullopt;
568 }
569 }
570 }
571
572 // Check types and kinds of the actual arguments against the intrinsic's
573 // interface. Ensure that two or more arguments that have to have the same
574 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19575 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33576 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19577 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33578 bool hasDimArg{false};
579 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
580 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
581 if (d.typePattern.kindCode == KindCode::kindArg) {
582 CHECK(kindDummyArg == nullptr);
583 kindDummyArg = &d;
584 }
peter klauslera62636f2018-10-08 22:35:19585 const ActualArgument *arg{actualForDummy[dummyArgIndex]};
peter klauslera70f5962018-10-04 20:43:33586 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54587 if (d.optionality == Optionality::required) {
588 messages.Say("missing '%s' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33589 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54590 } else {
591 continue;
peter klauslera70f5962018-10-04 20:43:33592 }
593 }
peter klauslera62636f2018-10-08 22:35:19594 std::optional<DynamicType> type{arg->GetType()};
595 if (!type.has_value()) {
596 CHECK(arg->Rank() == 0);
peter klauslercb308d32018-10-05 18:32:54597 if (d.typePattern.kindCode == KindCode::typeless ||
598 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33599 continue;
600 }
peter klauslercb308d32018-10-05 18:32:54601 messages.Say("typeless (BOZ) not allowed for '%s'"_err_en_US, d.keyword);
602 return std::nullopt;
peter klauslera62636f2018-10-08 22:35:19603 } else if (!d.typePattern.categorySet.test(type->category)) {
peter klauslercb308d32018-10-05 18:32:54604 messages.Say("actual argument for '%s' has bad type '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19605 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33606 return std::nullopt; // argument has invalid type category
607 }
608 bool argOk{false};
609 switch (d.typePattern.kindCode) {
610 case KindCode::none:
611 case KindCode::typeless:
612 case KindCode::teamType: // TODO: TEAM_TYPE
613 argOk = false;
614 break;
615 case KindCode::defaultIntegerKind:
peter klauslera62636f2018-10-08 22:35:19616 argOk = type->kind == defaults.defaultIntegerKind;
peter klauslera70f5962018-10-04 20:43:33617 break;
618 case KindCode::defaultRealKind:
peter klauslera62636f2018-10-08 22:35:19619 argOk = type->kind == defaults.defaultRealKind;
peter klauslera70f5962018-10-04 20:43:33620 break;
621 case KindCode::doublePrecision:
peter klauslera62636f2018-10-08 22:35:19622 argOk = type->kind == defaults.defaultDoublePrecisionKind;
peter klauslera70f5962018-10-04 20:43:33623 break;
624 case KindCode::defaultCharKind:
peter klauslera62636f2018-10-08 22:35:19625 argOk = type->kind == defaults.defaultCharacterKind;
peter klauslera70f5962018-10-04 20:43:33626 break;
627 case KindCode::defaultLogicalKind:
peter klauslera62636f2018-10-08 22:35:19628 argOk = type->kind == defaults.defaultLogicalKind;
peter klauslera70f5962018-10-04 20:43:33629 break;
630 case KindCode::any: argOk = true; break;
631 case KindCode::kindArg:
632 CHECK(kindArg == nullptr);
633 kindArg = arg;
634 argOk = arg->intValue.has_value();
635 break;
636 case KindCode::dimArg:
637 hasDimArg = true;
638 argOk = true;
639 break;
640 case KindCode::same:
641 if (sameArg == nullptr) {
642 sameArg = arg;
643 }
peter klauslera62636f2018-10-08 22:35:19644 argOk = *type == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33645 break;
646 case KindCode::effectiveKind:
647 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
648 "for intrinsic '%s'",
649 d.keyword, name);
650 break;
651 default: CRASH_NO_CASE;
652 }
653 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54654 messages.Say(
655 "actual argument for '%s' has bad type or kind '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19656 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33657 return std::nullopt;
658 }
659 }
660
661 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:19662 const ActualArgument *arrayArg{nullptr};
663 const ActualArgument *knownArg{nullptr};
664 const ActualArgument *shapeArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33665 int elementalRank{0};
666 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
667 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
peter klauslera62636f2018-10-08 22:35:19668 if (const ActualArgument * arg{actualForDummy[dummyArgIndex]}) {
peter klauslera70f5962018-10-04 20:43:33669 if (arg->isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
peter klauslercb308d32018-10-05 18:32:54670 messages.Say(
671 "assumed-rank array cannot be used for '%s' argument"_err_en_US,
672 d.keyword);
peter klauslera70f5962018-10-04 20:43:33673 return std::nullopt;
674 }
peter klauslera62636f2018-10-08 22:35:19675 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:33676 bool argOk{false};
677 switch (d.rank) {
678 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54679 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33680 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:19681 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:33682 }
peter klauslera62636f2018-10-08 22:35:19683 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:33684 break;
peter klauslera62636f2018-10-08 22:35:19685 case Rank::scalar: argOk = rank == 0; break;
686 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:33687 case Rank::shape:
688 CHECK(shapeArg == nullptr);
689 shapeArg = arg;
peter klauslera62636f2018-10-08 22:35:19690 argOk = rank == 1 && arg->vectorSize.has_value();
peter klauslera70f5962018-10-04 20:43:33691 break;
peter klauslera62636f2018-10-08 22:35:19692 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:33693 case Rank::array:
peter klauslera62636f2018-10-08 22:35:19694 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:33695 if (!arrayArg) {
696 arrayArg = arg;
697 } else {
peter klauslera62636f2018-10-08 22:35:19698 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33699 }
700 break;
701 case Rank::known:
702 CHECK(knownArg == nullptr);
703 knownArg = arg;
704 argOk = true;
705 break;
706 case Rank::anyOrAssumedRank: argOk = true; break;
707 case Rank::conformable:
708 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19709 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33710 break;
711 case Rank::dimRemoved:
712 CHECK(arrayArg != nullptr);
713 if (hasDimArg) {
peter klauslera62636f2018-10-08 22:35:19714 argOk = rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33715 } else {
peter klauslera62636f2018-10-08 22:35:19716 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:33717 }
718 break;
719 case Rank::dimReduced:
720 case Rank::rankPlus1:
721 case Rank::shaped:
722 common::die("INTERNAL: result-only rank code appears on argument '%s' "
723 "for intrinsic '%s'",
724 d.keyword, name);
725 default: CRASH_NO_CASE;
726 }
727 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54728 messages.Say("'%s' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19729 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:33730 return std::nullopt;
731 }
732 }
733 }
734
735 // At this point, the call is acceptable.
736 // Calculate the characteristics of the function result, if any
737 if (result.categorySet.empty()) {
738 CHECK(result.kindCode == KindCode::none);
739 return std::make_optional<SpecificIntrinsic>(name);
740 }
741 // Determine the result type.
742 DynamicType resultType{*result.categorySet.LeastElement(), 0};
743 switch (result.kindCode) {
744 case KindCode::defaultIntegerKind:
745 CHECK(result.categorySet == Int);
746 CHECK(resultType.category == TypeCategory::Integer);
747 resultType.kind = defaults.defaultIntegerKind;
748 break;
749 case KindCode::defaultRealKind:
750 CHECK(result.categorySet == CategorySet{resultType.category});
751 CHECK(Floating.test(resultType.category));
752 resultType.kind = defaults.defaultRealKind;
753 break;
754 case KindCode::doublePrecision:
755 CHECK(result.categorySet == Real);
756 CHECK(resultType.category == TypeCategory::Real);
757 resultType.kind = defaults.defaultDoublePrecisionKind;
758 break;
759 case KindCode::defaultCharKind:
760 CHECK(result.categorySet == Char);
761 CHECK(resultType.category == TypeCategory::Character);
762 resultType.kind = defaults.defaultCharacterKind;
763 break;
764 case KindCode::defaultLogicalKind:
765 CHECK(result.categorySet == Logical);
766 CHECK(resultType.category == TypeCategory::Logical);
767 resultType.kind = defaults.defaultLogicalKind;
768 break;
769 case KindCode::same:
770 CHECK(sameArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19771 resultType = *sameArg->GetType();
772 CHECK(result.categorySet.test(resultType.category));
peter klauslera70f5962018-10-04 20:43:33773 break;
774 case KindCode::effectiveKind:
775 CHECK(kindDummyArg != nullptr);
776 CHECK(result.categorySet == CategorySet{resultType.category});
777 if (kindArg != nullptr) {
778 CHECK(kindArg->intValue.has_value());
779 resultType.kind = *kindArg->intValue;
peter klauslera62636f2018-10-08 22:35:19780 // TODO pmk: validate this kind!!
peter klauslercb308d32018-10-05 18:32:54781 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
peter klauslera70f5962018-10-04 20:43:33782 CHECK(sameArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19783 resultType = *sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33784 } else {
peter klauslercb308d32018-10-05 18:32:54785 CHECK(
786 kindDummyArg->optionality == Optionality::defaultsToDefaultForResult);
peter klauslera70f5962018-10-04 20:43:33787 resultType.kind = defaults.DefaultKind(resultType.category);
788 }
789 break;
790 case KindCode::typeless:
791 case KindCode::teamType:
792 case KindCode::any:
793 case KindCode::kindArg:
794 case KindCode::dimArg:
795 common::die(
796 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
797 break;
798 default: CRASH_NO_CASE;
799 }
800
801 // Determine the rank of the function result.
802 int resultRank{0};
803 switch (rank) {
804 case Rank::elemental: resultRank = elementalRank; break;
805 case Rank::scalar: resultRank = 0; break;
806 case Rank::vector: resultRank = 1; break;
807 case Rank::matrix: resultRank = 2; break;
808 case Rank::dimReduced:
809 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19810 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:33811 break;
812 case Rank::rankPlus1:
813 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19814 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:33815 break;
816 case Rank::shaped:
817 CHECK(shapeArg != nullptr);
818 CHECK(shapeArg->vectorSize.has_value());
819 resultRank = *shapeArg->vectorSize;
820 break;
peter klauslercb308d32018-10-05 18:32:54821 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33822 case Rank::shape:
823 case Rank::array:
824 case Rank::known:
825 case Rank::anyOrAssumedRank:
826 case Rank::conformable:
827 case Rank::dimRemoved:
828 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
829 break;
830 default: CRASH_NO_CASE;
831 }
832 CHECK(resultRank >= 0);
833
834 return std::make_optional<SpecificIntrinsic>(
835 name, elementalRank > 0, resultType, resultRank);
836}
837
peter klauslera62636f2018-10-08 22:35:19838struct IntrinsicProcTable::Implementation {
839 explicit Implementation(const IntrinsicTypeDefaultKinds &dfts)
peter klauslera70f5962018-10-04 20:43:33840 : defaults{dfts} {
841 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
842 genericFuncs.insert(std::make_pair(std::string{f.name}, &f));
843 }
844 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
845 specificFuncs.insert(std::make_pair(std::string{f.name}, &f));
846 }
847 }
peter klausler42b33da2018-09-29 00:02:11848
peter klauslercb308d32018-10-05 18:32:54849 std::optional<SpecificIntrinsic> Probe(
850 const CallCharacteristics &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:53851
peter klauslera62636f2018-10-08 22:35:19852 IntrinsicTypeDefaultKinds defaults;
peter klauslera70f5962018-10-04 20:43:33853 std::multimap<std::string, const IntrinsicInterface *> genericFuncs;
854 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs;
peter klausler42b33da2018-09-29 00:02:11855};
856
peter klauslercb308d32018-10-05 18:32:54857// Probe the configured intrinsic procedure pattern tables in search of a
858// match for a given procedure reference.
peter klauslera62636f2018-10-08 22:35:19859std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
peter klauslercb308d32018-10-05 18:32:54860 const CallCharacteristics &call,
861 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:53862 if (call.isSubroutineCall) {
863 return std::nullopt; // TODO
864 }
peter klauslercb308d32018-10-05 18:32:54865 // A given intrinsic may have multiple patterns in the maps. If any of them
866 // succeeds, the buffered messages from previous failed pattern matches are
867 // discarded. Otherwise, all messages generated by the failing patterns are
868 // returned if the caller wants them.
869 parser::Messages buffer;
870 parser::ContextualMessages errors{
871 messages ? messages->at() : call.name, &buffer};
peter klausler75a32092018-10-05 16:57:53872 // Probe the specific intrinsic functions first.
873 std::string name{call.name.ToString()};
874 auto specificRange{specificFuncs.equal_range(name)};
875 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klauslercb308d32018-10-05 18:32:54876 if (auto specific{iter->second->Match(call, defaults, errors)}) {
peter klausler75a32092018-10-05 16:57:53877 specific->name = iter->second->generic;
878 return specific;
879 }
880 }
881 auto genericRange{specificFuncs.equal_range(name)};
882 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klauslercb308d32018-10-05 18:32:54883 if (auto specific{iter->second->Match(call, defaults, errors)}) {
peter klausler75a32092018-10-05 16:57:53884 return specific;
885 }
886 }
peter klauslercb308d32018-10-05 18:32:54887 CHECK(!buffer.empty());
888 if (messages != nullptr && messages->messages() != nullptr) {
889 messages->messages()->Annex(std::move(buffer));
890 }
peter klausler75a32092018-10-05 16:57:53891 return std::nullopt;
892}
893
peter klauslera62636f2018-10-08 22:35:19894IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:54895 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:11896 delete impl_;
897 impl_ = nullptr;
898}
899
peter klauslera62636f2018-10-08 22:35:19900IntrinsicProcTable IntrinsicProcTable::Configure(
901 const IntrinsicTypeDefaultKinds &defaults) {
902 IntrinsicProcTable result;
903 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:11904 return result;
905}
906
peter klauslera62636f2018-10-08 22:35:19907std::optional<SpecificIntrinsic> IntrinsicProcTable::Probe(
peter klauslercb308d32018-10-05 18:32:54908 const CallCharacteristics &call,
909 parser::ContextualMessages *messages) const {
peter klauslera62636f2018-10-08 22:35:19910 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klauslercb308d32018-10-05 18:32:54911 return impl_->Probe(call, messages);
peter klausler42b33da2018-09-29 00:02:11912}
913} // namespace Fortran::evaluate