blob: 93ce8bf984b13a434e1093e446ce1f8fd17635e4 [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"
16#include "type.h"
17#include "../common/enum-set.h"
18#include "../common/fortran.h"
peter klauslera70f5962018-10-04 20:43:3319#include "../common/idioms.h"
peter klausler42b33da2018-09-29 00:02:1120#include "../semantics/expression.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 klauslercb308d32018-10-05 18:32:54189 const semantics::IntrinsicTypeDefaultKinds &,
190 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(
531 const CallCharacteristics &call,
peter klauslercb308d32018-10-05 18:32:54532 const semantics::IntrinsicTypeDefaultKinds &defaults,
533 parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33534 // Attempt to construct a 1-1 correspondence between the dummy arguments in
535 // a particular intrinsic procedure's generic interface and the actual
536 // arguments in a procedure reference.
537 const ActualArgumentCharacteristics *actualForDummy[maxArguments];
538 int dummies{0};
539 for (; dummies < maxArguments && dummy[dummies].keyword != nullptr;
540 ++dummies) {
541 actualForDummy[dummies] = nullptr;
542 }
543 for (const ActualArgumentCharacteristics &arg : call.argument) {
544 bool found{false};
545 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
546 if (actualForDummy[dummyArgIndex] == nullptr) {
547 if (!arg.keyword.has_value() ||
548 *arg.keyword == dummy[dummyArgIndex].keyword) {
549 actualForDummy[dummyArgIndex] = &arg;
550 found = true;
551 break;
552 }
553 }
554 if (!found) {
peter klauslercb308d32018-10-05 18:32:54555 if (arg.keyword.has_value()) {
556 messages.Say(*arg.keyword,
557 "unknown keyword argument to intrinsic '%'"_err_en_US,
558 call.name.ToString().data());
559 } else {
560 messages.Say("too many actual arguments"_err_en_US);
561 }
peter klauslera70f5962018-10-04 20:43:33562 return std::nullopt;
563 }
564 }
565 }
566
567 // Check types and kinds of the actual arguments against the intrinsic's
568 // interface. Ensure that two or more arguments that have to have the same
569 // type and kind do so. Check for missing non-optional arguments now, too.
570 const ActualArgumentCharacteristics *sameArg{nullptr};
571 const IntrinsicDummyArgument *kindDummyArg{nullptr};
572 const ActualArgumentCharacteristics *kindArg{nullptr};
573 bool hasDimArg{false};
574 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
575 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
576 if (d.typePattern.kindCode == KindCode::kindArg) {
577 CHECK(kindDummyArg == nullptr);
578 kindDummyArg = &d;
579 }
580 const ActualArgumentCharacteristics *arg{actualForDummy[dummyArgIndex]};
581 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54582 if (d.optionality == Optionality::required) {
583 messages.Say("missing '%s' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33584 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54585 } else {
586 continue;
peter klauslera70f5962018-10-04 20:43:33587 }
588 }
589 if (arg->isBOZ) {
peter klauslercb308d32018-10-05 18:32:54590 CHECK(arg->rank == 0);
591 if (d.typePattern.kindCode == KindCode::typeless ||
592 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33593 continue;
594 }
peter klauslercb308d32018-10-05 18:32:54595 messages.Say("typeless (BOZ) not allowed for '%s'"_err_en_US, d.keyword);
596 return std::nullopt;
peter klauslera70f5962018-10-04 20:43:33597 } else if (!d.typePattern.categorySet.test(arg->type.category)) {
peter klauslercb308d32018-10-05 18:32:54598 messages.Say("actual argument for '%s' has bad type '%s'"_err_en_US,
599 d.keyword, arg->type.Dump().data());
peter klauslera70f5962018-10-04 20:43:33600 return std::nullopt; // argument has invalid type category
601 }
602 bool argOk{false};
603 switch (d.typePattern.kindCode) {
604 case KindCode::none:
605 case KindCode::typeless:
606 case KindCode::teamType: // TODO: TEAM_TYPE
607 argOk = false;
608 break;
609 case KindCode::defaultIntegerKind:
610 argOk = arg->type.kind == defaults.defaultIntegerKind;
611 break;
612 case KindCode::defaultRealKind:
613 argOk = arg->type.kind == defaults.defaultRealKind;
614 break;
615 case KindCode::doublePrecision:
616 argOk = arg->type.kind == defaults.defaultDoublePrecisionKind;
617 break;
618 case KindCode::defaultCharKind:
619 argOk = arg->type.kind == defaults.defaultCharacterKind;
620 break;
621 case KindCode::defaultLogicalKind:
622 argOk = arg->type.kind == defaults.defaultLogicalKind;
623 break;
624 case KindCode::any: argOk = true; break;
625 case KindCode::kindArg:
626 CHECK(kindArg == nullptr);
627 kindArg = arg;
628 argOk = arg->intValue.has_value();
629 break;
630 case KindCode::dimArg:
631 hasDimArg = true;
632 argOk = true;
633 break;
634 case KindCode::same:
635 if (sameArg == nullptr) {
636 sameArg = arg;
637 }
638 argOk = arg->type == sameArg->type;
639 break;
640 case KindCode::effectiveKind:
641 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
642 "for intrinsic '%s'",
643 d.keyword, name);
644 break;
645 default: CRASH_NO_CASE;
646 }
647 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54648 messages.Say(
649 "actual argument for '%s' has bad type or kind '%s'"_err_en_US,
650 d.keyword, arg->type.Dump().data());
peter klauslera70f5962018-10-04 20:43:33651 return std::nullopt;
652 }
653 }
654
655 // Check the ranks of the arguments against the intrinsic's interface.
656 const ActualArgumentCharacteristics *arrayArg{nullptr};
657 const ActualArgumentCharacteristics *knownArg{nullptr};
658 const ActualArgumentCharacteristics *shapeArg{nullptr};
659 int elementalRank{0};
660 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
661 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
662 if (const ActualArgumentCharacteristics *
663 arg{actualForDummy[dummyArgIndex]}) {
664 if (arg->isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
peter klauslercb308d32018-10-05 18:32:54665 messages.Say(
666 "assumed-rank array cannot be used for '%s' argument"_err_en_US,
667 d.keyword);
peter klauslera70f5962018-10-04 20:43:33668 return std::nullopt;
669 }
670 bool argOk{false};
671 switch (d.rank) {
672 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54673 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33674 if (elementalRank == 0) {
675 elementalRank = arg->rank;
676 }
677 argOk = arg->rank == 0 || arg->rank == elementalRank;
678 break;
679 case Rank::scalar: argOk = arg->rank == 0; break;
680 case Rank::vector: argOk = arg->rank == 1; break;
681 case Rank::shape:
682 CHECK(shapeArg == nullptr);
683 shapeArg = arg;
684 argOk = arg->rank == 1 && arg->vectorSize.has_value();
685 break;
686 case Rank::matrix: argOk = arg->rank == 2; break;
687 case Rank::array:
688 argOk = arg->rank > 0;
689 if (!arrayArg) {
690 arrayArg = arg;
691 } else {
692 argOk &= arg->rank == arrayArg->rank;
693 }
694 break;
695 case Rank::known:
696 CHECK(knownArg == nullptr);
697 knownArg = arg;
698 argOk = true;
699 break;
700 case Rank::anyOrAssumedRank: argOk = true; break;
701 case Rank::conformable:
702 CHECK(arrayArg != nullptr);
703 argOk = arg->rank == 0 || arg->rank == arrayArg->rank;
704 break;
705 case Rank::dimRemoved:
706 CHECK(arrayArg != nullptr);
707 if (hasDimArg) {
708 argOk = arg->rank + 1 == arrayArg->rank;
709 } else {
710 argOk = arg->rank == 0;
711 }
712 break;
713 case Rank::dimReduced:
714 case Rank::rankPlus1:
715 case Rank::shaped:
716 common::die("INTERNAL: result-only rank code appears on argument '%s' "
717 "for intrinsic '%s'",
718 d.keyword, name);
719 default: CRASH_NO_CASE;
720 }
721 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54722 messages.Say("'%s' argument has unacceptable rank %d"_err_en_US,
723 d.keyword, arg->rank);
peter klauslera70f5962018-10-04 20:43:33724 return std::nullopt;
725 }
726 }
727 }
728
729 // At this point, the call is acceptable.
730 // Calculate the characteristics of the function result, if any
731 if (result.categorySet.empty()) {
732 CHECK(result.kindCode == KindCode::none);
733 return std::make_optional<SpecificIntrinsic>(name);
734 }
735 // Determine the result type.
736 DynamicType resultType{*result.categorySet.LeastElement(), 0};
737 switch (result.kindCode) {
738 case KindCode::defaultIntegerKind:
739 CHECK(result.categorySet == Int);
740 CHECK(resultType.category == TypeCategory::Integer);
741 resultType.kind = defaults.defaultIntegerKind;
742 break;
743 case KindCode::defaultRealKind:
744 CHECK(result.categorySet == CategorySet{resultType.category});
745 CHECK(Floating.test(resultType.category));
746 resultType.kind = defaults.defaultRealKind;
747 break;
748 case KindCode::doublePrecision:
749 CHECK(result.categorySet == Real);
750 CHECK(resultType.category == TypeCategory::Real);
751 resultType.kind = defaults.defaultDoublePrecisionKind;
752 break;
753 case KindCode::defaultCharKind:
754 CHECK(result.categorySet == Char);
755 CHECK(resultType.category == TypeCategory::Character);
756 resultType.kind = defaults.defaultCharacterKind;
757 break;
758 case KindCode::defaultLogicalKind:
759 CHECK(result.categorySet == Logical);
760 CHECK(resultType.category == TypeCategory::Logical);
761 resultType.kind = defaults.defaultLogicalKind;
762 break;
763 case KindCode::same:
764 CHECK(sameArg != nullptr);
765 CHECK(result.categorySet.test(sameArg->type.category));
766 resultType = sameArg->type;
767 break;
768 case KindCode::effectiveKind:
769 CHECK(kindDummyArg != nullptr);
770 CHECK(result.categorySet == CategorySet{resultType.category});
771 if (kindArg != nullptr) {
772 CHECK(kindArg->intValue.has_value());
773 resultType.kind = *kindArg->intValue;
774 // TODO pmk: validate the kind!!
peter klauslercb308d32018-10-05 18:32:54775 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
peter klauslera70f5962018-10-04 20:43:33776 CHECK(sameArg != nullptr);
777 resultType = sameArg->type;
778 } else {
peter klauslercb308d32018-10-05 18:32:54779 CHECK(
780 kindDummyArg->optionality == Optionality::defaultsToDefaultForResult);
peter klauslera70f5962018-10-04 20:43:33781 resultType.kind = defaults.DefaultKind(resultType.category);
782 }
783 break;
784 case KindCode::typeless:
785 case KindCode::teamType:
786 case KindCode::any:
787 case KindCode::kindArg:
788 case KindCode::dimArg:
789 common::die(
790 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
791 break;
792 default: CRASH_NO_CASE;
793 }
794
795 // Determine the rank of the function result.
796 int resultRank{0};
797 switch (rank) {
798 case Rank::elemental: resultRank = elementalRank; break;
799 case Rank::scalar: resultRank = 0; break;
800 case Rank::vector: resultRank = 1; break;
801 case Rank::matrix: resultRank = 2; break;
802 case Rank::dimReduced:
803 CHECK(arrayArg != nullptr);
804 resultRank = hasDimArg ? arrayArg->rank - 1 : 0;
805 break;
806 case Rank::rankPlus1:
807 CHECK(knownArg != nullptr);
808 resultRank = knownArg->rank + 1;
809 break;
810 case Rank::shaped:
811 CHECK(shapeArg != nullptr);
812 CHECK(shapeArg->vectorSize.has_value());
813 resultRank = *shapeArg->vectorSize;
814 break;
peter klauslercb308d32018-10-05 18:32:54815 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33816 case Rank::shape:
817 case Rank::array:
818 case Rank::known:
819 case Rank::anyOrAssumedRank:
820 case Rank::conformable:
821 case Rank::dimRemoved:
822 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
823 break;
824 default: CRASH_NO_CASE;
825 }
826 CHECK(resultRank >= 0);
827
828 return std::make_optional<SpecificIntrinsic>(
829 name, elementalRank > 0, resultType, resultRank);
830}
831
peter klausler42b33da2018-09-29 00:02:11832struct IntrinsicTable::Implementation {
833 explicit Implementation(const semantics::IntrinsicTypeDefaultKinds &dfts)
peter klauslera70f5962018-10-04 20:43:33834 : defaults{dfts} {
835 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
836 genericFuncs.insert(std::make_pair(std::string{f.name}, &f));
837 }
838 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
839 specificFuncs.insert(std::make_pair(std::string{f.name}, &f));
840 }
841 }
peter klausler42b33da2018-09-29 00:02:11842
peter klauslercb308d32018-10-05 18:32:54843 std::optional<SpecificIntrinsic> Probe(
844 const CallCharacteristics &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:53845
peter klausler42b33da2018-09-29 00:02:11846 semantics::IntrinsicTypeDefaultKinds defaults;
peter klauslera70f5962018-10-04 20:43:33847 std::multimap<std::string, const IntrinsicInterface *> genericFuncs;
848 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs;
peter klausler42b33da2018-09-29 00:02:11849};
850
peter klauslercb308d32018-10-05 18:32:54851// Probe the configured intrinsic procedure pattern tables in search of a
852// match for a given procedure reference.
peter klausler75a32092018-10-05 16:57:53853std::optional<SpecificIntrinsic> IntrinsicTable::Implementation::Probe(
peter klauslercb308d32018-10-05 18:32:54854 const CallCharacteristics &call,
855 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:53856 if (call.isSubroutineCall) {
857 return std::nullopt; // TODO
858 }
peter klauslercb308d32018-10-05 18:32:54859 // A given intrinsic may have multiple patterns in the maps. If any of them
860 // succeeds, the buffered messages from previous failed pattern matches are
861 // discarded. Otherwise, all messages generated by the failing patterns are
862 // returned if the caller wants them.
863 parser::Messages buffer;
864 parser::ContextualMessages errors{
865 messages ? messages->at() : call.name, &buffer};
peter klausler75a32092018-10-05 16:57:53866 // Probe the specific intrinsic functions first.
867 std::string name{call.name.ToString()};
868 auto specificRange{specificFuncs.equal_range(name)};
869 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klauslercb308d32018-10-05 18:32:54870 if (auto specific{iter->second->Match(call, defaults, errors)}) {
peter klausler75a32092018-10-05 16:57:53871 specific->name = iter->second->generic;
872 return specific;
873 }
874 }
875 auto genericRange{specificFuncs.equal_range(name)};
876 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klauslercb308d32018-10-05 18:32:54877 if (auto specific{iter->second->Match(call, defaults, errors)}) {
peter klausler75a32092018-10-05 16:57:53878 return specific;
879 }
880 }
peter klauslercb308d32018-10-05 18:32:54881 CHECK(!buffer.empty());
882 if (messages != nullptr && messages->messages() != nullptr) {
883 messages->messages()->Annex(std::move(buffer));
884 }
peter klausler75a32092018-10-05 16:57:53885 return std::nullopt;
886}
887
peter klausler42b33da2018-09-29 00:02:11888IntrinsicTable::~IntrinsicTable() {
peter klauslercb308d32018-10-05 18:32:54889 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:11890 delete impl_;
891 impl_ = nullptr;
892}
893
894IntrinsicTable IntrinsicTable::Configure(
895 const semantics::IntrinsicTypeDefaultKinds &defaults) {
896 IntrinsicTable result;
897 result.impl_ = new IntrinsicTable::Implementation(defaults);
898 return result;
899}
900
peter klauslera70f5962018-10-04 20:43:33901std::optional<SpecificIntrinsic> IntrinsicTable::Probe(
peter klauslercb308d32018-10-05 18:32:54902 const CallCharacteristics &call,
903 parser::ContextualMessages *messages) const {
peter klauslera70f5962018-10-04 20:43:33904 CHECK(impl_ != nullptr || !"IntrinsicTable: not configured");
peter klauslercb308d32018-10-05 18:32:54905 return impl_->Probe(call, messages);
peter klausler42b33da2018-09-29 00:02:11906}
907} // namespace Fortran::evaluate