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.resolve.java.JvmClassName; 026 import org.jetbrains.jet.lang.types.JetType; 027 028 import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_RECEIVER_FIELD; 029 import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass; 030 import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun; 031 032 public interface LocalLookup { 033 boolean lookupLocal(DeclarationDescriptor descriptor); 034 035 enum LocalLookupCase { 036 VAR { 037 @Override 038 public boolean isCase(DeclarationDescriptor d, GenerationState state) { 039 return (d instanceof VariableDescriptor) && !(d instanceof PropertyDescriptor); 040 } 041 042 @Override 043 public StackValue innerValue( 044 DeclarationDescriptor d, 045 LocalLookup localLookup, 046 GenerationState state, 047 MutableClosure closure, JvmClassName className 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, className, fieldName) 061 : StackValue.field(type, className, 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 JvmClassName className 083 ) { 084 FunctionDescriptor vd = (FunctionDescriptor) d; 085 086 boolean idx = localLookup != null && localLookup.lookupLocal(vd); 087 if (!idx) return null; 088 089 Type localType = classNameForAnonymousClass(state.getBindingContext(), vd).getAsmType(); 090 091 String fieldName = "$" + vd.getName(); 092 StackValue innerValue = StackValue.field(localType, className, 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, JvmClassName className 113 ) { 114 if (closure.getEnclosingReceiverDescriptor() != d) return null; 115 116 JetType receiverType = ((CallableDescriptor) d).getReceiverParameter().getType(); 117 Type type = state.getTypeMapper().mapType(receiverType); 118 StackValue innerValue = StackValue.field(type, className, CAPTURED_RECEIVER_FIELD, false); 119 closure.setCaptureReceiver(); 120 121 return innerValue; 122 } 123 124 @Override 125 public StackValue outerValue(EnclosedValueDescriptor d, ExpressionCodegen expressionCodegen) { 126 CallableDescriptor descriptor = (CallableDescriptor) d.getDescriptor(); 127 return StackValue.local(descriptor.getExpectedThisObject() != null ? 1 : 0, d.getType()); 128 } 129 }; 130 131 public abstract boolean isCase(DeclarationDescriptor d, GenerationState state); 132 133 public abstract StackValue innerValue( 134 DeclarationDescriptor d, 135 LocalLookup localLookup, 136 GenerationState state, 137 MutableClosure closure, 138 JvmClassName className 139 ); 140 141 public StackValue outerValue(EnclosedValueDescriptor d, ExpressionCodegen expressionCodegen) { 142 int idx = expressionCodegen.lookupLocalIndex(d.getDescriptor()); 143 assert idx != -1; 144 145 return StackValue.local(idx, d.getType()); 146 } 147 } 148 }