first "OK" closure test.
This commit is contained in:
Generated
-3
@@ -1,8 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DependencyValidationManager">
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</component>
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
|
||||
@@ -19,14 +19,16 @@ public abstract class ClassBodyCodegen {
|
||||
protected final BindingContext bindingContext;
|
||||
protected final JetStandardLibrary stdlib;
|
||||
protected final JetTypeMapper typeMapper;
|
||||
protected final Codegens factory;
|
||||
protected final JetClassOrObject myClass;
|
||||
protected final OwnerKind kind;
|
||||
protected final ClassDescriptor descriptor;
|
||||
protected final ClassVisitor v;
|
||||
|
||||
public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, OwnerKind kind, ClassVisitor v) {
|
||||
public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, Codegens factory) {
|
||||
this.bindingContext = bindingContext;
|
||||
this.stdlib = stdlib;
|
||||
this.factory = factory;
|
||||
this.typeMapper = new JetTypeMapper(stdlib, bindingContext);
|
||||
descriptor = bindingContext.getClassDescriptor(aClass);
|
||||
myClass = aClass;
|
||||
@@ -50,7 +52,7 @@ public abstract class ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateClassBody() {
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, stdlib, bindingContext);
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, stdlib, bindingContext, factory);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
|
||||
|
||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ClassCodegen {
|
||||
|
||||
private void generateInterface(JetClassOrObject aClass) {
|
||||
final ClassVisitor visitor = factory.forClassInterface(bindingContext.getClassDescriptor(aClass));
|
||||
new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor).generate();
|
||||
new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor, factory).generate();
|
||||
}
|
||||
|
||||
private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) {
|
||||
@@ -53,7 +53,7 @@ public class ClassCodegen {
|
||||
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
|
||||
? factory.forClassImplementation(descriptor)
|
||||
: factory.forClassDelegatingImplementation(descriptor);
|
||||
new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v).generate();
|
||||
new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v, factory).generate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
import org.objectweb.asm.signature.SignatureWriter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ClosureCodegen {
|
||||
private final BindingContext bindingContext;
|
||||
private final JetTypeMapper typeMapper;
|
||||
private final Codegens factory;
|
||||
|
||||
public ClosureCodegen(BindingContext bindingContext, JetTypeMapper typeMapper, Codegens factory) {
|
||||
this.bindingContext = bindingContext;
|
||||
this.typeMapper = typeMapper;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
|
||||
boolean isExtensionFunction = fd.getReceiverType() != null;
|
||||
int paramCount = fd.getUnsubstitutedValueParameters().size();
|
||||
if (isExtensionFunction) {
|
||||
paramCount++;
|
||||
}
|
||||
|
||||
Type[] args = new Type[paramCount];
|
||||
Arrays.fill(args, JetTypeMapper.TYPE_OBJECT);
|
||||
return new Method("invoke", JetTypeMapper.TYPE_OBJECT, args);
|
||||
}
|
||||
|
||||
public Method invokeSignature(FunctionDescriptor fd) {
|
||||
return typeMapper.mapSignature("invoke", fd);
|
||||
}
|
||||
|
||||
public GeneratedClosureDescriptor gen(JetFunctionLiteralExpression fun) {
|
||||
JetNamedDeclaration container = PsiTreeUtil.getParentOfType(fun, JetNamespace.class, JetClass.class, JetObjectDeclaration.class);
|
||||
|
||||
final Pair<String, ClassVisitor> nameAndVisitor;
|
||||
if (container instanceof JetNamespace) {
|
||||
nameAndVisitor = factory.forClosureIn((JetNamespace) container);
|
||||
}
|
||||
else {
|
||||
nameAndVisitor = factory.forClosureIn(bindingContext.getClassDescriptor((JetClassOrObject) container));
|
||||
}
|
||||
|
||||
|
||||
final FunctionDescriptor funDescriptor = (FunctionDescriptor) bindingContext.getDeclarationDescriptor(fun);
|
||||
|
||||
final ClassVisitor cv = nameAndVisitor.getSecond();
|
||||
final String name = nameAndVisitor.getFirst();
|
||||
|
||||
SignatureWriter signatureWriter = new SignatureWriter();
|
||||
|
||||
final List<ValueParameterDescriptor> parameters = funDescriptor.getUnsubstitutedValueParameters();
|
||||
final String funClass = getInternalClassName(funDescriptor);
|
||||
signatureWriter.visitClassType(funClass);
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
appendType(signatureWriter, parameter.getOutType(), '=');
|
||||
}
|
||||
|
||||
appendType(signatureWriter, funDescriptor.getUnsubstitutedReturnType(), '=');
|
||||
signatureWriter.visitEnd();
|
||||
|
||||
cv.visit(Opcodes.V1_6,
|
||||
Opcodes.ACC_PUBLIC,
|
||||
name,
|
||||
null,
|
||||
funClass,
|
||||
new String[0]
|
||||
);
|
||||
|
||||
final Method constructor = generateConstructor(cv, funClass);
|
||||
|
||||
generateBridge(name, funDescriptor, cv);
|
||||
generateBody(name, funDescriptor, cv, container.getProject(), fun.getBody());
|
||||
|
||||
cv.visitEnd();
|
||||
|
||||
return new GeneratedClosureDescriptor(name, constructor);
|
||||
}
|
||||
|
||||
private void generateBody(String className, FunctionDescriptor funDescriptor, ClassVisitor cv, Project project, List<JetElement> body) {
|
||||
FunctionCodegen fc = new FunctionCodegen(null, cv, JetStandardLibrary.getJetStandardLibrary(project), bindingContext, factory);
|
||||
fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), null, funDescriptor.getUnsubstitutedValueParameters(), null);
|
||||
}
|
||||
|
||||
private void generateBridge(String className, FunctionDescriptor funDescriptor, ClassVisitor cv) {
|
||||
final Method bridge = erasedInvokeSignature(funDescriptor);
|
||||
|
||||
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "invoke", bridge.getDescriptor(), typeMapper.genericSignature(funDescriptor), new String[0]);
|
||||
mv.visitCode();
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
iv.load(0, Type.getObjectType(className));
|
||||
|
||||
final List<ValueParameterDescriptor> params = funDescriptor.getUnsubstitutedValueParameters();
|
||||
int count = 1;
|
||||
for (ValueParameterDescriptor param : params) {
|
||||
iv.load(count, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.checkcast(typeMapper.mapType(param.getOutType()));
|
||||
count++;
|
||||
}
|
||||
|
||||
iv.invokespecial(className, "invoke", invokeSignature(funDescriptor).getDescriptor());
|
||||
iv.areturn(JetTypeMapper.TYPE_OBJECT);
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private Method generateConstructor(ClassVisitor cv, String funClass) {
|
||||
final Method constructor = new Method("<init>", Type.VOID_TYPE, new Type[0]); // TODO:
|
||||
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
iv.load(0, Type.getObjectType(funClass));
|
||||
iv.invokespecial(funClass, "<init>", "()V");
|
||||
|
||||
iv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
return constructor;
|
||||
}
|
||||
|
||||
public static String getInternalClassName(FunctionDescriptor descriptor) {
|
||||
final int paramCount = descriptor.getUnsubstitutedValueParameters().size();
|
||||
if (descriptor.getReceiverType() != null) {
|
||||
return "jet/ExtensionFunction" + paramCount;
|
||||
}
|
||||
else {
|
||||
return "jet/Function" + paramCount;
|
||||
}
|
||||
}
|
||||
|
||||
private void appendType(SignatureWriter signatureWriter, JetType type, char variance) {
|
||||
signatureWriter.visitTypeArgument(variance);
|
||||
|
||||
final Type rawRetType = typeMapper.boxType(typeMapper.mapType(type));
|
||||
signatureWriter.visitClassType(rawRetType.getInternalName());
|
||||
signatureWriter.visitEnd();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -20,6 +21,7 @@ public class Codegens {
|
||||
private final boolean isText;
|
||||
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
|
||||
private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>();
|
||||
private final Map<String, Integer> closuresCount = new HashMap<String, Integer>();
|
||||
private boolean isDone = false;
|
||||
|
||||
public Codegens(Project project, boolean text) {
|
||||
@@ -56,6 +58,24 @@ public class Codegens {
|
||||
return newVisitor(JetTypeMapper.jvmNameForDelegatingImplementation(aClass) + ".class");
|
||||
}
|
||||
|
||||
public Pair<String, ClassVisitor> forClosureIn(ClassDescriptor aClass) {
|
||||
return forClosureIn(JetTypeMapper.jvmNameForInterface(aClass));
|
||||
}
|
||||
|
||||
public Pair<String, ClassVisitor> forClosureIn(JetNamespace namespace) {
|
||||
return forClosureIn(NamespaceCodegen.getJVMClassName(namespace.getFQName()));
|
||||
}
|
||||
|
||||
private Pair<String, ClassVisitor> forClosureIn(String baseName) {
|
||||
Integer count = closuresCount.get(baseName);
|
||||
if (count == null) count = 0;
|
||||
|
||||
closuresCount.put(baseName, count + 1);
|
||||
|
||||
final String className = baseName + "$" + (count + 1);
|
||||
return new Pair<String, ClassVisitor>(className, newVisitor(className + ".class"));
|
||||
}
|
||||
|
||||
public NamespaceCodegen forNamespace(JetNamespace namespace) {
|
||||
assert !isDone : "Already done!";
|
||||
String fqName = namespace.getFQName();
|
||||
|
||||
@@ -12,10 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
import org.objectweb.asm.Label;
|
||||
@@ -64,6 +61,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
private final InstructionAdapter v;
|
||||
private final FrameMap myMap;
|
||||
private final JetTypeMapper typeMapper;
|
||||
private final Codegens factory;
|
||||
private final Type returnType;
|
||||
private final DeclarationDescriptor contextType;
|
||||
private final OwnerKind contextKind;
|
||||
@@ -78,12 +76,14 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
Type returnType,
|
||||
DeclarationDescriptor contextType,
|
||||
OwnerKind contextKind,
|
||||
@Nullable StackValue thisExpression) {
|
||||
@Nullable StackValue thisExpression,
|
||||
Codegens factory) {
|
||||
this.myMap = myMap;
|
||||
this.typeMapper = typeMapper;
|
||||
this.returnType = returnType;
|
||||
this.contextType = contextType;
|
||||
this.contextKind = contextKind;
|
||||
this.factory = factory;
|
||||
this.v = new InstructionAdapter(v);
|
||||
this.bindingContext = bindingContext;
|
||||
this.thisExpression = thisExpression;
|
||||
@@ -481,7 +481,10 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
generateBlock(expression.getBody());
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("don't know how to generate non-block function literals");
|
||||
final GeneratedClosureDescriptor closure = new ClosureCodegen(bindingContext, typeMapper, factory).gen(expression);
|
||||
v.anew(Type.getObjectType(closure.getClassname()));
|
||||
v.dup();
|
||||
v.invokespecial(closure.getClassname(), "<init>", closure.getConstructor().getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +546,12 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
|
||||
@Override
|
||||
public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
|
||||
final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression);
|
||||
DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression);
|
||||
|
||||
if (descriptor instanceof VariableAsFunctionDescriptor) {
|
||||
descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
|
||||
}
|
||||
|
||||
final DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
if (descriptor instanceof VariableDescriptor) {
|
||||
if (isClass(container, "Number")) {
|
||||
@@ -702,13 +710,14 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
|
||||
|
||||
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor);
|
||||
final FunctionDescriptor fd = (FunctionDescriptor) funDescriptor;
|
||||
if (declarationPsiElement == null && isClass(functionParent, "String")) {
|
||||
final Project project = expression.getProject();
|
||||
PsiClass jlString = JavaPsiFacade.getInstance(project).findClass("java.lang.String",
|
||||
ProjectScope.getAllScope(project));
|
||||
// TODO better overload mapping
|
||||
final PsiMethod[] methods = jlString.findMethodsByName(funDescriptor.getName(), false);
|
||||
final int arity = ((FunctionDescriptor) funDescriptor).getUnsubstitutedValueParameters().size();
|
||||
final int arity = fd.getUnsubstitutedValueParameters().size();
|
||||
for (PsiMethod method : methods) {
|
||||
if (method.getParameterList().getParametersCount() == arity) {
|
||||
declarationPsiElement = method;
|
||||
@@ -744,7 +753,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
methodDescriptor.getName(),
|
||||
methodDescriptor.getDescriptor());
|
||||
}
|
||||
else {
|
||||
else if(declarationPsiElement instanceof JetFunction) {
|
||||
final JetFunction jetFunction = (JetFunction) declarationPsiElement;
|
||||
methodDescriptor = typeMapper.mapSignature(jetFunction);
|
||||
if (functionParent instanceof NamespaceDescriptorImpl) {
|
||||
@@ -765,8 +774,25 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
throw new UnsupportedOperationException("don't know how to generate call to " + declarationPsiElement);
|
||||
}
|
||||
}
|
||||
else {
|
||||
gen(callee, Type.getObjectType(ClosureCodegen.getInternalClassName(fd)));
|
||||
|
||||
boolean isExtensionFunction = fd.getReceiverType() != null;
|
||||
int paramCount = fd.getUnsubstitutedValueParameters().size();
|
||||
if (isExtensionFunction) {
|
||||
ensureReceiverOnStack(expression, null);
|
||||
paramCount++;
|
||||
}
|
||||
|
||||
methodDescriptor = ClosureCodegen.erasedInvokeSignature(fd);
|
||||
pushMethodArguments(expression, methodDescriptor);
|
||||
v.invokevirtual(ClosureCodegen.getInternalClassName(fd), "invoke", methodDescriptor.getDescriptor());
|
||||
}
|
||||
|
||||
if (methodDescriptor.getReturnType() != Type.VOID_TYPE) {
|
||||
myStack.push(StackValue.onStack(methodDescriptor.getReturnType()));
|
||||
final Type retType = typeMapper.mapType(fd.getUnsubstitutedReturnType());
|
||||
StackValue.onStack(methodDescriptor.getReturnType()).put(retType, v);
|
||||
myStack.push(StackValue.onStack(retType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -24,11 +25,13 @@ public class FunctionCodegen {
|
||||
private final ClassVisitor v;
|
||||
private final BindingContext bindingContext;
|
||||
private final JetTypeMapper typeMapper;
|
||||
private final Codegens factory;
|
||||
|
||||
public FunctionCodegen(JetDeclaration owner, ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||
public FunctionCodegen(JetDeclaration owner, ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext bindingContext, Codegens factory) {
|
||||
this.owner = owner;
|
||||
this.v = v;
|
||||
this.bindingContext = bindingContext;
|
||||
this.factory = factory;
|
||||
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||
}
|
||||
|
||||
@@ -45,23 +48,33 @@ public class FunctionCodegen {
|
||||
Method jvmSignature,
|
||||
@Nullable JetType receiverType,
|
||||
List<ValueParameterDescriptor> paramDescrs) {
|
||||
final DeclarationDescriptor contextDesc = owner instanceof JetClassOrObject
|
||||
? bindingContext.getClassDescriptor((JetClassOrObject) owner)
|
||||
: bindingContext.getNamespaceDescriptor((JetNamespace) owner);
|
||||
final JetExpression bodyExpression = f.getBodyExpression();
|
||||
final List<JetElement> bodyExpressions = bodyExpression != null ? Collections.<JetElement>singletonList(bodyExpression) : null;
|
||||
generatedMethod(bodyExpressions, kind, jvmSignature, receiverType, paramDescrs, contextDesc);
|
||||
}
|
||||
|
||||
public void generatedMethod(List<JetElement> bodyExpressions,
|
||||
OwnerKind kind,
|
||||
Method jvmSignature,
|
||||
JetType receiverType,
|
||||
List<ValueParameterDescriptor> paramDescrs,
|
||||
DeclarationDescriptor contextDesc)
|
||||
{
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
|
||||
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
||||
if (isStatic) flags |= Opcodes.ACC_STATIC;
|
||||
|
||||
final JetExpression bodyExpression = f.getBodyExpression();
|
||||
boolean isAbstract = kind == OwnerKind.INTERFACE || bodyExpression == null;
|
||||
boolean isAbstract = kind == OwnerKind.INTERFACE || bodyExpressions == null;
|
||||
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
|
||||
|
||||
if (isAbstract && (kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DeclarationDescriptor contextDescriptor = owner instanceof JetClassOrObject
|
||||
? bindingContext.getClassDescriptor((JetClassOrObject) owner)
|
||||
: bindingContext.getNamespaceDescriptor((JetNamespace) owner);
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||
if (kind != OwnerKind.INTERFACE) {
|
||||
mv.visitCode();
|
||||
@@ -79,7 +92,7 @@ public class FunctionCodegen {
|
||||
|
||||
StackValue thisExpression = receiverType == null ? null : StackValue.local(0, typeMapper.mapType(receiverType));
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper,
|
||||
jvmSignature.getReturnType(), contextDescriptor, kind, thisExpression);
|
||||
jvmSignature.getReturnType(), contextDesc, kind, thisExpression, factory);
|
||||
if (kind instanceof OwnerKind.DelegateKind) {
|
||||
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
@@ -93,15 +106,19 @@ public class FunctionCodegen {
|
||||
iv.areturn(jvmSignature.getReturnType());
|
||||
}
|
||||
else if (!isAbstract) {
|
||||
bodyExpression.accept(codegen);
|
||||
generateReturn(mv, bodyExpression, codegen, jvmSignature);
|
||||
JetElement last = null;
|
||||
for (JetElement expression : bodyExpressions) {
|
||||
expression.accept(codegen);
|
||||
last = expression;
|
||||
}
|
||||
generateReturn(mv, last, codegen, jvmSignature);
|
||||
}
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void generateReturn(MethodVisitor mv, JetExpression bodyExpression, ExpressionCodegen codegen, Method jvmSignature) {
|
||||
private void generateReturn(MethodVisitor mv, JetElement bodyExpression, ExpressionCodegen codegen, Method jvmSignature) {
|
||||
if (!endsWithReturn(bodyExpression)) {
|
||||
if (jvmSignature.getReturnType() == Type.VOID_TYPE) {
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
@@ -112,11 +129,12 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean endsWithReturn(JetExpression bodyExpression) {
|
||||
private static boolean endsWithReturn(JetElement bodyExpression) {
|
||||
if (bodyExpression instanceof JetBlockExpression) {
|
||||
final List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements();
|
||||
return statements.size() > 0 && statements.get(statements.size()-1) instanceof JetReturnExpression;
|
||||
}
|
||||
return false;
|
||||
|
||||
return bodyExpression instanceof JetReturnExpression;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
public class GeneratedClosureDescriptor {
|
||||
private final String classname;
|
||||
private Method constructor;
|
||||
|
||||
public GeneratedClosureDescriptor(String classname, Method constructor) {
|
||||
this.classname = classname;
|
||||
this.constructor = constructor;
|
||||
}
|
||||
|
||||
public String getClassname() {
|
||||
return classname;
|
||||
}
|
||||
|
||||
public Method getConstructor() {
|
||||
return constructor;
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,8 @@ import java.util.*;
|
||||
*/
|
||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass,
|
||||
OwnerKind kind, ClassVisitor v) {
|
||||
super(bindingContext, stdlib, aClass, kind, v);
|
||||
OwnerKind kind, ClassVisitor v, Codegens factory) {
|
||||
super(bindingContext, stdlib, aClass, kind, v, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,7 +109,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE,
|
||||
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)));
|
||||
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)), factory);
|
||||
|
||||
String classname = typeMapper.jvmName(descriptor, kind);
|
||||
final Type classType = Type.getType("L" + classname + ";");
|
||||
@@ -289,7 +289,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE,
|
||||
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)));
|
||||
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)), factory);
|
||||
|
||||
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
|
||||
if (initializer instanceof JetDelegatorToThisCall) {
|
||||
@@ -355,7 +355,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) {
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext);
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext, factory);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
|
||||
|
||||
for (JetDeclaration declaration : toClass.getDeclarations()) {
|
||||
|
||||
@@ -19,8 +19,8 @@ import java.util.Set;
|
||||
* @author yole
|
||||
*/
|
||||
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
||||
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v) {
|
||||
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v);
|
||||
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v, Codegens factory) {
|
||||
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v, factory);
|
||||
}
|
||||
|
||||
protected void generateDeclaration() {
|
||||
|
||||
@@ -219,6 +219,38 @@ public class JetTypeMapper {
|
||||
throw new UnsupportedOperationException("Unknown type " + jetType);
|
||||
}
|
||||
|
||||
public Type boxType(Type asmType) {
|
||||
switch (asmType.getSort()) {
|
||||
case Type.VOID:
|
||||
return Type.getObjectType("java/lang/Void");
|
||||
case Type.BYTE:
|
||||
return Type.getObjectType("java/lang/Byte");
|
||||
case Type.BOOLEAN:
|
||||
return Type.getObjectType("java/lang/Boolean");
|
||||
case Type.SHORT:
|
||||
return Type.getObjectType("java/lang.Short");
|
||||
case Type.CHAR:
|
||||
return Type.getObjectType("java/lang/Character");
|
||||
case Type.INT:
|
||||
return Type.getObjectType("java/lang/Integer");
|
||||
case Type.FLOAT:
|
||||
return Type.getObjectType("java/lang/Float");
|
||||
case Type.LONG:
|
||||
return Type.getObjectType("java/lang/Long");
|
||||
case Type.DOUBLE:
|
||||
return Type.getObjectType("java/lang/Double");
|
||||
}
|
||||
|
||||
return asmType;
|
||||
}
|
||||
|
||||
|
||||
private static Type getBoxedType(final Type type) {
|
||||
switch (type.getSort()) {
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public Method mapSignature(JetFunction f) {
|
||||
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
|
||||
final JetType receiverType = receiverTypeRef == null ? null : bindingContext.resolveTypeReference(receiverTypeRef);
|
||||
@@ -243,6 +275,50 @@ public class JetTypeMapper {
|
||||
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
}
|
||||
|
||||
public Method mapSignature(String name, FunctionDescriptor f) {
|
||||
final JetType receiverType = f.getReceiverType();
|
||||
final List<ValueParameterDescriptor> parameters = f.getUnsubstitutedValueParameters();
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
if (receiverType != null) {
|
||||
parameterTypes.add(mapType(receiverType));
|
||||
}
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
parameterTypes.add(mapType(parameter.getOutType()));
|
||||
}
|
||||
Type returnType = mapType(f.getUnsubstitutedReturnType());
|
||||
return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
}
|
||||
|
||||
public String genericSignature(FunctionDescriptor f) {
|
||||
StringBuffer answer = new StringBuffer();
|
||||
final List<TypeParameterDescriptor> typeParameters = f.getTypeParameters();
|
||||
if (!typeParameters.isEmpty()) {
|
||||
answer.append('<');
|
||||
for (TypeParameterDescriptor p : typeParameters) {
|
||||
appendTypeParameterSignature(answer, p);
|
||||
}
|
||||
answer.append('>');
|
||||
}
|
||||
|
||||
answer.append('(');
|
||||
for (ValueParameterDescriptor p : f.getUnsubstitutedValueParameters()) {
|
||||
appendType(answer, p.getOutType());
|
||||
}
|
||||
answer.append(')');
|
||||
|
||||
appendType(answer, f.getUnsubstitutedReturnType());
|
||||
|
||||
return answer.toString();
|
||||
}
|
||||
|
||||
private void appendType(StringBuffer answer, JetType type) {
|
||||
answer.append(mapType(type).getDescriptor()); // TODO: type parameter references!
|
||||
}
|
||||
|
||||
private void appendTypeParameterSignature(StringBuffer answer, TypeParameterDescriptor p) {
|
||||
answer.append(p.getName()); // TODO: BOUND!
|
||||
}
|
||||
|
||||
public Method mapGetterSignature(PropertyDescriptor descriptor) {
|
||||
Type returnType = mapType(descriptor.getOutType());
|
||||
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
|
||||
|
||||
@@ -45,7 +45,7 @@ public class NamespaceCodegen {
|
||||
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext);
|
||||
|
||||
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, standardLibrary, bindingContext);
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, standardLibrary, bindingContext, codegens);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen);
|
||||
final ClassCodegen classCodegen = codegens.forClass(bindingContext);
|
||||
|
||||
@@ -81,7 +81,7 @@ public class NamespaceCodegen {
|
||||
|
||||
FrameMap frameMap = new FrameMap();
|
||||
JetTypeMapper typeMapper = new JetTypeMapper(JetStandardLibrary.getJetStandardLibrary(namespace.getProject()), bindingContext);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, null, OwnerKind.NAMESPACE, null);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, null, OwnerKind.NAMESPACE, null, codegens);
|
||||
|
||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
|
||||
@@ -131,13 +131,18 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
protected void coerce(Type type, InstructionAdapter v) {
|
||||
if (type.getSort() == Type.OBJECT) {
|
||||
if (type.equals(this.type)) return;
|
||||
|
||||
if (type.getSort() == Type.OBJECT && this.type.getSort() == Type.OBJECT) {
|
||||
v.checkcast(type);
|
||||
}
|
||||
else if (type.getSort() == Type.OBJECT) {
|
||||
box(this.type, type, v);
|
||||
}
|
||||
else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
|
||||
unbox(type, v);
|
||||
}
|
||||
else if (type != this.type) {
|
||||
else {
|
||||
v.cast(this.type, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
fun box() : String {
|
||||
return if (invoker({49}) == 49) "OK" else "fail"
|
||||
return invoker( {"OK"} )
|
||||
}
|
||||
|
||||
fun invoker(gen : {() : Int}) : Int {
|
||||
fun invoker(gen : {() : String}) : String {
|
||||
return gen()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +71,9 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
|
||||
} catch (NoClassDefFoundError e) {
|
||||
System.out.println(generateToText());
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
System.out.println(generateToText());
|
||||
throw e;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
assertEquals("OK", actual);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package jet;
|
||||
|
||||
public abstract class ExtensionFunction0<E, R> {
|
||||
public abstract R invoke(E receiver);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{E.() : R}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package jet;
|
||||
|
||||
public abstract class ExtensionFunction1<E, D, R> {
|
||||
public abstract R invoke(E receiver, D d);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{E.(d: D) : R}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package jet;
|
||||
|
||||
public abstract class ExtensionFunction2<E, D1, D2, R> {
|
||||
public abstract R invoke(E receiver, D1 d1, D2 d2);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{E.(d1: D1, d2: D2) : R}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package jet;
|
||||
|
||||
public abstract class ExtensionFunction3<E, D1, D2, D3, R> {
|
||||
public abstract R invoke(E receiver, D1 d1, D2 d2, D3 d3);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{E.(d1: D1, d2: D2, d3: D3) : R}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package jet;
|
||||
|
||||
public abstract class Function0<R> {
|
||||
public abstract R invoke();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{() : R}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package jet;
|
||||
|
||||
public abstract class Function1<D, R> {
|
||||
public abstract R invoke(D d);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{(d: D) : R}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package jet;
|
||||
|
||||
public abstract class Function2<D1, D2, R> {
|
||||
public abstract R invoke(D1 d1, D2 d2);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{(d1: D1, d2: D2) : R}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package jet;
|
||||
|
||||
public abstract class Function3<D1, D2, D3, R> {
|
||||
public abstract R invoke(D1 d1, D2 d2, D3 d3);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{(d1: D1, d2: D2, d3: D3) : R}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user