diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java index 308115072..21028d7bb 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java @@ -172,4 +172,15 @@ public class TCollections extends TObject { } }); } + + public static void reverse(TList list) { + @SuppressWarnings("unchecked") + TList safeList = (TList)list; + int half = safeList.size() / 2; + for (int i = 0; i < half; ++i) { + Object tmp = safeList.get(i); + safeList.set(i, safeList.get(safeList.size() - i - 1)); + safeList.set(safeList.size() - i - 1, tmp); + } + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java new file mode 100644 index 000000000..4585cec6a --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java @@ -0,0 +1,59 @@ +/* + * 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; + +import org.teavm.classlib.java.lang.TIllegalStateException; +import org.teavm.classlib.java.lang.TObject; +import org.teavm.classlib.java.lang.TString; +import org.teavm.dependency.PluggableDependency; +import org.teavm.javascript.ni.GeneratedBy; + +/** + * + * @author Alexey Andreev + */ +public class TTimer extends TObject { + TSet tasks = new THashSet<>(); + private boolean cancelled; + + public TTimer() { + } + + public TTimer(@SuppressWarnings("unused") TString name) { + } + + public void cancel() { + if (cancelled) { + return; + } + cancelled = true; + for (TTimerTask task : tasks.toArray(new TTimerTask[0])) { + task.cancel(); + } + } + + public void schedule(TTimerTask task, long delay) { + if (cancelled || task.timer != null || task.nativeTimerId >= 0) { + throw new TIllegalStateException(); + } + task.timer = this; + task.nativeTimerId = scheduleOnce(task, (int)delay); + } + + @GeneratedBy(TimerNativeGenerator.class) + @PluggableDependency(TimerNativeGenerator.class) + private static native int scheduleOnce(TTimerTask task, int delay); +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimerTask.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimerTask.java new file mode 100644 index 000000000..1271e3e20 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimerTask.java @@ -0,0 +1,44 @@ +/* + * 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; + +import org.teavm.classlib.java.lang.TObject; +import org.teavm.classlib.java.lang.TRunnable; + +/** + * + * @author Alexey Andreev + */ +public abstract class TTimerTask extends TObject implements TRunnable { + TTimer timer; + int nativeTimerId = -1; + + public boolean cancel() { + if (timer == null) { + return false; + } + timer = null; + return true; + } + + void performOnce() { + if (timer != null) { + run(); + timer.tasks.remove(this); + timer = null; + } + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java new file mode 100644 index 000000000..387f44216 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java @@ -0,0 +1,62 @@ +/* + * 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; + +import java.io.IOException; +import org.teavm.codegen.SourceWriter; +import org.teavm.dependency.DependencyChecker; +import org.teavm.dependency.DependencyPlugin; +import org.teavm.dependency.MethodDependency; +import org.teavm.javascript.ni.Generator; +import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.model.MethodReference; +import org.teavm.model.ValueType; + +/** + * + * @author Alexey Andreev + */ +public class TimerNativeGenerator implements Generator, DependencyPlugin { + private static final MethodReference performOnceRef = new MethodReference("java.util.TimerTask", + "performOnce", ValueType.VOID); + + @Override + public void methodAchieved(DependencyChecker checker, MethodDependency method) { + switch (method.getReference().getName()) { + case "scheduleOnce": { + MethodDependency performMethod = checker.linkMethod(performOnceRef, method.getStack()); + method.getVariable(1).connect(performMethod.getVariable(1)); + break; + } + } + } + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { + switch (methodRef.getName()) { + case "scheduleOnce": + generateScheduleNative(context, writer); + break; + } + } + + private void generateScheduleNative(GeneratorContext context, SourceWriter writer) throws IOException { + writer.append("return setTimeout(function() {").indent().softNewLine(); + writer.append(context.getParameterName(1)).append(".").appendMethod(performOnceRef) + .append("();").softNewLine(); + writer.outdent().append("},").ws().append(context.getParameterName(2)).append(");").softNewLine(); + } +} diff --git a/teavm-core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java b/teavm-core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java index 2e6ad423d..fc9af0584 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java +++ b/teavm-core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java @@ -118,7 +118,7 @@ public abstract class InstructionVariableMapper implements InstructionVisitor { @Override public void visit(SwitchInstruction insn) { - insn.setCondition(insn.getCondition()); + insn.setCondition(map(insn.getCondition())); } @Override diff --git a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java index ac8cb63ba..8c3db9edc 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java +++ b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java @@ -98,9 +98,21 @@ public class ProgramParser { } } } + int signatureVars = countSignatureVariables(method.desc); + while (program.variableCount() <= signatureVars) { + program.createVariable(); + } return program; } + private int countSignatureVariables(String desc) { + int count = 1; + for (Type paramType : Type.getArgumentTypes(desc)) { + count += paramType.getSize(); + } + return count; + } + private int pushSingle() { stack = new StackFrame(stack, SINGLE); return stack.depth;