expressions as functions
This commit is contained in:
@@ -85,7 +85,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName());
|
final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName());
|
||||||
if (enclosingType == null) captureThis = false;
|
if (enclosingType == null) captureThis = false;
|
||||||
|
|
||||||
final Method constructor = generateConstructor(funClass, captureThis, fun, funDescriptor.getReturnType());
|
final Method constructor = generateConstructor(funClass, fun);
|
||||||
|
|
||||||
if (captureThis) {
|
if (captureThis) {
|
||||||
cv.newField(fun, 0, "this$0", enclosingType.getDescriptor(), null, null);
|
cv.newField(fun, 0, "this$0", enclosingType.getDescriptor(), null, null);
|
||||||
@@ -97,10 +97,12 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
|
|
||||||
cv.done();
|
cv.done();
|
||||||
|
|
||||||
final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis);
|
final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis, captureReceiver);
|
||||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
||||||
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
|
if(descriptor instanceof VariableDescriptor) {
|
||||||
answer.addArg(valueDescriptor.getOuterValue());
|
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
|
||||||
|
answer.addArg(valueDescriptor.getOuterValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
@@ -144,7 +146,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this);
|
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this);
|
||||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||||
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
||||||
return closureContext.isOuterWasUsed();
|
return closureContext.outerWasUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) {
|
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) {
|
||||||
@@ -185,26 +187,36 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Method generateConstructor(String funClass, boolean captureThis, JetFunctionLiteralExpression fun, JetType returnType) {
|
private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) {
|
||||||
int argCount = closure.size();
|
int argCount = captureThis ? 1 : 0;
|
||||||
|
|
||||||
if (captureThis) {
|
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
||||||
argCount++;
|
if(descriptor instanceof VariableDescriptor) {
|
||||||
|
argCount++;
|
||||||
|
}
|
||||||
|
else if(descriptor instanceof FunctionDescriptor) {
|
||||||
|
captureReceiver = state.getTypeMapper().mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType());
|
||||||
|
argCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type[] argTypes = new Type[argCount];
|
Type[] argTypes = new Type[argCount];
|
||||||
|
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (captureThis) {
|
if (captureThis) {
|
||||||
i = 1;
|
argTypes[i++] = Type.getObjectType(context.getThisDescriptor().getName());
|
||||||
argTypes[0] = Type.getObjectType(context.getThisDescriptor().getName());
|
}
|
||||||
|
|
||||||
|
if (captureReceiver != null) {
|
||||||
|
argTypes[i++] = captureReceiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
||||||
final Type sharedVarType = exprContext.getSharedVarType(descriptor);
|
if(descriptor instanceof VariableDescriptor) {
|
||||||
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
|
final Type sharedVarType = exprContext.getSharedVarType(descriptor);
|
||||||
argTypes[i++] = type;
|
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);
|
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
|
||||||
@@ -225,11 +237,15 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
final String fieldName;
|
final String fieldName;
|
||||||
if (captureThis && i == 1) {
|
if (captureThis && i == 1) {
|
||||||
fieldName = "this$0";
|
fieldName = "this$0";
|
||||||
captureThis = false;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fieldName = "$" + (i);
|
if (captureReceiver != null && (captureThis && i == 2 || !captureThis && i == 1)) {
|
||||||
i++;
|
fieldName = "receiver$0";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fieldName = "$" + (i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StackValue.field(type, name, fieldName, false).store(iv);
|
StackValue.field(type, name, fieldName, false).store(iv);
|
||||||
|
|||||||
@@ -36,14 +36,9 @@ public abstract class CodegenContext {
|
|||||||
HashMap<JetType,Integer> typeInfoConstants;
|
HashMap<JetType,Integer> typeInfoConstants;
|
||||||
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
||||||
|
|
||||||
protected DeclarationDescriptor outerDescriptor;
|
|
||||||
protected DeclarationDescriptor outerReceiverDescriptor;
|
|
||||||
|
|
||||||
protected StackValue outerExpression;
|
protected StackValue outerExpression;
|
||||||
|
|
||||||
protected StackValue outerReceiverExpression;
|
protected boolean outerWasUsed ;
|
||||||
|
|
||||||
protected boolean outerWasUsed = false;
|
|
||||||
|
|
||||||
public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
||||||
this.contextType = contextType;
|
this.contextType = contextType;
|
||||||
@@ -54,7 +49,7 @@ public abstract class CodegenContext {
|
|||||||
|
|
||||||
protected abstract ClassDescriptor getThisDescriptor ();
|
protected abstract ClassDescriptor getThisDescriptor ();
|
||||||
|
|
||||||
protected DeclarationDescriptor getReceiverDescriptor() {
|
protected FunctionDescriptor getReceiverDescriptor() {
|
||||||
return null;
|
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;
|
final ObjectOrClosureCodegen top = closure;
|
||||||
if (top != null) {
|
if (top != null) {
|
||||||
final StackValue answer = top.lookupInContext(d);
|
final StackValue answer = top.lookupInContext(d, result);
|
||||||
if (answer != null) return answer;
|
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() {
|
public Type enclosingClassType() {
|
||||||
@@ -229,32 +226,34 @@ public abstract class CodegenContext {
|
|||||||
return accessor;
|
return accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOuterWasUsed() {
|
public StackValue getReceiverExpression(JetTypeMapper typeMapper) {
|
||||||
return outerWasUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StackValue getReceiverExpression() {
|
|
||||||
assert getReceiverDescriptor() != null;
|
assert getReceiverDescriptor() != null;
|
||||||
return getThisDescriptor() != null ? local1 : local0;
|
Type asmType = typeMapper.mapType(getReceiverDescriptor().getReceiverParameter().getType());
|
||||||
}
|
return getThisDescriptor() != null ? StackValue.local(1, asmType) : StackValue.local(0, asmType);
|
||||||
|
|
||||||
public StackValue getThisExpression() {
|
|
||||||
assert getThisDescriptor() != null;
|
|
||||||
return local0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract static class FunctionContext extends CodegenContext {
|
public abstract static class FunctionContext extends CodegenContext {
|
||||||
final DeclarationDescriptor receiverDescriptor;
|
final FunctionDescriptor receiverDescriptor;
|
||||||
|
|
||||||
public FunctionContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
public FunctionContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
||||||
super(contextType, contextKind, parentContext, closureCodegen);
|
super(contextType, contextKind, parentContext, closureCodegen);
|
||||||
receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor() : null;
|
receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DeclarationDescriptor getReceiverDescriptor() {
|
protected FunctionDescriptor getReceiverDescriptor() {
|
||||||
return receiverDescriptor;
|
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 {
|
public static class MethodContext extends FunctionContext {
|
||||||
@@ -267,8 +266,8 @@ public abstract class CodegenContext {
|
|||||||
return getParentContext().getThisDescriptor();
|
return getParentContext().getThisDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
|
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) {
|
||||||
return getParentContext().lookupInContext(d, v);
|
return getParentContext().lookupInContext(d, v, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type enclosingClassType() {
|
public Type enclosingClassType() {
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetClass;
|
import org.jetbrains.jet.lang.psi.JetClass;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
|
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
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 org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,4 +126,20 @@ public class CodegenUtil {
|
|||||||
}
|
}
|
||||||
return jetClass.getName();
|
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.calls.*;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
|
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.lang.types.*;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
@@ -584,6 +585,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
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++) {
|
for (int i = 0; i < closure.getArgs().size(); i++) {
|
||||||
StackValue arg = closure.getArgs().get(i);
|
StackValue arg = closure.getArgs().get(i);
|
||||||
arg.put(cons.getArgumentTypes()[i], v);
|
arg.put(cons.getArgumentTypes()[i], v);
|
||||||
@@ -738,7 +743,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitSimpleNameExpression(JetSimpleNameExpression expression, StackValue receiver) {
|
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 NamespaceDescriptor) return StackValue.none(); // No code to generate
|
||||||
|
|
||||||
if (descriptor instanceof VariableAsFunctionDescriptor) {
|
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);
|
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null);
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
if (receiver == StackValue.none()) {
|
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);
|
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
|
||||||
receiver.put(receiverType != null && !isSuper? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
|
receiver.put(receiverType != null && !isSuper? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
|
||||||
@@ -856,13 +876,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// receiver
|
// receiver
|
||||||
StackValue.local(0, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, v);
|
StackValue value = context.lookupInContext(descriptor, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT));
|
||||||
|
|
||||||
final StackValue value = context.lookupInContext(descriptor, v);
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
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) {
|
if(value instanceof StackValue.FieldForSharedVar) {
|
||||||
StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
|
StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
|
||||||
Type sharedType = StackValue.sharedTypeForType(value.type);
|
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) {
|
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, @Nullable JetSuperExpression superExpression) {
|
||||||
boolean isSuper = superExpression != null;
|
boolean isSuper = superExpression != null;
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration().getOriginal();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
|
assert containingDeclaration != null;
|
||||||
|
containingDeclaration = containingDeclaration.getOriginal();
|
||||||
|
|
||||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
||||||
propertyDescriptor = propertyDescriptor.getOriginal();
|
propertyDescriptor = propertyDescriptor.getOriginal();
|
||||||
boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) ||
|
boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) ||
|
||||||
@@ -932,7 +958,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if(isSuper) {
|
if(isSuper) {
|
||||||
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||||
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
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()) {
|
if(enclosed != null && enclosed != context.getThisDescriptor()) {
|
||||||
CodegenContext c = context;
|
CodegenContext c = context;
|
||||||
while(c.getContextDescriptor() != enclosed) {
|
while(c.getContextDescriptor() != enclosed) {
|
||||||
@@ -1055,6 +1081,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
assert !superCall;
|
assert !superCall;
|
||||||
callableMethod = asCallableMethod((FunctionDescriptor) fd);
|
callableMethod = asCallableMethod((FunctionDescriptor) fd);
|
||||||
}
|
}
|
||||||
|
else if (fd instanceof ExpressionAsFunctionDescriptor) {
|
||||||
|
FunctionDescriptor invoke = CodegenUtil.createInvoke((ExpressionAsFunctionDescriptor) fd);
|
||||||
|
callableMethod = asCallableMethod(invoke);
|
||||||
|
}
|
||||||
else if (fd instanceof FunctionDescriptor) {
|
else if (fd instanceof FunctionDescriptor) {
|
||||||
callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, superCall, OwnerKind.IMPLEMENTATION);
|
callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, superCall, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
@@ -1066,14 +1096,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private DeclarationDescriptor resolveCalleeDescriptor(JetCallExpression call) {
|
private DeclarationDescriptor resolveCalleeDescriptor(JetCallExpression call) {
|
||||||
JetExpression callee = call.getCalleeExpression();
|
JetExpression callee = call.getCalleeExpression();
|
||||||
if (!(callee instanceof JetReferenceExpression)) {
|
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee);
|
||||||
throw new UnsupportedOperationException("Don't know how to generate a call to " + callee);
|
if(resolvedCall == null) {
|
||||||
}
|
assert callee != null;
|
||||||
DeclarationDescriptor funDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) callee);
|
|
||||||
if (funDescriptor == null) {
|
|
||||||
throw new CompilationException("Cannot resolve: " + callee.getText());
|
throw new CompilationException("Cannot resolve: " + callee.getText());
|
||||||
}
|
}
|
||||||
return funDescriptor;
|
|
||||||
|
return resolvedCall.getResultingDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) {
|
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);
|
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
else
|
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) {
|
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
|
||||||
CodegenContext cur = context;
|
CodegenContext cur = context;
|
||||||
if(cur.getReceiverDescriptor() == calleeContainingClass) {
|
|
||||||
return cur.getReceiverExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
StackValue result = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
StackValue result = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
while (cur != null) {
|
while (cur != null) {
|
||||||
@@ -2071,9 +2122,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(descriptor instanceof FunctionDescriptor) {
|
if(descriptor instanceof FunctionDescriptor) {
|
||||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
return generateReceiver((FunctionDescriptor) descriptor);
|
||||||
Type type = typeMapper.mapType(functionDescriptor.getReceiverParameter().getType());
|
|
||||||
return StackValue.local(descriptor.getContainingDeclaration() instanceof NamespaceDescriptor ? 0 : 1, type);
|
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
@@ -2362,8 +2411,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
||||||
if (context.getThisDescriptor() instanceof ClassDescriptor) {
|
if (context.getThisDescriptor() != null) {
|
||||||
ClassDescriptor descriptor = (ClassDescriptor) context.getThisDescriptor();
|
ClassDescriptor descriptor = context.getThisDescriptor();
|
||||||
assert containingDeclaration != null;
|
assert containingDeclaration != null;
|
||||||
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
|
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
|
||||||
Type ownerType = typeMapper.mapType(defaultType);
|
Type ownerType = typeMapper.mapType(defaultType);
|
||||||
|
|||||||
+8
-1
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -12,12 +13,14 @@ public class GeneratedAnonymousClassDescriptor {
|
|||||||
private final String classname;
|
private final String classname;
|
||||||
private Method constructor;
|
private Method constructor;
|
||||||
private final boolean captureThis;
|
private final boolean captureThis;
|
||||||
|
private final Type captureReceiver;
|
||||||
private List<StackValue> args = new ArrayList<StackValue>();
|
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.classname = classname;
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
this.captureThis = captureThis;
|
this.captureThis = captureThis;
|
||||||
|
this.captureReceiver = captureReceiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClassname() {
|
public String getClassname() {
|
||||||
@@ -39,4 +42,8 @@ public class GeneratedAnonymousClassDescriptor {
|
|||||||
public boolean isCaptureThis() {
|
public boolean isCaptureThis() {
|
||||||
return captureThis;
|
return captureThis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type isCaptureReceiver() {
|
||||||
|
return captureReceiver;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public class GenerationState {
|
|||||||
|
|
||||||
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
||||||
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
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) {
|
public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) {
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptorImpl;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
@@ -16,6 +14,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class ObjectOrClosureCodegen {
|
public class ObjectOrClosureCodegen {
|
||||||
protected boolean captureThis;
|
protected boolean captureThis;
|
||||||
|
protected Type captureReceiver;
|
||||||
|
|
||||||
public final GenerationState state;
|
public final GenerationState state;
|
||||||
protected final ExpressionCodegen exprContext;
|
protected final ExpressionCodegen exprContext;
|
||||||
@@ -30,13 +29,16 @@ public class ObjectOrClosureCodegen {
|
|||||||
this.state = state;
|
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) {
|
if (d instanceof VariableDescriptor) {
|
||||||
VariableDescriptor vd = (VariableDescriptor) d;
|
VariableDescriptor vd = (VariableDescriptor) d;
|
||||||
|
|
||||||
EnclosedValueDescriptor answer = closure.get(vd);
|
|
||||||
if (answer != null) return answer.getInnerValue();
|
|
||||||
|
|
||||||
final int idx = exprContext.lookupLocal(vd);
|
final int idx = exprContext.lookupLocal(vd);
|
||||||
if (idx < 0) return null;
|
if (idx < 0) return null;
|
||||||
|
|
||||||
@@ -56,14 +58,36 @@ public class ObjectOrClosureCodegen {
|
|||||||
return innerValue;
|
return innerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCaptureThis() {
|
|
||||||
return captureThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConst () {
|
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 {
|
public static class Composed extends StackValue {
|
||||||
private StackValue prefix;
|
public final StackValue prefix;
|
||||||
private StackValue suffix;
|
public final StackValue suffix;
|
||||||
|
|
||||||
public Composed(StackValue prefix, StackValue suffix) {
|
public Composed(StackValue prefix, StackValue suffix) {
|
||||||
super(suffix.type);
|
super(suffix.type);
|
||||||
@@ -810,5 +810,11 @@ public abstract class StackValue {
|
|||||||
prefix.put(prefix.type, v);
|
prefix.put(prefix.type, v);
|
||||||
suffix.put(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;
|
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);
|
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType);
|
||||||
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
|
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
|
||||||
resolvedCall.setReceiverArgument(call.getExplicitReceiver());
|
resolvedCall.setReceiverArgument(call.getExplicitReceiver());
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
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"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
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 () {
|
public void testKt395 () {
|
||||||
blackBoxFile("regressions/kt395.jet");
|
blackBoxFile("regressions/kt395.jet");
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
public void testFunction () throws InvocationTargetException, IllegalAccessException {
|
public void testFunction () throws InvocationTargetException, IllegalAccessException {
|
||||||
loadText("fun Any.foo() : fun(): String {\n" +
|
blackBoxFile("functions/functionExpression.jet");
|
||||||
" 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"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
@Override
|
||||||
public TypeInfo<?> getTypeInfo() {
|
public final TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user