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.context;
018
019 import org.jetbrains.asm4.Type;
020 import org.jetbrains.jet.codegen.ExpressionCodegen;
021 import org.jetbrains.jet.codegen.StackValue;
022 import org.jetbrains.jet.codegen.binding.MutableClosure;
023 import org.jetbrains.jet.codegen.state.GenerationState;
024 import org.jetbrains.jet.lang.descriptors.*;
025 import org.jetbrains.jet.lang.types.JetType;
026
027 import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_RECEIVER_FIELD;
028 import static org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
029 import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
030
031 public interface LocalLookup {
032 boolean lookupLocal(DeclarationDescriptor descriptor);
033
034 enum LocalLookupCase {
035 VAR {
036 @Override
037 public boolean isCase(DeclarationDescriptor d, GenerationState state) {
038 return (d instanceof VariableDescriptor) && !(d instanceof PropertyDescriptor);
039 }
040
041 @Override
042 public StackValue innerValue(
043 DeclarationDescriptor d,
044 LocalLookup localLookup,
045 GenerationState state,
046 MutableClosure closure,
047 Type classType
048 ) {
049 VariableDescriptor vd = (VariableDescriptor) d;
050
051 boolean idx = localLookup != null && localLookup.lookupLocal(vd);
052 if (!idx) return null;
053
054 Type sharedVarType = state.getTypeMapper().getSharedVarType(vd);
055 Type localType = state.getTypeMapper().mapType(vd);
056 Type type = sharedVarType != null ? sharedVarType : localType;
057
058 String fieldName = "$" + vd.getName();
059 StackValue innerValue = sharedVarType != null
060 ? StackValue.fieldForSharedVar(localType, classType, fieldName)
061 : StackValue.field(type, classType, fieldName, false);
062
063 closure.recordField(fieldName, type);
064 closure.captureVariable(new EnclosedValueDescriptor(d, innerValue, type));
065
066 return innerValue;
067 }
068 },
069
070 LOCAL_NAMED_FUNCTION {
071 @Override
072 public boolean isCase(DeclarationDescriptor d, GenerationState state) {
073 return isLocalNamedFun(d);
074 }
075
076 @Override
077 public StackValue innerValue(
078 DeclarationDescriptor d,
079 LocalLookup localLookup,
080 GenerationState state,
081 MutableClosure closure,
082 Type classType
083 ) {
084 FunctionDescriptor vd = (FunctionDescriptor) d;
085
086 boolean idx = localLookup != null && localLookup.lookupLocal(vd);
087 if (!idx) return null;
088
089 Type localType = asmTypeForAnonymousClass(state.getBindingContext(), vd);
090
091 String fieldName = "$" + vd.getName();
092 StackValue innerValue = StackValue.field(localType, classType, fieldName, false);
093
094 closure.recordField(fieldName, localType);
095 closure.captureVariable(new EnclosedValueDescriptor(d, innerValue, localType));
096
097 return innerValue;
098 }
099 },
100
101 RECEIVER {
102 @Override
103 public boolean isCase(DeclarationDescriptor d, GenerationState state) {
104 return d instanceof CallableDescriptor;
105 }
106
107 @Override
108 public StackValue innerValue(
109 DeclarationDescriptor d,
110 LocalLookup enclosingLocalLookup,
111 GenerationState state,
112 MutableClosure closure,
113 Type classType
114 ) {
115 if (closure.getEnclosingReceiverDescriptor() != d) return null;
116
117 JetType receiverType = ((CallableDescriptor) d).getReceiverParameter().getType();
118 Type type = state.getTypeMapper().mapType(receiverType);
119 StackValue innerValue = StackValue.field(type, classType, CAPTURED_RECEIVER_FIELD, false);
120 closure.setCaptureReceiver();
121
122 return innerValue;
123 }
124
125 @Override
126 public StackValue outerValue(EnclosedValueDescriptor d, ExpressionCodegen expressionCodegen) {
127 CallableDescriptor descriptor = (CallableDescriptor) d.getDescriptor();
128 return StackValue.local(descriptor.getExpectedThisObject() != null ? 1 : 0, d.getType());
129 }
130 };
131
132 public abstract boolean isCase(DeclarationDescriptor d, GenerationState state);
133
134 public abstract StackValue innerValue(
135 DeclarationDescriptor d,
136 LocalLookup localLookup,
137 GenerationState state,
138 MutableClosure closure,
139 Type classType
140 );
141
142 public StackValue outerValue(EnclosedValueDescriptor d, ExpressionCodegen expressionCodegen) {
143 int idx = expressionCodegen.lookupLocalIndex(d.getDescriptor());
144 assert idx != -1;
145
146 return StackValue.local(idx, d.getType());
147 }
148 }
149 }