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.jet.codegen.context.MethodContext;
021 import org.jetbrains.jet.codegen.state.GenerationState;
022 import org.jetbrains.jet.codegen.state.JetTypeMapper;
023 import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
024 import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
025 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
026 import org.jetbrains.org.objectweb.asm.MethodVisitor;
027
028 public abstract class FunctionGenerationStrategy {
029
030 private FrameMap frameMap;
031
032 public abstract void generateBody(
033 @NotNull MethodVisitor mv,
034 @NotNull JvmMethodSignature signature,
035 @NotNull MethodContext context,
036 @NotNull MemberCodegen<?> parentCodegen
037 );
038
039 @NotNull
040 protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) {
041 return context.prepareFrame(typeMapper);
042 }
043
044 @NotNull
045 public FrameMap getFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) {
046 if (frameMap == null) {
047 frameMap = createFrameMap(typeMapper, context);
048 }
049 return frameMap;
050 }
051
052 public static class FunctionDefault extends CodegenBased<CallableDescriptor> {
053 private final JetDeclarationWithBody declaration;
054
055 public FunctionDefault(
056 @NotNull GenerationState state,
057 @NotNull CallableDescriptor descriptor,
058 @NotNull JetDeclarationWithBody declaration
059 ) {
060 super(state, descriptor);
061 this.declaration = declaration;
062 }
063
064 @Override
065 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
066 codegen.returnExpression(declaration.getBodyExpression());
067 }
068 }
069
070 public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy {
071 protected final GenerationState state;
072 protected final T callableDescriptor;
073
074 public CodegenBased(@NotNull GenerationState state, @NotNull T callableDescriptor) {
075 this.state = state;
076 this.callableDescriptor = callableDescriptor;
077 }
078
079 @Override
080 public final void generateBody(
081 @NotNull MethodVisitor mv,
082 @NotNull JvmMethodSignature signature,
083 @NotNull MethodContext context,
084 @NotNull MemberCodegen<?> parentCodegen
085 ) {
086 ExpressionCodegen codegen = new ExpressionCodegen(mv, getFrameMap(state.getTypeMapper(), context),
087 signature.getReturnType(), context, state, parentCodegen);
088 doGenerateBody(codegen, signature);
089 }
090
091 public abstract void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature);
092 }
093 }