NamespaceCodegen.java 6.2 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;
S
Stepan Koltsov 已提交
25
import org.jetbrains.jet.lang.resolve.FqName;
26
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
S
Stepan Koltsov 已提交
27
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
28
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
29 30
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
31
import org.objectweb.asm.commons.InstructionAdapter;
M
Maxim Shafirov 已提交
32

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

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

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

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

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

        final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
        final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
M
Maxim Shafirov 已提交
64

A
Andrey Breslav 已提交
65
        for (JetDeclaration declaration : file.getDeclarations()) {
M
Maxim Shafirov 已提交
66
            if (declaration instanceof JetProperty) {
M
Maxim Shafirov 已提交
67
                propertyCodegen.gen((JetProperty) declaration);
M
Maxim Shafirov 已提交
68
            }
69
            else if (declaration instanceof JetNamedFunction) {
D
Dmitry Jemerov 已提交
70
                try {
M
Maxim Shafirov 已提交
71
                    functionCodegen.gen((JetNamedFunction) declaration);
A
Andrey Breslav 已提交
72 73
                }
                catch (CompilationException e) {
A
Alex Tkachman 已提交
74 75 76 77
                    throw e;
                }
                catch (Exception e) {
                    throw new CompilationException("Failed to generate function " + declaration.getName(), e, declaration);
D
Dmitry Jemerov 已提交
78
                }
M
Maxim Shafirov 已提交
79
            }
80
            else if (declaration instanceof JetClassOrObject) {
81
                state.getInjector().getClassCodegen().generate(context, (JetClassOrObject) declaration);
82
            }
A
Andrey Breslav 已提交
83 84 85 86
//            else if (declaration instanceof JetFile) {
//                JetFile childNamespace = (JetFile) declaration;
//                state.forNamespace(childNamespace).generate(childNamespace);
//            }
M
Maxim Shafirov 已提交
87
        }
A
Alex Tkachman 已提交
88

A
Andrey Breslav 已提交
89 90
        if (hasNonConstantPropertyInitializers(file)) {
            generateStaticInitializers(file);
A
Alex Tkachman 已提交
91
        }
92
    }
M
Maxim Shafirov 已提交
93

A
Andrey Breslav 已提交
94
    private void generateStaticInitializers(JetFile namespace) {
A
Alex Tkachman 已提交
95
        MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
96
        if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
97 98 99 100 101 102 103 104 105 106
            mv.visitCode();

            FrameMap frameMap = new FrameMap();
            ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);

            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);
107 108 109 110
                        assert descriptor != null;
                        if(descriptor.getReceiverParameter().exists()) {
                            continue;
                        }
111 112 113
                        codegen.genToJVMStack(initializer);
                        codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
                    }
114 115
                }
            }
A
Alex Tkachman 已提交
116

117
            mv.visitInsn(RETURN);
A
Alex Tkachman 已提交
118
            FunctionCodegen.endVisit(mv, "static initializer for namespace", namespace);
119 120
            mv.visitEnd();
        }
121 122
    }

A
Andrey Breslav 已提交
123
    private static boolean hasNonConstantPropertyInitializers(JetFile namespace) {
124 125 126 127 128 129 130 131 132 133 134 135
        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;
    }

136
    public void done() {
137
        v.done();
M
Maxim Shafirov 已提交
138
    }
D
Dmitry Jemerov 已提交
139

140 141
    @NotNull
    public static JvmClassName getJVMClassNameForKotlinNs(@NotNull FqName fqName) {
S
Stepan Koltsov 已提交
142
        if (fqName.isRoot()) {
143
            return JvmClassName.byInternalName(JvmAbi.PACKAGE_CLASS);
144
        }
A
Alex Tkachman 已提交
145

S
Stepan Koltsov 已提交
146
        String name = fqName.getFqName().replace('.', '/');
147 148
        if (name.startsWith(JavaDescriptorResolver.JAVA_ROOT)) {
            name = name.substring(JavaDescriptorResolver.JAVA_ROOT.length() + 1, name.length());
149
        }
150
        name += "/" + JvmAbi.PACKAGE_CLASS;
151
        return JvmClassName.byInternalName(name);
152
    }
M
Maxim Shafirov 已提交
153
}