From 653bb73ce350640c7dd5bc4c92e244e957c65483 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 22 Jun 2016 16:22:10 -0700
Subject: [PATCH] implement R_ParseVector

---
 .../fficall/src/jni/Parse.c                   | 20 +++++++++--
 .../fficall/src/jni/rfficall.c                |  1 +
 .../fficall/src/jni/rffiutils.h               |  1 +
 .../r/runtime/ffi/jnr/CallRFFIHelper.java     | 36 +++++++++++++++++++
 4 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
index 387a7b43cb..c1b33f9e43 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
@@ -23,6 +23,22 @@
 #include <rffiutils.h>
 #include <R_ext/Parse.h>
 
-SEXP R_ParseVector(SEXP x, int y, ParseStatus *z, SEXP w) {
-	return unimplemented("R_ParseVector");
+static jmethodID parseMethodID;
+static jclass parseResultClass;
+static jfieldID parseStatusFieldID;
+static jfieldID parseExprFieldID;
+
+
+void init_parse(JNIEnv *env) {
+	parseMethodID = checkGetMethodID(env, CallRFFIHelperClass, "R_ParseVector", "(Ljava/lang/Object;ILjava/lang/Object;)Ljava/lang/Object;", 1);
+	parseResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper$ParseResult");
+	parseStatusFieldID = checkGetFieldID(env, parseResultClass, "parseStatus", "I", 0);
+	parseExprFieldID = checkGetFieldID(env, parseResultClass, "expr", "Ljava/lang/Object;", 0);
+}
+
+SEXP R_ParseVector(SEXP text, int n, ParseStatus *z, SEXP srcfile) {
+	JNIEnv *env = getEnv();
+	jobject result = (*env)->CallStaticObjectMethod(env, CallRFFIHelperClass, parseMethodID, text, n, srcfile);
+	*z = (*env)->GetObjectField(env, result, parseStatusFieldID);
+    return (*env)->GetObjectField(env, result, parseExprFieldID);
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c b/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c
index 8a20c51ac7..a8d153d4a0 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c
@@ -34,6 +34,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_initialize(JNIEnv *env,
 	init_internals(env);
 	init_rmath(env);
 	init_random(env);
+	init_parse(env);
 }
 
 JNIEXPORT void JNICALL
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
index ee28f6641b..ee157855cd 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -74,6 +74,7 @@ void init_dynload(JNIEnv *env);
 void init_internals(JNIEnv *env);
 void init_random(JNIEnv *env);
 void init_utils(JNIEnv *env);
+void init_parse(JNIEnv *env);
 
 void setTempDir(JNIEnv *, jstring tempDir);
 
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 6e75748198..e5e02b266d 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
@@ -876,6 +876,42 @@ public class CallRFFIHelper {
         return result;
     }
 
+    private enum ParseStatus {
+        PARSE_NULL,
+        PARSE_OK,
+        PARSE_INCOMPLETE,
+        PARSE_ERROR,
+        PARSE_EOF
+    }
+
+    private static class ParseResult {
+        @SuppressWarnings("unused") private final int parseStatus;
+        @SuppressWarnings("unused") private final Object expr;
+
+        private ParseResult(int parseStatus, Object expr) {
+            this.parseStatus = parseStatus;
+            this.expr = expr;
+        }
+    }
+
+    public static Object R_ParseVector(Object text, int n, Object srcFile) {
+        // TODO general case
+        assert n == 1;
+        assert srcFile == RNull.instance;
+        String textString = RRuntime.asString(text);
+        assert textString != null;
+
+        try {
+            Source source = Source.fromText(textString, "<R_ParseVector>");
+            RExpression exprs = RContext.getEngine().parse(null, source);
+            return new ParseResult(ParseStatus.PARSE_OK.ordinal(), exprs);
+        } catch (ParseException ex) {
+            // TODO incomplete
+            return new ParseResult(ParseStatus.PARSE_ERROR.ordinal(), RNull.instance);
+        }
+
+    }
+
     @SuppressWarnings("unused")
     private static String R_HomeDir() {
         RFFIUtils.traceUpCall("R_HomeDir");
-- 
GitLab