blob: a575f2771c7d0e87900eb7194e6fad9241ed0113 [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 klausler7c402d92018-10-16 21:42:2290static constexpr TypePattern DefaultInt{IntType, KindCode::defaultIntegerKind};
91static constexpr TypePattern DefaultReal{RealType, KindCode::defaultRealKind};
92static constexpr TypePattern DefaultComplex{
93 ComplexType, KindCode::defaultRealKind};
94static constexpr TypePattern DefaultChar{CharType, KindCode::defaultCharKind};
95static constexpr TypePattern DefaultLogical{
peter klausler51b09b62018-10-15 19:17:3096 LogicalType, KindCode::defaultLogicalKind};
97static constexpr TypePattern BOZ{IntType, KindCode::typeless};
98static constexpr TypePattern TEAM_TYPE{IntType, KindCode::teamType};
99static constexpr TypePattern DoublePrecision{
100 RealType, KindCode::doublePrecision};
peter klauslera70f5962018-10-04 20:43:33101
102// Match any kind of some intrinsic or derived types
peter klausler51b09b62018-10-15 19:17:30103static constexpr TypePattern AnyInt{IntType, KindCode::any};
104static constexpr TypePattern AnyReal{RealType, KindCode::any};
105static constexpr TypePattern AnyIntOrReal{IntOrRealType, KindCode::any};
106static constexpr TypePattern AnyComplex{ComplexType, KindCode::any};
107static constexpr TypePattern AnyNumeric{NumericType, KindCode::any};
108static constexpr TypePattern AnyChar{CharType, KindCode::any};
109static constexpr TypePattern AnyLogical{LogicalType, KindCode::any};
110static constexpr TypePattern AnyRelatable{RelatableType, KindCode::any};
peter klauslerf7f2a732018-10-09 19:07:29111static constexpr TypePattern Anything{AnyType, KindCode::any};
peter klauslera70f5962018-10-04 20:43:33112
113// Match some kind of some intrinsic type(s); all "Same" values must match,
114// even when not in the same category (e.g., SameComplex and SameReal).
115// Can be used to specify a result so long as at least one argument is
116// a "Same".
peter klausler51b09b62018-10-15 19:17:30117static constexpr TypePattern SameInt{IntType, KindCode::same};
118static constexpr TypePattern SameReal{RealType, KindCode::same};
119static constexpr TypePattern SameIntOrReal{IntOrRealType, KindCode::same};
120static constexpr TypePattern SameComplex{ComplexType, KindCode::same};
121static constexpr TypePattern SameFloating{FloatingType, KindCode::same};
122static constexpr TypePattern SameNumeric{NumericType, KindCode::same};
123static constexpr TypePattern SameChar{CharType, KindCode::same};
124static constexpr TypePattern SameLogical{LogicalType, KindCode::same};
125static constexpr TypePattern SameRelatable{RelatableType, KindCode::same};
peter klauslera70f5962018-10-04 20:43:33126static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
127static constexpr TypePattern SameDerivedType{
128 CategorySet{TypeCategory::Derived}, KindCode::same};
129static constexpr TypePattern SameType{AnyType, KindCode::same};
130
peter klauslerf7f2a732018-10-09 19:07:29131// For DOT_PRODUCT and MATMUL, the result type depends on the arguments
peter klausler51b09b62018-10-15 19:17:30132static constexpr TypePattern ResultLogical{LogicalType, KindCode::likeMultiply};
133static constexpr TypePattern ResultNumeric{NumericType, KindCode::likeMultiply};
peter klauslerf7f2a732018-10-09 19:07:29134
peter klauslera70f5962018-10-04 20:43:33135// Result types with known category and KIND=
peter klausler51b09b62018-10-15 19:17:30136static constexpr TypePattern KINDInt{IntType, KindCode::effectiveKind};
137static constexpr TypePattern KINDReal{RealType, KindCode::effectiveKind};
138static constexpr TypePattern KINDComplex{ComplexType, KindCode::effectiveKind};
139static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind};
140static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11141
142// The default rank pattern for dummy arguments and function results is
143// "elemental".
peter klausler7bda1b32018-10-12 23:01:55144ENUM_CLASS(Rank,
145 elemental, // scalar, or array that conforms with other array arguments
146 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
147 scalar, vector,
148 shape, // INTEGER vector of known length and no negative element
149 matrix,
150 array, // not scalar, rank is known and greater than zero
151 known, // rank is known and can be scalar
152 anyOrAssumedRank, // rank can be unknown
153 conformable, // scalar, or array of same rank & shape as "array" argument
154 reduceOperation, // a pure function with constraints for REDUCE
155 dimReduced, // scalar if no DIM= argument, else rank(array)-1
156 dimRemoved, // scalar, or rank(array)-1
157 rankPlus1, // rank(known)+1
158 shaped, // rank is length of SHAPE vector
159)
peter klausler42b33da2018-09-29 00:02:11160
peter klausler7bda1b32018-10-12 23:01:55161ENUM_CLASS(Optionality, required, optional,
162 defaultsToSameKind, // for MatchingDefaultKIND
163 defaultsToDefaultForResult, // for DefaultingKIND
peter klausler7c402d92018-10-16 21:42:22164 defaultsToSubscriptKind, // for SubscriptDefaultKIND
peter klausler7bda1b32018-10-12 23:01:55165 repeats, // for MAX/MIN and their several variants
166)
peter klausler42b33da2018-09-29 00:02:11167
168struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45169 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11170 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33171 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54172 Optionality optionality{Optionality::required};
peter klausler7bda1b32018-10-12 23:01:55173 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11174};
175
peter klauslera70f5962018-10-04 20:43:33176// constexpr abbreviations for popular arguments:
177// DefaultingKIND is a KIND= argument whose default value is the appropriate
178// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54179static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30180 {IntType, KindCode::kindArg}, Rank::scalar,
peter klauslercb308d32018-10-05 18:32:54181 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33182// MatchingDefaultKIND is a KIND= argument whose default value is the
183// kind of any "Same" function argument (viz., the one whose kind pattern is
184// "same").
peter klauslercb308d32018-10-05 18:32:54185static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30186 {IntType, KindCode::kindArg}, Rank::scalar,
187 Optionality::defaultsToSameKind};
peter klausler7c402d92018-10-16 21:42:22188// SubscriptDefaultKind is a KIND= argument whose default value is
189// the kind of INTEGER used for address calculations.
190static constexpr IntrinsicDummyArgument SubscriptDefaultKIND{"kind",
191 {IntType, KindCode::kindArg}, Rank::scalar,
192 Optionality::defaultsToSubscriptKind};
peter klauslera70f5962018-10-04 20:43:33193static constexpr IntrinsicDummyArgument OptionalDIM{
peter klausler51b09b62018-10-15 19:17:30194 "dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33195static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54196 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11197
198struct IntrinsicInterface {
199 static constexpr int maxArguments{7};
peter klauslerb22d4942018-10-01 18:27:45200 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11201 IntrinsicDummyArgument dummy[maxArguments];
202 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33203 Rank rank{Rank::elemental};
204 std::optional<SpecificIntrinsic> Match(const CallCharacteristics &,
peter klauslerbf339f82018-10-15 22:28:47205 const semantics::IntrinsicTypeDefaultKinds &,
peter klauslercb308d32018-10-05 18:32:54206 parser::ContextualMessages &messages) const;
peter klausler7bda1b32018-10-12 23:01:55207 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11208};
209
peter klausler94041d72018-10-15 20:39:51210// GENERIC INTRINSIC FUNCTION INTERFACES
211// Each entry in this table defines a pattern. Some intrinsic
212// functions have more than one such pattern. Besides the name
213// of the intrinsic function, each pattern has specifications for
214// the dummy arguments and for the result of the function.
215// The dummy argument patterns each have a name (this are from the
216// standard, but rarely appear in actual code), a type and kind
217// pattern, allowable ranks, and optionality indicators.
218// Be advised, the default rank pattern is "elemental".
peter klauslerb22d4942018-10-01 18:27:45219static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33220 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
221 {"abs", {{"a", SameComplex}}, SameReal},
peter klauslerad9aede2018-10-11 21:51:14222 {"achar", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
peter klauslera70f5962018-10-04 20:43:33223 {"acos", {{"x", SameFloating}}, SameFloating},
224 {"acosh", {{"x", SameFloating}}, SameFloating},
225 {"adjustl", {{"string", SameChar}}, SameChar},
226 {"adjustr", {{"string", SameChar}}, SameChar},
227 {"aimag", {{"x", SameComplex}}, SameReal},
228 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
229 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
230 Rank::dimReduced},
231 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
232 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
233 Rank::dimReduced},
234 {"asin", {{"x", SameFloating}}, SameFloating},
235 {"asinh", {{"x", SameFloating}}, SameFloating},
236 {"atan", {{"x", SameFloating}}, SameFloating},
237 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
238 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
239 {"atanh", {{"x", SameFloating}}, SameFloating},
240 {"bessel_j0", {{"x", SameReal}}, SameReal},
241 {"bessel_j1", {{"x", SameReal}}, SameReal},
242 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29243 {"bessel_jn",
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 {"bessel_y0", {{"x", SameReal}}, SameReal},
248 {"bessel_y1", {{"x", SameReal}}, SameReal},
249 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29250 {"bessel_yn",
251 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
252 {"x", SameReal, Rank::scalar}},
253 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33254 {"bge",
peter klauslercb308d32018-10-05 18:32:54255 {{"i", AnyInt, Rank::elementalOrBOZ},
256 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22257 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33258 {"bgt",
peter klauslercb308d32018-10-05 18:32:54259 {{"i", AnyInt, Rank::elementalOrBOZ},
260 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22261 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33262 {"ble",
peter klauslercb308d32018-10-05 18:32:54263 {{"i", AnyInt, Rank::elementalOrBOZ},
264 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22265 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33266 {"blt",
peter klauslercb308d32018-10-05 18:32:54267 {{"i", AnyInt, Rank::elementalOrBOZ},
268 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22269 DefaultLogical},
270 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33271 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
272 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
273 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11274 {"cmplx",
peter klauslercb308d32018-10-05 18:32:54275 {{"x", SameIntOrReal, Rank::elementalOrBOZ},
276 {"y", SameIntOrReal, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33277 KINDComplex},
peter klausler7c402d92018-10-16 21:42:22278 {"command_argument_count", {}, DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33279 {"conjg", {{"z", SameComplex}}, SameComplex},
280 {"cos", {{"x", SameFloating}}, SameFloating},
281 {"cosh", {{"x", SameFloating}}, SameFloating},
282 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
283 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11284 {"cshift",
peter klauslera70f5962018-10-04 20:43:33285 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
286 OptionalDIM},
287 SameType, Rank::array},
288 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
peter klauslerf7f2a732018-10-09 19:07:29289 {"dot_product",
290 {{"vector_a", AnyLogical, Rank::vector},
291 {"vector_b", AnyLogical, Rank::vector}},
292 ResultLogical, Rank::scalar},
293 {"dot_product",
294 {{"vector_a", AnyComplex, Rank::vector},
295 {"vector_b", AnyNumeric, Rank::vector}},
296 ResultNumeric, Rank::scalar}, // conjugates vector_a
297 {"dot_product",
298 {{"vector_a", AnyIntOrReal, Rank::vector},
299 {"vector_b", AnyNumeric, Rank::vector}},
300 ResultNumeric, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22301 {"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33302 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54303 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33304 {"shift", AnyInt}},
305 SameInt},
306 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
307 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54308 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33309 {"shift", AnyInt}},
310 SameInt},
311 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11312 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33313 {{"array", SameIntrinsic, Rank::array},
314 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54315 {"boundary", SameIntrinsic, Rank::dimRemoved,
316 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33317 OptionalDIM},
318 SameIntrinsic, Rank::array},
peter klausler42b33da2018-09-29 00:02:11319 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33320 {{"array", SameDerivedType, Rank::array},
321 {"shift", AnyInt, Rank::dimRemoved},
322 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
323 SameDerivedType, Rank::array},
324 {"erf", {{"x", SameReal}}, SameReal},
325 {"erfc", {{"x", SameReal}}, SameReal},
326 {"erfc_scaled", {{"x", SameReal}}, SameReal},
327 {"exp", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22328 {"exponent", {{"x", AnyReal}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11329 {"findloc",
peter klauslerad9aede2018-10-11 21:51:14330 {{"array", AnyNumeric, Rank::array},
331 {"value", AnyNumeric, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22332 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54333 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33334 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11335 {"findloc",
peter klauslera70f5962018-10-04 20:43:33336 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22337 OptionalDIM, OptionalMASK, SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54338 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33339 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11340 {"findloc",
peter klauslera70f5962018-10-04 20:43:33341 {{"array", AnyLogical, Rank::array},
342 {"value", AnyLogical, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22343 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54344 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33345 KINDInt, Rank::dimReduced},
346 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
347 {"fraction", {{"x", SameReal}}, SameReal},
348 {"gamma", {{"x", SameReal}}, SameReal},
349 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
350 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
351 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
352 SameInt, Rank::dimReduced},
353 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
354 SameInt, Rank::dimReduced},
355 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
356 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54357 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33358 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
359 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
360 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
361 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
362 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54363 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33364 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
365 {"image_status",
peter klauslercb308d32018-10-05 18:32:54366 {{"image", SameInt},
367 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22368 DefaultInt},
peter klausler42b33da2018-09-29 00:02:11369 {"index",
peter klauslera70f5962018-10-04 20:43:33370 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54371 {"back", AnyLogical, Rank::scalar, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22372 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33373 KINDInt},
peter klauslercb308d32018-10-05 18:32:54374 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
375 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33376 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
377 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
378 {"ishftc",
379 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54380 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33381 SameInt},
peter klausler7c402d92018-10-16 21:42:22382 {"is_iostat_end", {{"i", AnyInt}}, DefaultLogical},
383 {"is_iostat_eor", {{"i", AnyInt}}, DefaultLogical},
384 {"lbound",
385 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29386 KINDInt, Rank::vector},
387 {"lbound",
388 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22389 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
390 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29391 KINDInt, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22392 {"leadz", {{"i", AnyInt}}, DefaultInt},
393 {"len", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
394 {"len_trim", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
395 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
396 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
397 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
398 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33399 {"log", {{"x", SameFloating}}, SameFloating},
400 {"log10", {{"x", SameReal}}, SameReal},
401 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
402 {"log_gamma", {{"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29403 {"matmul",
404 {{"array_a", AnyLogical, Rank::vector},
405 {"array_b", AnyLogical, Rank::matrix}},
406 ResultLogical, Rank::vector},
407 {"matmul",
408 {{"array_a", AnyLogical, Rank::matrix},
409 {"array_b", AnyLogical, Rank::vector}},
410 ResultLogical, Rank::vector},
411 {"matmul",
412 {{"array_a", AnyLogical, Rank::matrix},
413 {"array_b", AnyLogical, Rank::matrix}},
414 ResultLogical, Rank::matrix},
415 {"matmul",
416 {{"array_a", AnyNumeric, Rank::vector},
417 {"array_b", AnyNumeric, Rank::matrix}},
418 ResultNumeric, Rank::vector},
419 {"matmul",
420 {{"array_a", AnyNumeric, Rank::matrix},
421 {"array_b", AnyNumeric, Rank::vector}},
422 ResultNumeric, Rank::vector},
423 {"matmul",
424 {{"array_a", AnyNumeric, Rank::matrix},
425 {"array_b", AnyNumeric, Rank::matrix}},
426 ResultNumeric, Rank::matrix},
peter klauslera70f5962018-10-04 20:43:33427 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
428 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klauslerad9aede2018-10-11 21:51:14429 {"max",
430 {{"a1", SameRelatable}, {"a2", SameRelatable},
431 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
432 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11433 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33434 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22435 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54436 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33437 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11438 {"maxval",
peter klauslera70f5962018-10-04 20:43:33439 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
440 SameRelatable, Rank::dimReduced},
peter klauslerad9aede2018-10-11 21:51:14441 {"merge",
442 {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
443 SameType},
peter klausler42b33da2018-09-29 00:02:11444 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54445 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
446 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33447 SameInt},
448 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54449 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33450 SameInt},
peter klauslerad9aede2018-10-11 21:51:14451 {"min",
452 {{"a1", SameRelatable}, {"a2", SameRelatable},
453 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
454 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11455 {"minloc",
peter klauslera70f5962018-10-04 20:43:33456 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22457 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54458 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33459 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11460 {"minval",
peter klauslera70f5962018-10-04 20:43:33461 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
462 SameRelatable, Rank::dimReduced},
463 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
464 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
465 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
466 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
467 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
468 Rank::dimReduced},
469 {"not", {{"i", SameInt}}, SameInt},
peter klausler8efb8972018-10-10 17:48:12470 // NULL() is a special case handled in Probe() below
peter klausler42b33da2018-09-29 00:02:11471 {"out_of_range",
peter klauslerad9aede2018-10-11 21:51:14472 {{"x", AnyIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22473 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33474 {"out_of_range",
475 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54476 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22477 DefaultLogical},
478 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DefaultLogical},
peter klausler42b33da2018-09-29 00:02:11479 {"pack",
peter klauslera70f5962018-10-04 20:43:33480 {{"array", SameType, Rank::array},
481 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54482 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33483 SameType, Rank::vector},
484 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
485 Rank::dimReduced},
peter klausler7c402d92018-10-16 21:42:22486 {"popcnt", {{"i", AnyInt}}, DefaultInt},
487 {"poppar", {{"i", AnyInt}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11488 {"product",
peter klauslera70f5962018-10-04 20:43:33489 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
490 SameNumeric, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54491 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33492 KINDReal},
peter klauslerad9aede2018-10-11 21:51:14493 {"reduce",
494 {{"array", SameType, Rank::array},
495 {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
496 OptionalMASK, {"identity", SameType, Rank::scalar},
497 {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
498 SameType, Rank::dimReduced},
peter klausler24379cc2018-10-10 23:45:17499 {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
500 SameChar, Rank::scalar},
peter klausler42b33da2018-09-29 00:02:11501 {"reshape",
peter klauslera70f5962018-10-04 20:43:33502 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54503 {"pad", SameType, Rank::array, Optionality::optional},
504 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33505 SameType, Rank::shaped},
506 {"rrspacing", {{"x", SameReal}}, SameReal},
507 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11508 {"scan",
peter klauslera70f5962018-10-04 20:43:33509 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54510 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22511 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33512 KINDInt},
peter klausler7c402d92018-10-16 21:42:22513 {"selected_char_kind", {{"name", DefaultChar, Rank::scalar}}, DefaultInt,
peter klausler24379cc2018-10-10 23:45:17514 Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22515 {"selected_int_kind", {{"r", AnyInt, Rank::scalar}}, DefaultInt,
516 Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14517 {"selected_real_kind",
518 {{"p", AnyInt, Rank::scalar},
519 {"r", AnyInt, Rank::scalar, Optionality::optional},
520 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22521 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14522 {"selected_real_kind",
523 {{"p", AnyInt, Rank::scalar, Optionality::optional},
524 {"r", AnyInt, Rank::scalar},
525 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22526 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14527 {"selected_real_kind",
528 {{"p", AnyInt, Rank::scalar, Optionality::optional},
529 {"r", AnyInt, Rank::scalar, Optionality::optional},
530 {"radix", AnyInt, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22531 DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33532 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler7c402d92018-10-16 21:42:22533 {"shape",
534 {{"source", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klausler24379cc2018-10-10 23:45:17535 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33536 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
537 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
538 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
539 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
540 {"sin", {{"x", SameFloating}}, SameFloating},
541 {"sinh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22542 {"size",
543 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29544 KINDInt, Rank::vector},
545 {"size",
546 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22547 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
548 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29549 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33550 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11551 {"spread",
peter klauslera70f5962018-10-04 20:43:33552 {{"source", SameType, Rank::known},
peter klausler51b09b62018-10-15 19:17:30553 {"dim", {IntType, KindCode::dimArg}, Rank::scalar /*not optional*/},
peter klauslera70f5962018-10-04 20:43:33554 {"ncopies", AnyInt, Rank::scalar}},
555 SameType, Rank::rankPlus1},
556 {"sqrt", {{"x", SameFloating}}, SameFloating},
557 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
558 SameNumeric, Rank::dimReduced},
559 {"tan", {{"x", SameFloating}}, SameFloating},
560 {"tanh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22561 {"trailz", {{"i", AnyInt}}, DefaultInt},
peter klauslerf7f2a732018-10-09 19:07:29562 {"transfer",
563 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::scalar}},
564 SameType, Rank::scalar},
565 {"transfer",
566 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::array}},
567 SameType, Rank::vector},
568 {"transfer",
569 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::known},
570 {"size", AnyInt, Rank::scalar}},
571 SameType, Rank::vector},
572 {"transpose", {{"matrix", SameType, Rank::matrix}}, SameType, Rank::matrix},
peter klauslerad9aede2018-10-11 21:51:14573 {"trim", {{"string", SameChar, Rank::scalar}}, SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22574 {"ubound",
575 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29576 KINDInt, Rank::vector},
577 {"ubound",
578 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22579 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
580 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29581 KINDInt, Rank::scalar},
582 {"unpack",
583 {{"vector", SameType, Rank::vector}, {"mask", AnyLogical, Rank::array},
584 {"field", SameType, Rank::conformable}},
585 SameType, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11586 {"verify",
peter klauslera70f5962018-10-04 20:43:33587 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54588 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22589 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33590 KINDInt},
peter klausler42b33da2018-09-29 00:02:11591};
592
peter klausler8efb8972018-10-10 17:48:12593// TODO: Coarray intrinsic functions
peter klauslerad9aede2018-10-11 21:51:14594// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
595// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
596// COSHAPE
peter klausler8efb8972018-10-10 17:48:12597// TODO: Object characteristic inquiry functions
peter klauslerad9aede2018-10-11 21:51:14598// ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS,
599// PRESENT, RANK, SAME_TYPE, STORAGE_SIZE
600// TODO: Type inquiry intrinsic functions - these return constants
601// BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT,
602// NEW_LINE, PRECISION, RADIX, RANGE, TINY
603// TODO: Non-standard intrinsic functions
604// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
605// COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL,
606// DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC,
607// QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM,
608// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
609// MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
610// IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
611// EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
612// probably more (these are PGI + Intel, possibly incomplete)
peter klausler42b33da2018-09-29 00:02:11613
614struct SpecificIntrinsicInterface : public IntrinsicInterface {
615 const char *generic{nullptr};
peter klauslerad9aede2018-10-11 21:51:14616 bool isRestrictedSpecific{
617 false}; // when true, can only be called, not passed
peter klausler42b33da2018-09-29 00:02:11618};
619
peter klauslerb22d4942018-10-01 18:27:45620static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klausler7c402d92018-10-16 21:42:22621 {{"abs", {{"a", DefaultReal}}, DefaultReal}},
622 {{"acos", {{"x", DefaultReal}}, DefaultReal}},
623 {{"aimag", {{"z", DefaultComplex}}, DefaultReal}},
624 {{"aint", {{"a", DefaultReal}}, DefaultReal}},
625 {{"alog", {{"x", DefaultReal}}, DefaultReal}, "log"},
626 {{"alog10", {{"x", DefaultReal}}, DefaultReal}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14627 {{"amax0",
peter klausler7c402d92018-10-16 21:42:22628 {{"a1", DefaultInt}, {"a2", DefaultInt},
629 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
630 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14631 "max", true},
632 {{"amax1",
peter klausler7c402d92018-10-16 21:42:22633 {{"a1", DefaultReal}, {"a2", DefaultReal},
634 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
635 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14636 "max", true},
637 {{"amin0",
peter klausler7c402d92018-10-16 21:42:22638 {{"a1", DefaultInt}, {"a2", DefaultInt},
639 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
640 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14641 "min", true},
642 {{"amin1",
peter klausler7c402d92018-10-16 21:42:22643 {{"a1", DefaultReal}, {"a2", DefaultReal},
644 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
645 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14646 "min", true},
peter klausler7c402d92018-10-16 21:42:22647 {{"amod", {{"a", DefaultReal}, {"p", DefaultReal}}, DefaultReal}, "mod"},
648 {{"anint", {{"a", DefaultReal}}, DefaultReal}},
649 {{"asin", {{"x", DefaultReal}}, DefaultReal}},
650 {{"atan", {{"x", DefaultReal}}, DefaultReal}},
651 {{"atan2", {{"y", DefaultReal}, {"x", DefaultReal}}, DefaultReal}},
652 {{"cabs", {{"a", DefaultComplex}}, DefaultReal}, "abs"},
653 {{"ccos", {{"a", DefaultComplex}}, DefaultComplex}, "cos"},
654 {{"cexp", {{"a", DefaultComplex}}, DefaultComplex}, "exp"},
655 {{"clog", {{"a", DefaultComplex}}, DefaultComplex}, "log"},
656 {{"conjg", {{"a", DefaultComplex}}, DefaultComplex}},
657 {{"cos", {{"x", DefaultReal}}, DefaultReal}},
658 {{"csin", {{"a", DefaultComplex}}, DefaultComplex}, "sin"},
659 {{"csqrt", {{"a", DefaultComplex}}, DefaultComplex}, "sqrt"},
660 {{"ctan", {{"a", DefaultComplex}}, DefaultComplex}, "tan"},
peter klauslera70f5962018-10-04 20:43:33661 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
662 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
663 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
664 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
665 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
666 DoublePrecision},
667 "atan2"},
peter klausler7c402d92018-10-16 21:42:22668 {{"dble", {{"a", DefaultReal}, DefaultingKIND}, DoublePrecision}, "real",
669 true},
peter klauslera70f5962018-10-04 20:43:33670 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
671 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
672 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
673 DoublePrecision},
674 "dim"},
675 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
peter klausler7c402d92018-10-16 21:42:22676 {{"dim", {{"x", DefaultReal}, {"y", DefaultReal}}, DefaultReal}},
peter klauslera70f5962018-10-04 20:43:33677 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
678 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
679 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14680 {{"dmax1",
681 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
682 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
683 DoublePrecision},
684 "max", true},
685 {{"dmin1",
686 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
687 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
688 DoublePrecision},
689 "min", true},
peter klauslera70f5962018-10-04 20:43:33690 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
691 DoublePrecision},
692 "mod"},
693 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
peter klausler7c402d92018-10-16 21:42:22694 {{"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision}},
peter klauslera70f5962018-10-04 20:43:33695 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
696 DoublePrecision},
697 "sign"},
698 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
699 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
700 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
701 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
702 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
peter klausler7c402d92018-10-16 21:42:22703 {{"exp", {{"x", DefaultReal}}, DefaultReal}},
704 {{"float", {{"i", DefaultInt}}, DefaultReal}, "real", true},
705 {{"iabs", {{"a", DefaultInt}}, DefaultInt}, "abs"},
706 {{"idim", {{"x", DefaultInt}, {"y", DefaultInt}}, DefaultInt}, "dim"},
707 {{"idint", {{"a", DoublePrecision}}, DefaultInt}, "int", true},
708 {{"idnint", {{"a", DoublePrecision}}, DefaultInt}, "nint"},
709 {{"ifix", {{"a", DefaultReal}}, DefaultInt}, "int", true},
710 {{"index", {{"string", DefaultChar}, {"substring", DefaultChar}},
711 DefaultInt}},
712 {{"isign", {{"a", DefaultInt}, {"b", DefaultInt}}, DefaultInt}, "sign"},
713 {{"len", {{"string", DefaultChar}}, DefaultInt}},
714 {{"log", {{"x", DefaultReal}}, DefaultReal}},
715 {{"log10", {{"x", DefaultReal}}, DefaultReal}},
peter klauslerad9aede2018-10-11 21:51:14716 {{"max0",
peter klausler7c402d92018-10-16 21:42:22717 {{"a1", DefaultInt}, {"a2", DefaultInt},
718 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
719 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14720 "max", true},
721 {{"max1",
peter klausler7c402d92018-10-16 21:42:22722 {{"a1", DefaultReal}, {"a2", DefaultReal},
723 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
724 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14725 "max", true},
726 {{"min0",
peter klausler7c402d92018-10-16 21:42:22727 {{"a1", DefaultInt}, {"a2", DefaultInt},
728 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
729 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14730 "min", true},
731 {{"min1",
peter klausler7c402d92018-10-16 21:42:22732 {{"a1", DefaultReal}, {"a2", DefaultReal},
733 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
734 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14735 "min", true},
peter klausler7c402d92018-10-16 21:42:22736 {{"mod", {{"a", DefaultInt}, {"p", DefaultInt}}, DefaultInt}},
737 {{"nint", {{"a", DefaultReal}}, DefaultInt}},
738 {{"sign", {{"a", DefaultReal}, {"b", DefaultReal}}, DefaultReal}},
739 {{"sin", {{"x", DefaultReal}}, DefaultReal}},
740 {{"sinh", {{"x", DefaultReal}}, DefaultReal}},
741 {{"sngl", {{"a", DoublePrecision}}, DefaultReal}, "real", true},
742 {{"sqrt", {{"x", DefaultReal}}, DefaultReal}},
743 {{"tan", {{"x", DefaultReal}}, DefaultReal}},
744 {{"tanh", {{"x", DefaultReal}}, DefaultReal}},
peter klausler42b33da2018-09-29 00:02:11745};
746
peter klauslerad9aede2018-10-11 21:51:14747// TODO: Intrinsic subroutines
748// MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY,
749// EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT,
750// GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER,
751// RANDOM_SEED, SYSTEM_CLOCK
752// TODO: Atomic intrinsic subroutines: ATOMIC_ADD &al.
753// TODO: Collective intrinsic subroutines: CO_BROADCAST &al.
peter klausler42b33da2018-09-29 00:02:11754
peter klauslera70f5962018-10-04 20:43:33755// Intrinsic interface matching against the arguments of a particular
756// procedure reference.
peter klauslera70f5962018-10-04 20:43:33757std::optional<SpecificIntrinsic> IntrinsicInterface::Match(
peter klauslerbf339f82018-10-15 22:28:47758 const CallCharacteristics &call,
759 const semantics::IntrinsicTypeDefaultKinds &defaults,
peter klauslercb308d32018-10-05 18:32:54760 parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33761 // Attempt to construct a 1-1 correspondence between the dummy arguments in
762 // a particular intrinsic procedure's generic interface and the actual
763 // arguments in a procedure reference.
peter klauslera62636f2018-10-08 22:35:19764 const ActualArgument *actualForDummy[maxArguments];
peter klauslera70f5962018-10-04 20:43:33765 int dummies{0};
766 for (; dummies < maxArguments && dummy[dummies].keyword != nullptr;
767 ++dummies) {
768 actualForDummy[dummies] = nullptr;
769 }
peter klausler94041d72018-10-15 20:39:51770 for (const ActualArgument &arg : call.arguments) {
peter klauslera62636f2018-10-08 22:35:19771 if (arg.isAlternateReturn) {
772 messages.Say(
773 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
peter klausler7bda1b32018-10-12 23:01:55774 name);
peter klauslera62636f2018-10-08 22:35:19775 return std::nullopt;
776 }
peter klauslera70f5962018-10-04 20:43:33777 bool found{false};
778 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
779 if (actualForDummy[dummyArgIndex] == nullptr) {
780 if (!arg.keyword.has_value() ||
781 *arg.keyword == dummy[dummyArgIndex].keyword) {
782 actualForDummy[dummyArgIndex] = &arg;
783 found = true;
784 break;
785 }
786 }
peter klausler7bda1b32018-10-12 23:01:55787 }
788 if (!found) {
789 if (arg.keyword.has_value()) {
790 messages.Say(*arg.keyword,
791 "unknown keyword argument to intrinsic '%s'"_err_en_US, name);
792 } else {
793 messages.Say(
794 "too many actual arguments for intrinsic '%s'"_err_en_US, name);
peter klauslera70f5962018-10-04 20:43:33795 }
peter klausler7bda1b32018-10-12 23:01:55796 return std::nullopt;
peter klauslera70f5962018-10-04 20:43:33797 }
798 }
799
800 // Check types and kinds of the actual arguments against the intrinsic's
801 // interface. Ensure that two or more arguments that have to have the same
802 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19803 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33804 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19805 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33806 bool hasDimArg{false};
807 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
808 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
809 if (d.typePattern.kindCode == KindCode::kindArg) {
810 CHECK(kindDummyArg == nullptr);
811 kindDummyArg = &d;
812 }
peter klauslera62636f2018-10-08 22:35:19813 const ActualArgument *arg{actualForDummy[dummyArgIndex]};
peter klauslera70f5962018-10-04 20:43:33814 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54815 if (d.optionality == Optionality::required) {
peter klausler7bda1b32018-10-12 23:01:55816 messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33817 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54818 } else {
819 continue;
peter klauslera70f5962018-10-04 20:43:33820 }
821 }
peter klauslera62636f2018-10-08 22:35:19822 std::optional<DynamicType> type{arg->GetType()};
823 if (!type.has_value()) {
824 CHECK(arg->Rank() == 0);
peter klauslercb308d32018-10-05 18:32:54825 if (d.typePattern.kindCode == KindCode::typeless ||
826 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33827 continue;
828 }
peter klausler7bda1b32018-10-12 23:01:55829 messages.Say(
830 "typeless (BOZ) not allowed for '%s=' argument"_err_en_US, d.keyword);
peter klauslercb308d32018-10-05 18:32:54831 return std::nullopt;
peter klauslera62636f2018-10-08 22:35:19832 } else if (!d.typePattern.categorySet.test(type->category)) {
peter klausler7bda1b32018-10-12 23:01:55833 messages.Say("actual argument for '%s=' has bad type '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19834 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33835 return std::nullopt; // argument has invalid type category
836 }
837 bool argOk{false};
838 switch (d.typePattern.kindCode) {
839 case KindCode::none:
840 case KindCode::typeless:
841 case KindCode::teamType: // TODO: TEAM_TYPE
842 argOk = false;
843 break;
844 case KindCode::defaultIntegerKind:
peter klauslerbf339f82018-10-15 22:28:47845 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33846 break;
847 case KindCode::defaultRealKind:
peter klauslerbf339f82018-10-15 22:28:47848 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Real);
peter klauslera70f5962018-10-04 20:43:33849 break;
850 case KindCode::doublePrecision:
peter klauslerbf339f82018-10-15 22:28:47851 argOk = type->kind == defaults.doublePrecisionKind();
peter klauslera70f5962018-10-04 20:43:33852 break;
853 case KindCode::defaultCharKind:
peter klauslerbf339f82018-10-15 22:28:47854 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Character);
peter klauslera70f5962018-10-04 20:43:33855 break;
856 case KindCode::defaultLogicalKind:
peter klauslerbf339f82018-10-15 22:28:47857 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Logical);
peter klauslera70f5962018-10-04 20:43:33858 break;
859 case KindCode::any: argOk = true; break;
860 case KindCode::kindArg:
peter klauslerf7f2a732018-10-09 19:07:29861 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33862 CHECK(kindArg == nullptr);
863 kindArg = arg;
peter klauslerf7f2a732018-10-09 19:07:29864 argOk = true;
peter klauslera70f5962018-10-04 20:43:33865 break;
866 case KindCode::dimArg:
peter klauslerf7f2a732018-10-09 19:07:29867 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33868 hasDimArg = true;
869 argOk = true;
870 break;
871 case KindCode::same:
872 if (sameArg == nullptr) {
873 sameArg = arg;
874 }
peter klauslera62636f2018-10-08 22:35:19875 argOk = *type == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33876 break;
877 case KindCode::effectiveKind:
878 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
879 "for intrinsic '%s'",
880 d.keyword, name);
881 break;
882 default: CRASH_NO_CASE;
883 }
884 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54885 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55886 "actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19887 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33888 return std::nullopt;
889 }
890 }
891
892 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:19893 const ActualArgument *arrayArg{nullptr};
894 const ActualArgument *knownArg{nullptr};
895 const ActualArgument *shapeArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33896 int elementalRank{0};
897 for (int dummyArgIndex{0}; dummyArgIndex < dummies; ++dummyArgIndex) {
898 const IntrinsicDummyArgument &d{dummy[dummyArgIndex]};
peter klauslera62636f2018-10-08 22:35:19899 if (const ActualArgument * arg{actualForDummy[dummyArgIndex]}) {
peter klauslera70f5962018-10-04 20:43:33900 if (arg->isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
peter klauslercb308d32018-10-05 18:32:54901 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55902 "assumed-rank array cannot be used for '%s=' argument"_err_en_US,
peter klauslercb308d32018-10-05 18:32:54903 d.keyword);
peter klauslera70f5962018-10-04 20:43:33904 return std::nullopt;
905 }
peter klauslera62636f2018-10-08 22:35:19906 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:33907 bool argOk{false};
908 switch (d.rank) {
909 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54910 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33911 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:19912 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:33913 }
peter klauslera62636f2018-10-08 22:35:19914 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:33915 break;
peter klauslera62636f2018-10-08 22:35:19916 case Rank::scalar: argOk = rank == 0; break;
917 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:33918 case Rank::shape:
919 CHECK(shapeArg == nullptr);
920 shapeArg = arg;
peter klauslerad9aede2018-10-11 21:51:14921 argOk = rank == 1 && arg->VectorSize().has_value();
peter klauslera70f5962018-10-04 20:43:33922 break;
peter klauslera62636f2018-10-08 22:35:19923 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:33924 case Rank::array:
peter klauslera62636f2018-10-08 22:35:19925 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:33926 if (!arrayArg) {
927 arrayArg = arg;
928 } else {
peter klauslera62636f2018-10-08 22:35:19929 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33930 }
931 break;
932 case Rank::known:
933 CHECK(knownArg == nullptr);
934 knownArg = arg;
935 argOk = true;
936 break;
937 case Rank::anyOrAssumedRank: argOk = true; break;
938 case Rank::conformable:
939 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19940 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33941 break;
942 case Rank::dimRemoved:
943 CHECK(arrayArg != nullptr);
944 if (hasDimArg) {
peter klauslera62636f2018-10-08 22:35:19945 argOk = rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33946 } else {
peter klauslera62636f2018-10-08 22:35:19947 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:33948 }
949 break;
peter klauslerad9aede2018-10-11 21:51:14950 case Rank::reduceOperation:
951 // TODO: Confirm that the argument is a pure function
952 // of two arguments with several constraints
953 CHECK(arrayArg != nullptr);
954 argOk = rank == 0;
955 break;
peter klauslera70f5962018-10-04 20:43:33956 case Rank::dimReduced:
957 case Rank::rankPlus1:
958 case Rank::shaped:
959 common::die("INTERNAL: result-only rank code appears on argument '%s' "
960 "for intrinsic '%s'",
961 d.keyword, name);
962 default: CRASH_NO_CASE;
963 }
964 if (!argOk) {
peter klausler7bda1b32018-10-12 23:01:55965 messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19966 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:33967 return std::nullopt;
968 }
969 }
970 }
971
peter klauslera70f5962018-10-04 20:43:33972 // Calculate the characteristics of the function result, if any
973 if (result.categorySet.empty()) {
974 CHECK(result.kindCode == KindCode::none);
975 return std::make_optional<SpecificIntrinsic>(name);
976 }
977 // Determine the result type.
978 DynamicType resultType{*result.categorySet.LeastElement(), 0};
979 switch (result.kindCode) {
980 case KindCode::defaultIntegerKind:
peter klausler51b09b62018-10-15 19:17:30981 CHECK(result.categorySet == IntType);
peter klauslera70f5962018-10-04 20:43:33982 CHECK(resultType.category == TypeCategory::Integer);
peter klauslerbf339f82018-10-15 22:28:47983 resultType.kind = defaults.GetDefaultKind(TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33984 break;
985 case KindCode::defaultRealKind:
986 CHECK(result.categorySet == CategorySet{resultType.category});
peter klausler51b09b62018-10-15 19:17:30987 CHECK(FloatingType.test(resultType.category));
peter klauslerbf339f82018-10-15 22:28:47988 resultType.kind = defaults.GetDefaultKind(TypeCategory::Real);
peter klauslera70f5962018-10-04 20:43:33989 break;
990 case KindCode::doublePrecision:
peter klausler51b09b62018-10-15 19:17:30991 CHECK(result.categorySet == RealType);
peter klauslera70f5962018-10-04 20:43:33992 CHECK(resultType.category == TypeCategory::Real);
peter klauslerbf339f82018-10-15 22:28:47993 resultType.kind = defaults.doublePrecisionKind();
peter klauslera70f5962018-10-04 20:43:33994 break;
995 case KindCode::defaultCharKind:
peter klausler51b09b62018-10-15 19:17:30996 CHECK(result.categorySet == CharType);
peter klauslera70f5962018-10-04 20:43:33997 CHECK(resultType.category == TypeCategory::Character);
peter klauslerbf339f82018-10-15 22:28:47998 resultType.kind = defaults.GetDefaultKind(TypeCategory::Character);
peter klauslera70f5962018-10-04 20:43:33999 break;
1000 case KindCode::defaultLogicalKind:
peter klausler51b09b62018-10-15 19:17:301001 CHECK(result.categorySet == LogicalType);
peter klauslera70f5962018-10-04 20:43:331002 CHECK(resultType.category == TypeCategory::Logical);
peter klauslerbf339f82018-10-15 22:28:471003 resultType.kind = defaults.GetDefaultKind(TypeCategory::Logical);
peter klauslera70f5962018-10-04 20:43:331004 break;
1005 case KindCode::same:
1006 CHECK(sameArg != nullptr);
peter klausler55df4a72018-10-12 23:25:391007 if (std::optional<DynamicType> aType{sameArg->GetType()}) {
1008 if (result.categorySet.test(aType->category)) {
1009 resultType = *aType;
1010 } else {
1011 resultType.kind = aType->kind;
1012 }
1013 }
peter klauslera70f5962018-10-04 20:43:331014 break;
1015 case KindCode::effectiveKind:
1016 CHECK(kindDummyArg != nullptr);
1017 CHECK(result.categorySet == CategorySet{resultType.category});
1018 if (kindArg != nullptr) {
peter klauslerf7f2a732018-10-09 19:07:291019 if (auto *jExpr{std::get_if<Expr<SomeInteger>>(&kindArg->value->u)}) {
1020 CHECK(jExpr->Rank() == 0);
1021 if (auto value{jExpr->ScalarValue()}) {
1022 if (auto code{value->ToInt64()}) {
1023 if (IsValidKindOfIntrinsicType(resultType.category, *code)) {
1024 resultType.kind = *code;
1025 break;
1026 }
1027 }
1028 }
1029 }
peter klausler7bda1b32018-10-12 23:01:551030 messages.Say("'kind=' argument must be a constant scalar integer "
peter klauslerf7f2a732018-10-09 19:07:291031 "whose value is a supported kind for the "
1032 "intrinsic result type"_err_en_US);
1033 return std::nullopt;
peter klauslercb308d32018-10-05 18:32:541034 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
peter klauslera70f5962018-10-04 20:43:331035 CHECK(sameArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191036 resultType = *sameArg->GetType();
peter klausler7c402d92018-10-16 21:42:221037 } else if (kindDummyArg->optionality ==
1038 Optionality::defaultsToSubscriptKind) {
1039 CHECK(resultType.category == TypeCategory::Integer);
1040 resultType.kind = defaults.subscriptIntegerKind();
peter klauslera70f5962018-10-04 20:43:331041 } else {
peter klauslercb308d32018-10-05 18:32:541042 CHECK(
1043 kindDummyArg->optionality == Optionality::defaultsToDefaultForResult);
peter klauslerbf339f82018-10-15 22:28:471044 resultType.kind = defaults.GetDefaultKind(resultType.category);
peter klauslera70f5962018-10-04 20:43:331045 }
1046 break;
peter klauslerf7f2a732018-10-09 19:07:291047 case KindCode::likeMultiply:
1048 CHECK(dummies >= 2);
1049 CHECK(actualForDummy[0] != nullptr);
1050 CHECK(actualForDummy[1] != nullptr);
1051 resultType = actualForDummy[0]->GetType()->ResultTypeForMultiply(
1052 *actualForDummy[1]->GetType());
1053 break;
peter klauslera70f5962018-10-04 20:43:331054 case KindCode::typeless:
1055 case KindCode::teamType:
1056 case KindCode::any:
1057 case KindCode::kindArg:
1058 case KindCode::dimArg:
1059 common::die(
1060 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
1061 break;
1062 default: CRASH_NO_CASE;
1063 }
1064
peter klauslerf7f2a732018-10-09 19:07:291065 // At this point, the call is acceptable.
peter klauslera70f5962018-10-04 20:43:331066 // Determine the rank of the function result.
1067 int resultRank{0};
1068 switch (rank) {
1069 case Rank::elemental: resultRank = elementalRank; break;
1070 case Rank::scalar: resultRank = 0; break;
1071 case Rank::vector: resultRank = 1; break;
1072 case Rank::matrix: resultRank = 2; break;
peter klauslerf7f2a732018-10-09 19:07:291073 case Rank::conformable:
1074 CHECK(arrayArg != nullptr);
1075 resultRank = arrayArg->Rank();
1076 break;
peter klauslera70f5962018-10-04 20:43:331077 case Rank::dimReduced:
1078 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191079 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:331080 break;
1081 case Rank::rankPlus1:
1082 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191083 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:331084 break;
1085 case Rank::shaped:
1086 CHECK(shapeArg != nullptr);
peter klauslerad9aede2018-10-11 21:51:141087 {
1088 std::optional<int> shapeLen{shapeArg->VectorSize()};
1089 CHECK(shapeLen.has_value());
1090 resultRank = *shapeLen;
1091 }
peter klauslera70f5962018-10-04 20:43:331092 break;
peter klauslercb308d32018-10-05 18:32:541093 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331094 case Rank::shape:
1095 case Rank::array:
1096 case Rank::known:
1097 case Rank::anyOrAssumedRank:
peter klauslera70f5962018-10-04 20:43:331098 case Rank::dimRemoved:
peter klauslerad9aede2018-10-11 21:51:141099 case Rank::reduceOperation:
peter klauslera70f5962018-10-04 20:43:331100 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
1101 break;
1102 default: CRASH_NO_CASE;
1103 }
1104 CHECK(resultRank >= 0);
1105
1106 return std::make_optional<SpecificIntrinsic>(
1107 name, elementalRank > 0, resultType, resultRank);
1108}
1109
peter klauslera62636f2018-10-08 22:35:191110struct IntrinsicProcTable::Implementation {
peter klauslerbf339f82018-10-15 22:28:471111 explicit Implementation(const semantics::IntrinsicTypeDefaultKinds &dfts)
peter klauslera70f5962018-10-04 20:43:331112 : defaults{dfts} {
1113 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
1114 genericFuncs.insert(std::make_pair(std::string{f.name}, &f));
1115 }
1116 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
1117 specificFuncs.insert(std::make_pair(std::string{f.name}, &f));
1118 }
1119 }
peter klausler42b33da2018-09-29 00:02:111120
peter klauslercb308d32018-10-05 18:32:541121 std::optional<SpecificIntrinsic> Probe(
1122 const CallCharacteristics &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:531123
peter klauslerbf339f82018-10-15 22:28:471124 semantics::IntrinsicTypeDefaultKinds defaults;
peter klauslera70f5962018-10-04 20:43:331125 std::multimap<std::string, const IntrinsicInterface *> genericFuncs;
1126 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs;
peter klausler7bda1b32018-10-12 23:01:551127 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:111128};
1129
peter klauslercb308d32018-10-05 18:32:541130// Probe the configured intrinsic procedure pattern tables in search of a
1131// match for a given procedure reference.
peter klauslera62636f2018-10-08 22:35:191132std::optional<SpecificIntrinsic> IntrinsicProcTable::Implementation::Probe(
peter klauslercb308d32018-10-05 18:32:541133 const CallCharacteristics &call,
1134 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:531135 if (call.isSubroutineCall) {
1136 return std::nullopt; // TODO
1137 }
peter klausler7bda1b32018-10-12 23:01:551138 parser::Messages *finalBuffer{messages ? messages->messages() : nullptr};
peter klausler62425d62018-10-12 00:01:311139 // Probe the specific intrinsic function table first.
1140 parser::Messages specificBuffer;
1141 parser::ContextualMessages specificErrors{
1142 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551143 finalBuffer ? &specificBuffer : nullptr};
peter klausler75a32092018-10-05 16:57:531144 std::string name{call.name.ToString()};
1145 auto specificRange{specificFuncs.equal_range(name)};
1146 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klausler62425d62018-10-12 00:01:311147 if (auto specific{iter->second->Match(call, defaults, specificErrors)}) {
peter klauslerad9aede2018-10-11 21:51:141148 if (const char *genericName{iter->second->generic}) {
1149 specific->name = genericName;
1150 }
1151 specific->isRestrictedSpecific = iter->second->isRestrictedSpecific;
peter klausler75a32092018-10-05 16:57:531152 return specific;
1153 }
1154 }
peter klausler62425d62018-10-12 00:01:311155 // Probe the generic intrinsic function table next.
1156 parser::Messages genericBuffer;
1157 parser::ContextualMessages genericErrors{
1158 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551159 finalBuffer ? &genericBuffer : nullptr};
peter klausler62425d62018-10-12 00:01:311160 auto genericRange{genericFuncs.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531161 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klausler62425d62018-10-12 00:01:311162 if (auto specific{iter->second->Match(call, defaults, genericErrors)}) {
peter klausler75a32092018-10-05 16:57:531163 return specific;
1164 }
1165 }
peter klauslerad9aede2018-10-11 21:51:141166 // Special cases of intrinsic functions
peter klausler8efb8972018-10-10 17:48:121167 if (call.name.ToString() == "null") {
peter klausler94041d72018-10-15 20:39:511168 if (call.arguments.size() == 0) {
peter klausler8efb8972018-10-10 17:48:121169 // TODO: NULL() result type is determined by context
1170 // Can pass that context in, or return a token distinguishing
1171 // NULL, or represent NULL as a new kind of top-level expression
peter klausler94041d72018-10-15 20:39:511172 } else if (call.arguments.size() > 1) {
peter klausler62425d62018-10-12 00:01:311173 genericErrors.Say("too many arguments to NULL()"_err_en_US);
peter klausler94041d72018-10-15 20:39:511174 } else if (call.arguments[0].keyword.has_value() &&
1175 call.arguments[0].keyword->ToString() != "mold") {
peter klausler62425d62018-10-12 00:01:311176 genericErrors.Say("unknown argument '%s' to NULL()"_err_en_US,
peter klausler94041d72018-10-15 20:39:511177 call.arguments[0].keyword->ToString().data());
peter klausler8efb8972018-10-10 17:48:121178 } else {
1179 // TODO: Argument must be pointer, procedure pointer, or allocatable.
1180 // Characteristics, including dynamic length type parameter values,
1181 // must be taken from the MOLD argument.
1182 }
1183 }
1184 // No match
peter klausler7bda1b32018-10-12 23:01:551185 if (finalBuffer) {
peter klausler62425d62018-10-12 00:01:311186 if (genericBuffer.empty()) {
peter klausler7bda1b32018-10-12 23:01:551187 finalBuffer->Annex(std::move(specificBuffer));
peter klausler62425d62018-10-12 00:01:311188 } else {
peter klausler7bda1b32018-10-12 23:01:551189 finalBuffer->Annex(std::move(genericBuffer));
peter klausler62425d62018-10-12 00:01:311190 }
peter klauslercb308d32018-10-05 18:32:541191 }
peter klausler75a32092018-10-05 16:57:531192 return std::nullopt;
1193}
1194
peter klauslera62636f2018-10-08 22:35:191195IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:541196 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:111197 delete impl_;
1198 impl_ = nullptr;
1199}
1200
peter klauslera62636f2018-10-08 22:35:191201IntrinsicProcTable IntrinsicProcTable::Configure(
peter klauslerbf339f82018-10-15 22:28:471202 const semantics::IntrinsicTypeDefaultKinds &defaults) {
peter klauslera62636f2018-10-08 22:35:191203 IntrinsicProcTable result;
1204 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:111205 return result;
1206}
1207
peter klauslera62636f2018-10-08 22:35:191208std::optional<SpecificIntrinsic> IntrinsicProcTable::Probe(
peter klauslercb308d32018-10-05 18:32:541209 const CallCharacteristics &call,
1210 parser::ContextualMessages *messages) const {
peter klauslera62636f2018-10-08 22:35:191211 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klauslercb308d32018-10-05 18:32:541212 return impl_->Probe(call, messages);
peter klausler42b33da2018-09-29 00:02:111213}
peter klauslerad9aede2018-10-11 21:51:141214
1215std::ostream &SpecificIntrinsic::Dump(std::ostream &o) const {
1216 return o << name;
1217}
peter klausler7bda1b32018-10-12 23:01:551218
1219std::ostream &TypePattern::Dump(std::ostream &o) const {
1220 if (categorySet == AnyType) {
1221 o << "any type";
1222 } else {
1223 const char *sep = "";
1224 auto set{categorySet};
1225 while (auto least{set.LeastElement()}) {
1226 o << sep << EnumToString(*least);
1227 sep = " or ";
1228 set.reset(*least);
1229 }
1230 }
1231 o << '(' << EnumToString(kindCode) << ')';
1232 return o;
1233}
1234
1235std::ostream &IntrinsicDummyArgument::Dump(std::ostream &o) const {
1236 if (keyword) {
1237 o << keyword << '=';
1238 }
1239 return typePattern.Dump(o)
1240 << ' ' << EnumToString(rank) << ' ' << EnumToString(optionality);
1241}
1242
1243std::ostream &IntrinsicInterface::Dump(std::ostream &o) const {
1244 o << name;
1245 char sep{'('};
1246 for (const auto &d : dummy) {
1247 if (d.typePattern.kindCode == KindCode::none) {
1248 break;
1249 }
1250 d.Dump(o << sep);
1251 sep = ',';
1252 }
1253 if (sep == '(') {
1254 o << "()";
1255 }
1256 return result.Dump(o << " -> ") << ' ' << EnumToString(rank);
1257}
1258
1259std::ostream &IntrinsicProcTable::Implementation::Dump(std::ostream &o) const {
1260 o << "generic intrinsic functions:\n";
1261 for (const auto &iter : genericFuncs) {
1262 iter.second->Dump(o << iter.first << ": ") << '\n';
1263 }
1264 o << "specific intrinsic functions:\n";
1265 for (const auto &iter : specificFuncs) {
1266 iter.second->Dump(o << iter.first << ": ");
1267 if (const char *g{iter.second->generic}) {
1268 o << " -> " << g;
1269 }
1270 o << '\n';
1271 }
1272 return o;
1273}
1274
1275std::ostream &IntrinsicProcTable::Dump(std::ostream &o) const {
1276 return impl_->Dump(o);
1277}
Jean Perierf7e7cb32018-10-25 12:55:231278}