blob: 3216f530ad29b1be0fee9239e6f0f8320c600aa2 [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>
peter klausler7bda1b32018-10-12 23:01:5522#include <ostream>
23#include <sstream>
peter klauslera70f5962018-10-04 20:43:3324#include <string>
25#include <utility>
peter klausler42b33da2018-09-29 00:02:1126
peter klauslercb308d32018-10-05 18:32:5427using namespace Fortran::parser::literals;
28
peter klausler42b33da2018-09-29 00:02:1129namespace Fortran::evaluate {
30
31using common::TypeCategory;
32
peter klauslera70f5962018-10-04 20:43:3333// This file defines the supported intrinsic procedures and implements
34// their recognition and validation. It is largely table-driven. See
35// documentation/intrinsics.md and section 16 of the Fortran 2018 standard
36// for full details on each of the intrinsics. Be advised, they have
37// complicated details, and the design of these tables has to accommodate
38// that complexity.
39
peter klausler42b33da2018-09-29 00:02:1140// Dummy arguments to generic intrinsic procedures are each specified by
peter klauslera70f5962018-10-04 20:43:3341// their keyword name (rarely used, but always defined), allowable type
peter klauslercb308d32018-10-05 18:32:5442// categories, a kind pattern, a rank pattern, and information about
43// optionality and defaults. The kind and rank patterns are represented
44// here with code values that are significant to the matching/validation engine.
peter klausler42b33da2018-09-29 00:02:1145
peter klauslera70f5962018-10-04 20:43:3346// These are small bit-sets of type category enumerators.
47// Note that typeless (BOZ literal) values don't have a distinct type category.
48// These typeless arguments are represented in the tables as if they were
49// INTEGER with a special "typeless" kind code. Arguments of intrinsic types
peter klauslercb308d32018-10-05 18:32:5450// that can also be be typeless values are encoded with an "elementalOrBOZ"
51// rank pattern.
peter klauslera70f5962018-10-04 20:43:3352using CategorySet = common::EnumSet<TypeCategory, 8>;
peter klausler51b09b62018-10-15 19:17:3053static constexpr CategorySet IntType{TypeCategory::Integer};
54static constexpr CategorySet RealType{TypeCategory::Real};
55static constexpr CategorySet ComplexType{TypeCategory::Complex};
56static constexpr CategorySet CharType{TypeCategory::Character};
57static constexpr CategorySet LogicalType{TypeCategory::Logical};
58static constexpr CategorySet IntOrRealType{IntType | RealType};
59static constexpr CategorySet FloatingType{RealType | ComplexType};
60static constexpr CategorySet NumericType{IntType | RealType | ComplexType};
61static constexpr CategorySet RelatableType{IntType | RealType | CharType};
peter klauslera70f5962018-10-04 20:43:3362static constexpr CategorySet IntrinsicType{
peter klausler51b09b62018-10-15 19:17:3063 IntType | RealType | ComplexType | CharType | LogicalType};
peter klauslera70f5962018-10-04 20:43:3364static constexpr CategorySet AnyType{
65 IntrinsicType | CategorySet{TypeCategory::Derived}};
peter klausler42b33da2018-09-29 00:02:1166
peter klausler7bda1b32018-10-12 23:01:5567ENUM_CLASS(KindCode, none, defaultIntegerKind,
68 defaultRealKind, // is also the default COMPLEX kind
69 doublePrecision, defaultCharKind, defaultLogicalKind,
70 any, // matches any kind value; each instance is independent
71 typeless, // BOZ literals are INTEGER with this kind
72 teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
73 kindArg, // this argument is KIND=
74 effectiveKind, // for function results: same "kindArg", possibly defaulted
75 dimArg, // this argument is DIM=
76 same, // match any kind; all "same" kinds must be equal
77 likeMultiply, // for DOT_PRODUCT and MATMUL
78)
peter klausler42b33da2018-09-29 00:02:1179
80struct TypePattern {
81 CategorySet categorySet;
peter klauslerb22d4942018-10-01 18:27:4582 KindCode kindCode{KindCode::none};
peter klausler7bda1b32018-10-12 23:01:5583 std::ostream &Dump(std::ostream &) const;
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
peter klausler51b09b62018-10-15 19:17:3089static constexpr TypePattern DftInt{IntType, KindCode::defaultIntegerKind};
90static constexpr TypePattern DftReal{RealType, KindCode::defaultRealKind};
91static constexpr TypePattern DftComplex{ComplexType, KindCode::defaultRealKind};
92static constexpr TypePattern DftChar{CharType, KindCode::defaultCharKind};
93static constexpr TypePattern DftLogical{
94 LogicalType, KindCode::defaultLogicalKind};
95static constexpr TypePattern BOZ{IntType, KindCode::typeless};
96static constexpr TypePattern TEAM_TYPE{IntType, KindCode::teamType};
97static constexpr TypePattern DoublePrecision{
98 RealType, KindCode::doublePrecision};
peter klauslera70f5962018-10-04 20:43:3399
100// Match any kind of some intrinsic or derived types
peter klausler51b09b62018-10-15 19:17:30101static constexpr TypePattern AnyInt{IntType, KindCode::any};
102static constexpr TypePattern AnyReal{RealType, KindCode::any};
103static constexpr TypePattern AnyIntOrReal{IntOrRealType, KindCode::any};
104static constexpr TypePattern AnyComplex{ComplexType, KindCode::any};
105static constexpr TypePattern AnyNumeric{NumericType, KindCode::any};
106static constexpr TypePattern AnyChar{CharType, KindCode::any};
107static constexpr TypePattern AnyLogical{LogicalType, KindCode::any};
108static constexpr TypePattern AnyRelatable{RelatableType, KindCode::any};
peter klauslerf7f2a732018-10-09 19:07:29109static constexpr TypePattern Anything{AnyType, KindCode::any};
peter klauslera70f5962018-10-04 20:43:33110
111// Match some kind of some intrinsic type(s); all "Same" values must match,
112// even when not in the same category (e.g., SameComplex and SameReal).
113// Can be used to specify a result so long as at least one argument is
114// a "Same".
peter klausler51b09b62018-10-15 19:17:30115static constexpr TypePattern SameInt{IntType, KindCode::same};
116static constexpr TypePattern SameReal{RealType, KindCode::same};
117static constexpr TypePattern SameIntOrReal{IntOrRealType, KindCode::same};
118static constexpr TypePattern SameComplex{ComplexType, KindCode::same};
119static constexpr TypePattern SameFloating{FloatingType, KindCode::same};
120static constexpr TypePattern SameNumeric{NumericType, KindCode::same};
121static constexpr TypePattern SameChar{CharType, KindCode::same};
122static constexpr TypePattern SameLogical{LogicalType, KindCode::same};
123static constexpr TypePattern SameRelatable{RelatableType, KindCode::same};
peter klauslera70f5962018-10-04 20:43:33124static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
125static constexpr TypePattern SameDerivedType{
126 CategorySet{TypeCategory::Derived}, KindCode::same};
127static constexpr TypePattern SameType{AnyType, KindCode::same};
128
peter klauslerf7f2a732018-10-09 19:07:29129// For DOT_PRODUCT and MATMUL, the result type depends on the arguments
peter klausler51b09b62018-10-15 19:17:30130static constexpr TypePattern ResultLogical{LogicalType, KindCode::likeMultiply};
131static constexpr TypePattern ResultNumeric{NumericType, KindCode::likeMultiply};
peter klauslerf7f2a732018-10-09 19:07:29132
peter klauslera70f5962018-10-04 20:43:33133// Result types with known category and KIND=
peter klausler51b09b62018-10-15 19:17:30134static constexpr TypePattern KINDInt{IntType, KindCode::effectiveKind};
135static constexpr TypePattern KINDReal{RealType, KindCode::effectiveKind};
136static constexpr TypePattern KINDComplex{ComplexType, KindCode::effectiveKind};
137static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind};
138static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11139
140// The default rank pattern for dummy arguments and function results is
141// "elemental".
peter klausler7bda1b32018-10-12 23:01:55142ENUM_CLASS(Rank,
143 elemental, // scalar, or array that conforms with other array arguments
144 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
145 scalar, vector,
146 shape, // INTEGER vector of known length and no negative element
147 matrix,
148 array, // not scalar, rank is known and greater than zero
149 known, // rank is known and can be scalar
150 anyOrAssumedRank, // rank can be unknown
151 conformable, // scalar, or array of same rank & shape as "array" argument
152 reduceOperation, // a pure function with constraints for REDUCE
153 dimReduced, // scalar if no DIM= argument, else rank(array)-1
154 dimRemoved, // scalar, or rank(array)-1
155 rankPlus1, // rank(known)+1
156 shaped, // rank is length of SHAPE vector
157)
peter klausler42b33da2018-09-29 00:02:11158
peter klausler7bda1b32018-10-12 23:01:55159ENUM_CLASS(Optionality, required, optional,
160 defaultsToSameKind, // for MatchingDefaultKIND
161 defaultsToDefaultForResult, // for DefaultingKIND
162 repeats, // for MAX/MIN and their several variants
163)
peter klausler42b33da2018-09-29 00:02:11164
165struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45166 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11167 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33168 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54169 Optionality optionality{Optionality::required};
peter klausler7bda1b32018-10-12 23:01:55170 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11171};
172
peter klauslera70f5962018-10-04 20:43:33173// constexpr abbreviations for popular arguments:
174// DefaultingKIND is a KIND= argument whose default value is the appropriate
175// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54176static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30177 {IntType, KindCode::kindArg}, Rank::scalar,
peter klauslercb308d32018-10-05 18:32:54178 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33179// MatchingDefaultKIND is a KIND= argument whose default value is the
180// kind of any "Same" function argument (viz., the one whose kind pattern is
181// "same").
peter klauslercb308d32018-10-05 18:32:54182static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30183 {IntType, KindCode::kindArg}, Rank::scalar,
184 Optionality::defaultsToSameKind};
peter klauslera70f5962018-10-04 20:43:33185static constexpr IntrinsicDummyArgument OptionalDIM{
peter klausler51b09b62018-10-15 19:17:30186 "dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33187static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54188 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11189
190struct IntrinsicInterface {
191 static constexpr int maxArguments{7};
peter klauslerb22d4942018-10-01 18:27:45192 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11193 IntrinsicDummyArgument dummy[maxArguments];
194 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33195 Rank rank{Rank::elemental};
196 std::optional<SpecificIntrinsic> Match(const CallCharacteristics &,
peter klauslera62636f2018-10-08 22:35:19197 const IntrinsicTypeDefaultKinds &,
peter klauslercb308d32018-10-05 18:32:54198 parser::ContextualMessages &messages) const;
peter klausler7bda1b32018-10-12 23:01:55199 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11200};
201
peter klausler94041d72018-10-15 20:39:51202// GENERIC INTRINSIC FUNCTION INTERFACES
203// Each entry in this table defines a pattern. Some intrinsic
204// functions have more than one such pattern. Besides the name
205// of the intrinsic function, each pattern has specifications for
206// the dummy arguments and for the result of the function.
207// The dummy argument patterns each have a name (this are from the
208// standard, but rarely appear in actual code), a type and kind
209// pattern, allowable ranks, and optionality indicators.
210// Be advised, the default rank pattern is "elemental".
peter klauslerb22d4942018-10-01 18:27:45211static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33212 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
213 {"abs", {{"a", SameComplex}}, SameReal},
peter klauslerad9aede2018-10-11 21:51:14214 {"achar", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
peter klauslera70f5962018-10-04 20:43:33215 {"acos", {{"x", SameFloating}}, SameFloating},
216 {"acosh", {{"x", SameFloating}}, SameFloating},
217 {"adjustl", {{"string", SameChar}}, SameChar},
218 {"adjustr", {{"string", SameChar}}, SameChar},
219 {"aimag", {{"x", SameComplex}}, SameReal},
220 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
221 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
222 Rank::dimReduced},
223 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
224 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
225 Rank::dimReduced},
226 {"asin", {{"x", SameFloating}}, SameFloating},
227 {"asinh", {{"x", SameFloating}}, SameFloating},
228 {"atan", {{"x", SameFloating}}, SameFloating},
229 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
230 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
231 {"atanh", {{"x", SameFloating}}, SameFloating},
232 {"bessel_j0", {{"x", SameReal}}, SameReal},
233 {"bessel_j1", {{"x", SameReal}}, SameReal},
234 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29235 {"bessel_jn",
236 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
237 {"x", SameReal, Rank::scalar}},
238 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33239 {"bessel_y0", {{"x", SameReal}}, SameReal},
240 {"bessel_y1", {{"x", SameReal}}, SameReal},
241 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29242 {"bessel_yn",
243 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
244 {"x", SameReal, Rank::scalar}},
245 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33246 {"bge",
peter klauslercb308d32018-10-05 18:32:54247 {{"i", AnyInt, Rank::elementalOrBOZ},
248 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33249 DftLogical},
250 {"bgt",
peter klauslercb308d32018-10-05 18:32:54251 {{"i", AnyInt, Rank::elementalOrBOZ},
252 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33253 DftLogical},
254 {"ble",
peter klauslercb308d32018-10-05 18:32:54255 {{"i", AnyInt, Rank::elementalOrBOZ},
256 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33257 DftLogical},
258 {"blt",
peter klauslercb308d32018-10-05 18:32:54259 {{"i", AnyInt, Rank::elementalOrBOZ},
260 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33261 DftLogical},
262 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DftLogical},
263 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
264 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
265 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11266 {"cmplx",
peter klauslercb308d32018-10-05 18:32:54267 {{"x", SameIntOrReal, Rank::elementalOrBOZ},
268 {"y", SameIntOrReal, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33269 KINDComplex},
peter klauslerf7f2a732018-10-09 19:07:29270 {"command_argument_count", {}, DftInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33271 {"conjg", {{"z", SameComplex}}, SameComplex},
272 {"cos", {{"x", SameFloating}}, SameFloating},
273 {"cosh", {{"x", SameFloating}}, SameFloating},
274 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
275 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11276 {"cshift",
peter klauslera70f5962018-10-04 20:43:33277 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
278 OptionalDIM},
279 SameType, Rank::array},
280 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
peter klauslerf7f2a732018-10-09 19:07:29281 {"dot_product",
282 {{"vector_a", AnyLogical, Rank::vector},
283 {"vector_b", AnyLogical, Rank::vector}},
284 ResultLogical, Rank::scalar},
285 {"dot_product",
286 {{"vector_a", AnyComplex, Rank::vector},
287 {"vector_b", AnyNumeric, Rank::vector}},
288 ResultNumeric, Rank::scalar}, // conjugates vector_a
289 {"dot_product",
290 {{"vector_a", AnyIntOrReal, Rank::vector},
291 {"vector_b", AnyNumeric, Rank::vector}},
292 ResultNumeric, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33293 {"dprod", {{"x", DftReal}, {"y", DftReal}}, DoublePrecision},
294 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54295 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33296 {"shift", AnyInt}},
297 SameInt},
298 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
299 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54300 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33301 {"shift", AnyInt}},
302 SameInt},
303 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11304 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33305 {{"array", SameIntrinsic, Rank::array},
306 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54307 {"boundary", SameIntrinsic, Rank::dimRemoved,
308 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33309 OptionalDIM},
310 SameIntrinsic, Rank::array},
peter klausler42b33da2018-09-29 00:02:11311 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33312 {{"array", SameDerivedType, Rank::array},
313 {"shift", AnyInt, Rank::dimRemoved},
314 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
315 SameDerivedType, Rank::array},
316 {"erf", {{"x", SameReal}}, SameReal},
317 {"erfc", {{"x", SameReal}}, SameReal},
318 {"erfc_scaled", {{"x", SameReal}}, SameReal},
319 {"exp", {{"x", SameFloating}}, SameFloating},
320 {"exponent", {{"x", AnyReal}}, DftInt},
peter klausler42b33da2018-09-29 00:02:11321 {"findloc",
peter klauslerad9aede2018-10-11 21:51:14322 {{"array", AnyNumeric, Rank::array},
323 {"value", AnyNumeric, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54324 DefaultingKIND,
325 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33326 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11327 {"findloc",
peter klauslera70f5962018-10-04 20:43:33328 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
329 OptionalDIM, OptionalMASK, DefaultingKIND,
peter klauslercb308d32018-10-05 18:32:54330 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33331 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11332 {"findloc",
peter klauslera70f5962018-10-04 20:43:33333 {{"array", AnyLogical, Rank::array},
334 {"value", AnyLogical, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54335 DefaultingKIND,
336 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33337 KINDInt, Rank::dimReduced},
338 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
339 {"fraction", {{"x", SameReal}}, SameReal},
340 {"gamma", {{"x", SameReal}}, SameReal},
341 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
342 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
343 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
344 SameInt, Rank::dimReduced},
345 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
346 SameInt, Rank::dimReduced},
347 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
348 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54349 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33350 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
351 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
352 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
353 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
354 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54355 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33356 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
357 {"image_status",
peter klauslercb308d32018-10-05 18:32:54358 {{"image", SameInt},
359 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33360 DftInt},
peter klausler42b33da2018-09-29 00:02:11361 {"index",
peter klauslera70f5962018-10-04 20:43:33362 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54363 {"back", AnyLogical, Rank::scalar, Optionality::optional},
364 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33365 KINDInt},
peter klauslercb308d32018-10-05 18:32:54366 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
367 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33368 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
369 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
370 {"ishftc",
371 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54372 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33373 SameInt},
374 {"is_iostat_end", {{"i", AnyInt}}, DftLogical},
375 {"is_iostat_eor", {{"i", AnyInt}}, DftLogical},
peter klauslerf7f2a732018-10-09 19:07:29376 {"lbound", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
377 KINDInt, Rank::vector},
378 {"lbound",
379 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler51b09b62018-10-15 19:17:30380 {"dim", {IntType, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
peter klauslerf7f2a732018-10-09 19:07:29381 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33382 {"leadz", {{"i", AnyInt}}, DftInt},
383 {"len", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
384 {"len_trim", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
385 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
386 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
387 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
388 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
389 {"log", {{"x", SameFloating}}, SameFloating},
390 {"log10", {{"x", SameReal}}, SameReal},
391 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
392 {"log_gamma", {{"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29393 {"matmul",
394 {{"array_a", AnyLogical, Rank::vector},
395 {"array_b", AnyLogical, Rank::matrix}},
396 ResultLogical, Rank::vector},
397 {"matmul",
398 {{"array_a", AnyLogical, Rank::matrix},
399 {"array_b", AnyLogical, Rank::vector}},
400 ResultLogical, Rank::vector},
401 {"matmul",
402 {{"array_a", AnyLogical, Rank::matrix},
403 {"array_b", AnyLogical, Rank::matrix}},
404 ResultLogical, Rank::matrix},
405 {"matmul",
406 {{"array_a", AnyNumeric, Rank::vector},
407 {"array_b", AnyNumeric, Rank::matrix}},
408 ResultNumeric, Rank::vector},
409 {"matmul",
410 {{"array_a", AnyNumeric, Rank::matrix},
411 {"array_b", AnyNumeric, Rank::vector}},
412 ResultNumeric, Rank::vector},
413 {"matmul",
414 {{"array_a", AnyNumeric, Rank::matrix},
415 {"array_b", AnyNumeric, Rank::matrix}},
416 ResultNumeric, Rank::matrix},
peter klauslera70f5962018-10-04 20:43:33417 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
418 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klauslerad9aede2018-10-11 21:51:14419 {"max",
420 {{"a1", SameRelatable}, {"a2", SameRelatable},
421 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
422 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11423 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33424 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54425 DefaultingKIND,
426 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33427 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11428 {"maxval",
peter klauslera70f5962018-10-04 20:43:33429 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
430 SameRelatable, Rank::dimReduced},
peter klauslerad9aede2018-10-11 21:51:14431 {"merge",
432 {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
433 SameType},
peter klausler42b33da2018-09-29 00:02:11434 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54435 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
436 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33437 SameInt},
438 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54439 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33440 SameInt},
peter klauslerad9aede2018-10-11 21:51:14441 {"min",
442 {{"a1", SameRelatable}, {"a2", SameRelatable},
443 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
444 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11445 {"minloc",
peter klauslera70f5962018-10-04 20:43:33446 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54447 DefaultingKIND,
448 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33449 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11450 {"minval",
peter klauslera70f5962018-10-04 20:43:33451 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
452 SameRelatable, Rank::dimReduced},
453 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
454 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
455 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
456 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
457 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
458 Rank::dimReduced},
459 {"not", {{"i", SameInt}}, SameInt},
peter klausler8efb8972018-10-10 17:48:12460 // NULL() is a special case handled in Probe() below
peter klausler42b33da2018-09-29 00:02:11461 {"out_of_range",
peter klauslerad9aede2018-10-11 21:51:14462 {{"x", AnyIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
peter klauslera70f5962018-10-04 20:43:33463 DftLogical},
464 {"out_of_range",
465 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54466 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33467 DftLogical},
468 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DftLogical},
peter klausler42b33da2018-09-29 00:02:11469 {"pack",
peter klauslera70f5962018-10-04 20:43:33470 {{"array", SameType, Rank::array},
471 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54472 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33473 SameType, Rank::vector},
474 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
475 Rank::dimReduced},
476 {"popcnt", {{"i", AnyInt}}, DftInt},
477 {"poppar", {{"i", AnyInt}}, DftInt},
peter klausler42b33da2018-09-29 00:02:11478 {"product",
peter klauslera70f5962018-10-04 20:43:33479 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
480 SameNumeric, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54481 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33482 KINDReal},
peter klauslerad9aede2018-10-11 21:51:14483 {"reduce",
484 {{"array", SameType, Rank::array},
485 {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
486 OptionalMASK, {"identity", SameType, Rank::scalar},
487 {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
488 SameType, Rank::dimReduced},
peter klausler24379cc2018-10-10 23:45:17489 {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
490 SameChar, Rank::scalar},
peter klausler42b33da2018-09-29 00:02:11491 {"reshape",
peter klauslera70f5962018-10-04 20:43:33492 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54493 {"pad", SameType, Rank::array, Optionality::optional},
494 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33495 SameType, Rank::shaped},
496 {"rrspacing", {{"x", SameReal}}, SameReal},
497 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11498 {"scan",
peter klauslera70f5962018-10-04 20:43:33499 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54500 {"back", AnyLogical, Rank::elemental, Optionality::optional},
501 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33502 KINDInt},
peter klausler24379cc2018-10-10 23:45:17503 {"selected_char_kind", {{"name", DftChar, Rank::scalar}}, DftInt,
504 Rank::scalar},
505 {"selected_int_kind", {{"r", AnyInt, Rank::scalar}}, DftInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14506 {"selected_real_kind",
507 {{"p", AnyInt, Rank::scalar},
508 {"r", AnyInt, Rank::scalar, Optionality::optional},
509 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
510 DftInt, Rank::scalar},
511 {"selected_real_kind",
512 {{"p", AnyInt, Rank::scalar, Optionality::optional},
513 {"r", AnyInt, Rank::scalar},
514 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
515 DftInt, Rank::scalar},
516 {"selected_real_kind",
517 {{"p", AnyInt, Rank::scalar, Optionality::optional},
518 {"r", AnyInt, Rank::scalar, Optionality::optional},
519 {"radix", AnyInt, Rank::scalar}},
520 DftInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33521 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler24379cc2018-10-10 23:45:17522 {"shape", {{"source", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
523 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33524 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
525 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
526 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
527 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
528 {"sin", {{"x", SameFloating}}, SameFloating},
529 {"sinh", {{"x", SameFloating}}, SameFloating},
peter klauslerf7f2a732018-10-09 19:07:29530 {"size", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
531 KINDInt, Rank::vector},
532 {"size",
533 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler51b09b62018-10-15 19:17:30534 {"dim", {IntType, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
peter klauslerf7f2a732018-10-09 19:07:29535 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33536 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11537 {"spread",
peter klauslera70f5962018-10-04 20:43:33538 {{"source", SameType, Rank::known},
peter klausler51b09b62018-10-15 19:17:30539 {"dim", {IntType, KindCode::dimArg}, Rank::scalar /*not optional*/},
peter klauslera70f5962018-10-04 20:43:33540 {"ncopies", AnyInt, Rank::scalar}},
541 SameType, Rank::rankPlus1},
542 {"sqrt", {{"x", SameFloating}}, SameFloating},
543 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
544 SameNumeric, Rank::dimReduced},
545 {"tan", {{"x", SameFloating}}, SameFloating},
546 {"tanh", {{"x", SameFloating}}, SameFloating},
547 {"trailz", {{"i", AnyInt}}, DftInt},
peter klauslerf7f2a732018-10-09 19:07:29548 {"transfer",
549 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::scalar}},
550 SameType, Rank::scalar},
551 {"transfer",
552 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::array}},
553 SameType, Rank::vector},
554 {"transfer",
555 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::known},
556 {"size", AnyInt, Rank::scalar}},
557 SameType, Rank::vector},
558 {"transpose", {{"matrix", SameType, Rank::matrix}}, SameType, Rank::matrix},
peter klauslerad9aede2018-10-11 21:51:14559 {"trim", {{"string", SameChar, Rank::scalar}}, SameChar, Rank::scalar},
peter klauslerf7f2a732018-10-09 19:07:29560 {"ubound", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
561 KINDInt, Rank::vector},
562 {"ubound",
563 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler51b09b62018-10-15 19:17:30564 {"dim", {IntType, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
peter klauslerf7f2a732018-10-09 19:07:29565 KINDInt, Rank::scalar},
566 {"unpack",
567 {{"vector", SameType, Rank::vector}, {"mask", AnyLogical, Rank::array},
568 {"field", SameType, Rank::conformable}},
569 SameType, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11570 {"verify",
peter klauslera70f5962018-10-04 20:43:33571 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54572 {"back", AnyLogical, Rank::elemental, Optionality::optional},
573 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33574 KINDInt},
peter klausler42b33da2018-09-29 00:02:11575};
576
peter klausler8efb8972018-10-10 17:48:12577// TODO: Coarray intrinsic functions
peter klauslerad9aede2018-10-11 21:51:14578// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
579// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
580// COSHAPE
peter klausler8efb8972018-10-10 17:48:12581// TODO: Object characteristic inquiry functions
peter klauslerad9aede2018-10-11 21:51:14582// ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS,
583// PRESENT, RANK, SAME_TYPE, STORAGE_SIZE
584// TODO: Type inquiry intrinsic functions - these return constants
585// BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT,
586// NEW_LINE, PRECISION, RADIX, RANGE, TINY
587// TODO: Non-standard intrinsic functions
588// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
589// COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL,
590// DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC,
591// QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM,
592// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
593// MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
594// IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
595// EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
596// probably more (these are PGI + Intel, possibly incomplete)
peter klausler42b33da2018-09-29 00:02:11597
598struct SpecificIntrinsicInterface : public IntrinsicInterface {
599 const char *generic{nullptr};
peter klauslerad9aede2018-10-11 21:51:14600 bool isRestrictedSpecific{
601 false}; // when true, can only be called, not passed
peter klausler42b33da2018-09-29 00:02:11602};
603
peter klauslerb22d4942018-10-01 18:27:45604static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33605 {{"abs", {{"a", DftReal}}, DftReal}},
606 {{"acos", {{"x", DftReal}}, DftReal}},
607 {{"aimag", {{"z", DftComplex}}, DftReal}},
608 {{"aint", {{"a", DftReal}}, DftReal}},
609 {{"alog", {{"x", DftReal}}, DftReal}, "log"},
610 {{"alog10", {{"x", DftReal}}, DftReal}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14611 {{"amax0",
612 {{"a1", DftInt}, {"a2", DftInt},
613 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
614 DftReal},
615 "max", true},
616 {{"amax1",
617 {{"a1", DftReal}, {"a2", DftReal},
618 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
619 DftReal},
620 "max", true},
621 {{"amin0",
622 {{"a1", DftInt}, {"a2", DftInt},
623 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
624 DftReal},
625 "min", true},
626 {{"amin1",
627 {{"a1", DftReal}, {"a2", DftReal},
628 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
629 DftReal},
630 "min", true},
peter klauslera70f5962018-10-04 20:43:33631 {{"amod", {{"a", DftReal}, {"p", DftReal}}, DftReal}, "mod"},
632 {{"anint", {{"a", DftReal}}, DftReal}},
633 {{"asin", {{"x", DftReal}}, DftReal}},
634 {{"atan", {{"x", DftReal}}, DftReal}},
635 {{"atan2", {{"y", DftReal}, {"x", DftReal}}, DftReal}},
636 {{"cabs", {{"a", DftComplex}}, DftReal}, "abs"},
637 {{"ccos", {{"a", DftComplex}}, DftComplex}, "cos"},
638 {{"cexp", {{"a", DftComplex}}, DftComplex}, "exp"},
639 {{"clog", {{"a", DftComplex}}, DftComplex}, "log"},
640 {{"conjg", {{"a", DftComplex}}, DftComplex}},
641 {{"cos", {{"x", DftReal}}, DftReal}},
642 {{"csin", {{"a", DftComplex}}, DftComplex}, "sin"},
643 {{"csqrt", {{"a", DftComplex}}, DftComplex}, "sqrt"},
644 {{"ctan", {{"a", DftComplex}}, DftComplex}, "tan"},
645 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
646 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
647 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
648 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
649 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
650 DoublePrecision},
651 "atan2"},
peter klauslerad9aede2018-10-11 21:51:14652 {{"dble", {{"a", DftReal}, DefaultingKIND}, DoublePrecision}, "real", true},
peter klauslera70f5962018-10-04 20:43:33653 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
654 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
655 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
656 DoublePrecision},
657 "dim"},
658 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
659 {{"dim", {{"x", DftReal}, {"y", DftReal}}, DftReal}},
660 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
661 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
662 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14663 {{"dmax1",
664 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
665 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
666 DoublePrecision},
667 "max", true},
668 {{"dmin1",
669 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
670 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
671 DoublePrecision},
672 "min", true},
peter klauslera70f5962018-10-04 20:43:33673 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
674 DoublePrecision},
675 "mod"},
676 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
677 {{"dprod", {{"x", DftReal}, {"y", DftReal}}, DoublePrecision}},
678 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
679 DoublePrecision},
680 "sign"},
681 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
682 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
683 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
684 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
685 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
686 {{"exp", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14687 {{"float", {{"i", DftInt}}, DftReal}, "real", true},
peter klauslera70f5962018-10-04 20:43:33688 {{"iabs", {{"a", DftInt}}, DftInt}, "abs"},
689 {{"idim", {{"x", DftInt}, {"y", DftInt}}, DftInt}, "dim"},
peter klauslerad9aede2018-10-11 21:51:14690 {{"idint", {{"a", DoublePrecision}}, DftInt}, "int", true},
peter klauslera70f5962018-10-04 20:43:33691 {{"idnint", {{"a", DoublePrecision}}, DftInt}, "nint"},
peter klauslerad9aede2018-10-11 21:51:14692 {{"ifix", {{"a", DftReal}}, DftInt}, "int", true},
peter klauslera70f5962018-10-04 20:43:33693 {{"index", {{"string", DftChar}, {"substring", DftChar}}, DftInt}},
694 {{"isign", {{"a", DftInt}, {"b", DftInt}}, DftInt}, "sign"},
695 {{"len", {{"string", DftChar}}, DftInt}},
696 {{"log", {{"x", DftReal}}, DftReal}},
697 {{"log10", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14698 {{"max0",
699 {{"a1", DftInt}, {"a2", DftInt},
700 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
701 DftInt},
702 "max", true},
703 {{"max1",
704 {{"a1", DftReal}, {"a2", DftReal},
705 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
706 DftInt},
707 "max", true},
708 {{"min0",
709 {{"a1", DftInt}, {"a2", DftInt},
710 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
711 DftInt},
712 "min", true},
713 {{"min1",
714 {{"a1", DftReal}, {"a2", DftReal},
715 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
716 DftInt},
717 "min", true},
peter klauslera70f5962018-10-04 20:43:33718 {{"mod", {{"a", DftInt}, {"p", DftInt}}, DftInt}},
719 {{"nint", {{"a", DftReal}}, DftInt}},
720 {{"sign", {{"a", DftReal}, {"b", DftReal}}, DftReal}},
721 {{"sin", {{"x", DftReal}}, DftReal}},
722 {{"sinh", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14723 {{"sngl", {{"a", DoublePrecision}}, DftReal}, "real", true},
peter klauslera70f5962018-10-04 20:43:33724 {{"sqrt", {{"x", DftReal}}, DftReal}},
725 {{"tan", {{"x", DftReal}}, DftReal}},
726 {{"tanh", {{"x", DftReal}}, DftReal}},
peter klausler42b33da2018-09-29 00:02:11727};
728
peter klauslerad9aede2018-10-11 21:51:14729// TODO: Intrinsic subroutines
730// MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY,
731// EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT,
732// GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER,
733// RANDOM_SEED, SYSTEM_CLOCK
734// TODO: Atomic intrinsic subroutines: ATOMIC_ADD &al.
735// TODO: Collective intrinsic subroutines: CO_BROADCAST &al.
peter klausler42b33da2018-09-29 00:02:11736
peter klauslera70f5962018-10-04 20:43:33737// Intrinsic interface matching against the arguments of a particular
738// procedure reference.
peter klauslera70f5962018-10-04 20:43:33739std::optional<SpecificIntrinsic> IntrinsicInterface::Match(
peter klauslera62636f2018-10-08 22:35:19740 const CallCharacteristics &call, const IntrinsicTypeDefaultKinds &defaults,
peter klauslercb308d32018-10-05 18:32:54741 parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33742 // Attempt to construct a 1-1 correspondence between the dummy arguments in
743 // a particular intrinsic procedure's generic interface and the actual
744 // arguments in a procedure reference.
peter klauslera62636f2018-10-08 22:35:19745 const ActualArgument *actualForDummy[maxArguments];
peter klauslera70f5962018-10-04 20:43:33746 int dummies{0};
747 for (; dummies < maxArguments && dummy[dummies].keyword != nullptr;
748 ++dummies) {
749 actualForDummy[dummies] = nullptr;
750 }
peter klausler94041d72018-10-15 20:39:51751 for (const ActualArgument &arg : call.arguments) {
peter klauslera62636f2018-10-08 22:35:19752 if (arg.isAlternateReturn) {
753 messages.Say(
754 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
peter klausler7bda1b32018-10-12 23:01:55755 name);
peter klauslera62636f2018-10-08 22:35:19756 return std::nullopt;
757 }
peter klauslera70f5962018-10-04 20:43:33758 bool found{false};
759 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
760 if (actualForDummy[dummyArgIndex] == nullptr) {
761 if (!arg.keyword.has_value() ||
762 *arg.keyword == dummy[dummyArgIndex].keyword) {
763 actualForDummy[dummyArgIndex] = &arg;
764 found = true;
765 break;
766 }
767 }
peter klausler7bda1b32018-10-12 23:01:55768 }
769 if (!found) {
770 if (arg.keyword.has_value()) {
771 messages.Say(*arg.keyword,
772 "unknown keyword argument to intrinsic '%s'"_err_en_US, name);
773 } else {
774 messages.Say(
775 "too many actual arguments for intrinsic '%s'"_err_en_US, name);
peter klauslera70f5962018-10-04 20:43:33776 }
peter klausler7bda1b32018-10-12 23:01:55777 return std::nullopt;
peter klauslera70f5962018-10-04 20:43:33778 }
779 }
780
781 // Check types and kinds of the actual arguments against the intrinsic's
782 // interface. Ensure that two or more arguments that have to have the same
783 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19784 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33785 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19786 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33787 bool hasDimArg{false};
788 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
789 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
790 if (d.typePattern.kindCode == KindCode::kindArg) {
791 CHECK(kindDummyArg == nullptr);
792 kindDummyArg = &d;
793 }
peter klauslera62636f2018-10-08 22:35:19794 const ActualArgument *arg{actualForDummy[dummyArgIndex]};
peter klauslera70f5962018-10-04 20:43:33795 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54796 if (d.optionality == Optionality::required) {
peter klausler7bda1b32018-10-12 23:01:55797 messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33798 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54799 } else {
800 continue;
peter klauslera70f5962018-10-04 20:43:33801 }
802 }
peter klauslera62636f2018-10-08 22:35:19803 std::optional<DynamicType> type{arg->GetType()};
804 if (!type.has_value()) {
805 CHECK(arg->Rank() == 0);
peter klauslercb308d32018-10-05 18:32:54806 if (d.typePattern.kindCode == KindCode::typeless ||
807 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33808 continue;
809 }
peter klausler7bda1b32018-10-12 23:01:55810 messages.Say(
811 "typeless (BOZ) not allowed for '%s=' argument"_err_en_US, d.keyword);
peter klauslercb308d32018-10-05 18:32:54812 return std::nullopt;
peter klauslera62636f2018-10-08 22:35:19813 } else if (!d.typePattern.categorySet.test(type->category)) {
peter klausler7bda1b32018-10-12 23:01:55814 messages.Say("actual argument for '%s=' has bad type '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19815 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33816 return std::nullopt; // argument has invalid type category
817 }
818 bool argOk{false};
819 switch (d.typePattern.kindCode) {
820 case KindCode::none:
821 case KindCode::typeless:
822 case KindCode::teamType: // TODO: TEAM_TYPE
823 argOk = false;
824 break;
825 case KindCode::defaultIntegerKind:
peter klauslera62636f2018-10-08 22:35:19826 argOk = type->kind == defaults.defaultIntegerKind;
peter klauslera70f5962018-10-04 20:43:33827 break;
828 case KindCode::defaultRealKind:
peter klauslera62636f2018-10-08 22:35:19829 argOk = type->kind == defaults.defaultRealKind;
peter klauslera70f5962018-10-04 20:43:33830 break;
831 case KindCode::doublePrecision:
peter klauslera62636f2018-10-08 22:35:19832 argOk = type->kind == defaults.defaultDoublePrecisionKind;
peter klauslera70f5962018-10-04 20:43:33833 break;
834 case KindCode::defaultCharKind:
peter klauslera62636f2018-10-08 22:35:19835 argOk = type->kind == defaults.defaultCharacterKind;
peter klauslera70f5962018-10-04 20:43:33836 break;
837 case KindCode::defaultLogicalKind:
peter klauslera62636f2018-10-08 22:35:19838 argOk = type->kind == defaults.defaultLogicalKind;
peter klauslera70f5962018-10-04 20:43:33839 break;
840 case KindCode::any: argOk = true; break;
841 case KindCode::kindArg:
peter klauslerf7f2a732018-10-09 19:07:29842 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33843 CHECK(kindArg == nullptr);
844 kindArg = arg;
peter klauslerf7f2a732018-10-09 19:07:29845 argOk = true;
peter klauslera70f5962018-10-04 20:43:33846 break;
847 case KindCode::dimArg:
peter klauslerf7f2a732018-10-09 19:07:29848 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33849 hasDimArg = true;
850 argOk = true;
851 break;
852 case KindCode::same:
853 if (sameArg == nullptr) {
854 sameArg = arg;
855 }
peter klauslera62636f2018-10-08 22:35:19856 argOk = *type == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33857 break;
858 case KindCode::effectiveKind:
859 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
860 "for intrinsic '%s'",
861 d.keyword, name);
862 break;
863 default: CRASH_NO_CASE;
864 }
865 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54866 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55867 "actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19868 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33869 return std::nullopt;
870 }
871 }
872
873 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:19874 const ActualArgument *arrayArg{nullptr};
875 const ActualArgument *knownArg{nullptr};
876 const ActualArgument *shapeArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33877 int elementalRank{0};
878 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
879 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
peter klauslera62636f2018-10-08 22:35:19880 if (const ActualArgument * arg{actualForDummy[dummyArgIndex]}) {
peter klauslera70f5962018-10-04 20:43:33881 if (arg->isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
peter klauslercb308d32018-10-05 18:32:54882 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55883 "assumed-rank array cannot be used for '%s=' argument"_err_en_US,
peter klauslercb308d32018-10-05 18:32:54884 d.keyword);
peter klauslera70f5962018-10-04 20:43:33885 return std::nullopt;
886 }
peter klauslera62636f2018-10-08 22:35:19887 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:33888 bool argOk{false};
889 switch (d.rank) {
890 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54891 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33892 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:19893 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:33894 }
peter klauslera62636f2018-10-08 22:35:19895 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:33896 break;
peter klauslera62636f2018-10-08 22:35:19897 case Rank::scalar: argOk = rank == 0; break;
898 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:33899 case Rank::shape:
900 CHECK(shapeArg == nullptr);
901 shapeArg = arg;
peter klauslerad9aede2018-10-11 21:51:14902 argOk = rank == 1 && arg->VectorSize().has_value();
peter klauslera70f5962018-10-04 20:43:33903 break;
peter klauslera62636f2018-10-08 22:35:19904 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:33905 case Rank::array:
peter klauslera62636f2018-10-08 22:35:19906 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:33907 if (!arrayArg) {
908 arrayArg = arg;
909 } else {
peter klauslera62636f2018-10-08 22:35:19910 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33911 }
912 break;
913 case Rank::known:
914 CHECK(knownArg == nullptr);
915 knownArg = arg;
916 argOk = true;
917 break;
918 case Rank::anyOrAssumedRank: argOk = true; break;
919 case Rank::conformable:
920 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19921 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33922 break;
923 case Rank::dimRemoved:
924 CHECK(arrayArg != nullptr);
925 if (hasDimArg) {
peter klauslera62636f2018-10-08 22:35:19926 argOk = rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33927 } else {
peter klauslera62636f2018-10-08 22:35:19928 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:33929 }
930 break;
peter klauslerad9aede2018-10-11 21:51:14931 case Rank::reduceOperation:
932 // TODO: Confirm that the argument is a pure function
933 // of two arguments with several constraints
934 CHECK(arrayArg != nullptr);
935 argOk = rank == 0;
936 break;
peter klauslera70f5962018-10-04 20:43:33937 case Rank::dimReduced:
938 case Rank::rankPlus1:
939 case Rank::shaped:
940 common::die("INTERNAL: result-only rank code appears on argument '%s' "
941 "for intrinsic '%s'",
942 d.keyword, name);
943 default: CRASH_NO_CASE;
944 }
945 if (!argOk) {
peter klausler7bda1b32018-10-12 23:01:55946 messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19947 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:33948 return std::nullopt;
949 }
950 }
951 }
952
peter klauslera70f5962018-10-04 20:43:33953 // Calculate the characteristics of the function result, if any
954 if (result.categorySet.empty()) {
955 CHECK(result.kindCode == KindCode::none);
956 return std::make_optional<SpecificIntrinsic>(name);
957 }
958 // Determine the result type.
959 DynamicType resultType{*result.categorySet.LeastElement(), 0};
960 switch (result.kindCode) {
961 case KindCode::defaultIntegerKind:
peter klausler51b09b62018-10-15 19:17:30962 CHECK(result.categorySet == IntType);
peter klauslera70f5962018-10-04 20:43:33963 CHECK(resultType.category == TypeCategory::Integer);
964 resultType.kind = defaults.defaultIntegerKind;
965 break;
966 case KindCode::defaultRealKind:
967 CHECK(result.categorySet == CategorySet{resultType.category});
peter klausler51b09b62018-10-15 19:17:30968 CHECK(FloatingType.test(resultType.category));
peter klauslera70f5962018-10-04 20:43:33969 resultType.kind = defaults.defaultRealKind;
970 break;
971 case KindCode::doublePrecision:
peter klausler51b09b62018-10-15 19:17:30972 CHECK(result.categorySet == RealType);
peter klauslera70f5962018-10-04 20:43:33973 CHECK(resultType.category == TypeCategory::Real);
974 resultType.kind = defaults.defaultDoublePrecisionKind;
975 break;
976 case KindCode::defaultCharKind:
peter klausler51b09b62018-10-15 19:17:30977 CHECK(result.categorySet == CharType);
peter klauslera70f5962018-10-04 20:43:33978 CHECK(resultType.category == TypeCategory::Character);
979 resultType.kind = defaults.defaultCharacterKind;
980 break;
981 case KindCode::defaultLogicalKind:
peter klausler51b09b62018-10-15 19:17:30982 CHECK(result.categorySet == LogicalType);
peter klauslera70f5962018-10-04 20:43:33983 CHECK(resultType.category == TypeCategory::Logical);
984 resultType.kind = defaults.defaultLogicalKind;
985 break;
986 case KindCode::same:
987 CHECK(sameArg != nullptr);
peter klausler55df4a72018-10-12 23:25:39988 if (std::optional<DynamicType> aType{sameArg->GetType()}) {
989 if (result.categorySet.test(aType->category)) {
990 resultType = *aType;
991 } else {
992 resultType.kind = aType->kind;
993 }
994 }
peter klauslera70f5962018-10-04 20:43:33995 break;
996 case KindCode::effectiveKind:
997 CHECK(kindDummyArg != nullptr);
998 CHECK(result.categorySet == CategorySet{resultType.category});
999 if (kindArg != nullptr) {
peter klauslerf7f2a732018-10-09 19:07:291000 if (auto *jExpr{std::get_if<Expr<SomeInteger>>(&kindArg->value->u)}) {
1001 CHECK(jExpr->Rank() == 0);
1002 if (auto value{jExpr->ScalarValue()}) {
1003 if (auto code{value->ToInt64()}) {
1004 if (IsValidKindOfIntrinsicType(resultType.category, *code)) {
1005 resultType.kind = *code;
1006 break;
1007 }
1008 }
1009 }
1010 }
peter klausler7bda1b32018-10-12 23:01:551011 messages.Say("'kind=' argument must be a constant scalar integer "
peter klauslerf7f2a732018-10-09 19:07:291012 "whose value is a supported kind for the "
1013 "intrinsic result type"_err_en_US);
1014 return std::nullopt;
peter klauslercb308d32018-10-05 18:32:541015 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
peter klauslera70f5962018-10-04 20:43:331016 CHECK(sameArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191017 resultType = *sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:331018 } else {
peter klauslercb308d32018-10-05 18:32:541019 CHECK(
1020 kindDummyArg->optionality == Optionality::defaultsToDefaultForResult);
peter klauslera70f5962018-10-04 20:43:331021 resultType.kind = defaults.DefaultKind(resultType.category);
1022 }
1023 break;
peter klauslerf7f2a732018-10-09 19:07:291024 case KindCode::likeMultiply:
1025 CHECK(dummies >= 2);
1026 CHECK(actualForDummy[0] != nullptr);
1027 CHECK(actualForDummy[1] != nullptr);
1028 resultType = actualForDummy[0]->GetType()->ResultTypeForMultiply(
1029 *actualForDummy[1]->GetType());
1030 break;
peter klauslera70f5962018-10-04 20:43:331031 case KindCode::typeless:
1032 case KindCode::teamType:
1033 case KindCode::any:
1034 case KindCode::kindArg:
1035 case KindCode::dimArg:
1036 common::die(
1037 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
1038 break;
1039 default: CRASH_NO_CASE;
1040 }
1041
peter klauslerf7f2a732018-10-09 19:07:291042 // At this point, the call is acceptable.
peter klauslera70f5962018-10-04 20:43:331043 // Determine the rank of the function result.
1044 int resultRank{0};
1045 switch (rank) {
1046 case Rank::elemental: resultRank = elementalRank; break;
1047 case Rank::scalar: resultRank = 0; break;
1048 case Rank::vector: resultRank = 1; break;
1049 case Rank::matrix: resultRank = 2; break;
peter klauslerf7f2a732018-10-09 19:07:291050 case Rank::conformable:
1051 CHECK(arrayArg != nullptr);
1052 resultRank = arrayArg->Rank();
1053 break;
peter klauslera70f5962018-10-04 20:43:331054 case Rank::dimReduced:
1055 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191056 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:331057 break;
1058 case Rank::rankPlus1:
1059 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191060 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:331061 break;
1062 case Rank::shaped:
1063 CHECK(shapeArg != nullptr);
peter klauslerad9aede2018-10-11 21:51:141064 {
1065 std::optional<int> shapeLen{shapeArg->VectorSize()};
1066 CHECK(shapeLen.has_value());
1067 resultRank = *shapeLen;
1068 }
peter klauslera70f5962018-10-04 20:43:331069 break;
peter klauslercb308d32018-10-05 18:32:541070 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331071 case Rank::shape:
1072 case Rank::array:
1073 case Rank::known:
1074 case Rank::anyOrAssumedRank:
peter klauslera70f5962018-10-04 20:43:331075 case Rank::dimRemoved:
peter klauslerad9aede2018-10-11 21:51:141076 case Rank::reduceOperation:
peter klauslera70f5962018-10-04 20:43:331077 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
1078 break;
1079 default: CRASH_NO_CASE;
1080 }
1081 CHECK(resultRank >= 0);
1082
1083 return std::make_optional<SpecificIntrinsic>(
1084 name, elementalRank > 0, resultType, resultRank);
1085}
1086
peter klauslera62636f2018-10-08 22:35:191087struct IntrinsicProcTable::Implementation {
1088 explicit Implementation(const IntrinsicTypeDefaultKinds &dfts)
peter klauslera70f5962018-10-04 20:43:331089 : defaults{dfts} {
1090 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
1091 genericFuncs.insert(std::make_pair(std::string{f.name}, &f));
1092 }
1093 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
1094 specificFuncs.insert(std::make_pair(std::string{f.name}, &f));
1095 }
1096 }
peter klausler42b33da2018-09-29 00:02:111097
peter klauslercb308d32018-10-05 18:32:541098 std::optional<SpecificIntrinsic> Probe(
1099 const CallCharacteristics &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:531100
peter klauslera62636f2018-10-08 22:35:191101 IntrinsicTypeDefaultKinds defaults;
peter klauslera70f5962018-10-04 20:43:331102 std::multimap<std::string, const IntrinsicInterface *> genericFuncs;
1103 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs;
peter klausler7bda1b32018-10-12 23:01:551104 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:111105};
1106
peter klauslercb308d32018-10-05 18:32:541107// Probe the configured intrinsic procedure pattern tables in search of a
1108// match for a given procedure reference.
peter klauslera62636f2018-10-08 22:35:191109std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
peter klauslercb308d32018-10-05 18:32:541110 const CallCharacteristics &call,
1111 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:531112 if (call.isSubroutineCall) {
1113 return std::nullopt; // TODO
1114 }
peter klausler7bda1b32018-10-12 23:01:551115 parser::Messages *finalBuffer{messages ? messages->messages() : nullptr};
peter klausler62425d62018-10-12 00:01:311116 // Probe the specific intrinsic function table first.
1117 parser::Messages specificBuffer;
1118 parser::ContextualMessages specificErrors{
1119 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551120 finalBuffer ? &specificBuffer : nullptr};
peter klausler75a32092018-10-05 16:57:531121 std::string name{call.name.ToString()};
1122 auto specificRange{specificFuncs.equal_range(name)};
1123 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klausler62425d62018-10-12 00:01:311124 if (auto specific{iter->second->Match(call, defaults, specificErrors)}) {
peter klauslerad9aede2018-10-11 21:51:141125 if (const char *genericName{iter->second->generic}) {
1126 specific->name = genericName;
1127 }
1128 specific->isRestrictedSpecific = iter->second->isRestrictedSpecific;
peter klausler75a32092018-10-05 16:57:531129 return specific;
1130 }
1131 }
peter klausler62425d62018-10-12 00:01:311132 // Probe the generic intrinsic function table next.
1133 parser::Messages genericBuffer;
1134 parser::ContextualMessages genericErrors{
1135 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551136 finalBuffer ? &genericBuffer : nullptr};
peter klausler62425d62018-10-12 00:01:311137 auto genericRange{genericFuncs.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531138 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klausler62425d62018-10-12 00:01:311139 if (auto specific{iter->second->Match(call, defaults, genericErrors)}) {
peter klausler75a32092018-10-05 16:57:531140 return specific;
1141 }
1142 }
peter klauslerad9aede2018-10-11 21:51:141143 // Special cases of intrinsic functions
peter klausler8efb8972018-10-10 17:48:121144 if (call.name.ToString() == "null") {
peter klausler94041d72018-10-15 20:39:511145 if (call.arguments.size() == 0) {
peter klausler8efb8972018-10-10 17:48:121146 // TODO: NULL() result type is determined by context
1147 // Can pass that context in, or return a token distinguishing
1148 // NULL, or represent NULL as a new kind of top-level expression
peter klausler94041d72018-10-15 20:39:511149 } else if (call.arguments.size() > 1) {
peter klausler62425d62018-10-12 00:01:311150 genericErrors.Say("too many arguments to NULL()"_err_en_US);
peter klausler94041d72018-10-15 20:39:511151 } else if (call.arguments[0].keyword.has_value() &&
1152 call.arguments[0].keyword->ToString() != "mold") {
peter klausler62425d62018-10-12 00:01:311153 genericErrors.Say("unknown argument '%s' to NULL()"_err_en_US,
peter klausler94041d72018-10-15 20:39:511154 call.arguments[0].keyword->ToString().data());
peter klausler8efb8972018-10-10 17:48:121155 } else {
1156 // TODO: Argument must be pointer, procedure pointer, or allocatable.
1157 // Characteristics, including dynamic length type parameter values,
1158 // must be taken from the MOLD argument.
1159 }
1160 }
1161 // No match
peter klausler7bda1b32018-10-12 23:01:551162 if (finalBuffer) {
peter klausler62425d62018-10-12 00:01:311163 if (genericBuffer.empty()) {
peter klausler7bda1b32018-10-12 23:01:551164 finalBuffer->Annex(std::move(specificBuffer));
peter klausler62425d62018-10-12 00:01:311165 } else {
peter klausler7bda1b32018-10-12 23:01:551166 finalBuffer->Annex(std::move(genericBuffer));
peter klausler62425d62018-10-12 00:01:311167 }
peter klauslercb308d32018-10-05 18:32:541168 }
peter klausler75a32092018-10-05 16:57:531169 return std::nullopt;
1170}
1171
peter klauslera62636f2018-10-08 22:35:191172IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:541173 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:111174 delete impl_;
1175 impl_ = nullptr;
1176}
1177
peter klauslera62636f2018-10-08 22:35:191178IntrinsicProcTable IntrinsicProcTable::Configure(
1179 const IntrinsicTypeDefaultKinds &defaults) {
1180 IntrinsicProcTable result;
1181 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:111182 return result;
1183}
1184
peter klauslera62636f2018-10-08 22:35:191185std::optional<SpecificIntrinsic> IntrinsicProcTable::Probe(
peter klauslercb308d32018-10-05 18:32:541186 const CallCharacteristics &call,
1187 parser::ContextualMessages *messages) const {
peter klauslera62636f2018-10-08 22:35:191188 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klauslercb308d32018-10-05 18:32:541189 return impl_->Probe(call, messages);
peter klausler42b33da2018-09-29 00:02:111190}
peter klauslerad9aede2018-10-11 21:51:141191
1192std::ostream &SpecificIntrinsic::Dump(std::ostream &o) const {
1193 return o << name;
1194}
peter klausler7bda1b32018-10-12 23:01:551195
1196std::ostream &TypePattern::Dump(std::ostream &o) const {
1197 if (categorySet == AnyType) {
1198 o << "any type";
1199 } else {
1200 const char *sep = "";
1201 auto set{categorySet};
1202 while (auto least{set.LeastElement()}) {
1203 o << sep << EnumToString(*least);
1204 sep = " or ";
1205 set.reset(*least);
1206 }
1207 }
1208 o << '(' << EnumToString(kindCode) << ')';
1209 return o;
1210}
1211
1212std::ostream &IntrinsicDummyArgument::Dump(std::ostream &o) const {
1213 if (keyword) {
1214 o << keyword << '=';
1215 }
1216 return typePattern.Dump(o)
1217 << ' ' << EnumToString(rank) << ' ' << EnumToString(optionality);
1218}
1219
1220std::ostream &IntrinsicInterface::Dump(std::ostream &o) const {
1221 o << name;
1222 char sep{'('};
1223 for (const auto &d : dummy) {
1224 if (d.typePattern.kindCode == KindCode::none) {
1225 break;
1226 }
1227 d.Dump(o << sep);
1228 sep = ',';
1229 }
1230 if (sep == '(') {
1231 o << "()";
1232 }
1233 return result.Dump(o << " -> ") << ' ' << EnumToString(rank);
1234}
1235
1236std::ostream &IntrinsicProcTable::Implementation::Dump(std::ostream &o) const {
1237 o << "generic intrinsic functions:\n";
1238 for (const auto &iter : genericFuncs) {
1239 iter.second->Dump(o << iter.first << ": ") << '\n';
1240 }
1241 o << "specific intrinsic functions:\n";
1242 for (const auto &iter : specificFuncs) {
1243 iter.second->Dump(o << iter.first << ": ");
1244 if (const char *g{iter.second->generic}) {
1245 o << " -> " << g;
1246 }
1247 o << '\n';
1248 }
1249 return o;
1250}
1251
1252std::ostream &IntrinsicProcTable::Dump(std::ostream &o) const {
1253 return impl_->Dump(o);
1254}
1255
peter klausler42b33da2018-09-29 00:02:111256} // namespace Fortran::evaluate