diff --git a/com.oracle.truffle.r.native/fficall/jni/src/misc.c b/com.oracle.truffle.r.native/fficall/jni/src/misc.c index d3f42926195ec8b0943db3aca9c8991ff7b4417b..eef818af3a05d8c85eb0ab839e9ca9eb80fa5ba8 100644 --- a/com.oracle.truffle.r.native/fficall/jni/src/misc.c +++ b/com.oracle.truffle.r.native/fficall/jni/src/misc.c @@ -35,7 +35,8 @@ void init_misc(JNIEnv *env) { } char *dgettext(const char *domainname, const char *msgid) { - unimplemented("dgettext"); + printf("dgettext: '%s'\n", msgid); + return (char*) msgid; } const char *R_CHAR(SEXP string) { @@ -85,10 +86,6 @@ int R_IsNaN(double x) { return (*env)->CallStaticBooleanMethod(env, RRuntimeClass, isNAorNaNMethodID, x); } -void REprintf(const char *x, ...) { - unimplemented("REprintf"); -} - R_len_t R_BadLongVector(SEXP x, const char *y, int z) { unimplemented("R_BadLongVector"); } diff --git a/com.oracle.truffle.r.native/fficall/jni/src/rf_functions.c b/com.oracle.truffle.r.native/fficall/jni/src/rf_functions.c index 8486b64ef766668cea1bfbe7b2eefa0aa1798a21..82d1e4f859c011c76045ba3e8a7cbca3de0cb162 100644 --- a/com.oracle.truffle.r.native/fficall/jni/src/rf_functions.c +++ b/com.oracle.truffle.r.native/fficall/jni/src/rf_functions.c @@ -35,6 +35,7 @@ static jmethodID Rf_allocateArrayMethodID; static jmethodID Rf_allocateMatrixMethodID; static jmethodID Rf_duplicateMethodID; static jmethodID Rf_consMethodID; +static jmethodID Rf_evalMethodID; static jmethodID Rf_defineVarMethodID; static jmethodID Rf_findVarMethodID; static jmethodID Rf_findVarInFrameMethodID; @@ -49,6 +50,10 @@ static jmethodID Rf_NewHashedEnvMethodID; static jmethodID Rf_rPsortMethodID; static jmethodID Rf_iPsortMethodID; static jmethodID RprintfMethodID; +static jmethodID R_FindNamespaceMethodID; +static jmethodID Rf_GetOption1MethodID; +static jmethodID Rf_gsetVarMethodID; +static jmethodID Rf_inheritsMethodID; void init_rf_functions(JNIEnv *env) { Rf_ScalarIntegerMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_ScalarInteger", "(I)Lcom/oracle/truffle/r/runtime/data/RIntVector;", 1); @@ -56,6 +61,7 @@ void init_rf_functions(JNIEnv *env) { Rf_ScalarStringMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_ScalarString", "(Ljava/lang/String;)Lcom/oracle/truffle/r/runtime/data/RStringVector;", 1); Rf_ScalarLogicalMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_ScalarLogical", "(I)Lcom/oracle/truffle/r/runtime/data/RLogicalVector;", 1); Rf_consMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_cons", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1); + Rf_evalMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_eval", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1); Rf_defineVarMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_defineVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 1); Rf_findVarMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_findVar", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1); Rf_findVarInFrameMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_findVarInFrame", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1); @@ -72,6 +78,10 @@ void init_rf_functions(JNIEnv *env) { Rf_duplicateMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_duplicate", "(Ljava/lang/Object;)Ljava/lang/Object;", 1); Rf_NewHashedEnvMethodID = checkGetMethodID(env, RDataFactoryClass, "createNewEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;Ljava/lang/String;ZI)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 1); RprintfMethodID = checkGetMethodID(env, CallRFFIHelperClass, "printf", "(Ljava/lang/String;)V", 1); + R_FindNamespaceMethodID = checkGetMethodID(env, CallRFFIHelperClass, "R_FindNamespace", "(Ljava/lang/Object;)Ljava/lang/Object;", 1); + Rf_GetOption1MethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_GetOption1", "(Ljava/lang/Object;)Ljava/lang/Object;", 1); + Rf_gsetVarMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_gsetVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 1); + Rf_inheritsMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_inherits", "(Ljava/lang/Object;Ljava/lang/String;)I", 1); // Rf_rPsortMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_rPsort", "(Lcom/oracle/truffle/r/runtime/data/RDoubleVector;II)", 1); // Rf_iPsortMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_iPsort", "(Lcom/oracle/truffle/r/runtime/data/RIntVector;II)", 1); } @@ -115,14 +125,14 @@ SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) { } SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) { - TRACE(TARG2d, t, len); + TRACE(TARG2d, t, dims); JNIEnv *thisenv = getEnv(); SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_allocateArrayMethodID, t, dims); return checkRef(thisenv, result); } SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) { - TRACE(TARG2d, t, len); + TRACE(TARG2d, mode, nrow, ncol); JNIEnv *thisenv = getEnv(); SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_allocateMatrixMethodID, mode, nrow, ncol); return checkRef(thisenv, result); @@ -145,8 +155,9 @@ void Rf_defineVar(SEXP symbol, SEXP value, SEXP rho) { } SEXP Rf_eval(SEXP expr, SEXP env) { - unimplemented("Rf_eval)"); - return NULL; + JNIEnv *thisenv = getEnv(); + SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_evalMethodID, expr, env); + return checkRef(thisenv, result); } SEXP Rf_findFun(SEXP symbol, SEXP rho) { @@ -196,8 +207,9 @@ SEXP Rf_duplicated(SEXP x, Rboolean y) { } Rboolean Rf_inherits(SEXP x, const char * klass) { - unimplemented("Rf_inherits)"); - return FALSE; + JNIEnv *thisenv = getEnv(); + jstring klazz = (*thisenv)->NewStringUTF(thisenv, klass); + return (*thisenv)->CallStaticIntMethod(thisenv, CallRFFIHelperClass, Rf_inheritsMethodID, x, klazz); } Rboolean Rf_isReal(SEXP x) { @@ -253,8 +265,9 @@ Rboolean Rf_isString(SEXP s) { } cetype_t Rf_getCharCE(SEXP x) { - unimplemented("Rf_getCharCE"); - return CE_NATIVE; + // unimplemented("Rf_getCharCE"); + // TODO: real implementation + return CE_NATIVE; } SEXP Rf_mkChar(const char *x) { @@ -383,6 +396,28 @@ void Rprintf(const char *format, ...) { (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, RprintfMethodID, string); } +/* + REprintf is used by the error handler do not add + anything unless you're sure it won't + cause problems +*/ +void REprintf(const char *format, ...) +{ + // TODO: determine correct target for this message + char buf[8192]; + va_list(ap); + va_start(ap,format); + Rvsnprintf(buf, BUFSIZE - 1, format, ap); + va_end(ap); + JNIEnv *thisenv = getEnv(); + jstring string = (*thisenv)->NewStringUTF(thisenv, buf); + (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, RprintfMethodID, string); +} + +void R_FlushConsole(void) { + // ignored +} + // Tools package support, not in public API SEXP R_NewHashedEnv(SEXP parent, SEXP size) { @@ -398,8 +433,11 @@ SEXP Rf_classgets(SEXP x, SEXP y) { } const char *Rf_translateChar(SEXP x) { - unimplemented("Rf_translateChar"); - return NULL; +// unimplemented("Rf_translateChar"); + // TODO: proper implementation + const char *result = CHAR(x); +// printf("translateChar: '%s'\n", result); + return result; } const char *Rf_translateChar0(SEXP x) { @@ -419,6 +457,76 @@ const char *Rf_type2char(SEXPTYPE x) { SEXP Rf_type2str(SEXPTYPE x) { unimplemented("Rf_type2str"); + return R_NilValue; return NULL; } +SEXP R_FindNamespace(SEXP info) { + JNIEnv *thisenv = getEnv(); + SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, R_FindNamespaceMethodID, info); + return checkRef(thisenv, result); +} + + +SEXP GetOption1(SEXP tag) +{ + JNIEnv *thisenv = getEnv(); + SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_GetOption1MethodID, tag); + return checkRef(thisenv, result); +} + +int GetOptionCutoff(void) +{ + int w; + w = asInteger(GetOption1(install("deparse.cutoff"))); + if (w == NA_INTEGER || w <= 0) { + warning(_("invalid 'deparse.cutoff', used 60")); + w = 60; + } + return w; +} + +#define R_MIN_WIDTH_OPT 10 +#define R_MAX_WIDTH_OPT 10000 +#define R_MIN_DIGITS_OPT 0 +#define R_MAX_DIGITS_OPT 22 + +int GetOptionWidth(void) +{ + int w; + w = asInteger(GetOption1(install("width"))); + if (w < R_MIN_WIDTH_OPT || w > R_MAX_WIDTH_OPT) { + warning(_("invalid printing width, used 80")); + return 80; + } + return w; +} + +int GetOptionDigits(void) +{ + int d; + d = asInteger(GetOption1(install("digits"))); + if (d < R_MIN_DIGITS_OPT || d > R_MAX_DIGITS_OPT) { + warning(_("invalid printing digits, used 7")); + return 7; + } + return d; +} + +Rboolean Rf_GetOptionDeviceAsk(void) +{ + int ask; + ask = asLogical(GetOption1(install("device.ask.default"))); + if(ask == NA_LOGICAL) { + warning(_("invalid value for \"device.ask.default\", using FALSE")); + return FALSE; + } + return ask != 0; +} + +void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho) +{ + JNIEnv *thisenv = getEnv(); + (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_gsetVarMethodID, symbol, value, rho); +} + diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java index 2501963a3b2484b277b578a9cc010ba2535f7ba8..47e65caf321b08684f51762da09722e253a34a2c 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java @@ -215,6 +215,37 @@ public class CallRFFIHelper { } } + private static RStringVector getClassHr(Object v) { + if (v instanceof RAttributable) { + return ((RAttributable) v).getClassHierarchy(); + } else if (v instanceof Byte) { + return RLogicalVector.implicitClassHeader; + } else if (v instanceof String) { + return RStringVector.implicitClassHeader; + } else if (v instanceof Integer) { + return RIntVector.implicitClassHeader; + } else if (v instanceof Double) { + return RDoubleVector.implicitClassHeader; + } else if (v instanceof RComplex) { + return RComplexVector.implicitClassHeader; + } else if (v instanceof RRaw) { + return RRawVector.implicitClassHeader; + } else { + guaranteeInstanceOf(v, RNull.class); + return RNull.implicitClassHeader; + } + } + + static int Rf_inherits(Object x, String clazz) { + RStringVector hierarchy = getClassHr(x); + for (int i = 0; i < hierarchy.getLength(); i++) { + if (hierarchy.getDataAt(i).equals(clazz)) { + return 1; + } + } + return 0; + } + static int Rf_isString(Object x) { return RRuntime.asString(x) == null ? 0 : 1; } @@ -433,23 +464,18 @@ public class CallRFFIHelper { static Object TAG(Object e) { guaranteeInstanceOf(e, RPairList.class); -// System.out.println("TAG: " + e); return ((RPairList) e).getTag(); } static Object CAR(Object e) { guaranteeInstanceOf(e, RPairList.class); -// System.out.print("CAR: " + e); Object car = ((RPairList) e).car(); -// System.out.println(" = " + car); return car; } static Object CDR(Object e) { guaranteeInstanceOf(e, RPairList.class); -// System.out.print("CDR: " + e); Object cdr = ((RPairList) e).cdr(); -// System.out.println(" = " + cdr); return cdr; } @@ -464,11 +490,46 @@ public class CallRFFIHelper { } static Object SETCDR(Object x, Object y) { - if (x instanceof RPairList) { - ((RPairList) x).setCdr(y); - return x; // TODO check or y? + guaranteeInstanceOf(x, RPairList.class); + ((RPairList) x).setCdr(y); + return x; // TODO check or y? + } + + static Object R_FindNamespace(Object name) { + Object result = RContext.getInstance().stateREnvironment.getNamespaceRegistry().get(RRuntime.asString(name)); + return result; + } + + static Object Rf_eval(Object expr, Object env) { + guarantee(env instanceof REnvironment); + Object result; + if (expr instanceof RPromise) { + result = RContext.getRRuntimeASTAccess().forcePromise(expr); + } else if (expr instanceof RExpression) { + result = RContext.getEngine().eval((RExpression) expr, (REnvironment) env, 0); + } else if (expr instanceof RLanguage) { + result = RContext.getEngine().eval((RLanguage) expr, (REnvironment) env, 0); } else { - throw RInternalError.unimplemented(); + // just return value + result = expr; + } + return result; + } + + static Object Rf_GetOption1(Object tag) { + guarantee(tag instanceof RSymbol); + Object result = RContext.getInstance().stateROptions.getValue(((RSymbol) tag).getName()); + return result; + } + + static void Rf_gsetVar(Object symbol, Object value, Object rho) { + guarantee(symbol instanceof RSymbol); + REnvironment baseEnv = RContext.getInstance().stateREnvironment.getBaseEnv(); + guarantee(rho == baseEnv); + try { + baseEnv.put(((RSymbol) symbol).getName(), value); + } catch (PutException e) { + e.printStackTrace(); } }