diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index e1c3ca08e3b0899498abbe29882a93dc486d7462..b200768c1127edf4101bdbf8d53dd8eed8a7b69b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -361,6 +361,7 @@ public class BasePackage extends RBuiltinPackage { add(DimNames.class, DimNamesNodeGen::create); add(DoCall.class, DoCallNodeGen::create); add(DPut.class, DPutNodeGen::create); + add(Dump.class, DumpNodeGen::create); add(Drop.class, DropNodeGen::create); add(DuplicatedFunctions.AnyDuplicated.class, DuplicatedFunctionsFactory.AnyDuplicatedNodeGen::create); add(DuplicatedFunctions.Duplicated.class, DuplicatedFunctionsFactory.DuplicatedNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dump.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dump.java new file mode 100644 index 0000000000000000000000000000000000000000..22ef993e33fb83761e59cb3d0bce3e00349cff74 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dump.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.nodes.builtin.base; + +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT; +import static com.oracle.truffle.r.runtime.RVisibility.OFF; +import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; + +import java.io.IOException; +import java.util.Arrays; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +import com.oracle.truffle.r.runtime.RDeparse; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.conn.RConnection; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +@RBuiltin(name = "dump", visibility = OFF, kind = INTERNAL, parameterNames = {"list", "file", "envir", "opts", "evaluate"}, behavior = IO) +public abstract class Dump extends RBuiltinNode.Arg5 { + + @Child protected Helper helper; + + static { + Casts casts = new Casts(Dump.class); + casts.arg("list").mustNotBeMissing().mustBe(Predef.stringValue()).asStringVector(); + casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst(); + casts.arg("envir").mustNotBeMissing().mustBe(REnvironment.class, INVALID_ARGUMENT, "envir"); + casts.arg("opts").mustNotBeMissing().asIntegerVector().findFirst(); + casts.arg("evaluate").mustNotBeMissing().asLogicalVector().findFirst().map(Predef.toBoolean()); + } + + @Specialization + protected Object dump(VirtualFrame frame, RAbstractStringVector x, int file, REnvironment envir, int opts, boolean evaluate) { + if (helper == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + helper = insert(new Helper()); + } + int retrieved = 0; + String[] retrievedNames = new String[x.getLength()]; + Object[] objects = new Object[x.getLength()]; + for (int i = 0; i < x.getLength(); i++) { + String name = x.getDataAt(i); + objects[i] = helper.getAndCheck(frame, name, envir, evaluate); + if (objects[i] != null) { + retrievedNames[retrieved++] = name; + } + } + writeToConnection(deparse(x, objects, prepareOpts(opts, evaluate)), file); + return RDataFactory.createStringVector(Arrays.copyOfRange(retrievedNames, 0, retrieved), RDataFactory.COMPLETE_VECTOR); + } + + @TruffleBoundary + private static String deparse(RAbstractStringVector x, Object[] objects, int opts) { + assert x.getLength() == objects.length; + StringBuilder code = new StringBuilder(); + for (int i = 0; i < objects.length; i++) { + if (objects[i] != null) { + if (i != 0) { + code.append(System.lineSeparator()); + } + code.append(x.getDataAt(i)).append(" <-").append(System.lineSeparator()).append(RDeparse.deparse(objects[i], RDeparse.DEFAULT_CUTOFF, true, opts, -1)); + } + } + return code.toString(); + } + + @TruffleBoundary + private void writeToConnection(String code, int file) { + try (RConnection openConn = RConnection.fromIndex(file).forceOpen("wt")) { + openConn.writeString(code, true); + } catch (IOException ex) { + throw error(RError.Message.GENERIC, ex.getMessage()); + } + } + + private static int prepareOpts(int opts, boolean evaluate) { + return evaluate ? opts : opts | RDeparse.DELAYPROMISES; + } + + private static final class Helper extends RBaseNode { + + @Child private PromiseHelperNode promiseHelper; + + @CompilationFinal private boolean firstExecution = true; + + protected void unknownObject(String x) { + warning(RError.Message.UNKNOWN_OBJECT, x); + } + + protected Object checkPromise(VirtualFrame frame, Object r, String identifier) { + if (r instanceof RPromise) { + if (firstExecution) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + firstExecution = false; + return ReadVariableNode.evalPromiseSlowPathWithName(identifier, frame, (RPromise) r); + } + if (promiseHelper == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + promiseHelper = insert(new PromiseHelperNode()); + } + return promiseHelper.evaluate(frame, (RPromise) r); + } else { + return r; + } + } + + protected Object getAndCheck(VirtualFrame frame, String x, REnvironment env, boolean evaluatePromise) { + Object obj; + if (evaluatePromise) { + obj = checkPromise(frame, env.get(x), x); + } else { + obj = env.get(x); + } + if (obj != null) { + return obj; + } else { + unknownObject(x); + return null; + } + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java index bf283b26035874d27723ac6863c20439a148c5bd..fde5609e43395c48c0144a55ba92c565903a6f87 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java @@ -62,7 +62,7 @@ public final class GetCallerFrameNode extends RBaseNode { return slowPathFrame; } } - assert callerFrameObject == null; + assert callerFrameObject instanceof CallerFrameClosure || callerFrameObject == null; // S3 method can be dispatched from top-level where there is no caller frame // Since RArguments does not allow to create arguments with a 'null' caller frame, this diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java index 9fc48e238af3b92c8c436b8ac2f1ea8df9ddc596..53cf0b30375ebbfec7da318cd378c4f9e85e53d2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; @@ -183,6 +184,11 @@ public abstract class ConvertBooleanNode extends RNode { throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); } + @Fallback + protected byte doObject(Object o) { + throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); + } + public static ConvertBooleanNode create(RSyntaxNode node) { if (node instanceof ConvertBooleanNode) { return (ConvertBooleanNode) node; diff --git a/com.oracle.truffle.r.pkgs/refcmp/DESCRIPTION b/com.oracle.truffle.r.pkgs/refcmp/DESCRIPTION new file mode 100644 index 0000000000000000000000000000000000000000..db08b312ea63a20cd42da20fdf2e94fd446e1d61 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/DESCRIPTION @@ -0,0 +1,12 @@ +Package: refcmp +Type: Package +Title: Compare snapshotted variables to a reference run +Version: 1.0 +Date: 2017-09-07 +Author: Florian Angerer +Maintainer: Florian Angerer <florian.angerer@oracle.com> +Copyright: Oracle +Description: Compare values at defined snapshot to a reference run. +License: GPL-2 +Depends: +RoxygenNote: 6.0.1 diff --git a/com.oracle.truffle.r.pkgs/refcmp/NAMESPACE b/com.oracle.truffle.r.pkgs/refcmp/NAMESPACE new file mode 100644 index 0000000000000000000000000000000000000000..77c432a5901fda5ccbe5df9d60a6bbb96485adf4 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/NAMESPACE @@ -0,0 +1,6 @@ +# Generated by roxygen2: do not edit by hand + +export(snapshot) +export(snapshot.init) +export(snapshot.named) +export(snapshot.show) diff --git a/com.oracle.truffle.r.pkgs/refcmp/R/refcmp.R b/com.oracle.truffle.r.pkgs/refcmp/R/refcmp.R new file mode 100644 index 0000000000000000000000000000000000000000..1bea83401725d277bd48791c309be4f9c19b4c69 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/R/refcmp.R @@ -0,0 +1,25 @@ +#' The refcmp packages is supposed to compare intermediate values to a dedicated reference run. +#' +#' @name refcmp +#' @examples +#' # Loading and setting up +#' +#' library(refcmp) +#' snapshot.init() +#' +#' # Taking a snapshot of variables or comparing the values to the reference run +#' a <- 1 +#' b <- 2 +#' snapshot(a, b) +#' +#' # Taking a snapshot of expressions or comparing the values +#' # We need to name them +#' snapshot.named(c = 2 +3, d = a + b) +#' +#' # Show the contents of the latest snapshot +#' snapshot.show() +#' +#' # Show the contents of a snapshot using the ID (a sequence number) +#' snapshot.show(0) +#' +NULL diff --git a/com.oracle.truffle.r.pkgs/refcmp/R/snapshot.R b/com.oracle.truffle.r.pkgs/refcmp/R/snapshot.R new file mode 100644 index 0000000000000000000000000000000000000000..11673c4d50489f5e5b2ea6702c87871c22268bc0 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/R/snapshot.R @@ -0,0 +1,200 @@ +## + # Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it + # under the terms of the GNU General Public License version 2 only, as + # published by the Free Software Foundation. + # + # This code is distributed in the hope that it will be useful, but WITHOUT + # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + # version 2 for more details (a copy is included in the LICENSE file that + # accompanied this code). + # + # You should have received a copy of the GNU General Public License version + # 2 along with this work; if not, write to the Free Software Foundation, + # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + # + # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + # or visit www.oracle.com if you need additional information or have any + # questions. +## + +refcmpEnv <- new.env(parent = emptyenv()) +refcmpEnv$snapshot_dir <- 'snapshots' +refcmpEnv$snapshot_id <- 0L +refcmpEnv$equals <- all.equal + +snapshot.isFastR <- function() { + length(grep('FastR', R.Version()$version.string)) != 0 +} + +#' Initialize package +#' +#' @param dir The directory where to store snapshot to (default: 'snapshots') +#' @param is_reference_run A function returning TRUE if snapshots should be taken and FALSE if values should be compared (default: snapshot dir does not exist) +#' @param equalityFunction The function to use for comparing actual values to snapshotted values (default: 'all.equal') +#' @examples +#' # Only comparing using snapshots in directory "my/snapshot/dir" and using function 'identical' to compare values. +#' snapshot.init(dir = "my/snapshot/dir", referenceRunPredicate = function() FALSE, equalityFunction = identical) +#' +#' # This should do the job in most cases +#' snapshot.init() +#' @export +snapshot.init <- function (dir, is_reference_run, equalityFunction) { + if (!missing(dir)) { + refcmpEnv$snaphost_dir <- dir + } + if (!missing(is_reference_run)) { + refcmpEnv$is_reference_run <- is_reference_run + } else { + refcmpEnv$is_reference_run <- !file.exists(refcmpEnv$snapshot_dir) + } + if (!missing(equalityFunction)) { + refcmpEnv$equals <- equalityFunction + } + refcmpEnv$snapshot_id <- 0L +} + +#' Take a snapshot of some variable's values or compare the values to a previously taken snapshot. +#' +#' This function has two modes, (1) record, and (2) check. +#' Depending on the result of function 'refcmpEnv$is_reference_run', the mode is (1) if TRUE is returned or (2) otherwise. +#' +#' When in the first mode 'record', function 'snapshot' serializes the values of the specified variables into a file together with the names of the variables. It also increases the ID of the snapshot automatically. +#' +#' When in the second mode 'check', function 'snapshot' deserializes values of a previously taken snapshot and compares the values of the provided variables to the deserialized values by matching names. +#' +#' @examples +#' x <- 10 +#' y <- 20 +#' z <- function() print("hello") +#' +#' snapshot(x, y, z) +#' @export +snapshot <- function(...) { + # the actual parameter expessions + actParExprs <- as.list(match.call()[-1]) + valueList <- actParsToList(actParExprs, parent.frame()) + try({ + snapshot.id(refcmpEnv$snapshot_id, valueList) + refcmpEnv$snapshot_id <- refcmpEnv$snapshot_id + 1 + }) +} + +#' Take a snapshot of provided values and name the values as specified in the arguments. +#' +#' This function has two modes, (1) record, and (2) check. +#' Depending on the result of function 'refcmpEnv$is_reference_run', the mode is (1) if TRUE is returned or (2) otherwise. +#' +#' When in the first mode 'record', function 'snapshot.named' serializes the values of the specified variables into a file together with the names of the variables. It also increases the ID of the snapshot automatically. +#' +#' When in the second mode 'check', function 'snapshot.named' deserializes values of a previously taken snapshot and compares the values of the provided variables to the deserialized values by matching names. +#' +#' I contrast to function 'snapshot', this function does not try to automatically determine the name of a value. +#' It uses the names as provided in the arguments. +#' +#' @examples +#' snapshot.named(a = 10 + 20, b = 30, c = function() print("hello")) +#' @export +snapshot.named <- function (...) { + args <- list(...) + valueList <- args[names(args) != ""] + try({ + snapshot.id(refcmpEnv$snapshot_id, valueList) + refcmpEnv$snapshot_id <- refcmpEnv$snapshot_id + 1 + }) +} + +snapshot.id <- function(id, valueList) { + if(refcmpEnv$is_reference_run) { + snapshot.record(id, valueList) + } else { + snapshot.check(id, valueList) + } +} + +snapshot.record <- function(id, valueList) { + dumpDir <- file.path(refcmpEnv$snapshot_dir) + if(!dir.exists(dumpDir)) { + dir.create(dumpDir) + } + fcon <- file(file.path(refcmpEnv$snapshot_dir, paste0("snapshot", id, ".obj"))) + saveRDS(valueList, file=fcon) + close(fcon) +} + +snapshot.check <- function(id, valueList) { + fcon <- file(file.path(refcmpEnv$snapshot_dir, paste0("snapshot", id, ".obj"))) + restoredVars <- readRDS(file=fcon) + close(fcon) + + if(length(restoredVars) < length(valueList)) { + stop(paste("recorded snapshot has", length(restoredVars), "recorded variables but expected", length(valueList))) + } + + var_names <- names(valueList) + restored_names <- names(restoredVars) + for(i in seq_along(var_names)) { + if(var_names[[i]] %in% restored_names) { + actualVal <- valueList[[var_names[[i]]]] + expectedVal <- restoredVars[[var_names[[i]]]] + if(!refcmpEnv$equals(expectedVal, actualVal)) { + stop(paste0("Value of variable '", var_names[[i]], "' differs. Expected ", expectedVal, " but was ", actualVal)) + } + } else { + stop(paste0("Missing variable '", var_names[[i]], "' in recorded variables")) + } + } +} + +#' Shows the contents of a snapshot. +#' +#' @param id The ID of the snapshot to show (default: latest) +#' +#' @examples +#' a <- 1 +#' snapshot(a) +#' snapshot.show() +#' +#' a <- 2 +#' snapshot(a) +#' +#' a <- 3 +#' snapshot(a) +#' +#' a <- 4 +#' snapshot(a) +#' snapshot.show(0) +#' snapshot.show(1) +#' snapshot.show(2) +#' snapshot.show(3) +#' @export +snapshot.show <- function(id = refcmpEnv$snapshot_id) { + snapshot_filename <- file.path(refcmpEnv$snapshot_dir, paste0("snapshot", id, ".obj")) + if(!file.exists(snapshot_filename)) { + stop(paste0("Snapshot with ID=", id, " does not exist")) + } + fcon <- file(snapshot_filename) + restoredVars <- readRDS(file=fcon) + close(fcon) + + return (restoredVars) +} + +actParsToList <- function(pars, env) { + l <- list() + for(i in seq_along(pars)) { + strrep <- as.character(pars[[i]]) + if (is.symbol(pars[[i]])) { + value <- eval(pars[[i]], envir=env) + l[[strrep]] <- value + } else { + warning(paste0("Skipping '", strrep, "' because only symbols are allowed")) + } + } + l +} + + diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/refcmp.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/refcmp.Rd new file mode 100644 index 0000000000000000000000000000000000000000..98677ce0b2f04ff25fd34b005684a7bdc90461e5 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/man/refcmp.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/refcmp.R +\name{refcmp} +\alias{refcmp} +\title{The refcmp packages is supposed to compare intermediate values to a dedicated reference run.} +\description{ +The refcmp packages is supposed to compare intermediate values to a dedicated reference run. +} +\examples{ +# Loading and setting up + +library(refcmp) +snapshot.init() + +# Taking a snapshot of variables or comparing the values to the reference run +a <- 1 +b <- 2 +snapshot(a, b) + +# Taking a snapshot of expressions or comparing the values +# We need to name them +snapshot.named(c = 2 +3, d = a + b) + +# Show the contents of the latest snapshot +snapshot.show() + +# Show the contents of a snapshot using the ID (a sequence number) +snapshot.show(0) + +} diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.Rd new file mode 100644 index 0000000000000000000000000000000000000000..792bed41912e361590b4590d457735317e3a5f44 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/snapshot.R +\name{snapshot} +\alias{snapshot} +\title{Take a snapshot of some variable's values or compare the values to a previously taken snapshot.} +\usage{ +snapshot(...) +} +\description{ +This function has two modes, (1) record, and (2) check. +Depending on the result of function 'refcmpEnv$is_reference_run', the mode is (1) if TRUE is returned or (2) otherwise. +} +\details{ +When in the first mode 'record', function 'snapshot' serializes the values of the specified variables into a file together with the names of the variables. It also increases the ID of the snapshot automatically. + +When in the second mode 'check', function 'snapshot' deserializes values of a previously taken snapshot and compares the values of the provided variables to the deserialized values by matching names. +} +\examples{ +x <- 10 +y <- 20 +z <- function() print("hello") + +snapshot(x, y, z) +} diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.init.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.init.Rd new file mode 100644 index 0000000000000000000000000000000000000000..012f384caf43f652146f55ff2568401591c2601f --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.init.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/snapshot.R +\name{snapshot.init} +\alias{snapshot.init} +\title{Initialize package} +\usage{ +snapshot.init(dir, is_reference_run, equalityFunction) +} +\arguments{ +\item{dir}{The directory where to store snapshot to (default: 'snapshots')} + +\item{is_reference_run}{A function returning TRUE if snapshots should be taken and FALSE if values should be compared (default: snapshot dir does not exist)} + +\item{equalityFunction}{The function to use for comparing actual values to snapshotted values (default: 'all.equal')} +} +\description{ +Initialize package +} +\examples{ +# Only comparing using snapshots in directory "my/snapshot/dir" and using function 'identical' to compare values. +snapshot.init(dir = "my/snapshot/dir", referenceRunPredicate = function() FALSE, equalityFunction = identical) + +# This should do the job in most cases +snapshot.init() +} diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.named.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.named.Rd new file mode 100644 index 0000000000000000000000000000000000000000..1a076ec6915b17ab039728a26395a1d2ffbafeb2 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.named.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/snapshot.R +\name{snapshot.named} +\alias{snapshot.named} +\title{Take a snapshot of provided values and name the values as specified in the arguments.} +\usage{ +snapshot.named(...) +} +\description{ +This function has two modes, (1) record, and (2) check. +Depending on the result of function 'refcmpEnv$is_reference_run', the mode is (1) if TRUE is returned or (2) otherwise. +} +\details{ +When in the first mode 'record', function 'snapshot.named' serializes the values of the specified variables into a file together with the names of the variables. It also increases the ID of the snapshot automatically. + +When in the second mode 'check', function 'snapshot.named' deserializes values of a previously taken snapshot and compares the values of the provided variables to the deserialized values by matching names. + +I contrast to function 'snapshot', this function does not try to automatically determine the name of a value. +It uses the names as provided in the arguments. +} +\examples{ +snapshot.named(a = 10 + 20, b = 30, c = function() print("hello")) +} diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.show.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.show.Rd new file mode 100644 index 0000000000000000000000000000000000000000..d2170d4e23269777f151b33870dd145a36d416c9 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.show.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/snapshot.R +\name{snapshot.show} +\alias{snapshot.show} +\title{Shows the contents of a snapshot.} +\usage{ +snapshot.show(id = refcmpEnv$snapshot_id) +} +\arguments{ +\item{id}{The ID of the snapshot to show (default: latest)} +} +\description{ +Shows the contents of a snapshot. +} +\examples{ +a <- 1 +snapshot(a) +snapshot.show() + +a <- 2 +snapshot(a) + +a <- 3 +snapshot(a) + +a <- 4 +snapshot(a) +snapshot.show(0) +snapshot.show(1) +snapshot.show(2) +snapshot.show(3) +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java index ecd287b87b5bdf9a1c120d634bc935e074af3c8c..6dedde1535352ed78b38f7aa66e496d2e6ccf3ad 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java @@ -222,6 +222,9 @@ public final class ArgumentsSignature implements Iterable<String> { return false; } ArgumentsSignature other = (ArgumentsSignature) obj; + if (length != other.length) { + return false; + } if (!Arrays.equals(names, other.names)) { return false; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java index 79911c2ea1a89f89c83829060c0a7021336f1895..fec907242f0fc9d30cb9e084d97b8384a3fa941e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java @@ -363,8 +363,8 @@ abstract class DelegateRConnection implements RConnection, ByteChannel { channel.position(offset); break; case END: - throw RInternalError.unimplemented(); - + channel.position(channel.size()); + break; } return position; } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 23aeeb5945798641fbd90e60e94ccec19d95c57e..867ad706c8c086e9fe0427b76e16002d08686958 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -22909,6 +22909,48 @@ End = 1 Frequency = 1 [1] FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpData#Output.IgnoreWhitespace# +#{ x <- 10; .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), TRUE))} +x <- +10 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpData#Output.IgnoreWhitespace# +#{ x <- 1:10; .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), TRUE))} +x <- +1:10 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpData#Output.IgnoreWhitespace# +#{ x <- c(10,20,25); .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), TRUE))} +x <- +c(10, 20, 25) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpData#Output.IgnoreWhitespace# +#{ x <- list(a=10,b=20); .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), TRUE))} +x <- +structure(list(a = 10, b = 20), .Names = c("a", "b")) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpFunctions#Output.IgnoreWhitespace# +#{ foo <- function() cat("Hello"); bar <- function() cat("World"); .Internal(dump(c("foo", "bar"), stdout(), environment(), .deparseOpts("all"), TRUE))} +foo <- +function() cat("Hello") +bar <- +function() cat("World") + +##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpFunctions#Output.IgnoreWhitespace# +#{ fun <- function() print("Hello, World!"); .Internal(dump("fun", stdout(), environment(), .deparseOpts("all"), TRUE))} +fun <- +function() print("Hello, World!") + +##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpLanguage#Output.IgnoreWhitespace# +#{ x <- 2 + 3; .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), FALSE))} +x <- +5 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpLanguage#Output.IgnoreWhitespace# +#{ x <- quote(2 + 3); .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), FALSE))} +x <- +quote(2 + 3) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated# #{ duplicated(NULL, 0); } logical(0) @@ -86106,6 +86148,10 @@ NULL ##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfWithoutElseIgnore# #if(FALSE) 1 +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testInvalidCondition# +#{ f <- function() TRUE; if (f) 'unexpected' } +Error in if (f) "unexpected" : argument is not interpretable as logical + ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying# #a<-list(); a$x <- c(1,2,3); ident <- function(q)q; invisible(tracemem(a$x)); a$x[[1]] <- ident(a$x[[2]]); a$x [1] 2 2 3 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dump.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dump.java new file mode 100644 index 0000000000000000000000000000000000000000..8d81d425416539cf084cee2f1a745b44f607b994 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dump.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +// Checkstyle: stop line length check +public class TestBuiltin_dump extends TestBase { + + private static final String TEMPLATE = "{ %s; .Internal(dump(%s, stdout(), environment(), .deparseOpts(\"all\"), %s))}"; + + @Test + public void testDumpFunctions() { + assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "fun <- function() print(\"Hello, World!\")", "\"fun\"", "TRUE")); + assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "foo <- function() cat(\"Hello\"); bar <- function() cat(\"World\")", "c(\"foo\", \"bar\")", "TRUE")); + } + + @Test + public void testDumpData() { + assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- 10", "\"x\"", "TRUE")); + assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- list(a=10,b=20)", "\"x\"", "TRUE")); + assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- c(10,20,25)", "\"x\"", "TRUE")); + assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- 1:10", "\"x\"", "TRUE")); + } + + @Test + public void testDumpLanguage() { + assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- 2 + 3", "\"x\"", "FALSE")); + assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- quote(2 + 3)", "\"x\"", "FALSE")); + } + +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java index 60dc992cb1c4a89329dfdfd6dad428c00a7ad884..eaf9e7103d64916684fa218e2187505296bc38b0 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java @@ -100,4 +100,9 @@ public class TestSimpleIfEvaluator extends TestBase { assertEval("{ if (TRUE) invisible(23) }"); assertEval("{ if (FALSE) 23 else invisible(23) }"); } + + @Test + public void testInvalidCondition() { + assertEval("{ f <- function() TRUE; if (f) 'unexpected' }"); + } }