diff --git a/src/runtime/java/jpgf.c b/src/runtime/java/jpgf.c index 9a3c528ec..bca7a64e0 100644 --- a/src/runtime/java/jpgf.c +++ b/src/runtime/java/jpgf.c @@ -1334,6 +1334,42 @@ Java_org_grammaticalframework_pgf_Expr_initApp__Ljava_lang_String_2_3Lorg_gramma return expr; } +JNIEXPORT jobject JNICALL +Java_org_grammaticalframework_pgf_Expr_unApply(JNIEnv* env, jobject self) +{ + jclass expr_class = (*env)->FindClass(env, "org/grammaticalframework/pgf/Expr"); + if (!expr_class) + return NULL; + jmethodID expr_constrId = (*env)->GetMethodID(env, expr_class, "", "(Lorg/grammaticalframework/pgf/Pool;Ljava/lang/Object;J)V"); + jclass app_class = (*env)->FindClass(env, "org/grammaticalframework/pgf/ExprApplication"); + if (!app_class) + return NULL; + jmethodID app_constrId = (*env)->GetMethodID(env, app_class, "", "(Ljava/lang/String;[Lorg/grammaticalframework/pgf/Expr;)V"); + if (!app_constrId) + return NULL; + + PgfExpr expr = gu_variant_from_ptr(get_ref(env, self)); + + GuPool* tmp_pool = gu_local_pool(); + PgfApplication* app = pgf_expr_unapply(expr, tmp_pool); + + jobject japp = NULL; + if (app != NULL) { + jstring jfun = gu2j_string(env, app->fun); + jobject jargs = (*env)->NewObjectArray(env, app->n_args, expr_class, NULL); + for (size_t i = 0; i < app->n_args; i++) { + jobject jarg = (*env)->NewObject(env, expr_class, expr_constrId, NULL, self, p2l(app->args[i])); + (*env)->SetObjectArrayElement(env, jargs, i, jarg); + (*env)->DeleteLocalRef(env, jarg); + } + japp = (*env)->NewObject(env, app_class, app_constrId, jfun, jargs); + } + + gu_pool_free(tmp_pool); + + return japp; +} + JNIEXPORT jboolean JNICALL Java_org_grammaticalframework_pgf_Expr_equals(JNIEnv* env, jobject self, jobject other) { @@ -1368,7 +1404,7 @@ Java_org_grammaticalframework_pgf_Type_getHypos(JNIEnv* env, jobject self) jmethodID constrId = (*env)->GetMethodID(env, hypo_class, "", "(Ljava/lang/Object;J)V"); size_t n_hypos = gu_seq_length(tp->hypos); - jobjectArray jhypos = (*env)->NewObjectArray(env, n_hypos, hypo_class, NULL); + jobjectArray jhypos = (*env)->NewObjectArray(env, n_hypos, hypo_class, NULL); for (size_t i = 0; i < n_hypos; i++) { PgfHypo *hypo = gu_seq_index(tp->hypos, PgfHypo, i); jobject jhypo = (*env)->NewObject(env, hypo_class, constrId, self, p2l(hypo)); diff --git a/src/runtime/java/org/grammaticalframework/pgf/Expr.java b/src/runtime/java/org/grammaticalframework/pgf/Expr.java index 2c6882203..cdc62d1d1 100644 --- a/src/runtime/java/org/grammaticalframework/pgf/Expr.java +++ b/src/runtime/java/org/grammaticalframework/pgf/Expr.java @@ -83,6 +83,12 @@ public class Expr implements Serializable { return new Expr(pool, master, initApp(fun, args, pool.ref)); } + /** If the method is called on an expression which is + * a function application, then it is decomposed into + * a function name and a list of arguments. If this is not + * an application then the result is null. */ + public native ExprApplication unApply(); + /** Returns the expression as a string in the GF syntax */ public String toString() { return showExpr(ref); diff --git a/src/runtime/java/org/grammaticalframework/pgf/ExprApplication.java b/src/runtime/java/org/grammaticalframework/pgf/ExprApplication.java new file mode 100644 index 000000000..d33269448 --- /dev/null +++ b/src/runtime/java/org/grammaticalframework/pgf/ExprApplication.java @@ -0,0 +1,19 @@ +package org.grammaticalframework.pgf; + +public class ExprApplication { + private String fun; + private Expr[] arguments; + + public ExprApplication(String fun, Expr[] arguments) { + this.fun = fun; + this.arguments = arguments; + } + + public String getFunction() { + return fun; + } + + public Expr[] getArguments() { + return arguments; + } +}