blob: 8f133f38ff33cf623a1ad7ebd2632236b4cc854b [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 klauslerabac2282018-10-26 22:10:2417#include "tools.h"
peter klausler42b33da2018-09-29 00:02:1118#include "type.h"
19#include "../common/enum-set.h"
20#include "../common/fortran.h"
peter klauslera70f5962018-10-04 20:43:3321#include "../common/idioms.h"
peter klauslerbf339f82018-10-15 22:28:4722#include "../semantics/default-kinds.h"
peter klausler84ea49d2018-10-18 17:50:5523#include <algorithm>
peter klauslera70f5962018-10-04 20:43:3324#include <map>
peter klausler7bda1b32018-10-12 23:01:5525#include <ostream>
26#include <sstream>
peter klauslera70f5962018-10-04 20:43:3327#include <string>
28#include <utility>
peter klausler42b33da2018-09-29 00:02:1129
peter klauslercb308d32018-10-05 18:32:5430using namespace Fortran::parser::literals;
31
peter klausler42b33da2018-09-29 00:02:1132namespace Fortran::evaluate {
33
34using common::TypeCategory;
35
peter klauslera70f5962018-10-04 20:43:3336// This file defines the supported intrinsic procedures and implements
37// their recognition and validation. It is largely table-driven. See
38// documentation/intrinsics.md and section 16 of the Fortran 2018 standard
39// for full details on each of the intrinsics. Be advised, they have
40// complicated details, and the design of these tables has to accommodate
41// that complexity.
42
peter klausler42b33da2018-09-29 00:02:1143// Dummy arguments to generic intrinsic procedures are each specified by
peter klauslera70f5962018-10-04 20:43:3344// their keyword name (rarely used, but always defined), allowable type
peter klauslercb308d32018-10-05 18:32:5445// categories, a kind pattern, a rank pattern, and information about
46// optionality and defaults. The kind and rank patterns are represented
47// here with code values that are significant to the matching/validation engine.
peter klausler42b33da2018-09-29 00:02:1148
peter klauslera70f5962018-10-04 20:43:3349// These are small bit-sets of type category enumerators.
50// Note that typeless (BOZ literal) values don't have a distinct type category.
51// These typeless arguments are represented in the tables as if they were
52// INTEGER with a special "typeless" kind code. Arguments of intrinsic types
peter klauslercb308d32018-10-05 18:32:5453// that can also be be typeless values are encoded with an "elementalOrBOZ"
54// rank pattern.
peter klauslera70f5962018-10-04 20:43:3355using CategorySet = common::EnumSet<TypeCategory, 8>;
peter klausler51b09b62018-10-15 19:17:3056static constexpr CategorySet IntType{TypeCategory::Integer};
57static constexpr CategorySet RealType{TypeCategory::Real};
58static constexpr CategorySet ComplexType{TypeCategory::Complex};
59static constexpr CategorySet CharType{TypeCategory::Character};
60static constexpr CategorySet LogicalType{TypeCategory::Logical};
61static constexpr CategorySet IntOrRealType{IntType | RealType};
62static constexpr CategorySet FloatingType{RealType | ComplexType};
63static constexpr CategorySet NumericType{IntType | RealType | ComplexType};
64static constexpr CategorySet RelatableType{IntType | RealType | CharType};
peter klauslera70f5962018-10-04 20:43:3365static constexpr CategorySet IntrinsicType{
peter klausler51b09b62018-10-15 19:17:3066 IntType | RealType | ComplexType | CharType | LogicalType};
peter klauslera70f5962018-10-04 20:43:3367static constexpr CategorySet AnyType{
68 IntrinsicType | CategorySet{TypeCategory::Derived}};
peter klausler42b33da2018-09-29 00:02:1169
peter klausler7bda1b32018-10-12 23:01:5570ENUM_CLASS(KindCode, none, defaultIntegerKind,
71 defaultRealKind, // is also the default COMPLEX kind
72 doublePrecision, defaultCharKind, defaultLogicalKind,
73 any, // matches any kind value; each instance is independent
74 typeless, // BOZ literals are INTEGER with this kind
75 teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
76 kindArg, // this argument is KIND=
77 effectiveKind, // for function results: same "kindArg", possibly defaulted
78 dimArg, // this argument is DIM=
79 same, // match any kind; all "same" kinds must be equal
80 likeMultiply, // for DOT_PRODUCT and MATMUL
81)
peter klausler42b33da2018-09-29 00:02:1182
83struct TypePattern {
84 CategorySet categorySet;
peter klauslerb22d4942018-10-01 18:27:4585 KindCode kindCode{KindCode::none};
peter klausler7bda1b32018-10-12 23:01:5586 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:1187};
88
peter klauslera70f5962018-10-04 20:43:3389// Abbreviations for argument and result patterns in the intrinsic prototypes:
90
91// Match specific kinds of intrinsic types
peter klausler7c402d92018-10-16 21:42:2292static constexpr TypePattern DefaultInt{IntType, KindCode::defaultIntegerKind};
93static constexpr TypePattern DefaultReal{RealType, KindCode::defaultRealKind};
94static constexpr TypePattern DefaultComplex{
95 ComplexType, KindCode::defaultRealKind};
96static constexpr TypePattern DefaultChar{CharType, KindCode::defaultCharKind};
97static constexpr TypePattern DefaultLogical{
peter klausler51b09b62018-10-15 19:17:3098 LogicalType, KindCode::defaultLogicalKind};
99static constexpr TypePattern BOZ{IntType, KindCode::typeless};
100static constexpr TypePattern TEAM_TYPE{IntType, KindCode::teamType};
101static constexpr TypePattern DoublePrecision{
102 RealType, KindCode::doublePrecision};
peter klauslera70f5962018-10-04 20:43:33103
104// Match any kind of some intrinsic or derived types
peter klausler51b09b62018-10-15 19:17:30105static constexpr TypePattern AnyInt{IntType, KindCode::any};
106static constexpr TypePattern AnyReal{RealType, KindCode::any};
107static constexpr TypePattern AnyIntOrReal{IntOrRealType, KindCode::any};
108static constexpr TypePattern AnyComplex{ComplexType, KindCode::any};
109static constexpr TypePattern AnyNumeric{NumericType, KindCode::any};
110static constexpr TypePattern AnyChar{CharType, KindCode::any};
111static constexpr TypePattern AnyLogical{LogicalType, KindCode::any};
112static constexpr TypePattern AnyRelatable{RelatableType, KindCode::any};
peter klauslerf7f2a732018-10-09 19:07:29113static constexpr TypePattern Anything{AnyType, KindCode::any};
peter klauslera70f5962018-10-04 20:43:33114
115// Match some kind of some intrinsic type(s); all "Same" values must match,
116// even when not in the same category (e.g., SameComplex and SameReal).
117// Can be used to specify a result so long as at least one argument is
118// a "Same".
peter klausler51b09b62018-10-15 19:17:30119static constexpr TypePattern SameInt{IntType, KindCode::same};
120static constexpr TypePattern SameReal{RealType, KindCode::same};
121static constexpr TypePattern SameIntOrReal{IntOrRealType, KindCode::same};
122static constexpr TypePattern SameComplex{ComplexType, KindCode::same};
123static constexpr TypePattern SameFloating{FloatingType, KindCode::same};
124static constexpr TypePattern SameNumeric{NumericType, KindCode::same};
125static constexpr TypePattern SameChar{CharType, KindCode::same};
126static constexpr TypePattern SameLogical{LogicalType, KindCode::same};
127static constexpr TypePattern SameRelatable{RelatableType, KindCode::same};
peter klauslera70f5962018-10-04 20:43:33128static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
129static constexpr TypePattern SameDerivedType{
130 CategorySet{TypeCategory::Derived}, KindCode::same};
131static constexpr TypePattern SameType{AnyType, KindCode::same};
132
peter klauslerf7f2a732018-10-09 19:07:29133// For DOT_PRODUCT and MATMUL, the result type depends on the arguments
peter klausler51b09b62018-10-15 19:17:30134static constexpr TypePattern ResultLogical{LogicalType, KindCode::likeMultiply};
135static constexpr TypePattern ResultNumeric{NumericType, KindCode::likeMultiply};
peter klauslerf7f2a732018-10-09 19:07:29136
peter klauslera70f5962018-10-04 20:43:33137// Result types with known category and KIND=
peter klausler51b09b62018-10-15 19:17:30138static constexpr TypePattern KINDInt{IntType, KindCode::effectiveKind};
139static constexpr TypePattern KINDReal{RealType, KindCode::effectiveKind};
140static constexpr TypePattern KINDComplex{ComplexType, KindCode::effectiveKind};
141static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind};
142static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
peter klausler42b33da2018-09-29 00:02:11143
144// The default rank pattern for dummy arguments and function results is
145// "elemental".
peter klausler7bda1b32018-10-12 23:01:55146ENUM_CLASS(Rank,
147 elemental, // scalar, or array that conforms with other array arguments
148 elementalOrBOZ, // elemental, or typeless BOZ literal scalar
149 scalar, vector,
150 shape, // INTEGER vector of known length and no negative element
151 matrix,
152 array, // not scalar, rank is known and greater than zero
153 known, // rank is known and can be scalar
154 anyOrAssumedRank, // rank can be unknown
155 conformable, // scalar, or array of same rank & shape as "array" argument
156 reduceOperation, // a pure function with constraints for REDUCE
157 dimReduced, // scalar if no DIM= argument, else rank(array)-1
158 dimRemoved, // scalar, or rank(array)-1
159 rankPlus1, // rank(known)+1
160 shaped, // rank is length of SHAPE vector
161)
peter klausler42b33da2018-09-29 00:02:11162
peter klausler7bda1b32018-10-12 23:01:55163ENUM_CLASS(Optionality, required, optional,
164 defaultsToSameKind, // for MatchingDefaultKIND
165 defaultsToDefaultForResult, // for DefaultingKIND
peter klausler7c402d92018-10-16 21:42:22166 defaultsToSubscriptKind, // for SubscriptDefaultKIND
peter klausler7bda1b32018-10-12 23:01:55167 repeats, // for MAX/MIN and their several variants
168)
peter klausler42b33da2018-09-29 00:02:11169
170struct IntrinsicDummyArgument {
peter klauslerb22d4942018-10-01 18:27:45171 const char *keyword{nullptr};
peter klausler42b33da2018-09-29 00:02:11172 TypePattern typePattern;
peter klauslera70f5962018-10-04 20:43:33173 Rank rank{Rank::elemental};
peter klauslercb308d32018-10-05 18:32:54174 Optionality optionality{Optionality::required};
peter klausler7bda1b32018-10-12 23:01:55175 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11176};
177
peter klauslera70f5962018-10-04 20:43:33178// constexpr abbreviations for popular arguments:
179// DefaultingKIND is a KIND= argument whose default value is the appropriate
180// KIND(0), KIND(0.0), KIND(''), &c. value for the function result.
peter klauslercb308d32018-10-05 18:32:54181static constexpr IntrinsicDummyArgument DefaultingKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30182 {IntType, KindCode::kindArg}, Rank::scalar,
peter klauslercb308d32018-10-05 18:32:54183 Optionality::defaultsToDefaultForResult};
peter klauslera70f5962018-10-04 20:43:33184// MatchingDefaultKIND is a KIND= argument whose default value is the
185// kind of any "Same" function argument (viz., the one whose kind pattern is
186// "same").
peter klauslercb308d32018-10-05 18:32:54187static constexpr IntrinsicDummyArgument MatchingDefaultKIND{"kind",
peter klausler51b09b62018-10-15 19:17:30188 {IntType, KindCode::kindArg}, Rank::scalar,
189 Optionality::defaultsToSameKind};
peter klausler7c402d92018-10-16 21:42:22190// SubscriptDefaultKind is a KIND= argument whose default value is
191// the kind of INTEGER used for address calculations.
192static constexpr IntrinsicDummyArgument SubscriptDefaultKIND{"kind",
193 {IntType, KindCode::kindArg}, Rank::scalar,
194 Optionality::defaultsToSubscriptKind};
peter klauslera70f5962018-10-04 20:43:33195static constexpr IntrinsicDummyArgument OptionalDIM{
peter klausler51b09b62018-10-15 19:17:30196 "dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional};
peter klauslera70f5962018-10-04 20:43:33197static constexpr IntrinsicDummyArgument OptionalMASK{
peter klauslercb308d32018-10-05 18:32:54198 "mask", AnyLogical, Rank::conformable, Optionality::optional};
peter klausler42b33da2018-09-29 00:02:11199
200struct IntrinsicInterface {
peter klausler84ea49d2018-10-18 17:50:55201 static constexpr int maxArguments{7}; // if not a MAX/MIN(...)
peter klauslerb22d4942018-10-01 18:27:45202 const char *name{nullptr};
peter klausler42b33da2018-09-29 00:02:11203 IntrinsicDummyArgument dummy[maxArguments];
204 TypePattern result;
peter klauslera70f5962018-10-04 20:43:33205 Rank rank{Rank::elemental};
peter klausleref9dd9d2018-10-17 22:09:48206 std::optional<SpecificCall> Match(const CallCharacteristics &,
207 const semantics::IntrinsicTypeDefaultKinds &, ActualArguments &,
peter klauslercb308d32018-10-05 18:32:54208 parser::ContextualMessages &messages) const;
peter klausler7bda1b32018-10-12 23:01:55209 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:11210};
211
peter klausler94041d72018-10-15 20:39:51212// GENERIC INTRINSIC FUNCTION INTERFACES
213// Each entry in this table defines a pattern. Some intrinsic
214// functions have more than one such pattern. Besides the name
215// of the intrinsic function, each pattern has specifications for
216// the dummy arguments and for the result of the function.
217// The dummy argument patterns each have a name (this are from the
218// standard, but rarely appear in actual code), a type and kind
219// pattern, allowable ranks, and optionality indicators.
220// Be advised, the default rank pattern is "elemental".
peter klauslerb22d4942018-10-01 18:27:45221static const IntrinsicInterface genericIntrinsicFunction[]{
peter klauslera70f5962018-10-04 20:43:33222 {"abs", {{"a", SameIntOrReal}}, SameIntOrReal},
223 {"abs", {{"a", SameComplex}}, SameReal},
peter klauslerad9aede2018-10-11 21:51:14224 {"achar", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
peter klauslera70f5962018-10-04 20:43:33225 {"acos", {{"x", SameFloating}}, SameFloating},
226 {"acosh", {{"x", SameFloating}}, SameFloating},
227 {"adjustl", {{"string", SameChar}}, SameChar},
228 {"adjustr", {{"string", SameChar}}, SameChar},
229 {"aimag", {{"x", SameComplex}}, SameReal},
230 {"aint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
231 {"all", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
232 Rank::dimReduced},
233 {"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
234 {"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
235 Rank::dimReduced},
236 {"asin", {{"x", SameFloating}}, SameFloating},
237 {"asinh", {{"x", SameFloating}}, SameFloating},
238 {"atan", {{"x", SameFloating}}, SameFloating},
239 {"atan", {{"y", SameReal}, {"x", SameReal}}, SameReal},
240 {"atan2", {{"y", SameReal}, {"x", SameReal}}, SameReal},
241 {"atanh", {{"x", SameFloating}}, SameFloating},
242 {"bessel_j0", {{"x", SameReal}}, SameReal},
243 {"bessel_j1", {{"x", SameReal}}, SameReal},
244 {"bessel_jn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29245 {"bessel_jn",
246 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
247 {"x", SameReal, Rank::scalar}},
248 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33249 {"bessel_y0", {{"x", SameReal}}, SameReal},
250 {"bessel_y1", {{"x", SameReal}}, SameReal},
251 {"bessel_yn", {{"n", AnyInt}, {"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29252 {"bessel_yn",
253 {{"n1", AnyInt, Rank::scalar}, {"n2", AnyInt, Rank::scalar},
254 {"x", SameReal, Rank::scalar}},
255 SameReal, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33256 {"bge",
peter klauslercb308d32018-10-05 18:32:54257 {{"i", AnyInt, Rank::elementalOrBOZ},
258 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22259 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33260 {"bgt",
peter klauslercb308d32018-10-05 18:32:54261 {{"i", AnyInt, Rank::elementalOrBOZ},
262 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22263 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33264 {"ble",
peter klauslercb308d32018-10-05 18:32:54265 {{"i", AnyInt, Rank::elementalOrBOZ},
266 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22267 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33268 {"blt",
peter klauslercb308d32018-10-05 18:32:54269 {{"i", AnyInt, Rank::elementalOrBOZ},
270 {"j", AnyInt, Rank::elementalOrBOZ}},
peter klausler7c402d92018-10-16 21:42:22271 DefaultLogical},
272 {"btest", {{"i", AnyInt}, {"pos", AnyInt}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33273 {"ceiling", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
274 {"char", {{"i", AnyInt}, DefaultingKIND}, KINDChar},
275 {"cmplx", {{"x", AnyComplex}, DefaultingKIND}, KINDComplex},
peter klausler42b33da2018-09-29 00:02:11276 {"cmplx",
peter klauslercb308d32018-10-05 18:32:54277 {{"x", SameIntOrReal, Rank::elementalOrBOZ},
278 {"y", SameIntOrReal, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33279 KINDComplex},
peter klausler7c402d92018-10-16 21:42:22280 {"command_argument_count", {}, DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33281 {"conjg", {{"z", SameComplex}}, SameComplex},
282 {"cos", {{"x", SameFloating}}, SameFloating},
283 {"cosh", {{"x", SameFloating}}, SameFloating},
284 {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
285 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11286 {"cshift",
peter klauslera70f5962018-10-04 20:43:33287 {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
288 OptionalDIM},
289 SameType, Rank::array},
peter klausleref9dd9d2018-10-17 22:09:48290 {"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33291 {"dim", {{"x", SameIntOrReal}, {"y", SameIntOrReal}}, SameIntOrReal},
peter klauslerf7f2a732018-10-09 19:07:29292 {"dot_product",
293 {{"vector_a", AnyLogical, Rank::vector},
294 {"vector_b", AnyLogical, Rank::vector}},
295 ResultLogical, Rank::scalar},
296 {"dot_product",
297 {{"vector_a", AnyComplex, Rank::vector},
298 {"vector_b", AnyNumeric, Rank::vector}},
299 ResultNumeric, Rank::scalar}, // conjugates vector_a
300 {"dot_product",
301 {{"vector_a", AnyIntOrReal, Rank::vector},
302 {"vector_b", AnyNumeric, Rank::vector}},
303 ResultNumeric, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22304 {"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision},
peter klauslera70f5962018-10-04 20:43:33305 {"dshiftl",
peter klauslercb308d32018-10-05 18:32:54306 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33307 {"shift", AnyInt}},
308 SameInt},
309 {"dshiftl", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
310 {"dshiftr",
peter klauslercb308d32018-10-05 18:32:54311 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
peter klauslera70f5962018-10-04 20:43:33312 {"shift", AnyInt}},
313 SameInt},
314 {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
peter klausler42b33da2018-09-29 00:02:11315 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33316 {{"array", SameIntrinsic, Rank::array},
317 {"shift", AnyInt, Rank::dimRemoved},
peter klauslercb308d32018-10-05 18:32:54318 {"boundary", SameIntrinsic, Rank::dimRemoved,
319 Optionality::optional},
peter klauslera70f5962018-10-04 20:43:33320 OptionalDIM},
321 SameIntrinsic, Rank::array},
peter klausler42b33da2018-09-29 00:02:11322 {"eoshift",
peter klauslera70f5962018-10-04 20:43:33323 {{"array", SameDerivedType, Rank::array},
324 {"shift", AnyInt, Rank::dimRemoved},
325 {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
326 SameDerivedType, Rank::array},
327 {"erf", {{"x", SameReal}}, SameReal},
328 {"erfc", {{"x", SameReal}}, SameReal},
329 {"erfc_scaled", {{"x", SameReal}}, SameReal},
330 {"exp", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22331 {"exponent", {{"x", AnyReal}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11332 {"findloc",
peter klauslerad9aede2018-10-11 21:51:14333 {{"array", AnyNumeric, Rank::array},
334 {"value", AnyNumeric, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22335 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54336 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33337 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11338 {"findloc",
peter klauslera70f5962018-10-04 20:43:33339 {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22340 OptionalDIM, OptionalMASK, SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54341 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33342 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11343 {"findloc",
peter klauslera70f5962018-10-04 20:43:33344 {{"array", AnyLogical, Rank::array},
345 {"value", AnyLogical, Rank::scalar}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22346 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54347 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33348 KINDInt, Rank::dimReduced},
349 {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
350 {"fraction", {{"x", SameReal}}, SameReal},
351 {"gamma", {{"x", SameReal}}, SameReal},
352 {"hypot", {{"x", SameReal}, {"y", SameReal}}, SameReal},
353 {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
354 {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
355 SameInt, Rank::dimReduced},
356 {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
357 SameInt, Rank::dimReduced},
358 {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
359 SameInt, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54360 {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33361 {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
362 {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
363 {"ibits", {{"i", SameInt}, {"pos", AnyInt}, {"len", AnyInt}}, SameInt},
364 {"ibset", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
365 {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
peter klauslercb308d32018-10-05 18:32:54366 {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33367 {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt},
368 {"image_status",
peter klauslercb308d32018-10-05 18:32:54369 {{"image", SameInt},
370 {"team", TEAM_TYPE, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22371 DefaultInt},
peter klausler42b33da2018-09-29 00:02:11372 {"index",
peter klauslera70f5962018-10-04 20:43:33373 {{"string", SameChar}, {"substring", SameChar},
peter klauslercb308d32018-10-05 18:32:54374 {"back", AnyLogical, Rank::scalar, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22375 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33376 KINDInt},
peter klauslercb308d32018-10-05 18:32:54377 {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt},
378 {"ior", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
peter klauslera70f5962018-10-04 20:43:33379 {"ior", {{"i", BOZ}, {"j", SameInt}}, SameInt},
380 {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
381 {"ishftc",
382 {{"i", SameInt}, {"shift", AnyInt},
peter klauslercb308d32018-10-05 18:32:54383 {"size", AnyInt, Rank::elemental, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33384 SameInt},
peter klausler7c402d92018-10-16 21:42:22385 {"is_iostat_end", {{"i", AnyInt}}, DefaultLogical},
386 {"is_iostat_eor", {{"i", AnyInt}}, DefaultLogical},
387 {"lbound",
388 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29389 KINDInt, Rank::vector},
390 {"lbound",
391 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22392 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
393 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29394 KINDInt, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22395 {"leadz", {{"i", AnyInt}}, DefaultInt},
396 {"len", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
397 {"len_trim", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
398 {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
399 {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
400 {"lle", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
401 {"llt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33402 {"log", {{"x", SameFloating}}, SameFloating},
403 {"log10", {{"x", SameReal}}, SameReal},
404 {"logical", {{"l", AnyLogical}, DefaultingKIND}, KINDLogical},
405 {"log_gamma", {{"x", SameReal}}, SameReal},
peter klauslerf7f2a732018-10-09 19:07:29406 {"matmul",
407 {{"array_a", AnyLogical, Rank::vector},
408 {"array_b", AnyLogical, Rank::matrix}},
409 ResultLogical, Rank::vector},
410 {"matmul",
411 {{"array_a", AnyLogical, Rank::matrix},
412 {"array_b", AnyLogical, Rank::vector}},
413 ResultLogical, Rank::vector},
414 {"matmul",
415 {{"array_a", AnyLogical, Rank::matrix},
416 {"array_b", AnyLogical, Rank::matrix}},
417 ResultLogical, Rank::matrix},
418 {"matmul",
419 {{"array_a", AnyNumeric, Rank::vector},
420 {"array_b", AnyNumeric, Rank::matrix}},
421 ResultNumeric, Rank::vector},
422 {"matmul",
423 {{"array_a", AnyNumeric, Rank::matrix},
424 {"array_b", AnyNumeric, Rank::vector}},
425 ResultNumeric, Rank::vector},
426 {"matmul",
427 {{"array_a", AnyNumeric, Rank::matrix},
428 {"array_b", AnyNumeric, Rank::matrix}},
429 ResultNumeric, Rank::matrix},
peter klauslera70f5962018-10-04 20:43:33430 {"maskl", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
431 {"maskr", {{"i", AnyInt}, DefaultingKIND}, KINDInt},
peter klauslerad9aede2018-10-11 21:51:14432 {"max",
433 {{"a1", SameRelatable}, {"a2", SameRelatable},
434 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
435 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11436 {"maxloc",
peter klauslera70f5962018-10-04 20:43:33437 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22438 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54439 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33440 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11441 {"maxval",
peter klauslera70f5962018-10-04 20:43:33442 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
443 SameRelatable, Rank::dimReduced},
peter klauslerad9aede2018-10-11 21:51:14444 {"merge",
445 {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
446 SameType},
peter klausler42b33da2018-09-29 00:02:11447 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54448 {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ},
449 {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33450 SameInt},
451 {"merge_bits",
peter klauslercb308d32018-10-05 18:32:54452 {{"i", BOZ}, {"j", SameInt}, {"mask", SameInt, Rank::elementalOrBOZ}},
peter klauslera70f5962018-10-04 20:43:33453 SameInt},
peter klauslerad9aede2018-10-11 21:51:14454 {"min",
455 {{"a1", SameRelatable}, {"a2", SameRelatable},
456 {"a3", SameRelatable, Rank::elemental, Optionality::repeats}},
457 SameRelatable},
peter klausler42b33da2018-09-29 00:02:11458 {"minloc",
peter klauslera70f5962018-10-04 20:43:33459 {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
peter klausler7c402d92018-10-16 21:42:22460 SubscriptDefaultKIND,
peter klauslercb308d32018-10-05 18:32:54461 {"back", AnyLogical, Rank::scalar, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33462 KINDInt, Rank::dimReduced},
peter klausler42b33da2018-09-29 00:02:11463 {"minval",
peter klauslera70f5962018-10-04 20:43:33464 {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
465 SameRelatable, Rank::dimReduced},
466 {"mod", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
467 {"modulo", {{"a", SameIntOrReal}, {"p", SameIntOrReal}}, SameIntOrReal},
468 {"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
469 {"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
470 {"norm2", {{"x", SameReal, Rank::array}, OptionalDIM}, SameReal,
471 Rank::dimReduced},
472 {"not", {{"i", SameInt}}, SameInt},
peter klausler8efb8972018-10-10 17:48:12473 // NULL() is a special case handled in Probe() below
peter klausler42b33da2018-09-29 00:02:11474 {"out_of_range",
peter klauslerad9aede2018-10-11 21:51:14475 {{"x", AnyIntOrReal}, {"mold", AnyIntOrReal, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22476 DefaultLogical},
peter klauslera70f5962018-10-04 20:43:33477 {"out_of_range",
478 {{"x", AnyReal}, {"mold", AnyInt, Rank::scalar},
peter klauslercb308d32018-10-05 18:32:54479 {"round", AnyLogical, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22480 DefaultLogical},
481 {"out_of_range", {{"x", AnyReal}, {"mold", AnyReal}}, DefaultLogical},
peter klausler42b33da2018-09-29 00:02:11482 {"pack",
peter klauslera70f5962018-10-04 20:43:33483 {{"array", SameType, Rank::array},
484 {"mask", AnyLogical, Rank::conformable},
peter klauslercb308d32018-10-05 18:32:54485 {"vector", SameType, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33486 SameType, Rank::vector},
487 {"parity", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
488 Rank::dimReduced},
peter klausler7c402d92018-10-16 21:42:22489 {"popcnt", {{"i", AnyInt}}, DefaultInt},
490 {"poppar", {{"i", AnyInt}}, DefaultInt},
peter klausler42b33da2018-09-29 00:02:11491 {"product",
peter klauslera70f5962018-10-04 20:43:33492 {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
493 SameNumeric, Rank::dimReduced},
peter klauslercb308d32018-10-05 18:32:54494 {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
peter klauslera70f5962018-10-04 20:43:33495 KINDReal},
peter klauslerad9aede2018-10-11 21:51:14496 {"reduce",
497 {{"array", SameType, Rank::array},
498 {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
499 OptionalMASK, {"identity", SameType, Rank::scalar},
500 {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
501 SameType, Rank::dimReduced},
peter klausler24379cc2018-10-10 23:45:17502 {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
503 SameChar, Rank::scalar},
peter klausler42b33da2018-09-29 00:02:11504 {"reshape",
peter klauslera70f5962018-10-04 20:43:33505 {{"source", SameType, Rank::array}, {"shape", AnyInt, Rank::shape},
peter klauslercb308d32018-10-05 18:32:54506 {"pad", SameType, Rank::array, Optionality::optional},
507 {"order", AnyInt, Rank::vector, Optionality::optional}},
peter klauslera70f5962018-10-04 20:43:33508 SameType, Rank::shaped},
509 {"rrspacing", {{"x", SameReal}}, SameReal},
510 {"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11511 {"scan",
peter klauslera70f5962018-10-04 20:43:33512 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54513 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22514 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33515 KINDInt},
peter klausler7c402d92018-10-16 21:42:22516 {"selected_char_kind", {{"name", DefaultChar, Rank::scalar}}, DefaultInt,
peter klausler24379cc2018-10-10 23:45:17517 Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22518 {"selected_int_kind", {{"r", AnyInt, Rank::scalar}}, DefaultInt,
519 Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14520 {"selected_real_kind",
521 {{"p", AnyInt, Rank::scalar},
522 {"r", AnyInt, Rank::scalar, Optionality::optional},
523 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22524 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14525 {"selected_real_kind",
526 {{"p", AnyInt, Rank::scalar, Optionality::optional},
527 {"r", AnyInt, Rank::scalar},
528 {"radix", AnyInt, Rank::scalar, Optionality::optional}},
peter klausler7c402d92018-10-16 21:42:22529 DefaultInt, Rank::scalar},
peter klauslerad9aede2018-10-11 21:51:14530 {"selected_real_kind",
531 {{"p", AnyInt, Rank::scalar, Optionality::optional},
532 {"r", AnyInt, Rank::scalar, Optionality::optional},
533 {"radix", AnyInt, Rank::scalar}},
peter klausler7c402d92018-10-16 21:42:22534 DefaultInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33535 {"set_exponent", {{"x", SameReal}, {"i", AnyInt}}, SameReal},
peter klausler7c402d92018-10-16 21:42:22536 {"shape",
537 {{"source", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klausler24379cc2018-10-10 23:45:17538 KINDInt, Rank::vector},
peter klauslera70f5962018-10-04 20:43:33539 {"shifta", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
540 {"shiftl", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
541 {"shiftr", {{"i", SameInt}, {"shift", AnyInt}}, SameInt},
542 {"sign", {{"a", SameIntOrReal}, {"b", SameIntOrReal}}, SameIntOrReal},
543 {"sin", {{"x", SameFloating}}, SameFloating},
544 {"sinh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22545 {"size",
546 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29547 KINDInt, Rank::vector},
548 {"size",
549 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22550 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
551 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29552 KINDInt, Rank::scalar},
peter klauslera70f5962018-10-04 20:43:33553 {"spacing", {{"x", SameReal}}, SameReal},
peter klausler42b33da2018-09-29 00:02:11554 {"spread",
peter klauslera70f5962018-10-04 20:43:33555 {{"source", SameType, Rank::known},
peter klausler51b09b62018-10-15 19:17:30556 {"dim", {IntType, KindCode::dimArg}, Rank::scalar /*not optional*/},
peter klauslera70f5962018-10-04 20:43:33557 {"ncopies", AnyInt, Rank::scalar}},
558 SameType, Rank::rankPlus1},
559 {"sqrt", {{"x", SameFloating}}, SameFloating},
560 {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
561 SameNumeric, Rank::dimReduced},
562 {"tan", {{"x", SameFloating}}, SameFloating},
563 {"tanh", {{"x", SameFloating}}, SameFloating},
peter klausler7c402d92018-10-16 21:42:22564 {"trailz", {{"i", AnyInt}}, DefaultInt},
peter klauslerf7f2a732018-10-09 19:07:29565 {"transfer",
566 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::scalar}},
567 SameType, Rank::scalar},
568 {"transfer",
569 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::array}},
570 SameType, Rank::vector},
571 {"transfer",
572 {{"source", Anything, Rank::known}, {"mold", SameType, Rank::known},
573 {"size", AnyInt, Rank::scalar}},
574 SameType, Rank::vector},
575 {"transpose", {{"matrix", SameType, Rank::matrix}}, SameType, Rank::matrix},
peter klauslerad9aede2018-10-11 21:51:14576 {"trim", {{"string", SameChar, Rank::scalar}}, SameChar, Rank::scalar},
peter klausler7c402d92018-10-16 21:42:22577 {"ubound",
578 {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29579 KINDInt, Rank::vector},
580 {"ubound",
581 {{"array", Anything, Rank::anyOrAssumedRank},
peter klausler7c402d92018-10-16 21:42:22582 {"dim", {IntType, KindCode::dimArg}, Rank::scalar},
583 SubscriptDefaultKIND},
peter klauslerf7f2a732018-10-09 19:07:29584 KINDInt, Rank::scalar},
585 {"unpack",
586 {{"vector", SameType, Rank::vector}, {"mask", AnyLogical, Rank::array},
587 {"field", SameType, Rank::conformable}},
588 SameType, Rank::conformable},
peter klausler42b33da2018-09-29 00:02:11589 {"verify",
peter klauslera70f5962018-10-04 20:43:33590 {{"string", SameChar}, {"set", SameChar},
peter klauslercb308d32018-10-05 18:32:54591 {"back", AnyLogical, Rank::elemental, Optionality::optional},
peter klausler7c402d92018-10-16 21:42:22592 SubscriptDefaultKIND},
peter klauslera70f5962018-10-04 20:43:33593 KINDInt},
peter klausler42b33da2018-09-29 00:02:11594};
595
peter klausler8efb8972018-10-10 17:48:12596// TODO: Coarray intrinsic functions
peter klauslerad9aede2018-10-11 21:51:14597// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
598// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
599// COSHAPE
peter klausler8efb8972018-10-10 17:48:12600// TODO: Object characteristic inquiry functions
peter klauslerad9aede2018-10-11 21:51:14601// ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS,
602// PRESENT, RANK, SAME_TYPE, STORAGE_SIZE
603// TODO: Type inquiry intrinsic functions - these return constants
604// BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT,
605// NEW_LINE, PRECISION, RADIX, RANGE, TINY
606// TODO: Non-standard intrinsic functions
607// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
608// COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL,
609// DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC,
610// QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM,
611// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
612// MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
613// IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
614// EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
615// probably more (these are PGI + Intel, possibly incomplete)
peter klausler42b33da2018-09-29 00:02:11616
617struct SpecificIntrinsicInterface : public IntrinsicInterface {
618 const char *generic{nullptr};
peter klauslerad9aede2018-10-11 21:51:14619 bool isRestrictedSpecific{
620 false}; // when true, can only be called, not passed
peter klausler42b33da2018-09-29 00:02:11621};
622
peter klauslerb22d4942018-10-01 18:27:45623static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
peter klausler7c402d92018-10-16 21:42:22624 {{"abs", {{"a", DefaultReal}}, DefaultReal}},
625 {{"acos", {{"x", DefaultReal}}, DefaultReal}},
626 {{"aimag", {{"z", DefaultComplex}}, DefaultReal}},
627 {{"aint", {{"a", DefaultReal}}, DefaultReal}},
628 {{"alog", {{"x", DefaultReal}}, DefaultReal}, "log"},
629 {{"alog10", {{"x", DefaultReal}}, DefaultReal}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14630 {{"amax0",
peter klausler7c402d92018-10-16 21:42:22631 {{"a1", DefaultInt}, {"a2", DefaultInt},
632 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
633 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14634 "max", true},
635 {{"amax1",
peter klausler7c402d92018-10-16 21:42:22636 {{"a1", DefaultReal}, {"a2", DefaultReal},
637 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
638 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14639 "max", true},
640 {{"amin0",
peter klausler7c402d92018-10-16 21:42:22641 {{"a1", DefaultInt}, {"a2", DefaultInt},
642 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
643 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14644 "min", true},
645 {{"amin1",
peter klausler7c402d92018-10-16 21:42:22646 {{"a1", DefaultReal}, {"a2", DefaultReal},
647 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
648 DefaultReal},
peter klauslerad9aede2018-10-11 21:51:14649 "min", true},
peter klausler7c402d92018-10-16 21:42:22650 {{"amod", {{"a", DefaultReal}, {"p", DefaultReal}}, DefaultReal}, "mod"},
651 {{"anint", {{"a", DefaultReal}}, DefaultReal}},
652 {{"asin", {{"x", DefaultReal}}, DefaultReal}},
653 {{"atan", {{"x", DefaultReal}}, DefaultReal}},
654 {{"atan2", {{"y", DefaultReal}, {"x", DefaultReal}}, DefaultReal}},
655 {{"cabs", {{"a", DefaultComplex}}, DefaultReal}, "abs"},
656 {{"ccos", {{"a", DefaultComplex}}, DefaultComplex}, "cos"},
657 {{"cexp", {{"a", DefaultComplex}}, DefaultComplex}, "exp"},
658 {{"clog", {{"a", DefaultComplex}}, DefaultComplex}, "log"},
659 {{"conjg", {{"a", DefaultComplex}}, DefaultComplex}},
660 {{"cos", {{"x", DefaultReal}}, DefaultReal}},
661 {{"csin", {{"a", DefaultComplex}}, DefaultComplex}, "sin"},
662 {{"csqrt", {{"a", DefaultComplex}}, DefaultComplex}, "sqrt"},
663 {{"ctan", {{"a", DefaultComplex}}, DefaultComplex}, "tan"},
peter klauslera70f5962018-10-04 20:43:33664 {{"dabs", {{"a", DoublePrecision}}, DoublePrecision}, "abs"},
665 {{"dacos", {{"x", DoublePrecision}}, DoublePrecision}, "acos"},
666 {{"dasin", {{"x", DoublePrecision}}, DoublePrecision}, "asin"},
667 {{"datan", {{"x", DoublePrecision}}, DoublePrecision}, "atan"},
668 {{"datan2", {{"y", DoublePrecision}, {"x", DoublePrecision}},
669 DoublePrecision},
670 "atan2"},
peter klauslera70f5962018-10-04 20:43:33671 {{"dcos", {{"x", DoublePrecision}}, DoublePrecision}, "cos"},
672 {{"dcosh", {{"x", DoublePrecision}}, DoublePrecision}, "cosh"},
673 {{"ddim", {{"x", DoublePrecision}, {"y", DoublePrecision}},
674 DoublePrecision},
675 "dim"},
676 {{"dexp", {{"x", DoublePrecision}}, DoublePrecision}, "exp"},
peter klausler7c402d92018-10-16 21:42:22677 {{"dim", {{"x", DefaultReal}, {"y", DefaultReal}}, DefaultReal}},
peter klauslera70f5962018-10-04 20:43:33678 {{"dint", {{"a", DoublePrecision}}, DoublePrecision}, "aint"},
679 {{"dlog", {{"x", DoublePrecision}}, DoublePrecision}, "log"},
680 {{"dlog10", {{"x", DoublePrecision}}, DoublePrecision}, "log10"},
peter klauslerad9aede2018-10-11 21:51:14681 {{"dmax1",
682 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
683 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
684 DoublePrecision},
685 "max", true},
686 {{"dmin1",
687 {{"a1", DoublePrecision}, {"a2", DoublePrecision},
688 {"a3", DoublePrecision, Rank::elemental, Optionality::repeats}},
689 DoublePrecision},
690 "min", true},
peter klauslera70f5962018-10-04 20:43:33691 {{"dmod", {{"a", DoublePrecision}, {"p", DoublePrecision}},
692 DoublePrecision},
693 "mod"},
694 {{"dnint", {{"a", DoublePrecision}}, DoublePrecision}, "anint"},
peter klausler7c402d92018-10-16 21:42:22695 {{"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision}},
peter klauslera70f5962018-10-04 20:43:33696 {{"dsign", {{"a", DoublePrecision}, {"b", DoublePrecision}},
697 DoublePrecision},
698 "sign"},
699 {{"dsin", {{"x", DoublePrecision}}, DoublePrecision}, "sin"},
700 {{"dsinh", {{"x", DoublePrecision}}, DoublePrecision}, "sinh"},
701 {{"dsqrt", {{"x", DoublePrecision}}, DoublePrecision}, "sqrt"},
702 {{"dtan", {{"x", DoublePrecision}}, DoublePrecision}, "tan"},
703 {{"dtanh", {{"x", DoublePrecision}}, DoublePrecision}, "tanh"},
peter klausler7c402d92018-10-16 21:42:22704 {{"exp", {{"x", DefaultReal}}, DefaultReal}},
705 {{"float", {{"i", DefaultInt}}, DefaultReal}, "real", true},
706 {{"iabs", {{"a", DefaultInt}}, DefaultInt}, "abs"},
707 {{"idim", {{"x", DefaultInt}, {"y", DefaultInt}}, DefaultInt}, "dim"},
708 {{"idint", {{"a", DoublePrecision}}, DefaultInt}, "int", true},
709 {{"idnint", {{"a", DoublePrecision}}, DefaultInt}, "nint"},
710 {{"ifix", {{"a", DefaultReal}}, DefaultInt}, "int", true},
711 {{"index", {{"string", DefaultChar}, {"substring", DefaultChar}},
712 DefaultInt}},
713 {{"isign", {{"a", DefaultInt}, {"b", DefaultInt}}, DefaultInt}, "sign"},
714 {{"len", {{"string", DefaultChar}}, DefaultInt}},
715 {{"log", {{"x", DefaultReal}}, DefaultReal}},
716 {{"log10", {{"x", DefaultReal}}, DefaultReal}},
peter klauslerad9aede2018-10-11 21:51:14717 {{"max0",
peter klausler7c402d92018-10-16 21:42:22718 {{"a1", DefaultInt}, {"a2", DefaultInt},
719 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
720 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14721 "max", true},
722 {{"max1",
peter klausler7c402d92018-10-16 21:42:22723 {{"a1", DefaultReal}, {"a2", DefaultReal},
724 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
725 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14726 "max", true},
727 {{"min0",
peter klausler7c402d92018-10-16 21:42:22728 {{"a1", DefaultInt}, {"a2", DefaultInt},
729 {"a3", DefaultInt, Rank::elemental, Optionality::repeats}},
730 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14731 "min", true},
732 {{"min1",
peter klausler7c402d92018-10-16 21:42:22733 {{"a1", DefaultReal}, {"a2", DefaultReal},
734 {"a3", DefaultReal, Rank::elemental, Optionality::repeats}},
735 DefaultInt},
peter klauslerad9aede2018-10-11 21:51:14736 "min", true},
peter klausler7c402d92018-10-16 21:42:22737 {{"mod", {{"a", DefaultInt}, {"p", DefaultInt}}, DefaultInt}},
738 {{"nint", {{"a", DefaultReal}}, DefaultInt}},
739 {{"sign", {{"a", DefaultReal}, {"b", DefaultReal}}, DefaultReal}},
740 {{"sin", {{"x", DefaultReal}}, DefaultReal}},
741 {{"sinh", {{"x", DefaultReal}}, DefaultReal}},
742 {{"sngl", {{"a", DoublePrecision}}, DefaultReal}, "real", true},
743 {{"sqrt", {{"x", DefaultReal}}, DefaultReal}},
744 {{"tan", {{"x", DefaultReal}}, DefaultReal}},
745 {{"tanh", {{"x", DefaultReal}}, DefaultReal}},
peter klausler42b33da2018-09-29 00:02:11746};
747
peter klauslerad9aede2018-10-11 21:51:14748// TODO: Intrinsic subroutines
749// MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY,
750// EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT,
751// GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER,
752// RANDOM_SEED, SYSTEM_CLOCK
753// TODO: Atomic intrinsic subroutines: ATOMIC_ADD &al.
754// TODO: Collective intrinsic subroutines: CO_BROADCAST &al.
peter klausler42b33da2018-09-29 00:02:11755
peter klauslera70f5962018-10-04 20:43:33756// Intrinsic interface matching against the arguments of a particular
757// procedure reference.
peter klausleref9dd9d2018-10-17 22:09:48758std::optional<SpecificCall> IntrinsicInterface::Match(
peter klauslerbf339f82018-10-15 22:28:47759 const CallCharacteristics &call,
760 const semantics::IntrinsicTypeDefaultKinds &defaults,
peter klausleref9dd9d2018-10-17 22:09:48761 ActualArguments &arguments, parser::ContextualMessages &messages) const {
peter klauslera70f5962018-10-04 20:43:33762 // Attempt to construct a 1-1 correspondence between the dummy arguments in
763 // a particular intrinsic procedure's generic interface and the actual
764 // arguments in a procedure reference.
peter klausler84ea49d2018-10-18 17:50:55765 std::size_t dummyArgPatterns{0};
766 for (; dummyArgPatterns < maxArguments &&
767 dummy[dummyArgPatterns].keyword != nullptr;
768 ++dummyArgPatterns) {
peter klauslera70f5962018-10-04 20:43:33769 }
peter klausler84ea49d2018-10-18 17:50:55770 std::vector<ActualArgument *> actualForDummy(dummyArgPatterns, nullptr);
771 // MAX and MIN (and others that map to them) allow their last argument to
772 // be repeated indefinitely. The actualForDummy vector is sized
773 // and null-initialized to the non-repeated dummy argument count,
774 // but additional actual argument pointers can be pushed on it
775 // when this flag is set.
776 bool repeatLastDummy{dummyArgPatterns > 0 &&
777 dummy[dummyArgPatterns - 1].optionality == Optionality::repeats};
778 int missingActualArguments{0};
peter klausleref9dd9d2018-10-17 22:09:48779 for (std::optional<ActualArgument> &arg : arguments) {
peter klausler84ea49d2018-10-18 17:50:55780 if (!arg.has_value()) {
781 ++missingActualArguments;
782 } else {
peter klausleref9dd9d2018-10-17 22:09:48783 if (arg->isAlternateReturn) {
784 messages.Say(
785 "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
786 name);
787 return std::nullopt;
788 }
789 bool found{false};
peter klausler84ea49d2018-10-18 17:50:55790 int slot{missingActualArguments};
791 for (std::size_t j{0}; j < dummyArgPatterns && !found; ++j) {
792 if (arg->keyword.has_value()) {
793 found = *arg->keyword == dummy[j].keyword;
794 if (found) {
795 if (const auto *previous{actualForDummy[j]}) {
796 if (previous->keyword.has_value()) {
797 messages.Say(*arg->keyword,
798 "repeated keyword argument to intrinsic '%s'"_err_en_US,
799 name);
800 } else {
801 messages.Say(*arg->keyword,
802 "keyword argument to intrinsic '%s' was supplied "
803 "positionally by an earlier actual argument"_err_en_US,
804 name);
805 }
806 return std::nullopt;
807 }
peter klausleref9dd9d2018-10-17 22:09:48808 }
peter klausler84ea49d2018-10-18 17:50:55809 } else {
810 found = actualForDummy[j] == nullptr && slot-- == 0;
811 }
812 if (found) {
813 actualForDummy[j] = &*arg;
peter klauslera70f5962018-10-04 20:43:33814 }
815 }
peter klausleref9dd9d2018-10-17 22:09:48816 if (!found) {
peter klausler84ea49d2018-10-18 17:50:55817 if (repeatLastDummy && !arg->keyword.has_value()) {
818 // MAX/MIN argument after the 2nd
819 actualForDummy.push_back(&*arg);
peter klausleref9dd9d2018-10-17 22:09:48820 } else {
peter klausler84ea49d2018-10-18 17:50:55821 if (arg->keyword.has_value()) {
822 messages.Say(*arg->keyword,
823 "unknown keyword argument to intrinsic '%s'"_err_en_US, name);
824 } else {
825 messages.Say(
826 "too many actual arguments for intrinsic '%s'"_err_en_US, name);
827 }
828 return std::nullopt;
peter klausleref9dd9d2018-10-17 22:09:48829 }
peter klauslera70f5962018-10-04 20:43:33830 }
peter klauslera70f5962018-10-04 20:43:33831 }
832 }
833
peter klausler84ea49d2018-10-18 17:50:55834 std::size_t dummies{actualForDummy.size()};
835
peter klauslera70f5962018-10-04 20:43:33836 // Check types and kinds of the actual arguments against the intrinsic's
837 // interface. Ensure that two or more arguments that have to have the same
838 // type and kind do so. Check for missing non-optional arguments now, too.
peter klauslera62636f2018-10-08 22:35:19839 const ActualArgument *sameArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33840 const IntrinsicDummyArgument *kindDummyArg{nullptr};
peter klauslera62636f2018-10-08 22:35:19841 const ActualArgument *kindArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33842 bool hasDimArg{false};
peter klausler84ea49d2018-10-18 17:50:55843 for (std::size_t j{0}; j < dummies; ++j) {
844 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
peter klauslera70f5962018-10-04 20:43:33845 if (d.typePattern.kindCode == KindCode::kindArg) {
846 CHECK(kindDummyArg == nullptr);
847 kindDummyArg = &d;
848 }
peter klausler84ea49d2018-10-18 17:50:55849 const ActualArgument *arg{actualForDummy[j]};
peter klauslera70f5962018-10-04 20:43:33850 if (!arg) {
peter klauslercb308d32018-10-05 18:32:54851 if (d.optionality == Optionality::required) {
peter klausler7bda1b32018-10-12 23:01:55852 messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
peter klauslera70f5962018-10-04 20:43:33853 return std::nullopt; // missing non-OPTIONAL argument
peter klauslercb308d32018-10-05 18:32:54854 } else {
855 continue;
peter klauslera70f5962018-10-04 20:43:33856 }
857 }
peter klauslera62636f2018-10-08 22:35:19858 std::optional<DynamicType> type{arg->GetType()};
859 if (!type.has_value()) {
860 CHECK(arg->Rank() == 0);
peter klauslercb308d32018-10-05 18:32:54861 if (d.typePattern.kindCode == KindCode::typeless ||
862 d.rank == Rank::elementalOrBOZ) {
peter klauslera70f5962018-10-04 20:43:33863 continue;
864 }
peter klausler7bda1b32018-10-12 23:01:55865 messages.Say(
866 "typeless (BOZ) not allowed for '%s=' argument"_err_en_US, d.keyword);
peter klauslercb308d32018-10-05 18:32:54867 return std::nullopt;
peter klauslera62636f2018-10-08 22:35:19868 } else if (!d.typePattern.categorySet.test(type->category)) {
peter klausler7bda1b32018-10-12 23:01:55869 messages.Say("actual argument for '%s=' has bad type '%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; // argument has invalid type category
872 }
873 bool argOk{false};
874 switch (d.typePattern.kindCode) {
875 case KindCode::none:
876 case KindCode::typeless:
877 case KindCode::teamType: // TODO: TEAM_TYPE
878 argOk = false;
879 break;
880 case KindCode::defaultIntegerKind:
peter klauslerbf339f82018-10-15 22:28:47881 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33882 break;
883 case KindCode::defaultRealKind:
peter klauslerbf339f82018-10-15 22:28:47884 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Real);
peter klauslera70f5962018-10-04 20:43:33885 break;
886 case KindCode::doublePrecision:
peter klauslerbf339f82018-10-15 22:28:47887 argOk = type->kind == defaults.doublePrecisionKind();
peter klauslera70f5962018-10-04 20:43:33888 break;
889 case KindCode::defaultCharKind:
peter klauslerbf339f82018-10-15 22:28:47890 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Character);
peter klauslera70f5962018-10-04 20:43:33891 break;
892 case KindCode::defaultLogicalKind:
peter klauslerbf339f82018-10-15 22:28:47893 argOk = type->kind == defaults.GetDefaultKind(TypeCategory::Logical);
peter klauslera70f5962018-10-04 20:43:33894 break;
895 case KindCode::any: argOk = true; break;
896 case KindCode::kindArg:
peter klauslerf7f2a732018-10-09 19:07:29897 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33898 CHECK(kindArg == nullptr);
899 kindArg = arg;
peter klauslerf7f2a732018-10-09 19:07:29900 argOk = true;
peter klauslera70f5962018-10-04 20:43:33901 break;
902 case KindCode::dimArg:
peter klauslerf7f2a732018-10-09 19:07:29903 CHECK(type->category == TypeCategory::Integer);
peter klauslera70f5962018-10-04 20:43:33904 hasDimArg = true;
905 argOk = true;
906 break;
907 case KindCode::same:
908 if (sameArg == nullptr) {
909 sameArg = arg;
910 }
peter klauslera62636f2018-10-08 22:35:19911 argOk = *type == sameArg->GetType();
peter klauslera70f5962018-10-04 20:43:33912 break;
913 case KindCode::effectiveKind:
914 common::die("INTERNAL: KindCode::effectiveKind appears on argument '%s' "
915 "for intrinsic '%s'",
916 d.keyword, name);
917 break;
918 default: CRASH_NO_CASE;
919 }
920 if (!argOk) {
peter klauslercb308d32018-10-05 18:32:54921 messages.Say(
peter klausler7bda1b32018-10-12 23:01:55922 "actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
peter klauslera62636f2018-10-08 22:35:19923 d.keyword, type->Dump().data());
peter klauslera70f5962018-10-04 20:43:33924 return std::nullopt;
925 }
926 }
927
928 // Check the ranks of the arguments against the intrinsic's interface.
peter klauslera62636f2018-10-08 22:35:19929 const ActualArgument *arrayArg{nullptr};
930 const ActualArgument *knownArg{nullptr};
931 const ActualArgument *shapeArg{nullptr};
peter klauslera70f5962018-10-04 20:43:33932 int elementalRank{0};
peter klausler84ea49d2018-10-18 17:50:55933 for (std::size_t j{0}; j < dummies; ++j) {
934 const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
935 if (const ActualArgument * arg{actualForDummy[j]}) {
peter klausler03618fd2018-10-29 22:25:35936 if (IsAssumedRank(*arg->value) && d.rank != Rank::anyOrAssumedRank) {
937 messages.Say("assumed-rank array cannot be forwarded to "
938 "'%s=' argument"_err_en_US,
peter klauslercb308d32018-10-05 18:32:54939 d.keyword);
peter klauslera70f5962018-10-04 20:43:33940 return std::nullopt;
941 }
peter klauslera62636f2018-10-08 22:35:19942 int rank{arg->Rank()};
peter klauslera70f5962018-10-04 20:43:33943 bool argOk{false};
944 switch (d.rank) {
945 case Rank::elemental:
peter klauslercb308d32018-10-05 18:32:54946 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:33947 if (elementalRank == 0) {
peter klauslera62636f2018-10-08 22:35:19948 elementalRank = rank;
peter klauslera70f5962018-10-04 20:43:33949 }
peter klauslera62636f2018-10-08 22:35:19950 argOk = rank == 0 || rank == elementalRank;
peter klauslera70f5962018-10-04 20:43:33951 break;
peter klauslera62636f2018-10-08 22:35:19952 case Rank::scalar: argOk = rank == 0; break;
953 case Rank::vector: argOk = rank == 1; break;
peter klauslera70f5962018-10-04 20:43:33954 case Rank::shape:
955 CHECK(shapeArg == nullptr);
956 shapeArg = arg;
peter klauslerad9aede2018-10-11 21:51:14957 argOk = rank == 1 && arg->VectorSize().has_value();
peter klauslera70f5962018-10-04 20:43:33958 break;
peter klauslera62636f2018-10-08 22:35:19959 case Rank::matrix: argOk = rank == 2; break;
peter klauslera70f5962018-10-04 20:43:33960 case Rank::array:
peter klauslera62636f2018-10-08 22:35:19961 argOk = rank > 0;
peter klauslera70f5962018-10-04 20:43:33962 if (!arrayArg) {
963 arrayArg = arg;
964 } else {
peter klauslera62636f2018-10-08 22:35:19965 argOk &= rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33966 }
967 break;
968 case Rank::known:
969 CHECK(knownArg == nullptr);
970 knownArg = arg;
971 argOk = true;
972 break;
973 case Rank::anyOrAssumedRank: argOk = true; break;
974 case Rank::conformable:
975 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:19976 argOk = rank == 0 || rank == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33977 break;
978 case Rank::dimRemoved:
979 CHECK(arrayArg != nullptr);
980 if (hasDimArg) {
peter klauslera62636f2018-10-08 22:35:19981 argOk = rank + 1 == arrayArg->Rank();
peter klauslera70f5962018-10-04 20:43:33982 } else {
peter klauslera62636f2018-10-08 22:35:19983 argOk = rank == 0;
peter klauslera70f5962018-10-04 20:43:33984 }
985 break;
peter klauslerad9aede2018-10-11 21:51:14986 case Rank::reduceOperation:
987 // TODO: Confirm that the argument is a pure function
988 // of two arguments with several constraints
989 CHECK(arrayArg != nullptr);
990 argOk = rank == 0;
991 break;
peter klauslera70f5962018-10-04 20:43:33992 case Rank::dimReduced:
993 case Rank::rankPlus1:
994 case Rank::shaped:
995 common::die("INTERNAL: result-only rank code appears on argument '%s' "
996 "for intrinsic '%s'",
997 d.keyword, name);
998 default: CRASH_NO_CASE;
999 }
1000 if (!argOk) {
peter klausler7bda1b32018-10-12 23:01:551001 messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
peter klauslera62636f2018-10-08 22:35:191002 d.keyword, rank);
peter klauslera70f5962018-10-04 20:43:331003 return std::nullopt;
1004 }
1005 }
1006 }
1007
peter klauslera70f5962018-10-04 20:43:331008 // Calculate the characteristics of the function result, if any
peter klausleref9dd9d2018-10-17 22:09:481009 std::optional<DynamicType> resultType;
peter klauslera70f5962018-10-04 20:43:331010 if (result.categorySet.empty()) {
peter klausleref9dd9d2018-10-17 22:09:481011 if (!call.isSubroutineCall) {
1012 return std::nullopt;
peter klausler55df4a72018-10-12 23:25:391013 }
peter klausleref9dd9d2018-10-17 22:09:481014 CHECK(result.kindCode == KindCode::none);
1015 } else {
1016 // Determine the result type.
1017 if (call.isSubroutineCall) {
1018 return std::nullopt;
1019 }
1020 resultType = DynamicType{*result.categorySet.LeastElement(), 0};
1021 switch (result.kindCode) {
1022 case KindCode::defaultIntegerKind:
1023 CHECK(result.categorySet == IntType);
1024 CHECK(resultType->category == TypeCategory::Integer);
1025 resultType->kind = defaults.GetDefaultKind(TypeCategory::Integer);
1026 break;
1027 case KindCode::defaultRealKind:
1028 CHECK(result.categorySet == CategorySet{resultType->category});
1029 CHECK(FloatingType.test(resultType->category));
1030 resultType->kind = defaults.GetDefaultKind(TypeCategory::Real);
1031 break;
1032 case KindCode::doublePrecision:
1033 CHECK(result.categorySet == RealType);
1034 CHECK(resultType->category == TypeCategory::Real);
1035 resultType->kind = defaults.doublePrecisionKind();
1036 break;
1037 case KindCode::defaultCharKind:
1038 CHECK(result.categorySet == CharType);
1039 CHECK(resultType->category == TypeCategory::Character);
1040 resultType->kind = defaults.GetDefaultKind(TypeCategory::Character);
1041 break;
1042 case KindCode::defaultLogicalKind:
1043 CHECK(result.categorySet == LogicalType);
1044 CHECK(resultType->category == TypeCategory::Logical);
1045 resultType->kind = defaults.GetDefaultKind(TypeCategory::Logical);
1046 break;
1047 case KindCode::same:
1048 CHECK(sameArg != nullptr);
1049 if (std::optional<DynamicType> aType{sameArg->GetType()}) {
1050 if (result.categorySet.test(aType->category)) {
1051 resultType = *aType;
1052 } else {
1053 resultType->kind = aType->kind;
1054 }
1055 }
1056 break;
1057 case KindCode::effectiveKind:
1058 CHECK(kindDummyArg != nullptr);
1059 CHECK(result.categorySet == CategorySet{resultType->category});
1060 if (kindArg != nullptr) {
peter klauslerabac2282018-10-26 22:10:241061 auto &expr{*kindArg->value};
1062 CHECK(expr.Rank() == 0);
1063 if (auto code{ToInt64(expr)}) {
1064 if (IsValidKindOfIntrinsicType(resultType->category, *code)) {
1065 resultType->kind = *code;
1066 break;
peter klauslerf7f2a732018-10-09 19:07:291067 }
1068 }
peter klausleref9dd9d2018-10-17 22:09:481069 messages.Say("'kind=' argument must be a constant scalar integer "
1070 "whose value is a supported kind for the "
1071 "intrinsic result type"_err_en_US);
1072 return std::nullopt;
1073 } else if (kindDummyArg->optionality == Optionality::defaultsToSameKind) {
1074 CHECK(sameArg != nullptr);
1075 resultType = *sameArg->GetType();
1076 } else if (kindDummyArg->optionality ==
1077 Optionality::defaultsToSubscriptKind) {
1078 CHECK(resultType->category == TypeCategory::Integer);
1079 resultType->kind = defaults.subscriptIntegerKind();
1080 } else {
1081 CHECK(kindDummyArg->optionality ==
1082 Optionality::defaultsToDefaultForResult);
1083 resultType->kind = defaults.GetDefaultKind(resultType->category);
peter klauslerf7f2a732018-10-09 19:07:291084 }
peter klausleref9dd9d2018-10-17 22:09:481085 break;
1086 case KindCode::likeMultiply:
1087 CHECK(dummies >= 2);
1088 CHECK(actualForDummy[0] != nullptr);
1089 CHECK(actualForDummy[1] != nullptr);
1090 resultType = actualForDummy[0]->GetType()->ResultTypeForMultiply(
1091 *actualForDummy[1]->GetType());
1092 break;
1093 case KindCode::typeless:
1094 case KindCode::teamType:
1095 case KindCode::any:
1096 case KindCode::kindArg:
1097 case KindCode::dimArg:
1098 common::die(
1099 "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
1100 break;
1101 default: CRASH_NO_CASE;
peter klauslera70f5962018-10-04 20:43:331102 }
peter klauslera70f5962018-10-04 20:43:331103 }
1104
peter klauslerf7f2a732018-10-09 19:07:291105 // At this point, the call is acceptable.
peter klauslera70f5962018-10-04 20:43:331106 // Determine the rank of the function result.
1107 int resultRank{0};
1108 switch (rank) {
1109 case Rank::elemental: resultRank = elementalRank; break;
1110 case Rank::scalar: resultRank = 0; break;
1111 case Rank::vector: resultRank = 1; break;
1112 case Rank::matrix: resultRank = 2; break;
peter klauslerf7f2a732018-10-09 19:07:291113 case Rank::conformable:
1114 CHECK(arrayArg != nullptr);
1115 resultRank = arrayArg->Rank();
1116 break;
peter klauslera70f5962018-10-04 20:43:331117 case Rank::dimReduced:
1118 CHECK(arrayArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191119 resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
peter klauslera70f5962018-10-04 20:43:331120 break;
1121 case Rank::rankPlus1:
1122 CHECK(knownArg != nullptr);
peter klauslera62636f2018-10-08 22:35:191123 resultRank = knownArg->Rank() + 1;
peter klauslera70f5962018-10-04 20:43:331124 break;
1125 case Rank::shaped:
1126 CHECK(shapeArg != nullptr);
peter klauslerad9aede2018-10-11 21:51:141127 {
1128 std::optional<int> shapeLen{shapeArg->VectorSize()};
1129 CHECK(shapeLen.has_value());
1130 resultRank = *shapeLen;
1131 }
peter klauslera70f5962018-10-04 20:43:331132 break;
peter klauslercb308d32018-10-05 18:32:541133 case Rank::elementalOrBOZ:
peter klauslera70f5962018-10-04 20:43:331134 case Rank::shape:
1135 case Rank::array:
1136 case Rank::known:
1137 case Rank::anyOrAssumedRank:
peter klauslera70f5962018-10-04 20:43:331138 case Rank::dimRemoved:
peter klauslerad9aede2018-10-11 21:51:141139 case Rank::reduceOperation:
peter klauslera70f5962018-10-04 20:43:331140 common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
1141 break;
1142 default: CRASH_NO_CASE;
1143 }
1144 CHECK(resultRank >= 0);
1145
peter klauslerfdd3a2a2018-10-16 23:36:431146 semantics::Attrs attrs;
1147 if (elementalRank > 0) {
1148 attrs.set(semantics::Attr::ELEMENTAL);
1149 }
1150
peter klausleref9dd9d2018-10-17 22:09:481151 // Rearrange the actual arguments into dummy argument order.
1152 ActualArguments rearranged(dummies);
peter klausler84ea49d2018-10-18 17:50:551153 for (std::size_t j{0}; j < dummies; ++j) {
peter klausleref9dd9d2018-10-17 22:09:481154 if (ActualArgument * arg{actualForDummy[j]}) {
peter klausler84ea49d2018-10-18 17:50:551155 rearranged[j] = std::move(*arg);
peter klausleref9dd9d2018-10-17 22:09:481156 }
1157 }
1158
1159 return {SpecificCall{
1160 SpecificIntrinsic{name, std::move(resultType), resultRank, attrs},
1161 std::move(rearranged)}};
peter klauslera70f5962018-10-04 20:43:331162}
1163
peter klauslera62636f2018-10-08 22:35:191164struct IntrinsicProcTable::Implementation {
peter klauslerbf339f82018-10-15 22:28:471165 explicit Implementation(const semantics::IntrinsicTypeDefaultKinds &dfts)
peter klauslera70f5962018-10-04 20:43:331166 : defaults{dfts} {
1167 for (const IntrinsicInterface &f : genericIntrinsicFunction) {
1168 genericFuncs.insert(std::make_pair(std::string{f.name}, &f));
1169 }
1170 for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
1171 specificFuncs.insert(std::make_pair(std::string{f.name}, &f));
1172 }
1173 }
peter klausler42b33da2018-09-29 00:02:111174
peter klausleref9dd9d2018-10-17 22:09:481175 std::optional<SpecificCall> Probe(const CallCharacteristics &,
1176 ActualArguments &, parser::ContextualMessages *) const;
peter klausler75a32092018-10-05 16:57:531177
peter klauslerbf339f82018-10-15 22:28:471178 semantics::IntrinsicTypeDefaultKinds defaults;
peter klauslera70f5962018-10-04 20:43:331179 std::multimap<std::string, const IntrinsicInterface *> genericFuncs;
1180 std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs;
peter klausler7bda1b32018-10-12 23:01:551181 std::ostream &Dump(std::ostream &) const;
peter klausler42b33da2018-09-29 00:02:111182};
1183
peter klauslercb308d32018-10-05 18:32:541184// Probe the configured intrinsic procedure pattern tables in search of a
1185// match for a given procedure reference.
peter klausleref9dd9d2018-10-17 22:09:481186std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
1187 const CallCharacteristics &call, ActualArguments &arguments,
peter klauslercb308d32018-10-05 18:32:541188 parser::ContextualMessages *messages) const {
peter klausler75a32092018-10-05 16:57:531189 if (call.isSubroutineCall) {
1190 return std::nullopt; // TODO
1191 }
peter klausler7bda1b32018-10-12 23:01:551192 parser::Messages *finalBuffer{messages ? messages->messages() : nullptr};
peter klausler62425d62018-10-12 00:01:311193 // Probe the specific intrinsic function table first.
1194 parser::Messages specificBuffer;
1195 parser::ContextualMessages specificErrors{
1196 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551197 finalBuffer ? &specificBuffer : nullptr};
peter klausler75a32092018-10-05 16:57:531198 std::string name{call.name.ToString()};
1199 auto specificRange{specificFuncs.equal_range(name)};
1200 for (auto iter{specificRange.first}; iter != specificRange.second; ++iter) {
peter klausleref9dd9d2018-10-17 22:09:481201 if (auto specificCall{
1202 iter->second->Match(call, defaults, arguments, specificErrors)}) {
peter klauslerad9aede2018-10-11 21:51:141203 if (const char *genericName{iter->second->generic}) {
peter klausleref9dd9d2018-10-17 22:09:481204 specificCall->specificIntrinsic.name = genericName;
peter klauslerad9aede2018-10-11 21:51:141205 }
peter klausleref9dd9d2018-10-17 22:09:481206 specificCall->specificIntrinsic.isRestrictedSpecific =
1207 iter->second->isRestrictedSpecific;
1208 return specificCall;
peter klausler75a32092018-10-05 16:57:531209 }
1210 }
peter klausler62425d62018-10-12 00:01:311211 // Probe the generic intrinsic function table next.
1212 parser::Messages genericBuffer;
1213 parser::ContextualMessages genericErrors{
1214 messages ? messages->at() : call.name,
peter klausler7bda1b32018-10-12 23:01:551215 finalBuffer ? &genericBuffer : nullptr};
peter klausler62425d62018-10-12 00:01:311216 auto genericRange{genericFuncs.equal_range(name)};
peter klausler75a32092018-10-05 16:57:531217 for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
peter klausleref9dd9d2018-10-17 22:09:481218 if (auto specificCall{
1219 iter->second->Match(call, defaults, arguments, genericErrors)}) {
1220 return specificCall;
peter klausler75a32092018-10-05 16:57:531221 }
1222 }
peter klauslerad9aede2018-10-11 21:51:141223 // Special cases of intrinsic functions
peter klausler8efb8972018-10-10 17:48:121224 if (call.name.ToString() == "null") {
peter klausleref9dd9d2018-10-17 22:09:481225 if (arguments.size() == 0) {
peter klausler8efb8972018-10-10 17:48:121226 // TODO: NULL() result type is determined by context
1227 // Can pass that context in, or return a token distinguishing
1228 // NULL, or represent NULL as a new kind of top-level expression
peter klausleref9dd9d2018-10-17 22:09:481229 } else if (arguments.size() > 1) {
peter klausler62425d62018-10-12 00:01:311230 genericErrors.Say("too many arguments to NULL()"_err_en_US);
peter klausleref9dd9d2018-10-17 22:09:481231 } else if (arguments[0].has_value() && arguments[0]->keyword.has_value() &&
1232 arguments[0]->keyword->ToString() != "mold") {
peter klausler62425d62018-10-12 00:01:311233 genericErrors.Say("unknown argument '%s' to NULL()"_err_en_US,
peter klausleref9dd9d2018-10-17 22:09:481234 arguments[0]->keyword->ToString().data());
peter klausler8efb8972018-10-10 17:48:121235 } else {
1236 // TODO: Argument must be pointer, procedure pointer, or allocatable.
1237 // Characteristics, including dynamic length type parameter values,
1238 // must be taken from the MOLD argument.
peter klauslerfdd3a2a2018-10-16 23:36:431239 // TODO: set Attr::POINTER on NULL result
peter klausler8efb8972018-10-10 17:48:121240 }
1241 }
1242 // No match
peter klausler7bda1b32018-10-12 23:01:551243 if (finalBuffer) {
peter klausler62425d62018-10-12 00:01:311244 if (genericBuffer.empty()) {
peter klausler7bda1b32018-10-12 23:01:551245 finalBuffer->Annex(std::move(specificBuffer));
peter klausler62425d62018-10-12 00:01:311246 } else {
peter klausler7bda1b32018-10-12 23:01:551247 finalBuffer->Annex(std::move(genericBuffer));
peter klausler62425d62018-10-12 00:01:311248 }
peter klauslercb308d32018-10-05 18:32:541249 }
peter klausler75a32092018-10-05 16:57:531250 return std::nullopt;
1251}
1252
peter klauslera62636f2018-10-08 22:35:191253IntrinsicProcTable::~IntrinsicProcTable() {
peter klauslercb308d32018-10-05 18:32:541254 // Discard the configured tables.
peter klausler42b33da2018-09-29 00:02:111255 delete impl_;
1256 impl_ = nullptr;
1257}
1258
peter klauslera62636f2018-10-08 22:35:191259IntrinsicProcTable IntrinsicProcTable::Configure(
peter klauslerbf339f82018-10-15 22:28:471260 const semantics::IntrinsicTypeDefaultKinds &defaults) {
peter klauslera62636f2018-10-08 22:35:191261 IntrinsicProcTable result;
1262 result.impl_ = new IntrinsicProcTable::Implementation(defaults);
peter klausler42b33da2018-09-29 00:02:111263 return result;
1264}
1265
peter klausleref9dd9d2018-10-17 22:09:481266std::optional<SpecificCall> IntrinsicProcTable::Probe(
1267 const CallCharacteristics &call, ActualArguments &arguments,
peter klauslercb308d32018-10-05 18:32:541268 parser::ContextualMessages *messages) const {
peter klauslera62636f2018-10-08 22:35:191269 CHECK(impl_ != nullptr || !"IntrinsicProcTable: not configured");
peter klausleref9dd9d2018-10-17 22:09:481270 return impl_->Probe(call, arguments, messages);
peter klausler42b33da2018-09-29 00:02:111271}
peter klauslerad9aede2018-10-11 21:51:141272
1273std::ostream &SpecificIntrinsic::Dump(std::ostream &o) const {
1274 return o << name;
1275}
peter klausler7bda1b32018-10-12 23:01:551276
1277std::ostream &TypePattern::Dump(std::ostream &o) const {
1278 if (categorySet == AnyType) {
1279 o << "any type";
1280 } else {
1281 const char *sep = "";
1282 auto set{categorySet};
1283 while (auto least{set.LeastElement()}) {
1284 o << sep << EnumToString(*least);
1285 sep = " or ";
1286 set.reset(*least);
1287 }
1288 }
1289 o << '(' << EnumToString(kindCode) << ')';
1290 return o;
1291}
1292
1293std::ostream &IntrinsicDummyArgument::Dump(std::ostream &o) const {
1294 if (keyword) {
1295 o << keyword << '=';
1296 }
1297 return typePattern.Dump(o)
1298 << ' ' << EnumToString(rank) << ' ' << EnumToString(optionality);
1299}
1300
1301std::ostream &IntrinsicInterface::Dump(std::ostream &o) const {
1302 o << name;
1303 char sep{'('};
1304 for (const auto &d : dummy) {
1305 if (d.typePattern.kindCode == KindCode::none) {
1306 break;
1307 }
1308 d.Dump(o << sep);
1309 sep = ',';
1310 }
1311 if (sep == '(') {
1312 o << "()";
1313 }
1314 return result.Dump(o << " -> ") << ' ' << EnumToString(rank);
1315}
1316
1317std::ostream &IntrinsicProcTable::Implementation::Dump(std::ostream &o) const {
1318 o << "generic intrinsic functions:\n";
1319 for (const auto &iter : genericFuncs) {
1320 iter.second->Dump(o << iter.first << ": ") << '\n';
1321 }
1322 o << "specific intrinsic functions:\n";
1323 for (const auto &iter : specificFuncs) {
1324 iter.second->Dump(o << iter.first << ": ");
1325 if (const char *g{iter.second->generic}) {
1326 o << " -> " << g;
1327 }
1328 o << '\n';
1329 }
1330 return o;
1331}
1332
1333std::ostream &IntrinsicProcTable::Dump(std::ostream &o) const {
1334 return impl_->Dump(o);
1335}
Jean Perierf7e7cb32018-10-25 12:55:231336}