mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Adds implementation of some JCL methods/classes
This commit is contained in:
parent
da314bf6f2
commit
688d6191fd
|
@ -89,6 +89,7 @@ public class JCLComparisonBuilder {
|
|||
copyResource("html/package_obj.png");
|
||||
copyResource("html/int_obj.png");
|
||||
copyResource("html/enum_obj.png");
|
||||
copyResource("html/annotation_obj.png");
|
||||
try (Writer out = new OutputStreamWriter(new FileOutputStream(new File(
|
||||
outputDirectory, "jcl.html")), "UTF-8")) {
|
||||
generateHtml(out, packages);
|
||||
|
|
|
@ -57,10 +57,10 @@ class JCLComparisonVisitor implements ClassVisitor {
|
|||
jclClass = new JCLClass(simpleName);
|
||||
jclClass.status = classReader != null ? JCLStatus.FOUND : JCLStatus.MISSING;
|
||||
jclClass.visibility = (access & Opcodes.ACC_PROTECTED) != 0 ? JCLVisibility.PROTECTED : JCLVisibility.PUBLIC;
|
||||
if ((access & Opcodes.ACC_INTERFACE) != 0) {
|
||||
jclClass.type = JCLClassType.INTERFACE;
|
||||
} else if ((access & Opcodes.ACC_ANNOTATION) != 0) {
|
||||
if ((access & Opcodes.ACC_ANNOTATION) != 0) {
|
||||
jclClass.type = JCLClassType.ANNOTATION;
|
||||
} else if ((access & Opcodes.ACC_INTERFACE) != 0) {
|
||||
jclClass.type = JCLClassType.INTERFACE;
|
||||
} else if ((access & Opcodes.ACC_ENUM) != 0) {
|
||||
jclClass.type = JCLClassType.ENUM;
|
||||
} else {
|
||||
|
|
|
@ -86,6 +86,12 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
case "charClass":
|
||||
context.getWriter().append("$rt_cls($rt_charcls())");
|
||||
break;
|
||||
case "byteClass":
|
||||
context.getWriter().append("$rt_cls($rt_bytecls())");
|
||||
break;
|
||||
case "doubleClass":
|
||||
context.getWriter().append("$rt_cls($rt_doublecls())");
|
||||
break;
|
||||
case "wrap":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
break;
|
||||
|
@ -176,6 +182,9 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
case "booleanClass":
|
||||
case "intClass":
|
||||
case "charClass":
|
||||
case "byteClass":
|
||||
case "voidClass":
|
||||
case "doubleClass":
|
||||
case "wrap":
|
||||
case "getSuperclass":
|
||||
case "getComponentType0":
|
||||
|
|
|
@ -19,13 +19,15 @@ import java.io.IOException;
|
|||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.javascript.ni.Injector;
|
||||
import org.teavm.javascript.ni.InjectorContext;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DoubleNativeGenerator implements Generator {
|
||||
public class DoubleNativeGenerator implements Generator, Injector {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
|
@ -38,6 +40,15 @@ public class DoubleNativeGenerator implements Generator {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "getNaN":
|
||||
context.getWriter().append("NaN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateIsNaN(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append("return (isNaN(").append(context.getParameterName(1)).append(")").ws().append("?")
|
||||
.ws().append("1").ws().append(":").ws().append("0").ws().append(");").softNewLine();
|
||||
|
|
|
@ -29,4 +29,8 @@ public class TArrayIndexOutOfBoundsException extends TIndexOutOfBoundsException
|
|||
public TArrayIndexOutOfBoundsException(TString message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TArrayIndexOutOfBoundsException(int index) {
|
||||
super(TInteger.toString(index));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,12 +22,20 @@ import org.teavm.javascript.ni.Rename;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
public class TByte extends TNumber implements TComparable<TByte> {
|
||||
public static final byte MIN_VALUE = -128;
|
||||
public static final byte MAX_VALUE = 127;
|
||||
public static final TClass<TByte> TYPE = TClass.byteClass();
|
||||
public static final int SIZE = 8;
|
||||
private byte value;
|
||||
|
||||
public TByte(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public TByte(TString value) {
|
||||
this.value = parseByte(value, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return value;
|
||||
|
@ -54,6 +62,7 @@ public class TByte extends TNumber implements TComparable<TByte> {
|
|||
}
|
||||
|
||||
public static TByte valueOf(byte value) {
|
||||
// TODO: add caching
|
||||
return new TByte(value);
|
||||
}
|
||||
|
||||
|
@ -85,4 +94,32 @@ public class TByte extends TNumber implements TComparable<TByte> {
|
|||
public int compareTo(TByte other) {
|
||||
return compare(value, other.value);
|
||||
}
|
||||
|
||||
public static byte parseByte(TString s) throws TNumberFormatException {
|
||||
return parseByte(s, 10);
|
||||
}
|
||||
|
||||
public static byte parseByte(TString s, int radix) throws TNumberFormatException {
|
||||
int value = TInteger.parseInt(s, radix);
|
||||
if (value < MIN_VALUE || value >= MAX_VALUE) {
|
||||
throw new TNumberFormatException();
|
||||
}
|
||||
return (byte)value;
|
||||
}
|
||||
|
||||
public static TByte valueOf(TString s, int radix) throws TNumberFormatException {
|
||||
return valueOf(parseByte(s, radix));
|
||||
}
|
||||
|
||||
public static TByte valueOf(TString s) throws TNumberFormatException {
|
||||
return valueOf(parseByte(s));
|
||||
}
|
||||
|
||||
public static TByte decode(TString nm) throws TNumberFormatException {
|
||||
TInteger value = TInteger.decode(nm);
|
||||
if (value.intValue() < MIN_VALUE || value.intValue() >= MAX_VALUE) {
|
||||
throw new TNumberFormatException();
|
||||
}
|
||||
return TByte.valueOf((byte)value.intValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -558,6 +558,10 @@ public class TCharacter extends TObject implements TComparable<TCharacter> {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isUnicodeIdentifierPart(char ch) {
|
||||
return isUnicodeIdentifierPart((int)ch);
|
||||
}
|
||||
|
||||
public static boolean isUnicodeIdentifierPart(int codePoint) {
|
||||
switch (getType(codePoint)) {
|
||||
case UPPERCASE_LETTER:
|
||||
|
|
|
@ -85,6 +85,14 @@ public class TClass<T> extends TObject {
|
|||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TVoid> voidClass();
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TByte> byteClass();
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TDouble> doubleClass();
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
public static native <S extends TObject> TClass<S> wrap(Class<S> cls);
|
||||
|
|
|
@ -33,4 +33,8 @@ public class TClassNotFoundException extends TReflectiveOperationException {
|
|||
public TClassNotFoundException(TString message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TThrowable getException() {
|
||||
return getCause();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.javascript.ni.InjectedBy;
|
||||
import org.teavm.javascript.ni.Rename;
|
||||
|
||||
/**
|
||||
|
@ -23,14 +24,26 @@ import org.teavm.javascript.ni.Rename;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||
public static double POSITIVE_INFINITY = 1 / 0.0;
|
||||
public static double NEGATIVE_INFINITY = -POSITIVE_INFINITY;
|
||||
public static final double POSITIVE_INFINITY = 1 / 0.0;
|
||||
public static final double NEGATIVE_INFINITY = -POSITIVE_INFINITY;
|
||||
public static final double NaN = getNaN();
|
||||
public static final double MAX_VALUE = 0x1.FFFFFFFFFFFFFP+1023;
|
||||
public static final double MIN_NORMAL = -0x1.0P+1022;
|
||||
public static final double MIN_VALUE = 0x0.0000000000001P-1022;
|
||||
public static final int MAX_EXPONENT = 1023;
|
||||
public static final int MIN_EXPONENT = -1022;
|
||||
public static final int SIZE = 64;
|
||||
public static final TClass<TDouble> TYPE = TClass.doubleClass();
|
||||
private double value;
|
||||
|
||||
public TDouble(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public TDouble(TString value) throws TNumberFormatException {
|
||||
this.value = parseDouble(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double doubleValue() {
|
||||
return value;
|
||||
|
@ -199,9 +212,151 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
|||
return compare(value, other.value);
|
||||
}
|
||||
|
||||
public boolean isNaN() {
|
||||
return isNaN(value);
|
||||
}
|
||||
|
||||
public boolean isInfinite() {
|
||||
return isInfinite(value);
|
||||
}
|
||||
|
||||
@GeneratedBy(DoubleNativeGenerator.class)
|
||||
public static native boolean isNaN(double v);
|
||||
|
||||
@InjectedBy(DoubleNativeGenerator.class)
|
||||
private static native double getNaN();
|
||||
|
||||
@GeneratedBy(DoubleNativeGenerator.class)
|
||||
public static native boolean isInfinite(double v);
|
||||
|
||||
public static long doubleToRawLongBits(double value) {
|
||||
return doubleToLongBits(value);
|
||||
}
|
||||
|
||||
public static long doubleToLongBits(double value) {
|
||||
if (value == POSITIVE_INFINITY) {
|
||||
return 0x7FF0000000000000L;
|
||||
} else if (value == NEGATIVE_INFINITY) {
|
||||
return 0xFFF0000000000000L;
|
||||
} else if (isNaN(value)) {
|
||||
return 0x7FF8000000000000L;
|
||||
}
|
||||
double abs = TMath.abs(value);
|
||||
int exp = TMath.getExponent(abs);
|
||||
if (exp < -1022) {
|
||||
exp = -1023;
|
||||
}
|
||||
long mantissa = (long)(abs * binaryExponent(exp + 52)) & 0xFFFFFFFFFFFFFL;
|
||||
return mantissa | ((exp + 1023L) << 52) | (value < 0 ? (1L << 63) : 0);
|
||||
}
|
||||
|
||||
public static double longBitsToDouble(long bits) {
|
||||
if ((bits & 0x7FF0000000000000L) == 0x7FF0000000000000L) {
|
||||
if (bits == 0x7FF0000000000000L) {
|
||||
return POSITIVE_INFINITY;
|
||||
} else if (bits == 0xFFF0000000000000L) {
|
||||
return NEGATIVE_INFINITY;
|
||||
} else {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
boolean negative = (bits & (1 << 63)) != 0;
|
||||
int rawExp = (int)((bits >> 52) & 0x7FFL) - 1023;
|
||||
long mantissa = bits & 0xFFFFFFFFFFFFFL;
|
||||
if (rawExp == 0) {
|
||||
mantissa <<= 1;
|
||||
} else {
|
||||
mantissa |= (1L << 52);
|
||||
}
|
||||
double value = mantissa * binaryExponent(rawExp - 1023 - 52);
|
||||
return !negative ? value : -value;
|
||||
}
|
||||
|
||||
public static TString toHexString(double d) {
|
||||
if (isNaN(d)) {
|
||||
return TString.wrap("NaN");
|
||||
} else if (isInfinite(d)) {
|
||||
return d > 0 ? TString.wrap("Infinity") : TString.wrap("-Infinity");
|
||||
}
|
||||
char[] buffer = new char[30];
|
||||
int sz = 0;
|
||||
long bits = doubleToLongBits(d);
|
||||
long mantissa = bits & 0xFFFFFFFFFFFFFL;
|
||||
for (int i = 0; i < 13; ++i) {
|
||||
int digit = (int)(mantissa & 0xF);
|
||||
if (digit > 0 || sz > 0) {
|
||||
buffer[sz++] = TCharacter.forDigit(digit, 16);
|
||||
}
|
||||
mantissa >>>= 4;
|
||||
}
|
||||
if (sz == 0) {
|
||||
buffer[sz++] = '0';
|
||||
}
|
||||
buffer[sz++] = '.';
|
||||
int exp = (int)((bits >>> 52) & 0x7FF);
|
||||
if (exp == -1023) {
|
||||
buffer[sz++] = '0';
|
||||
++exp;
|
||||
} else {
|
||||
buffer[sz++] = '1';
|
||||
}
|
||||
buffer[sz++] = 'x';
|
||||
buffer[sz++] = '0';
|
||||
if ((bits & (1L << 63)) == 0) {
|
||||
buffer[sz++] = '-';
|
||||
}
|
||||
int half = sz / 2;
|
||||
for (int i = 0; i < half; ++i) {
|
||||
char tmp = buffer[i];
|
||||
buffer[i] = buffer[sz - i - 1];
|
||||
buffer[sz - i - 1] = tmp;
|
||||
}
|
||||
|
||||
buffer[sz++] = 'p';
|
||||
if (exp < 0) {
|
||||
exp = -exp;
|
||||
buffer[sz++] = '-';
|
||||
}
|
||||
int pos = 1000;
|
||||
boolean first = true;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int digit = exp / pos;
|
||||
if (digit > 0 || !first) {
|
||||
buffer[sz++] = TCharacter.forDigit(digit, 10);
|
||||
first = false;
|
||||
}
|
||||
digit *= 10;
|
||||
pos /= 10;
|
||||
}
|
||||
if (first) {
|
||||
buffer[sz++] = '0';
|
||||
}
|
||||
|
||||
return new TString(buffer, 0, sz);
|
||||
}
|
||||
|
||||
public static double binaryExponent(int n) {
|
||||
double result = 1;
|
||||
if (n >= 0) {
|
||||
double d = 2;
|
||||
while (n != 0) {
|
||||
if (n % 2 != 0) {
|
||||
result *= d;
|
||||
}
|
||||
n /= 2;
|
||||
d *= d;
|
||||
}
|
||||
} else {
|
||||
n = -n;
|
||||
double d = 0.5;
|
||||
while (n != 0) {
|
||||
if (n % 2 != 0) {
|
||||
result *= d;
|
||||
}
|
||||
n /= 2;
|
||||
d *= d;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,6 +224,11 @@ public final class TMath extends TObject {
|
|||
}
|
||||
} else if (d < 1) {
|
||||
int expBit = 1 << (negativeExponents.length - 1);
|
||||
int offset = 0;
|
||||
if (d < 0x1P-1024) {
|
||||
d *= 0x1P52;
|
||||
offset = 52;
|
||||
}
|
||||
for (int i = negativeExponents.length - 1; i >= 0; --i) {
|
||||
if (d < negativeExponents[i]) {
|
||||
d *= exponents[i];
|
||||
|
@ -231,7 +236,7 @@ public final class TMath extends TObject {
|
|||
}
|
||||
expBit >>>= 1;
|
||||
}
|
||||
exp = -exp;
|
||||
exp = -(exp + offset);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
@ -263,7 +268,9 @@ public final class TMath extends TObject {
|
|||
}
|
||||
|
||||
private static class ExponentConstants {
|
||||
public static double[] exponents = { 1E1, 1E2, 1E4, 1E8, 1E16, 1E32, 1E64, 1E128, 1E256 };
|
||||
public static double[] negativeExponents = { 1E-1, 1E-2, 1E-4, 1E-8, 1E-16, 1E-32, 1E-64, 1E-128, 1E-256 };
|
||||
public static double[] exponents = { 0x1P1, 0x1P2, 0x1P4, 0x1P8, 0x1P16, 0x1P32, 0x1P64, 0x1P128, 0x1P256,
|
||||
0x1P256, 0x1P512 };
|
||||
public static double[] negativeExponents = { 0x1P-1, 0x1P-2, 0x1P-4, 0x1P-8, 0x1P-16, 0x1P-32, 0x1P-64,
|
||||
0x1P-128, 0x1P-256, 0x1P-256, 0x1P-512 };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,4 +48,37 @@ public class DoubleTest {
|
|||
assertEquals(0, Double.parseDouble("00000"), 1E-12);
|
||||
assertEquals(0, Double.parseDouble("00000.0000"), 1E-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void longBitsExtracted() {
|
||||
assertEquals(0x41E23456789ABCDEL, Double.doubleToLongBits(0x1.23456789ABCDEP+31));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subNormalLongBitsExtracted() {
|
||||
assertEquals(0x00000056789ABCDEL, Double.doubleToLongBits(0x0.00056789ABCDEP-1022));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void longBitsPacked() {
|
||||
assertEquals(0x1.23456789ABCDEP+31, Double.longBitsToDouble(0x41E23456789ABCDEL), 0x1.0P-19);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subNormalLongBitsPacked() {
|
||||
assertEquals(0x0.00056789ABCDEP-1022, Double.longBitsToDouble(0x00000056789ABCDEL), 0x1.0P-19);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hexStringBuilt() {
|
||||
assertEquals("0x1.23456789abcdep31", Double.toHexString(0x1.23456789ABCDEP+31));
|
||||
assertEquals("0x1.0p0", Double.toHexString(1));
|
||||
assertEquals("-0x1.0p0", Double.toHexString(-1));
|
||||
assertEquals("0x1.0p1", Double.toHexString(2));
|
||||
assertEquals("0x1.8p1", Double.toHexString(3));
|
||||
assertEquals("0x1.0p-1", Double.toHexString(0.5));
|
||||
assertEquals("0x1.0p-2", Double.toHexString(0.25));
|
||||
assertEquals("0x1.0p-1022", Double.toHexString(Double.MIN_NORMAL));
|
||||
assertEquals("0x0.0000000000001p-1022", Double.toHexString(Double.MIN_VALUE));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -817,19 +817,19 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
visitBinary(expr, "<<");
|
||||
break;
|
||||
case LEFT_SHIFT_LONG:
|
||||
visitBinaryFunction(expr, "Long_lsh");
|
||||
visitBinaryFunction(expr, "Long_shr");
|
||||
break;
|
||||
case RIGHT_SHIFT:
|
||||
visitBinary(expr, ">>");
|
||||
break;
|
||||
case RIGHT_SHIFT_LONG:
|
||||
visitBinaryFunction(expr, "Long_rsh");
|
||||
visitBinaryFunction(expr, "Long_shr");
|
||||
break;
|
||||
case UNSIGNED_RIGHT_SHIFT:
|
||||
visitBinary(expr, ">>>");
|
||||
break;
|
||||
case UNSIGNED_RIGHT_SHIFT_LONG:
|
||||
visitBinaryFunction(expr, "Long_rshu");
|
||||
visitBinaryFunction(expr, "Long_shru");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user