jvm-has-method

This commit is contained in:
zeroflag 2021-06-27 16:47:24 +02:00
parent da0a365bcf
commit e93fd4d6bb
5 changed files with 36 additions and 0 deletions

View file

@ -350,6 +350,7 @@ public class Fcl {
addPrimitive(".", () -> show(stack.pop())); addPrimitive(".", () -> show(stack.pop()));
addPrimitive("jvm-call-static", interOp::jvmCallStatic); addPrimitive("jvm-call-static", interOp::jvmCallStatic);
addPrimitive("jvm-call-method", interOp::jvmCallMethod); addPrimitive("jvm-call-method", interOp::jvmCallMethod);
addPrimitive("jvm-has-method", interOp::jvmHasMethod);
addPrimitive("jvm-static-var", interOp::jvmStaticVar); addPrimitive("jvm-static-var", interOp::jvmStaticVar);
addPrimitive("jvm-null", () -> stack.push(null)); addPrimitive("jvm-null", () -> stack.push(null));
addPrimitive("asc*", this::sortAsc); addPrimitive("asc*", this::sortAsc);

View file

@ -2,6 +2,7 @@ package com.vectron.fcl.interop;
import com.vectron.fcl.FclStack; import com.vectron.fcl.FclStack;
import com.vectron.fcl.exceptions.InterOpFailed; import com.vectron.fcl.exceptions.InterOpFailed;
import com.vectron.fcl.types.Bool;
import com.vectron.fcl.types.JvmObj; import com.vectron.fcl.types.JvmObj;
import com.vectron.fcl.types.Obj; import com.vectron.fcl.types.Obj;
@ -31,6 +32,15 @@ public class JvmInterOp {
spec.invoke(stack); spec.invoke(stack);
} }
public void jvmHasMethod() {
String methodName = stack.pop().asStr().value();
Obj receiver = stack.pop();
MethodSpec spec = MethodSpec.parseDynamic(
methodName,
receiver instanceof JvmObj ? ((JvmObj) receiver).value() : receiver);
stack.push(spec.exists() ? Bool.TRUE : Bool.FALSE);
}
public void jvmStaticVar() { public void jvmStaticVar() {
String spec = stack.pop().asStr().value(); String spec = stack.pop().asStr().value();
String[] parts = spec.split("/"); String[] parts = spec.split("/");

View file

@ -71,6 +71,20 @@ class MethodSpec {
} }
} }
public boolean exists() {
List<Class<?>> types = new ArrayList<>();
for (int i = 0; i < arity; i++) {
Class<?> clazz = typeOf(typeSpec.charAt(i));
types.add(clazz);
}
try {
clazz.getMethod(methodName, types.toArray(new Class[0]));
return true;
} catch (ReflectiveOperationException e) {
return false;
}
}
public static void processResult(Object result, FclStack stack) { public static void processResult(Object result, FclStack stack) {
if (result != null) { if (result != null) {
if (result instanceof Number) if (result instanceof Number)

View file

@ -1,4 +1,7 @@
: hist ( c -- m ) : hist ( c -- m )
dup 'iterator' jvm-has-method not if
drop #[ ]# exit
then
<map> -> tbl { <map> -> tbl {
-> elem -> elem
tbl elem at -> count tbl elem at -> count

View file

@ -26,6 +26,7 @@ import static com.vectron.fcl.types.Bool.TRUE;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -391,6 +392,12 @@ public class FclTest {
assertEquals(1.5430, evalPop("1 cosh").doubleValue(), 0.001); assertEquals(1.5430, evalPop("1 cosh").doubleValue(), 0.001);
assertEquals(0.7616, evalPop("1 tanh").doubleValue(), 0.001); assertEquals(0.7616, evalPop("1 tanh").doubleValue(), 0.001);
assertEquals(1, evalPop("1.3 'intValue' jvm-call-method").doubleValue(), 0.01); assertEquals(1, evalPop("1.3 'intValue' jvm-call-method").doubleValue(), 0.01);
assertFalse(evalPop("1.3 'nosuch' jvm-has-method").boolValue());
assertTrue(evalPop("1.3 'round' jvm-has-method").boolValue());
assertTrue(evalPop("[ 1 2 ] 'iterator' jvm-has-method").boolValue());
assertTrue(evalPop("[ 1 2 ] 'append/O' jvm-has-method").boolValue());
assertFalse(evalPop("[ 1 2 ] 'append/i' jvm-has-method").boolValue());
assertFalse(evalPop("[ 1 2 ] 'append/OO' jvm-has-method").boolValue());
} }
@Test @Test
@ -1122,6 +1129,7 @@ public class FclTest {
public void testHist() { public void testHist() {
assertEquals("#[ 'a' 2 'b' 3 'c' 1 ]#", evalPop("'ababbc' hist").toString()); assertEquals("#[ 'a' 2 'b' 3 'c' 1 ]#", evalPop("'ababbc' hist").toString());
assertEquals("#[ ]#", evalPop("'' hist").toString()); assertEquals("#[ ]#", evalPop("'' hist").toString());
assertEquals("#[ ]#", evalPop("12 hist").toString());
} }
private String transcript() { private String transcript() {