mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Adds JavascriptBuilder - a facade for building whole JavaScript files
This commit is contained in:
parent
a736359a07
commit
e5cb7a20d3
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
|
@ -11,7 +12,8 @@ import org.teavm.model.MethodReference;
|
||||||
*/
|
*/
|
||||||
public class ClassNativeGenerator implements Generator {
|
public class ClassNativeGenerator implements Generator {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||||
|
throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "isInstance":
|
case "isInstance":
|
||||||
generateIsInstance(context, writer);
|
generateIsInstance(context, writer);
|
||||||
|
@ -25,17 +27,17 @@ public class ClassNativeGenerator implements Generator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateIsInstance(GeneratorContext context, SourceWriter writer) {
|
private void generateIsInstance(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append("return $rt_isInstance(").append(context.getParameterName(1)).append(", ")
|
writer.append("return $rt_isInstance(").append(context.getParameterName(1)).append(", ")
|
||||||
.append(context.getParameterName(0)).append(".$data);").softNewLine();
|
.append(context.getParameterName(0)).append(".$data);").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateIsAssignableFrom(GeneratorContext context, SourceWriter writer) {
|
private void generateIsAssignableFrom(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append("return $rt_isAssignable(").append(context.getParameterName(1)).append(".$data, ")
|
writer.append("return $rt_isAssignable(").append(context.getParameterName(1)).append(".$data, ")
|
||||||
.append(context.getParameterName(0)).append(".$data;").softNewLine();
|
.append(context.getParameterName(0)).append(".$data;").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateGetComponentType(GeneratorContext context, SourceWriter writer) {
|
private void generateGetComponentType(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
String thisArg = context.getParameterName(0);
|
String thisArg = context.getParameterName(0);
|
||||||
writer.append("var item = " + thisArg + ".$data.$meta.item;").softNewLine();
|
writer.append("var item = " + thisArg + ".$data.$meta.item;").softNewLine();
|
||||||
writer.append("return item != null ? $rt_cls(item) : null;").softNewLine();
|
writer.append("return item != null ? $rt_cls(item) : null;").softNewLine();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
|
@ -11,7 +12,7 @@ import org.teavm.model.MethodReference;
|
||||||
*/
|
*/
|
||||||
public class FloatNativeGenerator implements Generator {
|
public class FloatNativeGenerator implements Generator {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "isNaN":
|
case "isNaN":
|
||||||
generateIsNaN(context, writer);
|
generateIsNaN(context, writer);
|
||||||
|
@ -22,12 +23,12 @@ public class FloatNativeGenerator implements Generator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateIsNaN(GeneratorContext context, SourceWriter writer) {
|
private void generateIsNaN(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append("return (isNaN(").append(context.getParameterName(1)).append(")").ws().append("?")
|
writer.append("return (isNaN(").append(context.getParameterName(1)).append(")").ws().append("?")
|
||||||
.ws().append("1").ws().append(":").ws().append("0").ws().append(");").softNewLine();
|
.ws().append("1").ws().append(":").ws().append("0").ws().append(");").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateIsInfinite(GeneratorContext context, SourceWriter writer) {
|
private void generateIsInfinite(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append("return (isFinite(").append(context.getParameterName(1)).append(")").ws().append("?")
|
writer.append("return (isFinite(").append(context.getParameterName(1)).append(")").ws().append("?")
|
||||||
.ws().append("0").ws().append(":").ws().append("1").append(");").softNewLine();
|
.ws().append("0").ws().append(":").ws().append("1").append(");").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.dependency.DependencyChecker;
|
import org.teavm.dependency.DependencyChecker;
|
||||||
import org.teavm.dependency.DependencyPlugin;
|
import org.teavm.dependency.DependencyPlugin;
|
||||||
|
@ -16,7 +17,7 @@ import org.teavm.model.ValueType;
|
||||||
*/
|
*/
|
||||||
public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getDescriptor().getName()) {
|
switch (methodRef.getDescriptor().getName()) {
|
||||||
case "<init>":
|
case "<init>":
|
||||||
generateInit(context, writer);
|
generateInit(context, writer);
|
||||||
|
@ -51,11 +52,11 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateInit(GeneratorContext context, SourceWriter writer) {
|
private void generateInit(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").softNewLine();
|
writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateGetClass(GeneratorContext context, SourceWriter writer) {
|
private void generateGetClass(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
String thisArg = context.getParameterName(0);
|
String thisArg = context.getParameterName(0);
|
||||||
writer.append("return $rt_cls(").append(thisArg).append(".$class);").softNewLine();
|
writer.append("return $rt_cls(").append(thisArg).append(".$class);").softNewLine();
|
||||||
}
|
}
|
||||||
|
@ -68,11 +69,11 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
checker.attachMethodGraph(method).getResultNode().propagate("java.lang.Class");
|
checker.attachMethodGraph(method).getResultNode().propagate("java.lang.Class");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateHashCode(GeneratorContext context, SourceWriter writer) {
|
private void generateHashCode(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append("return ").append(context.getParameterName(0)).append(".$id;").softNewLine();
|
writer.append("return ").append(context.getParameterName(0)).append(".$id;").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateClone(GeneratorContext context, SourceWriter writer) {
|
private void generateClone(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append("var copy = new ").append(context.getParameterName(0)).append(".$class();").softNewLine();
|
writer.append("var copy = new ").append(context.getParameterName(0)).append(".$class();").softNewLine();
|
||||||
writer.append("for (var field in obj) {").softNewLine().indent();
|
writer.append("for (var field in obj) {").softNewLine().indent();
|
||||||
writer.append("if (!obj.hasOwnProperty(field)) {").softNewLine().indent();
|
writer.append("if (!obj.hasOwnProperty(field)) {").softNewLine().indent();
|
||||||
|
@ -86,7 +87,7 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
graph.getVariableNode(0).connect(graph.getResultNode());
|
graph.getVariableNode(0).connect(graph.getResultNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateWrap(GeneratorContext context, SourceWriter writer) {
|
private void generateWrap(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append("return ").append(context.getParameterName(1)).append(";").softNewLine();
|
writer.append("return ").append(context.getParameterName(1)).append(";").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
|
@ -11,7 +12,7 @@ import org.teavm.model.MethodReference;
|
||||||
*/
|
*/
|
||||||
public class StringNativeGenerator implements Generator {
|
public class StringNativeGenerator implements Generator {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "wrap":
|
case "wrap":
|
||||||
generateWrap(context, writer);
|
generateWrap(context, writer);
|
||||||
|
@ -19,7 +20,7 @@ public class StringNativeGenerator implements Generator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateWrap(GeneratorContext context, SourceWriter writer) {
|
private void generateWrap(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
writer.append("return ").append(context.getParameterName(1)).softNewLine();
|
writer.append("return ").append(context.getParameterName(1)).softNewLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.dependency.DependencyChecker;
|
import org.teavm.dependency.DependencyChecker;
|
||||||
import org.teavm.dependency.DependencyNode;
|
import org.teavm.dependency.DependencyNode;
|
||||||
|
@ -15,7 +16,7 @@ import org.teavm.model.MethodReference;
|
||||||
*/
|
*/
|
||||||
public class SystemNativeGenerator implements Generator, DependencyPlugin {
|
public class SystemNativeGenerator implements Generator, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "doArrayCopy":
|
case "doArrayCopy":
|
||||||
generateArrayCopy(context, writer);
|
generateArrayCopy(context, writer);
|
||||||
|
@ -32,7 +33,7 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateArrayCopy(GeneratorContext context, SourceWriter writer) {
|
private void generateArrayCopy(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
String src = context.getParameterName(1);
|
String src = context.getParameterName(1);
|
||||||
String srcPos = context.getParameterName(2);
|
String srcPos = context.getParameterName(2);
|
||||||
String dest = context.getParameterName(3);
|
String dest = context.getParameterName(3);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.classlib.java.lang.reflect;
|
package org.teavm.classlib.java.lang.reflect;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.dependency.DependencyChecker;
|
import org.teavm.dependency.DependencyChecker;
|
||||||
import org.teavm.dependency.DependencyConsumer;
|
import org.teavm.dependency.DependencyConsumer;
|
||||||
|
@ -24,7 +25,7 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "getLength":
|
case "getLength":
|
||||||
generateGetLength(context, writer);
|
generateGetLength(context, writer);
|
||||||
|
@ -32,7 +33,7 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateGetLength(GeneratorContext context, SourceWriter writer) {
|
private void generateGetLength(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
String array = context.getParameterName(1);
|
String array = context.getParameterName(1);
|
||||||
writer.append("if (" + array + " === null || " + array + " .$class.$meta.item === undefined) {")
|
writer.append("if (" + array + " === null || " + array + " .$class.$meta.item === undefined) {")
|
||||||
.softNewLine().indent();
|
.softNewLine().indent();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.classlib.org.junit;
|
package org.teavm.classlib.org.junit;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
|
@ -11,7 +12,8 @@ import org.teavm.model.MethodReference;
|
||||||
*/
|
*/
|
||||||
public class AssertNativeGenerator implements Generator {
|
public class AssertNativeGenerator implements Generator {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||||
|
throws IOException {
|
||||||
switch (methodRef.getDescriptor().getName()) {
|
switch (methodRef.getDescriptor().getName()) {
|
||||||
case "fail":
|
case "fail":
|
||||||
generateFail(writer);
|
generateFail(writer);
|
||||||
|
@ -19,7 +21,7 @@ public class AssertNativeGenerator implements Generator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateFail(SourceWriter writer) {
|
private void generateFail(SourceWriter writer) throws IOException {
|
||||||
writer.append("throw new Error();").newLine();
|
writer.append("throw new Error();").newLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
package org.teavm.classlibgen;
|
package org.teavm.classlibgen;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.teavm.codegen.*;
|
import org.teavm.javascript.JavascriptBuilder;
|
||||||
import org.teavm.dependency.DependencyChecker;
|
|
||||||
import org.teavm.javascript.Decompiler;
|
|
||||||
import org.teavm.javascript.Renderer;
|
|
||||||
import org.teavm.javascript.ast.ClassNode;
|
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.resource.ClasspathClassHolderSource;
|
import org.teavm.model.resource.ClasspathClassHolderSource;
|
||||||
import org.teavm.optimization.ClassSetOptimizer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -19,11 +17,6 @@ import org.teavm.optimization.ClassSetOptimizer;
|
||||||
public class ClasslibTestGenerator {
|
public class ClasslibTestGenerator {
|
||||||
private static File outputDir;
|
private static File outputDir;
|
||||||
private static ClasspathClassHolderSource classSource;
|
private static ClasspathClassHolderSource classSource;
|
||||||
private static Decompiler decompiler;
|
|
||||||
private static AliasProvider aliasProvider;
|
|
||||||
private static DefaultNamingStrategy naming;
|
|
||||||
private static SourceWriter writer;
|
|
||||||
private static Renderer renderer;
|
|
||||||
private static List<MethodReference> testMethods = new ArrayList<>();
|
private static List<MethodReference> testMethods = new ArrayList<>();
|
||||||
private static Map<String, List<MethodReference>> groupedMethods = new HashMap<>();
|
private static Map<String, List<MethodReference>> groupedMethods = new HashMap<>();
|
||||||
private static Map<MethodReference, String> fileNames = new HashMap<>();
|
private static Map<MethodReference, String> fileNames = new HashMap<>();
|
||||||
|
@ -90,46 +83,19 @@ public class ClasslibTestGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void decompileClassesForTest(MethodReference methodRef, String targetName) throws IOException {
|
private static void decompileClassesForTest(MethodReference methodRef, String targetName) throws IOException {
|
||||||
classSource = new ClasspathClassHolderSource();
|
JavascriptBuilder builder = new JavascriptBuilder();
|
||||||
decompiler = new Decompiler(classSource);
|
builder.setMinifying(true);
|
||||||
aliasProvider = new DefaultAliasProvider();
|
@SuppressWarnings("resource")
|
||||||
naming = new DefaultNamingStrategy(aliasProvider, classSource);
|
Writer innerWriter = new OutputStreamWriter(new FileOutputStream(new File(outputDir, targetName)), "UTF-8");
|
||||||
naming.setMinifying(false);
|
|
||||||
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
|
||||||
builder.setMinified(false);
|
|
||||||
writer = builder.build();
|
|
||||||
renderer = new Renderer(writer, classSource);
|
|
||||||
renderer.renderRuntime();
|
|
||||||
DependencyChecker dependencyChecker = new DependencyChecker(classSource);
|
|
||||||
MethodReference cons = new MethodReference(methodRef.getClassName(),
|
MethodReference cons = new MethodReference(methodRef.getClassName(),
|
||||||
new MethodDescriptor("<init>", ValueType.VOID));
|
new MethodDescriptor("<init>", ValueType.VOID));
|
||||||
dependencyChecker.addEntryPoint(cons);
|
builder.entryPoint("initInstance", cons);
|
||||||
dependencyChecker.addEntryPoint(methodRef);
|
builder.entryPoint("runTest", methodRef).withValue(0, cons.getClassName());
|
||||||
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.Class", new MethodDescriptor("createNew",
|
builder.exportType("TestClass", cons.getClassName());
|
||||||
ValueType.object("java.lang.Class"))));
|
builder.build(innerWriter);
|
||||||
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.String", new MethodDescriptor("<init>",
|
innerWriter.append("\n");
|
||||||
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)));
|
innerWriter.append("\nJUnitClient.run();");
|
||||||
dependencyChecker.checkDependencies();
|
innerWriter.close();
|
||||||
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
|
||||||
ClassSetOptimizer optimizer = new ClassSetOptimizer();
|
|
||||||
optimizer.optimizeAll(classSet);
|
|
||||||
renderer.renderRuntime();
|
|
||||||
decompileClasses(classSet.getClassNames());
|
|
||||||
writer.append("JUnitClient.run(function() {").softNewLine().indent();
|
|
||||||
writer.append("var testObj = ").appendClass(methodRef.getClassName()).append(".")
|
|
||||||
.appendMethod(cons).append("();").softNewLine();
|
|
||||||
writer.append("testObj.").appendMethod(methodRef).append("();").softNewLine();
|
|
||||||
writer.outdent().append("});").newLine();
|
|
||||||
try (Writer out = new OutputStreamWriter(new FileOutputStream(new File(outputDir, targetName)), "UTF-8")) {
|
|
||||||
out.write(writer.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void decompileClasses(Collection<String> classNames) {
|
|
||||||
List<ClassNode> clsNodes = decompiler.decompile(classNames);
|
|
||||||
for (ClassNode clsNode : clsNodes) {
|
|
||||||
renderer.render(clsNode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void findTests(ClassHolder cls) {
|
private static void findTests(ClassHolder cls) {
|
||||||
|
|
|
@ -182,12 +182,14 @@ JUnitServer.prototype.createFooter = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
JUnitClient = {};
|
JUnitClient = {};
|
||||||
JUnitClient.run = function(runner) {
|
JUnitClient.run = function() {
|
||||||
var handler = window.addEventListener("message", function() {
|
var handler = window.addEventListener("message", function() {
|
||||||
window.removeEventListener("message", handler);
|
window.removeEventListener("message", handler);
|
||||||
var message = {};
|
var message = {};
|
||||||
try {
|
try {
|
||||||
runner();
|
var instance = new TestClass();
|
||||||
|
initInstance(instance);
|
||||||
|
runTest(instance);
|
||||||
message.status = "ok";
|
message.status = "ok";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
message.status = "exception";
|
message.status = "exception";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.codegen;
|
package org.teavm.codegen;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
@ -7,87 +8,98 @@ import org.teavm.model.MethodReference;
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class SourceWriter {
|
public class SourceWriter implements Appendable {
|
||||||
private StringBuilder sb = new StringBuilder();
|
private Appendable innerWriter;
|
||||||
private int indentSize = 0;
|
private int indentSize = 0;
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
private boolean lineStart;
|
private boolean lineStart;
|
||||||
private boolean minified;
|
private boolean minified;
|
||||||
|
|
||||||
SourceWriter(NamingStrategy naming) {
|
SourceWriter(NamingStrategy naming, Appendable innerWriter) {
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
|
this.innerWriter = innerWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMinified(boolean minified) {
|
void setMinified(boolean minified) {
|
||||||
this.minified = minified;
|
this.minified = minified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public SourceWriter append(String value) throws IOException {
|
||||||
sb.setLength(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter append(String value) {
|
|
||||||
appendIndent();
|
appendIndent();
|
||||||
sb.append(value);
|
innerWriter.append(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter append(Object value) {
|
public SourceWriter append(Object value) throws IOException {
|
||||||
return append(String.valueOf(value));
|
return append(String.valueOf(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter append(int value) {
|
public SourceWriter append(int value) throws IOException {
|
||||||
return append(String.valueOf(value));
|
return append(String.valueOf(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter append(char value) {
|
@Override
|
||||||
return append(String.valueOf(value));
|
public SourceWriter append(char value) throws IOException {
|
||||||
|
innerWriter.append(value);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendClass(String cls) throws NamingException {
|
@Override
|
||||||
|
public SourceWriter append(CharSequence csq) throws IOException {
|
||||||
|
innerWriter.append(csq);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter append(CharSequence csq, int start, int end) throws IOException {
|
||||||
|
innerWriter.append(csq, start, end);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceWriter appendClass(String cls) throws NamingException, IOException {
|
||||||
return append(naming.getNameFor(cls));
|
return append(naming.getNameFor(cls));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendField(FieldReference field) throws NamingException {
|
public SourceWriter appendField(FieldReference field) throws NamingException, IOException {
|
||||||
return append(naming.getNameFor(field));
|
return append(naming.getNameFor(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendMethod(MethodReference method) throws NamingException {
|
public SourceWriter appendMethod(MethodReference method) throws NamingException, IOException {
|
||||||
return append(naming.getNameFor(method));
|
return append(naming.getNameFor(method));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendMethodBody(MethodReference method) throws NamingException {
|
public SourceWriter appendMethodBody(MethodReference method) throws NamingException, IOException {
|
||||||
return append(naming.getFullNameFor(method));
|
return append(naming.getFullNameFor(method));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendIndent() {
|
private void appendIndent() throws IOException {
|
||||||
if (minified) {
|
if (minified) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (lineStart) {
|
if (lineStart) {
|
||||||
for (int i = 0; i < indentSize; ++i) {
|
for (int i = 0; i < indentSize; ++i) {
|
||||||
sb.append(" ");
|
innerWriter.append(" ");
|
||||||
}
|
}
|
||||||
lineStart = false;
|
lineStart = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter newLine() {
|
public SourceWriter newLine() throws IOException{
|
||||||
sb.append('\n');
|
innerWriter.append('\n');
|
||||||
lineStart = true;
|
lineStart = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter ws() {
|
public SourceWriter ws() throws IOException{
|
||||||
if (!minified) {
|
if (!minified) {
|
||||||
sb.append(' ');
|
innerWriter.append(' ');
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter softNewLine() {
|
public SourceWriter softNewLine() throws IOException{
|
||||||
if (!minified) {
|
if (!minified) {
|
||||||
sb.append('\n');
|
innerWriter.append('\n');
|
||||||
lineStart = true;
|
lineStart = true;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -106,9 +118,4 @@ public class SourceWriter {
|
||||||
public NamingStrategy getNaming() {
|
public NamingStrategy getNaming() {
|
||||||
return naming;
|
return naming;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.teavm.codegen;
|
package org.teavm.codegen;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
|
@ -21,8 +20,8 @@ public class SourceWriterBuilder {
|
||||||
this.minified = minified;
|
this.minified = minified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter build() {
|
public SourceWriter build(Appendable innerWriter) {
|
||||||
SourceWriter writer = new SourceWriter(naming);
|
SourceWriter writer = new SourceWriter(naming, innerWriter);
|
||||||
writer.setMinified(minified);
|
writer.setMinified(minified);
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.codegen.*;
|
||||||
|
import org.teavm.dependency.DependencyChecker;
|
||||||
|
import org.teavm.javascript.ast.ClassNode;
|
||||||
|
import org.teavm.model.*;
|
||||||
|
import org.teavm.model.resource.ClasspathClassHolderSource;
|
||||||
|
import org.teavm.optimization.ClassSetOptimizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class JavascriptBuilder {
|
||||||
|
private ClassHolderSource classSource;
|
||||||
|
private DependencyChecker dependencyChecker;
|
||||||
|
private boolean minifying = true;
|
||||||
|
private Map<String, JavascriptEntryPoint> entryPoints = new HashMap<>();
|
||||||
|
private Map<String, String> exportedClasses = new HashMap<>();
|
||||||
|
|
||||||
|
public JavascriptBuilder(ClassHolderSource classSource) {
|
||||||
|
this.classSource = classSource;
|
||||||
|
dependencyChecker = new DependencyChecker(classSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavascriptBuilder() {
|
||||||
|
this(new ClasspathClassHolderSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMinifying() {
|
||||||
|
return minifying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinifying(boolean minifying) {
|
||||||
|
this.minifying = minifying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavascriptEntryPoint entryPoint(String name, MethodReference ref) {
|
||||||
|
if (entryPoints.containsKey(name)) {
|
||||||
|
throw new IllegalArgumentException("Entry point with public name `" + name + "' already defined " +
|
||||||
|
"for method " + ref);
|
||||||
|
}
|
||||||
|
JavascriptEntryPoint entryPoint = new JavascriptEntryPoint(name, ref,
|
||||||
|
dependencyChecker.attachMethodGraph(ref));
|
||||||
|
entryPoints.put(name, entryPoint);
|
||||||
|
return entryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportType(String name, String className) {
|
||||||
|
if (exportedClasses.containsKey(name)) {
|
||||||
|
throw new IllegalArgumentException("Class with public name `" + name + "' already defined for class " +
|
||||||
|
className);
|
||||||
|
}
|
||||||
|
exportedClasses.put(name, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassHolderSource getClassSource() {
|
||||||
|
return classSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(Appendable writer) throws RenderingException {
|
||||||
|
Decompiler decompiler = new Decompiler(classSource);
|
||||||
|
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
|
||||||
|
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, classSource);
|
||||||
|
naming.setMinifying(minifying);
|
||||||
|
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
||||||
|
builder.setMinified(minifying);
|
||||||
|
SourceWriter sourceWriter = builder.build(writer);
|
||||||
|
Renderer renderer = new Renderer(sourceWriter, classSource);
|
||||||
|
renderer.renderRuntime();
|
||||||
|
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.Class", new MethodDescriptor("createNew",
|
||||||
|
ValueType.object("java.lang.Class"))));
|
||||||
|
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.String", new MethodDescriptor("<init>",
|
||||||
|
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)));
|
||||||
|
dependencyChecker.checkDependencies();
|
||||||
|
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
||||||
|
ClassSetOptimizer optimizer = new ClassSetOptimizer();
|
||||||
|
optimizer.optimizeAll(classSet);
|
||||||
|
renderer.renderRuntime();
|
||||||
|
List<ClassNode> clsNodes = decompiler.decompile(classSet.getClassNames());
|
||||||
|
for (ClassNode clsNode : clsNodes) {
|
||||||
|
renderer.render(clsNode);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (Map.Entry<String, JavascriptEntryPoint> entry : entryPoints.entrySet()) {
|
||||||
|
sourceWriter.append(entry.getKey()).ws().append("=").ws().appendMethodBody(entry.getValue().reference)
|
||||||
|
.append(";").softNewLine();
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, String> entry : exportedClasses.entrySet()) {
|
||||||
|
sourceWriter.append(entry.getKey()).ws().append("=").ws().appendClass(entry.getValue()).append(";")
|
||||||
|
.softNewLine();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO Error occured", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(File file) throws RenderingException {
|
||||||
|
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
|
||||||
|
build(writer);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException("Platform does not support UTF-8", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import org.teavm.dependency.MethodGraph;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class JavascriptEntryPoint {
|
||||||
|
private String publicName;
|
||||||
|
MethodReference reference;
|
||||||
|
private MethodGraph graph;
|
||||||
|
|
||||||
|
JavascriptEntryPoint(String publicName, MethodReference reference, MethodGraph graph) {
|
||||||
|
this.publicName = publicName;
|
||||||
|
this.reference = reference;
|
||||||
|
this.graph = graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPublicName() {
|
||||||
|
return publicName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavascriptEntryPoint withValue(int argument, String type) {
|
||||||
|
if (argument > reference.parameterCount()) {
|
||||||
|
throw new IllegalArgumentException("Illegal argument #" + argument + " of " + reference.parameterCount());
|
||||||
|
}
|
||||||
|
graph.getVariableNode(argument).propagate(type);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
package org.teavm.javascript;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class JavascriptGenerator {
|
|
||||||
|
|
||||||
}
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.javascript;
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.teavm.codegen.NamingException;
|
import org.teavm.codegen.NamingException;
|
||||||
|
@ -64,10 +65,12 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
renderRuntimeObjcls();
|
renderRuntimeObjcls();
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
throw new RenderingException("Error rendering runtime methods. See a cause for details", e);
|
throw new RenderingException("Error rendering runtime methods. See a cause for details", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRuntimeCls() {
|
private void renderRuntimeCls() throws IOException {
|
||||||
writer.append("$rt_cls").ws().append("=").ws().append("function(clsProto)").ws().append("{")
|
writer.append("$rt_cls").ws().append("=").ws().append("function(clsProto)").ws().append("{")
|
||||||
.indent().softNewLine();
|
.indent().softNewLine();
|
||||||
String classClass = "java.lang.Class";
|
String classClass = "java.lang.Class";
|
||||||
|
@ -98,7 +101,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRuntimeString() {
|
private void renderRuntimeString() throws IOException {
|
||||||
String stringClass = "java.lang.String";
|
String stringClass = "java.lang.String";
|
||||||
MethodReference stringCons = new MethodReference(stringClass, new MethodDescriptor("<init>",
|
MethodReference stringCons = new MethodReference(stringClass, new MethodDescriptor("<init>",
|
||||||
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID));
|
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID));
|
||||||
|
@ -113,7 +116,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRuntimeObjcls() {
|
private void renderRuntimeObjcls() throws IOException {
|
||||||
writer.append("$rt_objcls = function() { return ").appendClass("java.lang.Object").append("; }").newLine();
|
writer.append("$rt_objcls = function() { return ").appendClass("java.lang.Object").append("; }").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +205,8 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
throw new RenderingException("Error rendering class " + cls.getName() + ". See a cause for details", e);
|
throw new RenderingException("Error rendering class " + cls.getName() + ". See a cause for details", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +235,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderInitializer(MethodNode method) {
|
private void renderInitializer(MethodNode method) throws IOException {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
writer.appendClass(ref.getClassName()).append(".").appendMethod(ref).ws().append("=").ws().append("function(");
|
writer.appendClass(ref.getClassName()).append(".").appendMethod(ref).ws().append("=").ws().append("function(");
|
||||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||||
|
@ -254,7 +259,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderDeclaration(MethodNode method) throws RenderingException {
|
public void renderDeclaration(MethodNode method) throws RenderingException, IOException {
|
||||||
try {
|
try {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
if (ref.getDescriptor().getName().equals("<init>")) {
|
if (ref.getDescriptor().getName().equals("<init>")) {
|
||||||
|
@ -294,7 +299,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderBody(MethodNode method) {
|
public void renderBody(MethodNode method) throws IOException {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
writer.appendMethodBody(ref).ws().append("=").ws().append("function(");
|
writer.appendMethodBody(ref).ws().append("=").ws().append("function(");
|
||||||
int startParam = 0;
|
int startParam = 0;
|
||||||
|
@ -315,27 +320,35 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
private class MethodBodyRenderer implements MethodNodeVisitor, GeneratorContext {
|
private class MethodBodyRenderer implements MethodNodeVisitor, GeneratorContext {
|
||||||
@Override
|
@Override
|
||||||
public void visit(NativeMethodNode methodNode) {
|
public void visit(NativeMethodNode methodNode) {
|
||||||
methodNode.getGenerator().generate(this, writer, methodNode.getReference());
|
try {
|
||||||
|
methodNode.getGenerator().generate(this, writer, methodNode.getReference());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(RegularMethodNode method) {
|
public void visit(RegularMethodNode method) {
|
||||||
MethodReference ref = method.getReference();
|
try {
|
||||||
int variableCount = method.getVariableCount();
|
MethodReference ref = method.getReference();
|
||||||
boolean hasVars = variableCount > ref.parameterCount() + 1;
|
int variableCount = method.getVariableCount();
|
||||||
if (hasVars) {
|
boolean hasVars = variableCount > ref.parameterCount() + 1;
|
||||||
writer.append("var ");
|
if (hasVars) {
|
||||||
boolean first = true;
|
writer.append("var ");
|
||||||
for (int i = ref.parameterCount() + 1; i < variableCount; ++i) {
|
boolean first = true;
|
||||||
if (!first) {
|
for (int i = ref.parameterCount() + 1; i < variableCount; ++i) {
|
||||||
writer.append(",").ws();
|
if (!first) {
|
||||||
|
writer.append(",").ws();
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
writer.append(variableName(i));
|
||||||
}
|
}
|
||||||
first = false;
|
writer.append(";").softNewLine();
|
||||||
writer.append(variableName(i));
|
|
||||||
}
|
}
|
||||||
writer.append(";").softNewLine();
|
method.getBody().acceptVisitor(Renderer.this);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
method.getBody().acceptVisitor(Renderer.this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -345,13 +358,17 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignmentStatement statement) {
|
public void visit(AssignmentStatement statement) throws RenderingException {
|
||||||
if (statement.getLeftValue() != null) {
|
try {
|
||||||
statement.getLeftValue().acceptVisitor(this);
|
if (statement.getLeftValue() != null) {
|
||||||
writer.ws().append("=").ws();
|
statement.getLeftValue().acceptVisitor(this);
|
||||||
|
writer.ws().append("=").ws();
|
||||||
|
}
|
||||||
|
statement.getRightValue().acceptVisitor(this);
|
||||||
|
writer.append(";").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
statement.getRightValue().acceptVisitor(this);
|
|
||||||
writer.append(";").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -363,66 +380,82 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConditionalStatement statement) {
|
public void visit(ConditionalStatement statement) {
|
||||||
writer.append("if").ws().append("(");
|
try {
|
||||||
statement.getCondition().acceptVisitor(this);
|
writer.append("if").ws().append("(");
|
||||||
writer.append(")").ws().append("{").softNewLine().indent();
|
statement.getCondition().acceptVisitor(this);
|
||||||
statement.getConsequent().acceptVisitor(this);
|
writer.append(")").ws().append("{").softNewLine().indent();
|
||||||
if (statement.getAlternative() != null) {
|
statement.getConsequent().acceptVisitor(this);
|
||||||
writer.outdent().append("}").ws().append("else").ws().append("{").indent().softNewLine();
|
if (statement.getAlternative() != null) {
|
||||||
statement.getAlternative().acceptVisitor(this);
|
writer.outdent().append("}").ws().append("else").ws().append("{").indent().softNewLine();
|
||||||
|
statement.getAlternative().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
writer.outdent().append("}").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SwitchStatement statement) {
|
public void visit(SwitchStatement statement) {
|
||||||
if (statement.getId() != null) {
|
try {
|
||||||
writer.append(statement.getId()).append(": ");
|
if (statement.getId() != null) {
|
||||||
}
|
writer.append(statement.getId()).append(": ");
|
||||||
writer.append("switch").ws().append("(");
|
|
||||||
statement.getValue().acceptVisitor(this);
|
|
||||||
writer.append(")").ws().append("{").softNewLine().indent();
|
|
||||||
for (SwitchClause clause : statement.getClauses()) {
|
|
||||||
for (int condition : clause.getConditions()) {
|
|
||||||
writer.append("case ").append(condition).append(":").softNewLine();
|
|
||||||
}
|
}
|
||||||
writer.indent();
|
writer.append("switch").ws().append("(");
|
||||||
clause.getStatement().acceptVisitor(this);
|
statement.getValue().acceptVisitor(this);
|
||||||
writer.outdent();
|
writer.append(")").ws().append("{").softNewLine().indent();
|
||||||
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
|
for (int condition : clause.getConditions()) {
|
||||||
|
writer.append("case ").append(condition).append(":").softNewLine();
|
||||||
|
}
|
||||||
|
writer.indent();
|
||||||
|
clause.getStatement().acceptVisitor(this);
|
||||||
|
writer.outdent();
|
||||||
|
}
|
||||||
|
if (statement.getDefaultClause() != null) {
|
||||||
|
writer.append("default:").softNewLine().indent();
|
||||||
|
statement.getDefaultClause().acceptVisitor(this);
|
||||||
|
writer.outdent();
|
||||||
|
}
|
||||||
|
writer.outdent().append("}").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
if (statement.getDefaultClause() != null) {
|
|
||||||
writer.append("default:").softNewLine().indent();
|
|
||||||
statement.getDefaultClause().acceptVisitor(this);
|
|
||||||
writer.outdent();
|
|
||||||
}
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WhileStatement statement) {
|
public void visit(WhileStatement statement) {
|
||||||
if (statement.getId() != null) {
|
try {
|
||||||
writer.append(statement.getId()).append(":").ws();
|
if (statement.getId() != null) {
|
||||||
|
writer.append(statement.getId()).append(":").ws();
|
||||||
|
}
|
||||||
|
writer.append("while").ws().append("(");
|
||||||
|
if (statement.getCondition() != null) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
} else {
|
||||||
|
writer.append("true");
|
||||||
|
}
|
||||||
|
writer.append(")").ws().append("{").softNewLine().indent();
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
writer.outdent().append("}").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
writer.append("while").ws().append("(");
|
|
||||||
if (statement.getCondition() != null) {
|
|
||||||
statement.getCondition().acceptVisitor(this);
|
|
||||||
} else {
|
|
||||||
writer.append("true");
|
|
||||||
}
|
|
||||||
writer.append(")").ws().append("{").softNewLine().indent();
|
|
||||||
for (Statement part : statement.getBody()) {
|
|
||||||
part.acceptVisitor(this);
|
|
||||||
}
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BlockStatement statement) {
|
public void visit(BlockStatement statement) {
|
||||||
writer.append(statement.getId()).append(":").ws().append("{").softNewLine().indent();
|
try {
|
||||||
for (Statement part : statement.getBody()) {
|
writer.append(statement.getId()).append(":").ws().append("{").softNewLine().indent();
|
||||||
part.acceptVisitor(this);
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
writer.outdent().append("}").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -432,48 +465,68 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BreakStatement statement) {
|
public void visit(BreakStatement statement) {
|
||||||
writer.append("break ").append(statement.getTarget().getId()).append(";").softNewLine();
|
try {
|
||||||
|
writer.append("break ").append(statement.getTarget().getId()).append(";").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ContinueStatement statement) {
|
public void visit(ContinueStatement statement) {
|
||||||
writer.append("continue ").append(statement.getTarget().getId()).append(";").softNewLine();
|
try {
|
||||||
|
writer.append("continue ").append(statement.getTarget().getId()).append(";").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ReturnStatement statement) {
|
public void visit(ReturnStatement statement) {
|
||||||
writer.append("return");
|
try {
|
||||||
if (statement.getResult() != null) {
|
writer.append("return");
|
||||||
writer.append(' ');
|
if (statement.getResult() != null) {
|
||||||
statement.getResult().acceptVisitor(this);
|
writer.append(' ');
|
||||||
|
statement.getResult().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
writer.append(";").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
writer.append(";").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ThrowStatement statement) {
|
public void visit(ThrowStatement statement) {
|
||||||
writer.append("$rt_throw(");
|
try {
|
||||||
statement.getException().acceptVisitor(this);
|
writer.append("$rt_throw(");
|
||||||
writer.append(");").softNewLine();
|
statement.getException().acceptVisitor(this);
|
||||||
|
writer.append(");").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IncrementStatement statement) {
|
public void visit(IncrementStatement statement) {
|
||||||
writer.append(variableName(statement.getVar()));
|
try {
|
||||||
if (statement.getAmount() > 0) {
|
writer.append(variableName(statement.getVar()));
|
||||||
if (statement.getAmount() == 1) {
|
if (statement.getAmount() > 0) {
|
||||||
writer.append("++");
|
if (statement.getAmount() == 1) {
|
||||||
|
writer.append("++");
|
||||||
|
} else {
|
||||||
|
writer.ws().append("+=").ws().append(statement.getAmount());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
writer.ws().append("+=").ws().append(statement.getAmount());
|
if (statement.getAmount() == -1) {
|
||||||
}
|
writer.append("--");
|
||||||
} else {
|
} else {
|
||||||
if (statement.getAmount() == -1) {
|
writer.ws().append("-=").ws().append(statement.getAmount());
|
||||||
writer.append("--");
|
}
|
||||||
} else {
|
|
||||||
writer.ws().append("-=").ws().append(statement.getAmount());
|
|
||||||
}
|
}
|
||||||
|
writer.append(";").softNewLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
writer.append(";").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String variableName(int index) {
|
public String variableName(int index) {
|
||||||
|
@ -490,20 +543,28 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitBinary(BinaryExpr expr, String op) {
|
private void visitBinary(BinaryExpr expr, String op) {
|
||||||
writer.append('(');
|
try {
|
||||||
expr.getFirstOperand().acceptVisitor(this);
|
writer.append('(');
|
||||||
writer.ws().append(op).ws();
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
expr.getSecondOperand().acceptVisitor(this);
|
writer.ws().append(op).ws();
|
||||||
writer.append(')');
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
writer.append(')');
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitBinaryFunction(BinaryExpr expr, String function) {
|
private void visitBinaryFunction(BinaryExpr expr, String function) {
|
||||||
writer.append(function);
|
try {
|
||||||
writer.append('(');
|
writer.append(function);
|
||||||
expr.getFirstOperand().acceptVisitor(this);
|
writer.append('(');
|
||||||
writer.append(",").ws();
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
expr.getSecondOperand().acceptVisitor(this);
|
writer.append(",").ws();
|
||||||
writer.append(')');
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
writer.append(')');
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -616,73 +677,85 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnaryExpr expr) {
|
public void visit(UnaryExpr expr) {
|
||||||
switch (expr.getOperation()) {
|
try {
|
||||||
case NOT:
|
switch (expr.getOperation()) {
|
||||||
writer.append("(!");
|
case NOT:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("(!");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
case NEGATE:
|
break;
|
||||||
writer.append("(-");
|
case NEGATE:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("(-");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
case LENGTH:
|
break;
|
||||||
expr.getOperand().acceptVisitor(this);
|
case LENGTH:
|
||||||
writer.append(".length");
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(".length");
|
||||||
case INT_TO_LONG:
|
break;
|
||||||
writer.append("Long_fromInt(");
|
case INT_TO_LONG:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("Long_fromInt(");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
case NUM_TO_LONG:
|
break;
|
||||||
writer.append("Long_fromNumber(");
|
case NUM_TO_LONG:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("Long_fromNumber(");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
case LONG_TO_NUM:
|
break;
|
||||||
writer.append("Long_toNumber(");
|
case LONG_TO_NUM:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("Long_toNumber(");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
case NEGATE_LONG:
|
break;
|
||||||
writer.append("Long_neg(");
|
case NEGATE_LONG:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("Long_neg(");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
case NOT_LONG:
|
break;
|
||||||
writer.append("Long_not(");
|
case NOT_LONG:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("Long_not(");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
case BYTE_TO_INT:
|
break;
|
||||||
writer.append("$rt_byteToInt(");
|
case BYTE_TO_INT:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("$rt_byteToInt(");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
case SHORT_TO_INT:
|
break;
|
||||||
writer.append("$rt_shortToInt(");
|
case SHORT_TO_INT:
|
||||||
expr.getOperand().acceptVisitor(this);
|
writer.append("$rt_shortToInt(");
|
||||||
writer.append(')');
|
expr.getOperand().acceptVisitor(this);
|
||||||
break;
|
writer.append(')');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConditionalExpr expr) {
|
public void visit(ConditionalExpr expr) {
|
||||||
writer.append('(');
|
try {
|
||||||
expr.getCondition().acceptVisitor(this);
|
writer.append('(');
|
||||||
writer.ws().append("?").ws();
|
expr.getCondition().acceptVisitor(this);
|
||||||
expr.getConsequent().acceptVisitor(this);
|
writer.ws().append("?").ws();
|
||||||
writer.ws().append(":").ws();
|
expr.getConsequent().acceptVisitor(this);
|
||||||
expr.getAlternative().acceptVisitor(this);
|
writer.ws().append(":").ws();
|
||||||
writer.append(')');
|
expr.getAlternative().acceptVisitor(this);
|
||||||
|
writer.append(')');
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstantExpr expr) {
|
public void visit(ConstantExpr expr) {
|
||||||
writer.append(constantToString(expr.getValue()));
|
try {
|
||||||
|
writer.append(constantToString(expr.getValue()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String constantToString(Object cst) {
|
public String constantToString(Object cst) {
|
||||||
|
@ -798,173 +871,213 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(VariableExpr expr) {
|
public void visit(VariableExpr expr) {
|
||||||
writer.append(variableName(expr.getIndex()));
|
try {
|
||||||
|
writer.append(variableName(expr.getIndex()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SubscriptExpr expr) {
|
public void visit(SubscriptExpr expr) {
|
||||||
expr.getArray().acceptVisitor(this);
|
try {
|
||||||
writer.append('[');
|
expr.getArray().acceptVisitor(this);
|
||||||
expr.getIndex().acceptVisitor(this);
|
writer.append('[');
|
||||||
writer.append(']');
|
expr.getIndex().acceptVisitor(this);
|
||||||
|
writer.append(']');
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnwrapArrayExpr expr) {
|
public void visit(UnwrapArrayExpr expr) {
|
||||||
expr.getArray().acceptVisitor(this);
|
try {
|
||||||
writer.append(".data");
|
expr.getArray().acceptVisitor(this);
|
||||||
|
writer.append(".data");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InvocationExpr expr) {
|
public void visit(InvocationExpr expr) {
|
||||||
String className = naming.getNameFor(expr.getMethod().getClassName());
|
try {
|
||||||
String name = naming.getNameFor(expr.getMethod());
|
String className = naming.getNameFor(expr.getMethod().getClassName());
|
||||||
String fullName = naming.getFullNameFor(expr.getMethod());
|
String name = naming.getNameFor(expr.getMethod());
|
||||||
switch (expr.getType()) {
|
String fullName = naming.getFullNameFor(expr.getMethod());
|
||||||
case STATIC:
|
switch (expr.getType()) {
|
||||||
writer.append(fullName).append("(");
|
case STATIC:
|
||||||
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
writer.append(fullName).append("(");
|
||||||
if (i > 0) {
|
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
||||||
writer.append(",").ws();
|
if (i > 0) {
|
||||||
|
writer.append(",").ws();
|
||||||
|
}
|
||||||
|
expr.getArguments().get(i).acceptVisitor(this);
|
||||||
}
|
}
|
||||||
expr.getArguments().get(i).acceptVisitor(this);
|
writer.append(')');
|
||||||
}
|
break;
|
||||||
writer.append(')');
|
case SPECIAL:
|
||||||
break;
|
writer.append(fullName).append("(");
|
||||||
case SPECIAL:
|
expr.getArguments().get(0).acceptVisitor(this);
|
||||||
writer.append(fullName).append("(");
|
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
||||||
expr.getArguments().get(0).acceptVisitor(this);
|
|
||||||
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
|
||||||
writer.append(",").ws();
|
|
||||||
expr.getArguments().get(i).acceptVisitor(this);
|
|
||||||
}
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
case DYNAMIC:
|
|
||||||
expr.getArguments().get(0).acceptVisitor(this);
|
|
||||||
writer.append(".").append(name).append("(");
|
|
||||||
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
|
||||||
if (i > 1) {
|
|
||||||
writer.append(",").ws();
|
writer.append(",").ws();
|
||||||
|
expr.getArguments().get(i).acceptVisitor(this);
|
||||||
}
|
}
|
||||||
expr.getArguments().get(i).acceptVisitor(this);
|
writer.append(")");
|
||||||
}
|
break;
|
||||||
writer.append(')');
|
case DYNAMIC:
|
||||||
break;
|
expr.getArguments().get(0).acceptVisitor(this);
|
||||||
case CONSTRUCTOR:
|
writer.append(".").append(name).append("(");
|
||||||
writer.append(className).append(".").append(name).append("(");
|
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
||||||
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
if (i > 1) {
|
||||||
if (i > 0) {
|
writer.append(",").ws();
|
||||||
writer.append(",").ws();
|
}
|
||||||
|
expr.getArguments().get(i).acceptVisitor(this);
|
||||||
}
|
}
|
||||||
expr.getArguments().get(i).acceptVisitor(this);
|
writer.append(')');
|
||||||
}
|
break;
|
||||||
writer.append(')');
|
case CONSTRUCTOR:
|
||||||
break;
|
writer.append(className).append(".").append(name).append("(");
|
||||||
|
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(",").ws();
|
||||||
|
}
|
||||||
|
expr.getArguments().get(i).acceptVisitor(this);
|
||||||
|
}
|
||||||
|
writer.append(')');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(QualificationExpr expr) {
|
public void visit(QualificationExpr expr) {
|
||||||
expr.getQualified().acceptVisitor(this);
|
try {
|
||||||
writer.append('.').appendField(expr.getField());
|
expr.getQualified().acceptVisitor(this);
|
||||||
|
writer.append('.').appendField(expr.getField());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewExpr expr) {
|
public void visit(NewExpr expr) {
|
||||||
writer.append("new ").append(naming.getNameFor(expr.getConstructedClass())).append("()");
|
try {
|
||||||
|
writer.append("new ").append(naming.getNameFor(expr.getConstructedClass())).append("()");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewArrayExpr expr) {
|
public void visit(NewArrayExpr expr) {
|
||||||
ValueType type = expr.getType();
|
try {
|
||||||
while (type instanceof ValueType.Array) {
|
ValueType type = expr.getType();
|
||||||
type = ((ValueType.Array)type).getItemType();
|
while (type instanceof ValueType.Array) {
|
||||||
}
|
type = ((ValueType.Array)type).getItemType();
|
||||||
if (type instanceof ValueType.Primitive) {
|
|
||||||
switch (((ValueType.Primitive)type).getKind()) {
|
|
||||||
case BOOLEAN:
|
|
||||||
writer.append("$rt_createBooleanArray(");
|
|
||||||
expr.getLength().acceptVisitor(this);
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
case BYTE:
|
|
||||||
writer.append("$rt_createByteArray(");
|
|
||||||
expr.getLength().acceptVisitor(this);
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
case SHORT:
|
|
||||||
writer.append("$rt_createShortArray(");
|
|
||||||
expr.getLength().acceptVisitor(this);
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
case INTEGER:
|
|
||||||
writer.append("$rt_createIntArray(");
|
|
||||||
expr.getLength().acceptVisitor(this);
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
case LONG:
|
|
||||||
writer.append("$rt_createLongArray(");
|
|
||||||
expr.getLength().acceptVisitor(this);
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
case FLOAT:
|
|
||||||
writer.append("$rt_createFloatArray(");
|
|
||||||
expr.getLength().acceptVisitor(this);
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
case DOUBLE:
|
|
||||||
writer.append("$rt_createDoubleArray(");
|
|
||||||
expr.getLength().acceptVisitor(this);
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
case CHARACTER:
|
|
||||||
writer.append("$rt_createCharArray(");
|
|
||||||
expr.getLength().acceptVisitor(this);
|
|
||||||
writer.append(")");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else {
|
if (type instanceof ValueType.Primitive) {
|
||||||
writer.append("$rt_createArray(").append(typeToClsString(naming, expr.getType())).append(", ");
|
switch (((ValueType.Primitive)type).getKind()) {
|
||||||
expr.getLength().acceptVisitor(this);
|
case BOOLEAN:
|
||||||
writer.append(")");
|
writer.append("$rt_createBooleanArray(");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
break;
|
||||||
|
case BYTE:
|
||||||
|
writer.append("$rt_createByteArray(");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
break;
|
||||||
|
case SHORT:
|
||||||
|
writer.append("$rt_createShortArray(");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
break;
|
||||||
|
case INTEGER:
|
||||||
|
writer.append("$rt_createIntArray(");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
break;
|
||||||
|
case LONG:
|
||||||
|
writer.append("$rt_createLongArray(");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
writer.append("$rt_createFloatArray(");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
break;
|
||||||
|
case DOUBLE:
|
||||||
|
writer.append("$rt_createDoubleArray(");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
break;
|
||||||
|
case CHARACTER:
|
||||||
|
writer.append("$rt_createCharArray(");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writer.append("$rt_createArray(").append(typeToClsString(naming, expr.getType())).append(", ");
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
writer.append(")");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewMultiArrayExpr expr) {
|
public void visit(NewMultiArrayExpr expr) {
|
||||||
writer.append("$rt_createMultiArray(").append(typeToClsString(naming, expr.getType())).append(",")
|
try {
|
||||||
.ws().append("[");
|
writer.append("$rt_createMultiArray(").append(typeToClsString(naming, expr.getType())).append(",")
|
||||||
boolean first = true;
|
.ws().append("[");
|
||||||
for (Expr dimension : expr.getDimensions()) {
|
boolean first = true;
|
||||||
if (!first) {
|
for (Expr dimension : expr.getDimensions()) {
|
||||||
writer.append(",").ws();
|
if (!first) {
|
||||||
|
writer.append(",").ws();
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
dimension.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
first = false;
|
writer.append("])");
|
||||||
dimension.acceptVisitor(this);
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
writer.append("])");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InstanceOfExpr expr) {
|
public void visit(InstanceOfExpr expr) {
|
||||||
if (expr.getType() instanceof ValueType.Object) {
|
try {
|
||||||
String clsName = ((ValueType.Object)expr.getType()).getClassName();
|
if (expr.getType() instanceof ValueType.Object) {
|
||||||
ClassHolder cls = classSource.getClassHolder(clsName);
|
String clsName = ((ValueType.Object)expr.getType()).getClassName();
|
||||||
if (!cls.getModifiers().contains(ElementModifier.INTERFACE)) {
|
ClassHolder cls = classSource.getClassHolder(clsName);
|
||||||
writer.append("(");
|
if (!cls.getModifiers().contains(ElementModifier.INTERFACE)) {
|
||||||
expr.getExpr().acceptVisitor(this);
|
writer.append("(");
|
||||||
writer.append(" instanceof ").appendClass(clsName).append(")");
|
expr.getExpr().acceptVisitor(this);
|
||||||
return;
|
writer.append(" instanceof ").appendClass(clsName).append(")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
writer.append("$rt_isInstance(");
|
||||||
|
expr.getExpr().acceptVisitor(this);
|
||||||
|
writer.append(",").ws().append(typeToClsString(naming, expr.getType())).append(")");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
writer.append("$rt_isInstance(");
|
|
||||||
expr.getExpr().acceptVisitor(this);
|
|
||||||
writer.append(",").ws().append(typeToClsString(naming, expr.getType())).append(")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(StaticClassExpr expr) {
|
public void visit(StaticClassExpr expr) {
|
||||||
writer.append(typeToClsString(naming, expr.getType()));
|
try {
|
||||||
|
writer.append(typeToClsString(naming, expr.getType()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RenderingException("IO error occured", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import org.teavm.model.instructions.InvocationType;
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class StatementGenerator implements InstructionVisitor {
|
class StatementGenerator implements InstructionVisitor {
|
||||||
private int lastSwitchId;
|
private int lastSwitchId;
|
||||||
List<Statement> statements = new ArrayList<>();
|
List<Statement> statements = new ArrayList<>();
|
||||||
GraphIndexer indexer;
|
GraphIndexer indexer;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.javascript.ni;
|
package org.teavm.javascript.ni;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
@ -8,5 +9,5 @@ import org.teavm.model.MethodReference;
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public interface Generator {
|
public interface Generator {
|
||||||
void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef);
|
void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user