Skip to content

Commit

Permalink
Merge branch 'nom' into newio
Browse files Browse the repository at this point in the history
  • Loading branch information
lizmat committed Jan 11, 2015
2 parents 7749d90 + 09c5420 commit 5c5a060
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 25 deletions.
8 changes: 7 additions & 1 deletion src/Perl6/Optimizer.nqp
Expand Up @@ -1509,8 +1509,14 @@ class Perl6::Optimizer {
# stuff like Nil is also stored in a QAST::Var, but
# we certainly don't want to warn about that one.
my str $sigil := nqp::substr($var.name, 0, 1);
my str $name := nqp::substr($var.name, 1);
if $sigil eq '$' || $sigil eq '@' || $sigil eq '%' {
$!problems.add_worry($var, "Useless use of variable " ~ $var.name ~ " in sink context");
$!problems.add_worry(
$var,
$name eq ''
?? "Useless use of unnamed $sigil variable in sink context"
!! "Useless use of variable $sigil$name in sink context"
);
return $NULL;
}
}
Expand Down
148 changes: 133 additions & 15 deletions src/vm/jvm/runtime/org/perl6/rakudo/RakudoJavaInterop.java
Expand Up @@ -83,11 +83,37 @@ else if( Ops.isint((SixModelObject) inArgs[i], tc) == 1 ) {
outArgs[i - offset] = Ops.unbox_i((SixModelObject) inArgs[i], tc);
}
else {
try {
outArgs[i - offset] = RuntimeSupport.unboxJava(Ops.decont((SixModelObject) inArgs[i], tc));
} catch (Exception e) {
throw ExceptionHandling.dieInternal(tc,
"Couldn't parse arguments in Java call. (Did you pass a type object?)");
if( Ops.islist( (SixModelObject) inArgs[i], tc ) == 1 ) {
outArgs[i - offset] = null;
// XXX: obviously breaks for arrays with elems > Integer.MAX_VALUE
int elems = (int) Ops.elems((SixModelObject) inArgs[i], tc);
SixModelObject argsContent = (SixModelObject) inArgs[i];
for( int j = 0; j < elems; ++j ) {
argsContent.at_pos_native(tc, j);
if( tc.native_type == ThreadContext.NATIVE_NUM ) {
if( outArgs[i - offset] == null )
outArgs[i - offset] = new double[elems];
((double[])outArgs[i - offset])[j] = tc.native_n;
}
else if( tc.native_type == ThreadContext.NATIVE_STR ) {
if( outArgs[i - offset] == null )
outArgs[i - offset] = new String[elems];
((String[])outArgs[i - offset])[j] = tc.native_s;
}
else if( tc.native_type == ThreadContext.NATIVE_INT ) {
if( outArgs[i - offset] == null )
outArgs[i - offset] = new long[elems];
((long[])outArgs[i - offset])[j] = tc.native_i;
}
}
}
else {
try {
outArgs[i - offset] = RuntimeSupport.unboxJava(Ops.decont((SixModelObject) inArgs[i], tc));
} catch (Exception e) {
throw ExceptionHandling.dieInternal(tc,
"Couldn't parse arguments in Java call. (Did you pass a type object?)");
}
}
}
}
Expand Down Expand Up @@ -119,7 +145,7 @@ int findHandle(Object[] parsedArgs, ThreadContext tc) throws Throwable {
INNER: for( int j = 0; j < parsedArgs.length; ++j ) {
switch (argTypes[j].getSort()) {
case Type.BOOLEAN:
if( parsedArgs[j].getClass().equals(long.class) ) {
if( parsedArgs[j].getClass().equals(Long.class) ) {
parsedArgs[j] = parsedArgs[j] != null ? ((Long) parsedArgs[j]) == 0 ? false : true : null;
continue INNER;
}
Expand All @@ -128,25 +154,25 @@ else if( parsedArgs[j].getClass().equals(boolean.class) ) {
}
break;
case Type.BYTE:
if( parsedArgs[j].getClass().equals(long.class) ) {
if( parsedArgs[j].getClass().equals(Long.class) ) {
parsedArgs[j] = parsedArgs[j] != null ? ((Long)parsedArgs[j]).byteValue() : null;
continue INNER;
}
break;
case Type.SHORT:
if( parsedArgs[j].getClass().equals(long.class) ) {
if( parsedArgs[j].getClass().equals(Long.class) ) {
parsedArgs[j] = parsedArgs[j] != null ? ((Long)parsedArgs[j]).shortValue() : null;
continue INNER;
}
break;
case Type.INT:
if( parsedArgs[j].getClass().equals(long.class) ) {
if( parsedArgs[j].getClass().equals(Long.class) ) {
parsedArgs[j] = parsedArgs[j] != null ? ((Long)parsedArgs[j]).intValue() : null;
continue INNER;
}
break;
case Type.LONG:
if( parsedArgs[j].getClass().equals(long.class) ) {
if( parsedArgs[j].getClass().equals(Long.class) ) {
continue INNER;
}
break;
Expand Down Expand Up @@ -174,8 +200,91 @@ else if( parsedArgs[j].getClass().equals(boolean.class) ) {
continue INNER;
}
break;
case Type.ARRAY:
// check that we actually have an array as argument
if( parsedArgs[j].getClass().getComponentType() != null ) {
// and then check types again
switch( argTypes[j].getElementType().getSort() ) {
case Type.BOOLEAN:
if( parsedArgs[j].getClass().getComponentType().equals(long.class) ) {
boolean[] converted = new boolean[((Object[])parsedArgs[j]).length];
for( int k = 0; k < ((long[])parsedArgs[j]).length; ++k )
converted[k] = ((Long) ((long[])parsedArgs[j])[k]) == 0 ? false : true;
parsedArgs[j] = converted;
continue INNER;
}
break;
case Type.BYTE:
if( parsedArgs[j].getClass().getComponentType().equals(long.class) ) {
byte[] converted = new byte[((long[])parsedArgs[j]).length];
for( int k = 0; k < ((long[])parsedArgs[j]).length; ++k )
converted[k] = ((Long)((long[])parsedArgs[j])[k]).byteValue();
parsedArgs[j] = converted;
continue INNER;
}
break;
case Type.SHORT:
if( parsedArgs[j].getClass().getComponentType().equals(long.class) ) {
short[] converted = new short[((long[])parsedArgs[j]).length];
for( int k = 0; k < ((long[])parsedArgs[j]).length; ++k )
converted[k] = ((Long)((long[])parsedArgs[j])[k]).shortValue();
parsedArgs[j] = converted;
continue INNER;
}
break;
case Type.INT:
if( parsedArgs[j].getClass().getComponentType().equals(long.class) ) {
int[] converted = new int[((long[])parsedArgs[j]).length];
for( int k = 0; k < ((long[])parsedArgs[j]).length; ++k )
converted[k] = ((Long)((long[])parsedArgs[j])[k]).intValue();
parsedArgs[j] = converted;
continue INNER;
}
break;
case Type.LONG:
if( parsedArgs[j].getClass().getComponentType().equals(long.class) ) {
continue INNER;
}
break;
case Type.CHAR:
if( parsedArgs[j].getClass().getComponentType().equals(String.class) ) {
continue INNER;
}
break;
case Type.FLOAT:
if( parsedArgs[j].getClass().getComponentType().equals(double.class) ) {
float[] converted = new float[((double[])parsedArgs[j]).length];
for( int k = 0; k < ((double[])parsedArgs[j]).length; ++k )
converted[k] = ((Double)((double[])parsedArgs[j])[k]).floatValue();
parsedArgs[j] = converted;
continue INNER;
}
break;
case Type.DOUBLE:
if( parsedArgs[j].getClass().getComponentType().equals(double.class) ) {
continue INNER;
}
break;
case Type.OBJECT:
Class<?> innerArgType = Class.forName(argTypes[j].getElementType()
.getInternalName().replace('/', '.'), false, tc.gc.byteClassLoader);
if( innerArgType.isAssignableFrom(parsedArgs[j].getClass()) ) {
// not sure how unboxing of Object[] is gonna work...
continue INNER;
}
break;
}
}

default:
/* debug
System.out.print("skipping handle with ");
for(Type type : argTypes)
System.out.print(type.toString() + ", ");
System.out.println();
*/
// if we didn't continue INNER we failed to match types

}
continue OUTER;
}
Expand All @@ -185,14 +294,14 @@ else if( parsedArgs[j].getClass().equals(boolean.class) ) {
if( handlePos == -1 ) {
String types = "void";
boolean first = true;
if( argTypes != null ) {
for( Type type : argTypes ) {
if( parsedArgs != null ) {
for( Object arg : parsedArgs ) {
if( first ) {
types = type.toString();
types = arg.getClass().toString();
first = false;
}
else {
types += ", " + type;
types += ", " + arg.getClass().toString();
}
}
}
Expand All @@ -209,6 +318,12 @@ Object fallback(Object intc, Object incf, Object incsd, Object[] args) throws Th
CallFrame cf = (CallFrame) incf;
CallSiteDescriptor csd = (CallSiteDescriptor) incsd;
Object[] parsedArgs = parseArgs(args, tc);

/* debug
for(int i = 0; i < parsedArgs.length; ++i ) {
System.out.println("parsed arg " + i + " as " + parsedArgs[i].getClass());
}
*/

if(forCtors) {
this.handleList = Class.forName(Type.getObjectType(((String) declaringClass).replace('/', '.')).getInternalName(),
Expand Down Expand Up @@ -512,7 +627,8 @@ protected ClassContext createAdaptor(Class<?> target) {
// &new()-equivalent, which dispatches among the generated
// adaptorConstructors - which aren't really constructors but static
// methods
createConstructorDispatchAdaptor(cc, target.getConstructors());
if( target.getConstructors().length > 0 )
createConstructorDispatchAdaptor(cc, target.getConstructors());
createAdaptorSpecials(cc);
compunitMethods(cc);

Expand Down Expand Up @@ -600,3 +716,5 @@ protected SixModelObject computeInterop(ThreadContext tc, Class<?> klass) {
}

}


45 changes: 36 additions & 9 deletions t/03-jvm/01-interop.t
Expand Up @@ -8,19 +8,46 @@ use Test;
ok 1, "alive after 'use java::lang::String:from<java>' (not deprecated yet)";
}

use java::lang::String:from<Java>;
{
use java::lang::String:from<Java>;

ok 1, "alive after 'use java::lang::String:from<Java>'";

is String."method/valueOf/(Z)Ljava/lang/String;"(True), "true",
"calling explicit static methods works";

ok 1, "alive after 'use java::lang::String:from<Java>'";
is String.valueOf(True), "true", "calling multi static methods works";

is String."method/valueOf/(Z)Ljava/lang/String;"(True), "true",
"calling explicit static methods works";
my $jstr = String."constructor/new/(Ljava/lang/String;)V"("foo");
is $jstr, "foo", "instantiation with explicit constructors works";

is String.valueOf(True), "true", "calling multi static methods works";
$jstr = String.new("bar");
is $jstr, "bar", "multi constructor works";
}

my $jstr = String."constructor/new/(Ljava/lang/String;)V"("foo");
is $jstr, "foo", "instantiation with explicit constructors works";
{
use java::util::zip::CRC32:from<Java>;
# check two of the .update candidates for CRC32
{
my $crc32 = CRC32.new;
for 'Hello, Java'.encode('utf-8').list {
# utf8 elems aren't int-y and not marshalled smart enough (yet?) either
# to clarify, the coercion should probably be not neccessary
# and should be considered a bug
$crc32.update($_.Int);
}
is $crc32.getValue, 1072431491, "(I)V candidate for CRC32 is recognized correctly";
}

{
my $crc32 = CRC32.new;
for 'Hello, Java'.encode('utf-8') {
# because utf8 lists automatically know they're something int-y
$crc32.update($_);
}
is $crc32.getValue, 1072431491, "([B)V candidate for CRC32 is recognized correctly";
}
}

$jstr = String.new("bar");
is $jstr, "bar", "multi constructor works";

done;

0 comments on commit 5c5a060

Please sign in to comment.