mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Start porting metaprogramming API implementation
This commit is contained in:
parent
92dbed2593
commit
5e7311d8cc
|
@ -45,6 +45,7 @@
|
|||
<file type="gwt" url="file://$PROJECT_DIR$/samples/benchmark" />
|
||||
<file type="Osmorc" url="file://$PROJECT_DIR$/classlib" />
|
||||
<file type="Osmorc" url="file://$PROJECT_DIR$/core" />
|
||||
<file type="Osmorc" url="file://$PROJECT_DIR$/metaprogramming-api" />
|
||||
<file type="Osmorc" url="file://$PROJECT_DIR$/platform" />
|
||||
<file type="Osmorc" url="file://$PROJECT_DIR$/tools/chrome-rdp" />
|
||||
<file type="Osmorc" url="file://$PROJECT_DIR$/tools/core" />
|
||||
|
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* Copyright 2016 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.metaprogramming.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.teavm.common.DisjointSet;
|
||||
import org.teavm.model.BasicBlockReader;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodHandle;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.PhiReader;
|
||||
import org.teavm.model.ProgramReader;
|
||||
import org.teavm.model.RuntimeConstant;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.VariableReader;
|
||||
import org.teavm.model.instructions.ArrayElementType;
|
||||
import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||
import org.teavm.model.instructions.BinaryOperation;
|
||||
import org.teavm.model.instructions.BranchingCondition;
|
||||
import org.teavm.model.instructions.CastIntegerDirection;
|
||||
import org.teavm.model.instructions.InstructionReader;
|
||||
import org.teavm.model.instructions.IntegerSubtype;
|
||||
import org.teavm.model.instructions.InvocationType;
|
||||
import org.teavm.model.instructions.NumericOperandType;
|
||||
import org.teavm.model.instructions.SwitchTableEntryReader;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class AliasFinder {
|
||||
int[] aliases;
|
||||
Object[] constants;
|
||||
ArrayElement[] arrayElements;
|
||||
|
||||
public void findAliases(ProgramReader program) {
|
||||
DisjointSet set = new DisjointSet();
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
set.create();
|
||||
}
|
||||
|
||||
AliasReader reader = new AliasReader(set, program.variableCount());
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlockReader block = program.basicBlockAt(i);
|
||||
block.readAllInstructions(reader);
|
||||
for (PhiReader phi : block.readPhis()) {
|
||||
Set<Integer> inputs = phi.readIncomings().stream()
|
||||
.map(incoming -> incoming.getValue().getIndex())
|
||||
.collect(Collectors.toSet());
|
||||
if (inputs.size() == 1) {
|
||||
set.union(inputs.iterator().next(), phi.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] map = new int[set.size()];
|
||||
Arrays.fill(map, -1);
|
||||
int[] variables = new int[program.variableCount()];
|
||||
for (int i = 0; i < variables.length; ++i) {
|
||||
int v = set.find(i);
|
||||
int master = map[v];
|
||||
if (master == -1) {
|
||||
master = i;
|
||||
map[v] = master;
|
||||
}
|
||||
variables[i] = master;
|
||||
}
|
||||
|
||||
aliases = variables;
|
||||
constants = reader.constants;
|
||||
arrayElements = reader.arrayElements;
|
||||
|
||||
for (int i = 0; i < arrayElements.length; ++i) {
|
||||
ArrayElement elem = arrayElements[i];
|
||||
if (elem == null) {
|
||||
continue;
|
||||
}
|
||||
elem.index = aliases[elem.index];
|
||||
if (constants[elem.index] instanceof Integer) {
|
||||
elem.index = (Integer) constants[elem.index];
|
||||
} else {
|
||||
arrayElements[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArrayElement {
|
||||
public int array;
|
||||
public int index;
|
||||
}
|
||||
|
||||
public int[] getAliases() {
|
||||
return aliases.clone();
|
||||
}
|
||||
|
||||
public Object[] getConstants() {
|
||||
return constants.clone();
|
||||
}
|
||||
|
||||
public ArrayElement[] getArrayElements() {
|
||||
return arrayElements.clone();
|
||||
}
|
||||
|
||||
static class AliasReader implements InstructionReader {
|
||||
DisjointSet disjointSet;
|
||||
Object[] constants;
|
||||
ArrayElement[] arrayElements;
|
||||
|
||||
AliasReader(DisjointSet disjointSet, int variableCount) {
|
||||
this.disjointSet = disjointSet;
|
||||
this.constants = new Object[variableCount];
|
||||
this.arrayElements = new ArrayElement[variableCount];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void location(InstructionLocation location) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nop() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void classConstant(VariableReader receiver, ValueType cst) {
|
||||
constants[receiver.getIndex()] = cst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullConstant(VariableReader receiver) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void integerConstant(VariableReader receiver, int cst) {
|
||||
constants[receiver.getIndex()] = cst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void longConstant(VariableReader receiver, long cst) {
|
||||
constants[receiver.getIndex()] = cst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void floatConstant(VariableReader receiver, float cst) {
|
||||
constants[receiver.getIndex()] = cst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doubleConstant(VariableReader receiver, double cst) {
|
||||
constants[receiver.getIndex()] = cst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stringConstant(VariableReader receiver, String cst) {
|
||||
constants[receiver.getIndex()] = cst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void binary(BinaryOperation op, VariableReader receiver, VariableReader first, VariableReader second,
|
||||
NumericOperandType type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assign(VariableReader receiver, VariableReader assignee) {
|
||||
disjointSet.union(receiver.getIndex(), assignee.getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cast(VariableReader receiver, VariableReader value, NumericOperandType sourceType,
|
||||
NumericOperandType targetType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cast(VariableReader receiver, VariableReader value, IntegerSubtype type,
|
||||
CastIntegerDirection targetType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpIf(BranchingCondition cond, VariableReader operand, BasicBlockReader consequent,
|
||||
BasicBlockReader alternative) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpIf(BinaryBranchingCondition cond, VariableReader first, VariableReader second,
|
||||
BasicBlockReader consequent, BasicBlockReader alternative) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jump(BasicBlockReader target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void choose(VariableReader condition, List<? extends SwitchTableEntryReader> table,
|
||||
BasicBlockReader defaultTarget) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(VariableReader valueToReturn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raise(VariableReader exception) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createArray(VariableReader receiver, ValueType itemType,
|
||||
List<? extends VariableReader> dimensions) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(VariableReader receiver, String type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getField(VariableReader receiver, VariableReader instance, FieldReference field,
|
||||
ValueType fieldType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putField(VariableReader instance, FieldReference field, VariableReader value, ValueType fieldType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayLength(VariableReader receiver, VariableReader array) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cloneArray(VariableReader receiver, VariableReader array) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) {
|
||||
disjointSet.union(receiver.getIndex(), array.getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
|
||||
ArrayElement elem = new ArrayElement();
|
||||
elem.array = array.getIndex();
|
||||
elem.index = index.getIndex();
|
||||
arrayElements[receiver.getIndex()] = elem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||
List<? extends VariableReader> arguments, InvocationType type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeDynamic(VariableReader receiver, VariableReader instance, MethodDescriptor method,
|
||||
List<? extends VariableReader> arguments, MethodHandle bootstrapMethod,
|
||||
List<RuntimeConstant> bootstrapArguments) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void isInstance(VariableReader receiver, VariableReader value, ValueType type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initClass(String className) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullCheck(VariableReader receiver, VariableReader value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void monitorEnter(VariableReader objectRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void monitorExit(VariableReader objectRef) {
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2016 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.metaprogramming.impl;
|
||||
|
||||
import org.teavm.metaprogramming.LazyComputation;
|
||||
import org.teavm.metaprogramming.Value;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class LazyValueImpl<T> implements Value<T> {
|
||||
boolean evaluated;
|
||||
VariableContext context;
|
||||
LazyComputation<T> computation;
|
||||
ValueType type;
|
||||
InstructionLocation forcedLocation;
|
||||
|
||||
public LazyValueImpl(VariableContext context, LazyComputation<T> computation, ValueType type,
|
||||
InstructionLocation forcedLocation) {
|
||||
this.context = context;
|
||||
this.computation = computation;
|
||||
this.type = type;
|
||||
this.forcedLocation = forcedLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
throw new IllegalStateException("Can only read this value in emitter domain");
|
||||
}
|
||||
}
|
|
@ -15,46 +15,151 @@
|
|||
*/
|
||||
package org.teavm.metaprogramming.impl;
|
||||
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.metaprogramming.Action;
|
||||
import org.teavm.metaprogramming.Computation;
|
||||
import org.teavm.metaprogramming.Diagnostics;
|
||||
import org.teavm.metaprogramming.InvocationHandler;
|
||||
import org.teavm.metaprogramming.LazyComputation;
|
||||
import org.teavm.metaprogramming.ReflectClass;
|
||||
import org.teavm.metaprogramming.Scope;
|
||||
import org.teavm.metaprogramming.SourceLocation;
|
||||
import org.teavm.metaprogramming.Value;
|
||||
import org.teavm.metaprogramming.impl.reflect.ReflectClassImpl;
|
||||
import org.teavm.metaprogramming.impl.reflect.ReflectContext;
|
||||
import org.teavm.metaprogramming.impl.reflect.ReflectFieldImpl;
|
||||
import org.teavm.metaprogramming.impl.reflect.ReflectMethodImpl;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.ExitInstruction;
|
||||
import org.teavm.model.instructions.InvocationType;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
|
||||
public final class MetaprogrammingImpl {
|
||||
static ClassLoader classLoader;
|
||||
static ClassReaderSource classSource;
|
||||
static ReflectContext reflectContext;
|
||||
static DependencyAgent agent;
|
||||
static VariableContext varContext;
|
||||
static MethodReference templateMethod;
|
||||
static CompositeMethodGenerator generator;
|
||||
static ValueType returnType;
|
||||
|
||||
private MetaprogrammingImpl() {
|
||||
}
|
||||
|
||||
public static <T> Value<T> emit(Computation<T> computation) {
|
||||
unsupported();
|
||||
return null;
|
||||
if (computation instanceof ValueImpl<?>) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ValueImpl<T> valueImpl = (ValueImpl<T>) computation;
|
||||
Variable var = varContext.emitVariable(valueImpl, new CallLocation(templateMethod, generator.location));
|
||||
return new ValueImpl<>(var, varContext, valueImpl.type);
|
||||
} else if (computation instanceof LazyValueImpl<?>) {
|
||||
LazyValueImpl<?> valueImpl = (LazyValueImpl<?>) computation;
|
||||
Variable var = generator.lazy(valueImpl);
|
||||
return var != null ? new ValueImpl<>(var, varContext, valueImpl.type) : null;
|
||||
} else {
|
||||
Fragment fragment = (Fragment) computation;
|
||||
MethodReader method = classSource.resolve(fragment.method);
|
||||
generator.addProgram(method.getProgram(), fragment.capturedValues);
|
||||
return new ValueImpl<>(generator.getResultVar(), varContext, fragment.method.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
public static void emit(Action action) {
|
||||
unsupported();
|
||||
Fragment fragment = (Fragment) action;
|
||||
MethodReader method = classSource.resolve(fragment.method);
|
||||
generator.addProgram(method.getProgram(), fragment.capturedValues);
|
||||
}
|
||||
|
||||
public static <T> Value<T> lazyFragment(LazyComputation<T> computation) {
|
||||
unsupported();
|
||||
return null;
|
||||
return lazyFragment(ValueType.object("java.lang.Object"), computation);
|
||||
}
|
||||
|
||||
public static <T> Value<T> lazy(Computation<T> computation) {
|
||||
unsupported();
|
||||
return null;
|
||||
Fragment fragment = (Fragment) computation;
|
||||
return lazyFragment(fragment.method.getReturnType(), () -> emit(computation));
|
||||
}
|
||||
|
||||
public static Scope currentScope() {
|
||||
unsupported();
|
||||
return null;
|
||||
private static <T> Value<T> lazyFragment(ValueType type, LazyComputation<T> computation) {
|
||||
return new LazyValueImpl<>(varContext, computation, type, generator.forcedLocation);
|
||||
}
|
||||
|
||||
public static void exit(Value<?> value) {
|
||||
if (value == null) {
|
||||
returnValue(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Fragment) {
|
||||
Fragment fragment = (Fragment) value;
|
||||
MethodReader method = classSource.resolve(fragment.method);
|
||||
generator.addProgram(method.getProgram(), fragment.capturedValues);
|
||||
generator.blockIndex = generator.returnBlockIndex;
|
||||
|
||||
returnValue(unbox(generator.getResultVar()));
|
||||
} else if (value instanceof ValueImpl) {
|
||||
ValueImpl<?> valueImpl = (ValueImpl<?>) value;
|
||||
returnValue(unbox(varContext.emitVariable(valueImpl, new CallLocation(templateMethod,
|
||||
generator.location))));
|
||||
} else if (value instanceof LazyValueImpl) {
|
||||
Variable var = generator.lazy((LazyValueImpl<?>) value);
|
||||
returnValue(unbox(var));
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected computation type: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
static Variable unbox(Variable var) {
|
||||
if (returnType instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) returnType).getKind()) {
|
||||
case BOOLEAN:
|
||||
var = unbox(var, Boolean.class, boolean.class);
|
||||
break;
|
||||
case BYTE:
|
||||
var = unbox(var, Byte.class, byte.class);
|
||||
break;
|
||||
case SHORT:
|
||||
var = unbox(var, Short.class, short.class);
|
||||
break;
|
||||
case CHARACTER:
|
||||
var = unbox(var, Character.class, char.class);
|
||||
break;
|
||||
case INTEGER:
|
||||
var = unbox(var, Integer.class, int.class);
|
||||
break;
|
||||
case LONG:
|
||||
var = unbox(var, Long.class, long.class);
|
||||
break;
|
||||
case FLOAT:
|
||||
var = unbox(var, Float.class, float.class);
|
||||
break;
|
||||
case DOUBLE:
|
||||
var = unbox(var, Double.class, double.class);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
static Variable unbox(Variable var, Class<?> boxed, Class<?> primitive) {
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setInstance(var);
|
||||
insn.setType(InvocationType.VIRTUAL);
|
||||
insn.setMethod(new MethodReference(boxed, primitive.getName() + "Value", primitive));
|
||||
var = generator.program.createVariable();
|
||||
insn.setReceiver(var);
|
||||
generator.add(insn);
|
||||
return var;
|
||||
}
|
||||
|
||||
public static void exit() {
|
||||
exit(null);
|
||||
}
|
||||
|
||||
public static void location(String fileName, int lineNumber) {
|
||||
|
@ -88,8 +193,7 @@ public final class MetaprogrammingImpl {
|
|||
}
|
||||
|
||||
public static ReflectClass<?> createClass(byte[] bytecode) {
|
||||
unsupported();
|
||||
return null;
|
||||
return findClass(agent.submitClassFile(bytecode).replace('/', '.'));
|
||||
}
|
||||
|
||||
public static <T> Value<T> proxy(Class<T> type, InvocationHandler<T> handler) {
|
||||
|
@ -101,8 +205,58 @@ public final class MetaprogrammingImpl {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static void returnValue(Variable var) {
|
||||
ExitInstruction insn = new ExitInstruction();
|
||||
insn.setValueToReturn(var);
|
||||
generator.add(insn);
|
||||
}
|
||||
|
||||
public static Diagnostics getDiagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public void submitClass(ClassHolder cls) {
|
||||
agent.submitClass(cls);
|
||||
}
|
||||
|
||||
private static void unsupported() {
|
||||
throw new UnsupportedOperationException("This operation is only supported from TeaVM compile-time "
|
||||
+ "environment");
|
||||
}
|
||||
|
||||
private static Diagnostics diagnostics = new Diagnostics() {
|
||||
@Override
|
||||
public void error(SourceLocation location, String error, Object... params) {
|
||||
convertParams(params);
|
||||
agent.getDiagnostics().error(convertLocation(location), error, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(SourceLocation location, String error, Object... params) {
|
||||
convertParams(params);
|
||||
agent.getDiagnostics().warning(convertLocation(location), error, params);
|
||||
}
|
||||
|
||||
private void convertParams(Object[] params) {
|
||||
for (int i = 0; i < params.length; ++i) {
|
||||
if (params[i] instanceof ReflectMethodImpl) {
|
||||
params[i] = ((ReflectMethodImpl) params[i]).method.getReference();
|
||||
} else if (params[i] instanceof ReflectClassImpl) {
|
||||
params[i] = ((ReflectClassImpl<?>) params[i]).type;
|
||||
} else if (params[i] instanceof ReflectFieldImpl) {
|
||||
params[i] = ((ReflectFieldImpl) params[i]).field.getReference();
|
||||
} else if (params[i] instanceof Class<?>) {
|
||||
params[i] = ValueType.parse((Class<?>) params[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CallLocation convertLocation(SourceLocation location) {
|
||||
MethodReader method = ((ReflectMethodImpl) location.getMethod()).method;
|
||||
return location.getFileName() != null
|
||||
? new CallLocation(method.getReference(),
|
||||
new InstructionLocation(location.getFileName(), location.getLineNumber()))
|
||||
: new CallLocation(method.getReference());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -27,9 +27,19 @@
|
|||
</parent>
|
||||
<artifactId>teavm-metaprogramming-api</artifactId>
|
||||
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<name>TeaVM metaprogramming API</name>
|
||||
<description>Declaration of interfaces and annotations for TeaVM metaprogramming</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -47,6 +57,17 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
|
|
|
@ -39,9 +39,12 @@ public final class Metaprogramming {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Scope currentScope() {
|
||||
public static void exit(Value<?> returnValue) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public static void exit() {
|
||||
unsupported();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void location(String fileName, int lineNumber) {
|
||||
|
@ -86,6 +89,11 @@ public final class Metaprogramming {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Diagnostics getDiagnostics() {
|
||||
unsupported();
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void unsupported() {
|
||||
throw new UnsupportedOperationException("This operation is only supported from TeaVM compile-time "
|
||||
+ "environment");
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.metaprogramming;
|
||||
|
||||
public interface Scope {
|
||||
void exit(Object returnValue);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2016 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.metaprogramming.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.teavm.metaprogramming.Metaprogramming.exit;
|
||||
import org.junit.Test;
|
||||
import org.teavm.metaprogramming.CompileTime;
|
||||
import org.teavm.metaprogramming.Meta;
|
||||
import org.teavm.metaprogramming.ReflectClass;
|
||||
import org.teavm.metaprogramming.Value;
|
||||
|
||||
@CompileTime
|
||||
public class MetaprogrammingTest {
|
||||
@Test
|
||||
public void works() {
|
||||
assertEquals("java.lang.Object".length() + 2, classNameLength(Object.class, 2));
|
||||
assertEquals("java.lang.Integer".length() + 3, classNameLength(Integer.valueOf(5).getClass(), 3));
|
||||
}
|
||||
|
||||
@Meta
|
||||
static native int classNameLength(Class<?> cls, int add);
|
||||
static void classNameLength(ReflectClass<Object> cls, Value<Integer> add) {
|
||||
int length = cls.getName().length();
|
||||
exit(() -> length + add.get());
|
||||
}
|
||||
}
|
|
@ -1,13 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="Osmorc" name="OSGi">
|
||||
<configuration manifestGenerationMode="OsmorcControlled" manifestLocation="" jarfileLocation="teavm-metaprogramming-api-1.0.0-SNAPSHOT.jar" outputPathType="CompilerOutputPath" bndFileLocation="" bundlorFileLocation="" bundleActivator="" bundleSymbolicName="teavm-metaprogramming-api" bundleVersion="1.0.0.SNAPSHOT" ignoreFilePattern="" useProjectDefaultManifestFileLocation="true" alwaysRebuildBundleJAR="false" doNotSynchronizeWithMaven="false">
|
||||
<additionalProperties>
|
||||
<property key="Bundle-Description" value="Declaration of interfaces and annotations for TeaVM metaprogramming" />
|
||||
<property key="Export-Package" value="org.teavm.metaprogramming.*" />
|
||||
<property key="Bundle-Name" value="TeaVM metaprogramming API" />
|
||||
</additionalProperties>
|
||||
<additionalJARContents />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.11" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -55,6 +55,13 @@
|
|||
<classifier>tests</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-metaprogramming-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<orderEntry type="module" module-name="teavm-platform" />
|
||||
<orderEntry type="module" module-name="teavm-jso-apis" />
|
||||
<orderEntry type="module" module-name="teavm-jso-apis" production-on-test="" />
|
||||
<orderEntry type="module" module-name="teavm-metaprogramming-api" production-on-test="" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.11" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
||||
<orderEntry type="module" module-name="teavm-tooling" scope="TEST" />
|
||||
|
|
Loading…
Reference in New Issue
Block a user