mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
JS: introduce JS template engine to write runtime, rewrite several functions using this engine
This commit is contained in:
parent
350cff776e
commit
16cd0aaab2
|
@ -91,7 +91,7 @@ public class AstWriter {
|
||||||
public static final int PRECEDENCE_COND = 16;
|
public static final int PRECEDENCE_COND = 16;
|
||||||
public static final int PRECEDENCE_ASSIGN = 17;
|
public static final int PRECEDENCE_ASSIGN = 17;
|
||||||
public static final int PRECEDENCE_COMMA = 18;
|
public static final int PRECEDENCE_COMMA = 18;
|
||||||
private SourceWriter writer;
|
protected final SourceWriter writer;
|
||||||
private Map<String, NameEmitter> nameMap = new HashMap<>();
|
private Map<String, NameEmitter> nameMap = new HashMap<>();
|
||||||
private boolean rootScope = true;
|
private boolean rootScope = true;
|
||||||
private Set<String> aliases = new HashSet<>();
|
private Set<String> aliases = new HashSet<>();
|
||||||
|
@ -495,7 +495,7 @@ public class AstWriter {
|
||||||
writer.append(';');
|
writer.append(';');
|
||||||
}
|
}
|
||||||
|
|
||||||
private void print(ElementGet node) throws IOException {
|
protected void print(ElementGet node) throws IOException {
|
||||||
print(node.getTarget(), PRECEDENCE_MEMBER);
|
print(node.getTarget(), PRECEDENCE_MEMBER);
|
||||||
writer.append('[');
|
writer.append('[');
|
||||||
print(node.getElement());
|
print(node.getElement());
|
||||||
|
@ -512,6 +512,10 @@ public class AstWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void print(FunctionCall node, int precedence) throws IOException {
|
private void print(FunctionCall node, int precedence) throws IOException {
|
||||||
|
if (intrinsic(node, precedence)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tryJavaInvocation(node)) {
|
if (tryJavaInvocation(node)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -539,6 +543,10 @@ public class AstWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean intrinsic(FunctionCall node, int precedence) throws IOException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean tryJavaInvocation(FunctionCall node) throws IOException {
|
private boolean tryJavaInvocation(FunctionCall node) throws IOException {
|
||||||
if (!(node.getTarget() instanceof PropertyGet)) {
|
if (!(node.getTarget() instanceof PropertyGet)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 konsoletyper.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.teavm.backend.javascript.rendering;
|
|
||||||
|
|
||||||
import org.mozilla.javascript.Token;
|
|
||||||
import org.mozilla.javascript.ast.AstNode;
|
|
||||||
import org.mozilla.javascript.ast.ExpressionStatement;
|
|
||||||
import org.mozilla.javascript.ast.FunctionCall;
|
|
||||||
import org.mozilla.javascript.ast.InfixExpression;
|
|
||||||
import org.mozilla.javascript.ast.KeywordLiteral;
|
|
||||||
import org.mozilla.javascript.ast.Name;
|
|
||||||
import org.mozilla.javascript.ast.PropertyGet;
|
|
||||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
|
||||||
import org.teavm.model.FieldReference;
|
|
||||||
|
|
||||||
public class RuntimeAstTransformer extends AstVisitor {
|
|
||||||
private static final FieldReference MONITOR_FIELD = new FieldReference(
|
|
||||||
"java.lang.Object", "monitor");
|
|
||||||
private NamingStrategy names;
|
|
||||||
|
|
||||||
public RuntimeAstTransformer(NamingStrategy names) {
|
|
||||||
this.names = names;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void visitExpressionStatement(ExpressionStatement node) {
|
|
||||||
AstNode expression = node.getExpression();
|
|
||||||
if (expression.getType() == Token.CALL) {
|
|
||||||
FunctionCall call = (FunctionCall) expression;
|
|
||||||
if (call.getTarget().getType() == Token.NAME) {
|
|
||||||
String id = ((Name) call.getTarget()).getIdentifier();
|
|
||||||
if (id.equals("$rt_initMonitorField")) {
|
|
||||||
AstNode arg = call.getArguments().get(0);
|
|
||||||
accept(arg);
|
|
||||||
String fieldId = names.getNameFor(MONITOR_FIELD);
|
|
||||||
PropertyGet propertyGet = new PropertyGet(arg, new Name(0, fieldId));
|
|
||||||
KeywordLiteral nullExpr = new KeywordLiteral(0, 0, Token.NULL);
|
|
||||||
InfixExpression assign = new InfixExpression(Token.ASSIGN, propertyGet, nullExpr, 0);
|
|
||||||
node.setExpression(assign);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.visitExpressionStatement(node);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,14 +24,13 @@ import org.mozilla.javascript.CompilerEnvirons;
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
import org.mozilla.javascript.ast.AstRoot;
|
import org.mozilla.javascript.ast.AstRoot;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
|
import org.teavm.backend.javascript.templating.TemplatingAstWriter;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldReference;
|
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
|
||||||
import org.teavm.vm.RenderingException;
|
import org.teavm.vm.RenderingException;
|
||||||
|
|
||||||
public class RuntimeRenderer {
|
public class RuntimeRenderer {
|
||||||
|
@ -39,8 +38,6 @@ public class RuntimeRenderer {
|
||||||
private static final String THREAD_CLASS = Thread.class.getName();
|
private static final String THREAD_CLASS = Thread.class.getName();
|
||||||
private static final String STE_CLASS = StackTraceElement.class.getName();
|
private static final String STE_CLASS = StackTraceElement.class.getName();
|
||||||
|
|
||||||
private static final MethodReference NPE_INIT_METHOD = new MethodReference(NullPointerException.class,
|
|
||||||
"<init>", void.class);
|
|
||||||
private static final MethodDescriptor STRING_INTERN_METHOD = new MethodDescriptor("intern", String.class);
|
private static final MethodDescriptor STRING_INTERN_METHOD = new MethodDescriptor("intern", String.class);
|
||||||
private static final MethodDescriptor CURRENT_THREAD_METHOD = new MethodDescriptor("currentThread",
|
private static final MethodDescriptor CURRENT_THREAD_METHOD = new MethodDescriptor("currentThread",
|
||||||
Thread.class);
|
Thread.class);
|
||||||
|
@ -64,18 +61,9 @@ public class RuntimeRenderer {
|
||||||
public void renderRuntime() throws RenderingException {
|
public void renderRuntime() throws RenderingException {
|
||||||
try {
|
try {
|
||||||
renderHandWrittenRuntime("runtime.js");
|
renderHandWrittenRuntime("runtime.js");
|
||||||
renderSetCloneMethod();
|
|
||||||
renderRuntimeCls();
|
|
||||||
renderRuntimeString();
|
|
||||||
renderRuntimeUnwrapString();
|
|
||||||
renderRuntimeObjcls();
|
|
||||||
renderRuntimeThrowablecls();
|
renderRuntimeThrowablecls();
|
||||||
renderRuntimeThrowableMethods();
|
|
||||||
renderRuntimeNullCheck();
|
|
||||||
renderRuntimeIntern();
|
renderRuntimeIntern();
|
||||||
renderStringClassInit();
|
|
||||||
renderRuntimeThreads();
|
renderRuntimeThreads();
|
||||||
renderRuntimeCreateException();
|
|
||||||
renderCreateStackTraceElement();
|
renderCreateStackTraceElement();
|
||||||
renderSetStackTrace();
|
renderSetStackTrace();
|
||||||
renderThrowAIOOBE();
|
renderThrowAIOOBE();
|
||||||
|
@ -88,8 +76,7 @@ public class RuntimeRenderer {
|
||||||
public void renderHandWrittenRuntime(String name) throws IOException {
|
public void renderHandWrittenRuntime(String name) throws IOException {
|
||||||
AstRoot ast = parseRuntime(name);
|
AstRoot ast = parseRuntime(name);
|
||||||
ast.visit(new StringConstantElimination());
|
ast.visit(new StringConstantElimination());
|
||||||
new RuntimeAstTransformer(writer.getNaming()).accept(ast);
|
var astWriter = new TemplatingAstWriter(writer);
|
||||||
var astWriter = new AstWriter(writer, new DefaultGlobalNameWriter(writer));
|
|
||||||
astWriter.hoist(ast);
|
astWriter.hoist(ast);
|
||||||
astWriter.print(ast);
|
astWriter.print(ast);
|
||||||
}
|
}
|
||||||
|
@ -107,50 +94,6 @@ public class RuntimeRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderSetCloneMethod() throws IOException {
|
|
||||||
writer.append("function $rt_setCloneMethod(target, f)").ws().append("{").softNewLine().indent();
|
|
||||||
writer.append("target.").appendMethod("clone", Object.class).ws().append('=').ws().append("f;").
|
|
||||||
softNewLine();
|
|
||||||
writer.outdent().append("}").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderRuntimeCls() throws IOException {
|
|
||||||
writer.append("function $rt_cls(cls)").ws().append("{").softNewLine().indent();
|
|
||||||
writer.append("return ").appendMethodBody("java.lang.Class", "getClass",
|
|
||||||
ValueType.object("org.teavm.platform.PlatformClass"),
|
|
||||||
ValueType.object("java.lang.Class")).append("(cls);")
|
|
||||||
.softNewLine();
|
|
||||||
writer.outdent().append("}").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderRuntimeString() throws IOException {
|
|
||||||
MethodReference stringCons = new MethodReference(String.class, "<init>", Object.class, void.class);
|
|
||||||
writer.append("function $rt_str(str)").ws().append("{").indent().softNewLine();
|
|
||||||
writer.append("if (str === null) {").indent().softNewLine();
|
|
||||||
writer.append("return null;").softNewLine();
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
writer.append("return ").appendInit(stringCons).append("(str);").softNewLine();
|
|
||||||
writer.outdent().append("}").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderRuntimeUnwrapString() throws IOException {
|
|
||||||
FieldReference stringChars = new FieldReference(STRING_CLASS, "nativeString");
|
|
||||||
writer.append("function $rt_ustr(str)").ws().append("{").indent().softNewLine();
|
|
||||||
writer.append("return str").ws().append("!==").ws().append("null");
|
|
||||||
writer.ws().append("?").ws().append("str.").appendField(stringChars);
|
|
||||||
writer.ws().append(":").ws().append("null").append(";").softNewLine();
|
|
||||||
writer.outdent().append("}").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderRuntimeNullCheck() throws IOException {
|
|
||||||
writer.append("function $rt_nullCheck(val) {").indent().softNewLine();
|
|
||||||
writer.append("if (val === null) {").indent().softNewLine();
|
|
||||||
writer.append("$rt_throw(").appendInit(NPE_INIT_METHOD).append("());").softNewLine();
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
writer.append("return val;").softNewLine();
|
|
||||||
writer.outdent().append("}").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderRuntimeIntern() throws IOException {
|
private void renderRuntimeIntern() throws IOException {
|
||||||
if (!needInternMethod()) {
|
if (!needInternMethod()) {
|
||||||
writer.append("function $rt_intern(str) {").indent().softNewLine();
|
writer.append("function $rt_intern(str) {").indent().softNewLine();
|
||||||
|
@ -161,12 +104,6 @@ public class RuntimeRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderStringClassInit() throws IOException {
|
|
||||||
writer.append("function $rt_stringClassInit(str)").ws().append("{").indent().softNewLine();
|
|
||||||
writer.appendClassInit("java.lang.String").append("();").softNewLine();
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean needInternMethod() {
|
private boolean needInternMethod() {
|
||||||
ClassReader cls = classSource.get(STRING_CLASS);
|
ClassReader cls = classSource.get(STRING_CLASS);
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
|
@ -176,10 +113,6 @@ public class RuntimeRenderer {
|
||||||
return method != null && method.hasModifier(ElementModifier.NATIVE);
|
return method != null && method.hasModifier(ElementModifier.NATIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRuntimeObjcls() throws IOException {
|
|
||||||
writer.append("function $rt_objcls() { return ").appendClass("java.lang.Object").append("; }").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderRuntimeThrowablecls() throws IOException {
|
private void renderRuntimeThrowablecls() throws IOException {
|
||||||
writer.append("function $rt_stecls()").ws().append("{").indent().softNewLine();
|
writer.append("function $rt_stecls()").ws().append("{").indent().softNewLine();
|
||||||
writer.append("return ");
|
writer.append("return ");
|
||||||
|
@ -191,18 +124,6 @@ public class RuntimeRenderer {
|
||||||
writer.append(";").softNewLine().outdent().append("}").newLine();
|
writer.append(";").softNewLine().outdent().append("}").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRuntimeThrowableMethods() throws IOException {
|
|
||||||
writer.append("function $rt_throwableMessage(t)").ws().append("{").indent().softNewLine();
|
|
||||||
writer.append("return ");
|
|
||||||
writer.appendMethodBody(Throwable.class, "getMessage", String.class).append("(t);").softNewLine();
|
|
||||||
writer.outdent().append("}").newLine();
|
|
||||||
|
|
||||||
writer.append("function $rt_throwableCause(t)").ws().append("{").indent().softNewLine();
|
|
||||||
writer.append("return ");
|
|
||||||
writer.appendMethodBody(Throwable.class, "getCause", Throwable.class).append("(t);").softNewLine();
|
|
||||||
writer.outdent().append("}").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderRuntimeThreads() throws IOException {
|
private void renderRuntimeThreads() throws IOException {
|
||||||
ClassReader threadCls = classSource.get(THREAD_CLASS);
|
ClassReader threadCls = classSource.get(THREAD_CLASS);
|
||||||
MethodReader currentThreadMethod = threadCls != null ? threadCls.getMethod(CURRENT_THREAD_METHOD) : null;
|
MethodReader currentThreadMethod = threadCls != null ? threadCls.getMethod(CURRENT_THREAD_METHOD) : null;
|
||||||
|
@ -225,14 +146,6 @@ public class RuntimeRenderer {
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRuntimeCreateException() throws IOException {
|
|
||||||
writer.append("function $rt_createException(message)").ws().append("{").indent().softNewLine();
|
|
||||||
writer.append("return ");
|
|
||||||
writer.appendInit(new MethodReference(RuntimeException.class, "<init>", String.class, void.class));
|
|
||||||
writer.append("(message);").softNewLine();
|
|
||||||
writer.outdent().append("}").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderCreateStackTraceElement() throws IOException {
|
private void renderCreateStackTraceElement() throws IOException {
|
||||||
ClassReader cls = classSource.get(STACK_TRACE_ELEM_INIT.getClassName());
|
ClassReader cls = classSource.get(STACK_TRACE_ELEM_INIT.getClassName());
|
||||||
MethodReader stackTraceElemInit = cls != null ? cls.getMethod(STACK_TRACE_ELEM_INIT.getDescriptor()) : null;
|
MethodReader stackTraceElemInit = cls != null ? cls.getMethod(STACK_TRACE_ELEM_INIT.getDescriptor()) : null;
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.javascript.templating;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.mozilla.javascript.ast.ElementGet;
|
||||||
|
import org.mozilla.javascript.ast.FunctionCall;
|
||||||
|
import org.mozilla.javascript.ast.Name;
|
||||||
|
import org.mozilla.javascript.ast.StringLiteral;
|
||||||
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
|
import org.teavm.backend.javascript.rendering.AstWriter;
|
||||||
|
import org.teavm.backend.javascript.rendering.DefaultGlobalNameWriter;
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
public class TemplatingAstWriter extends AstWriter {
|
||||||
|
public TemplatingAstWriter(SourceWriter writer) {
|
||||||
|
super(writer, new DefaultGlobalNameWriter(writer));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean intrinsic(FunctionCall node, int precedence) throws IOException {
|
||||||
|
if (node.getTarget() instanceof Name) {
|
||||||
|
var name = (Name) node.getTarget();
|
||||||
|
if (name.getDefiningScope() == null) {
|
||||||
|
return tryIntrinsicName(node, name.getIdentifier());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.intrinsic(node, precedence);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tryIntrinsicName(FunctionCall node, String name) throws IOException {
|
||||||
|
switch (name) {
|
||||||
|
case "teavm_javaClass":
|
||||||
|
return writeJavaClass(node);
|
||||||
|
case "teavm_javaMethod":
|
||||||
|
return writeJavaMethod(node);
|
||||||
|
case "teavm_javaConstructor":
|
||||||
|
return writeJavaConstructor(node);
|
||||||
|
case "teavm_javaClassInit":
|
||||||
|
return writeJavaClassInit(node);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeJavaClass(FunctionCall node) throws IOException {
|
||||||
|
if (node.getArguments().size() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var classArg = node.getArguments().get(0);
|
||||||
|
if (!(classArg instanceof StringLiteral)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
writer.appendClass(((StringLiteral) classArg).getValue());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeJavaMethod(FunctionCall node) throws IOException {
|
||||||
|
if (node.getArguments().size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var classArg = node.getArguments().get(0);
|
||||||
|
var methodArg = node.getArguments().get(1);
|
||||||
|
if (!(classArg instanceof StringLiteral) || !(methodArg instanceof StringLiteral)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var method = new MethodReference(((StringLiteral) classArg).getValue(),
|
||||||
|
MethodDescriptor.parse(((StringLiteral) methodArg).getValue()));
|
||||||
|
writer.appendMethodBody(method);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeJavaConstructor(FunctionCall node) throws IOException {
|
||||||
|
if (node.getArguments().size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var classArg = node.getArguments().get(0);
|
||||||
|
var methodArg = node.getArguments().get(1);
|
||||||
|
if (!(classArg instanceof StringLiteral) || !(methodArg instanceof StringLiteral)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var method = new MethodReference(((StringLiteral) classArg).getValue(), "<init>",
|
||||||
|
MethodDescriptor.parseSignature(((StringLiteral) methodArg).getValue()));
|
||||||
|
writer.appendInit(method);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeJavaClassInit(FunctionCall node) throws IOException {
|
||||||
|
if (node.getArguments().size() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var classArg = node.getArguments().get(0);
|
||||||
|
if (!(classArg instanceof StringLiteral)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
writer.appendClassInit(((StringLiteral) classArg).getValue());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void print(ElementGet node) throws IOException {
|
||||||
|
if (node.getElement() instanceof FunctionCall) {
|
||||||
|
var call = (FunctionCall) node.getElement();
|
||||||
|
if (call.getTarget() instanceof Name) {
|
||||||
|
var name = (Name) call.getTarget();
|
||||||
|
if (name.getDefiningScope() == null) {
|
||||||
|
switch (name.getIdentifier()) {
|
||||||
|
case "teavm_javaVirtualMethod":
|
||||||
|
if (writeJavaVirtualMethod(node, call)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "teavm_javaField":
|
||||||
|
if (writeJavaField(node, call)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.print(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeJavaVirtualMethod(ElementGet get, FunctionCall call) throws IOException {
|
||||||
|
var arg = call.getArguments().get(0);
|
||||||
|
if (!(arg instanceof StringLiteral)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var method = MethodDescriptor.parse(((StringLiteral) arg).getValue());
|
||||||
|
print(get.getTarget());
|
||||||
|
writer.append('.').appendMethod(method);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeJavaField(ElementGet get, FunctionCall call) throws IOException {
|
||||||
|
if (call.getArguments().size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var classArg = call.getArguments().get(0);
|
||||||
|
var fieldArg = call.getArguments().get(1);
|
||||||
|
if (!(classArg instanceof StringLiteral) || !(fieldArg instanceof StringLiteral)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var className = ((StringLiteral) classArg).getValue();
|
||||||
|
var fieldName = ((StringLiteral) fieldArg).getValue();
|
||||||
|
print(get.getTarget());
|
||||||
|
writer.append('.').appendField(new FieldReference(className, fieldName));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -930,3 +930,41 @@ function $rt_substring(string, start, end) {
|
||||||
$rt_substringSink = ($rt_substringSink + result.charCodeAt(result.length - 1)) | 0;
|
$rt_substringSink = ($rt_substringSink + result.charCodeAt(result.length - 1)) | 0;
|
||||||
}
|
}
|
||||||
var $rt_substringSink = 0;
|
var $rt_substringSink = 0;
|
||||||
|
|
||||||
|
function $rt_setCloneMethod(target, method) {
|
||||||
|
target[teavm_javaVirtualMethod('clone()Ljava/lang/Object;')] = method;
|
||||||
|
}
|
||||||
|
function $rt_cls(cls) {
|
||||||
|
return teavm_javaMethod("java.lang.Class",
|
||||||
|
"getClass(Lorg/teavm/platform/PlatformClass;)Ljava/lang/Class;")(cls);
|
||||||
|
}
|
||||||
|
function $rt_str(str) {
|
||||||
|
if (str === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return teavm_javaConstructor("java.lang.String", "(Ljava/lang/Object;)V")(str);
|
||||||
|
}
|
||||||
|
function $rt_ustr(str) {
|
||||||
|
return str === null ? null : str[teavm_javaField("java.lang.String", "nativeString")];
|
||||||
|
}
|
||||||
|
function $rt_nullCheck(val) {
|
||||||
|
if (val === null) {
|
||||||
|
$rt_throw(teavm_javaConstructor("java.lang.NullPointerException", "()V")());
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
function $rt_stringClassInit() {
|
||||||
|
teavm_javaClassInit("java.lang.String")();
|
||||||
|
}
|
||||||
|
function $rt_objcls() {
|
||||||
|
return teavm_javaClass("java.lang.Object");
|
||||||
|
}
|
||||||
|
function $rt_createException(message) {
|
||||||
|
return teavm_javaConstructor("java.lang.RuntimeException", "(Ljava/lang/String;)V")(message);
|
||||||
|
}
|
||||||
|
function $rt_throwableMessage(t) {
|
||||||
|
return teavm_javaMethod("java.lang.Throwable", "getMessage()Ljava/lang/String;")(t);
|
||||||
|
}
|
||||||
|
function $rt_throwableCause(t) {
|
||||||
|
return teavm_javaMethod("java.lang.Throwable", "getCause()Ljava/lang/Throwable;")(t);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user