diff --git a/checkstyle.xml b/checkstyle.xml index f09602312..a55a0915d 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -44,7 +44,6 @@ - diff --git a/pom.xml b/pom.xml index 54733ecef..b2cdeb921 100644 --- a/pom.xml +++ b/pom.xml @@ -222,8 +222,6 @@ validate validate - config_loc=${basedir}/.. - ../checkstyle.xml UTF-8 true true @@ -234,6 +232,10 @@ + + config_loc=${basedir}/.. + ../checkstyle.xml + org.apache.felix @@ -266,12 +268,6 @@ - - enable-scala - - teavm-scala-samples - - enable-samples diff --git a/teavm-classlib/pom.xml b/teavm-classlib/pom.xml index 04f1af794..4c67e2cf4 100644 --- a/teavm-classlib/pom.xml +++ b/teavm-classlib/pom.xml @@ -26,6 +26,9 @@ bundle + TeaVM Java class library + TeaVM Java class library emulation + junit @@ -49,9 +52,6 @@ - TeaVM JCL - TeaVM Java class library emulation - diff --git a/teavm-core/src/main/java/org/teavm/model/package-info.java b/teavm-core/src/main/java/org/teavm/model/package-info.java index 78d19c131..f50ee2cd4 100644 --- a/teavm-core/src/main/java/org/teavm/model/package-info.java +++ b/teavm-core/src/main/java/org/teavm/model/package-info.java @@ -17,9 +17,9 @@ * Represents a class model that is alternative to {@link java.lang.reflection} package. * Model is suitable for representing classes that are not in class path. Also * it allows to disassemble method bodies into three-address code that is very - * close to JVM bytecode (see {@link org.teavm.instructions}. + * close to JVM bytecode (see {@link org.teavm.model.instructions}. * - *

The entry point is some implementation of {@link ClassHolderSource} interface. + *

The entry point is some implementation of {@link org.teavm.model.ClassHolderSource} interface. * */ package org.teavm.model; \ No newline at end of file diff --git a/teavm-samples/pom.xml b/teavm-samples/pom.xml index e75fe9742..8b607bec3 100644 --- a/teavm-samples/pom.xml +++ b/teavm-samples/pom.xml @@ -16,6 +16,7 @@ 4.0.0 + org.teavm teavm @@ -23,108 +24,13 @@ teavm-samples - - - org.teavm - teavm-core - ${project.version} - - - org.teavm - teavm-dom - ${project.version} - - + pom - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - ../checkstyle.xml - - - - org.teavm - teavm-maven-plugin - ${project.version} - - - org.teavm - teavm-classlib - ${project.version} - - - - - generate-hello - - build-javascript - - process-classes - - false - org.teavm.samples.HelloWorld - true - true - true - true - ${project.build.directory}/javascript/hello - - - - generate-matrix - - build-javascript - - process-classes - - false - org.teavm.samples.MatrixMultiplication - true - true - true - ${project.build.directory}/javascript/matrix - - - - generate-datetime - - build-javascript - - process-classes - - false - org.teavm.samples.DateTime - ${project.build.directory}/javascript/datetime - true - true - - en_US,en_GB,ru_RU,ru_UA,nl_NL,nl_BE - - - - - - - maven-assembly-plugin - 2.4 - - - src/main/assembly/teavm-demos.xml - - - - - make-assembly - package - - single - - - - - - + TeaVM samples + TeaVM code samples + + + teavm-samples-hello + teavm-samples-benchmark + \ No newline at end of file diff --git a/teavm-samples/src/main/assembly/teavm-demos.xml b/teavm-samples/src/main/assembly/teavm-demos.xml deleted file mode 100644 index bb618e19a..000000000 --- a/teavm-samples/src/main/assembly/teavm-demos.xml +++ /dev/null @@ -1,24 +0,0 @@ - - teavm-demos - - zip - - - - src/main/resources/datetime.html - / - - - ${project.build.directory}/javascript/datetime/classes.js - / - datetime.js - - - ${project.build.directory}/javascript/datetime/runtime.js - / - - - \ No newline at end of file diff --git a/teavm-samples/src/main/java/org/teavm/samples/DateTime.java b/teavm-samples/src/main/java/org/teavm/samples/DateTime.java deleted file mode 100644 index daf5b64c5..000000000 --- a/teavm-samples/src/main/java/org/teavm/samples/DateTime.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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.samples; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Locale; -import org.teavm.dom.browser.TimerHandler; -import org.teavm.dom.browser.Window; -import org.teavm.dom.events.Event; -import org.teavm.dom.events.EventListener; -import org.teavm.dom.html.HTMLDocument; -import org.teavm.dom.html.HTMLInputElement; -import org.teavm.dom.html.HTMLOptionElement; -import org.teavm.dom.html.HTMLSelectElement; -import org.teavm.jso.JS; - -/** - * - * @author Alexey Andreev - */ -public final class DateTime { - private DateTime() { - } - - private static Window window = (Window)JS.getGlobal(); - private static HTMLDocument document = window.getDocument(); - private static HTMLSelectElement localeElem = (HTMLSelectElement)document.getElementById("locale"); - private static HTMLSelectElement formatElem = (HTMLSelectElement)document.getElementById("format"); - private static HTMLSelectElement customFormatElem = (HTMLSelectElement)document.getElementById("custom-format"); - private static Date currentDate = new Date(); - private static Locale[] locales; - private static Locale currentLocale; - private static DateFormat dateFormat; - - public static void main(String[] args) { - fillLocales(); - window.setInterval(new TimerHandler() { - @Override public void onTimer() { - updateCurrentTime(); - } - }, 250); - updateCurrentLocale(); - updateFormat(); - formatElem.addEventListener("change", new EventListener() { - @Override public void handleEvent(Event evt) { - updateFormat(); - updateCurrentTimeText(); - } - }); - customFormatElem.addEventListener("change", new EventListener() { - @Override public void handleEvent(Event evt) { - updateFormat(); - updateCurrentTimeText(); - } - }); - } - - private static void fillLocales() { - locales = Locale.getAvailableLocales(); - for (Locale locale : locales) { - HTMLOptionElement option = (HTMLOptionElement)document.createElement("option"); - option.setValue(locale.toString()); - option.setLabel(locale.getDisplayName(Locale.getDefault())); - localeElem.getOptions().add(option); - } - localeElem.addEventListener("change", new EventListener() { - @Override public void handleEvent(Event evt) { - updateCurrentLocale(); - updateFormat(); - updateCurrentTimeText(); - } - }); - } - - private static void updateCurrentLocale() { - currentLocale = locales[localeElem.getSelectedIndex()]; - GregorianCalendar calendar = new GregorianCalendar(currentLocale); - HTMLInputElement weekStartElem = (HTMLInputElement)document.getElementById("week-start"); - weekStartElem.setValue(String.valueOf(calendar.getFirstDayOfWeek())); - HTMLInputElement weekLengthElem = (HTMLInputElement)document.getElementById("week-length"); - weekLengthElem.setValue(String.valueOf(calendar.getMinimalDaysInFirstWeek())); - } - - private static void updateCurrentTime() { - setCurrentTime(new Date()); - } - - private static void setCurrentTime(Date date) { - currentDate = date; - updateCurrentTimeText(); - } - - private static void updateCurrentTimeText() { - HTMLInputElement timeElem = (HTMLInputElement)document.getElementById("current-time"); - try { - timeElem.setValue(dateFormat.format(currentDate)); - } catch (RuntimeException e) { - timeElem.setValue("Error formatting date"); - } - } - - private static void updateFormat() { - customFormatElem.setDisabled(true); - switch (formatElem.getValue()) { - case "short-date": - dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, currentLocale); - break; - case "medium-date": - dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, currentLocale); - break; - case "long-date": - dateFormat = DateFormat.getDateInstance(DateFormat.LONG, currentLocale); - break; - case "full-date": - dateFormat = DateFormat.getDateInstance(DateFormat.FULL, currentLocale); - break; - case "short-time": - dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT, currentLocale); - break; - case "medium-time": - dateFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM, currentLocale); - break; - case "long-time": - dateFormat = DateFormat.getTimeInstance(DateFormat.LONG, currentLocale); - break; - case "full-time": - dateFormat = DateFormat.getTimeInstance(DateFormat.FULL, currentLocale); - break; - case "short-datetime": - dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, currentLocale); - break; - case "medium-datetime": - dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, currentLocale); - break; - case "long-datetime": - dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, currentLocale); - break; - case "full-datetime": - dateFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, currentLocale); - break; - case "custom": - customFormatElem.setDisabled(false); - try { - dateFormat = new SimpleDateFormat(customFormatElem.getValue(), currentLocale); - } catch (IllegalArgumentException e) { - dateFormat = new SimpleDateFormat("'Invalid pattern'"); - } - break; - } - } -} diff --git a/teavm-samples/src/main/java/org/teavm/samples/HelloWorld.java b/teavm-samples/src/main/java/org/teavm/samples/HelloWorld.java deleted file mode 100644 index c8255a95b..000000000 --- a/teavm-samples/src/main/java/org/teavm/samples/HelloWorld.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2013 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.samples; - -import org.teavm.dom.browser.Window; -import org.teavm.dom.core.Document; -import org.teavm.dom.core.Element; -import org.teavm.dom.events.Event; -import org.teavm.dom.events.EventListener; -import org.teavm.dom.events.EventTarget; -import org.teavm.jso.JS; - -/** - * - * @author Alexey Andreev - */ -public final class HelloWorld { - private HelloWorld() { - } - - private static Window window; - private static Document document; - private static Element body; - - public static void main(String[] args) { - window = (Window)JS.getGlobal(); - document = window.getDocument(); - body = document.getDocumentElement().getElementsByTagName("body").item(0); - createButton(); - } - - private static void createButton() { - Element elem = document.createElement("div"); - body.appendChild(elem); - final Element button = document.createElement("button"); - button.appendChild(document.createTextNode("Click me!")); - elem.appendChild(button); - ((EventTarget)button).addEventListener("click", new EventListener() { - @Override public void handleEvent(Event evt) { - button.getParentNode().removeChild(button); - printHelloWorld(); - } - }, false); - } - - private static void printHelloWorld() { - println("Hello, world!"); - println("Here is the Fibonacci sequence:"); - long a = 0; - long b = 1; - for (int i = 0; i < 70; ++i) { - println(a); - long c = a + b; - a = b; - b = c; - } - println("And so on..."); - } - - private static void println(Object obj) { - Element elem = document.createElement("div"); - elem.appendChild(document.createTextNode(String.valueOf(obj))); - body.appendChild(elem); - } - - private static void println(long val) { - Element elem = document.createElement("div"); - elem.appendChild(document.createTextNode(String.valueOf(val))); - body.appendChild(elem); - } -} diff --git a/teavm-samples/src/main/java/org/teavm/samples/Matrix.java b/teavm-samples/src/main/java/org/teavm/samples/Matrix.java deleted file mode 100644 index daf7db9fc..000000000 --- a/teavm-samples/src/main/java/org/teavm/samples/Matrix.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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. - */ -// This file is based on the original source code from Bck2Brwsr -/** - * Back 2 Browser Bytecode Translator - * Copyright (C) 2012 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://opensource.org/licenses/GPL-2.0. - */ -package org.teavm.samples; - -import java.io.IOException; -import java.util.Arrays; - -/** - * - * @author Alexey Andreev - */ -public class Matrix { - private final int rank; - private final float[][] data; - - public Matrix(int r) { - this(r, new float[r][r]); - } - - private Matrix(int r, float[][] data) { - this.rank = r; - this.data = data; - } - - public void setElement(int i, int j, float value) { - data[i][j] = value; - } - public float getElement(int i, int j) { - return data[i][j]; - } - - public void generateData() { - //final Random rand = new Random(); - //final int x = 10; - for (int i = 0; i < rank; i++) { - for (int j = 0; j < rank; j++) { - data[i][j] = 1 / (1 + i + j); - } - } - } - - public Matrix multiply(Matrix m) { - if (rank != m.rank) { - throw new IllegalArgumentException("Rank doesn't match"); - } - - final float[][] res = new float[rank][rank]; - for (int i = 0; i < rank; i++) { - for (int j = 0; j < rank; j++) { - float ij = 0; - for (int q = 0; q < rank; q++) { - ij += data[i][q] * m.data[q][j]; - } - res[i][j] = ij; - } - } - return new Matrix(rank, res); - } - - public void printOn(Appendable s) throws IOException { - for (int i = 0; i < rank; i++) { - String sep = ""; - for (int j = 0; j < rank; j++) { - s.append(sep + data[i][j]); - sep = " "; - } - s.append("\n"); - } - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Matrix) { - Matrix snd = (Matrix)obj; - if (snd.rank != rank) { - return false; - } - for (int i = 0; i < rank; i++) { - for (int j = 0; j < rank; j++) { - if (data[i][j] != snd.data[i][j]) { - return false; - } - } - } - return true; - } - return false; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 97 * hash + this.rank; - hash = 97 * hash + Arrays.deepHashCode(this.data); - return hash; - } -} diff --git a/teavm-samples/src/main/java/org/teavm/samples/MatrixMultiplication.java b/teavm-samples/src/main/java/org/teavm/samples/MatrixMultiplication.java deleted file mode 100644 index a2445bd6f..000000000 --- a/teavm-samples/src/main/java/org/teavm/samples/MatrixMultiplication.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.samples; - -import java.io.IOException; - -/** - * - * @author Alexey Andreev - */ -public final class MatrixMultiplication { - private MatrixMultiplication() { - } - - public static void main(String[] args) throws IOException { - for (int k = 0; k < 20; ++k) { - long startTime = System.currentTimeMillis(); - - Matrix m1 = new Matrix(5); - Matrix m2 = new Matrix(5); - - m1.generateData(); - m2.generateData(); - - Matrix res = null; - for (int i = 0; i < 10000; i++) { - res = m1.multiply(m2); - m1 = res; - } - StringBuilder sb = new StringBuilder(); - res.printOn(sb); - long timeSpent = System.currentTimeMillis() - startTime; - System.out.println(sb.toString()); - System.out.println("Time spent: " + timeSpent); - } - } -} diff --git a/teavm-samples/src/main/resources/.gitignore b/teavm-samples/src/main/resources/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/teavm-samples/src/main/resources/datetime.html b/teavm-samples/src/main/resources/datetime.html deleted file mode 100644 index a8ea7e585..000000000 --- a/teavm-samples/src/main/resources/datetime.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - Localized date & time demo application - - - - - -

