Adds a minimal code to support HelloWorld application

This commit is contained in:
konsoletyper 2013-12-18 15:04:11 +04:00
parent e595ecc5db
commit eb6627c532
32 changed files with 418 additions and 46 deletions

View File

@ -16,6 +16,7 @@
<module>teavm-core</module>
<module>teavm-classlib</module>
<module>teavm-maven-plugin</module>
<module>teavm-samples</module>
</modules>
<build>

View File

@ -20,7 +20,6 @@
<groupId>org.teavm</groupId>
<artifactId>teavm-core</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
</dependencies>

View File

@ -0,0 +1,55 @@
package org.teavm.classlib.impl.charset;
/**
*
* @author Alexey Andreev
*/
public class ByteBuffer {
private byte[] data;
private int end;
private int pos;
public ByteBuffer(byte[] data) {
this(data, 0, data.length);
}
public ByteBuffer(byte[] data, int start, int end) {
this.data = data;
this.end = end;
this.pos = start;
}
public void put(byte b) {
data[pos++] = b;
}
public void rewind(int start) {
this.pos = start;
}
public int available() {
return end - pos;
}
public void back(int count) {
pos -= count;
}
public boolean end() {
return pos == end;
}
public byte get() {
return data[pos++];
}
public int position() {
return pos;
}
public void put(ByteBuffer buffer) {
while (buffer.pos < buffer.end) {
data[pos++] = buffer.data[buffer.pos++];
}
}
}

View File

@ -0,0 +1,55 @@
package org.teavm.classlib.impl.charset;
/**
*
* @author Alexey Andreev
*/
public class CharBuffer {
private char[] data;
private int end;
private int pos;
public CharBuffer(char[] data, int start, int end) {
this.data = data;
this.end = end;
this.pos = start;
}
public CharBuffer(char[] data) {
this(data, 0, data.length);
}
public void put(char b) {
data[pos++] = b;
}
public void rewind(int start) {
this.pos = start;
}
public int available() {
return end - pos;
}
public void back(int count) {
pos -= count;
}
public boolean end() {
return pos == end;
}
public char get() {
return data[pos++];
}
public int position() {
return pos;
}
public void put(CharBuffer buffer) {
while (buffer.pos < buffer.end) {
data[pos++] = buffer.data[buffer.pos++];
}
}
}

View File

@ -5,9 +5,14 @@ package org.teavm.classlib.impl.charset;
* @author Alexey Andreev
*/
public abstract class Charset {
public abstract int encode(int[] buffer, int offset, int length, byte[] dest, int destOffset, int destLength);
public abstract void encode(CharBuffer source, ByteBuffer dest);
public abstract int decode(byte[] buffer, int offset, int length, int[] dest, int destOffset, int destLength);
public abstract void decode(ByteBuffer source, CharBuffer dest);
public static native Charset get(String name);
public static Charset get(String name) {
if (name.equals("UTF-8")) {
return new UTF8Charset();
}
return null;
}
}

View File

@ -1,16 +0,0 @@
package org.teavm.classlib.impl.charset;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author Alexey Andreev
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface CharsetName {
String value();
}

View File

