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 }