- - -
-
- - -
-
- - - - -
-
- - - -
- - \ No newline at end of file diff --git a/teavm-samples/src/test/java/.gitignore b/teavm-samples/src/test/java/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/teavm-samples/src/test/resources/.gitignore b/teavm-samples/src/test/resources/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/teavm-scala-samples/.gitignore b/teavm-samples/teavm-samples-benchmark/.gitignore similarity index 83% rename from teavm-scala-samples/.gitignore rename to teavm-samples/teavm-samples-benchmark/.gitignore index ee44b687e..c708c363d 100644 --- a/teavm-scala-samples/.gitignore +++ b/teavm-samples/teavm-samples-benchmark/.gitignore @@ -2,4 +2,3 @@ /.settings /.classpath /.project -/.cache diff --git a/teavm-samples/teavm-samples-benchmark/pom.xml b/teavm-samples/teavm-samples-benchmark/pom.xml new file mode 100644 index 000000000..369f784ba --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/pom.xml @@ -0,0 +1,136 @@ + + + 4.0.0 + + + org.teavm + teavm-samples + 0.2-SNAPSHOT + + teavm-samples-benchmark + war + + TeaVM performance benchmark + Compares performance of the JavaScript code produced by TeaVM and GWT + + + + org.teavm + teavm-classlib + ${project.version} + + + org.teavm + teavm-jso + ${project.version} + + + org.teavm + teavm-dom + ${project.version} + + + org.jbox2d + jbox2d-library + 2.2.1.1 + + + org.jbox2d + jbox2d-library + 2.2.1.1 + sources + + + com.google.gwt + gwt-user + 2.6.1 + provided + + + + + + + maven-war-plugin + 2.4 + + + + ${project.build.directory}/generated/js + + + + + + org.teavm + teavm-maven-plugin + ${project.version} + + + web-client + prepare-package + + build-javascript + + + ${project.build.directory}/generated/js/teavm + org.teavm.samples.benchmark.teavm.BenchmarkStarter + SEPARATE + true + true + + + + + + org.codehaus.mojo + gwt-maven-plugin + 2.6.1 + + + + compile + + + 9 + + org.jbox2d:jbox2d-library + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ../../checkstyle.xml + config_loc=${basedir}/../.. + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/Scene.java b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/Scene.java new file mode 100644 index 000000000..0dfded7f1 --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/Scene.java @@ -0,0 +1,158 @@ +/* + * 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.samples.benchmark; + +import org.jbox2d.collision.shapes.CircleShape; +import org.jbox2d.collision.shapes.PolygonShape; +import org.jbox2d.common.Vec2; +import org.jbox2d.dynamics.*; +import org.jbox2d.dynamics.joints.RevoluteJointDef; + +/** + * + * @author Alexey Andreev + */ +public class Scene { + private World world; + private Body axis; + private Body reel; + private long lastCalculated; + private long startTime; + + public Scene() { + world = new World(new Vec2(0, -9.8f)); + initAxis(); + initReel(); + joinReelToAxis(); + initBalls(); + lastCalculated = System.currentTimeMillis(); + startTime = lastCalculated; + } + + private void initAxis() { + BodyDef axisDef = new BodyDef(); + axisDef.type = BodyType.STATIC; + axisDef.position = new Vec2(3, 3); + axis = world.createBody(axisDef); + + CircleShape axisShape = new CircleShape(); + axisShape.setRadius(0.02f); + axisShape.m_p.set(0, 0); + + FixtureDef axisFixture = new FixtureDef(); + axisFixture.shape = axisShape; + axis.createFixture(axisFixture); + } + + private void initReel() { + BodyDef reelDef = new BodyDef(); + reelDef.type = BodyType.DYNAMIC; + reelDef.position = new Vec2(3, 3); + reel = world.createBody(reelDef); + + FixtureDef fixture = new FixtureDef(); + fixture.friction = 0.5f; + fixture.restitution = 0.4f; + fixture.density = 1; + + int parts = 30; + for (int i = 0; i < parts; ++i) { + PolygonShape shape = new PolygonShape(); + double angle1 = i / (double)parts * 2 * Math.PI; + double x1 = 2.7 * Math.cos(angle1); + double y1 = 2.7 * Math.sin(angle1); + double angle2 = (i + 1) / (double)parts * 2 * Math.PI; + double x2 = 2.7 * Math.cos(angle2); + double y2 = 2.7 * Math.sin(angle2); + double angle = (angle1 + angle2) / 2; + double x = 0.01 * Math.cos(angle); + double y = 0.01 * Math.sin(angle); + + shape.set(new Vec2[] { new Vec2((float)x1, (float)y1), new Vec2((float)x2, (float)y2), + new Vec2((float)(x2 - x), (float)(y2 - y)), new Vec2((float)(x1 - x), (float)(y1 - y)) }, 4); + fixture.shape = shape; + reel.createFixture(fixture); + } + } + + private void initBalls() { + float ballRadius = 0.15f; + + BodyDef ballDef = new BodyDef(); + ballDef.type = BodyType.DYNAMIC; + FixtureDef fixtureDef = new FixtureDef(); + fixtureDef.friction = 0.3f; + fixtureDef.restitution = 0.3f; + fixtureDef.density = 0.2f; + CircleShape shape = new CircleShape(); + shape.m_radius = ballRadius; + fixtureDef.shape = shape; + + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 5; ++j) { + float x = (j + 0.5f) * (ballRadius * 2 + 0.01f); + float y = (i + 0.5f) * (ballRadius * 2 + 0.01f); + ballDef.position.x = 3 + x; + ballDef.position.y = 3 + y; + Body body = world.createBody(ballDef); + body.createFixture(fixtureDef); + + ballDef.position.x = 3 - x; + ballDef.position.y = 3 + y; + body = world.createBody(ballDef); + body.createFixture(fixtureDef); + + ballDef.position.x = 3 + x; + ballDef.position.y = 3 - y; + body = world.createBody(ballDef); + body.createFixture(fixtureDef); + + ballDef.position.x = 3 - x; + ballDef.position.y = 3 - y; + body = world.createBody(ballDef); + body.createFixture(fixtureDef); + } + } + } + + private void joinReelToAxis() { + RevoluteJointDef jointDef = new RevoluteJointDef(); + jointDef.bodyA = axis; + jointDef.bodyB = reel; + world.createJoint(jointDef); + } + + public void calculate() { + long currentTime = System.currentTimeMillis(); + int timeToCalculate = (int)(currentTime - lastCalculated); + long relativeTime = currentTime - startTime; + while (timeToCalculate > 10) { + int period = (int)((relativeTime + 5000) / 10000); + reel.applyTorque(period % 2 == 0 ? 8f : -8f); + world.step(0.01f, 20, 40); + lastCalculated += 10; + timeToCalculate -= 10; + } + } + + public int timeUntilNextStep() { + return (int)Math.max(0, lastCalculated + 10 - System.currentTimeMillis()); + } + + public World getWorld() { + return world; + } +} diff --git a/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/gwt/BenchmarkStarter.java b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/gwt/BenchmarkStarter.java new file mode 100644 index 000000000..1c18065c4 --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/gwt/BenchmarkStarter.java @@ -0,0 +1,118 @@ +/* + * 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.samples.benchmark.gwt; + +import com.google.gwt.canvas.dom.client.Context2d; +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.dom.client.CanvasElement; +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.Element; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.RootPanel; +import org.jbox2d.collision.shapes.CircleShape; +import org.jbox2d.collision.shapes.PolygonShape; +import org.jbox2d.collision.shapes.Shape; +import org.jbox2d.collision.shapes.ShapeType; +import org.jbox2d.common.Vec2; +import org.jbox2d.dynamics.Body; +import org.jbox2d.dynamics.Fixture; +import org.teavm.samples.benchmark.Scene; + +public class BenchmarkStarter implements EntryPoint { + private Document document; + private CanvasElement canvas; + private Element resultTableBody; + private Scene scene = new Scene(); + private static int currentSecond; + private static long startMillisecond; + private static double timeSpentCalculating; + + @Override + public void onModuleLoad() { + document = RootPanel.getBodyElement().getOwnerDocument(); + canvas = (CanvasElement)document.getElementById("benchmark-canvas"); + resultTableBody = document.getElementById("result-table-body"); + startMillisecond = System.currentTimeMillis(); + makeStep(); + } + + private void makeStep() { + double start = Performance.now(); + scene.calculate(); + double end = Performance.now(); + int second = (int)((System.currentTimeMillis() - startMillisecond) / 1000); + if (second > currentSecond) { + Element row = document.createElement("tr"); + resultTableBody.appendChild(row); + Element secondCell = document.createElement("td"); + row.appendChild(secondCell); + secondCell.appendChild(document.createTextNode(String.valueOf(second))); + Element timeCell = document.createElement("td"); + row.appendChild(timeCell); + timeCell.appendChild(document.createTextNode(String.valueOf(timeSpentCalculating))); + + timeSpentCalculating = 0; + currentSecond = second; + } + timeSpentCalculating += end - start; + render(); + new Timer() { + @Override public void run() { + makeStep(); + } + }.schedule(scene.timeUntilNextStep()); + } + + private void render() { + Context2d context = canvas.getContext2d(); + context.setFillStyle("white"); + context.setStrokeStyle("grey"); + context.fillRect(0, 0, 600, 600); + context.save(); + context.translate(0, 600); + context.scale(1, -1); + context.scale(100, 100); + context.setLineWidth(0.01); + for (Body body = scene.getWorld().getBodyList(); body != null; body = body.getNext()) { + Vec2 center = body.getPosition(); + context.save(); + context.translate(center.x, center.y); + context.rotate(body.getAngle()); + for (Fixture fixture = body.getFixtureList(); fixture != null; fixture = fixture.getNext()) { + Shape shape = fixture.getShape(); + if (shape.getType() == ShapeType.CIRCLE) { + CircleShape circle = (CircleShape)shape; + context.beginPath(); + context.arc(circle.m_p.x, circle.m_p.y, circle.getRadius(), 0, Math.PI * 2, true); + context.closePath(); + context.stroke(); + } else if (shape.getType() == ShapeType.POLYGON) { + PolygonShape poly = (PolygonShape)shape; + Vec2[] vertices = poly.getVertices(); + context.beginPath(); + context.moveTo(vertices[0].x, vertices[0].y); + for (int i = 1; i < poly.getVertexCount(); ++i) { + context.lineTo(vertices[i].x, vertices[i].y); + } + context.closePath(); + context.stroke(); + } + } + context.restore(); + } + context.restore(); + } +} diff --git a/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/gwt/Performance.java b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/gwt/Performance.java new file mode 100644 index 000000000..4bddbe57d --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/gwt/Performance.java @@ -0,0 +1,25 @@ +/* + * 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.samples.benchmark.gwt; + +public final class Performance { + private Performance() { + } + + public static native double now() /*-{ + return $wnd.performance.now(); + }-*/; +} diff --git a/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/teavm/BenchmarkStarter.java b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/teavm/BenchmarkStarter.java new file mode 100644 index 000000000..c3a9edd62 --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/teavm/BenchmarkStarter.java @@ -0,0 +1,123 @@ +/* + * 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.samples.benchmark.teavm; + +import org.jbox2d.collision.shapes.CircleShape; +import org.jbox2d.collision.shapes.PolygonShape; +import org.jbox2d.collision.shapes.Shape; +import org.jbox2d.collision.shapes.ShapeType; +import org.jbox2d.common.Vec2; +import org.jbox2d.dynamics.Body; +import org.jbox2d.dynamics.Fixture; +import org.teavm.dom.browser.TimerHandler; +import org.teavm.dom.browser.Window; +import org.teavm.dom.canvas.CanvasRenderingContext2D; +import org.teavm.dom.html.HTMLCanvasElement; +import org.teavm.dom.html.HTMLDocument; +import org.teavm.dom.html.HTMLElement; +import org.teavm.jso.JS; +import org.teavm.samples.benchmark.Scene; + +/** + * + * @author Alexey Andreev + */ +public final class BenchmarkStarter { + private static Window window = (Window)JS.getGlobal(); + private static HTMLDocument document = window.getDocument(); + private static HTMLCanvasElement canvas = (HTMLCanvasElement)document.getElementById("benchmark-canvas"); + private static HTMLElement resultTableBody = document.getElementById("result-table-body"); + private static Performance performance = (Performance)JS.get(window, JS.wrap("performance")); + private static Scene scene = new Scene(); + private static int currentSecond; + private static long startMillisecond; + private static double timeSpentCalculating; + + private BenchmarkStarter() { + } + + public static void main(String[] args) { + startMillisecond = System.currentTimeMillis(); + makeStep(); + } + + private static void makeStep() { + double start = performance.now(); + scene.calculate(); + double end = performance.now(); + int second = (int)((System.currentTimeMillis() - startMillisecond) / 1000); + if (second > currentSecond) { + HTMLElement row = document.createElement("tr"); + resultTableBody.appendChild(row); + HTMLElement secondCell = document.createElement("td"); + row.appendChild(secondCell); + secondCell.appendChild(document.createTextNode(String.valueOf(second))); + HTMLElement timeCell = document.createElement("td"); + row.appendChild(timeCell); + timeCell.appendChild(document.createTextNode(String.valueOf(timeSpentCalculating))); + + timeSpentCalculating = 0; + currentSecond = second; + } + timeSpentCalculating += end - start; + render(); + window.setTimeout(new TimerHandler() { + @Override public void onTimer() { + makeStep(); + } + }, scene.timeUntilNextStep()); + } + + private static void render() { + CanvasRenderingContext2D context = (CanvasRenderingContext2D)canvas.getContext("2d"); + context.setFillStyle("white"); + context.setStrokeStyle("grey"); + context.fillRect(0, 0, 600, 600); + context.save(); + context.translate(0, 600); + context.scale(1, -1); + context.scale(100, 100); + context.setLineWidth(0.01); + for (Body body = scene.getWorld().getBodyList(); body != null; body = body.getNext()) { + Vec2 center = body.getPosition(); + context.save(); + context.translate(center.x, center.y); + context.rotate(body.getAngle()); + for (Fixture fixture = body.getFixtureList(); fixture != null; fixture = fixture.getNext()) { + Shape shape = fixture.getShape(); + if (shape.getType() == ShapeType.CIRCLE) { + CircleShape circle = (CircleShape)shape; + context.beginPath(); + context.arc(circle.m_p.x, circle.m_p.y, circle.getRadius(), 0, Math.PI * 2, true); + context.closePath(); + context.stroke(); + } else if (shape.getType() == ShapeType.POLYGON) { + PolygonShape poly = (PolygonShape)shape; + Vec2[] vertices = poly.getVertices(); + context.beginPath(); + context.moveTo(vertices[0].x, vertices[0].y); + for (int i = 1; i < poly.getVertexCount(); ++i) { + context.lineTo(vertices[i].x, vertices[i].y); + } + context.closePath(); + context.stroke(); + } + } + context.restore(); + } + context.restore(); + } +} diff --git a/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/teavm/Performance.java b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/teavm/Performance.java new file mode 100644 index 000000000..a0fe3650c --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/java/org/teavm/samples/benchmark/teavm/Performance.java @@ -0,0 +1,22 @@ +/* + * 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.samples.benchmark.teavm; + +import org.teavm.jso.JSObject; + +public interface Performance extends JSObject { + double now(); +} diff --git a/teavm-samples/teavm-samples-benchmark/src/main/resources/org/teavm/samples/benchmark/benchmark.gwt.xml b/teavm-samples/teavm-samples-benchmark/src/main/resources/org/teavm/samples/benchmark/benchmark.gwt.xml new file mode 100644 index 000000000..898176ecd --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/resources/org/teavm/samples/benchmark/benchmark.gwt.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-benchmark/src/main/webapp/WEB-INF/web.xml b/teavm-samples/teavm-samples-benchmark/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..bfc410b12 --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-benchmark/src/main/webapp/gwt.html b/teavm-samples/teavm-samples-benchmark/src/main/webapp/gwt.html new file mode 100644 index 000000000..db1cfbec6 --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/webapp/gwt.html @@ -0,0 +1,40 @@ + + + + + + GWT jbox2d benchmark + + + + +

GWT performance

+
+ +
+ + + + + + + + + +
SecondTime spent computing, ms
+ + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-benchmark/src/main/webapp/index.html b/teavm-samples/teavm-samples-benchmark/src/main/webapp/index.html new file mode 100644 index 000000000..6c8f5de14 --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/webapp/index.html @@ -0,0 +1,29 @@ + + + + + + TeaVM vs. GWT performance comparison + + +

TeaVM vs. GWT performance

+ + + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-benchmark/src/main/webapp/teavm.html b/teavm-samples/teavm-samples-benchmark/src/main/webapp/teavm.html new file mode 100644 index 000000000..ff02593fb --- /dev/null +++ b/teavm-samples/teavm-samples-benchmark/src/main/webapp/teavm.html @@ -0,0 +1,40 @@ + + + + + + TeaVM jbox2d benchmark + + + + +

TeaVM performance

+
+ +
+ + + + + + + + + +
SecondTime spent computing, ms
+ + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-hello/.gitignore b/teavm-samples/teavm-samples-hello/.gitignore new file mode 100644 index 000000000..c708c363d --- /dev/null +++ b/teavm-samples/teavm-samples-hello/.gitignore @@ -0,0 +1,4 @@ +/target +/.settings +/.classpath +/.project diff --git a/teavm-samples/teavm-samples-hello/pom.xml b/teavm-samples/teavm-samples-hello/pom.xml new file mode 100644 index 000000000..eda584209 --- /dev/null +++ b/teavm-samples/teavm-samples-hello/pom.xml @@ -0,0 +1,110 @@ + + + 4.0.0 + + + org.teavm + teavm-samples + 0.2-SNAPSHOT + + teavm-samples-hello + + war + + TeaVM Hello world web application + A sample application that shows how TeaVM can communicate with the server + + + + org.teavm + teavm-classlib + ${project.version} + + + org.teavm + teavm-jso + ${project.version} + + + org.teavm + teavm-dom + ${project.version} + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + + + + maven-war-plugin + 2.4 + + + + ${project.build.directory}/generated/js + + + + + + org.teavm + teavm-maven-plugin + ${project.version} + + + web-client + prepare-package + + build-javascript + + + ${project.build.directory}/generated/js/teavm + org.teavm.samples.hello.Client + SEPARATE + true + true + true + true + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ../../checkstyle.xml + config_loc=${basedir}/../.. + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-hello/src/main/java/org/teavm/samples/hello/Client.java b/teavm-samples/teavm-samples-hello/src/main/java/org/teavm/samples/hello/Client.java new file mode 100644 index 000000000..425bac1b2 --- /dev/null +++ b/teavm-samples/teavm-samples-hello/src/main/java/org/teavm/samples/hello/Client.java @@ -0,0 +1,68 @@ +/* + * 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.samples.hello; + +import org.teavm.dom.ajax.ReadyStateChangeHandler; +import org.teavm.dom.ajax.XMLHttpRequest; +import org.teavm.dom.browser.Window; +import org.teavm.dom.events.Event; +import org.teavm.dom.events.EventListener; +import org.teavm.dom.html.HTMLButtonElement; +import org.teavm.dom.html.HTMLDocument; +import org.teavm.dom.html.HTMLElement; +import org.teavm.jso.JS; + +public final class Client { + private static Window window = (Window)JS.getGlobal(); + private static HTMLDocument document = window.getDocument(); + private static HTMLButtonElement helloButton = (HTMLButtonElement)document.getElementById("hello-button"); + private static HTMLElement responsePanel = document.getElementById("response-panel"); + private static HTMLElement thinkingPanel = document.getElementById("thinking-panel"); + + private Client() { + } + + public static void main(String[] args) { + helloButton.addEventListener("click", new EventListener() { + @Override public void handleEvent(Event evt) { + sayHello(); + } + }); + } + + private static void sayHello() { + helloButton.setDisabled(true); + thinkingPanel.getStyle().setProperty("display", ""); + final XMLHttpRequest xhr = window.createXMLHttpRequest(); + xhr.setOnReadyStateChange(new ReadyStateChangeHandler() { + @Override public void stateChanged() { + if (xhr.getReadyState() == XMLHttpRequest.DONE) { + receiveResponse(xhr.getResponseText()); + } + } + }); + xhr.open("GET", "hello"); + xhr.send(); + } + + private static void receiveResponse(String text) { + HTMLElement responseElem = document.createElement("div"); + responseElem.appendChild(document.createTextNode(text)); + responsePanel.appendChild(responseElem); + helloButton.setDisabled(false); + thinkingPanel.getStyle().setProperty("display", "none"); + } +} diff --git a/teavm-samples/teavm-samples-hello/src/main/java/org/teavm/samples/hello/Server.java b/teavm-samples/teavm-samples-hello/src/main/java/org/teavm/samples/hello/Server.java new file mode 100644 index 000000000..aa5635776 --- /dev/null +++ b/teavm-samples/teavm-samples-hello/src/main/java/org/teavm/samples/hello/Server.java @@ -0,0 +1,39 @@ +/* + * 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.samples.hello; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet("/hello") +public class Server extends HttpServlet { + private static final long serialVersionUID = -5014505771271825585L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + return; + } + String userAgent = req.getHeader("User-Agent"); + resp.getWriter().println("Hello, " + userAgent); + } +} diff --git a/teavm-samples/teavm-samples-hello/src/main/webapp/WEB-INF/web.xml b/teavm-samples/teavm-samples-hello/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..bfc410b12 --- /dev/null +++ b/teavm-samples/teavm-samples-hello/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-hello/src/main/webapp/index.html b/teavm-samples/teavm-samples-hello/src/main/webapp/index.html new file mode 100644 index 000000000..dc0c2a474 --- /dev/null +++ b/teavm-samples/teavm-samples-hello/src/main/webapp/index.html @@ -0,0 +1,31 @@ + + + + + Hello web application + + + + + +

Hello web application

+ +
+
+ + + \ No newline at end of file diff --git a/teavm-scala-samples/pom.xml b/teavm-scala-samples/pom.xml deleted file mode 100644 index bc32acdad..000000000 --- a/teavm-scala-samples/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - 4.0.0 - - - org.teavm - teavm - 0.2-SNAPSHOT - - teavm-scala-samples - - - - org.teavm - teavm-core - ${project.version} - - - org.teavm - teavm-dom - ${project.version} - - - - - src/main/scala - src/test/scala - - - net.alchim31.maven - scala-maven-plugin - 3.1.6 - - - - compile - testCompile - - - - - 2.10.0 - - - - org.teavm - teavm-maven-plugin - ${project.version} - - - org.teavm - teavm-classlib - ${project.version} - - - org.scala-lang - scala-library - 2.10.0 - - - - - generate-hello - - build-javascript - - process-classes - - false - org.teavm.scala.samples.HelloWorld - true - ${project.build.directory}/javascript - - - - - - - \ No newline at end of file diff --git a/teavm-scala-samples/src/main/scala/org/teavm/scala/samples/HelloWorld.scala b/teavm-scala-samples/src/main/scala/org/teavm/scala/samples/HelloWorld.scala deleted file mode 100644 index 5d50c2bbd..000000000 --- a/teavm-scala-samples/src/main/scala/org/teavm/scala/samples/HelloWorld.scala +++ /dev/null @@ -1,11 +0,0 @@ -package org.teavm.scala.samples - -/** - * - * @author Alexey Andreev - */ -object HelloWorld { - def main(args : Array[String]) { - print("Hello") - } -} \ No newline at end of file