@ -5,10 +5,12 @@ package org.teavm.classlib.impl.charset;
* @author Alexey Andreev
*/
public class UTF16Helper {
public static final int SURROGATE_NEUTRAL_BIT_MASK = 0xF800;
public static final int SURROGATE_BITS = 0xD800;
public static final int SURROGATE_BIT_MASK = 0xFC00;
public static final int SURROGATE_BIT_INV_MASK = 0x03FF;
public static final int HIGH_SURROGATE_BITS = 0xF800;
public static final int LOW_SURROGATE_BITS = 0xF800;
public static final int HIGH_SURROGATE_BITS = 0xD800;
public static final int LOW_SURROGATE_BITS = 0xDC00;
public static final int MEANINGFUL_SURROGATE_BITS = 10;
public static final int SUPPLEMENTARY_PLANE = 0x10000;
@ -34,6 +36,10 @@ public class UTF16Helper {
public static int buildCodePoint(char a, char b) {
return ((a & SURROGATE_BIT_INV_MASK) << MEANINGFUL_SURROGATE_BITS) |
(b & SURROGATE_BIT_INV_MASK) + SUPPLEMENTARY_PLANE;
(b & SURROGATE_BIT_INV_MASK) + SUPPLEMENTARY_PLANE;
}
public static boolean isSurrogate(char c) {
return (c & SURROGATE_NEUTRAL_BIT_MASK) == SURROGATE_BITS;
}
}

View File

@ -4,15 +4,40 @@ package org.teavm.classlib.impl.charset;
*
* @author Alexey Andreev
*/
@CharsetName("UTF-8")
public class UTF8Charset extends Charset {
@Override
public int encode(int[] buffer, int offset, int length, byte[] dest, int destOffset, int destLength) {
return 0;
public void encode(CharBuffer source, ByteBuffer dest) {
while (!source.end() && dest.available() >= 4) {
char ch = source.get();
if (ch < 0x80) {
dest.put((byte)ch);
} else if (ch < 0x400) {
dest.put((byte)(0xC0 | (ch >> 6)));
dest.put((byte)(0x80 | (ch & 0x3F)));
} else if (!UTF16Helper.isSurrogate(ch)) {
dest.put((byte)(0xE0 | (ch >> 12)));
dest.put((byte)(0x80 | ((ch >> 6) & 0x3F)));
dest.put((byte)(0x80 | (ch & 0x3F)));
} else if (UTF16Helper.isHighSurrogate(ch)) {
char low = source.get();
if (!UTF16Helper.isLowSurrogate(ch)) {
source.back(1);
dest.put((byte)'?');
} else {
int codePoint = UTF16Helper.buildCodePoint(ch, low);
dest.put((byte)(0xF0 | (codePoint >> 18)));
dest.put((byte)(0x80 | ((codePoint >> 12) & 0x3F)));
dest.put((byte)(0x80 | ((codePoint >> 6) & 0x3F)));
dest.put((byte)(0x80 | (codePoint & 0x3F)));
}
} else {
dest.put((byte)'?');
}
}
}
@Override
public int decode(byte[] buffer, int offset, int length, int[] dest, int destOffset, int destLength) {
return 0;
public void decode(ByteBuffer source, CharBuffer dest) {
}
}

View File

@ -1,4 +1,4 @@
package org.teavm.classlib.java.lang.io;
package org.teavm.classlib.java.io;
import org.teavm.classlib.java.lang.TAutoCloseable;

View File

@ -1,4 +1,4 @@
package org.teavm.classlib.java.lang.io;
package org.teavm.classlib.java.io;
/**
*

View File

@ -1,4 +1,4 @@
package org.teavm.classlib.java.lang.io;
package org.teavm.classlib.java.io;
import org.teavm.classlib.java.lang.TException;
import org.teavm.classlib.java.lang.TString;

View File

@ -1,4 +1,4 @@
package org.teavm.classlib.java.lang.io;
package org.teavm.classlib.java.io;
import org.teavm.classlib.java.lang.TObject;

View File

@ -1,6 +1,10 @@
package org.teavm.classlib.java.lang.io;
package org.teavm.classlib.java.io;
import org.teavm.classlib.impl.charset.ByteBuffer;
import org.teavm.classlib.impl.charset.CharBuffer;
import org.teavm.classlib.impl.charset.Charset;
import org.teavm.classlib.java.lang.TMath;
import org.teavm.classlib.java.lang.TString;
import org.teavm.classlib.java.lang.TStringBuilder;
/**
@ -12,10 +16,21 @@ public class TPrintStream extends TFilterOutputStream {
private boolean errorState;
private TStringBuilder sb = new TStringBuilder();
private char[] buffer = new char[32];
private Charset charset;
public TPrintStream(TOutputStream out, boolean autoFlush, TString encoding) throws TUnsupportedEncodingException {
super(out);
this.autoFlush = autoFlush;
charset = Charset.get(encoding.toString());
if (charset == null) {
throw new TUnsupportedEncodingException(TString.wrap("Unsupported encoding: ").concat(encoding));
}
}
public TPrintStream(TOutputStream out, boolean autoFlush) {
super(out);
this.autoFlush = autoFlush;
this.charset = Charset.get("UTF-8");
}
public TPrintStream(TOutputStream out) {
@ -100,7 +115,14 @@ public class TPrintStream extends TFilterOutputStream {
}
private void print(char[] s, int begin, int end) {
int[] codePoints = new int[TMath.min(s.length, 4096)];
CharBuffer src = new CharBuffer(s, begin, end);
byte[] destBytes = new byte[TMath.max(16, TMath.min(s.length, 1024))];
ByteBuffer dest = new ByteBuffer(new byte[TMath.max(16, TMath.min(s.length, 1024))]);
while (!src.end()) {
charset.encode(src, dest);
write(destBytes, 0, dest.position());
dest.rewind(0);
}
}
public void print(char c) {
@ -113,6 +135,20 @@ public class TPrintStream extends TFilterOutputStream {
printSB();
}
public void print(TString s) {
sb.append(s).append('\n');
printSB();
}
public void println(TString s) {
sb.append(s);
printSB();
}
public void println() {
print('\n');
}
private void printSB() {
char[] buffer = sb.length() > this.buffer.length ? new char[sb.length()] : this.buffer;
sb.getChars(0, sb.length(), buffer, 0);

View File

@ -1,4 +1,4 @@
package org.teavm.classlib.java.lang.io;
package org.teavm.classlib.java.io;
/**
*

View File

@ -0,0 +1,19 @@
package org.teavm.classlib.java.io;
import org.teavm.classlib.java.lang.TString;
/**
*
* @author Alexey Andreev
*/
public class TUnsupportedEncodingException extends TIOException {
private static final long serialVersionUID = 2403781130729330252L;
public TUnsupportedEncodingException() {
super();
}
public TUnsupportedEncodingException(TString message) {
super(message);
}
}

View File

@ -0,0 +1,26 @@
package org.teavm.classlib.java.lang;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class ConsoleOutputStreamGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
if (methodRef.getClassName().endsWith("_stderr")) {
if (methodRef.getName().equals("write")) {
writer.append("$rt_putStderr(").append(context.getParameterName(1)).append(");").softNewLine();
}
} else if (methodRef.getClassName().endsWith("_stdout")) {
if (methodRef.getName().equals("write")) {
writer.append("$rt_putStdout(").append(context.getParameterName(1)).append(");").softNewLine();
}
}
}
}

View File

@ -1,7 +1,7 @@
package org.teavm.classlib.java.lang;
import org.teavm.classlib.impl.charset.UTF16Helper;
import org.teavm.classlib.java.lang.io.TSerializable;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.util.TArrays;
import org.teavm.javascript.ni.Remove;
import org.teavm.javascript.ni.Rename;

View File

@ -0,0 +1,15 @@
package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TIOException;
import org.teavm.classlib.java.io.TOutputStream;
import org.teavm.javascript.ni.GeneratedBy;
/**
*
* @author Alexey Andreev
*/
class TConsoleOutputStream_stderr extends TOutputStream {
@Override
@GeneratedBy(ConsoleOutputStreamGenerator.class)
public native void write(int b) throws TIOException;
}

View File

@ -0,0 +1,15 @@
package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TIOException;
import org.teavm.classlib.java.io.TOutputStream;
import org.teavm.javascript.ni.GeneratedBy;
/**
*
* @author Alexey Andreev
*/
class TConsoleOutputStream_stdout extends TOutputStream {
@Override
@GeneratedBy(ConsoleOutputStreamGenerator.class)
public native void write(int b) throws TIOException;
}

View File

@ -1,7 +1,7 @@
package org.teavm.classlib.java.lang;
import org.teavm.classlib.impl.charset.UTF16Helper;
import org.teavm.classlib.java.lang.io.TSerializable;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.Rename;

View File

@ -1,5 +1,6 @@
package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TPrintStream;
import org.teavm.classlib.java.lang.reflect.TArray;
import org.teavm.javascript.ni.GeneratedBy;
@ -8,6 +9,9 @@ import org.teavm.javascript.ni.GeneratedBy;
* @author Alexey Andreev
*/
public final class TSystem extends TObject {
public static final TPrintStream out = new TPrintStream(new TConsoleOutputStream_stdout(), false);
public static final TPrintStream err = new TPrintStream(new TConsoleOutputStream_stderr(), false);
private TSystem() {
}

View File

@ -68,7 +68,7 @@ public class TThrowable extends RuntimeException {
@Rename("getLocalizedMessage")
public TString getLocalizedMessage0() {
return getMessage0();
return TString.wrap(getMessage());
}
@Override

View File

@ -111,7 +111,7 @@ public class JavascriptBuilder {
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Platform does not support UTF-8", e);
} catch (IOException e) {
throw new RenderingException();
throw new RenderingException("IO error occured", e);
}
}
}

View File

@ -79,7 +79,7 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder> {
int index = name.lastIndexOf('.');
String className = name.substring(index + 1);
String packageName = name.substring(0, index);
ClassHolder classHolder = innerMapper.map(transformation.packagePrefix + "." + packageName +
ClassHolder classHolder = innerMapper.map(transformation.packagePrefix + packageName +
"." + transformation.classPrefix + className);
if (classHolder != null) {
classHolder = renamer.rename(classHolder);

View File

@ -18,7 +18,7 @@ public class Parser {
MethodHolder method = new MethodHolder(node.name, signature);
parseModifiers(node.access, method);
ProgramParser programParser = new ProgramParser();
Program program = programParser.parser(node);
Program program = programParser.parse(node);
new UnreachableBasicBlockEliminator().optimize(program);
SSATransformer ssaProducer = new SSATransformer();
ssaProducer.transformToSSA(program, method.getParameterTypes());

View File

@ -53,7 +53,7 @@ public class ProgramParser {
}
}
public Program parser(MethodNode method) {
public Program parse(MethodNode method) {
program = new Program();
InsnList instructions = method.instructions;
if (instructions.size() == 0) {
@ -61,7 +61,11 @@ public class ProgramParser {
}
prepare(method);
prepareParameters(method);
program.createBasicBlock();
getBasicBlock(0);
JumpInstruction insn = new JumpInstruction();
insn.setTarget(program.basicBlockAt(1));
program.basicBlockAt(0).getInstructions().add(insn);
doAnalyze(method);
assemble();
return program;

View File

@ -248,6 +248,28 @@ $rt_methodStubs = function(clinit, names) {
})(names[i]);
}
}
$rt_stdoutBuffer = "";
$rt_putStdout = function(ch) {
if (ch == '\n') {
if (console) {
console.info($rt_stdoutBuffer);
}
$rt_stdoutBuffer = "";
} else {
$rt_stdoutBuffer += String.fromCharCode(ch);
}
}
$rt_stderrBuffer = "";
$rt_putStderr = function(ch) {
if (ch == '\n') {
if (console) {
console.info($rt_stderrBuffer);
}
$rt_stderrBuffer = "";
} else {
$rt_stderrBuffer += String.fromCharCode(ch);
}
}
Long = function(lo, hi) {
this.lo = lo | 0;

View File

@ -12,6 +12,7 @@ import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.teavm.javascript.JavascriptBuilder;
import org.teavm.model.MethodDescriptor;
@ -22,7 +23,8 @@ import org.teavm.model.ValueType;
*
* @author Alexey Andreev
*/
@Mojo(name = "build-javascript")
@Mojo(name = "build-javascript", requiresDependencyResolution = ResolutionScope.COMPILE,
requiresDependencyCollection = ResolutionScope.COMPILE)
public class BuildJavascriptMojo extends AbstractMojo {
private static Set<String> compileScopes = new HashSet<>(Arrays.asList(
Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_SYSTEM));
@ -70,6 +72,7 @@ public class BuildJavascriptMojo extends AbstractMojo {
ValueType.object("java.lang.String")), ValueType.VOID);
builder.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
.withValue(1, "java.lang.String");
targetFile.getParentFile().mkdirs();
builder.build(targetFile);
log.info("JavaScript file successfully built");
} catch (RuntimeException e) {
@ -94,9 +97,13 @@ public class BuildJavascriptMojo extends AbstractMojo {
classpath.append(file.getPath());
urls.add(file.toURI().toURL());
}
log.info("Using the following classpath for JavaScript generation: " + classpath);
if (classpath.length() > 0) {
classpath.append(':');
}
classpath.append(classFiles.getPath());
urls.add(classFiles.toURI().toURL());
return new URLClassLoader(urls.toArray(new URL[urls.size()]));
log.info("Using the following classpath for JavaScript generation: " + classpath);
return new URLClassLoader(urls.toArray(new URL[urls.size()]), BuildJavascriptMojo.class.getClassLoader());
} catch (MalformedURLException e) {
throw new MojoExecutionException("Error gathering classpath information", e);
}

4
teavm-samples/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/target
/.settings
/.classpath
/.project

79
teavm-samples/pom.xml Normal file
View File

@ -0,0 +1,79 @@
<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</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>teavm-samples</artifactId>
<dependencies>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-classlib</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.teavm</groupId>
<artifactId>teavm-maven-plugin</artifactId>
<version>${project.version}</version>
<dependencies>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>generate-javascript</id>
<goals>
<goal>build-javascript</goal>
</goals>
<phase>process-classes</phase>
<configuration>
<minifiying>false</minifiying>
<mainClass>org.teavm.samples.HelloWorld</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings only.
It has no influence on the Maven build itself.-->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.teavm</groupId>
<artifactId>teavm-maven-plugin</artifactId>
<versionRange>[0.0.1-SNAPSHOT,)</versionRange>
<goals>
<goal>build-javascript</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,11 @@
package org.teavm.samples;
/**
*
* @author Alexey Andreev
*/
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}