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; 018 019 import org.jetbrains.annotations.NotNull; 020 import org.jetbrains.asm4.MethodVisitor; 021 import org.jetbrains.asm4.Type; 022 import org.jetbrains.jet.codegen.context.MethodContext; 023 import org.jetbrains.jet.codegen.signature.JvmMethodSignature; 024 import org.jetbrains.jet.codegen.state.GenerationState; 025 import org.jetbrains.jet.codegen.state.JetTypeMapper; 026 import org.jetbrains.jet.lang.descriptors.CallableDescriptor; 027 import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; 028 029 import java.util.ArrayList; 030 import java.util.Collection; 031 032 public abstract class FunctionGenerationStrategy { 033 034 private final Collection<String> localVariableNames = new ArrayList<String>(); 035 036 private FrameMap frameMap; 037 038 public abstract void generateBody( 039 @NotNull MethodVisitor mv, 040 @NotNull JvmMethodSignature signature, 041 @NotNull MethodContext context 042 ); 043 044 protected void addLocalVariableName(@NotNull String name) { 045 localVariableNames.add(name); 046 } 047 048 @NotNull 049 public Collection<String> getLocalVariableNames() { 050 return localVariableNames; 051 } 052 053 @NotNull 054 protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) { 055 return context.prepareFrame(typeMapper); 056 } 057 058 @NotNull 059 public FrameMap getFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) { 060 if (frameMap == null) { 061 frameMap = createFrameMap(typeMapper, context); 062 } 063 return frameMap; 064 } 065 066 public static class FunctionDefault extends CodegenBased<CallableDescriptor> { 067 068 private final JetDeclarationWithBody declaration; 069 070 public FunctionDefault( 071 @NotNull GenerationState state, 072 @NotNull CallableDescriptor descriptor, 073 @NotNull JetDeclarationWithBody declaration 074 ) { 075 super(state, descriptor); 076 this.declaration = declaration; 077 } 078 079 @Override 080 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 081 codegen.returnExpression(declaration.getBodyExpression()); 082 } 083 } 084 085 public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy { 086 087 protected final GenerationState state; 088 089 protected final T callableDescriptor; 090 091 public CodegenBased(@NotNull GenerationState state, T callableDescriptor) { 092 this.state = state; 093 this.callableDescriptor = callableDescriptor; 094 } 095 096 @Override 097 public void generateBody( 098 @NotNull MethodVisitor mv, 099 @NotNull JvmMethodSignature signature, 100 @NotNull MethodContext context 101 ) { 102 ExpressionCodegen codegen = initializeExpressionCodegen(signature, context, mv, signature.getAsmMethod().getReturnType()); 103 doGenerateBody(codegen, signature); 104 generateLocalVarNames(codegen); 105 } 106 107 abstract public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature); 108 109 @NotNull 110 public ExpressionCodegen initializeExpressionCodegen( 111 JvmMethodSignature signature, 112 MethodContext context, 113 MethodVisitor mv, 114 Type returnType 115 ) { 116 return new ExpressionCodegen(mv, getFrameMap(state.getTypeMapper(), context), returnType, context, state); 117 } 118 119 public void generateLocalVarNames(@NotNull ExpressionCodegen codegen) { 120 for (String name : codegen.getLocalVariableNamesForExpression()) { 121 addLocalVariableName(name); 122 } 123 } 124 } 125 }