Files
CraftTweaker/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionJavaLambda.java
T

102 lines
3.1 KiB
Java
Raw Normal View History

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.expression;
import java.lang.reflect.Method;
import java.util.List;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import stanhebben.zenscript.compiler.EnvironmentClass;
import stanhebben.zenscript.compiler.IEnvironmentMethod;
import stanhebben.zenscript.compiler.EnvironmentMethod;
import stanhebben.zenscript.compiler.IEnvironmentClass;
import stanhebben.zenscript.definitions.ParsedFunctionArgument;
import stanhebben.zenscript.statements.Statement;
import stanhebben.zenscript.symbols.SymbolArgument;
import stanhebben.zenscript.type.ZenType;
import stanhebben.zenscript.util.MethodOutput;
import stanhebben.zenscript.util.ZenPosition;
import static stanhebben.zenscript.util.ZenTypeUtil.descriptor;
import static stanhebben.zenscript.util.ZenTypeUtil.internal;
/**
*
* @author Stanneke
*/
public class ExpressionJavaLambda extends Expression {
private final Class interfaceClass;
private final List<ParsedFunctionArgument> arguments;
private final List<Statement> statements;
2015-08-31 19:15:35 +02:00
private final ZenType type;
2015-08-31 19:15:35 +02:00
public ExpressionJavaLambda(
ZenPosition position,
Class interfaceClass,
List<ParsedFunctionArgument> arguments,
List<Statement> statements,
ZenType type) {
super(position);
2015-08-31 19:15:35 +02:00
this.interfaceClass = interfaceClass;
this.arguments = arguments;
this.statements = statements;
2015-08-31 19:15:35 +02:00
this.type = type;
}
@Override
public ZenType getType() {
return type;
}
@Override
public void compile(boolean result, IEnvironmentMethod environment) {
2015-08-31 19:15:35 +02:00
if (!result)
return;
Method method = interfaceClass.getMethods()[0];
2015-08-31 19:15:35 +02:00
// generate class
String clsName = environment.makeClassName();
2015-08-31 19:15:35 +02:00
2014-07-04 22:03:03 +02:00
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, clsName, null, "java/lang/Object", new String[] { internal(interfaceClass) });
2015-08-31 19:15:35 +02:00
MethodOutput constructor = new MethodOutput(cw, Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
constructor.start();
constructor.loadObject(0);
constructor.invokeSpecial("java/lang/Object", "<init>", "()V");
constructor.ret();
constructor.end();
2015-08-31 19:15:35 +02:00
MethodOutput output = new MethodOutput(cw, Opcodes.ACC_PUBLIC, method.getName(), descriptor(method), null, null);
2015-08-31 19:15:35 +02:00
IEnvironmentClass environmentClass = new EnvironmentClass(cw, environment);
IEnvironmentMethod environmentMethod = new EnvironmentMethod(output, environmentClass);
2015-08-31 19:15:35 +02:00
for (int i = 0; i < arguments.size(); i++) {
environmentMethod.putValue(
arguments.get(i).getName(),
new SymbolArgument(i + 1, environment.getType(method.getGenericParameterTypes()[i])),
getPosition());
}
2015-08-31 19:15:35 +02:00
output.start();
for (Statement statement : statements) {
statement.compile(environmentMethod);
}
output.end();
2015-08-31 19:15:35 +02:00
environment.putClass(clsName, cw.toByteArray());
2015-08-31 19:15:35 +02:00
// make class instance
environment.getOutput().newObject(clsName);
environment.getOutput().dup();
environment.getOutput().construct(clsName);
}
}