diff --git a/src/runtime/java/jpgf.c b/src/runtime/java/jpgf.c index 7e0c9b39e..d91709082 100644 --- a/src/runtime/java/jpgf.c +++ b/src/runtime/java/jpgf.c @@ -1432,6 +1432,59 @@ Java_org_grammaticalframework_pgf_Expr_unStr(JNIEnv* env, jobject self) return NULL; } +JNIEXPORT void JNICALL +Java_org_grammaticalframework_pgf_Expr_visit(JNIEnv* env, jobject self, jobject visitor) +{ + PgfExpr e = gu_variant_from_ptr(l2p(get_ref(env, self))); + + GuPool* tmp_pool = gu_local_pool(); + + PgfApplication* app = pgf_expr_unapply(e, tmp_pool); + if (app != NULL) { + char* method_name = gu_malloc(tmp_pool, strlen(app->fun)+4); + strcpy(method_name, "on_"); + strcat(method_name, app->fun); + + GuExn* err = gu_exn(tmp_pool); + GuStringBuf* sbuf = gu_new_string_buf(tmp_pool); + GuOut* out = gu_string_buf_out(sbuf); + + gu_putc('(', out, err); + for (size_t i = 0; i < app->n_args; i++) { + gu_puts("Lorg/grammaticalframework/pgf/Expr;", out, err); + } + gu_puts(")V", out, err); + gu_putc('\0', out, err); + + char* sig = gu_string_buf_data(sbuf); + + jclass visitor_class = (*env)->GetObjectClass(env, visitor); + jmethodID methodID = (*env)->GetMethodID(env, visitor_class, method_name, sig); + + if (methodID != NULL) { + jclass expr_class = (*env)->FindClass(env, "org/grammaticalframework/pgf/Expr"); + jmethodID expr_constrId = (*env)->GetMethodID(env, expr_class, "", "(Lorg/grammaticalframework/pgf/Pool;Ljava/lang/Object;J)V"); + + jvalue* args = gu_malloc(tmp_pool, sizeof(jvalue)*app->n_args); + for (size_t i = 0; i < app->n_args; i++) { + args[i].l = (*env)->NewObject(env, expr_class, expr_constrId, NULL, self, p2l(app->args[i])); + } + (*env)->CallVoidMethodA(env, visitor, methodID, args); + } else { + (*env)->ExceptionClear(env); + + methodID = (*env)->GetMethodID(env, visitor_class, "defaultCase", "(Lorg/grammaticalframework/pgf/Expr;)V"); + if (methodID != NULL) { + (*env)->CallVoidMethod(env, visitor, methodID, self); + } else { + (*env)->ExceptionClear(env); + } + } + } + + gu_pool_free(tmp_pool); +} + JNIEXPORT jboolean JNICALL Java_org_grammaticalframework_pgf_Expr_equals(JNIEnv* env, jobject self, jobject other) { diff --git a/src/runtime/java/org/grammaticalframework/pgf/Expr.java b/src/runtime/java/org/grammaticalframework/pgf/Expr.java index 8462cb30f..40655cbcb 100644 --- a/src/runtime/java/org/grammaticalframework/pgf/Expr.java +++ b/src/runtime/java/org/grammaticalframework/pgf/Expr.java @@ -99,6 +99,10 @@ public class Expr implements Serializable { * If this is not a string literal then the result is null. */ public native String unStr(); + /** An implementation for the visitor pattern. The method uses + * reflection to find the relevant methods from the visitor object */ + public native void visit(Object visitor); + /** Returns the expression as a string in the GF syntax */ public String toString() { return showExpr(ref);