From 95489c444434d4b9fdcdbbecd212b242fc5f5011 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Fri, 21 Sep 2012 16:41:50 +0300 Subject: [PATCH] common superclass introduced for (Namespace/ClassBody/Script)Codegen --- .../jet/codegen/ClassBodyCodegen.java | 5 +- .../jet/codegen/ExpressionCodegen.java | 8 +- .../jetbrains/jet/codegen/MemberCodegen.java | 145 ++++++++++++++++++ .../jet/codegen/NamespaceCodegen.java | 13 +- .../jetbrains/jet/codegen/ScriptCodegen.java | 5 +- .../jet/codegen/context/CodegenContext.java | 110 +------------ 6 files changed, 163 insertions(+), 123 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 5a7d4effef0..218c74a4a44 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -22,7 +22,6 @@ import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.state.GenerationState; -import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; @@ -41,7 +40,7 @@ import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag; * @author max * @author yole */ -public abstract class ClassBodyCodegen extends GenerationStateAware { +public abstract class ClassBodyCodegen extends MemberCodegen { protected final JetClassOrObject myClass; protected final OwnerKind kind; protected final ClassDescriptor descriptor; @@ -89,7 +88,7 @@ public abstract class ClassBodyCodegen extends GenerationStateAware { protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) { if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) { - context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, v); + genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 6d4c30a6522..287eabd251d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -118,11 +118,15 @@ public class ExpressionCodegen extends JetVisitor implem final CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); final CodegenContext contextForInners = context.intoClass(classDescriptor, OwnerKind.IMPLEMENTATION, state); - contextForInners.genInners(state, objectDeclaration); final CodegenContext objectContext = context.intoAnonymousClass(classDescriptor, this); + final ImplementationBodyCodegen implementationBodyCodegen = new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state); + + implementationBodyCodegen.genInners(contextForInners, state, objectDeclaration); + objectContext.copyAccessors(contextForInners.getAccessors()); - new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state).generate(); + + implementationBodyCodegen.generate(); return closure; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java new file mode 100644 index 00000000000..dd642a4ba1f --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java @@ -0,0 +1,145 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.codegen; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.context.CodegenContext; +import org.jetbrains.jet.codegen.state.GenerationState; +import org.jetbrains.jet.codegen.state.GenerationStateAware; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.ErrorUtils; + +import java.util.Map; + +import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass; + +/** + * @author alex.tkachman + */ +public class MemberCodegen extends GenerationStateAware { + public MemberCodegen(@NotNull GenerationState state) { + super(state); + } + + public void genFunctionOrProperty( + CodegenContext context, + @NotNull JetTypeParameterListOwner functionOrProperty, + @NotNull ClassBuilder classBuilder + ) { + FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state); + if (functionOrProperty instanceof JetNamedFunction) { + try { + functionCodegen.gen((JetNamedFunction) functionOrProperty); + } + catch (CompilationException e) { + throw e; + } + catch (Exception e) { + throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty); + } + } + else if (functionOrProperty instanceof JetProperty) { + try { + new PropertyCodegen(context, classBuilder, functionCodegen).gen((JetProperty) functionOrProperty); + } + catch (CompilationException e) { + throw e; + } + catch (Exception e) { + throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty); + } + } + else { + throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty); + } + } + + public static void genImplementation( + CodegenContext context, + GenerationState state, + JetClassOrObject aClass, + OwnerKind kind, + Map accessors, + ClassBuilder classBuilder + ) { + ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); + CodegenContext classContext = context.intoClass(descriptor, kind, state); + classContext.copyAccessors(accessors); + + new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate(); + + if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) { + ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state); + new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state) + .generate(); + traitBuilder.done(); + } + } + + public void genInners(CodegenContext context, GenerationState state, JetClassOrObject aClass) { + for (JetDeclaration declaration : aClass.getDeclarations()) { + if (declaration instanceof JetClass) { + if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass( + state.getBindingContext(), (JetEnumEntry) declaration)) { + continue; + } + + genClassOrObject(context, (JetClass) declaration); + } + else if (declaration instanceof JetClassObject) { + genClassOrObject(context, ((JetClassObject) declaration).getObjectDeclaration()); + } + else if (declaration instanceof JetObjectDeclaration) { + genClassOrObject(context, (JetObjectDeclaration) declaration); + } + } + } + + public void genClassOrObject(CodegenContext context, JetClassOrObject aClass) { + ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); + + if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(JetPsiUtil.NO_NAME_PROVIDED)) { + if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) { + throw new IllegalStateException( + "Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor); + } + return; + } + + ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor); + + final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state); + + if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) { + // Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate + // The same code is present below for the case when we genClassOrObject real bytecode. This is because the order should be + // different for the case when we compute closures + genImplementation(context, state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder); + } + + genInners(contextForInners, state, aClass); + + if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) { + genImplementation(context, state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder); + } + + classBuilder.done(); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index d5ecb65cb2c..018e4ca7281 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -28,7 +28,6 @@ import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.state.GenerationState; -import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; @@ -48,7 +47,7 @@ import static org.jetbrains.asm4.Opcodes.*; /** * @author max */ -public class NamespaceCodegen extends GenerationStateAware { +public class NamespaceCodegen extends MemberCodegen { @NotNull private final ClassBuilderOnDemand v; @NotNull private final FqName name; @@ -128,17 +127,17 @@ public class NamespaceCodegen extends GenerationStateAware { for (JetDeclaration declaration : file.getDeclarations()) { if (declaration instanceof JetProperty) { final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); - context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, v.getClassBuilder()); + genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder()); } else if (declaration instanceof JetNamedFunction) { if (!multiFile) { final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); - context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, v.getClassBuilder()); + genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder()); } } else if (declaration instanceof JetClassOrObject) { final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); - context.genClassOrObject(state, (JetClassOrObject) declaration); + genClassOrObject(context, (JetClassOrObject) declaration); } else if (declaration instanceof JetScript) { state.getScriptCodegen().generate((JetScript) declaration); @@ -174,12 +173,12 @@ public class NamespaceCodegen extends GenerationStateAware { { final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); - context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, builder); + genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, builder); } { final CodegenContext context = CodegenContext.STATIC.intoNamespacePart(className, descriptor); - context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, v.getClassBuilder()); + genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder()); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java index 6ba72c11122..11155696bbd 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java @@ -27,7 +27,6 @@ import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.ScriptContext; import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.codegen.state.GenerationState; -import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.codegen.state.GenerationStrategy; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; @@ -48,7 +47,7 @@ import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; /** * @author Stepan Koltsov */ -public class ScriptCodegen extends GenerationStateAware { +public class ScriptCodegen extends MemberCodegen { @NotNull private ClassFileFactory classFileFactory; @@ -202,7 +201,7 @@ public class ScriptCodegen extends GenerationStateAware { private void genMembers(@NotNull JetScript scriptDeclaration, @NotNull CodegenContext context, @NotNull ClassBuilder classBuilder) { for (JetDeclaration decl : scriptDeclaration.getDeclarations()) { - context.genFunctionOrProperty(state, (JetTypeParameterListOwner) decl, classBuilder); + genFunctionOrProperty(context, (JetTypeParameterListOwner) decl, classBuilder); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java index 4fec60bf7f0..472474965fc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java @@ -26,16 +26,14 @@ import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.types.ErrorUtils; import java.util.Collections; import java.util.HashMap; import java.util.Map; import static org.jetbrains.jet.codegen.AsmUtil.THIS$0; -import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; +import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLASS_FOR_FUNCTION; +import static org.jetbrains.jet.codegen.binding.CodegenBinding.FQN; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; /* @@ -301,108 +299,4 @@ public abstract class CodegenContext { public Map getAccessors() { return accessors == null ? Collections.emptyMap() : accessors; } - - public void genFunctionOrProperty( - GenerationState state, - @NotNull JetTypeParameterListOwner functionOrProperty, - @NotNull ClassBuilder classBuilder - ) { - FunctionCodegen functionCodegen = new FunctionCodegen(this, classBuilder, state); - if (functionOrProperty instanceof JetNamedFunction) { - try { - functionCodegen.gen((JetNamedFunction) functionOrProperty); - } - catch (CompilationException e) { - throw e; - } - catch (Exception e) { - throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty); - } - } - else if (functionOrProperty instanceof JetProperty) { - try { - new PropertyCodegen(this, classBuilder, functionCodegen).gen((JetProperty) functionOrProperty); - } - catch (CompilationException e) { - throw e; - } - catch (Exception e) { - throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty); - } - } - else { - throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty); - } - } - - public void genImplementation( - GenerationState state, - JetClassOrObject aClass, - OwnerKind kind, - Map accessors, - ClassBuilder classBuilder - ) { - ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); - CodegenContext classContext = intoClass(descriptor, kind, state); - classContext.copyAccessors(accessors); - - new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate(); - - if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) { - ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state); - new TraitImplBodyCodegen(aClass, intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state) - .generate(); - traitBuilder.done(); - } - } - - public void genInners(GenerationState state, JetClassOrObject aClass) { - for (JetDeclaration declaration : aClass.getDeclarations()) { - if (declaration instanceof JetClass) { - if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass( - state.getBindingContext(), (JetEnumEntry) declaration)) { - continue; - } - - genClassOrObject(state, (JetClass) declaration); - } - else if (declaration instanceof JetClassObject) { - genClassOrObject(state, ((JetClassObject) declaration).getObjectDeclaration()); - } - else if (declaration instanceof JetObjectDeclaration) { - genClassOrObject(state, (JetObjectDeclaration) declaration); - } - } - } - - public void genClassOrObject(GenerationState state, JetClassOrObject aClass) { - ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); - - if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(JetPsiUtil.NO_NAME_PROVIDED)) { - if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) { - throw new IllegalStateException( - "Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor); - } - return; - } - - ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor); - - final CodegenContext contextForInners = intoClass(descriptor, OwnerKind.IMPLEMENTATION, state); - - if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) { - // Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate - // The same code is present below for the case when we genClassOrObject real bytecode. This is because the order should be - // different for the case when we compute closures - genImplementation(state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder); - } - - contextForInners.genInners(state, aClass); - - if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) { - genImplementation(state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder); - } - - classBuilder.done(); - } }