mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-27 01:30:35 +08:00
Implements Double.parseDouble. Fixes bugs. Disabled devirtualization
optimization due to bugs
This commit is contained in:
parent
b4347b4eb8
commit
5c613d2f7f
@ -22,7 +22,9 @@ import org.teavm.javascript.ni.Rename;
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class TDouble extends TNumber {
|
||||
public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||
public static double POSITIVE_INFINITY = 1 / 0.0;
|
||||
public static double NEGATIVE_INFINITY = -POSITIVE_INFINITY;
|
||||
private double value;
|
||||
|
||||
public TDouble(double value) {
|
||||
@ -57,6 +59,123 @@ public class TDouble extends TNumber {
|
||||
return TString.wrap(new TStringBuilder().append(d).toString());
|
||||
}
|
||||
|
||||
public static TDouble valueOf(TString string) {
|
||||
return valueOf(parseDouble(string));
|
||||
}
|
||||
|
||||
public static double parseDouble(TString string) throws TNumberFormatException {
|
||||
// TODO: parse infinite and different radix
|
||||
string = string.trim();
|
||||
boolean negative = false;
|
||||
int index = 0;
|
||||
if (string.charAt(index) == '-') {
|
||||
++index;
|
||||
negative = true;
|
||||
} else if (string.charAt(index) == '+') {
|
||||
++index;
|
||||
}
|
||||
char c = string.charAt(index);
|
||||
if (c < '0' || c > '9') {
|
||||
throw new TNumberFormatException();
|
||||
}
|
||||
long mantissa = 0;
|
||||
int exp = 0;
|
||||
while (string.charAt(index) == '0') {
|
||||
if (++index == string.length()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (index < string.length()) {
|
||||
c = string.charAt(index);
|
||||
if (c < '0' || c > '9') {
|
||||
break;
|
||||
}
|
||||
if (mantissa < 1E17) {
|
||||
mantissa = mantissa * 10 + (c - '0');
|
||||
} else {
|
||||
++exp;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
if (index < string.length() && string.charAt(index) == '.') {
|
||||
++index;
|
||||
boolean hasOneDigit = false;
|
||||
while (index < string.length()) {
|
||||
c = string.charAt(index);
|
||||
if (c < '0' || c > '9') {
|
||||
break;
|
||||
}
|
||||
if (mantissa < 1E17) {
|
||||
mantissa = mantissa * 10 + (c - '0');
|
||||
--exp;
|
||||
}
|
||||
++index;
|
||||
hasOneDigit = true;
|
||||
}
|
||||
if (!hasOneDigit) {
|
||||
throw new TNumberFormatException();
|
||||
}
|
||||
}
|
||||
if (index < string.length()) {
|
||||
c = string.charAt(index);
|
||||
if (c != 'e' && c != 'E') {
|
||||
throw new TNumberFormatException();
|
||||
}
|
||||
++index;
|
||||
boolean negativeExp = false;
|
||||
if (string.charAt(index) == '-') {
|
||||
++index;
|
||||
negativeExp = true;
|
||||
} else if (string.charAt(index) == '+') {
|
||||
++index;
|
||||
}
|
||||
int numExp = 0;
|
||||
boolean hasOneDigit = false;
|
||||
while (index < string.length()) {
|
||||
c = string.charAt(index);
|
||||
if (c < '0' || c > '9') {
|
||||
break;
|
||||
}
|
||||
numExp = 10 * numExp + (c - '0');
|
||||
hasOneDigit = true;
|
||||
++index;
|
||||
}
|
||||
if (!hasOneDigit) {
|
||||
throw new TNumberFormatException();
|
||||
}
|
||||
if (negativeExp) {
|
||||
numExp = -numExp;
|
||||
}
|
||||
exp += numExp;
|
||||
}
|
||||
if (exp > 308 || exp == 308 && mantissa > 17976931348623157L) {
|
||||
return !negative ? POSITIVE_INFINITY : NEGATIVE_INFINITY;
|
||||
}
|
||||
if (negative) {
|
||||
mantissa = -mantissa;
|
||||
}
|
||||
return mantissa * decimalExponent(exp);
|
||||
}
|
||||
|
||||
private static double decimalExponent(int n) {
|
||||
double d;
|
||||
if (n < 0) {
|
||||
d = 0.1;
|
||||
n = -n;
|
||||
} else {
|
||||
d = 10;
|
||||
}
|
||||
double result = 1;
|
||||
while (n != 0) {
|
||||
if (n % 2 != 0) {
|
||||
result *= d;
|
||||
}
|
||||
d *= d;
|
||||
n /= 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Rename("toString")
|
||||
public TString toString0() {
|
||||
@ -71,6 +190,15 @@ public class TDouble extends TNumber {
|
||||
return other instanceof TDouble && ((TDouble)other).value == value;
|
||||
}
|
||||
|
||||
public static int compare(double a, double b) {
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TDouble other) {
|
||||
return compare(value, other.value);
|
||||
}
|
||||
|
||||
@GeneratedBy(DoubleNativeGenerator.class)
|
||||
public static native boolean isNaN(double v);
|
||||
|
||||
|
@ -38,4 +38,24 @@ public final class TMath extends TObject {
|
||||
public static long max(long a, long b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
public static double min(double a, double b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
public static double max(double a, double b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
public static int abs(int n) {
|
||||
return n > 0 ? n : -n;
|
||||
}
|
||||
|
||||
public static long abs(long n) {
|
||||
return n > 0 ? n : -n;
|
||||
}
|
||||
|
||||
public static double abs(double n) {
|
||||
return n > 0 ? n : -n;
|
||||
}
|
||||
}
|
||||
|
@ -219,6 +219,9 @@ public class TArrays extends TObject {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> void sort(T[] a, TComparator<? super T> c) {
|
||||
if (a.length == 0) {
|
||||
return;
|
||||
}
|
||||
Object[] first = a;
|
||||
Object[] second = new Object[a.length];
|
||||
int chunkSize = 1;
|
||||
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.java.util.concurrent;
|
||||
|
||||
import org.teavm.classlib.java.lang.TRunnable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface TExecutor {
|
||||
void execute(TRunnable command);
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DoubleTest {
|
||||
@Test
|
||||
public void parsed() {
|
||||
assertEquals(23, Double.parseDouble("23"), 1E-12);
|
||||
assertEquals(23, Double.parseDouble("23.0"), 1E-12);
|
||||
assertEquals(23, Double.parseDouble("23E0"), 1E-12);
|
||||
assertEquals(23, Double.parseDouble("2.30000E1"), 1E-12);
|
||||
assertEquals(23, Double.parseDouble("0.23E2"), 1E-12);
|
||||
assertEquals(23, Double.parseDouble("0.000023E6"), 1E-12);
|
||||
assertEquals(23, Double.parseDouble("00230000e-4"), 1E-12);
|
||||
assertEquals(23, Double.parseDouble("2300000000000000000000e-20"), 1E-12);
|
||||
assertEquals(23, Double.parseDouble("2300000000000000000000e-20"), 1E-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negativeParsed() {
|
||||
assertEquals(-23, Double.parseDouble("-23"), 1E-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zeroParsed() {
|
||||
assertEquals(0, Double.parseDouble("0.0"), 1E-12);
|
||||
assertEquals(0, Double.parseDouble("23E-8000"), 1E-12);
|
||||
assertEquals(0, Double.parseDouble("00000"), 1E-12);
|
||||
assertEquals(0, Double.parseDouble("00000.0000"), 1E-12);
|
||||
}
|
||||
}
|
@ -158,8 +158,8 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
||||
Linker linker = new Linker(dependencyChecker);
|
||||
ListableClassHolderSource classSet = linker.link(classSource);
|
||||
Decompiler decompiler = new Decompiler(classSet, classLoader, executor);
|
||||
devirtualize(classSet, dependencyChecker);
|
||||
executor.complete();
|
||||
/*devirtualize(classSet, dependencyChecker);
|
||||
executor.complete();*/
|
||||
ClassSetOptimizer optimizer = new ClassSetOptimizer(executor);
|
||||
optimizer.optimizeAll(classSet);
|
||||
executor.complete();
|
||||
@ -198,6 +198,8 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: repair devirtualization
|
||||
@SuppressWarnings("unused")
|
||||
private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) {
|
||||
final Devirtualization devirtualization = new Devirtualization(dependency, classes);
|
||||
for (String className : classes.getClassNames()) {
|
||||
|
@ -1274,11 +1274,9 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||
.appendClass(catchClause.getExceptionType());
|
||||
}
|
||||
writer.append(")").ws().append("{").indent().softNewLine();
|
||||
if (statement.getExceptionVariable() != catchClause.getExceptionVariable()) {
|
||||
if (catchClause.getExceptionVariable() != null) {
|
||||
writer.append(variableName(catchClause.getExceptionVariable())).ws().append("=").ws()
|
||||
.append("$e;").softNewLine();
|
||||
}
|
||||
if (catchClause.getExceptionVariable() != null) {
|
||||
writer.append(variableName(catchClause.getExceptionVariable())).ws().append("=").ws()
|
||||
.append("$je;").softNewLine();
|
||||
}
|
||||
for (Statement part : catchClause.getHandler()) {
|
||||
part.acceptVisitor(this);
|
||||
|
@ -89,6 +89,15 @@ public class ProgramParser {
|
||||
program.basicBlockAt(0).getInstructions().add(insn);
|
||||
doAnalyze(method);
|
||||
assemble();
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock block = program.basicBlockAt(i);
|
||||
for (int j = 0; j < block.getTryCatchBlocks().size(); ++j) {
|
||||
TryCatchBlock tryCatch = block.getTryCatchBlocks().get(j);
|
||||
if (tryCatch.getHandler() == block) {
|
||||
block.getTryCatchBlocks().remove(j--);
|
||||
}
|
||||
}
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
|
@ -228,8 +228,12 @@ $rt_init = function(cls, constructor, args) {
|
||||
return obj;
|
||||
}
|
||||
$rt_throw = function(ex) {
|
||||
var err = new Error("Java exception thrown");
|
||||
err.$javaException = ex;
|
||||
var err = ex.$jsException;
|
||||
if (!err) {
|
||||
var err = new Error("Java exception thrown");
|
||||
err.$javaException = ex;
|
||||
ex.$jsException = err;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
$rt_byteToInt = function(value) {
|
||||
|
Loading…
Reference in New Issue
Block a user