diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java index 113e978f5282df6795529eb754e586ba158f2a65..3e8b28ed974eef02fe102aaf02086d6554704dc9 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java @@ -13,6 +13,7 @@ package com.oracle.truffle.r.library.methods; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthGt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthGte; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; @@ -55,7 +56,6 @@ import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RS4Object; -import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -68,6 +68,18 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public class MethodsListDispatch { + private static void checkSingleString(CastBuilder casts, int argNum, String argName, String msg, boolean nonEmpty, Function<Object, String> clsHierFn, Function<Object, Integer> vecLenFn) { + //@formatter:off + casts.arg(argNum, argName). + defaultError(RError.NO_CALLER, RError.Message.SINGLE_STRING_WRONG_TYPE, msg, clsHierFn). + mustBe(stringValue()). + asStringVector(). + mustBe(singleElement(), RError.NO_CALLER, RError.Message.SINGLE_STRING_TOO_LONG, msg, vecLenFn). + findFirst(). + mustBe(nonEmpty ? lengthGt(0) : lengthGte(0), RError.NO_CALLER, RError.Message.NON_EMPTY_STRING, msg); + //@formatter:on + } + public abstract static class R_initMethodDispatch extends RExternalBuiltinNode.Arg1 { @Specialization @@ -87,19 +99,23 @@ public class MethodsListDispatch { public abstract static class R_methodsPackageMetaName extends RExternalBuiltinNode.Arg3 { + @Override + protected void createCasts(CastBuilder casts) { + Function<Object, String> clsHierFn = ClassHierarchyScalarNode::get; + Function<Object, Integer> vecLenFn = arg -> ((RAbstractStringVector) arg).getLength(); + + checkSingleString(casts, 0, "prefix", "The internal prefix (e.g., \"C\") for a meta-data object", true, clsHierFn, vecLenFn); + checkSingleString(casts, 1, "name", "The name of the object (e.g,. a class or generic function) to find in the meta-data", false, clsHierFn, vecLenFn); + checkSingleString(casts, 2, "pkg", "The name of the package for a meta-data object", false, clsHierFn, vecLenFn); + } + @Specialization @TruffleBoundary - protected String callMethodsPackageMetaName(RAbstractStringVector prefixStringVector, RAbstractStringVector nameStringVector, RAbstractStringVector pkgStringVector) { - // TODO: proper error messages - assert prefixStringVector.getLength() == 1 && nameStringVector.getLength() == 1 && pkgStringVector.getLength() == 1; - String prefixString = prefixStringVector.getDataAt(0); - String nameString = nameStringVector.getDataAt(0); - String pkgString = pkgStringVector.getDataAt(0); - - if (pkgString.length() == 0) { - return ".__" + prefixString + "__" + nameString; + protected String callMethodsPackageMetaName(String prefix, String name, String pkg) { + if (pkg.length() == 0) { + return ".__" + prefix + "__" + name; } else { - return ".__" + prefixString + "__" + nameString + ":" + pkgString; + return ".__" + prefix + "__" + name + ":" + pkg; } } } @@ -300,14 +316,7 @@ public class MethodsListDispatch { //@formatter:off Function<Object, Integer> vecLenFn = arg -> ((RAbstractStringVector) arg).getLength(); - String msg0 = "The argument \"f\" to getGeneric"; - casts.arg(0, "f"). - defaultError(RError.NO_CALLER, RError.Message.SINGLE_STRING_WRONG_TYPE, msg0, clsHierFn). - mustBe(stringValue()). - asStringVector(). - mustBe(singleElement(), RError.NO_CALLER, RError.Message.SINGLE_STRING_TOO_LONG, msg0, vecLenFn). - findFirst(). - mustBe(lengthGt(0), RError.NO_CALLER, RError.Message.NON_EMPTY_STRING, msg0); + checkSingleString(casts, 0, "f", "The argument \"f\" to getGeneric", true, clsHierFn, vecLenFn); casts.arg(1, "mustFind"). asLogicalVector(). @@ -317,13 +326,7 @@ public class MethodsListDispatch { casts.arg(2, "env"). mustBe(instanceOf(REnvironment.class)); - String msg1 = "The argument \"package\" to getGeneric"; - casts.arg(3, "package"). - defaultError(RError.NO_CALLER, RError.Message.SINGLE_STRING_WRONG_TYPE, msg1, clsHierFn). - mustBe(stringValue()). - asStringVector(). - mustBe(singleElement(), RError.NO_CALLER, RError.Message.SINGLE_STRING_TOO_LONG, msg1, vecLenFn). - findFirst(); + checkSingleString(casts, 3, "package", "The argument \"package\" to getGeneric", false, clsHierFn, vecLenFn); //@formatter:on } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java index 4eab6dfc718fa092d6d56eec4234770ad1e5b21e..a67b35e7adb2026afbfdb1121c058b2408b4b523 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java @@ -22,18 +22,23 @@ */ package com.oracle.truffle.r.library.tools; -import java.io.IOException; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.ffi.AsIntegerNode; +import com.oracle.truffle.r.nodes.ffi.AsLogicalNode; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -44,38 +49,43 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 { @Override protected void createCasts(CastBuilder casts) { - casts.arg(0).defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst(); - } - - @Specialization - protected Object parseRd(int con, REnvironment srcfile, String encoding, byte verboseL, RAbstractStringVector basename, byte fragmentL, byte warningCallsL, byte macrosL, byte warndupsL) { - return doParseRd(con, srcfile, encoding, verboseL, basename, fragmentL, warningCallsL, RDataFactory.createLogicalVectorFromScalar(macrosL), warndupsL); - } - - @Specialization - protected Object parseRd(int con, REnvironment srcfile, String encoding, byte verboseL, RAbstractStringVector basename, byte fragmentL, byte warningCallsL, REnvironment macros, byte warndupsL) { - return doParseRd(con, srcfile, encoding, verboseL, basename, fragmentL, warningCallsL, macros, warndupsL); + /* + * Most arguments require coercion using, e.g., asLogical; N.B. GNU R doesn't check + * everything, e.g., srcfile. Since this is "internal" code we do not really expect argument + * errors. + */ + casts.arg(1, "srcfile").mustBe(instanceOf(REnvironment.class)); + casts.arg(3, "verbose").mustBe(logicalValue()).asLogicalVector(); + casts.arg(4, "basename").mustBe(stringValue()).asStringVector(); } @TruffleBoundary - private Object doParseRd(int con, REnvironment srcfile, @SuppressWarnings("unused") String encoding, byte verboseL, RAbstractStringVector basename, byte fragmentL, byte warningCallsL, - Object macros, byte warndupsL) { - if (RRuntime.isNA(warningCallsL)) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "warningCalls"); + @Specialization + protected Object parseRd(Object conObj, REnvironment srcfile, @SuppressWarnings("unused") Object encoding, RAbstractLogicalVector verbose, RAbstractStringVector basename, Object fragmentObj, + Object warningCallsObj, Object macros, Object warndupsObj, + @Cached("create()") AsIntegerNode conAsInteger, + @Cached("create()") AsLogicalNode fragmentAsLogical, + @Cached("create()") AsLogicalNode warningCallsAsLogical, + @Cached("create()") AsLogicalNode warnDupsAsLogical) { + int con = conAsInteger.execute(conObj); + int warningCalls = warningCallsAsLogical.execute(warningCallsObj); + if (RRuntime.isNA(warningCalls)) { + throw RError.error(this, RError.Message.INVALID_VALUE, "warningCalls"); } + int fragment = fragmentAsLogical.execute(fragmentObj); + int warndups = warnDupsAsLogical.execute(warndupsObj); + // fromIndex checks validity of con and throws error if not try (RConnection openConn = RConnection.fromIndex(con).forceOpen("r")) { // @formatter:off return toolsRFFINode.parseRd(openConn, srcfile, - RDataFactory.createLogicalVectorFromScalar(verboseL), - RDataFactory.createLogicalVectorFromScalar(fragmentL), - RDataFactory.createStringVectorFromScalar(basename.getDataAt(0)), - RDataFactory.createLogicalVectorFromScalar(warningCallsL), + verbose.materialize(), + RDataFactory.createLogicalVectorFromScalar((byte) fragment), + basename.materialize(), + RDataFactory.createLogicalVectorFromScalar((byte) warningCalls), macros, - RDataFactory.createLogicalVectorFromScalar(warndupsL)); + RDataFactory.createLogicalVectorFromScalar((byte) warndups)); // @formatter:on - } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); } catch (Throwable ex) { throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java index 27352dc09f5c1f2a2a62d58fcb06cf47e929e416..bbce4bf49e0fc2c3d86a9cc6fc882f2d635a9e4e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java @@ -33,6 +33,7 @@ import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments.S3Args; +import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java index 3868c0d29e32c66fe4bde0466ef4e360db3c9fab..c2c0162bfa59e6808708b553ebe5f158927d7ea8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java @@ -54,7 +54,7 @@ public abstract class RExplicitCallNode extends Node { @Specialization Object doCall(VirtualFrame frame, RFunction function, RArgsValuesAndNames args, - @Cached("createArgsIdentifier()") Object argsIdentifier, + @SuppressWarnings("unused") @Cached("createArgsIdentifier()") Object argsIdentifier, @Cached("createExplicitCall(argsIdentifier)") RCallBaseNode call, @Cached("createFrameSlotNode(argsIdentifier)") FrameSlotNode argumentsSlot) { FrameSlot argsFrameSlot = argumentsSlot.executeFrameSlot(frame);