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 017package org.jetbrains.jet.codegen.binding; 018 019import com.intellij.openapi.util.Pair; 020import org.jetbrains.annotations.NotNull; 021import org.jetbrains.annotations.Nullable; 022import org.jetbrains.asm4.Type; 023import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor; 024import org.jetbrains.jet.lang.descriptors.CallableDescriptor; 025import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 026import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; 027import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; 028import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; 029 030import java.util.*; 031 032public final class MutableClosure implements CalculatedClosure { 033 private final JetDelegatorToSuperCall 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 JetDelegatorToSuperCall superCall, 046 ClassDescriptor enclosingClass, 047 CallableDescriptor enclosingReceiverDescriptor 048 ) { 049 this.superCall = superCall; 050 this.enclosingClass = enclosingClass; 051 this.enclosingReceiverDescriptor = enclosingReceiverDescriptor; 052 } 053 054 @Nullable 055 @Override 056 public ClassDescriptor getEnclosingClass() { 057 return enclosingClass; 058 } 059 060 @Override 061 public JetDelegatorToSuperCall getSuperCall() { 062 return superCall; 063 } 064 065 @Override 066 public ClassDescriptor getCaptureThis() { 067 return captureThis ? enclosingClass : null; 068 } 069 070 public void setCaptureThis() { 071 this.captureThis = true; 072 } 073 074 @Override 075 public ClassifierDescriptor getCaptureReceiver() { 076 return captureReceiver 077 ? enclosingReceiverDescriptor.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor() 078 : null; 079 } 080 081 public void setCaptureReceiver() { 082 if (enclosingReceiverDescriptor == null) { 083 throw new IllegalStateException(); 084 } 085 this.captureReceiver = true; 086 } 087 088 @NotNull 089 @Override 090 public Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables() { 091 return captureVariables != null ? captureVariables : Collections.<DeclarationDescriptor, EnclosedValueDescriptor>emptyMap(); 092 } 093 094 @NotNull 095 @Override 096 public List<Pair<String, Type>> getRecordedFields() { 097 return recordedFields != null ? recordedFields : Collections.<Pair<String, Type>>emptyList(); 098 } 099 100 public void recordField(String name, Type type) { 101 if (recordedFields == null) { 102 recordedFields = new LinkedList<Pair<String, Type>>(); 103 } 104 recordedFields.add(new Pair<String, Type>(name, type)); 105 } 106 107 public void captureVariable(EnclosedValueDescriptor value) { 108 if (captureVariables == null) { 109 captureVariables = new HashMap<DeclarationDescriptor, EnclosedValueDescriptor>(); 110 } 111 captureVariables.put(value.getDescriptor(), value); 112 } 113 114 public CallableDescriptor getEnclosingReceiverDescriptor() { 115 return enclosingReceiverDescriptor; 116 } 117}