ClassBodyCodegen.java 4.6 KB
Newer Older
1 2 3 4 5
package org.jetbrains.jet.codegen;

import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
6
import org.jetbrains.jet.lang.resolve.BindingContext;
7
import org.objectweb.asm.ClassVisitor;
8
import org.objectweb.asm.MethodVisitor;
9
import org.objectweb.asm.Opcodes;
10
import org.objectweb.asm.commons.InstructionAdapter;
11

12
import java.util.ArrayList;
13 14 15
import java.util.Collections;
import java.util.List;

16 17 18 19 20
/**
 * @author max
 * @author yole
 */
public abstract class ClassBodyCodegen {
21 22
    protected final GenerationState state;

23
    protected final JetClassOrObject myClass;
24 25 26
    protected final OwnerKind kind;
    protected final ClassDescriptor descriptor;
    protected final ClassVisitor v;
M
Maxim Shafirov 已提交
27
    protected final ClassContext context;
28

29 30
    protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();

M
Maxim Shafirov 已提交
31
    public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
32
        this.state = state;
33
        descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
34
        myClass = aClass;
M
Maxim Shafirov 已提交
35 36
        this.context = context;
        this.kind = context.getContextKind();
37 38 39 40 41 42 43 44 45 46
        this.v = v;
    }

    public void generate() {
        generateDeclaration();

        generateSyntheticParts();

        generateClassBody();

47 48
        generateStaticInitializer();

49 50 51 52 53 54 55 56 57
        v.visitEnd();
    }

    protected abstract void generateDeclaration();

    protected void generateSyntheticParts() {
    }

    private void generateClassBody() {
M
Maxim Shafirov 已提交
58 59
        final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
        final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
60 61

        for (JetDeclaration declaration : myClass.getDeclarations()) {
62
            generateDeclaration(propertyCodegen, declaration, functionCodegen);
63 64
        }

65 66 67
        generatePrimaryConstructorProperties(propertyCodegen);
    }

68 69
    protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
        if (declaration instanceof JetProperty) {
M
Maxim Shafirov 已提交
70
            propertyCodegen.gen((JetProperty) declaration);
71
        }
72
        else if (declaration instanceof JetNamedFunction) {
73
            try {
M
Maxim Shafirov 已提交
74
                functionCodegen.gen((JetNamedFunction) declaration);
75
            } catch (RuntimeException e) {
M
Maxim Shafirov 已提交
76
                throw new RuntimeException("Error generating method " + myClass.getName() + "." + declaration.getName() + " in " + context, e);
77 78 79 80
            }
        }
    }

81
    private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
M
Maxim Shafirov 已提交
82
        OwnerKind kind = context.getContextKind();
83
        for (JetParameter p : getPrimaryConstructorParameters()) {
84
            if (p.getValOrVarNode() != null) {
85
                PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
86
                if (propertyDescriptor != null) {
M
Maxim Shafirov 已提交
87
                    propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
88
                    if (propertyDescriptor.isVar()) {
M
Maxim Shafirov 已提交
89
                        propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
90 91
                    }

92
                    //noinspection ConstantConditions
93
                    if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
94
                        v.visitField(Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
95 96 97 98 99 100
                    }
                }
            }
        }
    }

101 102 103 104 105 106
    protected List<JetParameter> getPrimaryConstructorParameters() {
        if (myClass instanceof JetClass) {
            return ((JetClass) myClass).getPrimaryConstructorParameters();
        }
        return Collections.emptyList();
    }
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

    private void generateStaticInitializer() {
        if (staticInitializerChunks.size() > 0) {
            final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
                    "<clinit>", "()V", null, null);
            mv.visitCode();

            InstructionAdapter v = new InstructionAdapter(mv);

            for (CodeChunk chunk : staticInitializerChunks) {
                chunk.generate(v);
            }

            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(0, 0);

            mv.visitEnd();
        }
    }
126
}