NamespaceCodegen.java 5.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * 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.
 */

M
Maxim Shafirov 已提交
17 18
package org.jetbrains.jet.codegen;

19
import com.intellij.psi.PsiFile;
S
Stepan Koltsov 已提交
20
import org.jetbrains.annotations.NotNull;
A
Alex Tkachman 已提交
21
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
A
Andrey Breslav 已提交
22
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
23
import org.jetbrains.jet.lang.psi.*;
24
import org.jetbrains.jet.lang.resolve.BindingContext;
25
import org.jetbrains.jet.lang.resolve.name.FqName;
S
Stepan Koltsov 已提交
26
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
27
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
28 29
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
30
import org.objectweb.asm.commons.InstructionAdapter;
M
Maxim Shafirov 已提交
31

A
Alex Tkachman 已提交
32
import static org.objectweb.asm.Opcodes.*;
A
Alex Tkachman 已提交
33

M
Maxim Shafirov 已提交
34 35 36 37
/**
 * @author max
 */
public class NamespaceCodegen {
38
    private final ClassBuilder v;
39
    private final GenerationState state;
M
Maxim Shafirov 已提交
40

S
Stepan Koltsov 已提交
41
    public NamespaceCodegen(ClassBuilder v, @NotNull FqName fqName, GenerationState state, PsiFile sourceFile) {
42
        this.v = v;
43
        this.state = state;
44

45
        v.defineClass(sourceFile, V1_6,
A
Alex Tkachman 已提交
46
                      ACC_PUBLIC/*|ACC_SUPER*/,
47
                      getJVMClassNameForKotlinNs(fqName).getInternalName(),
48 49 50 51
                      null,
                      //"jet/lang/Namespace",
                      "java/lang/Object",
                      new String[0]
52
        );
53
        // TODO figure something out for a namespace that spans multiple files
54
        v.visitSource(sourceFile.getName(), null);
55 56
    }

A
Andrey Breslav 已提交
57
    public void generate(JetFile file) {
58
        NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
59
        final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor);
M
Maxim Shafirov 已提交
60

A
Andrey Breslav 已提交
61
        for (JetDeclaration declaration : file.getDeclarations()) {
S
Stepan Koltsov 已提交
62 63 64
            if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
                state.getInjector().getMemberCodegen().generateFunctionOrProperty(
                        (JetTypeParameterListOwner) declaration, context, v);
M
Maxim Shafirov 已提交
65
            }
66
            else if (declaration instanceof JetClassOrObject) {
67
                state.getInjector().getClassCodegen().generate(context, (JetClassOrObject) declaration);
68
            }
S
Stepan Koltsov 已提交
69 70 71
            else if (declaration instanceof JetScript) {
                state.getInjector().getScriptCodegen().generate(context, (JetScript) declaration);
            }
A
Andrey Breslav 已提交
72 73 74 75
//            else if (declaration instanceof JetFile) {
//                JetFile childNamespace = (JetFile) declaration;
//                state.forNamespace(childNamespace).generate(childNamespace);
//            }
M
Maxim Shafirov 已提交
76
        }
A
Alex Tkachman 已提交
77

A
Andrey Breslav 已提交
78 79
        if (hasNonConstantPropertyInitializers(file)) {
            generateStaticInitializers(file);
A
Alex Tkachman 已提交
80
        }
81
    }
M
Maxim Shafirov 已提交
82

A
Andrey Breslav 已提交
83
    private void generateStaticInitializers(JetFile namespace) {
A
Alex Tkachman 已提交
84
        MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
85
        if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
86 87 88
            mv.visitCode();

            FrameMap frameMap = new FrameMap();
89
            ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContexts.STATIC, state);
90 91 92 93 94 95

            for (JetDeclaration declaration : namespace.getDeclarations()) {
                if (declaration instanceof JetProperty) {
                    final JetExpression initializer = ((JetProperty) declaration).getInitializer();
                    if (initializer != null && !(initializer instanceof JetConstantExpression)) {
                        final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
96 97 98 99
                        assert descriptor != null;
                        if(descriptor.getReceiverParameter().exists()) {
                            continue;
                        }
100 101 102
                        codegen.genToJVMStack(initializer);
                        codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
                    }
103 104
                }
            }
A
Alex Tkachman 已提交
105

106
            mv.visitInsn(RETURN);
A
Alex Tkachman 已提交
107
            FunctionCodegen.endVisit(mv, "static initializer for namespace", namespace);
108 109
            mv.visitEnd();
        }
110 111
    }

A
Andrey Breslav 已提交
112
    private static boolean hasNonConstantPropertyInitializers(JetFile namespace) {
113 114 115 116 117 118 119 120 121 122 123 124
        for (JetDeclaration declaration : namespace.getDeclarations()) {
            if (declaration instanceof JetProperty) {
                final JetExpression initializer = ((JetProperty) declaration).getInitializer();
                if (initializer != null && !(initializer instanceof JetConstantExpression)) {
                    return true;
                }

            }
        }
        return false;
    }

125
    public void done() {
126
        v.done();
M
Maxim Shafirov 已提交
127
    }
D
Dmitry Jemerov 已提交
128

129 130
    @NotNull
    public static JvmClassName getJVMClassNameForKotlinNs(@NotNull FqName fqName) {
S
Stepan Koltsov 已提交
131
        if (fqName.isRoot()) {
132
            return JvmClassName.byInternalName(JvmAbi.PACKAGE_CLASS);
133
        }
A
Alex Tkachman 已提交
134

S
Stepan Koltsov 已提交
135
        return JvmClassName.byInternalName(fqName.getFqName().replace('.', '/') + "/" + JvmAbi.PACKAGE_CLASS);
136
    }
M
Maxim Shafirov 已提交
137
}