refactoring of property handling and general handling of (this,receiver)

This commit is contained in:
Alex Tkachman
2011-12-01 12:58:20 +02:00
parent aad2d17cd8
commit 74fe24ef80
10 changed files with 427 additions and 423 deletions
@@ -5,6 +5,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
@@ -53,6 +54,14 @@ public class CallableMethod implements Callable {
this.receiverFunction = receiverClass; this.receiverFunction = receiverClass;
} }
public JetType getThisType() {
return thisClass.getDefaultType();
}
public JetType getReceiverClass() {
return receiverFunction.getReceiverParameter().getType();
}
public void setNeedsThis(@Nullable ClassDescriptor receiverClass) { public void setNeedsThis(@Nullable ClassDescriptor receiverClass) {
this.thisClass = receiverClass; this.thisClass = receiverClass;
} }
@@ -5,8 +5,11 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunctionLiteral; import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -123,7 +126,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
return answer; return answer;
} }
private void generateConstInstance(JetFunctionLiteralExpression fun) { private void generateConstInstance(PsiElement fun) {
String classDescr = "L" + name + ";"; String classDescr = "L" + name + ";";
cv.newField(fun, ACC_PRIVATE | ACC_STATIC, "$instance", classDescr, null, null); cv.newField(fun, ACC_PRIVATE | ACC_STATIC, "$instance", classDescr, null, null);
@@ -149,7 +152,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
} }
} }
private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) { private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) {
int arity = funDescriptor.getValueParameters().size(); int arity = funDescriptor.getValueParameters().size();
ClassDescriptorImpl function = new ClassDescriptorImpl( ClassDescriptorImpl function = new ClassDescriptorImpl(
@@ -167,7 +170,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
return closureContext.outerWasUsed; return closureContext.outerWasUsed;
} }
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) { private void generateBridge(String className, FunctionDescriptor funDescriptor, JetExpression fun, ClassBuilder cv) {
final Method bridge = erasedInvokeSignature(funDescriptor); final Method bridge = erasedInvokeSignature(funDescriptor);
final Method delegate = invokeSignature(funDescriptor); final Method delegate = invokeSignature(funDescriptor);
@@ -207,7 +210,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
} }
} }
private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) { private Method generateConstructor(String funClass, PsiElement fun) {
int argCount = captureThis ? 1 : 0; int argCount = captureThis ? 1 : 0;
argCount += (captureReceiver != null ? 1 : 0); argCount += (captureReceiver != null ? 1 : 0);
@@ -294,7 +297,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
signatureWriter.visitTypeArgument(variance); signatureWriter.visitTypeArgument(variance);
final JetTypeMapper typeMapper = state.getTypeMapper(); final JetTypeMapper typeMapper = state.getTypeMapper();
final Type rawRetType = typeMapper.boxType(typeMapper.mapType(type)); final Type rawRetType = JetTypeMapper.boxType(typeMapper.mapType(type));
signatureWriter.visitClassType(rawRetType.getInternalName()); signatureWriter.visitClassType(rawRetType.getInternalName());
signatureWriter.visitEnd(); signatureWriter.visitEnd();
} }
File diff suppressed because it is too large Load Diff
@@ -1,11 +1,9 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
@@ -101,11 +99,7 @@ public abstract class StackValue {
return new Field(type, owner, name, isStatic); return new Field(type, owner, name, isStatic);
} }
public static StackValue instanceField(Type type, String owner, String name) { public static Property property(String name, String owner, Type type, boolean isStatic, boolean isInterface, boolean isSuper, Method getter, Method setter) {
return new InstanceField(type, owner, name);
}
public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, boolean isSuper, Method getter, Method setter) {
return new Property(name, owner, getter, setter, isStatic, isInterface, isSuper, type); return new Property(name, owner, getter, setter, isStatic, isInterface, isSuper, type);
} }
@@ -264,6 +258,12 @@ public abstract class StackValue {
return new PreIncrement(index, increment); return new PreIncrement(index, increment);
} }
public static StackValue receiver(ResolvedCall<? extends CallableDescriptor> resolvedCall, StackValue receiver, ExpressionCodegen codegen, @Nullable CallableMethod callableMethod) {
if(resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists())
return new CallReceiver(resolvedCall, receiver, codegen, callableMethod);
return receiver;
}
private static class None extends StackValue { private static class None extends StackValue {
public static None INSTANCE = new None(); public static None INSTANCE = new None();
private None() { private None() {
@@ -614,7 +614,7 @@ public abstract class StackValue {
if(resolvedSetCall.getThisObject().exists()) { if(resolvedSetCall.getThisObject().exists()) {
if(resolvedSetCall.getReceiverArgument().exists()) { if(resolvedSetCall.getReceiverArgument().exists()) {
codegen.generateFromResolvedCall(resolvedSetCall.getThisObject()); codegen.generateFromResolvedCall(resolvedSetCall.getThisObject(), JetTypeMapper.TYPE_OBJECT);
} }
v.load(realReceiverIndex - realReceiverType.getSize(), realReceiverType); v.load(realReceiverIndex - realReceiverType.getSize(), realReceiverType);
} }
@@ -730,39 +730,11 @@ public abstract class StackValue {
} }
} }
static class InstanceField extends StackValue { static class Property extends StackValue {
final String owner;
final String name;
public InstanceField(Type type, String owner, String name) {
super(type);
this.owner = owner;
this.name = name;
}
@Override
public void put(Type type, InstructionAdapter v) {
v.load(0, JetTypeMapper.TYPE_OBJECT);
v.getfield(owner, name, this.type.getDescriptor());
coerce(type, v);
}
@Override
public void dupReceiver(InstructionAdapter v) {
}
@Override
public void store(InstructionAdapter v) {
v.load(0, JetTypeMapper.TYPE_OBJECT);
v.putfield(owner, name, this.type.getDescriptor());
}
}
private static class Property extends StackValue {
private final String name; private final String name;
private final Method getter; private final Method getter;
private final Method setter; private final Method setter;
private final String owner; public final String owner;
private final boolean isStatic; private final boolean isStatic;
private final boolean isInterface; private final boolean isInterface;
private boolean isSuper; private boolean isSuper;
@@ -1011,4 +983,94 @@ public abstract class StackValue {
} }
} }
} }
public static class CallReceiver extends StackValue {
private ResolvedCall<? extends CallableDescriptor> resolvedCall;
StackValue receiver;
private ExpressionCodegen codegen;
private CallableMethod callableMethod;
public CallReceiver(ResolvedCall<? extends CallableDescriptor> resolvedCall, StackValue receiver, ExpressionCodegen codegen, CallableMethod callableMethod) {
super(calcType(resolvedCall, codegen, callableMethod));
this.resolvedCall = resolvedCall;
this.receiver = receiver;
this.codegen = codegen;
this.callableMethod = callableMethod;
}
private static Type calcType(ResolvedCall<? extends CallableDescriptor> resolvedCall, ExpressionCodegen codegen, CallableMethod callableMethod) {
ReceiverDescriptor thisObject = resolvedCall.getThisObject();
ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
if (thisObject.exists()) {
if(callableMethod != null) {
if(receiverArgument.exists()) {
return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
}
else {
return codegen.typeMapper.mapType(callableMethod.getThisType());
}
}
else {
if(receiverArgument.exists()) {
return codegen.typeMapper.mapType(descriptor.getReceiverParameter().getType());
}
else {
return codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType());
}
}
}
else {
if (receiverArgument.exists()) {
if(callableMethod != null)
return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
else
return codegen.typeMapper.mapType(descriptor.getReceiverParameter().getType());
}
else {
return Type.VOID_TYPE;
}
}
}
@Override
public void put(Type type, InstructionAdapter v) {
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
ReceiverDescriptor thisObject = resolvedCall.getThisObject();
ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();
if (thisObject.exists()) {
if(receiverArgument.exists()) {
codegen.generateFromResolvedCall(thisObject, codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType()));
genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter());
}
else {
genReceiver(v, thisObject, type, null);
}
}
else {
if (receiverArgument.exists()) {
genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter());
}
}
}
private void genReceiver(InstructionAdapter v, ReceiverDescriptor receiverArgument, Type type, ReceiverDescriptor receiverParameter) {
if(receiver == StackValue.none()) {
if(receiverParameter != null) {
Type receiverType = codegen.typeMapper.mapType(receiverParameter.getType());
codegen.generateFromResolvedCall(receiverArgument, receiverType);
StackValue.onStack(receiverType).put(type, v);
}
else {
codegen.generateFromResolvedCall(receiverArgument, type);
}
}
else {
receiver.put(type, v);
}
}
}
} }
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen.intrinsics; package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.Callable; import org.jetbrains.jet.codegen.Callable;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
@@ -14,5 +15,5 @@ import java.util.List;
* @author yole * @author yole
*/ */
public interface IntrinsicMethod extends Callable { public interface IntrinsicMethod extends Callable {
StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver); StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, @Nullable PsiElement element, @Nullable List<JetExpression> arguments, StackValue receiver);
} }
@@ -113,7 +113,11 @@ public class CompileEnvironment {
} }
if ((rtJar == null || !rtJar.exists()) && failOnError) { if ((rtJar == null || !rtJar.exists()) && failOnError) {
throw new CompileEnvironmentException("No rt.jar found under JAVA_HOME=" + javaHome); rtJar = findActiveRtJar(failOnError);
if ((rtJar == null || !rtJar.exists())) {
throw new CompileEnvironmentException("No rt.jar found under JAVA_HOME=" + javaHome);
}
} }
return rtJar; return rtJar;
} }
@@ -144,7 +148,7 @@ public class CompileEnvironment {
throw new CompileEnvironmentException("Could not find rt.jar in system class loader: " + StringUtil.join(loader.getURLs(), new Function<URL, String>() { throw new CompileEnvironmentException("Could not find rt.jar in system class loader: " + StringUtil.join(loader.getURLs(), new Function<URL, String>() {
@Override @Override
public String fun(URL url) { public String fun(URL url) {
return url.toString(); return url.toString() + "\n";
} }
}, ", ")); }, ", "));
} }
@@ -26,7 +26,7 @@ public class JetPrefixExpression extends JetUnaryExpression {
@Nullable @IfNotParsed @Nullable @IfNotParsed
public JetExpression getBaseExpression() { public JetExpression getBaseExpression() {
PsiElement expression = getOperationSign().getNextSibling(); PsiElement expression = getOperationSign().getNextSibling();
while (expression != null && false == expression instanceof JetExpression) { while (expression != null && !(expression instanceof JetExpression)) {
expression = expression.getNextSibling(); expression = expression.getNextSibling();
} }
return (JetExpression) expression; return (JetExpression) expression;
@@ -21,6 +21,7 @@ public class ExtensionFunctionsTest extends CodegenTestCase {
public void testWhenFail() throws Exception { public void testWhenFail() throws Exception {
loadFile(); loadFile();
// System.out.println(generateToText());
Method foo = generateFunction("foo"); Method foo = generateFunction("foo");
assertThrows(foo, Exception.class, null, new StringBuilder()); assertThrows(foo, Exception.class, null, new StringBuilder());
} }
@@ -7,6 +7,7 @@ package org.jetbrains.jet.codegen;
public class ObjectGenTest extends CodegenTestCase { public class ObjectGenTest extends CodegenTestCase {
public void testSimpleObject() throws Exception { public void testSimpleObject() throws Exception {
blackBoxFile("objects/simpleObject.jet"); blackBoxFile("objects/simpleObject.jet");
// System.out.println(generateToText());
} }
public void testObjectLiteral() throws Exception { public void testObjectLiteral() throws Exception {
@@ -134,6 +134,7 @@ public class PropertyGenTest extends CodegenTestCase {
public void testKt257 () throws Exception { public void testKt257 () throws Exception {
blackBoxFile("regressions/kt257.jet"); blackBoxFile("regressions/kt257.jet");
// System.out.println(generateToText());
} }
public void testKt613 () throws Exception { public void testKt613 () throws Exception {