common superclass introduced for (Namespace/ClassBody/Script)Codegen

This commit is contained in:
Alex Tkachman
2012-09-21 16:41:50 +03:00
parent 726e6be076
commit 95489c4444
6 changed files with 163 additions and 123 deletions
@@ -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);
}
}
@@ -118,11 +118,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> 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;
}
@@ -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<DeclarationDescriptor, DeclarationDescriptor> 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();
}
}
@@ -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());
}
}
}
@@ -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);
}
}
@@ -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<DeclarationDescriptor, DeclarationDescriptor> getAccessors() {
return accessors == null ? Collections.<DeclarationDescriptor, DeclarationDescriptor>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<DeclarationDescriptor, DeclarationDescriptor> 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();
}
}