From eb2733545ae7bdcf164ccfa1c9c979b7c0d5749d Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Thu, 29 Sep 2016 18:00:16 +0200
Subject: [PATCH] rbdiag can use RMissing and RNull values as the only samples

---
 .../oracle/truffle/r/nodes/casts/Samples.java |  2 +-
 .../truffle/r/nodes/test/ChimneySweeping.java | 52 ++++++++++++-------
 .../r/nodes/builtin/casts/PipelineStep.java   |  2 +-
 .../builtin/casts/PipelineToCastNode.java     |  2 +-
 .../builtin/casts/fluent/ChainBuilder.java    |  3 +-
 mx.fastr/mx_fastr.py                          |  4 +-
 6 files changed, 42 insertions(+), 23 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java
index 2819f8e639..3a65ebcc6d 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java
@@ -130,7 +130,7 @@ public final class Samples<T> {
     }
 
     @SuppressWarnings("unchecked")
-    public Samples<T> or(Samples<? extends T> other) {
+    public Samples<T> or(Samples<?> other) {
         String newName = "or(" + name + "," + other.name + ")";
 
         Set<Object> negativeUnion = new HashSet<>(other.negativeSamples());
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
index a2332b4861..868c3a9ea9 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
@@ -57,6 +57,7 @@ import com.oracle.truffle.r.runtime.ResourceHandlerFactory;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.test.TestBase;
 import com.oracle.truffle.r.test.generate.FastRSession;
@@ -69,6 +70,8 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
     private static final String TEST_PREFIX = "com.oracle.truffle.r.test.builtins.TestBuiltin_";
     private static final String SWEEP_MODE_ARG = "--sweep";
     private static final String SWEEP_MODE_ARG_SPEC = SWEEP_MODE_ARG + "-";
+    private static final String NO_SELF_TEST_ARG = "--noSelfTest";
+    private static final String MISSING_AND_NULL_SAMPLES_ONLY_ARG = "--mnonly";
 
     enum ChimneySweepingMode {
         auto,
@@ -88,6 +91,8 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
 
     static class ChimneySweepingConfig extends DiagConfig {
         ChimneySweepingMode sweepingMode;
+        boolean missingAndNullSamplesOnly;
+        boolean performPipelineSelfTest;
     }
 
     static class ChimneySweepingSuite extends RBuiltinDiagnostics {
@@ -122,6 +127,10 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
 
         static <C extends ChimneySweepingConfig> C initChimneySweepingConfig(C config, String[] args) {
             config.sweepingMode = getSweepMode(args).flatMap(ChimneySweepingMode::fromArg).orElse(ChimneySweepingMode.auto);
+            config.missingAndNullSamplesOnly = Arrays.stream(args).filter(arg -> MISSING_AND_NULL_SAMPLES_ONLY_ARG.equals(arg)).findFirst().isPresent();
+            // The pipeline self-test is disabled when only RMissing and RNull samples are used as
+            // these values are not determined via the pipeline static type analysis
+            config.performPipelineSelfTest = config.missingAndNullSamplesOnly ? false : !Arrays.stream(args).filter(arg -> NO_SELF_TEST_ARG.equals(arg)).findFirst().isPresent();
             return RBuiltinDiagnostics.initDiagConfig(config, args);
         }
 
@@ -164,10 +173,10 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
 
     ChimneySweeping(ChimneySweepingSuite diagSuite, RIntBuiltinDiagFactory builtinFactory) {
         super(diagSuite, builtinFactory);
+        this.kind = builtinFactory.getBuiltinKind();
         this.diagSuite = diagSuite;
         this.validArgsList = extractValidArgsForBuiltin();
         this.argSamples = createSamples();
-        this.kind = builtinFactory.getBuiltinKind();
     }
 
     @Override
@@ -184,7 +193,9 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
         System.out.println(" Samples:");
         System.out.println(argSamples.get(i));
 
-        checkPipelines(i);
+        if (diagSuite.diagConfig.performPipelineSelfTest) {
+            checkPipelines(i);
+        }
     }
 
     @SuppressWarnings({"rawtypes", "unchecked"})
@@ -194,26 +205,31 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
 
         List<Samples<?>> as = new ArrayList<>();
         for (int i = 0; i < argLength; i++) {
-            CastNode cn;
-            if (i < castNodes.length) {
-                cn = castNodes[i];
-            } else {
-                cn = null;
-            }
             Samples samples;
-            try {
-                if (cn == null) {
-                    samples = Samples.anything();
+
+            if (diagSuite.diagConfig.missingAndNullSamplesOnly) {
+                samples = Samples.anything(RNull.instance).or(Samples.anything(RMissing.instance));
+            } else {
+                CastNode cn;
+                if (i < castNodes.length) {
+                    cn = castNodes[i];
                 } else {
-                    CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cn);
-                    samples = sampler.collectSamples();
+                    cn = null;
+                }
+                try {
+                    if (cn == null) {
+                        samples = Samples.anything();
+                    } else {
+                        CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cn);
+                        samples = sampler.collectSamples();
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException("Error in sample generation from argument " + i, e);
                 }
-            } catch (Exception e) {
-                throw new RuntimeException("Error in sample generation from argument " + i, e);
-            }
 
-            Samples defArgSamples = defaultArgs.get(parameterNames[i]);
-            samples = defArgSamples == null ? samples : samples.and(defArgSamples);
+                Samples defArgSamples = defaultArgs.get(parameterNames[i]);
+                samples = defArgSamples == null ? samples : samples.and(defArgSamples);
+            }
 
             as.add(samples);
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
index a25f7db4e7..94b247b46e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
@@ -161,7 +161,7 @@ public abstract class PipelineStep<T, R> {
      * then if the vector is empty, the default value is returned without any warning. If the
      * default value is not provided, then error is raised if the vector is empty, the error message
      * chosen in the following order: provided message, explicitly set default error message using
-     * {@link DefaultErrorStep}, default find first message.
+     * {@link PipelineStep.DefaultErrorStep}, default find first message.
      */
     public static final class FindFirstStep<V, E> extends PipelineStep<V, E> {
         private final MessageData error;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 232e2aa96d..2f7182b34f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -214,7 +214,7 @@ public final class PipelineToCastNode {
         public CastNode visit(FilterStep<?, ?> step) {
             Filter<?, ?> filter = step.getFilter();
             if (filter instanceof RTypeFilter) {
-                canBeOptimized(((RTypeFilter) filter).getType());
+                canBeOptimized(((RTypeFilter<?>) filter).getType());
             } else {
                 cannotBeOptimizedBeforeFindFirst();
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ChainBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ChainBuilder.java
index 2a4178aacf..d52c46dbbe 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ChainBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ChainBuilder.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.casts.Mapper;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
@@ -31,7 +32,7 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
  * can be used to create a chain outside of a context of {@link PipelineBuilder}, it can be
  * constructed using the {@code chain} method from {@code Predef}.
  *
- * {@see Predef#chain}
+ * @see Predef#chain
  */
 public final class ChainBuilder<T> {
     private final PipelineStep<?, ?> firstStep;
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index e329ea7149..578bd96fed 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -444,6 +444,8 @@ def rbdiag(args):
 	-v		Verbose output including the list of unimplemented specializations
 	-n		Ignore RNull as an argument type
 	-m		Ignore RMissing as an argument type
+    --mnonly		Uses the RMissing and RNull values as the only samples for the chimney-sweeping
+    --noSelfTest	Does not perform the pipeline self-test using the generated samples as the intro to each chimney-sweeping. It has no effect when --mnonly is specified as the self-test is never performed in that case.
     --sweep		Performs the 'chimney-sweeping'. The sample combination selection method is determined automatically.
     --sweep-lite	Performs the 'chimney-sweeping'. The diagonal sample selection method is used.
     --sweep-total	Performs the 'chimney-sweeping'. The total sample selection method is used.
@@ -524,7 +526,7 @@ _commands = {
     'junitnoapps' : [junit_noapps, ['options']],
     'unittest' : [unittest, ['options']],
     'rbcheck' : [rbcheck, '--filter [gnur-only,fastr-only,both,both-diff]'],
-    'rbdiag' : [rbdiag, '(builtin)* [-v] [-n] [-m] [--sweep | --sweep-lite | --sweep-total'],
+    'rbdiag' : [rbdiag, '(builtin)* [-v] [-n] [-m] [--sweep | --sweep-lite | --sweep-total] [--mnonly] [--noSelfTest]'],
     'rcmplib' : [rcmplib, ['options']],
     'rrepl' : [rrepl, '[options]'],
     'rembed' : [rembed, '[options]'],
-- 
GitLab