blob: ba774a016d76c1f4b56a5f5d074ed561d5e5cbe0 [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 klauslerbf339f82018-10-15 22:28:4721#include "../semantics/default-kinds.h"
peter klauslera70f5962018-10-04 20:43:3322#include <map>
peter klausler7bda1b32018-10-12 23:01:5523#include <ostream>
24#include <sstream>
peter klauslera70f5962018-10-04 20:43:3325#include <string>
26#include <utility>
peter klausler42b33da2018-09-29 00:02:1127
peter klauslercb308d32018-10-05 18:32:5428using namespace Fortran::parser::literals;
29
peter klausler42b33da2018-09-29 00:02:1130namespace Fortran::evaluate {
31
32using common::TypeCategory;
33
peter klauslera70f5962018-10-04 20:43:3334// This file defines the supported intrinsic procedures and implements
35// their recognition and validation. It is largely table-driven. See
36// documentation/intrinsics.md and section 16 of the Fortran 2018 standard
37// for full details on each of the intrinsics. Be advised, they have
38// complicated details, and the design of these tables has to accommodate
39// that complexity.
40
peter klausler42b33da2018-09-29 00:02:1141// Dummy arguments to generic intrinsic procedures are each specified by
peter klauslera70f5962018-10-04 20:43:3342// their keyword name (rarely used, but always defined), allowable type
peter klauslercb308d32018-10-05 18:32:5443// categories, a kind pattern, a rank pattern, and information about
44// optionality and defaults. The kind and rank patterns are represented
45// here with code values that are significant to the matching/validation engine.
peter klausler42b33da2018-09-29 00:02:1146
peter klauslera70f5962018-10-04 20:43:3347// These are small bit-sets of type category enumerators.
48// Note that typeless (BOZ literal) values don't have a distinct type category.
49// These typeless arguments are represented in the tables as if they were
50// INTEGER with a special "typeless" kind code. Arguments of intrinsic types
peter klauslercb308d32018-10-05 18:32:5451// that can also be be typeless values are encoded with an "elementalOrBOZ"
52// rank pattern.
peter klauslera70f5962018-10-04 20:43:3353using CategorySet = common::EnumSet<TypeCategory, 8>;
peter klausler51b09b62018-10-15 19:17:3054static constexpr CategorySet IntType{TypeCategory::Integer};
55static constexpr CategorySet RealType{TypeCategory::Real};
56static constexpr CategorySet ComplexType{TypeCategory::Complex};
57static constexpr CategorySet CharType{TypeCategory::Character};
58static constexpr CategorySet LogicalType{TypeCategory::Logical};
59static constexpr CategorySet IntOrRealType{IntType | RealType};
60static constexpr CategorySet FloatingType{RealType | ComplexType};
61static constexpr CategorySet NumericType{IntType | RealType | ComplexType};
62static constexpr CategorySet RelatableType{IntType | RealType | CharType};
peter klauslera70f5962018-10-04 20:43:3363static constexpr CategorySet IntrinsicType{
peter klausler51b09b62018-10-15 19:17:3064 IntType | RealType | ComplexType | CharType | LogicalType};
peter klauslera70f5962018-10-04 20:43:3365static constexpr CategorySet AnyType{
66 IntrinsicType | CategorySet{TypeCategory::Derived}};
peter klausler42b33da2018-09-29 00:02:1167
peter klausler7bda1b32018-10-12 23:01:5568ENUM_CLASS(KindCode, none, defaultIntegerKind,
69 defaultRealKind, // is also the default COMPLEX kind
70 doublePrecision, defaultCharKind, defaultLogicalKind,
71 any, // matches any kind value; each instance is independent
72 typeless, // BOZ literals are INTEGER with this kind
73 teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
74 kindArg, // this argument is KIND=
75 effectiveKind, // for function results: same "kindArg", possibly defaulted
76 dimArg, // this argument is DIM=
77 same, // match any kind; all "same" kinds must be equal
78 likeMultiply, // for DOT_PRODUCT and MATMUL
79)
peter klausler42b33da2018-09-29 00:02:1180
81struct TypePattern {
82 CategorySet categorySet;
peter klauslerb22d4942018-10-01 18:27:4583 KindCode kindCode{KindCode::none};
peter klausler7bda1b32018-10-12 23:01:5584 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:1185};
86
peter klauslera70f5962018-10-04 20:43:3387// Abbreviations for argument and result patterns in the intrinsic prototypes:
88
89// Match specific kinds of intrinsic types
peter klausler51b09b62018-10-15 19:17:3090static constexpr TypePattern DftInt{IntType, KindCode::defaultIntegerKind};
91static constexpr TypePattern DftReal{RealType, KindCode::defaultRealKind};
92static constexpr TypePattern DftComplex{ComplexType, KindCode::defaultRealKind};
93static constexpr TypePattern DftChar{CharType, KindCode::defaultCharKind};
94static constexpr TypePattern DftLogical{
95 LogicalType, KindCode::defaultLogicalKind};
96static constexpr TypePattern BOZ{IntType, KindCode::typeless};
97static constexpr TypePattern TEAM_TYPE{IntType, KindCode::teamType};
98static constexpr TypePattern DoublePrecision{
99 RealType, KindCode::doublePrecision};
peter klauslera70f5962018-10-04 20:43:33100
101// Match any kind of some intrinsic or derived types
peter klausler51b09b62018-10-15 19:17:30102static constexpr TypePattern AnyInt{IntType, KindCode::any};
103static constexpr TypePattern AnyReal{RealType, KindCode::any};
104static constexpr TypePattern AnyIntOrReal{IntOrRealType, KindCode::any};
105static constexpr TypePattern AnyComplex{ComplexType, KindCode::any};
106static constexpr TypePattern AnyNumeric{NumericType, KindCode::any};
107static constexpr TypePattern AnyChar{CharType, KindCode::any};
108static constexpr TypePattern AnyLogical{LogicalType, KindCode::any};
109static constexpr TypePattern AnyRelatable{RelatableType, KindCode::any};
peter klauslerf7f2a732018-10-09 19:07:29110static constexpr TypePattern Anything{AnyType, KindCode::any};
peter klauslera70f5962018-10-04 20:43:33111
112// Match some kind of some intrinsic type(s); all "Same" values must match,
113// even when not in the same category (e.g., SameComplex and SameReal).
114// Can be used to specify a result so long as at least one argument is
115// a "Same".
peter klausler51b09b62018-10-15 19:17:30116static constexpr TypePattern SameInt{IntType, KindCode::same};
117static constexpr TypePattern SameReal{RealType, KindCode::same};
118static constexpr TypePattern SameIntOrReal{IntOrRealType, KindCode::same};
119static constexpr TypePattern SameComplex{ComplexType, KindCode::same};
120static constexpr TypePattern SameFloating{FloatingType, KindCode::same};
121static constexpr TypePattern SameNumeric{NumericType, KindCode::same};
122static constexpr TypePattern SameChar{CharType, KindCode::same};
123static constexpr TypePattern SameLogical{LogicalType, KindCode::same};
124static constexpr TypePattern SameRelatable{RelatableType, KindCode::same};
peter klauslera70f5962018-10-04 20:43:33125static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
126static constexpr TypePattern SameDerivedType{
127 CategorySet{TypeCategory::Derived}, KindCode::same};
128static constexpr TypePattern SameType{AnyType, KindCode::same};
129
peter klauslerf7f2a732018-10-09 19:07:29130// For DOT_PRODUCT and MATMUL, the result type depends on the arguments
peter klausler51b09b62018-10-15 19:17:30131static constexpr TypePattern ResultLogical{LogicalType, KindCode::likeMultiply};
132static constexpr TypePattern ResultNumeric{NumericType, KindCode::likeMultiply};
peter klauslerf7f2a732018-10-09 19:07:29133
peter klauslera70f5962018-10-04 20:43:33134// Result types with known category and KIND=
peter klausler51b09b62018-10-15 19:17:30135static constexpr TypePattern KINDInt{IntType, KindCode::effectiveKind};
136static constexpr TypePattern KINDReal{RealType, KindCode::effectiveKind};
137static constexpr TypePattern KINDComplex{ComplexType, KindCode::effectiveKind};
138static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind};
139static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11140
141// The default rank pattern for dummy arguments and function results is
142// "elemental".
peter klausler7bda1b32018-10-12 23:01:55143ENUM_CLASS(Rank,
144 elemental, // scalar, or array that conforms with other array arguments
145 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
146 scalar, vector,
147 shape, // INTEGER vector of known length and no negative element
148 matrix,
149 array, // not scalar, rank is known and greater than zero
150 known, // rank is known and can be scalar
151 anyOrAssumedRank, // rank can be unknown
152 conformable, // scalar, or array of same rank & shape as "array" argument
153 reduceOperation, // a pure function with constraints for REDUCE
154 dimReduced, // scalar if no DIM= argument, else rank(array)-1
155 dimRemoved, // scalar, or rank(array)-1
156 rankPlus1, // rank(known)+1
157 shaped, // rank is length of SHAPE vector
158)
peter klausler42b33da2018-09-29 00:02:11159
peter klausler7bda1b32018-10-12 23:01:55160ENUM_CLASS(Optionality, required, optional,
161 defaultsToSameKind, // for MatchingDefaultKIND
162 defaultsToDefaultForResult, // for DefaultingKIND
163 repeats, // for MAX/MIN and their several variants
164)
peter klausler42b33da2018-09-29 00:02:11165
166struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45167 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11168 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33169 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54170 Optionality optionality{Optionality::required};
peter klausler7bda1b32018-10-12 23:01:55171 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11172};
173
peter klauslera70f5962018-10-04 20:43:33174// constexpr abbreviations for popular arguments:
175// DefaultingKIND is a KIND= argument whose default value is the appropriate
176// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54177static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30178 {IntType, KindCode::kindArg}, Rank::scalar,
peter klauslercb308d32018-10-05 18:32:54179 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33180// MatchingDefaultKIND is a KIND= argument whose default value is the
181// kind of any "Same" function argument (viz., the one whose kind pattern is
182// "same").
peter klauslercb308d32018-10-05 18:32:54183static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30184 {IntType, KindCode::kindArg}, Rank::scalar,
185 Optionality::defaultsToSameKind};
peter klauslera70f5962018-10-04 20:43:33186static constexpr IntrinsicDummyArgument OptionalDIM{
peter klausler51b09b62018-10-15 19:17:30187 "dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33188static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54189 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11190
191struct IntrinsicInterface {
192 static constexpr int maxArguments{7};
peter klauslerb22d4942018-10-01 18:27:45193 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11194 IntrinsicDummyArgument dummy[maxArguments];
195 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33196 Rank rank{Rank::elemental};
197 std::optional<SpecificIntrinsic> Match(const CallCharacteristics &,
peter klauslerbf339f82018-10-15 22:28:47198 const semantics::IntrinsicTypeDefaultKinds &,
peter klauslercb308d32018-10-05 18:32:54199 parser::ContextualMessages &messages) const;
peter klausler7bda1b32018-10-12 23:01:55200 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11201};
202
peter klausler94041d72018-10-15 20:39:51203// GENERIC INTRINSIC FUNCTION INTERFACES
204// Each entry in this table defines a pattern. Some intrinsic
205// functions have more than one such pattern. Besides the name
206// of the intrinsic function, each pattern has specifications for
207// the dummy arguments and for the result of the function.
208// The dummy argument patterns each have a name (this are from the
209// standard, but rarely appear in actual code), a type and kind
210// pattern, allowable ranks, and optionality indicators.
211// Be advised, the default rank pattern is "elemental".
peter klauslerb22d4942018-10-01 18:27:45212static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33213 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
214 {"abs", {{"a", SameComplex}}, SameReal},
peter klauslerad9aede2018-10-11 21:51:14215 {"achar", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
peter klauslera70f5962018-10-04 20:43:33216 {"acos", {{"x", SameFloating}}, SameFloating},
217 {"acosh", {{"x", SameFloating}}, SameFloating},
218 {"adjustl", {{"string", SameChar}}, SameChar},
219 {"adjustr", {{"string", SameChar}}, SameChar},
220 {"aimag", {{"x", SameComplex}}, SameReal},
221 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
222 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
223 Rank::dimReduced},
224 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
225 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
226 Rank::dimReduced},
227 {"asin", {{"x", SameFloating}}, SameFloating},
228 {"asinh", {{"x", SameFloating}}, SameFloating},
229 {"atan", {{"x", SameFloating}}, SameFloating},
230 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
231 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
232 {"atanh", {{"x", SameFloating}}, SameFloating},
233 {"bessel_j0", {{"x", SameReal}}, SameReal},
234 {"bessel_j1", {{"x", SameReal}}, SameReal},
235 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29236 {"bessel_jn",
237 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
238 {"x", SameReal, Rank::scalar}},
239 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33240 {"bessel_y0", {{"x", SameReal}}, SameReal},
241 {"bessel_y1", {{"x", SameReal}}, SameReal},
242 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29243 {"bessel_yn",
244 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
245 {"x", SameReal, Rank::scalar}},
246 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33247 {"bge",
peter klauslercb308d32018-10-05 18:32:54248 {{"i", AnyInt, Rank::elementalOrBOZ},
249 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33250 DftLogical},
251 {"bgt",
peter klauslercb308d32018-10-05 18:32:54252 {{"i", AnyInt, Rank::elementalOrBOZ},
253 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33254 DftLogical},
255 {"ble",
peter klauslercb308d32018-10-05 18:32:54256 {{"i", AnyInt, Rank::elementalOrBOZ},
257 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33258 DftLogical},
259 {"blt",
peter klauslercb308d32018-10-05 18:32:54260 {{"i", AnyInt, Rank::elementalOrBOZ},
261 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33262 DftLogical},
263 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DftLogical},
264 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
265 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
266 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11267 {"cmplx",
peter klauslercb308d32018-10-05 18:32:54268 {{"x", SameIntOrReal, Rank::elementalOrBOZ},
269 {"y", SameIntOrReal, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33270 KINDComplex},
peter klauslerf7f2a732018-10-09 19:07:29271 {"command_argument_count", {}, DftInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33272 {"conjg", {{"z", SameComplex}}, SameComplex},
273 {"cos", {{"x", SameFloating}}, SameFloating},
274 {"cosh", {{"x", SameFloating}}, SameFloating},
275 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
276 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11277 {"cshift",
peter klauslera70f5962018-10-04 20:43:33278 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
279 OptionalDIM},
280 SameType, Rank::array},
281 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
peter klauslerf7f2a732018-10-09 19:07:29282 {"dot_product",
283 {{"vector_a", AnyLogical, Rank::vector},
284 {"vector_b", AnyLogical, Rank::vector}},
285 ResultLogical, Rank::scalar},
286 {"dot_product",
287 {{"vector_a", AnyComplex, Rank::vector},
288 {"vector_b", AnyNumeric, Rank::vector}},
289 ResultNumeric, Rank::scalar}, // conjugates vector_a
290 {"dot_product",
291 {{"vector_a", AnyIntOrReal, Rank::vector},
292 {"vector_b", AnyNumeric, Rank::vector}},
293 ResultNumeric, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33294 {"dprod", {{"x", DftReal}, {"y", DftReal}}, DoublePrecision},
295 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54296 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33297 {"shift", AnyInt}},
298 SameInt},
299 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
300 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54301 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33302 {"shift", AnyInt}},
303 SameInt},
304 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11305 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33306 {{"array", SameIntrinsic, Rank::array},
307 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54308 {"boundary", SameIntrinsic, Rank::dimRemoved,
309 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33310 OptionalDIM},
311 SameIntrinsic, Rank::array},
peter klausler42b33da2018-09-29 00:02:11312 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33313 {{"array", SameDerivedType, Rank::array},
314 {"shift", AnyInt, Rank::dimRemoved},
315 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
316 SameDerivedType, Rank::array},
317 {"erf", {{"x", SameReal}}, SameReal},
318 {"erfc", {{"x", SameReal}}, SameReal},
319 {"erfc_scaled", {{"x", SameReal}}, SameReal},
320 {"exp", {{"x", SameFloating}}, SameFloating},
321 {"exponent", {{"x", AnyReal}}, DftInt},
peter klausler42b33da2018-09-29 00:02:11322 {"findloc",
peter klauslerad9aede2018-10-11 21:51:14323 {{"array", AnyNumeric, Rank::array},
324 {"value", AnyNumeric, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54325 DefaultingKIND,
326 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33327 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11328 {"findloc",
peter klauslera70f5962018-10-04 20:43:33329 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
330 OptionalDIM, OptionalMASK, DefaultingKIND,
peter klauslercb308d32018-10-05 18:32:54331 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33332 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11333 {"findloc",
peter klauslera70f5962018-10-04 20:43:33334 {{"array", AnyLogical, Rank::array},
335 {"value", AnyLogical, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54336 DefaultingKIND,
337 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33338 KINDInt, Rank::dimReduced},
339 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
340 {"fraction", {{"x", SameReal}}, SameReal},
341 {"gamma", {{"x", SameReal}}, SameReal},
342 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
343 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
344 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
345 SameInt, Rank::dimReduced},
346 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
347 SameInt, Rank::dimReduced},
348 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
349 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54350 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33351 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
352 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
353 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
354 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
355 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54356 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33357 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
358 {"image_status",
peter klauslercb308d32018-10-05 18:32:54359 {{"image", SameInt},
360 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33361 DftInt},
peter klausler42b33da2018-09-29 00:02:11362 {"index",
peter klauslera70f5962018-10-04 20:43:33363 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54364 {"back", AnyLogical, Rank::scalar, Optionality::optional},
365 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33366 KINDInt},
peter klauslercb308d32018-10-05 18:32:54367 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
368 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33369 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
370 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
371 {"ishftc",
372 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54373 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33374 SameInt},
375 {"is_iostat_end", {{"i", AnyInt}}, DftLogical},
376 {"is_iostat_eor", {{"i", AnyInt}}, DftLogical},
peter klauslerf7f2a732018-10-09 19:07:29377 {"lbound", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
378 KINDInt, Rank::vector},
379 {"lbound",
380 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler51b09b62018-10-15 19:17:30381 {"dim", {IntType, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
peter klauslerf7f2a732018-10-09 19:07:29382 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33383 {"leadz", {{"i", AnyInt}}, DftInt},
384 {"len", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
385 {"len_trim", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
386 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
387 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
388 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
389 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DftLogical},
390 {"log", {{"x", SameFloating}}, SameFloating},
391 {"log10", {{"x", SameReal}}, SameReal},
392 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
393 {"log_gamma", {{"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29394 {"matmul",
395 {{"array_a", AnyLogical, Rank::vector},
396 {"array_b", AnyLogical, Rank::matrix}},
397 ResultLogical, Rank::vector},
398 {"matmul",
399 {{"array_a", AnyLogical, Rank::matrix},
400 {"array_b", AnyLogical, Rank::vector}},
401 ResultLogical, Rank::vector},
402 {"matmul",
403 {{"array_a", AnyLogical, Rank::matrix},
404 {"array_b", AnyLogical, Rank::matrix}},
405 ResultLogical, Rank::matrix},
406 {"matmul",
407 {{"array_a", AnyNumeric, Rank::vector},
408 {"array_b", AnyNumeric, Rank::matrix}},
409 ResultNumeric, Rank::vector},
410 {"matmul",
411 {{"array_a", AnyNumeric, Rank::matrix},
412 {"array_b", AnyNumeric, Rank::vector}},
413 ResultNumeric, Rank::vector},
414 {"matmul",
415 {{"array_a", AnyNumeric, Rank::matrix},
416 {"array_b", AnyNumeric, Rank::matrix}},
417 ResultNumeric, Rank::matrix},
peter klauslera70f5962018-10-04 20:43:33418 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
419 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klauslerad9aede2018-10-11 21:51:14420 {"max",
421 {{"a1", SameRelatable}, {"a2", SameRelatable},
422 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
423 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11424 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33425 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54426 DefaultingKIND,
427 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33428 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11429 {"maxval",
peter klauslera70f5962018-10-04 20:43:33430 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
431 SameRelatable, Rank::dimReduced},
peter klauslerad9aede2018-10-11 21:51:14432 {"merge",
433 {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
434 SameType},
peter klausler42b33da2018-09-29 00:02:11435 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54436 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
437 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33438 SameInt},
439 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54440 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33441 SameInt},
peter klauslerad9aede2018-10-11 21:51:14442 {"min",
443 {{"a1", SameRelatable}, {"a2", SameRelatable},
444 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
445 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11446 {"minloc",
peter klauslera70f5962018-10-04 20:43:33447 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klauslercb308d32018-10-05 18:32:54448 DefaultingKIND,
449 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33450 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11451 {"minval",
peter klauslera70f5962018-10-04 20:43:33452 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
453 SameRelatable, Rank::dimReduced},
454 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
455 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
456 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
457 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
458 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
459 Rank::dimReduced},
460 {"not", {{"i", SameInt}}, SameInt},
peter klausler8efb8972018-10-10 17:48:12461 // NULL() is a special case handled in Probe() below
peter klausler42b33da2018-09-29 00:02:11462 {"out_of_range",
peter klauslerad9aede2018-10-11 21:51:14463 {{"x", AnyIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
peter klauslera70f5962018-10-04 20:43:33464 DftLogical},
465 {"out_of_range",
466 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54467 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33468 DftLogical},
469 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DftLogical},
peter klausler42b33da2018-09-29 00:02:11470 {"pack",
peter klauslera70f5962018-10-04 20:43:33471 {{"array", SameType, Rank::array},
472 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54473 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33474 SameType, Rank::vector},
475 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
476 Rank::dimReduced},
477 {"popcnt", {{"i", AnyInt}}, DftInt},
478 {"poppar", {{"i", AnyInt}}, DftInt},
peter klausler42b33da2018-09-29 00:02:11479 {"product",
peter klauslera70f5962018-10-04 20:43:33480 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
481 SameNumeric, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54482 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33483 KINDReal},
peter klauslerad9aede2018-10-11 21:51:14484 {"reduce",
485 {{"array", SameType, Rank::array},
486 {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
487 OptionalMASK, {"identity", SameType, Rank::scalar},
488 {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
489 SameType, Rank::dimReduced},
peter klausler24379cc2018-10-10 23:45:17490 {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
491 SameChar, Rank::scalar},
peter klausler42b33da2018-09-29 00:02:11492 {"reshape",
peter klauslera70f5962018-10-04 20:43:33493 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54494 {"pad", SameType, Rank::array, Optionality::optional},
495 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33496 SameType, Rank::shaped},
497 {"rrspacing", {{"x", SameReal}}, SameReal},
498 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11499 {"scan",
peter klauslera70f5962018-10-04 20:43:33500 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54501 {"back", AnyLogical, Rank::elemental, Optionality::optional},
502 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33503 KINDInt},
peter klausler24379cc2018-10-10 23:45:17504 {"selected_char_kind", {{"name", DftChar, Rank::scalar}}, DftInt,
505 Rank::scalar},
506 {"selected_int_kind", {{"r", AnyInt, Rank::scalar}}, DftInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14507 {"selected_real_kind",
508 {{"p", AnyInt, Rank::scalar},
509 {"r", AnyInt, Rank::scalar, Optionality::optional},
510 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
511 DftInt, Rank::scalar},
512 {"selected_real_kind",
513 {{"p", AnyInt, Rank::scalar, Optionality::optional},
514 {"r", AnyInt, Rank::scalar},
515 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
516 DftInt, Rank::scalar},
517 {"selected_real_kind",
518 {{"p", AnyInt, Rank::scalar, Optionality::optional},
519 {"r", AnyInt, Rank::scalar, Optionality::optional},
520 {"radix", AnyInt, Rank::scalar}},
521 DftInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33522 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler24379cc2018-10-10 23:45:17523 {"shape", {{"source", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
524 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33525 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
526 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
527 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
528 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
529 {"sin", {{"x", SameFloating}}, SameFloating},
530 {"sinh", {{"x", SameFloating}}, SameFloating},
peter klauslerf7f2a732018-10-09 19:07:29531 {"size", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
532 KINDInt, Rank::vector},
533 {"size",
534 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler51b09b62018-10-15 19:17:30535 {"dim", {IntType, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
peter klauslerf7f2a732018-10-09 19:07:29536 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33537 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11538 {"spread",
peter klauslera70f5962018-10-04 20:43:33539 {{"source", SameType, Rank::known},
peter klausler51b09b62018-10-15 19:17:30540 {"dim", {IntType, KindCode::dimArg}, Rank::scalar /*not optional*/},
peter klauslera70f5962018-10-04 20:43:33541 {"ncopies", AnyInt, Rank::scalar}},
542 SameType, Rank::rankPlus1},
543 {"sqrt", {{"x", SameFloating}}, SameFloating},
544 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
545 SameNumeric, Rank::dimReduced},
546 {"tan", {{"x", SameFloating}}, SameFloating},
547 {"tanh", {{"x", SameFloating}}, SameFloating},
548 {"trailz", {{"i", AnyInt}}, DftInt},
peter klauslerf7f2a732018-10-09 19:07:29549 {"transfer",
550 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::scalar}},
551 SameType, Rank::scalar},
552 {"transfer",
553 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::array}},
554 SameType, Rank::vector},
555 {"transfer",
556 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::known},
557 {"size", AnyInt, Rank::scalar}},
558 SameType, Rank::vector},
559 {"transpose", {{"matrix", SameType, Rank::matrix}}, SameType, Rank::matrix},
peter klauslerad9aede2018-10-11 21:51:14560 {"trim", {{"string", SameChar, Rank::scalar}}, SameChar, Rank::scalar},
peter klauslerf7f2a732018-10-09 19:07:29561 {"ubound", {{"array", Anything, Rank::anyOrAssumedRank}, DefaultingKIND},
562 KINDInt, Rank::vector},
563 {"ubound",
564 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler51b09b62018-10-15 19:17:30565 {"dim", {IntType, KindCode::dimArg}, Rank::scalar}, DefaultingKIND},
peter klauslerf7f2a732018-10-09 19:07:29566 KINDInt, Rank::scalar},
567 {"unpack",
568 {{"vector", SameType, Rank::vector}, {"mask", AnyLogical, Rank::array},
569 {"field", SameType, Rank::conformable}},
570 SameType, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11571 {"verify",
peter klauslera70f5962018-10-04 20:43:33572 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54573 {"back", AnyLogical, Rank::elemental, Optionality::optional},
574 DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33575 KINDInt},
peter klausler42b33da2018-09-29 00:02:11576};
577
peter klausler8efb8972018-10-10 17:48:12578// TODO: Coarray intrinsic functions
peter klauslerad9aede2018-10-11 21:51:14579// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
580// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
581// COSHAPE
peter klausler8efb8972018-10-10 17:48:12582// TODO: Object characteristic inquiry functions
peter klauslerad9aede2018-10-11 21:51:14583// ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS,
584// PRESENT, RANK, SAME_TYPE, STORAGE_SIZE
585// TODO: Type inquiry intrinsic functions - these return constants
586// BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT,
587// NEW_LINE, PRECISION, RADIX, RANGE, TINY
588// TODO: Non-standard intrinsic functions
589// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
590// COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL,
591// DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC,
592// QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM,
593// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
594// MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
595// IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
596// EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
597// probably more (these are PGI + Intel, possibly incomplete)
peter klausler42b33da2018-09-29 00:02:11598
599struct SpecificIntrinsicInterface : public IntrinsicInterface {
600 const char *generic{nullptr};
peter klauslerad9aede2018-10-11 21:51:14601 bool isRestrictedSpecific{
602 false}; // when true, can only be called, not passed
peter klausler42b33da2018-09-29 00:02:11603};
604
peter klauslerb22d4942018-10-01 18:27:45605static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33606 {{"abs", {{"a", DftReal}}, DftReal}},
607 {{"acos", {{"x", DftReal}}, DftReal}},
608 {{"aimag", {{"z", DftComplex}}, DftReal}},
609 {{"aint", {{"a", DftReal}}, DftReal}},
610 {{"alog", {{"x", DftReal}}, DftReal}, "log"},
611 {{"alog10", {{"x", DftReal}}, DftReal}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14612 {{"amax0",
613 {{"a1", DftInt}, {"a2", DftInt},
614 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
615 DftReal},
616 "max", true},
617 {{"amax1",
618 {{"a1", DftReal}, {"a2", DftReal},
619 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
620 DftReal},
621 "max", true},
622 {{"amin0",
623 {{"a1", DftInt}, {"a2", DftInt},
624 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
625 DftReal},
626 "min", true},
627 {{"amin1",
628 {{"a1", DftReal}, {"a2", DftReal},
629 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
630 DftReal},
631 "min", true},
peter klauslera70f5962018-10-04 20:43:33632 {{"amod", {{"a", DftReal}, {"p", DftReal}}, DftReal}, "mod"},
633 {{"anint", {{"a", DftReal}}, DftReal}},
634 {{"asin", {{"x", DftReal}}, DftReal}},
635 {{"atan", {{"x", DftReal}}, DftReal}},
636 {{"atan2", {{"y", DftReal}, {"x", DftReal}}, DftReal}},
637 {{"cabs", {{"a", DftComplex}}, DftReal}, "abs"},
638 {{"ccos", {{"a", DftComplex}}, DftComplex}, "cos"},
639 {{"cexp", {{"a", DftComplex}}, DftComplex}, "exp"},
640 {{"clog", {{"a", DftComplex}}, DftComplex}, "log"},
641 {{"conjg", {{"a", DftComplex}}, DftComplex}},
642 {{"cos", {{"x", DftReal}}, DftReal}},
643 {{"csin", {{"a", DftComplex}}, DftComplex}, "sin"},
644 {{"csqrt", {{"a", DftComplex}}, DftComplex}, "sqrt"},
645 {{"ctan", {{"a", DftComplex}}, DftComplex}, "tan"},
646 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
647 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
648 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
649 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
650 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
651 DoublePrecision},
652 "atan2"},
peter klauslerad9aede2018-10-11 21:51:14653 {{"dble", {{"a", DftReal}, DefaultingKIND}, DoublePrecision}, "real", true},
peter klauslera70f5962018-10-04 20:43:33654 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
655 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
656 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
657 DoublePrecision},
658 "dim"},
659 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
660 {{"dim", {{"x", DftReal}, {"y", DftReal}}, DftReal}},
661 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
662 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
663 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14664 {{"dmax1",
665 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
666 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
667 DoublePrecision},
668 "max", true},
669 {{"dmin1",
670 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
671 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
672 DoublePrecision},
673 "min", true},
peter klauslera70f5962018-10-04 20:43:33674 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
675 DoublePrecision},
676 "mod"},
677 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
678 {{"dprod", {{"x", DftReal}, {"y", DftReal}}, DoublePrecision}},
679 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
680 DoublePrecision},
681 "sign"},
682 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
683 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
684 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
685 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
686 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
687 {{"exp", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14688 {{"float", {{"i", DftInt}}, DftReal}, "real", true},
peter klauslera70f5962018-10-04 20:43:33689 {{"iabs", {{"a", DftInt}}, DftInt}, "abs"},
690 {{"idim", {{"x", DftInt}, {"y", DftInt}}, DftInt}, "dim"},
peter klauslerad9aede2018-10-11 21:51:14691 {{"idint", {{"a", DoublePrecision}}, DftInt}, "int", true},
peter klauslera70f5962018-10-04 20:43:33692 {{"idnint", {{"a", DoublePrecision}}, DftInt}, "nint"},
peter klauslerad9aede2018-10-11 21:51:14693 {{"ifix", {{"a", DftReal}}, DftInt}, "int", true},
peter klauslera70f5962018-10-04 20:43:33694 {{"index", {{"string", DftChar}, {"substring", DftChar}}, DftInt}},
695 {{"isign", {{"a", DftInt}, {"b", DftInt}}, DftInt}, "sign"},
696 {{"len", {{"string", DftChar}}, DftInt}},
697 {{"log", {{"x", DftReal}}, DftReal}},
698 {{"log10", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14699 {{"max0",
700 {{"a1", DftInt}, {"a2", DftInt},
701 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
702 DftInt},
703 "max", true},
704 {{"max1",
705 {{"a1", DftReal}, {"a2", DftReal},
706 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
707 DftInt},
708 "max", true},
709 {{"min0",
710 {{"a1", DftInt}, {"a2", DftInt},
711 {"a3", DftInt, Rank::elemental, Optionality::repeats}},
712 DftInt},
713 "min", true},
714 {{"min1",
715 {{"a1", DftReal}, {"a2", DftReal},
716 {"a3", DftReal, Rank::elemental, Optionality::repeats}},
717 DftInt},
718 "min", true},
peter klauslera70f5962018-10-04 20:43:33719 {{"mod", {{"a", DftInt}, {"p", DftInt}}, DftInt}},
720 {{"nint", {{"a", DftReal}}, DftInt}},
721 {{"sign", {{"a", DftReal}, {"b", DftReal}}, DftReal}},
722 {{"sin", {{"x", DftReal}}, DftReal}},
723 {{"sinh", {{"x", DftReal}}, DftReal}},
peter klauslerad9aede2018-10-11 21:51:14724 {{"sngl", {{"a", DoublePrecision}}, DftReal}, "real", true},
peter klauslera70f5962018-10-04 20:43:33725 {{"sqrt", {{"x", DftReal}}, DftReal}},
726 {{"tan", {{"x", DftReal}}, DftReal}},
727 {{"tanh", {{"x", DftReal}}, DftReal}},
peter klausler42b33da2018-09-29 00:02:11728};
729
peter klauslerad9aede2018-10-11 21:51:14730// TODO: Intrinsic subroutines
731// MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY,
732// EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT,
733// GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER,
734// RANDOM_SEED, SYSTEM_CLOCK
735// TODO: Atomic intrinsic subroutines: ATOMIC_ADD &al.
736// TODO: Collective intrinsic subroutines: CO_BROADCAST &al.
peter klausler42b33da2018-09-29 00:02:11737
peter klauslera70f5962018-10-04 20:43:33738// Intrinsic interface matching against the arguments of a particular
739// procedure reference.
peter klauslera70f5962018-10-04 20:43:33740std::optional<SpecificIntrinsic> IntrinsicInterface::Match(
peter klauslerbf339f82018-10-15 22:28:47741 const CallCharacteristics &call,
742 const semantics::IntrinsicTypeDefaultKinds &defaults,
peter klauslercb308d32018-10-05 18:32:54743 parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33744 // Attempt to construct a 1-1 correspondence between the dummy arguments in
745 // a particular intrinsic procedure's generic interface and the actual
746 // arguments in a procedure reference.
peter klauslera62636f2018-10-08 22:35:19747 const ActualArgument *actualForDummy[maxArguments];
peter klauslera70f5962018-10-04 20:43:33748 int dummies{0};
749 for (; dummies < maxArguments && dummy[dummies].keyword != nullptr;
750 ++dummies) {
751 actualForDummy[dummies] = nullptr;
752 }
peter klausler94041d72018-10-15 20:39:51753 for (const ActualArgument &arg : call.arguments) {
peter klauslera62636f2018-10-08 22:35:19754 if (arg.isAlternateReturn) {
755 messages.Say(
756 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
peter klausler7bda1b32018-10-12 23:01:55757 name);
peter klauslera62636f2018-10-08 22:35:19758 return std::nullopt;
759 }
peter klauslera70f5962018-10-04 20:43:33760 bool found{false};
761 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
762 if (actualForDummy[dummyArgIndex] == nullptr) {
763 if (!arg.keyword.has_value() ||
764 *arg.keyword == dummy[dummyArgIndex].keyword) {
765 actualForDummy[dummyArgIndex] = &arg;
766 found = true;
767 break;
768 }
769 }
peter klausler7bda1b32018-10-12 23:01:55770 }
771 if (!found) {
772 if (arg.keyword.has_value()) {
773 messages.Say(*arg.keyword,
774 "unknown keyword argument to intrinsic '%s'"_err_en_US, name);
775 } else {
776 messages.Say(
777 "too many actual arguments for intrinsic '%s'"_err_en_US, name);
peter klauslera70f5962018-10-04 20:43:33778 }
peter klausler7bda1b32018-10-12 23:01:55779 return std::nullopt;
peter klauslera70f5962018-10-04 20:43:33780 }
781 }
782
783 // Check types and kinds of the actual arguments against the intrinsic's
784 // interface. Ensure that two or more arguments that have to have the same
785 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19786 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33787 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19788 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33789 bool hasDimArg{false};
790 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
791 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
792 if (d.typePattern.kindCode == KindCode::kindArg) {
793 CHECK(kindDummyArg == nullptr);
794 kindDummyArg = &d;
795 }
peter klauslera62636f2018-10-08 22:35:19796 const ActualArgument *arg{actualForDummy[dummyArgIndex]};
peter klauslera70f5962018-10-04 20:43:33797 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54798 if (d.optionality == Optionality::required) {
peter klausler7bda1b32018-10-12 23:01:55799 messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33800 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54801 } else {
802 continue;
peter klauslera70f5962018-10-04 20:43:33803 }
804 }
peter klauslera62636f2018-10-08 22:35:19805 std::optional<DynamicType> type{arg->GetType()};
806 if (!type.has_value()) {
807 CHECK(arg->Rank() == 0);
peter klauslercb308d32018-10-05 18:32:54808 if (d.typePattern.kindCode == KindCode::typeless ||
809 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33810 continue;
811 }
peter klausler7bda1b32018-10-12 23:01:55812 messages.Say(
813 "typeless (BOZ) not allowed for '%s=' argument"_err_en_US, d.keyword);
peter klauslercb308d32018-10-05 18:32:54814 return std::nullopt;
peter klauslera62636f2018-10-08 22:35:19815 } else if (!d.typePattern.categorySet.test(type->category)) {
peter klausler7bda1b32018-10-12 23:01:55816 messages.Say("actual argument for '%s=' has bad type '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19817 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33818 return std::nullopt; // argument has invalid type category
819 }
820 bool argOk{false};
821 switch (d.typePattern.kindCode) {
822 case KindCode::none:
823 case KindCode::typeless:
824 case KindCode::teamType: // TODO: TEAM_TYPE
825 argOk = false;
826 break;
827 case KindCode::defaultIntegerKind:
peter klauslerbf339f82018-10-15 22:28:47828 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33829 break;
830 case KindCode::defaultRealKind:
peter klauslerbf339f82018-10-15 22:28:47831 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Real);
peter klauslera70f5962018-10-04 20:43:33832 break;
833 case KindCode::doublePrecision:
peter klauslerbf339f82018-10-15 22:28:47834 argOk = type->kind == defaults.doublePrecisionKind();
peter klauslera70f5962018-10-04 20:43:33835 break;
836 case KindCode::defaultCharKind:
peter klauslerbf339f82018-10-15 22:28:47837 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Character);
peter klauslera70f5962018-10-04 20:43:33838 break;
839 case KindCode::defaultLogicalKind:
peter klauslerbf339f82018-10-15 22:28:47840 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Logical);
peter klauslera70f5962018-10-04 20:43:33841 break;
842 case KindCode::any: argOk = true; break;
843 case KindCode::kindArg:
peter klauslerf7f2a732018-10-09 19:07:29844 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33845 CHECK(kindArg == nullptr);
846 kindArg = arg;
peter klauslerf7f2a732018-10-09 19:07:29847 argOk = true;
peter klauslera70f5962018-10-04 20:43:33848 break;
849 case KindCode::dimArg:
peter klauslerf7f2a732018-10-09 19:07:29850 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33851 hasDimArg = true;
852 argOk = true;
853 break;
854 case KindCode::same:
855 if (sameArg == nullptr) {
856 sameArg = arg;
857 }
peter klauslera62636f2018-10-08 22:35:19858 argOk = *type == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33859 break;
860 case KindCode::effectiveKind:
861 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
862 "for intrinsic '%s'",
863 d.keyword, name);
864 break;
865 default: CRASH_NO_CASE;
866 }
867 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54868 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55869 "actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19870 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33871 return std::nullopt;
872 }
873 }
874
875 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:19876 const ActualArgument *arrayArg{nullptr};
877 const ActualArgument *knownArg{nullptr};
878 const ActualArgument *shapeArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33879 int elementalRank{0};
880 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
881 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
peter klauslera62636f2018-10-08 22:35:19882 if (const ActualArgument * arg{actualForDummy[dummyArgIndex]}) {
peter klauslera70f5962018-10-04 20:43:33883 if (arg->isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
peter klauslercb308d32018-10-05 18:32:54884 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55885 "assumed-rank array cannot be used for '%s=' argument"_err_en_US,
peter klauslercb308d32018-10-05 18:32:54886 d.keyword);
peter klauslera70f5962018-10-04 20:43:33887 return std::nullopt;
888 }
peter klauslera62636f2018-10-08 22:35:19889 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:33890 bool argOk{false};
891 switch (d.rank) {
892 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54893 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33894 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:19895 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:33896 }
peter klauslera62636f2018-10-08 22:35:19897 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:33898 break;
peter klauslera62636f2018-10-08 22:35:19899 case Rank::scalar: argOk = rank == 0; break;
900 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:33901 case Rank::shape:
902 CHECK(shapeArg == nullptr);
903 shapeArg = arg;
peter klauslerad9aede2018-10-11 21:51:14904 argOk = rank == 1 && arg->VectorSize().has_value();
peter klauslera70f5962018-10-04 20:43:33905 break;
peter klauslera62636f2018-10-08 22:35:19906 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:33907 case Rank::array:
peter klauslera62636f2018-10-08 22:35:19908 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:33909 if (!arrayArg) {
910 arrayArg = arg;
911 } else {
peter klauslera62636f2018-10-08 22:35:19912 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33913 }
914 break;
915 case Rank::known:
916 CHECK(knownArg == nullptr);
917 knownArg = arg;
918 argOk = true;
919 break;
920 case Rank::anyOrAssumedRank: argOk = true; break;
921 case Rank::conformable:
922 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19923 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33924 break;
925 case Rank::dimRemoved:
926 CHECK(arrayArg != nullptr);
927 if (hasDimArg) {
peter klauslera62636f2018-10-08 22:35:19928 argOk = rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33929 } else {
peter klauslera62636f2018-10-08 22:35:19930 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:33931 }
932 break;
peter klauslerad9aede2018-10-11 21:51:14933 case Rank::reduceOperation:
934 // TODO: Confirm that the argument is a pure function
935 // of two arguments with several constraints
936 CHECK(arrayArg != nullptr);
937 argOk = rank == 0;
938 break;
peter klauslera70f5962018-10-04 20:43:33939 case Rank::dimReduced:
940 case Rank::rankPlus1:
941 case Rank::shaped:
942 common::die("INTERNAL: result-only rank code appears on argument '%s' "
943 "for intrinsic '%s'",
944 d.keyword, name);
945 default: CRASH_NO_CASE;
946 }
947 if (!argOk) {
peter klausler7bda1b32018-10-12 23:01:55948 messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19949 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:33950 return std::nullopt;
951 }
952 }
953 }
954
peter klauslera70f5962018-10-04 20:43:33955 // Calculate the characteristics of the function result, if any
956 if (result.categorySet.empty()) {
957 CHECK(result.kindCode == KindCode::none);
958 return std::make_optional<SpecificIntrinsic>(name);
959 }
960 // Determine the result type.
961 DynamicType resultType{*result.categorySet.LeastElement(), 0};
962 switch (result.kindCode) {
963 case KindCode::defaultIntegerKind:
peter klausler51b09b62018-10-15 19:17:30964 CHECK(result.categorySet == IntType);
peter klauslera70f5962018-10-04 20:43:33965 CHECK(resultType.category == TypeCategory::Integer);
peter klauslerbf339f82018-10-15 22:28:47966 resultType.kind = defaults.GetDefaultKind(TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33967 break;
968 case KindCode::defaultRealKind:
969 CHECK(result.categorySet == CategorySet{resultType.category});
peter klausler51b09b62018-10-15 19:17:30970 CHECK(FloatingType.test(resultType.category));
peter klauslerbf339f82018-10-15 22:28:47971 resultType.kind = defaults.GetDefaultKind(TypeCategory::Real);
peter klauslera70f5962018-10-04 20:43:33972 break;
973 case KindCode::doublePrecision:
peter klausler51b09b62018-10-15 19:17:30974 CHECK(result.categorySet == RealType);
peter klauslera70f5962018-10-04 20:43:33975 CHECK(resultType.category == TypeCategory::Real);
peter klauslerbf339f82018-10-15 22:28:47976 resultType.kind = defaults.doublePrecisionKind();
peter klauslera70f5962018-10-04 20:43:33977 break;
978 case KindCode::defaultCharKind:
peter klausler51b09b62018-10-15 19:17:30979 CHECK(result.categorySet == CharType);
peter klauslera70f5962018-10-04 20:43:33980 CHECK(resultType.category == TypeCategory::Character);
peter klauslerbf339f82018-10-15 22:28:47981 resultType.kind = defaults.GetDefaultKind(TypeCategory::Character);
peter klauslera70f5962018-10-04 20:43:33982 break;
983 case KindCode::defaultLogicalKind:
peter klausler51b09b62018-10-15 19:17:30984 CHECK(result.categorySet == LogicalType);
peter klauslera70f5962018-10-04 20:43:33985 CHECK(resultType.category == TypeCategory::Logical);
peter klauslerbf339f82018-10-15 22:28:47986 resultType.kind = defaults.GetDefaultKind(TypeCategory::Logical);
peter klauslera70f5962018-10-04 20:43:33987 break;
988 case KindCode::same:
989 CHECK(sameArg != nullptr);
peter klausler55df4a72018-10-12 23:25:39990 if (std::optional<DynamicType> aType{sameArg->GetType()}) {
991 if (result.categorySet.test(aType->category)) {
992 resultType = *aType;
993 } else {
994 resultType.kind = aType->kind;
995 }
996 }
peter klauslera70f5962018-10-04 20:43:33997 break;
998 case KindCode::effectiveKind:
999 CHECK(kindDummyArg != nullptr);
1000 CHECK(result.categorySet == CategorySet{resultType.category});
1001 if (kindArg != nullptr) {
peter klauslerf7f2a732018-10-09 19:07:291002 if (auto *jExpr{std::get_if<Expr<SomeInteger>>(&kindArg->value->u)}) {
1003 CHECK(jExpr->Rank() == 0);
1004 if (auto value{jExpr->ScalarValue()}) {
1005 if (auto code{value->ToInt64()}) {
1006 if (IsValidKindOfIntrinsicType(resultType.category, *code)) {
1007 resultType.kind = *code;
1008 break;
1009 }
1010 }
1011 }
1012 }
peter klausler7bda1b32018-10-12 23:01:551013 messages.Say("'kind=' argument must be a constant scalar integer "
peter klauslerf7f2a732018-10-09 19:07:291014 "whose value is a supported kind for the "
1015 "intrinsic result type"_err_en_US);
1016 return std::nullopt;
peter klauslercb308d32018-10-05 18:32:541017 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
peter klauslera70f5962018-10-04 20:43:331018 CHECK(sameArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191019 resultType = *sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:331020 } else {
peter klauslercb308d32018-10-05 18:32:541021 CHECK(
1022 kindDummyArg->optionality == Optionality::defaultsToDefaultForResult);
peter klauslerbf339f82018-10-15 22:28:471023 resultType.kind = defaults.GetDefaultKind(resultType.category);
peter klauslera70f5962018-10-04 20:43:331024 }
1025 break;
peter klauslerf7f2a732018-10-09 19:07:291026 case KindCode::likeMultiply:
1027 CHECK(dummies >= 2);
1028 CHECK(actualForDummy[0] != nullptr);
1029 CHECK(actualForDummy[1] != nullptr);
1030 resultType = actualForDummy[0]->GetType()->ResultTypeForMultiply(
1031 *actualForDummy[1]->GetType());
1032 break;
peter klauslera70f5962018-10-04 20:43:331033 case KindCode::typeless:
1034 case KindCode::teamType:
1035 case KindCode::any:
1036 case KindCode::kindArg:
1037 case KindCode::dimArg:
1038 common::die(
1039 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
1040 break;
1041 default: CRASH_NO_CASE;
1042 }
1043
peter klauslerf7f2a732018-10-09 19:07:291044 // At this point, the call is acceptable.
peter klauslera70f5962018-10-04 20:43:331045 // Determine the rank of the function result.
1046 int resultRank{0};
1047 switch (rank) {
1048 case Rank::elemental: resultRank = elementalRank; break;
1049 case Rank::scalar: resultRank = 0; break;
1050 case Rank::vector: resultRank = 1; break;
1051 case Rank::matrix: resultRank = 2; break;
peter klauslerf7f2a732018-10-09 19:07:291052 case Rank::conformable:
1053 CHECK(arrayArg != nullptr);
1054 resultRank = arrayArg->Rank();
1055 break;
peter klauslera70f5962018-10-04 20:43:331056 case Rank::dimReduced:
1057 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191058 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:331059 break;
1060 case Rank::rankPlus1:
1061 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191062 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:331063 break;
1064 case Rank::shaped:
1065 CHECK(shapeArg != nullptr);
peter klauslerad9aede2018-10-11 21:51:141066 {
1067 std::optional<int> shapeLen{shapeArg->VectorSize()};
1068 CHECK(shapeLen.has_value());
1069 resultRank = *shapeLen;
1070 }
peter klauslera70f5962018-10-04 20:43:331071 break;
peter klauslercb308d32018-10-05 18:32:541072 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331073 case Rank::shape:
1074 case Rank::array:
1075 case Rank::known:
1076 case Rank::anyOrAssumedRank:
peter klauslera70f5962018-10-04 20:43:331077 case Rank::dimRemoved:
peter klauslerad9aede2018-10-11 21:51:141078 case Rank::reduceOperation:
peter klauslera70f5962018-10-04 20:43:331079 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
1080 break;
1081 default: CRASH_NO_CASE;
1082 }
1083 CHECK(resultRank >= 0);
1084
1085 return std::make_optional<SpecificIntrinsic>(
1086 name, elementalRank > 0, resultType, resultRank);
1087}
1088
peter klauslera62636f2018-10-08 22:35:191089struct IntrinsicProcTable::Implementation {
peter klauslerbf339f82018-10-15 22:28:471090 explicit Implementation(const semantics::IntrinsicTypeDefaultKinds &dfts)
peter klauslera70f5962018-10-04 20:43:331091 : defaults{dfts} {
1092 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
1093 genericFuncs.insert(std::make_pair(std::string{f.name}, &f));
1094 }
1095 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
1096 specificFuncs.insert(std::make_pair(std::string{f.name}, &f));
1097 }
1098 }
peter klausler42b33da2018-09-29 00:02:111099
peter klauslercb308d32018-10-05 18:32:541100 std::optional<SpecificIntrinsic> Probe(
1101 const CallCharacteristics &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:531102
peter klauslerbf339f82018-10-15 22:28:471103 semantics::IntrinsicTypeDefaultKinds defaults;
peter klauslera70f5962018-10-04 20:43:331104 std::multimap<std::string, const IntrinsicInterface *> genericFuncs;
1105 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs;
peter klausler7bda1b32018-10-12 23:01:551106 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:111107};
1108
peter klauslercb308d32018-10-05 18:32:541109// Probe the configured intrinsic procedure pattern tables in search of a
1110// match for a given procedure reference.
peter klauslera62636f2018-10-08 22:35:191111std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
peter klauslercb308d32018-10-05 18:32:541112 const CallCharacteristics &call,
1113 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:531114 if (call.isSubroutineCall) {
1115 return std::nullopt; // TODO
1116 }
peter klausler7bda1b32018-10-12 23:01:551117 parser::Messages *finalBuffer{messages ? messages->messages() : nullptr};
peter klausler62425d62018-10-12 00:01:311118 // Probe the specific intrinsic function table first.
1119 parser::Messages specificBuffer;
1120 parser::ContextualMessages specificErrors{
1121 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551122 finalBuffer ? &specificBuffer : nullptr};
peter klausler75a32092018-10-05 16:57:531123 std::string name{call.name.ToString()};
1124 auto specificRange{specificFuncs.equal_range(name)};
1125 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klausler62425d62018-10-12 00:01:311126 if (auto specific{iter->second->Match(call, defaults, specificErrors)}) {
peter klauslerad9aede2018-10-11 21:51:141127 if (const char *genericName{iter->second->generic}) {
1128 specific->name = genericName;
1129 }
1130 specific->isRestrictedSpecific = iter->second->isRestrictedSpecific;
peter klausler75a32092018-10-05 16:57:531131 return specific;
1132 }
1133 }
peter klausler62425d62018-10-12 00:01:311134 // Probe the generic intrinsic function table next.
1135 parser::Messages genericBuffer;
1136 parser::ContextualMessages genericErrors{
1137 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551138 finalBuffer ? &genericBuffer : nullptr};
peter klausler62425d62018-10-12 00:01:311139 auto genericRange{genericFuncs.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531140 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klausler62425d62018-10-12 00:01:311141 if (auto specific{iter->second->Match(call, defaults, genericErrors)}) {
peter klausler75a32092018-10-05 16:57:531142 return specific;
1143 }
1144 }
peter klauslerad9aede2018-10-11 21:51:141145 // Special cases of intrinsic functions
peter klausler8efb8972018-10-10 17:48:121146 if (call.name.ToString() == "null") {
peter klausler94041d72018-10-15 20:39:511147 if (call.arguments.size() == 0) {
peter klausler8efb8972018-10-10 17:48:121148 // TODO: NULL() result type is determined by context
1149 // Can pass that context in, or return a token distinguishing
1150 // NULL, or represent NULL as a new kind of top-level expression
peter klausler94041d72018-10-15 20:39:511151 } else if (call.arguments.size() > 1) {
peter klausler62425d62018-10-12 00:01:311152 genericErrors.Say("too many arguments to NULL()"_err_en_US);
peter klausler94041d72018-10-15 20:39:511153 } else if (call.arguments[0].keyword.has_value() &&
1154 call.arguments[0].keyword->ToString() != "mold") {
peter klausler62425d62018-10-12 00:01:311155 genericErrors.Say("unknown argument '%s' to NULL()"_err_en_US,
peter klausler94041d72018-10-15 20:39:511156 call.arguments[0].keyword->ToString().data());
peter klausler8efb8972018-10-10 17:48:121157 } else {
1158 // TODO: Argument must be pointer, procedure pointer, or allocatable.
1159 // Characteristics, including dynamic length type parameter values,
1160 // must be taken from the MOLD argument.
1161 }
1162 }
1163 // No match
peter klausler7bda1b32018-10-12 23:01:551164 if (finalBuffer) {
peter klausler62425d62018-10-12 00:01:311165 if (genericBuffer.empty()) {
peter klausler7bda1b32018-10-12 23:01:551166 finalBuffer->Annex(std::move(specificBuffer));
peter klausler62425d62018-10-12 00:01:311167 } else {
peter klausler7bda1b32018-10-12 23:01:551168 finalBuffer->Annex(std::move(genericBuffer));
peter klausler62425d62018-10-12 00:01:311169 }
peter klauslercb308d32018-10-05 18:32:541170 }
peter klausler75a32092018-10-05 16:57:531171 return std::nullopt;
1172}
1173
peter klauslera62636f2018-10-08 22:35:191174IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:541175 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:111176 delete impl_;
1177 impl_ = nullptr;
1178}
1179
peter klauslera62636f2018-10-08 22:35:191180IntrinsicProcTable IntrinsicProcTable::Configure(
peter klauslerbf339f82018-10-15 22:28:471181 const semantics::IntrinsicTypeDefaultKinds &defaults) {
peter klauslera62636f2018-10-08 22:35:191182 IntrinsicProcTable result;
1183 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:111184 return result;
1185}
1186
peter klauslera62636f2018-10-08 22:35:191187std::optional<SpecificIntrinsic> IntrinsicProcTable::Probe(
peter klauslercb308d32018-10-05 18:32:541188 const CallCharacteristics &call,
1189 parser::ContextualMessages *messages) const {
peter klauslera62636f2018-10-08 22:35:191190 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klauslercb308d32018-10-05 18:32:541191 return impl_->Probe(call, messages);
peter klausler42b33da2018-09-29 00:02:111192}
peter klauslerad9aede2018-10-11 21:51:141193
1194std::ostream &SpecificIntrinsic::Dump(std::ostream &o) const {
1195 return o << name;
1196}
peter klausler7bda1b32018-10-12 23:01:551197
1198std::ostream &TypePattern::Dump(std::ostream &o) const {
1199 if (categorySet == AnyType) {
1200 o << "any type";
1201 } else {
1202 const char *sep = "";
1203 auto set{categorySet};
1204 while (auto least{set.LeastElement()}) {
1205 o << sep << EnumToString(*least);
1206 sep = " or ";
1207 set.reset(*least);
1208 }
1209 }
1210 o << '(' << EnumToString(kindCode) << ')';
1211 return o;
1212}
1213
1214std::ostream &IntrinsicDummyArgument::Dump(std::ostream &o) const {
1215 if (keyword) {
1216 o << keyword << '=';
1217 }
1218 return typePattern.Dump(o)
1219 << ' ' << EnumToString(rank) << ' ' << EnumToString(optionality);
1220}
1221
1222std::ostream &IntrinsicInterface::Dump(std::ostream &o) const {
1223 o << name;
1224 char sep{'('};
1225 for (const auto &d : dummy) {
1226 if (d.typePattern.kindCode == KindCode::none) {
1227 break;
1228 }
1229 d.Dump(o << sep);
1230 sep = ',';
1231 }
1232 if (sep == '(') {
1233 o << "()";
1234 }
1235 return result.Dump(o << " -> ") << ' ' << EnumToString(rank);
1236}
1237
1238std::ostream &IntrinsicProcTable::Implementation::Dump(std::ostream &o) const {
1239 o << "generic intrinsic functions:\n";
1240 for (const auto &iter : genericFuncs) {
1241 iter.second->Dump(o << iter.first << ": ") << '\n';
1242 }
1243 o << "specific intrinsic functions:\n";
1244 for (const auto &iter : specificFuncs) {
1245 iter.second->Dump(o << iter.first << ": ");
1246 if (const char *g{iter.second->generic}) {
1247 o << " -> " << g;
1248 }
1249 o << '\n';
1250 }
1251 return o;
1252}
1253
1254std::ostream &IntrinsicProcTable::Dump(std::ostream &o) const {
1255 return impl_->Dump(o);
1256}
1257
peter klausler42b33da2018-09-29 00:02:111258} // namespace Fortran::evaluate