mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Adds ResourceAccessor and its implementation. ResourceAccessor is to
access properties and methods of resource in rumtime.
This commit is contained in:
parent
10a8e0261a
commit
3cf7991cfb
|
@ -44,6 +44,7 @@ public class Decompiler {
|
||||||
private RangeTree.Node parentNode;
|
private RangeTree.Node parentNode;
|
||||||
private FiniteExecutor executor;
|
private FiniteExecutor executor;
|
||||||
private Map<MethodReference, Generator> generators = new HashMap<>();
|
private Map<MethodReference, Generator> generators = new HashMap<>();
|
||||||
|
private Set<MethodReference> methodsToPass = new HashSet<>();
|
||||||
|
|
||||||
public Decompiler(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
public Decompiler(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
|
@ -96,6 +97,10 @@ public class Decompiler {
|
||||||
generators.put(method, generator);
|
generators.put(method, generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addMethodToPass(MethodReference method) {
|
||||||
|
methodsToPass.add(method);
|
||||||
|
}
|
||||||
|
|
||||||
private void orderClasses(String className, Set<String> visited, List<String> order) {
|
private void orderClasses(String className, Set<String> visited, List<String> order) {
|
||||||
if (!visited.add(className)) {
|
if (!visited.add(className)) {
|
||||||
return;
|
return;
|
||||||
|
@ -125,7 +130,8 @@ public class Decompiler {
|
||||||
if (method.getModifiers().contains(ElementModifier.ABSTRACT)) {
|
if (method.getModifiers().contains(ElementModifier.ABSTRACT)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (method.getAnnotations().get(InjectedBy.class.getName()) != null) {
|
if (method.getAnnotations().get(InjectedBy.class.getName()) != null ||
|
||||||
|
methodsToPass.contains(method)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MethodNode methodNode = decompile(method);
|
MethodNode methodNode = decompile(method);
|
||||||
|
@ -140,8 +146,8 @@ public class Decompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodNode decompile(MethodHolder method) {
|
public MethodNode decompile(MethodHolder method) {
|
||||||
return method.getModifiers().contains(ElementModifier.NATIVE) ?
|
return method.getModifiers().contains(ElementModifier.NATIVE) ? decompileNative(method) :
|
||||||
decompileNative(method) : decompileRegular(method);
|
decompileRegular(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NativeMethodNode decompileNative(MethodHolder method) {
|
public NativeMethodNode decompileNative(MethodHolder method) {
|
||||||
|
|
|
@ -53,6 +53,10 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addInjector(MethodReference method, Injector injector) {
|
||||||
|
injectorMap.put(method, new InjectorHolder(injector));
|
||||||
|
}
|
||||||
|
|
||||||
public Renderer(SourceWriter writer, ListableClassHolderSource classSource, ClassLoader classLoader) {
|
public Renderer(SourceWriter writer, ListableClassHolderSource classSource, ClassLoader classLoader) {
|
||||||
this.naming = writer.getNaming();
|
this.naming = writer.getNaming();
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
|
|
|
@ -34,6 +34,17 @@ public class MethodDescriptor {
|
||||||
this.signature = Arrays.copyOf(signature, signature.length);
|
this.signature = Arrays.copyOf(signature, signature.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MethodDescriptor(String name, Class<?>... signature) {
|
||||||
|
if (signature.length < 1) {
|
||||||
|
throw new IllegalArgumentException("Signature must be at least 1 element length");
|
||||||
|
}
|
||||||
|
this.name = name;
|
||||||
|
this.signature = new ValueType[signature.length];
|
||||||
|
for (int i = 0; i < signature.length; ++i) {
|
||||||
|
this.signature[i] = ValueType.parse(signature[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,10 @@ public class MethodReference {
|
||||||
this(className, new MethodDescriptor(name, signature));
|
this(className, new MethodDescriptor(name, signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MethodReference(Class<?> cls, String name, Class<?>... signature) {
|
||||||
|
this(cls.getName(), new MethodDescriptor(name, signature));
|
||||||
|
}
|
||||||
|
|
||||||
public String getClassName() {
|
public String getClassName() {
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
package org.teavm.model;
|
package org.teavm.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +27,7 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public abstract class ValueType {
|
public abstract class ValueType {
|
||||||
volatile String reprCache;
|
volatile String reprCache;
|
||||||
|
private static final Map<Class<?>, ValueType> primitiveMap = new HashMap<>();
|
||||||
|
|
||||||
private ValueType() {
|
private ValueType() {
|
||||||
}
|
}
|
||||||
|
@ -166,6 +169,19 @@ public abstract class ValueType {
|
||||||
|
|
||||||
public static final Null NULL = new Null();
|
public static final Null NULL = new Null();
|
||||||
|
|
||||||
|
|
||||||
|
static {
|
||||||
|
primitiveMap.put(boolean.class, BOOLEAN);
|
||||||
|
primitiveMap.put(char.class, CHARACTER);
|
||||||
|
primitiveMap.put(byte.class, BYTE);
|
||||||
|
primitiveMap.put(short.class, SHORT);
|
||||||
|
primitiveMap.put(int.class, INTEGER);
|
||||||
|
primitiveMap.put(long.class, LONG);
|
||||||
|
primitiveMap.put(float.class, FLOAT);
|
||||||
|
primitiveMap.put(double.class, DOUBLE);
|
||||||
|
primitiveMap.put(void.class, VOID);
|
||||||
|
}
|
||||||
|
|
||||||
public static ValueType object(String cls) {
|
public static ValueType object(String cls) {
|
||||||
return new Object(cls);
|
return new Object(cls);
|
||||||
}
|
}
|
||||||
|
@ -267,6 +283,16 @@ public abstract class ValueType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ValueType parse(Class<?> cls) {
|
||||||
|
if (cls.isPrimitive()) {
|
||||||
|
return primitiveMap.get(cls);
|
||||||
|
} else if (cls.getComponentType() != null) {
|
||||||
|
return ValueType.arrayOf(ValueType.parse(cls.getComponentType()));
|
||||||
|
} else {
|
||||||
|
return ValueType.object(cls.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return toString().hashCode();
|
return toString().hashCode();
|
||||||
|
|
|
@ -20,9 +20,12 @@ import java.util.*;
|
||||||
import org.teavm.codegen.*;
|
import org.teavm.codegen.*;
|
||||||
import org.teavm.common.FiniteExecutor;
|
import org.teavm.common.FiniteExecutor;
|
||||||
import org.teavm.dependency.*;
|
import org.teavm.dependency.*;
|
||||||
import org.teavm.javascript.*;
|
import org.teavm.javascript.Decompiler;
|
||||||
|
import org.teavm.javascript.Renderer;
|
||||||
|
import org.teavm.javascript.RenderingException;
|
||||||
import org.teavm.javascript.ast.ClassNode;
|
import org.teavm.javascript.ast.ClassNode;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
|
import org.teavm.javascript.ni.Injector;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.util.ListingBuilder;
|
import org.teavm.model.util.ListingBuilder;
|
||||||
import org.teavm.model.util.ProgramUtils;
|
import org.teavm.model.util.ProgramUtils;
|
||||||
|
@ -73,6 +76,7 @@ public class TeaVM implements TeaVMHost {
|
||||||
private Map<String, TeaVMEntryPoint> entryPoints = new HashMap<>();
|
private Map<String, TeaVMEntryPoint> entryPoints = new HashMap<>();
|
||||||
private Map<String, String> exportedClasses = new HashMap<>();
|
private Map<String, String> exportedClasses = new HashMap<>();
|
||||||
private Map<MethodReference, Generator> methodGenerators = new HashMap<>();
|
private Map<MethodReference, Generator> methodGenerators = new HashMap<>();
|
||||||
|
private Map<MethodReference, Injector> methodInjectors = new HashMap<>();
|
||||||
private List<RendererListener> rendererListeners = new ArrayList<>();
|
private List<RendererListener> rendererListeners = new ArrayList<>();
|
||||||
private Properties properties = new Properties();
|
private Properties properties = new Properties();
|
||||||
|
|
||||||
|
@ -98,6 +102,11 @@ public class TeaVM implements TeaVMHost {
|
||||||
methodGenerators.put(methodRef, generator);
|
methodGenerators.put(methodRef, generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(MethodReference methodRef, Injector injector) {
|
||||||
|
methodInjectors.put(methodRef, injector);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(RendererListener listener) {
|
public void add(RendererListener listener) {
|
||||||
rendererListeners.add(listener);
|
rendererListeners.add(listener);
|
||||||
|
@ -315,6 +324,9 @@ public class TeaVM implements TeaVMHost {
|
||||||
for (Map.Entry<MethodReference, Generator> entry : methodGenerators.entrySet()) {
|
for (Map.Entry<MethodReference, Generator> entry : methodGenerators.entrySet()) {
|
||||||
decompiler.addGenerator(entry.getKey(), entry.getValue());
|
decompiler.addGenerator(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
for (MethodReference injectedMethod : methodInjectors.keySet()) {
|
||||||
|
decompiler.addMethodToPass(injectedMethod);
|
||||||
|
}
|
||||||
List<ClassNode> clsNodes = decompiler.decompile(classSet.getClassNames());
|
List<ClassNode> clsNodes = decompiler.decompile(classSet.getClassNames());
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
|
@ -324,6 +336,9 @@ public class TeaVM implements TeaVMHost {
|
||||||
builder.setMinified(minifying);
|
builder.setMinified(minifying);
|
||||||
SourceWriter sourceWriter = builder.build(writer);
|
SourceWriter sourceWriter = builder.build(writer);
|
||||||
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader);
|
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader);
|
||||||
|
for (Map.Entry<MethodReference, Injector> entry : methodInjectors.entrySet()) {
|
||||||
|
renderer.addInjector(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
for (RendererListener listener : rendererListeners) {
|
for (RendererListener listener : rendererListeners) {
|
||||||
listener.begin(renderer, target);
|
listener.begin(renderer, target);
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.vm.spi;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import org.teavm.dependency.DependencyListener;
|
import org.teavm.dependency.DependencyListener;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
|
import org.teavm.javascript.ni.Injector;
|
||||||
import org.teavm.model.ClassHolderTransformer;
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.vm.TeaVM;
|
import org.teavm.vm.TeaVM;
|
||||||
|
@ -36,6 +37,8 @@ public interface TeaVMHost {
|
||||||
|
|
||||||
void add(MethodReference methodRef, Generator generator);
|
void add(MethodReference methodRef, Generator generator);
|
||||||
|
|
||||||
|
void add(MethodReference methodRef, Injector injector);
|
||||||
|
|
||||||
void add(RendererListener listener);
|
void add(RendererListener listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,10 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.platform.metadata;
|
package org.teavm.platform.metadata;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.*;
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Marks a valid <b>resource interface</b>. Resource interface is an interface, that has get* and set* methods,
|
* <p>Marks a valid <b>resource interface</b>. Resource interface is an interface, that has get* and set* methods,
|
||||||
|
@ -33,5 +30,7 @@ import java.lang.annotation.Target;
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
public @interface Resource {
|
public @interface Resource {
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,5 +26,8 @@ public class PlatformPlugin implements TeaVMPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void install(TeaVMHost host) {
|
public void install(TeaVMHost host) {
|
||||||
host.add(new MetadataProviderTransformer());
|
host.add(new MetadataProviderTransformer());
|
||||||
|
host.add(new ResourceTransformer());
|
||||||
|
host.add(new ResourceAccessorTransformer(host));
|
||||||
|
host.add(new ResourceAccessorDependencyListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
final class ResourceAccessor {
|
||||||
|
public static native Object get(Object obj, String propertyName);
|
||||||
|
|
||||||
|
public static native void put(Object obj, String propertyName, Object elem);
|
||||||
|
|
||||||
|
public static native Object get(Object obj, int index);
|
||||||
|
|
||||||
|
public static native Object add(Object obj, Object elem);
|
||||||
|
|
||||||
|
public static native boolean has(Object obj, String key);
|
||||||
|
|
||||||
|
public static native boolean size(Object obj);
|
||||||
|
|
||||||
|
public static native int castToInt(Object obj);
|
||||||
|
|
||||||
|
public static native Integer castToIntWrapper(Object obj);
|
||||||
|
|
||||||
|
public static native short castToShort(Object obj);
|
||||||
|
|
||||||
|
public static native Short castToShortWrapper(Object obj);
|
||||||
|
|
||||||
|
public static native byte castToByte(Object obj);
|
||||||
|
|
||||||
|
public static native Byte castToByteWrapper(Object obj);
|
||||||
|
|
||||||
|
public static native boolean castToBoolean(Object obj);
|
||||||
|
|
||||||
|
public static native Boolean castToBooleanWrapper(Object obj);
|
||||||
|
|
||||||
|
public static native float castToFloat(Object obj);
|
||||||
|
|
||||||
|
public static native Float castToFloatWrapper(Object obj);
|
||||||
|
|
||||||
|
public static native double castToDouble(Object obj);
|
||||||
|
|
||||||
|
public static native Double castToDoubleWrapper(Object obj);
|
||||||
|
|
||||||
|
public static native String castToString(Object obj);
|
||||||
|
|
||||||
|
public static native Object castFromInt(int value);
|
||||||
|
|
||||||
|
public static native Object castFromIntWrapper(Integer value);
|
||||||
|
|
||||||
|
public static native Object castFromShort(short value);
|
||||||
|
|
||||||
|
public static native Object castFromShortWrapper(Short value);
|
||||||
|
|
||||||
|
public static native Object castFromByte(byte value);
|
||||||
|
|
||||||
|
public static native Object castFromByteWrapper(Byte value);
|
||||||
|
|
||||||
|
public static native Object castFromBoolean(boolean value);
|
||||||
|
|
||||||
|
public static native Object castFromBooleanWrapper(Boolean value);
|
||||||
|
|
||||||
|
public static native Object castFromFloat(float value);
|
||||||
|
|
||||||
|
public static native Object castFromFloatWrapper(Float value);
|
||||||
|
|
||||||
|
public static native Object castFromDouble(double value);
|
||||||
|
|
||||||
|
public static native Object castFromDoubleWrapper(Double value);
|
||||||
|
|
||||||
|
public static native Object castFromString(String value);
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
import org.teavm.dependency.DependencyAgent;
|
||||||
|
import org.teavm.dependency.DependencyListener;
|
||||||
|
import org.teavm.dependency.FieldDependency;
|
||||||
|
import org.teavm.dependency.MethodDependency;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class ResourceAccessorDependencyListener implements DependencyListener {
|
||||||
|
@Override
|
||||||
|
public void started(DependencyAgent agent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void classAchieved(DependencyAgent agent, String className) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||||
|
switch (method.getReference().getName()) {
|
||||||
|
case "castToIntWrapper":
|
||||||
|
castToWrapper(agent, method, Integer.class, int.class);
|
||||||
|
break;
|
||||||
|
case "castToShortWrapper":
|
||||||
|
castToWrapper(agent, method, Short.class, short.class);
|
||||||
|
break;
|
||||||
|
case "castToByteWrapper":
|
||||||
|
castToWrapper(agent, method, Byte.class, byte.class);
|
||||||
|
break;
|
||||||
|
case "castToBooleanWrapper":
|
||||||
|
castToWrapper(agent, method, Boolean.class, boolean.class);
|
||||||
|
break;
|
||||||
|
case "castToFloatWrapper":
|
||||||
|
castToWrapper(agent, method, Float.class, float.class);
|
||||||
|
break;
|
||||||
|
case "castToDoubleWrapper":
|
||||||
|
castToWrapper(agent, method, Double.class, double.class);
|
||||||
|
break;
|
||||||
|
case "castFromIntegerWrapper":
|
||||||
|
castFromWrapper(agent, method, Integer.class, int.class);
|
||||||
|
break;
|
||||||
|
case "castFromShortWrapper":
|
||||||
|
castFromWrapper(agent, method, Short.class, short.class);
|
||||||
|
break;
|
||||||
|
case "castFromByteWrapper":
|
||||||
|
castFromWrapper(agent, method, Byte.class, byte.class);
|
||||||
|
break;
|
||||||
|
case "castFromBooleanWrapper":
|
||||||
|
castFromWrapper(agent, method, Boolean.class, boolean.class);
|
||||||
|
break;
|
||||||
|
case "castFromFloatWrapper":
|
||||||
|
castFromWrapper(agent, method, Float.class, float.class);
|
||||||
|
break;
|
||||||
|
case "castFromDoubleWrapper":
|
||||||
|
castFromWrapper(agent, method, Double.class, double.class);
|
||||||
|
break;
|
||||||
|
case "castToString":
|
||||||
|
method.getResult().propagate("java.lang.String");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void castToWrapper(DependencyAgent agent, MethodDependency method, Class<?> wrapper, Class<?> primitive) {
|
||||||
|
method.getResult().propagate(wrapper.getName());
|
||||||
|
agent.linkMethod(new MethodReference(wrapper, "valueOf", primitive, wrapper), method.getStack()).use();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void castFromWrapper(DependencyAgent agent, MethodDependency method, Class<?> wrapper, Class<?> primitive) {
|
||||||
|
String primitiveName = primitive.getName();
|
||||||
|
agent.linkMethod(new MethodReference(wrapper, primitiveName + "Value", primitive), method.getStack()).use();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.teavm.javascript.ast.ConstantExpr;
|
||||||
|
import org.teavm.javascript.ast.Expr;
|
||||||
|
import org.teavm.javascript.ni.Injector;
|
||||||
|
import org.teavm.javascript.ni.InjectorContext;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class ResourceAccessorGenerator implements Injector {
|
||||||
|
@Override
|
||||||
|
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||||
|
switch (methodRef.getName()) {
|
||||||
|
case "get":
|
||||||
|
if (methodRef.getDescriptor().parameterType(1) == ValueType.INTEGER) {
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append('[');
|
||||||
|
context.writeExpr(context.getArgument(2));
|
||||||
|
context.getWriter().append(']');
|
||||||
|
} else {
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
writePropertyAccessor(context, context.getArgument(2));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "put":
|
||||||
|
context.getWriter().append('(');
|
||||||
|
if (methodRef.getDescriptor().parameterType(1) == ValueType.INTEGER) {
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append('[');
|
||||||
|
context.writeExpr(context.getArgument(2));
|
||||||
|
} else {
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
writePropertyAccessor(context, context.getArgument(2));
|
||||||
|
}
|
||||||
|
context.getWriter().append(']').ws().append('=').ws();
|
||||||
|
context.writeExpr(context.getArgument(3));
|
||||||
|
context.getWriter().append(')');
|
||||||
|
break;
|
||||||
|
case "add":
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append(".push(");
|
||||||
|
context.writeExpr(context.getArgument(2));
|
||||||
|
context.getWriter().append(')');
|
||||||
|
break;
|
||||||
|
case "has":
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append(".hasOwnProperty(");
|
||||||
|
writeStringExpr(context, context.getArgument(2));
|
||||||
|
context.getWriter().append(')');
|
||||||
|
break;
|
||||||
|
case "size":
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append(".length");
|
||||||
|
break;
|
||||||
|
case "castToInt":
|
||||||
|
case "castToShort":
|
||||||
|
case "castToByte":
|
||||||
|
case "castToBoolean":
|
||||||
|
case "castToFloat":
|
||||||
|
case "castToDouble":
|
||||||
|
case "castFromInt":
|
||||||
|
case "castFromShort":
|
||||||
|
case "castFromByte":
|
||||||
|
case "castFromBoolean":
|
||||||
|
case "castFromFloat":
|
||||||
|
case "castFromDouble":
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
break;
|
||||||
|
case "castToIntWrapper":
|
||||||
|
castToWrapper(context, Integer.class, int.class);
|
||||||
|
break;
|
||||||
|
case "castToShortWrapper":
|
||||||
|
castToWrapper(context, Short.class, short.class);
|
||||||
|
break;
|
||||||
|
case "castToByteWrapper":
|
||||||
|
castToWrapper(context, Byte.class, byte.class);
|
||||||
|
break;
|
||||||
|
case "castToBooleanWrapper":
|
||||||
|
castToWrapper(context, Boolean.class, boolean.class);
|
||||||
|
break;
|
||||||
|
case "castToFloatWrapper":
|
||||||
|
castToWrapper(context, Float.class, float.class);
|
||||||
|
break;
|
||||||
|
case "castToDoubleWrapper":
|
||||||
|
castToWrapper(context, Double.class, double.class);
|
||||||
|
break;
|
||||||
|
case "castFromIntWrapper":
|
||||||
|
castFromWrapper(context, Integer.class, int.class);
|
||||||
|
break;
|
||||||
|
case "castFromShortWrapper":
|
||||||
|
castFromWrapper(context, Short.class, short.class);
|
||||||
|
break;
|
||||||
|
case "castFromByteWrapper":
|
||||||
|
castFromWrapper(context, Byte.class, byte.class);
|
||||||
|
break;
|
||||||
|
case "castFromBooleanWrapper":
|
||||||
|
castFromWrapper(context, Boolean.class, boolean.class);
|
||||||
|
break;
|
||||||
|
case "castFromFloatWrapper":
|
||||||
|
castFromWrapper(context, Float.class, float.class);
|
||||||
|
break;
|
||||||
|
case "castFromDoubleWrapper":
|
||||||
|
castFromWrapper(context, Double.class, double.class);
|
||||||
|
break;
|
||||||
|
case "castToString":
|
||||||
|
context.getWriter().append("$rt_str(");
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append(")");
|
||||||
|
break;
|
||||||
|
case "castFromString":
|
||||||
|
context.getWriter().append("$rt_ustr(");
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append(")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void castToWrapper(InjectorContext context, Class<?> wrapper, Class<?> primitive) throws IOException {
|
||||||
|
context.getWriter().appendMethodBody(new MethodReference(wrapper, "valueOf", primitive, wrapper)).append('(');
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append(')');
|
||||||
|
}
|
||||||
|
|
||||||
|
private void castFromWrapper(InjectorContext context, Class<?> wrapper, Class<?> primitive) throws IOException {
|
||||||
|
String primitiveName = primitive.getName();
|
||||||
|
context.getWriter().appendMethodBody(new MethodReference(wrapper, primitiveName + "Value", primitive))
|
||||||
|
.append('(');
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
context.getWriter().append(')');
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writePropertyAccessor(InjectorContext context, Expr property) throws IOException {
|
||||||
|
if (property instanceof ConstantExpr) {
|
||||||
|
String str = (String)((ConstantExpr)property).getValue();
|
||||||
|
if (str.isEmpty()) {
|
||||||
|
context.getWriter().append("[\"\"]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isValidIndentifier(str)) {
|
||||||
|
context.getWriter().append(".").append(str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.getWriter().append("[$rt_ustr(");
|
||||||
|
context.writeExpr(property);
|
||||||
|
context.getWriter().append(")]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeStringExpr(InjectorContext context, Expr expr) throws IOException {
|
||||||
|
if (expr instanceof ConstantExpr) {
|
||||||
|
String str = (String)((ConstantExpr)expr).getValue();
|
||||||
|
context.getWriter().append('"');
|
||||||
|
context.writeEscaped(str);
|
||||||
|
context.getWriter().append('"');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.getWriter().append("$rt_ustr(");
|
||||||
|
context.writeExpr(expr);
|
||||||
|
context.getWriter().append(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidIndentifier(String str) {
|
||||||
|
if (!Character.isJavaIdentifierStart(str.charAt(0))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 1; i < str.length(); ++i) {
|
||||||
|
if (!Character.isJavaIdentifierPart(str.charAt(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
import org.teavm.vm.spi.TeaVMHost;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class ResourceAccessorTransformer implements ClassHolderTransformer {
|
||||||
|
private TeaVMHost vm;
|
||||||
|
|
||||||
|
public ResourceAccessorTransformer(TeaVMHost vm) {
|
||||||
|
this.vm = vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
|
||||||
|
ResourceAccessorGenerator generator = new ResourceAccessorGenerator();
|
||||||
|
if (cls.getName().equals(ResourceAccessor.class)) {
|
||||||
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
vm.add(method.getReference(), generator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class ResourceTransformer implements ClassHolderTransformer {
|
||||||
|
@Override
|
||||||
|
public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user