NamespaceCodegen.java 6.1 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 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
                      getJVMClassName(fqName, true),
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);
A
Alex Tkachman 已提交
59
        final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
M
Maxim Shafirov 已提交
60 61 62

        final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
        final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
63
        final ClassCodegen classCodegen = state.forClass();
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
Alex Tkachman 已提交
72 73 74 75 76
                } catch (CompilationException e) {
                    throw e;
                }
                catch (Exception e) {
                    throw new CompilationException("Failed to generate function " + declaration.getName(), e, declaration);
D
Dmitry Jemerov 已提交
77
                }
M
Maxim Shafirov 已提交
78
            }
79
            else if (declaration instanceof JetClassOrObject) {
M
Maxim Shafirov 已提交
80
                classCodegen.generate(context, (JetClassOrObject) declaration);
81
            }
A
Andrey Breslav 已提交
82 83 84 85
//            else if (declaration instanceof JetFile) {
//                JetFile childNamespace = (JetFile) declaration;
//                state.forNamespace(childNamespace).generate(childNamespace);
//            }
M
Maxim Shafirov 已提交
86
        }
A
Alex Tkachman 已提交
87

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

A
Andrey Breslav 已提交
93
    private void generateStaticInitializers(JetFile namespace) {
A
Alex Tkachman 已提交
94
        MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
S
Stepan Koltsov 已提交
95
        if (v.generateCode() == ClassBuilder.Mode.FULL) {
96 97 98 99 100 101 102 103 104 105
            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);
106 107 108 109
                        assert descriptor != null;
                        if(descriptor.getReceiverParameter().exists()) {
                            continue;
                        }
110 111 112
                        codegen.genToJVMStack(initializer);
                        codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
                    }
113 114
                }
            }
A
Alex Tkachman 已提交
115

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

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

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

139 140 141
    /**
     * @param namespace true for "namespace" suffix 
     */
S
Stepan Koltsov 已提交
142 143
    public static String getJVMClassName(@NotNull FqName fqName, boolean namespace) {
        if (fqName.isRoot()) {
S
Stepan Koltsov 已提交
144
            return JvmAbi.PACKAGE_CLASS;
145
        }
A
Alex Tkachman 已提交
146

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