mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Add Scala example
This commit is contained in:
parent
97bdd35617
commit
3b8b819c48
|
@ -640,8 +640,10 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
||||||
try {
|
try {
|
||||||
IContainer container = (IContainer)workspaceRoot.findMember(
|
IContainer container = (IContainer)workspaceRoot.findMember(
|
||||||
depJavaProject.getOutputLocation());
|
depJavaProject.getOutputLocation());
|
||||||
|
if (container != null) {
|
||||||
collector.addPath(container.getLocation());
|
collector.addPath(container.getLocation());
|
||||||
binCollector.addContainer(container);
|
binCollector.addContainer(container);
|
||||||
|
}
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
TeaVMEclipsePlugin.logError(e);
|
TeaVMEclipsePlugin.logError(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,5 +36,6 @@
|
||||||
<module>teavm-samples-video</module>
|
<module>teavm-samples-video</module>
|
||||||
<module>teavm-samples-async</module>
|
<module>teavm-samples-async</module>
|
||||||
<module>teavm-samples-kotlin</module>
|
<module>teavm-samples-kotlin</module>
|
||||||
|
<module>teavm-samples-scala</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
4
teavm-samples/teavm-samples-scala/.gitignore
vendored
Normal file
4
teavm-samples/teavm-samples-scala/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/target/
|
||||||
|
/.settings/
|
||||||
|
/.classpath
|
||||||
|
/.project
|
108
teavm-samples/teavm-samples-scala/pom.xml
Normal file
108
teavm-samples/teavm-samples-scala/pom.xml
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-samples</artifactId>
|
||||||
|
<version>0.4.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<artifactId>teavm-samples-scala</artifactId>
|
||||||
|
|
||||||
|
<name>TeaVM Scala example</name>
|
||||||
|
<description>A sample application written in Scala.</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<teavm.version>0.4.0-SNAPSHOT</teavm.version>
|
||||||
|
<scala.version>2.11.7</scala.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-classlib</artifactId>
|
||||||
|
<version>${teavm.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-jso</artifactId>
|
||||||
|
<version>${teavm.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scala-lang</groupId>
|
||||||
|
<artifactId>scala-library</artifactId>
|
||||||
|
<version>${scala.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<sourceDirectory>src/main/scala</sourceDirectory>
|
||||||
|
<testSourceDirectory>src/test/scala</testSourceDirectory>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.alchim31.maven</groupId>
|
||||||
|
<artifactId>scala-maven-plugin</artifactId>
|
||||||
|
<version>3.2.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<scalaVersion>${scala.version}</scalaVersion>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-maven-plugin</artifactId>
|
||||||
|
<version>${teavm.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>web-client</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>build-javascript</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>
|
||||||
|
<mainClass>org.teavm.samples.scala.Client</mainClass>
|
||||||
|
<runtime>SEPARATE</runtime>
|
||||||
|
<minifying>false</minifying>
|
||||||
|
<debugInformationGenerated>true</debugInformationGenerated>
|
||||||
|
<sourceMapsGenerated>true</sourceMapsGenerated>
|
||||||
|
<sourceFilesCopied>true</sourceFilesCopied>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
|
<configuration>
|
||||||
|
<webResources>
|
||||||
|
<resource>
|
||||||
|
<directory>${project.build.directory}/generated/js</directory>
|
||||||
|
</resource>
|
||||||
|
</webResources>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,86 @@
|
||||||
|
package org.teavm.samples.scala
|
||||||
|
|
||||||
|
import org.teavm.jso.browser.Window
|
||||||
|
import org.teavm.jso.dom.html._
|
||||||
|
import org.teavm.jso.dom.events._
|
||||||
|
|
||||||
|
object Client extends Grammar {
|
||||||
|
def main(args: Array[String]) {
|
||||||
|
var document = HTMLDocument.current
|
||||||
|
var exprElem = document.getElementById("expr").asInstanceOf[HTMLInputElement]
|
||||||
|
var calcElem = document.getElementById("calculate")
|
||||||
|
var resultList = document.getElementById("result-list");
|
||||||
|
calcElem.addEventListener("click", new EventListener[MouseEvent]() {
|
||||||
|
def handleEvent(e : MouseEvent) {
|
||||||
|
additive.parse(exprElem.getValue().toSeq) match {
|
||||||
|
case (None, _) => Window.alert("Error parsing expression");
|
||||||
|
case (Some(x), Nil) => {
|
||||||
|
val resultElem = document.createElement("div")
|
||||||
|
var exprSpan = document.createElement("span");
|
||||||
|
exprSpan.setAttribute("class", "plan")
|
||||||
|
exprSpan.appendChild(document.createTextNode(print(x) + " = "))
|
||||||
|
var resultSpan = document.createElement("span")
|
||||||
|
resultSpan.setAttribute("class", "result")
|
||||||
|
resultSpan.appendChild(document.createTextNode(eval(x).toString()))
|
||||||
|
resultElem.appendChild(exprSpan)
|
||||||
|
resultElem.appendChild(resultSpan)
|
||||||
|
resultList.insertBefore(resultElem, resultList.getFirstChild)
|
||||||
|
}
|
||||||
|
case (_, err) => Window.alert("Error parsing expression: " + err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
def eval(expr : Expr) : BigInt = expr match {
|
||||||
|
case Add(a, b) => eval(a) + eval(b)
|
||||||
|
case Subtract(a, b) => eval(a) - eval(b)
|
||||||
|
case Multiply(a, b) => eval(a) * eval(b)
|
||||||
|
case Divide(a, b) => eval(a) * eval(b)
|
||||||
|
case Negate(n) => -eval(n)
|
||||||
|
case Number(v) => v
|
||||||
|
}
|
||||||
|
|
||||||
|
def print(expr : Expr) : String = expr match {
|
||||||
|
case Add(a, b) => "(" + print(a) + " + " + print(b) + ")"
|
||||||
|
case Subtract(a, b) => "(" + print(a) + " - " + print(b) + ")"
|
||||||
|
case Multiply(a, b) => "(" + print(a) + " * " + print(b) + ")"
|
||||||
|
case Divide(a, b) => "(" + print(a) + " / " + print(b) + ")"
|
||||||
|
case Negate(n) => "-" + print(n)
|
||||||
|
case Number(v) => v.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
def additive = multiplicative ~ ((keyword("+") | keyword("-")) ~ multiplicative).* >> {
|
||||||
|
case (h, t) => t.foldLeft(h) {
|
||||||
|
case (left, ("+", right)) => Add(left, right)
|
||||||
|
case (left, ("-", right)) => Subtract(left, right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def multiplicative = primitive ~ ((keyword("*") | keyword("/")) ~ primitive).* >> {
|
||||||
|
case (h, t) => t.foldLeft(h) {
|
||||||
|
case (left, ("*", right)) => Multiply(left, right)
|
||||||
|
case (left, ("/", right)) => Divide(left, right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def unary : Rule[Expr] = keyword("-").? ~ primitive >> {
|
||||||
|
case (Some(_), v) => Negate(v)
|
||||||
|
case (None, v) => v
|
||||||
|
}
|
||||||
|
def primitive : Rule[Expr] = Rule.firstOf(number >> Number, group)
|
||||||
|
def group : Rule[Expr] = keyword("(") ~ additive ~ keyword(")") >> { case ((_, result), _) => result }
|
||||||
|
|
||||||
|
def number : Rule[Int] = range('1', '9') ~ range('0', '9').* ~ ws >> {
|
||||||
|
case ((h, t), _) => t.foldLeft(h - '0')((n, c) => n * 10 + (c - '0'))
|
||||||
|
}
|
||||||
|
|
||||||
|
def keyword(str : String) = s(str) ~ ws >> { case (s, _) => s }
|
||||||
|
def ws = s(" ").* >> { case _ => Unit }
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed abstract class Expr
|
||||||
|
case class Number(value : Int) extends Expr
|
||||||
|
case class Add(left : Expr, right : Expr) extends Expr
|
||||||
|
case class Subtract(left : Expr, right : Expr) extends Expr
|
||||||
|
case class Multiply(left : Expr, right : Expr) extends Expr
|
||||||
|
case class Divide(left : Expr, right : Expr) extends Expr
|
||||||
|
case class Negate(argument : Expr) extends Expr
|
|
@ -0,0 +1,112 @@
|
||||||
|
package org.teavm.samples.scala
|
||||||
|
|
||||||
|
trait Grammar {
|
||||||
|
def rule[T](f : Seq[Char] => (Option[T], Seq[Char])) : Rule[T] = Rule.rule(f)
|
||||||
|
def s(str : String) : Rule[String] = Rule.expect(str)
|
||||||
|
def range(first : Char, last : Char) : Rule[Char] = Rule.range(first, last)
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Rule[T] {
|
||||||
|
def parse(chars : Seq[Char]) : (Option[T], Seq[Char])
|
||||||
|
def ~[S](other : Rule[S]) : Rule[(T, S)] = Rule.concat(this, other)
|
||||||
|
def ~(other : => String) : Rule[(T, String)] = Rule.concat(this, Rule.expect(other))
|
||||||
|
def |(other : => Rule[T]) : Rule[T] = Rule.firstOf(this, other)
|
||||||
|
def *() : Rule[List[T]] = Rule.unlimited(this)
|
||||||
|
def >>[S](f : T => S) : Rule[S] = Rule.andThen(this, f)
|
||||||
|
def ?() : Rule[Option[T]] = Rule.optional(this)
|
||||||
|
|
||||||
|
def debug(str : String) = Rule.rule { x =>
|
||||||
|
var (result, rem) = parse(x)
|
||||||
|
println(str + ":" + result + ":" + rem)
|
||||||
|
(result, rem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Rule {
|
||||||
|
def rule[T](f : Seq[Char] => (Option[T], Seq[Char])) : Rule[T] = {
|
||||||
|
new Rule[T]() {
|
||||||
|
def parse(chars : Seq[Char]) : (Option[T], Seq[Char]) = f(chars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def concat[S, T](left : Rule[S], right : => Rule[T]) : Rule[(S, T)] = {
|
||||||
|
lazy val right2 = right
|
||||||
|
rule(chars => {
|
||||||
|
left.parse(chars) match {
|
||||||
|
case (Some(leftResult), rem) => right2.parse(rem) match {
|
||||||
|
case (Some(rightResult), rem2) => (Some((leftResult, rightResult)), rem2)
|
||||||
|
case (None, rem2) => (None, rem)
|
||||||
|
}
|
||||||
|
case (None, rem) => (None, rem)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
def unlimited[T](inner : Rule[T]) : Rule[List[T]] = {
|
||||||
|
def iter(chars : Seq[Char]) : (List[T], Seq[Char]) = {
|
||||||
|
inner.parse(chars) match {
|
||||||
|
case (Some(result), rem) => {
|
||||||
|
val (tail, rem2) = iter(rem)
|
||||||
|
(result :: tail, rem2)
|
||||||
|
}
|
||||||
|
case (None, rem) => (Nil, rem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rule(chars => {
|
||||||
|
val (result, rem) = iter(chars)
|
||||||
|
(Some(result.reverse), rem)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
def firstOf[T](first : Rule[T], second : => Rule[T]) : Rule[T] = {
|
||||||
|
lazy val second2 = second
|
||||||
|
rule(chars => {
|
||||||
|
first.parse(chars) match {
|
||||||
|
case (Some(result), rem) => (Some(result), rem)
|
||||||
|
case (None, _) => second2.parse(chars) match {
|
||||||
|
case (Some(result), rem) => (Some(result), rem)
|
||||||
|
case (None, _) => (None, chars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
def optional[T](inner : Rule[T]) : Rule[Option[T]] = {
|
||||||
|
rule {
|
||||||
|
chars => inner.parse(chars) match {
|
||||||
|
case (Some(result), rem) => (Some(Some(result)), rem)
|
||||||
|
case (None, rem) => (Some(None), chars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
implicit def expect(str : String) : Rule[String] = {
|
||||||
|
def iter(chars : Seq[Char], index : Int) : (Boolean, Seq[Char]) = {
|
||||||
|
if (index == str.length())
|
||||||
|
(true, chars)
|
||||||
|
else chars match {
|
||||||
|
case Seq() => (false, Nil);
|
||||||
|
case c +: tail if c == str.charAt(index) => iter(tail, index + 1)
|
||||||
|
case _ => (false, chars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rule(chars => {
|
||||||
|
val (matched, rem) = iter(chars, 0)
|
||||||
|
(matched match {
|
||||||
|
case true => Some(str)
|
||||||
|
case false => None
|
||||||
|
}, rem)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
def andThen[T, S](inner : Rule[T], f : T => S) : Rule[S] = {
|
||||||
|
rule(chars => {
|
||||||
|
inner.parse(chars) match {
|
||||||
|
case (Some(result), rem) => (Some(f(result)), rem)
|
||||||
|
case (None, rem) => (None, rem)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
def range(first : Char, last : Char) : Rule[Char] = {
|
||||||
|
rule(chars => {
|
||||||
|
chars match {
|
||||||
|
case c +: rem if c >= first && c <= last => (Some(c), rem)
|
||||||
|
case _ => (None, chars)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||||
|
version="3.0">
|
||||||
|
</web-app>
|
|
@ -0,0 +1,65 @@
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
.top {
|
||||||
|
position: static;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 80px;
|
||||||
|
border-bottom-color: rgb(120,120,120);
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
background-color: rgb(230,230,230);
|
||||||
|
}
|
||||||
|
.expr {
|
||||||
|
width: 100%;
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
.calc-panel {
|
||||||
|
margin-right: 80px;
|
||||||
|
}
|
||||||
|
.calculate {
|
||||||
|
float: right;
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
.result-list {
|
||||||
|
position: static;
|
||||||
|
top: 81;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
overflow: auto
|
||||||
|
}
|
||||||
|
.result-list > div {
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
border-bottom-color: rgb(170,170,170);
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-bottom-style: dotted;
|
||||||
|
}
|
||||||
|
.result-list > div > span.result {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.result-list > div:nth-child(1) {
|
||||||
|
color: rgb(0,0,0);
|
||||||
|
}
|
||||||
|
.result-list > div:nth-child(2) {
|
||||||
|
color: rgb(30,30,30);
|
||||||
|
}
|
||||||
|
.result-list > div:nth-child(3) {
|
||||||
|
color: rgb(60,60,60);
|
||||||
|
}
|
||||||
|
.result-list > div:nth-child(4) {
|
||||||
|
color: rgb(90,90,90);
|
||||||
|
}
|
||||||
|
.result-list > div:nth-child(5) {
|
||||||
|
color: rgb(120,120,120);
|
||||||
|
}
|
||||||
|
.result-list > div:nth-child(n+6) {
|
||||||
|
color: rgb(150,150,150);
|
||||||
|
}
|
21
teavm-samples/teavm-samples-scala/src/main/webapp/index.html
Normal file
21
teavm-samples/teavm-samples-scala/src/main/webapp/index.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Hello Scala</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||||
|
<script type="text/javascript" charset="utf-8" src="teavm/runtime.js"></script>
|
||||||
|
<script type="text/javascript" charset="utf-8" src="teavm/classes.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="calculator.css">
|
||||||
|
</head>
|
||||||
|
<body onload="main()">
|
||||||
|
<div class="top">
|
||||||
|
<p>This calculator supports the following operators: + - * /.
|
||||||
|
Also grouping parentheses supported. Example: (4 + 5) * 6</p>
|
||||||
|
<button id="calculate" class="calculate" tabindex="2">Calculate</button>
|
||||||
|
<div class="calc-panel">
|
||||||
|
<input type="text" id="expr" class="expr" tabindex="1"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="result-list" class="result-list"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user