Add support for Array.set

This commit is contained in:
Alexey Andreev 2018-08-28 15:47:08 +03:00
parent 365e47882a
commit d20accc20c
3 changed files with 77 additions and 0 deletions

View File

@ -53,6 +53,9 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
case "getImpl": case "getImpl":
reachGet(agent, method); reachGet(agent, method);
break; break;
case "setImpl":
reachSet(agent, method);
break;
} }
} }
@ -68,6 +71,9 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
case "getImpl": case "getImpl":
generateGet(context, writer); generateGet(context, writer);
break; break;
case "setImpl":
generateSet(context, writer);
break;
} }
} }
@ -126,6 +132,31 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
writer.outdent().append("}").softNewLine(); writer.outdent().append("}").softNewLine();
} }
private void generateSet(GeneratorContext context, SourceWriter writer) throws IOException {
String array = context.getParameterName(1);
String item = context.getParameterName(3);
writer.append("var type = " + array + ".constructor.$meta.item;").softNewLine();
boolean first = true;
for (int i = 0; i < primitives.length; ++i) {
String wrapper = "java.lang." + primitiveWrappers[i];
MethodReference methodRef = new MethodReference(wrapper, primitives[i].toLowerCase() + "Value",
primitiveTypes[i]);
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
if (cls == null || cls.getMethod(methodRef.getDescriptor()) == null) {
continue;
}
if (!first) {
writer.append(" else ");
}
first = false;
writer.append("if (type === $rt_" + primitives[i].toLowerCase() + "cls()) {").indent().softNewLine();
writer.append(item + " = ").appendMethodBody(methodRef).append("(" + item + ");").softNewLine();
writer.outdent().append("}");
}
writer.softNewLine();
writer.append(array + ".data[" + context.getParameterName(2) + "] = " + item + ";").softNewLine();
}
private void reachGet(DependencyAgent agent, MethodDependency method) { private void reachGet(DependencyAgent agent, MethodDependency method) {
method.getVariable(1).getArrayItem().connect(method.getResult()); method.getVariable(1).getArrayItem().connect(method.getResult());
method.getVariable(1).addConsumer(type -> { method.getVariable(1).addConsumer(type -> {
@ -143,4 +174,21 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
} }
}); });
} }
private void reachSet(DependencyAgent agent, MethodDependency method) {
method.getVariable(3).connect(method.getVariable(1).getArrayItem());
method.getVariable(1).addConsumer(type -> {
if (type.getName().startsWith("[")) {
String typeName = type.getName().substring(1);
for (int i = 0; i < primitiveTypes.length; ++i) {
if (primitiveTypes[i].toString().equals(typeName)) {
String wrapper = "java.lang." + primitiveWrappers[i];
MethodReference methodRef = new MethodReference(wrapper,
primitives[i].toLowerCase() + "Value", primitiveTypes[i]);
agent.linkMethod(methodRef, null).use();
}
}
}
});
}
} }

View File

@ -79,7 +79,19 @@ public final class TArray extends TObject {
return getImpl(array, index); return getImpl(array, index);
} }
public static void set(TObject array, int index, TObject value) throws TIllegalArgumentException,
TArrayIndexOutOfBoundsException {
if (index < 0 || index >= getLength(array)) {
throw new TArrayIndexOutOfBoundsException();
}
setImpl(array, index, value);
}
@GeneratedBy(ArrayNativeGenerator.class) @GeneratedBy(ArrayNativeGenerator.class)
@PluggableDependency(ArrayNativeGenerator.class) @PluggableDependency(ArrayNativeGenerator.class)
private static native TObject getImpl(TObject array, int index); private static native TObject getImpl(TObject array, int index);
@GeneratedBy(ArrayNativeGenerator.class)
@PluggableDependency(ArrayNativeGenerator.class)
private static native void setImpl(TObject array, int index, TObject value);
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.classlib.java.lang.reflect; package org.teavm.classlib.java.lang.reflect;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import org.junit.Test; import org.junit.Test;
@ -36,4 +37,20 @@ public class ArrayTest {
assertEquals(int[].class, instance.getClass()); assertEquals(int[].class, instance.getClass());
assertEquals(15, Array.getLength(instance)); assertEquals(15, Array.getLength(instance));
} }
@Test
public void setWorks() {
Object array = Array.newInstance(String.class, 2);
Array.set(array, 0, "foo");
Array.set(array, 1, "bar");
assertArrayEquals(new String[] { "foo", "bar" }, (String[]) array);
}
@Test
public void setPrimitiveWorks() {
Object array = Array.newInstance(int.class, 2);
Array.set(array, 0, 23);
Array.set(array, 1, 42);
assertArrayEquals(new int[] { 23, 42 }, (int[]) array);
}
} }