提交 cfc41361 编写于 作者: A Alex Tkachman

expressions as functions

上级 30e44b16
......@@ -85,7 +85,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName());
if (enclosingType == null) captureThis = false;
final Method constructor = generateConstructor(funClass, captureThis, fun, funDescriptor.getReturnType());
final Method constructor = generateConstructor(funClass, fun);
if (captureThis) {
cv.newField(fun, 0, "this$0", enclosingType.getDescriptor(), null, null);
......@@ -97,10 +97,12 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
cv.done();
final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis);
final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis, captureReceiver);
for (DeclarationDescriptor descriptor : closure.keySet()) {
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
answer.addArg(valueDescriptor.getOuterValue());
if(descriptor instanceof VariableDescriptor) {
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
answer.addArg(valueDescriptor.getOuterValue());
}
}
return answer;
}
......@@ -144,7 +146,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this);
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
return closureContext.isOuterWasUsed();
return closureContext.outerWasUsed;
}
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) {
......@@ -185,26 +187,36 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
mv.visitEnd();
}
private Method generateConstructor(String funClass, boolean captureThis, JetFunctionLiteralExpression fun, JetType returnType) {
int argCount = closure.size();
private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) {
int argCount = captureThis ? 1 : 0;
if (captureThis) {
argCount++;
for (DeclarationDescriptor descriptor : closure.keySet()) {
if(descriptor instanceof VariableDescriptor) {
argCount++;
}
else if(descriptor instanceof FunctionDescriptor) {
captureReceiver = state.getTypeMapper().mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType());
argCount++;
}
}
Type[] argTypes = new Type[argCount];
int i = 0;
if (captureThis) {
i = 1;
argTypes[0] = Type.getObjectType(context.getThisDescriptor().getName());
argTypes[i++] = Type.getObjectType(context.getThisDescriptor().getName());
}
if (captureReceiver != null) {
argTypes[i++] = captureReceiver;
}
for (DeclarationDescriptor descriptor : closure.keySet()) {
final Type sharedVarType = exprContext.getSharedVarType(descriptor);
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
argTypes[i++] = type;
if(descriptor instanceof VariableDescriptor) {
final Type sharedVarType = exprContext.getSharedVarType(descriptor);
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
argTypes[i++] = type;
}
}
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
......@@ -225,11 +237,15 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final String fieldName;
if (captureThis && i == 1) {
fieldName = "this$0";
captureThis = false;
}
else {
fieldName = "$" + (i);
i++;
if (captureReceiver != null && (captureThis && i == 2 || !captureThis && i == 1)) {
fieldName = "receiver$0";
}
else {
fieldName = "$" + (i);
i++;
}
}
StackValue.field(type, name, fieldName, false).store(iv);
......
......@@ -36,14 +36,9 @@ public abstract class CodegenContext {
HashMap<JetType,Integer> typeInfoConstants;
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
protected DeclarationDescriptor outerDescriptor;
protected DeclarationDescriptor outerReceiverDescriptor;
protected StackValue outerExpression;
protected StackValue outerReceiverExpression;
protected boolean outerWasUsed = false;
protected boolean outerWasUsed ;
public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
this.contextType = contextType;
......@@ -54,7 +49,7 @@ public abstract class CodegenContext {
protected abstract ClassDescriptor getThisDescriptor ();
protected DeclarationDescriptor getReceiverDescriptor() {
protected FunctionDescriptor getReceiverDescriptor() {
return null;
}
......@@ -139,16 +134,18 @@ public abstract class CodegenContext {
}
}
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) {
final ObjectOrClosureCodegen top = closure;
if (top != null) {
final StackValue answer = top.lookupInContext(d);
if (answer != null) return answer;
final StackValue answer = top.lookupInContext(d, result);
if (answer != null)
return result == null ? answer : StackValue.composed(result, answer);
getOuterExpression(null).put(JetTypeMapper.TYPE_OBJECT, v);
StackValue outer = getOuterExpression(null);
result = result == null ? outer : StackValue.composed(result, outer);
}
return parentContext != null ? parentContext.lookupInContext(d, v) : null;
return parentContext != null ? parentContext.lookupInContext(d, v, result) : null;
}
public Type enclosingClassType() {
......@@ -229,32 +226,34 @@ public abstract class CodegenContext {
return accessor;
}
public boolean isOuterWasUsed() {
return outerWasUsed;
}
public StackValue getReceiverExpression() {
public StackValue getReceiverExpression(JetTypeMapper typeMapper) {
assert getReceiverDescriptor() != null;
return getThisDescriptor() != null ? local1 : local0;
}
public StackValue getThisExpression() {
assert getThisDescriptor() != null;
return local0;
Type asmType = typeMapper.mapType(getReceiverDescriptor().getReceiverParameter().getType());
return getThisDescriptor() != null ? StackValue.local(1, asmType) : StackValue.local(0, asmType);
}
public abstract static class FunctionContext extends CodegenContext {
final DeclarationDescriptor receiverDescriptor;
final FunctionDescriptor receiverDescriptor;
public FunctionContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
super(contextType, contextKind, parentContext, closureCodegen);
receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor() : null;
receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType : null;
}
@Override
protected DeclarationDescriptor getReceiverDescriptor() {
protected FunctionDescriptor getReceiverDescriptor() {
return receiverDescriptor;
}
public FunctionContext getOuterFunction() {
CodegenContext c = getParentContext();
while(c != null) {
if(c instanceof FunctionContext)
return (FunctionContext) c;
c = c.getParentContext();
}
return null;
}
}
public static class MethodContext extends FunctionContext {
......@@ -267,8 +266,8 @@ public abstract class CodegenContext {
return getParentContext().getThisDescriptor();
}
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
return getParentContext().lookupInContext(d, v);
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) {
return getParentContext().lookupInContext(d, v, result);
}
public Type enclosingClassType() {
......
package org.jetbrains.jet.codegen;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.calls.ExpressionAsFunctionDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.List;
/**
......@@ -124,4 +126,20 @@ public class CodegenUtil {
}
return jetClass.getName();
}
public static FunctionDescriptor createInvoke(ExpressionAsFunctionDescriptor fd) {
int arity = fd.getValueParameters().size();
FunctionDescriptorImpl invokeDescriptor = new FunctionDescriptorImpl(
fd.getExpectedThisObject().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity),
Collections.<AnnotationDescriptor>emptyList(),
"invoke");
invokeDescriptor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null,
fd.getExpectedThisObject(),
Collections.<TypeParameterDescriptor>emptyList(),
fd.getValueParameters(),
fd.getReturnType(),
Modality.FINAL, Visibility.PUBLIC);
return invokeDescriptor;
}
}
......@@ -15,6 +15,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label;
......@@ -584,6 +585,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.load(0, JetTypeMapper.TYPE_OBJECT);
}
if (closure.isCaptureReceiver() != null) {
v.load(context.getContextDescriptor().getContainingDeclaration() instanceof NamespaceDescriptor ? 0: 1, closure.isCaptureReceiver());
}
for (int i = 0; i < closure.getArgs().size(); i++) {
StackValue arg = closure.getArgs().get(i);
arg.put(cons.getArgumentTypes()[i], v);
......@@ -738,7 +743,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
public StackValue visitSimpleNameExpression(JetSimpleNameExpression expression, StackValue receiver) {
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression);
DeclarationDescriptor descriptor;
if(resolvedCall == null) {
descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
}
else
descriptor = resolvedCall.getResultingDescriptor();
if (descriptor instanceof NamespaceDescriptor) return StackValue.none(); // No code to generate
if (descriptor instanceof VariableAsFunctionDescriptor) {
......@@ -813,7 +826,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null);
if (!isStatic) {
if (receiver == StackValue.none()) {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
if(resolvedCall == null)
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
else {
if(resolvedCall.getThisObject() instanceof ExtensionReceiver)
receiver = generateReceiver((FunctionDescriptor) ((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor());
else
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
}
}
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
receiver.put(receiverType != null && !isSuper? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
......@@ -856,13 +876,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else {
// receiver
StackValue.local(0, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, v);
final StackValue value = context.lookupInContext(descriptor, v);
StackValue value = context.lookupInContext(descriptor, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT));
if (value == null) {
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
}
if(value instanceof StackValue.Composed) {
StackValue.Composed composed = (StackValue.Composed) value;
composed.prefix.put(JetTypeMapper.TYPE_OBJECT, v);
value = composed.suffix;
}
if(value instanceof StackValue.FieldForSharedVar) {
StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
Type sharedType = StackValue.sharedTypeForType(value.type);
......@@ -911,7 +934,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, @Nullable JetSuperExpression superExpression) {
boolean isSuper = superExpression != null;
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration().getOriginal();
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
assert containingDeclaration != null;
containingDeclaration = containingDeclaration.getOriginal();
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
propertyDescriptor = propertyDescriptor.getOriginal();
boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) ||
......@@ -932,7 +958,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if(isSuper) {
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
if(!CodegenUtil.isInterface(propertyDescriptor.getContainingDeclaration())) {
if(!CodegenUtil.isInterface(containingDeclaration)) {
if(enclosed != null && enclosed != context.getThisDescriptor()) {
CodegenContext c = context;
while(c.getContextDescriptor() != enclosed) {
......@@ -1055,6 +1081,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
assert !superCall;
callableMethod = asCallableMethod((FunctionDescriptor) fd);
}
else if (fd instanceof ExpressionAsFunctionDescriptor) {
FunctionDescriptor invoke = CodegenUtil.createInvoke((ExpressionAsFunctionDescriptor) fd);
callableMethod = asCallableMethod(invoke);
}
else if (fd instanceof FunctionDescriptor) {
callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, superCall, OwnerKind.IMPLEMENTATION);
}
......@@ -1066,14 +1096,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private DeclarationDescriptor resolveCalleeDescriptor(JetCallExpression call) {
JetExpression callee = call.getCalleeExpression();
if (!(callee instanceof JetReferenceExpression)) {
throw new UnsupportedOperationException("Don't know how to generate a call to " + callee);
}
DeclarationDescriptor funDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) callee);
if (funDescriptor == null) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee);
if(resolvedCall == null) {
assert callee != null;
throw new CompilationException("Cannot resolve: " + callee.getText());
}
return funDescriptor;
return resolvedCall.getResultingDescriptor();
}
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) {
......@@ -1102,7 +1131,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.load(0, JetTypeMapper.TYPE_OBJECT);
}
else
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
receiver.put(callableMethod.getSignature().getArgumentTypes()[0], v);
}
}
......@@ -1147,11 +1176,33 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
private StackValue generateReceiver(FunctionDescriptor descriptor) {
assert context instanceof CodegenContext.FunctionContext;
CodegenContext.FunctionContext cur = (CodegenContext.FunctionContext) context;
if (cur.getReceiverDescriptor() == descriptor) {
return cur.getReceiverExpression(typeMapper);
}
return context.lookupInContext(descriptor, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT));
// assert context instanceof CodegenContext.FunctionContext;
// CodegenContext.FunctionContext cur = (CodegenContext.FunctionContext) context;
//
// StackValue result = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
// while (cur != null) {
//
// if (cur.getReceiverDescriptor() == descriptor) {
// return cur.getReceiverExpression(typeMapper);
// }
//
// result = cur.getOuterExpression(result);
// cur = cur.getOuterFunction();
// }
//
// throw new UnsupportedOperationException("Don't know how to generate receiver for " + descriptor);
}
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
CodegenContext cur = context;
if(cur.getReceiverDescriptor() == calleeContainingClass) {
return cur.getReceiverExpression();
}
StackValue result = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
while (cur != null) {
......@@ -2071,9 +2122,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else {
if(descriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
Type type = typeMapper.mapType(functionDescriptor.getReceiverParameter().getType());
return StackValue.local(descriptor.getContainingDeclaration() instanceof NamespaceDescriptor ? 0 : 1, type);
return generateReceiver((FunctionDescriptor) descriptor);
}
throw new UnsupportedOperationException();
}
......@@ -2362,8 +2411,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return;
}
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
if (context.getThisDescriptor() instanceof ClassDescriptor) {
ClassDescriptor descriptor = (ClassDescriptor) context.getThisDescriptor();
if (context.getThisDescriptor() != null) {
ClassDescriptor descriptor = context.getThisDescriptor();
assert containingDeclaration != null;
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
Type ownerType = typeMapper.mapType(defaultType);
......
......@@ -3,6 +3,7 @@
*/
package org.jetbrains.jet.codegen;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.util.ArrayList;
......@@ -12,12 +13,14 @@ public class GeneratedAnonymousClassDescriptor {
private final String classname;
private Method constructor;
private final boolean captureThis;
private final Type captureReceiver;
private List<StackValue> args = new ArrayList<StackValue>();
public GeneratedAnonymousClassDescriptor(String classname, Method constructor, boolean captureThis) {
public GeneratedAnonymousClassDescriptor(String classname, Method constructor, boolean captureThis, Type captureReceiver) {
this.classname = classname;
this.constructor = constructor;
this.captureThis = captureThis;
this.captureReceiver = captureReceiver;
}
public String getClassname() {
......@@ -39,4 +42,8 @@ public class GeneratedAnonymousClassDescriptor {
public boolean isCaptureThis() {
return captureThis;
}
public Type isCaptureReceiver() {
return captureReceiver;
}
}
......@@ -126,7 +126,7 @@ public class GenerationState {
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature(), false);
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature(), objectContext.outerWasUsed, null);
}
public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) {
......
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.ClassDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
......@@ -16,6 +14,7 @@ import java.util.Map;
*/
public class ObjectOrClosureCodegen {
protected boolean captureThis;
protected Type captureReceiver;
public final GenerationState state;
protected final ExpressionCodegen exprContext;
......@@ -30,13 +29,16 @@ public class ObjectOrClosureCodegen {
this.state = state;
}
public StackValue lookupInContext(DeclarationDescriptor d) {
public StackValue lookupInContext(DeclarationDescriptor d, StackValue result) {
EnclosedValueDescriptor answer = closure.get(d);
if (answer != null) {
StackValue innerValue = answer.getInnerValue();
return result != null ? innerValue : StackValue.composed(result, innerValue);
}
if (d instanceof VariableDescriptor) {
VariableDescriptor vd = (VariableDescriptor) d;
EnclosedValueDescriptor answer = closure.get(vd);
if (answer != null) return answer.getInnerValue();
final int idx = exprContext.lookupLocal(vd);
if (idx < 0) return null;
......@@ -56,14 +58,36 @@ public class ObjectOrClosureCodegen {
return innerValue;
}
return null;
}
if(d instanceof FunctionDescriptor) {
// we are looking for receiver
FunctionDescriptor fd = (FunctionDescriptor) d;
// we generate method
assert context instanceof CodegenContext.FunctionContext;
CodegenContext.FunctionContext fcontext = (CodegenContext.FunctionContext) context;
if(fcontext.getReceiverDescriptor() != fd)
return null;
Type type = state.getTypeMapper().mapType(fcontext.getReceiverDescriptor().getReceiverParameter().getType());
boolean isStatic = fcontext.getContextDescriptor().getContainingDeclaration() instanceof NamespaceDescriptor;
StackValue outerValue = StackValue.local(isStatic ? 0 : 1, type);
final String fieldName = "receiver$0";
StackValue innerValue = StackValue.field(type, name, fieldName, false);
public boolean isCaptureThis() {
return captureThis;
cv.newField(null, Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer);
return innerValue;
}
return null;
}
public boolean isConst () {
return !captureThis && closure.isEmpty();
return !captureThis && captureReceiver != null && closure.isEmpty();
}
}
......@@ -795,9 +795,9 @@ public abstract class StackValue {
}
}
private static class Composed extends StackValue {
private StackValue prefix;
private StackValue suffix;
public static class Composed extends StackValue {
public final StackValue prefix;
public final StackValue suffix;
public Composed(StackValue prefix, StackValue suffix) {
super(suffix.type);
......@@ -810,5 +810,11 @@ public abstract class StackValue {
prefix.put(prefix.type, v);
suffix.put(type, v);
}
@Override
public void store(InstructionAdapter v) {
prefix.put(JetTypeMapper.TYPE_OBJECT, v);
suffix.store(v);
}
}
}
......@@ -187,7 +187,7 @@ public class CallResolver {
return null;
}
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType);
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
resolvedCall.setReceiverArgument(call.getExplicitReceiver());
......
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.List;
/**
* @author alex.tkachman
*/
public class ExpressionAsFunctionDescriptor extends FunctionDescriptorImpl {
public ExpressionAsFunctionDescriptor(DeclarationDescriptor containingDeclaration, String name) {
super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), name);
}
}
fun Any.foo1() : fun(): String {
return { "239" + this }
}
fun Int.foo2() : fun(i : Int) : Int {
return { x => x + this }
}
fun fooT1<T>(t : T) = { t.toString() }
fun fooT2<T>(t: T) = { (x:T) => t.toString() + x.toString() }
fun box() : String {
if( (10.foo1())() != "23910") return "foo1 fail"
if( (10.foo2())(1) != 11 ) return "foo2 fail"
if(1.{Int.() => this + 1}() != 2) return "test 3 failed";
if( {1}() != 1) return "test 4 failed";
if( {(x : Int) => x}(1) != 1) return "test 5 failed";
if( 1.{Int.(x : Int) => x + this}(1) != 2) return "test 6 failed";
if( 1.({Int.() => this})() != 1) return "test 7 failed";
if( (fooT1<String>("mama"))() != "mama") return "test 8 failed";
if( (fooT2<String>("mama"))("papa") != "mamapapa") return "test 9 failed";
return "OK"
}
class X<T> () {
fun getTypeChecker() = { (a : Any) => a is T }
}
fun box() : String {
val c = X<String>().getTypeChecker()
if(c(10)) return "fail"
if(!c("lala")) return "fail"
return "OK"
}
......@@ -80,55 +80,8 @@ public class FunctionGenTest extends CodegenTestCase {
public void testKt395 () {
blackBoxFile("regressions/kt395.jet");
}
/*
public void testFunction () throws InvocationTargetException, IllegalAccessException {
loadText("fun Any.foo() : fun(): String {\n" +
" return { \"239\" + this }\n" +
"}\n" +
"fun box() : String {\n" +
" return if((10.foo())() == \"23910\") \"OK\" else \"fail\"" +
"}" +
"");
System.out.println(generateToText());
Method foo = generateFunction();
assertTrue((Boolean) foo.invoke(null, "lala"));
assertFalse((Boolean) foo.invoke(null, "mama"));
blackBoxFile("functions/functionExpression.jet");
}
fun Any.foo() : fun() : Unit {
return {}
}
fun Any.foo1() : fun(i : Int) : Unit {
return {}
}
fun foo2() : fun(i : fun()) : Unit {
return {}
}
fun fooT1<T>(t : T) : fun() : T {
return {t}
}
fun fooT2<T>() : fun(t : T) : T {
return {it}
}
fun main(args : Array<String>) {
args.foo()()
args.foo1()(1)
foo2()({})
(foo2()){}
val a = fooT1(1)()
a : Int
val b = fooT2<Int>()(1)
b : Int
fooT2()(1) // : Any?
}
*/
}
......@@ -13,7 +13,7 @@ public class DefaultJetObject implements JetObject {
}
@Override
public TypeInfo<?> getTypeInfo() {
public final TypeInfo<?> getTypeInfo() {
return typeInfo;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册