blob: 0f6995f571e83880495049125b18316c1dbc5264 [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>;
53static constexpr CategorySet Int{TypeCategory::Integer};
54static constexpr CategorySet Real{TypeCategory::Real};
55static constexpr CategorySet Complex{TypeCategory::Complex};
56static constexpr CategorySet Char{TypeCategory::Character};
57static constexpr CategorySet Logical{TypeCategory::Logical};
58static constexpr CategorySet IntOrReal{Int | Real};
59static constexpr CategorySet Floating{Real | Complex};
60static constexpr CategorySet Numeric{Int | Real | Complex};
61static constexpr CategorySet Relatable{Int | Real | Char};
62static constexpr CategorySet IntrinsicType{
63 Int | Real | Complex | Char | Logical};
64static 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
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};
peter klauslerf7f2a732018-10-09 19:07:29107static constexpr TypePattern Anything{AnyType, KindCode::any};
peter klauslera70f5962018-10-04 20:43:33108
109// Match some kind of some intrinsic type(s); all "Same" values must match,
110// even when not in the same category (e.g., SameComplex and SameReal).
111// Can be used to specify a result so long as at least one argument is
112// a "Same".
113static constexpr TypePattern SameInt{Int, KindCode::same};
114static constexpr TypePattern SameReal{Real, KindCode::same};
115static constexpr TypePattern SameIntOrReal{IntOrReal, KindCode::same};
116static constexpr TypePattern SameComplex{Complex, KindCode::same};
117static constexpr TypePattern SameFloating{Floating, KindCode::same};
118static constexpr TypePattern SameNumeric{Numeric, KindCode::same};
119static constexpr TypePattern SameChar{Char, KindCode::same};
120static constexpr TypePattern SameLogical{Logical, KindCode::same};
121static constexpr TypePattern SameRelatable{Relatable, KindCode::same};
122static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
123static constexpr TypePattern SameDerivedType{
124 CategorySet{TypeCategory::Derived}, KindCode::same};
125static constexpr TypePattern SameType{AnyType, KindCode::same};
126
peter klauslerf7f2a732018-10-09 19:07:29127// For DOT_PRODUCT and MATMUL, the result type depends on the arguments
128static constexpr TypePattern ResultLogical{Logical, KindCode::likeMultiply};
129static constexpr TypePattern ResultNumeric{Numeric, KindCode::likeMultiply};
130
peter klauslera70f5962018-10-04 20:43:33131// Result types with known category and KIND=
132static constexpr TypePattern KINDInt{Int, KindCode::effectiveKind};
133static constexpr TypePattern KINDReal{Real, KindCode::effectiveKind};
134static constexpr TypePattern KINDComplex{Complex, KindCode::effectiveKind};
135static constexpr TypePattern KINDChar{Char, KindCode::effectiveKind};
136static constexpr TypePattern KINDLogical{Logical, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11137
138// The default rank pattern for dummy arguments and function results is
139// "elemental".
peter klausler7bda1b32018-10-12 23:01:55140ENUM_CLASS(Rank,
141 elemental, // scalar, or array that conforms with other array arguments
142 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
143 scalar, vector,
144 shape, // INTEGER vector of known length and no negative element
145 matrix,
146 array, // not scalar, rank is known and greater than zero
147 known, // rank is known and can be scalar
148 anyOrAssumedRank, // rank can be unknown
149 conformable, // scalar, or array of same rank & shape as "array" argument
150 reduceOperation, // a pure function with constraints for REDUCE
151 dimReduced, // scalar if no DIM= argument, else rank(array)-1
152 dimRemoved, // scalar, or rank(array)-1
153 rankPlus1, // rank(known)+1
154 shaped, // rank is length of SHAPE vector
155)
peter klausler42b33da2018-09-29 00:02:11156
peter klausler7bda1b32018-10-12 23:01:55157ENUM_CLASS(Optionality, required, optional,
158 defaultsToSameKind, // for MatchingDefaultKIND
159 defaultsToDefaultForResult, // for DefaultingKIND
160 repeats, // for MAX/MIN and their several variants
161)
peter klausler42b33da2018-09-29 00:02:11162
163struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45164 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11165 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33166 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54167 Optionality optionality{Optionality::required};
peter klausler7bda1b32018-10-12 23:01:55168 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11169};
170
peter klauslera70f5962018-10-04 20:43:33171// constexpr abbreviations for popular arguments:
172// DefaultingKIND is a KIND= argument whose default value is the appropriate
173// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54174static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
175 {Int, KindCode::kindArg}, Rank::scalar,
176 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33177// MatchingDefaultKIND is a KIND= argument whose default value is the
178// kind of any "Same" function argument (viz., the one whose kind pattern is
179// "same").
peter klauslercb308d32018-10-05 18:32:54180static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
181 {Int, KindCode::kindArg}, Rank::scalar, Optionality::defaultsToSameKind};
peter klauslera70f5962018-10-04 20:43:33182static constexpr IntrinsicDummyArgument OptionalDIM{
peter klauslercb308d32018-10-05 18:32:54183 "dim", {Int, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33184static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54185 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11186
187struct IntrinsicInterface {
188 static constexpr int maxArguments{7};
peter klauslerb22d4942018-10-01 18:27:45189 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11190 IntrinsicDummyArgument dummy[maxArguments];
191 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33192 Rank rank{Rank::elemental};
193 std::optional<SpecificIntrinsic> Match(const CallCharacteristics &,
peter klauslera62636f2018-10-08 22:35:19194 const IntrinsicTypeDefaultKinds &,
peter klauslercb308d32018-10-05 18:32:54195 parser::ContextualMessages &messages) const;
peter klausler7bda1b32018-10-12 23:01:55196 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11197};
198
peter klauslerb22d4942018-10-01 18:27:45199static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33200 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
201 {"abs", {{"a", SameComplex}}, SameReal},
peter klauslerad9aede2018-10-11 21:51:14202 {"achar", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
peter klauslera70f5962018-10-04 20:43:33203 {"acos", {{"x", SameFloating}}, SameFloating},
204 {"acosh", {{"x", SameFloating}}, SameFloating},
205 {"adjustl", {{"string", SameChar}}, SameChar},
206 {"adjustr", {{"string", SameChar}}, SameChar},
207 {"aimag", {{"x", SameComplex}}, SameReal},
208 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
209 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
210 Rank::dimReduced},
211 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
212 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
213 Rank::dimReduced},
214 {"asin", {{"x", SameFloating}}, SameFloating},
215 {"asinh", {{"x", SameFloating}}, SameFloating},
216 {"atan", {{"x", SameFloating}}, SameFloating},
217 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
218 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
219 {"atanh", {{"x", SameFloating}}, SameFloating},
220 {"bessel_j0", {{"x", SameReal}}, SameReal},
221 {"bessel_j1", {{"x", SameReal}}, SameReal},
222 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29223 {"bessel_jn",
224 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
225 {"x", SameReal, Rank::scalar}},
226 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33227 {"bessel_y0", {{"x", SameReal}}, SameReal},
228 {"bessel_y1", {{"x", SameReal}}, SameReal},
229 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29230 {"bessel_yn",
231 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
232 {"x", SameReal, Rank::scalar}},
233 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33234 {"bge",
peter klauslercb308d32018-10-05 18:32:54235 {{"i", AnyInt, Rank::elementalOrBOZ},
236 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33237 DftLogical},
238 {"bgt",
peter klauslercb308d32018-10-05 18:32:54239 {{"i", AnyInt, Rank::elementalOrBOZ},
240 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33241 DftLogical},
242 {"ble",
peter klauslercb308d32018-10-05 18:32:54243 {{"i", AnyInt, Rank::elementalOrBOZ},
244 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33245 DftLogical},
246 {"blt",
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 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DftLogical},
251 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
252 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
253 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11254 {"cmplx",
peter klauslercb308d32018-10-05 18:32:54255 {{"x", SameIntOrReal, Rank::elementalOrBOZ},
256 {"y", SameIntOrReal, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33257 KINDComplex},
peter klauslerf7f2a732018-10-09 19:07:29258 {"command_argument_count", {}, DftInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33259 {"conjg", {{"z", SameComplex}}, SameComplex},
260 {"cos", {{"x", SameFloating}}, SameFloating},
261 {"cosh", {{"x", SameFloating}}, SameFloating},
262 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
263 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11264 {"cshift",
peter klauslera70f5962018-10-04 20:43:33265 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
266 OptionalDIM},
267 SameType, Rank::array},
268 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
peter klauslerf7f2a732018-10-09 19:07:29269 {"dot_product",
270 {{"vector_a", AnyLogical, Rank::vector},
271 {"vector_b", AnyLogical, Rank::vector}},
272 ResultLogical, Rank::scalar},
273 {"dot_product",
274 {{"vector_a", AnyComplex, Rank::vector},
275 {"vector_b", AnyNumeric, Rank::vector}},
276 ResultNumeric, Rank::scalar}, // conjugates vector_a
277 {"dot_product",
278 {{"vector_a", AnyIntOrReal, Rank::vector},
279 {"vector_b", AnyNumeric, Rank::vector}},
280 ResultNumeric, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33281 {"dprod", {{"x", DftReal}, {"y", DftReal}}, DoublePrecision},
282 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54283 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33284 {"shift", AnyInt}},
285 SameInt},
286 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
287 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54288 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33289 {"shift", AnyInt}},
290 SameInt},
291 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11292 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33293 {{"array", SameIntrinsic, Rank::array},
294 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54295 {"boundary", SameIntrinsic, Rank::dimRemoved,
296 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33297 OptionalDIM},
298 SameIntrinsic, Rank::array},
peter klausler42b33da2018-09-29 00:02:11299 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33300 {{"array", SameDerivedType, Rank::array},
301 {"shift", AnyInt, Rank::dimRemoved},
302 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
303 SameDerivedType, Rank::array},
304 {"erf", {{"x", SameReal}}, SameReal},
305 {"erfc", {{"x", SameReal}}, SameReal},
306 {"erfc_scaled", {{"x", SameReal}}, SameReal},
307 {"exp", {{"x", SameFloating}}, SameFloating},
308 {"exponent", {{"x", AnyReal}}, DftInt},
peter klausler42b33da2018-09-29 00:02:11309 {"findloc",
peter klauslerad9aede2018-10-11 21:51:14310 {{"array", AnyNumeric, Rank::array},
311 {"value", AnyNumeric, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54312 DefaultingKIND,
313 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33314 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11315 {"findloc",
peter klauslera70f5962018-10-04 20:43:33316 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
317 OptionalDIM, OptionalMASK, DefaultingKIND,
peter klauslercb308d32018-10-05 18:32:54318 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33319 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11320 {"findloc",
peter klauslera70f5962018-10-04 20:43:33321 {{"array", AnyLogical, Rank::array},
322 {"value", AnyLogical, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54323 DefaultingKIND,
324 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33325 KINDInt, Rank::dimReduced},
326 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
327 {"fraction", {{"x", SameReal}}, SameReal},
328 {"gamma", {{"x", SameReal}}, SameReal},
329 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
330 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
331 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
332 SameInt, Rank::dimReduced},
333 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
334 SameInt, Rank::dimReduced},
335 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
336 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54337 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33338 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
339 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
340 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
341 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
342 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54343 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33344 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
345 {"image_status",
peter klauslercb308d32018-10-05 18:32:54346 {{"image", SameInt},
347 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33348 DftInt},
peter klausler42b33da2018-09-29 00:02:11349 {"index",
peter klauslera70f5962018-10-04 20:43:33350 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54351 {"back", AnyLogical, Rank::scalar, Optionality::optional},
352 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33353 KINDInt},
peter klauslercb308d32018-10-05 18:32:54354 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
355 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33356 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
357 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
358 {"ishftc",
359 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54360 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33361 SameInt},
362 {"is_iostat_end", {{"i", AnyInt}}, DftLogical},
363 {"is_iostat_eor", {{"i", AnyInt}}, DftLogical},
peter klauslerf7f2a732018-10-09 19:07:29364 {"lbound", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
365 KINDInt, Rank::vector},
366 {"lbound",
367 {{"array", Anything, Rank::anyOrAssumedRank},
368 {"dim", {Int, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
369 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33370 {"leadz", {{"i", AnyInt}}, DftInt},
371 {"len", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
372 {"len_trim", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
373 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
374 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
375 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
376 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
377 {"log", {{"x", SameFloating}}, SameFloating},
378 {"log10", {{"x", SameReal}}, SameReal},
379 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
380 {"log_gamma", {{"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29381 {"matmul",
382 {{"array_a", AnyLogical, Rank::vector},
383 {"array_b", AnyLogical, Rank::matrix}},
384 ResultLogical, Rank::vector},
385 {"matmul",
386 {{"array_a", AnyLogical, Rank::matrix},
387 {"array_b", AnyLogical, Rank::vector}},
388 ResultLogical, Rank::vector},
389 {"matmul",
390 {{"array_a", AnyLogical, Rank::matrix},
391 {"array_b", AnyLogical, Rank::matrix}},
392 ResultLogical, Rank::matrix},
393 {"matmul",
394 {{"array_a", AnyNumeric, Rank::vector},
395 {"array_b", AnyNumeric, Rank::matrix}},
396 ResultNumeric, Rank::vector},
397 {"matmul",
398 {{"array_a", AnyNumeric, Rank::matrix},
399 {"array_b", AnyNumeric, Rank::vector}},
400 ResultNumeric, Rank::vector},
401 {"matmul",
402 {{"array_a", AnyNumeric, Rank::matrix},
403 {"array_b", AnyNumeric, Rank::matrix}},
404 ResultNumeric, Rank::matrix},
peter klauslera70f5962018-10-04 20:43:33405 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
406 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klauslerad9aede2018-10-11 21:51:14407 {"max",
408 {{"a1", SameRelatable}, {"a2", SameRelatable},
409 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
410 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11411 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33412 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54413 DefaultingKIND,
414 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33415 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11416 {"maxval",
peter klauslera70f5962018-10-04 20:43:33417 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
418 SameRelatable, Rank::dimReduced},
peter klauslerad9aede2018-10-11 21:51:14419 {"merge",
420 {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
421 SameType},
peter klausler42b33da2018-09-29 00:02:11422 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54423 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
424 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33425 SameInt},
426 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54427 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33428 SameInt},
peter klauslerad9aede2018-10-11 21:51:14429 {"min",
430 {{"a1", SameRelatable}, {"a2", SameRelatable},
431 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
432 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11433 {"minloc",
peter klauslera70f5962018-10-04 20:43:33434 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54435 DefaultingKIND,
436 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33437 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11438 {"minval",
peter klauslera70f5962018-10-04 20:43:33439 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
440 SameRelatable, Rank::dimReduced},
441 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
442 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
443 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
444 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
445 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
446 Rank::dimReduced},
447 {"not", {{"i", SameInt}}, SameInt},
peter klausler8efb8972018-10-10 17:48:12448 // NULL() is a special case handled in Probe() below
peter klausler42b33da2018-09-29 00:02:11449 {"out_of_range",
peter klauslerad9aede2018-10-11 21:51:14450 {{"x", AnyIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
peter klauslera70f5962018-10-04 20:43:33451 DftLogical},
452 {"out_of_range",
453 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54454 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33455 DftLogical},
456 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DftLogical},
peter klausler42b33da2018-09-29 00:02:11457 {"pack",
peter klauslera70f5962018-10-04 20:43:33458 {{"array", SameType, Rank::array},
459 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54460 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33461 SameType, Rank::vector},
462 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
463 Rank::dimReduced},
464 {"popcnt", {{"i", AnyInt}}, DftInt},
465 {"poppar", {{"i", AnyInt}}, DftInt},
peter klausler42b33da2018-09-29 00:02:11466 {"product",
peter klauslera70f5962018-10-04 20:43:33467 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
468 SameNumeric, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54469 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33470 KINDReal},
peter klauslerad9aede2018-10-11 21:51:14471 {"reduce",
472 {{"array", SameType, Rank::array},
473 {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
474 OptionalMASK, {"identity", SameType, Rank::scalar},
475 {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
476 SameType, Rank::dimReduced},
peter klausler24379cc2018-10-10 23:45:17477 {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
478 SameChar, Rank::scalar},
peter klausler42b33da2018-09-29 00:02:11479 {"reshape",
peter klauslera70f5962018-10-04 20:43:33480 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54481 {"pad", SameType, Rank::array, Optionality::optional},
482 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33483 SameType, Rank::shaped},
484 {"rrspacing", {{"x", SameReal}}, SameReal},
485 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11486 {"scan",
peter klauslera70f5962018-10-04 20:43:33487 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54488 {"back", AnyLogical, Rank::elemental, Optionality::optional},
489 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33490 KINDInt},
peter klausler24379cc2018-10-10 23:45:17491 {"selected_char_kind", {{"name", DftChar, Rank::scalar}}, DftInt,
492 Rank::scalar},
493 {"selected_int_kind", {{"r", AnyInt, Rank::scalar}}, DftInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14494 {"selected_real_kind",
495 {{"p", AnyInt, Rank::scalar},
496 {"r", AnyInt, Rank::scalar, Optionality::optional},
497 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
498 DftInt, Rank::scalar},
499 {"selected_real_kind",
500 {{"p", AnyInt, Rank::scalar, Optionality::optional},
501 {"r", AnyInt, Rank::scalar},
502 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
503 DftInt, Rank::scalar},
504 {"selected_real_kind",
505 {{"p", AnyInt, Rank::scalar, Optionality::optional},
506 {"r", AnyInt, Rank::scalar, Optionality::optional},
507 {"radix", AnyInt, Rank::scalar}},
508 DftInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33509 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler24379cc2018-10-10 23:45:17510 {"shape", {{"source", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
511 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33512 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
513 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
514 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
515 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
516 {"sin", {{"x", SameFloating}}, SameFloating},
517 {"sinh", {{"x", SameFloating}}, SameFloating},
peter klauslerf7f2a732018-10-09 19:07:29518 {"size", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
519 KINDInt, Rank::vector},
520 {"size",
521 {{"array", Anything, Rank::anyOrAssumedRank},
522 {"dim", {Int, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
523 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33524 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11525 {"spread",
peter klauslera70f5962018-10-04 20:43:33526 {{"source", SameType, Rank::known},
527 {"dim", {Int, KindCode::dimArg}, Rank::scalar /*not optional*/},
528 {"ncopies", AnyInt, Rank::scalar}},
529 SameType, Rank::rankPlus1},
530 {"sqrt", {{"x", SameFloating}}, SameFloating},
531 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
532 SameNumeric, Rank::dimReduced},
533 {"tan", {{"x", SameFloating}}, SameFloating},
534 {"tanh", {{"x", SameFloating}}, SameFloating},
535 {"trailz", {{"i", AnyInt}}, DftInt},
peter klauslerf7f2a732018-10-09 19:07:29536 {"transfer",
537 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::scalar}},
538 SameType, Rank::scalar},
539 {"transfer",
540 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::array}},
541 SameType, Rank::vector},
542 {"transfer",
543 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::known},
544 {"size", AnyInt, Rank::scalar}},
545 SameType, Rank::vector},
546 {"transpose", {{"matrix", SameType, Rank::matrix}}, SameType, Rank::matrix},
peter klauslerad9aede2018-10-11 21:51:14547 {"trim", {{"string", SameChar, Rank::scalar}}, SameChar, Rank::scalar},
peter klauslerf7f2a732018-10-09 19:07:29548 {"ubound", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
549 KINDInt, Rank::vector},
550 {"ubound",
551 {{"array", Anything, Rank::anyOrAssumedRank},
552 {"dim", {Int, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
553 KINDInt, Rank::scalar},
554 {"unpack",
555 {{"vector", SameType, Rank::vector}, {"mask", AnyLogical, Rank::array},
556 {"field", SameType, Rank::conformable}},
557 SameType, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11558 {"verify",
peter klauslera70f5962018-10-04 20:43:33559 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54560 {"back", AnyLogical, Rank::elemental, Optionality::optional},
561 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33562 KINDInt},
peter klausler42b33da2018-09-29 00:02:11563};
564
peter klausler8efb8972018-10-10 17:48:12565// TODO: Coarray intrinsic functions
peter klauslerad9aede2018-10-11 21:51:14566// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
567// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
568// COSHAPE
peter klausler8efb8972018-10-10 17:48:12569// TODO: Object characteristic inquiry functions
peter klauslerad9aede2018-10-11 21:51:14570// ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS,
571// PRESENT, RANK, SAME_TYPE, STORAGE_SIZE
572// TODO: Type inquiry intrinsic functions - these return constants
573// BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT,
574// NEW_LINE, PRECISION, RADIX, RANGE, TINY
575// TODO: Non-standard intrinsic functions
576// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
577// COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL,
578// DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC,
579// QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM,
580// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
581// MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
582// IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
583// EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
584// probably more (these are PGI + Intel, possibly incomplete)
peter klausler42b33da2018-09-29 00:02:11585
586struct SpecificIntrinsicInterface : public IntrinsicInterface {
587 const char *generic{nullptr};
peter klauslerad9aede2018-10-11 21:51:14588 bool isRestrictedSpecific{
589 false}; // when true, can only be called, not passed
peter klausler42b33da2018-09-29 00:02:11590};
591
peter klauslerb22d4942018-10-01 18:27:45592static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33593 {{"abs", {{"a", DftReal}}, DftReal}},
594 {{"acos", {{"x", DftReal}}, DftReal}},
595 {{"aimag", {{"z", DftComplex}}, DftReal}},
596 {{"aint", {{"a", DftReal}}, DftReal}},
597 {{"alog", {{"x", DftReal}}, DftReal}, "log"},
598 {{"alog10", {{"x", DftReal}}, DftReal}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14599 {{"amax0",
600 {{"a1", DftInt}, {"a2", DftInt},
601 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
602 DftReal},
603 "max", true},
604 {{"amax1",
605 {{"a1", DftReal}, {"a2", DftReal},
606 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
607 DftReal},
608 "max", true},
609 {{"amin0",
610 {{"a1", DftInt}, {"a2", DftInt},
611 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
612 DftReal},
613 "min", true},
614 {{"amin1",
615 {{"a1", DftReal}, {"a2", DftReal},
616 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
617 DftReal},
618 "min", true},
peter klauslera70f5962018-10-04 20:43:33619 {{"amod", {{"a", DftReal}, {"p", DftReal}}, DftReal}, "mod"},
620 {{"anint", {{"a", DftReal}}, DftReal}},
621 {{"asin", {{"x", DftReal}}, DftReal}},
622 {{"atan", {{"x", DftReal}}, DftReal}},
623 {{"atan2", {{"y", DftReal}, {"x", DftReal}}, DftReal}},
624 {{"cabs", {{"a", DftComplex}}, DftReal}, "abs"},
625 {{"ccos", {{"a", DftComplex}}, DftComplex}, "cos"},
626 {{"cexp", {{"a", DftComplex}}, DftComplex}, "exp"},
627 {{"clog", {{"a", DftComplex}}, DftComplex}, "log"},
628 {{"conjg", {{"a", DftComplex}}, DftComplex}},
629 {{"cos", {{"x", DftReal}}, DftReal}},
630 {{"csin", {{"a", DftComplex}}, DftComplex}, "sin"},
631 {{"csqrt", {{"a", DftComplex}}, DftComplex}, "sqrt"},
632 {{"ctan", {{"a", DftComplex}}, DftComplex}, "tan"},
633 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
634 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
635 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
636 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
637 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
638 DoublePrecision},
639 "atan2"},
peter klauslerad9aede2018-10-11 21:51:14640 {{"dble", {{"a", DftReal}, DefaultingKIND}, DoublePrecision}, "real", true},
peter klauslera70f5962018-10-04 20:43:33641 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
642 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
643 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
644 DoublePrecision},
645 "dim"},
646 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
647 {{"dim", {{"x", DftReal}, {"y", DftReal}}, DftReal}},
648 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
649 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
650 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14651 {{"dmax1",
652 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
653 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
654 DoublePrecision},
655 "max", true},
656 {{"dmin1",
657 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
658 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
659 DoublePrecision},
660 "min", true},
peter klauslera70f5962018-10-04 20:43:33661 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
662 DoublePrecision},
663 "mod"},
664 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
665 {{"dprod", {{"x", DftReal}, {"y", DftReal}}, DoublePrecision}},
666 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
667 DoublePrecision},
668 "sign"},
669 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
670 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
671 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
672 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
673 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
674 {{"exp", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14675 {{"float", {{"i", DftInt}}, DftReal}, "real", true},
peter klauslera70f5962018-10-04 20:43:33676 {{"iabs", {{"a", DftInt}}, DftInt}, "abs"},
677 {{"idim", {{"x", DftInt}, {"y", DftInt}}, DftInt}, "dim"},
peter klauslerad9aede2018-10-11 21:51:14678 {{"idint", {{"a", DoublePrecision}}, DftInt}, "int", true},
peter klauslera70f5962018-10-04 20:43:33679 {{"idnint", {{"a", DoublePrecision}}, DftInt}, "nint"},
peter klauslerad9aede2018-10-11 21:51:14680 {{"ifix", {{"a", DftReal}}, DftInt}, "int", true},
peter klauslera70f5962018-10-04 20:43:33681 {{"index", {{"string", DftChar}, {"substring", DftChar}}, DftInt}},
682 {{"isign", {{"a", DftInt}, {"b", DftInt}}, DftInt}, "sign"},
683 {{"len", {{"string", DftChar}}, DftInt}},
684 {{"log", {{"x", DftReal}}, DftReal}},
685 {{"log10", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14686 {{"max0",
687 {{"a1", DftInt}, {"a2", DftInt},
688 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
689 DftInt},
690 "max", true},
691 {{"max1",
692 {{"a1", DftReal}, {"a2", DftReal},
693 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
694 DftInt},
695 "max", true},
696 {{"min0",
697 {{"a1", DftInt}, {"a2", DftInt},
698 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
699 DftInt},
700 "min", true},
701 {{"min1",
702 {{"a1", DftReal}, {"a2", DftReal},
703 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
704 DftInt},
705 "min", true},
peter klauslera70f5962018-10-04 20:43:33706 {{"mod", {{"a", DftInt}, {"p", DftInt}}, DftInt}},
707 {{"nint", {{"a", DftReal}}, DftInt}},
708 {{"sign", {{"a", DftReal}, {"b", DftReal}}, DftReal}},
709 {{"sin", {{"x", DftReal}}, DftReal}},
710 {{"sinh", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14711 {{"sngl", {{"a", DoublePrecision}}, DftReal}, "real", true},
peter klauslera70f5962018-10-04 20:43:33712 {{"sqrt", {{"x", DftReal}}, DftReal}},
713 {{"tan", {{"x", DftReal}}, DftReal}},
714 {{"tanh", {{"x", DftReal}}, DftReal}},
peter klausler42b33da2018-09-29 00:02:11715};
716
peter klauslerad9aede2018-10-11 21:51:14717// TODO: Intrinsic subroutines
718// MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY,
719// EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT,
720// GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER,
721// RANDOM_SEED, SYSTEM_CLOCK
722// TODO: Atomic intrinsic subroutines: ATOMIC_ADD &al.
723// TODO: Collective intrinsic subroutines: CO_BROADCAST &al.
peter klausler42b33da2018-09-29 00:02:11724
peter klauslera70f5962018-10-04 20:43:33725// Intrinsic interface matching against the arguments of a particular
726// procedure reference.
peter klauslera70f5962018-10-04 20:43:33727std::optional<SpecificIntrinsic> IntrinsicInterface::Match(
peter klauslera62636f2018-10-08 22:35:19728 const CallCharacteristics &call, const IntrinsicTypeDefaultKinds &defaults,
peter klauslercb308d32018-10-05 18:32:54729 parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33730 // Attempt to construct a 1-1 correspondence between the dummy arguments in
731 // a particular intrinsic procedure's generic interface and the actual
732 // arguments in a procedure reference.
peter klauslera62636f2018-10-08 22:35:19733 const ActualArgument *actualForDummy[maxArguments];
peter klauslera70f5962018-10-04 20:43:33734 int dummies{0};
735 for (; dummies < maxArguments && dummy[dummies].keyword != nullptr;
736 ++dummies) {
737 actualForDummy[dummies] = nullptr;
738 }
peter klauslera62636f2018-10-08 22:35:19739 for (const ActualArgument &arg : call.argument) {
740 if (arg.isAlternateReturn) {
741 messages.Say(
742 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
peter klausler7bda1b32018-10-12 23:01:55743 name);
peter klauslera62636f2018-10-08 22:35:19744 return std::nullopt;
745 }
peter klauslera70f5962018-10-04 20:43:33746 bool found{false};
747 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
748 if (actualForDummy[dummyArgIndex] == nullptr) {
749 if (!arg.keyword.has_value() ||
750 *arg.keyword == dummy[dummyArgIndex].keyword) {
751 actualForDummy[dummyArgIndex] = &arg;
752 found = true;
753 break;
754 }
755 }
peter klausler7bda1b32018-10-12 23:01:55756 }
757 if (!found) {
758 if (arg.keyword.has_value()) {
759 messages.Say(*arg.keyword,
760 "unknown keyword argument to intrinsic '%s'"_err_en_US, name);
761 } else {
762 messages.Say(
763 "too many actual arguments for intrinsic '%s'"_err_en_US, name);
peter klauslera70f5962018-10-04 20:43:33764 }
peter klausler7bda1b32018-10-12 23:01:55765 return std::nullopt;
peter klauslera70f5962018-10-04 20:43:33766 }
767 }
768
769 // Check types and kinds of the actual arguments against the intrinsic's
770 // interface. Ensure that two or more arguments that have to have the same
771 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19772 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33773 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19774 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33775 bool hasDimArg{false};
776 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
777 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
778 if (d.typePattern.kindCode == KindCode::kindArg) {
779 CHECK(kindDummyArg == nullptr);
780 kindDummyArg = &d;
781 }
peter klauslera62636f2018-10-08 22:35:19782 const ActualArgument *arg{actualForDummy[dummyArgIndex]};
peter klauslera70f5962018-10-04 20:43:33783 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54784 if (d.optionality == Optionality::required) {
peter klausler7bda1b32018-10-12 23:01:55785 messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33786 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54787 } else {
788 continue;
peter klauslera70f5962018-10-04 20:43:33789 }
790 }
peter klauslera62636f2018-10-08 22:35:19791 std::optional<DynamicType> type{arg->GetType()};
792 if (!type.has_value()) {
793 CHECK(arg->Rank() == 0);
peter klauslercb308d32018-10-05 18:32:54794 if (d.typePattern.kindCode == KindCode::typeless ||
795 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33796 continue;
797 }
peter klausler7bda1b32018-10-12 23:01:55798 messages.Say(
799 "typeless (BOZ) not allowed for '%s=' argument"_err_en_US, d.keyword);
peter klauslercb308d32018-10-05 18:32:54800 return std::nullopt;
peter klauslera62636f2018-10-08 22:35:19801 } else if (!d.typePattern.categorySet.test(type->category)) {
peter klausler7bda1b32018-10-12 23:01:55802 messages.Say("actual argument for '%s=' has bad type '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19803 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33804 return std::nullopt; // argument has invalid type category
805 }
806 bool argOk{false};
807 switch (d.typePattern.kindCode) {
808 case KindCode::none:
809 case KindCode::typeless:
810 case KindCode::teamType: // TODO: TEAM_TYPE
811 argOk = false;
812 break;
813 case KindCode::defaultIntegerKind:
peter klauslera62636f2018-10-08 22:35:19814 argOk = type->kind == defaults.defaultIntegerKind;
peter klauslera70f5962018-10-04 20:43:33815 break;
816 case KindCode::defaultRealKind:
peter klauslera62636f2018-10-08 22:35:19817 argOk = type->kind == defaults.defaultRealKind;
peter klauslera70f5962018-10-04 20:43:33818 break;
819 case KindCode::doublePrecision:
peter klauslera62636f2018-10-08 22:35:19820 argOk = type->kind == defaults.defaultDoublePrecisionKind;
peter klauslera70f5962018-10-04 20:43:33821 break;
822 case KindCode::defaultCharKind:
peter klauslera62636f2018-10-08 22:35:19823 argOk = type->kind == defaults.defaultCharacterKind;
peter klauslera70f5962018-10-04 20:43:33824 break;
825 case KindCode::defaultLogicalKind:
peter klauslera62636f2018-10-08 22:35:19826 argOk = type->kind == defaults.defaultLogicalKind;
peter klauslera70f5962018-10-04 20:43:33827 break;
828 case KindCode::any: argOk = true; break;
829 case KindCode::kindArg:
peter klauslerf7f2a732018-10-09 19:07:29830 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33831 CHECK(kindArg == nullptr);
832 kindArg = arg;
peter klauslerf7f2a732018-10-09 19:07:29833 argOk = true;
peter klauslera70f5962018-10-04 20:43:33834 break;
835 case KindCode::dimArg:
peter klauslerf7f2a732018-10-09 19:07:29836 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33837 hasDimArg = true;
838 argOk = true;
839 break;
840 case KindCode::same:
841 if (sameArg == nullptr) {
842 sameArg = arg;
843 }
peter klauslera62636f2018-10-08 22:35:19844 argOk = *type == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33845 break;
846 case KindCode::effectiveKind:
847 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
848 "for intrinsic '%s'",
849 d.keyword, name);
850 break;
851 default: CRASH_NO_CASE;
852 }
853 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54854 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55855 "actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19856 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33857 return std::nullopt;
858 }
859 }
860
861 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:19862 const ActualArgument *arrayArg{nullptr};
863 const ActualArgument *knownArg{nullptr};
864 const ActualArgument *shapeArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33865 int elementalRank{0};
866 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
867 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
peter klauslera62636f2018-10-08 22:35:19868 if (const ActualArgument * arg{actualForDummy[dummyArgIndex]}) {
peter klauslera70f5962018-10-04 20:43:33869 if (arg->isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
peter klauslercb308d32018-10-05 18:32:54870 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55871 "assumed-rank array cannot be used for '%s=' argument"_err_en_US,
peter klauslercb308d32018-10-05 18:32:54872 d.keyword);
peter klauslera70f5962018-10-04 20:43:33873 return std::nullopt;
874 }
peter klauslera62636f2018-10-08 22:35:19875 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:33876 bool argOk{false};
877 switch (d.rank) {
878 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54879 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33880 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:19881 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:33882 }
peter klauslera62636f2018-10-08 22:35:19883 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:33884 break;
peter klauslera62636f2018-10-08 22:35:19885 case Rank::scalar: argOk = rank == 0; break;
886 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:33887 case Rank::shape:
888 CHECK(shapeArg == nullptr);
889 shapeArg = arg;
peter klauslerad9aede2018-10-11 21:51:14890 argOk = rank == 1 && arg->VectorSize().has_value();
peter klauslera70f5962018-10-04 20:43:33891 break;
peter klauslera62636f2018-10-08 22:35:19892 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:33893 case Rank::array:
peter klauslera62636f2018-10-08 22:35:19894 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:33895 if (!arrayArg) {
896 arrayArg = arg;
897 } else {
peter klauslera62636f2018-10-08 22:35:19898 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33899 }
900 break;
901 case Rank::known:
902 CHECK(knownArg == nullptr);
903 knownArg = arg;
904 argOk = true;
905 break;
906 case Rank::anyOrAssumedRank: argOk = true; break;
907 case Rank::conformable:
908 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19909 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33910 break;
911 case Rank::dimRemoved:
912 CHECK(arrayArg != nullptr);
913 if (hasDimArg) {
peter klauslera62636f2018-10-08 22:35:19914 argOk = rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33915 } else {
peter klauslera62636f2018-10-08 22:35:19916 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:33917 }
918 break;
peter klauslerad9aede2018-10-11 21:51:14919 case Rank::reduceOperation:
920 // TODO: Confirm that the argument is a pure function
921 // of two arguments with several constraints
922 CHECK(arrayArg != nullptr);
923 argOk = rank == 0;
924 break;
peter klauslera70f5962018-10-04 20:43:33925 case Rank::dimReduced:
926 case Rank::rankPlus1:
927 case Rank::shaped:
928 common::die("INTERNAL: result-only rank code appears on argument '%s' "
929 "for intrinsic '%s'",
930 d.keyword, name);
931 default: CRASH_NO_CASE;
932 }
933 if (!argOk) {
peter klausler7bda1b32018-10-12 23:01:55934 messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19935 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:33936 return std::nullopt;
937 }
938 }
939 }
940
peter klauslera70f5962018-10-04 20:43:33941 // Calculate the characteristics of the function result, if any
942 if (result.categorySet.empty()) {
943 CHECK(result.kindCode == KindCode::none);
944 return std::make_optional<SpecificIntrinsic>(name);
945 }
946 // Determine the result type.
947 DynamicType resultType{*result.categorySet.LeastElement(), 0};
948 switch (result.kindCode) {
949 case KindCode::defaultIntegerKind:
950 CHECK(result.categorySet == Int);
951 CHECK(resultType.category == TypeCategory::Integer);
952 resultType.kind = defaults.defaultIntegerKind;
953 break;
954 case KindCode::defaultRealKind:
955 CHECK(result.categorySet == CategorySet{resultType.category});
956 CHECK(Floating.test(resultType.category));
957 resultType.kind = defaults.defaultRealKind;
958 break;
959 case KindCode::doublePrecision:
960 CHECK(result.categorySet == Real);
961 CHECK(resultType.category == TypeCategory::Real);
962 resultType.kind = defaults.defaultDoublePrecisionKind;
963 break;
964 case KindCode::defaultCharKind:
965 CHECK(result.categorySet == Char);
966 CHECK(resultType.category == TypeCategory::Character);
967 resultType.kind = defaults.defaultCharacterKind;
968 break;
969 case KindCode::defaultLogicalKind:
970 CHECK(result.categorySet == Logical);
971 CHECK(resultType.category == TypeCategory::Logical);
972 resultType.kind = defaults.defaultLogicalKind;
973 break;
974 case KindCode::same:
975 CHECK(sameArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19976 resultType = *sameArg->GetType();
977 CHECK(result.categorySet.test(resultType.category));
peter klauslera70f5962018-10-04 20:43:33978 break;
979 case KindCode::effectiveKind:
980 CHECK(kindDummyArg != nullptr);
981 CHECK(result.categorySet == CategorySet{resultType.category});
982 if (kindArg != nullptr) {
peter klauslerf7f2a732018-10-09 19:07:29983 if (auto *jExpr{std::get_if<Expr<SomeInteger>>(&kindArg->value->u)}) {
984 CHECK(jExpr->Rank() == 0);
985 if (auto value{jExpr->ScalarValue()}) {
986 if (auto code{value->ToInt64()}) {
987 if (IsValidKindOfIntrinsicType(resultType.category, *code)) {
988 resultType.kind = *code;
989 break;
990 }
991 }
992 }
993 }
peter klausler7bda1b32018-10-12 23:01:55994 messages.Say("'kind=' argument must be a constant scalar integer "
peter klauslerf7f2a732018-10-09 19:07:29995 "whose value is a supported kind for the "
996 "intrinsic result type"_err_en_US);
997 return std::nullopt;
peter klauslercb308d32018-10-05 18:32:54998 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
peter klauslera70f5962018-10-04 20:43:33999 CHECK(sameArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191000 resultType = *sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:331001 } else {
peter klauslercb308d32018-10-05 18:32:541002 CHECK(
1003 kindDummyArg->optionality == Optionality::defaultsToDefaultForResult);
peter klauslera70f5962018-10-04 20:43:331004 resultType.kind = defaults.DefaultKind(resultType.category);
1005 }
1006 break;
peter klauslerf7f2a732018-10-09 19:07:291007 case KindCode::likeMultiply:
1008 CHECK(dummies >= 2);
1009 CHECK(actualForDummy[0] != nullptr);
1010 CHECK(actualForDummy[1] != nullptr);
1011 resultType = actualForDummy[0]->GetType()->ResultTypeForMultiply(
1012 *actualForDummy[1]->GetType());
1013 break;
peter klauslera70f5962018-10-04 20:43:331014 case KindCode::typeless:
1015 case KindCode::teamType:
1016 case KindCode::any:
1017 case KindCode::kindArg:
1018 case KindCode::dimArg:
1019 common::die(
1020 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
1021 break;
1022 default: CRASH_NO_CASE;
1023 }
1024
peter klauslerf7f2a732018-10-09 19:07:291025 // At this point, the call is acceptable.
peter klauslera70f5962018-10-04 20:43:331026 // Determine the rank of the function result.
1027 int resultRank{0};
1028 switch (rank) {
1029 case Rank::elemental: resultRank = elementalRank; break;
1030 case Rank::scalar: resultRank = 0; break;
1031 case Rank::vector: resultRank = 1; break;
1032 case Rank::matrix: resultRank = 2; break;
peter klauslerf7f2a732018-10-09 19:07:291033 case Rank::conformable:
1034 CHECK(arrayArg != nullptr);
1035 resultRank = arrayArg->Rank();
1036 break;
peter klauslera70f5962018-10-04 20:43:331037 case Rank::dimReduced:
1038 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191039 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:331040 break;
1041 case Rank::rankPlus1:
1042 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191043 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:331044 break;
1045 case Rank::shaped:
1046 CHECK(shapeArg != nullptr);
peter klauslerad9aede2018-10-11 21:51:141047 {
1048 std::optional<int> shapeLen{shapeArg->VectorSize()};
1049 CHECK(shapeLen.has_value());
1050 resultRank = *shapeLen;
1051 }
peter klauslera70f5962018-10-04 20:43:331052 break;
peter klauslercb308d32018-10-05 18:32:541053 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331054 case Rank::shape:
1055 case Rank::array:
1056 case Rank::known:
1057 case Rank::anyOrAssumedRank:
peter klauslera70f5962018-10-04 20:43:331058 case Rank::dimRemoved:
peter klauslerad9aede2018-10-11 21:51:141059 case Rank::reduceOperation:
peter klauslera70f5962018-10-04 20:43:331060 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
1061 break;
1062 default: CRASH_NO_CASE;
1063 }
1064 CHECK(resultRank >= 0);
1065
1066 return std::make_optional<SpecificIntrinsic>(
1067 name, elementalRank > 0, resultType, resultRank);
1068}
1069
peter klauslera62636f2018-10-08 22:35:191070struct IntrinsicProcTable::Implementation {
1071 explicit Implementation(const IntrinsicTypeDefaultKinds &dfts)
peter klauslera70f5962018-10-04 20:43:331072 : defaults{dfts} {
1073 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
1074 genericFuncs.insert(std::make_pair(std::string{f.name}, &f));
1075 }
1076 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
1077 specificFuncs.insert(std::make_pair(std::string{f.name}, &f));
1078 }
1079 }
peter klausler42b33da2018-09-29 00:02:111080
peter klauslercb308d32018-10-05 18:32:541081 std::optional<SpecificIntrinsic> Probe(
1082 const CallCharacteristics &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:531083
peter klauslera62636f2018-10-08 22:35:191084 IntrinsicTypeDefaultKinds defaults;
peter klauslera70f5962018-10-04 20:43:331085 std::multimap<std::string, const IntrinsicInterface *> genericFuncs;
1086 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs;
peter klausler7bda1b32018-10-12 23:01:551087 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:111088};
1089
peter klauslercb308d32018-10-05 18:32:541090// Probe the configured intrinsic procedure pattern tables in search of a
1091// match for a given procedure reference.
peter klauslera62636f2018-10-08 22:35:191092std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
peter klauslercb308d32018-10-05 18:32:541093 const CallCharacteristics &call,
1094 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:531095 if (call.isSubroutineCall) {
1096 return std::nullopt; // TODO
1097 }
peter klausler7bda1b32018-10-12 23:01:551098 parser::Messages *finalBuffer{messages ? messages->messages() : nullptr};
peter klausler62425d62018-10-12 00:01:311099 // Probe the specific intrinsic function table first.
1100 parser::Messages specificBuffer;
1101 parser::ContextualMessages specificErrors{
1102 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551103 finalBuffer ? &specificBuffer : nullptr};
peter klausler75a32092018-10-05 16:57:531104 std::string name{call.name.ToString()};
1105 auto specificRange{specificFuncs.equal_range(name)};
1106 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klausler62425d62018-10-12 00:01:311107 if (auto specific{iter->second->Match(call, defaults, specificErrors)}) {
peter klauslerad9aede2018-10-11 21:51:141108 if (const char *genericName{iter->second->generic}) {
1109 specific->name = genericName;
1110 }
1111 specific->isRestrictedSpecific = iter->second->isRestrictedSpecific;
peter klausler75a32092018-10-05 16:57:531112 return specific;
1113 }
1114 }
peter klausler62425d62018-10-12 00:01:311115 // Probe the generic intrinsic function table next.
1116 parser::Messages genericBuffer;
1117 parser::ContextualMessages genericErrors{
1118 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551119 finalBuffer ? &genericBuffer : nullptr};
peter klausler62425d62018-10-12 00:01:311120 auto genericRange{genericFuncs.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531121 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klausler62425d62018-10-12 00:01:311122 if (auto specific{iter->second->Match(call, defaults, genericErrors)}) {
peter klausler75a32092018-10-05 16:57:531123 return specific;
1124 }
1125 }
peter klauslerad9aede2018-10-11 21:51:141126 // Special cases of intrinsic functions
peter klausler8efb8972018-10-10 17:48:121127 if (call.name.ToString() == "null") {
1128 if (call.argument.size() == 0) {
1129 // TODO: NULL() result type is determined by context
1130 // Can pass that context in, or return a token distinguishing
1131 // NULL, or represent NULL as a new kind of top-level expression
1132 } else if (call.argument.size() > 1) {
peter klausler62425d62018-10-12 00:01:311133 genericErrors.Say("too many arguments to NULL()"_err_en_US);
peter klausler8efb8972018-10-10 17:48:121134 } else if (call.argument[0].keyword.has_value() &&
1135 call.argument[0].keyword->ToString() != "mold") {
peter klausler62425d62018-10-12 00:01:311136 genericErrors.Say("unknown argument '%s' to NULL()"_err_en_US,
peter klausler8efb8972018-10-10 17:48:121137 call.argument[0].keyword->ToString().data());
1138 } else {
1139 // TODO: Argument must be pointer, procedure pointer, or allocatable.
1140 // Characteristics, including dynamic length type parameter values,
1141 // must be taken from the MOLD argument.
1142 }
1143 }
1144 // No match
peter klausler7bda1b32018-10-12 23:01:551145 if (finalBuffer) {
peter klausler62425d62018-10-12 00:01:311146 if (genericBuffer.empty()) {
peter klausler7bda1b32018-10-12 23:01:551147 finalBuffer->Annex(std::move(specificBuffer));
peter klausler62425d62018-10-12 00:01:311148 } else {
peter klausler7bda1b32018-10-12 23:01:551149 finalBuffer->Annex(std::move(genericBuffer));
peter klausler62425d62018-10-12 00:01:311150 }
peter klauslercb308d32018-10-05 18:32:541151 }
peter klausler75a32092018-10-05 16:57:531152 return std::nullopt;
1153}
1154
peter klauslera62636f2018-10-08 22:35:191155IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:541156 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:111157 delete impl_;
1158 impl_ = nullptr;
1159}
1160
peter klauslera62636f2018-10-08 22:35:191161IntrinsicProcTable IntrinsicProcTable::Configure(
1162 const IntrinsicTypeDefaultKinds &defaults) {
1163 IntrinsicProcTable result;
1164 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:111165 return result;
1166}
1167
peter klauslera62636f2018-10-08 22:35:191168std::optional<SpecificIntrinsic> IntrinsicProcTable::Probe(
peter klauslercb308d32018-10-05 18:32:541169 const CallCharacteristics &call,
1170 parser::ContextualMessages *messages) const {
peter klauslera62636f2018-10-08 22:35:191171 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klauslercb308d32018-10-05 18:32:541172 return impl_->Probe(call, messages);
peter klausler42b33da2018-09-29 00:02:111173}
peter klauslerad9aede2018-10-11 21:51:141174
1175std::ostream &SpecificIntrinsic::Dump(std::ostream &o) const {
1176 return o << name;
1177}
peter klausler7bda1b32018-10-12 23:01:551178
1179std::ostream &TypePattern::Dump(std::ostream &o) const {
1180 if (categorySet == AnyType) {
1181 o << "any type";
1182 } else {
1183 const char *sep = "";
1184 auto set{categorySet};
1185 while (auto least{set.LeastElement()}) {
1186 o << sep << EnumToString(*least);
1187 sep = " or ";
1188 set.reset(*least);
1189 }
1190 }
1191 o << '(' << EnumToString(kindCode) << ')';
1192 return o;
1193}
1194
1195std::ostream &IntrinsicDummyArgument::Dump(std::ostream &o) const {
1196 if (keyword) {
1197 o << keyword << '=';
1198 }
1199 return typePattern.Dump(o)
1200 << ' ' << EnumToString(rank) << ' ' << EnumToString(optionality);
1201}
1202
1203std::ostream &IntrinsicInterface::Dump(std::ostream &o) const {
1204 o << name;
1205 char sep{'('};
1206 for (const auto &d : dummy) {
1207 if (d.typePattern.kindCode == KindCode::none) {
1208 break;
1209 }
1210 d.Dump(o << sep);
1211 sep = ',';
1212 }
1213 if (sep == '(') {
1214 o << "()";
1215 }
1216 return result.Dump(o << " -> ") << ' ' << EnumToString(rank);
1217}
1218
1219std::ostream &IntrinsicProcTable::Implementation::Dump(std::ostream &o) const {
1220 o << "generic intrinsic functions:\n";
1221 for (const auto &iter : genericFuncs) {
1222 iter.second->Dump(o << iter.first << ": ") << '\n';
1223 }
1224 o << "specific intrinsic functions:\n";
1225 for (const auto &iter : specificFuncs) {
1226 iter.second->Dump(o << iter.first << ": ");
1227 if (const char *g{iter.second->generic}) {
1228 o << " -> " << g;
1229 }
1230 o << '\n';
1231 }
1232 return o;
1233}
1234
1235std::ostream &IntrinsicProcTable::Dump(std::ostream &o) const {
1236 return impl_->Dump(o);
1237}
1238
peter klausler42b33da2018-09-29 00:02:111239} // namespace Fortran::evaluate