Skip to content

Commit

Permalink
Support marshalling of Positional to List<Object>
Browse files Browse the repository at this point in the history
...as well as add a test.

Typing generic lists as Positional.of() needs a cleaner way to
map types between Rakudo and Java than we have at the moment.
Suggestions welcome.
  • Loading branch information
peschwa committed Sep 24, 2016
1 parent 8aa0aa1 commit 539a7d1
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 16 deletions.
36 changes: 22 additions & 14 deletions src/vm/jvm/runtime/org/perl6/rakudo/RakudoJavaInterop.java
Expand Up @@ -15,6 +15,8 @@
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;

import org.perl6.rakudo.RakOps;
Expand Down Expand Up @@ -309,7 +311,7 @@ else if( argType.equals(String.class) && obj.getClass().equals(String.class) ){
}
break;
default:

throw new ArrayIndexOutOfBoundsException(1);
}

return retVal;
Expand Down Expand Up @@ -346,6 +348,8 @@ Object fallback(Object intc, Object incf, Object incsd, Object[] args) throws Th
CallSiteDescriptor csd = (CallSiteDescriptor) incsd;
Object[] parsedArgs = parseArgArray(args);

Ops.debugnoop((SixModelObject) args[0], (ThreadContext) intc);

/* debug
for(int i = 0; i < parsedArgs.length; ++i ) {
System.out.println("parsed arg " + i + " as " + parsedArgs[i].getClass());
Expand Down Expand Up @@ -433,7 +437,6 @@ public static Object marshalOutRecursive(SixModelObject in, ThreadContext tc, Cl
}
else if(Ops.istype(in, gcx.List, tc) == 1) {
SixModelObject reified = Ops.decont(in, tc);
boolean arrayish = true;
SixModelObject methElems = Ops.findmethod(reified, "elems", tc);
Ops.invokeDirect(tc, methElems, Ops.invocantCallSite, new Object[] { reified });
try {
Expand All @@ -442,18 +445,16 @@ else if(Ops.istype(in, gcx.List, tc) == 1) {
catch(Throwable t) {
ExceptionHandling.dieInternal(tc, "Cannot marshal a lazy list to Java");
}
// XXX: there *might* be a smarter way to do this
// where "this" means "figure out if we have a Positional of containers or of values"

// TODO get half the work of parseSingleArg() abstracted out of there
// i.e. the type mapping between Java and Rakudo, so we
// can actually do something with the "of" and thus
// can dispatch to e.g. int[] instead of just Object[]
SixModelObject methOf = Ops.findmethod(reified, "of", tc);
Ops.invokeDirect(tc, methOf, Ops.invocantCallSite, new Object[] { reified });
SixModelObject ofType = Ops.result_o(tc.curFrame);
SixModelObject methAtPos = Ops.findmethod(reified, "AT-POS", tc);
for(int i = 0; i < size; i++) {
Ops.invokeDirect(tc, methAtPos,
new CallSiteDescriptor(new byte[] { CallSiteDescriptor.ARG_OBJ, CallSiteDescriptor.ARG_OBJ }, null),
new Object[] { reified, Ops.box_i((long)i, gcx.Int, tc) });
if(Ops.iscont(Ops.result_o(tc.curFrame)) == 0) {
arrayish = false;
break;
}
}

for(int i = 0; i < size; i++) {
Ops.invokeDirect(tc, methAtPos,
new CallSiteDescriptor(new byte[] { CallSiteDescriptor.ARG_OBJ, CallSiteDescriptor.ARG_OBJ }, null),
Expand All @@ -474,7 +475,12 @@ else if(Ops.istype((SixModelObject) cur, gcx.List, tc) == 1) {
}
Array.set(out, i, value);
}
if (List.class.isAssignableFrom(what)) {
out = Arrays.asList((Object[]) out);
}
}
// TODO associative types, which could for starters default to Map<Object> similar
// to how Positionals currently do, but we will want "of" checking there too
return out;
}

Expand Down Expand Up @@ -538,13 +544,15 @@ else if( Ops.isfalse((SixModelObject) inArg, tc) == 1 ) {
protected void marshalOut(MethodContext c, Class<?> what, int ix) {
MethodVisitor mv = c.mv;

if(what.getComponentType() != null) {
if(what.getComponentType() != null
|| List.class.isAssignableFrom(what)) {
emitGetFromNQP(c, ix, storageForType(what));
mv.visitVarInsn(Opcodes.ALOAD, c.tcLoc);
mv.visitLdcInsn(Type.getType(what));
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/perl6/rakudo/RakudoJavaInterop", "marshalOutRecursive",
Type.getMethodDescriptor(Type.getType(Object.class), TYPE_SMO, TYPE_TC, Type.getType(Class.class)));
}

else {
super.marshalOut(c, what, ix);
}
Expand Down
4 changes: 3 additions & 1 deletion t/03-jvm/01-interop.t
@@ -1,7 +1,7 @@
use v6;
use Test;

plan 28;
plan 29;

{
use java::lang::String:from<JavaRuntime>;
Expand Down Expand Up @@ -159,6 +159,8 @@ plan 28;
is $out.out.lines, "baz womble", "(compiling and) loading a .class file via 'use lib' works";
$out = shell("$*EXECUTABLE -e'use lib q[java#t/03-jvm/]; use Foo:from<Java>; say Foo.trizzle([1, 2e0, <bar>])'", :out);
is $out.out.lines, "12.0bar", "passing arrays with mixed types to Object[] works";
$out = shell("$*EXECUTABLE -e'use lib q[java#t/03-jvm/]; use Foo:from<Java>; say Foo.suzzle([1, 2e0, <bar>])'", :out);
is $out.out.lines, "12.0bar", "passing arrays with mixed types to List<Object> works";
}
else {
skip 2;
Expand Down
9 changes: 8 additions & 1 deletion t/03-jvm/Foo.java
@@ -1,7 +1,14 @@
public class Foo {
public static String bar() { return "baz"; }
public String quux() { return "womble"; }
public static String trizzle(Object[] in) {
public static String trizzle(Object[] in) {
String out = "";
for(Object elem : in) {
out += elem;
}
return out;
}
public static String suzzle(java.util.List in) {
String out = "";
for(Object elem : in) {
out += elem;
Expand Down

0 comments on commit 539a7d1

Please sign in to comment.