diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java index 00e8d03e3f6c55b1f7ef38d6f59ce8c5cd047f0a..2164f840c03c283d9dd476ece6fc2f227b3c5136 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java @@ -37,6 +37,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.EvalNodeGen.EvalEnvCastNodeGen; import com.oracle.truffle.r.nodes.builtin.base.FrameFunctions.SysFrame; @@ -63,6 +64,11 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; @RBuiltin(name = "eval", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"expr", "envir", "enclos"}, behavior = COMPLEX) public abstract class Eval extends RBuiltinNode { + /** + * Profiling for catching {@link ReturnException}s. + */ + private final ConditionProfile returnTopLevelProfile = ConditionProfile.createBinaryProfile(); + /** * Eval takes two arguments that specify the environment where the expression should be * evaluated: 'envir', 'enclos'. These arguments are pre-processed by the means of default @@ -148,7 +154,11 @@ public abstract class Eval extends RBuiltinNode { try { return RContext.getEngine().eval(expr, environment, rCaller); } catch (ReturnException ret) { - return ret.getResult(); + if (returnTopLevelProfile.profile(ret.getTarget() == rCaller)) { + return ret.getResult(); + } else { + throw ret; + } } finally { visibility.executeAfterCall(frame, rCaller); } @@ -161,7 +171,11 @@ public abstract class Eval extends RBuiltinNode { try { return RContext.getEngine().eval(expr, environment, rCaller); } catch (ReturnException ret) { - return ret.getResult(); + if (returnTopLevelProfile.profile(ret.getTarget() == rCaller)) { + return ret.getResult(); + } else { + throw ret; + } } finally { visibility.executeAfterCall(frame, rCaller); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java index 67b2bbd51707a4e5a18fa48104f2401aecb7404c..5d2925cfbe235ae9cfbaab2e5cda6b1272c32a42 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java @@ -27,6 +27,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.UnlistNodeGen.RecursiveLengthNodeGen; import com.oracle.truffle.r.nodes.unary.PrecedenceNode; import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen; +import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -40,11 +41,12 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -@RBuiltin(name = "unlist", kind = INTERNAL, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE) +@RBuiltin(name = "unlist", kind = INTERNAL, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE) public abstract class Unlist extends RBuiltinNode { // portions of the algorithm were transcribed from GNU R @@ -96,6 +98,11 @@ public abstract class Unlist extends RBuiltinNode { return 1; } + @Specialization + protected int getLength(@SuppressWarnings("unused") RSymbol s) { + return 1; + } + @Specialization(guards = "!isVectorList(vector)") protected int getLength(RAbstractVector vector) { return vector.getLength(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java index 4619df7873767cf57eb2f9b2b0a24c3512e4f14e..636a8b4c95988a4dcad547e4e1e10c00ee99ca39 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * Copyright (c) 2015, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -14,14 +14,12 @@ package com.oracle.truffle.r.nodes.objects; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.function.CallMatcherNode; -import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.signature.CollectArgumentsNode; import com.oracle.truffle.r.nodes.function.signature.CollectArgumentsNodeGen; -import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.S4Args; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RFunction; @@ -45,12 +43,8 @@ final class ExecuteMethod extends RBaseNode { callMatcher = insert(CallMatcherNode.create(false)); } - FormalArguments formals = ((RRootNode) fdef.getRootNode()).getFormalArguments(); - ArgumentsSignature signature = formals.getSignature(); - Object[] oldArgs = collectArgs.execute(frame, signature); - S4Args s4Args = new S4Args(readDefined.execute(frame), readMethod.execute(frame), readTarget.execute(frame), readGeneric.execute(frame), readMethods.execute(frame)); - return callMatcher.execute(frame, signature, oldArgs, fdef, fname, s4Args); + return callMatcher.execute(frame, RArguments.getSignature(frame), RArguments.getArguments(frame), fdef, fname, s4Args); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index a28f47de137f5aa79972bdf9af6aef0b4dae09eb..eda8d1fee8af05be6eb5d8add2d77776f0b80202 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -33,6 +33,10 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.r.runtime.conn.RConnection; @@ -71,6 +75,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; @@ -115,6 +120,7 @@ public class RSerialize { static final int LEVELS_SHIFT = 12; static final int CACHED_MASK = 1 << 5; static final int HASHASH_MASK = 1; + static final int IS_ACTIVE_BINDING_MASK = 1 << 15; private Flags() { // prevent construction @@ -142,6 +148,10 @@ public class RSerialize { return (flagsValue & HAS_TAG_BIT_MASK) != 0; } + public static boolean isActiveBinding(int levs) { + return (levs & IS_ACTIVE_BINDING_MASK) != 0; + } + public static int packFlags(SEXPTYPE type, int gpbits, boolean isObj, boolean hasAttr, boolean hasTag) { int val = type.code; int levs = gpbits & (~(CACHED_MASK | HASHASH_MASK)); @@ -490,14 +500,13 @@ public class RSerialize { if (val == RNull.instance) { continue; } - RPairList pl = (RPairList) val; - env.safePut(((RSymbol) pl.getTag()).getName(), pl.car()); + safePutToEnv(env, (RPairList) val); } } } else { while (frame != RNull.instance) { RPairList pl = (RPairList) frame; - env.safePut(((RSymbol) pl.getTag()).getName(), pl.car()); + safePutToEnv(env, pl); frame = pl.cdr(); } } @@ -534,8 +543,14 @@ public class RSerialize { Object attrItem = RNull.instance; Object tagItem = RNull.instance; if (Flags.hasAttr(flags)) { + // create new language parsing context + int safedLangDepth = langDepth; + langDepth = 0; attrItem = readItem(); + // restore language parsing context + langDepth = safedLangDepth; + } if (Flags.hasTag(flags)) { tagItem = readItem(); @@ -622,6 +637,10 @@ public class RSerialize { } case LISTSXP: + if (Flags.isActiveBinding(levs)) { + assert carItem instanceof RFunction; + carItem = new ActiveBinding(RType.Any, (RFunction) carItem); + } RPairList pairList = RDataFactory.createPairList(carItem, cdrItem, tagItem, type); result = pairList; if (attrItem != RNull.instance) { @@ -829,6 +848,17 @@ public class RSerialize { return checkResult(result); } + private static void safePutToEnv(REnvironment env, RPairList pl) { + String name = ((RSymbol) pl.getTag()).getName(); + Object car = pl.car(); + if (ActiveBinding.isActiveBinding(car)) { + FrameSlot frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(env.getFrame().getFrameDescriptor(), name, FrameSlotKind.Object); + FrameSlotChangeMonitor.setActiveBinding(env.getFrame(), frameSlot, (ActiveBinding) car, false, null); + } else { + env.safePut(name, car); + } + } + private static Object checkResult(Object result) { assert result != null; return result; @@ -1422,7 +1452,7 @@ public class RSerialize { */ String[] bindings = env.ls(true, null, false).getDataWithoutCopying(); for (String binding : bindings) { - Object value = env.get(binding); + Object value = getValueIgnoreActiveBinding(env.getFrame(), binding); writePairListEntry(binding, value); } terminatePairList(); @@ -1655,6 +1685,16 @@ public class RSerialize { } while (tailCall); } + private static Object getValueIgnoreActiveBinding(Frame frame, String key) { + FrameDescriptor fd = frame.getFrameDescriptor(); + FrameSlot slot = fd.findFrameSlot(key); + if (slot == null) { + return null; + } else { + return frame.getValue(slot); + } + } + private Object getPersistentName(Object obj) { if (hook == null) { return RNull.instance; @@ -1728,7 +1768,8 @@ public class RSerialize { } private void writePairListEntry(String name, Object value) throws IOException { - stream.writeInt(Flags.packFlags(SEXPTYPE.LISTSXP, 0, false, false, true)); + boolean isActiveBinding = ActiveBinding.isActiveBinding(value); + stream.writeInt(Flags.packFlags(SEXPTYPE.LISTSXP, isActiveBinding ? Flags.IS_ACTIVE_BINDING_MASK : 0, false, false, true)); RSymbol sym = state.findSymbol(name); int refIndex; if ((refIndex = getRefIndex(sym)) != -1) { @@ -1736,7 +1777,11 @@ public class RSerialize { } else { writeSymbol(sym); } - writeItem(value); + if (isActiveBinding) { + writeItem(((ActiveBinding) value).getFunction()); + } else { + writeItem(value); + } } private void writeSymbol(RSymbol name) throws IOException { 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 339c40082612ed69f404d3c2ba5bc212fcaed989..322f7f2982969487d5eef7207afc71be99a48059 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 @@ -60,7 +60,7 @@ Error: invalid assignment for reference class field ‘a’, should be from clas [1] TRUE [1] TRUE -##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Output.IgnoreWhitespace# +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Ignored.OutputFormatting# #print(suppressMessages({clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo')})) function() NULL attr(,"mayCall") @@ -425,6 +425,26 @@ Slots: Name: j Class: numeric +##com.oracle.truffle.r.test.S4.TestS4.testClassCreation# +#{ setClass('foo', contains='standardGeneric'); getClass('foo') } +Class "foo" [in ".GlobalEnv"] + +Slots: + +Name: .Data generic package group +Class: function character character list + +Name: valueClass signature default skeleton +Class: character character optionalMethod call + +Extends: +Class "standardGeneric", directly +Class "genericFunction", by class "standardGeneric", distance 2 +Class "function", by class "standardGeneric", distance 3 +Class "OptionalFunction", by class "standardGeneric", distance 4 +Class "PossibleMethod", by class "standardGeneric", distance 4 +Class "optionalMethod", by class "standardGeneric", distance 5 + ##com.oracle.truffle.r.test.S4.TestS4.testConversions# #{ asS4(7:42) } [1] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @@ -725,6 +745,10 @@ Error in (function (cl, name, valueClass) : ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate# #{ x<-initialize@valueClass; initialize@valueClass<-"foo"; initialize@valueClass<-x } +##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric# +#{ setClass('A4', representation(a = 'numeric')); setMethod('[[', 'A4', function(x, i, j, ...) NULL); obj <- new('A4'); obj[[1]] } +NULL + ##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric# #{ standardGeneric("") } Error in standardGeneric("") : @@ -62325,6 +62349,35 @@ Error in seq.int(NaN) : 'from' cannot be NA, NaN or infinite #argv <- list(from = 0, to = 0.793110173512391, length.out = FALSE);do.call('seq.int', argv); integer(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#Ignored.ImplementationError# +#options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 07 03 00 00 04 02 00 00 00 + [26] 01 00 04 00 09 00 00 00 09 63 6c 61 73 73 4e 61 6d 65 00 00 02 10 00 00 00 + [51] 01 00 04 00 09 00 00 00 0a 46 6f 6f 53 65 72 69 61 6c 31 00 00 04 02 00 00 + [76] 00 01 00 04 00 09 00 00 00 07 70 61 63 6b 61 67 65 00 00 00 10 00 00 00 01 +[101] 00 04 00 09 00 00 00 0a 2e 47 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 04 +[126] 02 00 00 02 ff 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47 6c 6f +[151] 62 61 6c 45 6e 76 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 05 63 6c 61 +[176] 73 73 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 16 63 6c 61 73 73 47 65 +[201] 6e 65 72 61 74 6f 72 46 75 6e 63 74 69 6f 6e 00 00 04 02 00 00 02 ff 00 00 +[226] 00 10 00 00 00 01 00 04 00 09 00 00 00 07 6d 65 74 68 6f 64 73 00 00 00 fe +[251] 00 00 00 fe 00 00 00 fd 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 03 2e +[276] 2e 2e 00 00 00 fb 00 00 00 fe 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00 +[301] 03 6e 65 77 00 00 00 02 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 0a 46 +[326] 6f 6f 53 65 72 69 61 6c 31 00 00 04 02 00 00 02 ff 00 00 00 10 00 00 00 01 +[351] 00 04 00 09 00 00 00 0a 2e 47 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 00 +[376] 06 00 00 04 ff 00 00 00 fe + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); mc <- setClass('FooSerial0', representation(a = 'call')); obj <- new('FooSerial0'); serialize(obj, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 03 19 00 00 04 02 00 00 00 + [26] 01 00 04 00 09 00 00 00 01 61 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00 + [51] 07 3c 75 6e 64 65 66 3e 00 00 00 fe 00 00 04 02 00 00 00 01 00 04 00 09 00 + [76] 00 00 05 63 6c 61 73 73 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 0a 46 +[101] 6f 6f 53 65 72 69 61 6c 30 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 07 +[126] 70 61 63 6b 61 67 65 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47 +[151] 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 00 fe + ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# #options(keep.source=FALSE); serialize('asdf', connection=NULL) [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 10 00 00 00 01 00 04 00 @@ -62759,6 +62812,20 @@ integer(0) [51] 00 00 00 01 00 04 00 09 00 00 00 05 6e 61 6d 65 73 00 00 00 10 00 00 00 01 [76] 00 04 00 09 00 00 00 06 65 6e 63 6c 6f 73 00 00 00 fe +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); data <- serialize(val, connection=NULL); newenv <- unserialize(rawConnection(data)); newenv$a +[1] "hello" +[1] "hello" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); serialize(val, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 04 00 00 00 00 00 00 00 + [26] fd 08 00 04 02 00 00 00 01 00 04 00 09 00 00 00 01 61 00 00 04 03 00 00 00 + [51] fd 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 01 78 00 00 00 fb 00 00 00 + [76] fe 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00 05 70 72 69 6e 74 00 00 00 +[101] 02 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 05 68 65 6c 6c 6f 00 00 00 +[126] fe 00 00 00 fe 00 00 00 fe 00 00 00 fe + ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# #options(keep.source=FALSE); val <- new.env(hash=FALSE); serialize(val, connection=NULL) [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 04 00 00 00 00 00 00 00 @@ -62812,6 +62879,13 @@ integer(0) [151] 63 6b 61 67 65 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47 6c 6f [176] 62 61 6c 45 6e 76 00 00 00 fe 00 00 00 fe +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) } +function () +NULL +attr(,"skeleton") +`<undef>`() + ##com.oracle.truffle.r.test.builtins.TestBuiltin_setEncoding.testsetEncoding1# #argv <- list('abc', 'UTF-8'); .Internal(setEncoding(argv[[1]], argv[[2]])) [1] "abc" diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java index d5cf915d84ec92569f0f9b2bdfa78e0c3a658104..a69b6a84e1360650ad23ec0f8c6f9a05431139e5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java @@ -103,6 +103,7 @@ public class TestS4 extends TestRBase { public void testClassCreation() { assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); getClass(\"foo\") }"); assertEval("{ setClass(\"foo\"); setClass(\"bar\", representation(j = \"numeric\"), contains = \"foo\"); is.null(getClass(\"foo\")@prototype) }"); + assertEval("{ setClass('foo', contains='standardGeneric'); getClass('foo') }"); } @Test @@ -141,6 +142,7 @@ public class TestS4 extends TestRBase { assertEval("{ standardGeneric(\"\") }"); assertEval(Output.IgnoreErrorContext, "{ standardGeneric(\"foo\", 42) }"); assertEval(Output.IgnoreErrorContext, "{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }"); + assertEval("{ setClass('A4', representation(a = 'numeric')); setMethod('[[', 'A4', function(x, i, j, ...) NULL); obj <- new('A4'); obj[[1]] }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java index 0679742b3e203e2e39342a53b5ff4a00193b7722..3e031ad10ee498a5d31a0b7b12cf40732aa86c79 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java @@ -101,5 +101,14 @@ public class TestBuiltin_serialize extends TestBase { assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$d <- TRUE; serialize(val, connection=NULL)"); assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$e <- 5+9i; serialize(val, connection=NULL)"); assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$f <- NA; serialize(val, connection=NULL)"); + + // active bindings + assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); serialize(val, connection=NULL)"); + assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); data <- serialize(val, connection=NULL); newenv <- unserialize(rawConnection(data)); newenv$a"); + + assertEval("options(keep.source=FALSE); mc <- setClass('FooSerial0', representation(a = 'call')); obj <- new('FooSerial0'); serialize(obj, connection=NULL)"); + assertEval(Ignored.ImplementationError, "options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL)"); + + assertEval("{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) }"); } }