001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.jet.codegen.binding; 018 019 import com.intellij.openapi.util.Pair; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.annotations.Nullable; 022 import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor; 023 import org.jetbrains.jet.lang.descriptors.*; 024 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 025 import org.jetbrains.jet.lang.types.JetType; 026 import org.jetbrains.org.objectweb.asm.Type; 027 028 import java.util.*; 029 030 import static org.jetbrains.jet.codegen.JvmCodegenUtil.getDirectMember; 031 032 public final class MutableClosure implements CalculatedClosure { 033 private final ResolvedCall<ConstructorDescriptor> superCall; 034 035 private final ClassDescriptor enclosingClass; 036 private final CallableDescriptor enclosingReceiverDescriptor; 037 038 private boolean captureThis; 039 private boolean captureReceiver; 040 041 private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables; 042 private List<Pair<String, Type>> recordedFields; 043 044 MutableClosure( 045 @NotNull ClassDescriptor classDescriptor, 046 @Nullable ResolvedCall<ConstructorDescriptor> superCall, 047 @Nullable ClassDescriptor enclosingClass 048 ) { 049 this.enclosingClass = enclosingClass; 050 this.superCall = superCall; 051 this.enclosingReceiverDescriptor = enclosingExtensionMemberForClass(classDescriptor); 052 } 053 054 @Nullable 055 private static CallableDescriptor enclosingExtensionMemberForClass(@NotNull ClassDescriptor classDescriptor) { 056 DeclarationDescriptor classContainer = classDescriptor.getContainingDeclaration(); 057 if (classContainer instanceof CallableMemberDescriptor) { 058 CallableMemberDescriptor member = getDirectMember((CallableMemberDescriptor) classContainer); 059 if (member.getReceiverParameter() != null) { 060 return member; 061 } 062 } 063 return null; 064 } 065 066 @Nullable 067 public ClassDescriptor getEnclosingClass() { 068 return enclosingClass; 069 } 070 071 @Override 072 public ResolvedCall<ConstructorDescriptor> getSuperCall() { 073 return superCall; 074 } 075 076 @Override 077 public ClassDescriptor getCaptureThis() { 078 return captureThis ? enclosingClass : null; 079 } 080 081 public void setCaptureThis() { 082 this.captureThis = true; 083 } 084 085 @Override 086 public JetType getCaptureReceiverType() { 087 if (captureReceiver) { 088 //noinspection ConstantConditions 089 ReceiverParameterDescriptor parameter = enclosingReceiverDescriptor.getReceiverParameter(); 090 assert parameter != null : "Receiver parameter should exist in " + enclosingReceiverDescriptor; 091 return parameter.getType(); 092 } 093 094 return null; 095 } 096 097 public void setCaptureReceiver() { 098 if (enclosingReceiverDescriptor == null) { 099 throw new IllegalStateException(); 100 } 101 this.captureReceiver = true; 102 } 103 104 @NotNull 105 @Override 106 public Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables() { 107 return captureVariables != null ? captureVariables : Collections.<DeclarationDescriptor, EnclosedValueDescriptor>emptyMap(); 108 } 109 110 @NotNull 111 @Override 112 public List<Pair<String, Type>> getRecordedFields() { 113 return recordedFields != null ? recordedFields : Collections.<Pair<String, Type>>emptyList(); 114 } 115 116 public void recordField(String name, Type type) { 117 if (recordedFields == null) { 118 recordedFields = new LinkedList<Pair<String, Type>>(); 119 } 120 recordedFields.add(new Pair<String, Type>(name, type)); 121 } 122 123 public void captureVariable(EnclosedValueDescriptor value) { 124 if (captureVariables == null) { 125 captureVariables = new HashMap<DeclarationDescriptor, EnclosedValueDescriptor>(); 126 } 127 captureVariables.put(value.getDescriptor(), value); 128 } 129 130 public CallableDescriptor getEnclosingReceiverDescriptor() { 131 return enclosingReceiverDescriptor; 132 } 133 }