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 com.intellij.openapi.progress.ProcessCanceledException; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.annotations.Nullable; 022 import org.jetbrains.jet.codegen.inline.InlineCodegenUtil; 023 import org.jetbrains.jet.codegen.inline.NameGenerator; 024 import org.jetbrains.jet.codegen.context.ClassContext; 025 import org.jetbrains.jet.codegen.context.CodegenContext; 026 import org.jetbrains.jet.codegen.context.FieldOwnerContext; 027 import org.jetbrains.jet.codegen.state.GenerationState; 028 import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 029 import org.jetbrains.jet.lang.psi.*; 030 import org.jetbrains.jet.lang.resolve.BindingContext; 031 import org.jetbrains.jet.lang.resolve.name.SpecialNames; 032 import org.jetbrains.jet.lang.types.ErrorUtils; 033 034 035 public class MemberCodegen extends ParentCodegenAwareImpl { 036 037 protected final FieldOwnerContext context; 038 039 private final ClassBuilder builder; 040 041 private NameGenerator inlineNameGenerator; 042 043 public MemberCodegen( 044 @NotNull GenerationState state, 045 @Nullable MemberCodegen parentCodegen, 046 @NotNull FieldOwnerContext context, 047 @Nullable ClassBuilder builder 048 ) { 049 super(state, parentCodegen); 050 this.context = context; 051 this.builder = builder; 052 } 053 054 public void genFunctionOrProperty( 055 @NotNull FieldOwnerContext context, 056 @NotNull JetTypeParameterListOwner functionOrProperty, 057 @NotNull ClassBuilder classBuilder 058 ) { 059 FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state, this); 060 if (functionOrProperty instanceof JetNamedFunction) { 061 try { 062 functionCodegen.gen((JetNamedFunction) functionOrProperty); 063 } 064 catch (ProcessCanceledException e) { 065 throw e; 066 } 067 catch (CompilationException e) { 068 throw e; 069 } 070 catch (Exception e) { 071 throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty); 072 } 073 } 074 else if (functionOrProperty instanceof JetProperty) { 075 try { 076 new PropertyCodegen(context, classBuilder, functionCodegen, this).gen((JetProperty) functionOrProperty); 077 } 078 catch (ProcessCanceledException e) { 079 throw e; 080 } 081 catch (CompilationException e) { 082 throw e; 083 } 084 catch (Exception e) { 085 throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty); 086 } 087 } 088 else { 089 throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty); 090 } 091 } 092 093 public static void genClassOrObject( 094 @NotNull CodegenContext parentContext, 095 @NotNull JetClassOrObject aClass, 096 @NotNull GenerationState state, 097 @Nullable MemberCodegen parentCodegen 098 ) { 099 ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); 100 101 if (descriptor == null || ErrorUtils.isError(descriptor)) { 102 badDescriptor(descriptor, state.getClassBuilderMode()); 103 return; 104 } 105 106 if (descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) { 107 badDescriptor(descriptor, state.getClassBuilderMode()); 108 } 109 110 ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor, aClass.getContainingFile()); 111 ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state); 112 new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen).generate(); 113 classBuilder.done(); 114 115 if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) { 116 ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state, aClass.getContainingFile()); 117 new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state, parentCodegen) 118 .generate(); 119 traitBuilder.done(); 120 } 121 } 122 123 private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) { 124 if (mode != ClassBuilderMode.LIGHT_CLASSES) { 125 throw new IllegalStateException( 126 "Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor); 127 } 128 } 129 130 public void genClassOrObject(CodegenContext parentContext, JetClassOrObject aClass) { 131 genClassOrObject(parentContext, aClass, state, this); 132 } 133 134 @NotNull 135 public ClassBuilder getBuilder() { 136 return builder; 137 } 138 139 public NameGenerator getInlineNameGenerator() { 140 if (inlineNameGenerator == null) { 141 String prefix = InlineCodegenUtil.getInlineName(context, typeMapper); 142 143 inlineNameGenerator = new NameGenerator(prefix); 144 } 145 return inlineNameGenerator; 146 } 147 }