11/*
2- * Copyright (c) 2017, 2019 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2017, 2021 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2323package com .oracle .truffle .r .test .tck ;
2424
2525import static org .graalvm .polyglot .tck .TypeDescriptor .array ;
26+ import static org .graalvm .polyglot .tck .TypeDescriptor .intersection ;
2627
2728import java .io .IOException ;
2829import java .io .InputStreamReader ;
3435import java .util .List ;
3536import java .util .Objects ;
3637import java .util .function .BiFunction ;
38+ import java .util .function .Function ;
3739import java .util .function .Predicate ;
40+
3841import org .graalvm .polyglot .Context ;
3942import org .graalvm .polyglot .PolyglotException ;
4043import org .graalvm .polyglot .Source ;
4144import org .graalvm .polyglot .SourceSection ;
4245import org .graalvm .polyglot .Value ;
4346import org .graalvm .polyglot .tck .InlineSnippet ;
47+ import org .graalvm .polyglot .tck .LanguageProvider ;
48+ import org .graalvm .polyglot .tck .ResultVerifier ;
4449import org .graalvm .polyglot .tck .Snippet ;
4550import org .graalvm .polyglot .tck .TypeDescriptor ;
4651import org .junit .Assert ;
47- import org .graalvm .polyglot .tck .LanguageProvider ;
48- import org .graalvm .polyglot .tck .ResultVerifier ;
49- import static org .graalvm .polyglot .tck .TypeDescriptor .intersection ;
5052
5153public final class RTCKLanguageProvider implements LanguageProvider {
5254
@@ -147,41 +149,42 @@ public Collection<? extends Snippet> createExpressions(Context context) {
147149
148150 // +
149151 ops .add (createBinaryOperator (context , "+" , numOrBoolOrArrNumBool , numOrBoolOrArrayPrNull , numOrBoolOrArrayPrNull ,
150- RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).emptyArrayCheck ().build ()));
152+ RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).primitiveAndArrayMismatchCheck (). emptyArrayCheck ().build ()));
151153 // -
152154 ops .add (createBinaryOperator (context , "-" , numOrBoolOrArrNumBool , numOrBoolOrArrayPrNull , numOrBoolOrArrayPrNull ,
153- RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).emptyArrayCheck ().build ()));
155+ RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).primitiveAndArrayMismatchCheck (). emptyArrayCheck ().build ()));
154156 // *
155157 ops .add (createBinaryOperator (context , "*" , numOrBoolOrArrNumBool , numOrBoolOrArrayPrNull , numOrBoolOrArrayPrNull ,
156- RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).emptyArrayCheck ().build ()));
158+ RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).primitiveAndArrayMismatchCheck (). emptyArrayCheck ().build ()));
157159 // /
158160 ops .add (createBinaryOperator (context , "/" , numOrBoolOrArrNumBool , numOrBoolOrArrayPrNull , numOrBoolOrArrayPrNull ,
159- RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).emptyArrayCheck ().build ()));
161+ RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).primitiveAndArrayMismatchCheck (). emptyArrayCheck ().build ()));
160162
161163 acceptedParameterTypes = new TypeDescriptor []{TypeDescriptor .ANY , TypeDescriptor .ANY };
162164 // <
163165 ops .add (createBinaryOperator (context , "<" , boolOrArrBool , TypeDescriptor .ANY , TypeDescriptor .ANY ,
164- RResultVerifier .newBuilder (acceptedParameterTypes ).compareParametersCheck ().build ()));
166+ RResultVerifier .newBuilder (acceptedParameterTypes ).primitiveAndArrayMismatchCheck (). compareParametersCheck ().build ()));
165167 // >
166168 ops .add (createBinaryOperator (context , ">" , boolOrArrBool , TypeDescriptor .ANY , TypeDescriptor .ANY ,
167- RResultVerifier .newBuilder (acceptedParameterTypes ).compareParametersCheck ().build ()));
169+ RResultVerifier .newBuilder (acceptedParameterTypes ).primitiveAndArrayMismatchCheck (). compareParametersCheck ().build ()));
168170 // <=
169171 ops .add (createBinaryOperator (context , "<=" , boolOrArrBool , TypeDescriptor .ANY , TypeDescriptor .ANY ,
170- RResultVerifier .newBuilder (acceptedParameterTypes ).compareParametersCheck ().build ()));
172+ RResultVerifier .newBuilder (acceptedParameterTypes ).primitiveAndArrayMismatchCheck (). compareParametersCheck ().build ()));
171173 // >=
172174 ops .add (createBinaryOperator (context , ">=" , boolOrArrBool , TypeDescriptor .ANY , TypeDescriptor .ANY ,
173- RResultVerifier .newBuilder (acceptedParameterTypes ).compareParametersCheck ().build ()));
175+ RResultVerifier .newBuilder (acceptedParameterTypes ).primitiveAndArrayMismatchCheck (). compareParametersCheck ().build ()));
174176 // ==
175177 ops .add (createBinaryOperator (context , "==" , boolOrArrBool , TypeDescriptor .ANY , TypeDescriptor .ANY ,
176- RResultVerifier .newBuilder (acceptedParameterTypes ).compareParametersCheck ().build ()));
178+ RResultVerifier .newBuilder (acceptedParameterTypes ).primitiveAndArrayMismatchCheck (). compareParametersCheck ().build ()));
177179 // !=
178180 ops .add (createBinaryOperator (context , "!=" , boolOrArrBool , TypeDescriptor .ANY , TypeDescriptor .ANY ,
179- RResultVerifier .newBuilder (acceptedParameterTypes ).compareParametersCheck ().build ()));
181+ RResultVerifier .newBuilder (acceptedParameterTypes ).primitiveAndArrayMismatchCheck (). compareParametersCheck ().build ()));
180182 // // TODO &, |, &&, ||
181183
182184 // !
183185 ops .add (createPrefixOperator (context , "!" , boolOrArrBool , numOrBoolOrArray ,
184- RResultVerifier .newBuilder (new TypeDescriptor []{numOrBoolOrNullOrArrNumBool }, new TypeDescriptor []{numOrBoolOrArray }).emptyArrayCheck ().build ()));
186+ RResultVerifier .newBuilder (new TypeDescriptor []{numOrBoolOrNullOrArrNumBool },
187+ new TypeDescriptor []{numOrBoolOrArray }).primitiveAndArrayMismatchCheck ().emptyArrayCheck ().build ()));
185188
186189 // TODO unary +, -, ...
187190
@@ -201,13 +204,13 @@ public Collection<? extends Snippet> createStatements(Context context) {
201204 // if
202205 String ifStatement = "if ({1}) '{'\n {0}<-TRUE\n '}' else '{'\n {0}<-FALSE\n '}'" ;
203206 res .add (createStatement (context , "if" , ifStatement ,
204- RResultVerifier .newBuilder (acceptedParameterTypes , new TypeDescriptor []{numOrBoolOrArray }).emptyArrayCheck ().build (),
207+ RResultVerifier .newBuilder (acceptedParameterTypes , new TypeDescriptor []{numOrBoolOrArray }).primitiveAndArrayMismatchCheck (). emptyArrayCheck ().build (),
205208 TypeDescriptor .BOOLEAN , numOrBoolOrArray ));
206209
207210 // while
208211 String whileStatement = "while ({1})'{'\n break\n '}'" ;
209212 res .add (createStatement (context , "while" , whileStatement ,
210- RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).emptyArrayCheck ().build (),
213+ RResultVerifier .newBuilder (acceptedParameterTypes , declaredParameterTypes ).primitiveAndArrayMismatchCheck (). emptyArrayCheck ().build (),
211214 TypeDescriptor .NULL , numOrBoolOrArray ));
212215
213216 // for
@@ -455,8 +458,6 @@ public void accept(SnippetRun snippetRun) throws PolyglotException {
455458 if (hasValidDeclaredTypes ) {
456459 if (hasValidArgumentTypes ) {
457460 next .apply (hasValidArgumentTypes , snippetRun );
458- } else {
459- return ;
460461 }
461462 } else {
462463 next .apply (hasValidArgumentTypes , snippetRun );
@@ -527,6 +528,48 @@ private boolean hasEmptyArrayArg(List<? extends Value> args) {
527528 return this ;
528529 }
529530
531+ /**
532+ * Ignores errors from interop values that unbox to a different type than what is their
533+ * array type from FastR default conversions point of view. Example: object that
534+ * {@code isString}, but its array elements are bytes. Another example: object that
535+ * looks like integer, but is also an integer array of size > 1.
536+ *
537+ * @return the Builder
538+ */
539+ Builder primitiveAndArrayMismatchCheck () {
540+ chain = new BiFunction <Boolean , SnippetRun , Void >() {
541+ private final BiFunction <Boolean , SnippetRun , Void > next = chain ;
542+
543+ @ Override
544+ public Void apply (Boolean valid , SnippetRun sr ) {
545+ if (valid && sr .getException () != null && hasMismatchingArgs (sr .getParameters ())) {
546+ return null ;
547+ }
548+ return next .apply (valid , sr );
549+ }
550+
551+ private boolean hasMismatchingArgs (List <? extends Value > args ) {
552+ for (Value arg : args ) {
553+ if (checkPrimitive (arg , Value ::isString ) ||
554+ checkPrimitive (arg , Value ::fitsInByte ) ||
555+ checkPrimitive (arg , Value ::fitsInShort ) ||
556+ checkPrimitive (arg , Value ::fitsInInt ) ||
557+ checkPrimitive (arg , Value ::fitsInLong ) ||
558+ checkPrimitive (arg , Value ::fitsInDouble ) ||
559+ checkPrimitive (arg , Value ::fitsInFloat )) {
560+ return true ;
561+ }
562+ }
563+ return false ;
564+ }
565+
566+ private boolean checkPrimitive (Value arg , Function <Value , Boolean > fitsIn ) {
567+ return fitsIn .apply (arg ) && arg .hasArrayElements () && (arg .getArraySize () != 1 || !fitsIn .apply (arg .getArrayElement (0 )));
568+ }
569+ };
570+ return this ;
571+ }
572+
530573 // - not empty homogenous number, boolean or string arrays -> vector
531574 // - any other array -> list
532575 //
0 commit comments