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 public final class MutableClosure implements CalculatedClosure { 031 private final ResolvedCall<ConstructorDescriptor> superCall; 032 033 private final ClassDescriptor enclosingClass; 034 private final CallableDescriptor enclosingReceiverDescriptor; 035 036 private boolean captureThis; 037 private boolean captureReceiver; 038 039 private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables; 040 private List<Pair<String, Type>> recordedFields; 041 042 MutableClosure( 043 @Nullable ResolvedCall<ConstructorDescriptor> superCall, 044 @Nullable ClassDescriptor enclosingClass, 045 @Nullable CallableDescriptor enclosingReceiverDescriptor 046 ) { 047 this.superCall = superCall; 048 this.enclosingClass = enclosingClass; 049 this.enclosingReceiverDescriptor = enclosingReceiverDescriptor; 050 } 051 052 @Nullable 053 public ClassDescriptor getEnclosingClass() { 054 return enclosingClass; 055 } 056 057 @Override 058 public ResolvedCall<ConstructorDescriptor> getSuperCall() { 059 return superCall; 060 } 061 062 @Override 063 public ClassDescriptor getCaptureThis() { 064 return captureThis ? enclosingClass : null; 065 } 066 067 public void setCaptureThis() { 068 this.captureThis = true; 069 } 070 071 @Override 072 public JetType getCaptureReceiverType() { 073 if (captureReceiver) { 074 //noinspection ConstantConditions 075 ReceiverParameterDescriptor parameter = enclosingReceiverDescriptor.getReceiverParameter(); 076 assert parameter != null : "Receiver parameter should exist in " + enclosingReceiverDescriptor; 077 return parameter.getType(); 078 } 079 080 return null; 081 } 082 083 public void setCaptureReceiver() { 084 if (enclosingReceiverDescriptor == null) { 085 throw new IllegalStateException(); 086 } 087 this.captureReceiver = true; 088 } 089 090 @NotNull 091 @Override 092 public Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables() { 093 return captureVariables != null ? captureVariables : Collections.<DeclarationDescriptor, EnclosedValueDescriptor>emptyMap(); 094 } 095 096 @NotNull 097 @Override 098 public List<Pair<String, Type>> getRecordedFields() { 099 return recordedFields != null ? recordedFields : Collections.<Pair<String, Type>>emptyList(); 100 } 101 102 public void recordField(String name, Type type) { 103 if (recordedFields == null) { 104 recordedFields = new LinkedList<Pair<String, Type>>(); 105 } 106 recordedFields.add(new Pair<String, Type>(name, type)); 107 } 108 109 public void captureVariable(EnclosedValueDescriptor value) { 110 if (captureVariables == null) { 111 captureVariables = new HashMap<DeclarationDescriptor, EnclosedValueDescriptor>(); 112 } 113 captureVariables.put(value.getDescriptor(), value); 114 } 115 116 public CallableDescriptor getEnclosingReceiverDescriptor() { 117 return enclosingReceiverDescriptor; 118 } 119 }