one more step to multi-file compilation

This commit is contained in:
Alex Tkachman
2012-06-06 12:17:25 +03:00
parent 03c4e755fa
commit 7d938dd98f
5 changed files with 84 additions and 64 deletions
@@ -61,13 +61,12 @@ public class ClassFileFactory {
return newVisitor(className.getInternalName() + ".class");
}
NamespaceCodegen forNamespace(JetFile file) {
NamespaceCodegen forNamespace(FqName fqName, Collection<JetFile> files) {
assert !isDone : "Already done!";
FqName fqName = JetPsiUtil.getFQName(file);
NamespaceCodegen codegen = ns2codegen.get(fqName);
if (codegen == null) {
final ClassBuilder builder = newVisitor(NamespaceCodegen.getJVMClassNameForKotlinNs(fqName).getInternalName() + ".class");
codegen = new NamespaceCodegen(builder, fqName, state, file.getContainingFile());
codegen = new NamespaceCodegen(builder, fqName, state, files);
ns2codegen.put(fqName, codegen);
}
@@ -119,42 +119,25 @@ public class GenerationState {
return Pair.create(className, getFactory().forAnonymousSubclass(className));
}
public NamespaceCodegen forNamespace(JetFile namespace) {
return getFactory().forNamespace(namespace);
public NamespaceCodegen forNamespace(FqName fqName, Collection<JetFile> namespace) {
return getFactory().forNamespace(fqName, namespace);
}
public void compileCorrectFiles(@NotNull CompilationErrorHandler errorHandler) {
MultiMap<String, JetFile> namespaceGrouping = new MultiMap<String, JetFile>();
MultiMap<FqName, JetFile> namespaceGrouping = new MultiMap<FqName, JetFile>();
for (JetFile file : this.files) {
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
namespaceGrouping.putValue(JetPsiUtil.getFQName(file).getFqName(), file);
namespaceGrouping.putValue(JetPsiUtil.getFQName(file), file);
}
for (Map.Entry<String, Collection<JetFile>> entry : namespaceGrouping.entrySet()) {
for (JetFile file : entry.getValue()) {
VirtualFile vFile = file.getVirtualFile();
String path = vFile != null ? vFile.getPath() : "no_virtual_file/" + file.getName();
progress.log("For source: " + path + "\tFor namespace: " + entry.getKey());
try {
generateNamespace(file);
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
errorHandler.reportException(e, vFile == null ? "no file" : vFile.getUrl());
DiagnosticUtils.throwIfRunningOnServer(e);
if (ApplicationManager.getApplication().isInternal()) {
e.printStackTrace();
}
}
}
for (Map.Entry<FqName, Collection<JetFile>> entry : namespaceGrouping.entrySet()) {
generateNamespace(entry.getKey(), entry.getValue(), errorHandler, progress);
}
}
protected void generateNamespace(JetFile namespace) {
NamespaceCodegen codegen = forNamespace(namespace);
codegen.generate(namespace);
protected void generateNamespace(FqName fqName, Collection<JetFile> namespace, CompilationErrorHandler errorHandler, Progress progress) {
NamespaceCodegen codegen = forNamespace(fqName, namespace);
codegen.generate(errorHandler, progress);
}
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) {
@@ -16,19 +16,26 @@
package org.jetbrains.jet.codegen;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.utils.Progress;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.Collection;
import static org.objectweb.asm.Opcodes.*;
/**
@@ -36,12 +43,17 @@ import static org.objectweb.asm.Opcodes.*;
*/
public class NamespaceCodegen {
private final ClassBuilder v;
@NotNull private final FqName name;
private final GenerationState state;
private final Collection<JetFile> files;
public NamespaceCodegen(ClassBuilder v, @NotNull FqName fqName, GenerationState state, PsiFile sourceFile) {
public NamespaceCodegen(ClassBuilder v, @NotNull FqName fqName, GenerationState state, Collection<JetFile> files) {
this.v = v;
name = fqName;
this.state = state;
this.files = files;
PsiFile sourceFile = files.iterator().next().getContainingFile();
v.defineClass(sourceFile, V1_6,
ACC_PUBLIC/*|ACC_SUPER*/,
getJVMClassNameForKotlinNs(fqName).getInternalName(),
@@ -54,8 +66,32 @@ public class NamespaceCodegen {
v.visitSource(sourceFile.getName(), null);
}
public void generate(JetFile file) {
public void generate(CompilationErrorHandler errorHandler, Progress progress) {
for (JetFile file : files) {
VirtualFile vFile = file.getVirtualFile();
try {
String path = vFile != null ? vFile.getPath() : "no_virtual_file/" + file.getName();
if(progress != null) progress.log("For source: " + path);
generate(file);
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
if(errorHandler != null) errorHandler.reportException(e, vFile == null ? "no file" : vFile.getUrl());
DiagnosticUtils.throwIfRunningOnServer(e);
if (ApplicationManager.getApplication().isInternal()) {
e.printStackTrace();
}
}
}
if (hasNonConstantPropertyInitializers()) {
generateStaticInitializers();
}
}
private void generate(JetFile file) {
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
@@ -71,54 +107,54 @@ public class NamespaceCodegen {
else if (declaration instanceof JetScript) {
state.getInjector().getScriptCodegen().generate((JetScript) declaration);
}
// else if (declaration instanceof JetFile) {
// JetFile childNamespace = (JetFile) declaration;
// state.forNamespace(childNamespace).generate(childNamespace);
// }
}
if (hasNonConstantPropertyInitializers(file)) {
generateStaticInitializers(file);
}
}
private void generateStaticInitializers(JetFile namespace) {
private void generateStaticInitializers() {
JetFile namespace = files.iterator().next(); // @todo: hack
MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
for (JetFile file : files) {
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
FrameMap frameMap = new FrameMap();
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContexts.STATIC, state);
FrameMap frameMap = new FrameMap();
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContexts.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);
assert descriptor != null;
if(descriptor.getReceiverParameter().exists()) {
continue;
for (JetDeclaration declaration : file.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);
assert descriptor != null;
if(descriptor.getReceiverParameter().exists()) {
continue;
}
codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
}
codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
}
}
}
}
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "static initializer for namespace", namespace);
mv.visitEnd();
}
}
private static boolean hasNonConstantPropertyInitializers(JetFile namespace) {
for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
return true;
}
private boolean hasNonConstantPropertyInitializers() {
for (JetFile file : files) {
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
return true;
}
}
}
}
return false;
@@ -52,8 +52,10 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.plugin.JetLanguage;
import org.jetbrains.jet.util.QualifiedNamesUtil;
import org.jetbrains.jet.utils.Progress;
import javax.swing.*;
import java.util.Collection;
import java.util.Collections;
public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMarker {
@@ -178,7 +180,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
final GenerationState state = new GenerationState(project, builderFactory, context, Collections.singletonList(file)) {
@Override
protected void generateNamespace(JetFile namespace) {
protected void generateNamespace(FqName fqName, Collection<JetFile> namespace, CompilationErrorHandler errorHandler, Progress progress) {
PsiManager manager = PsiManager.getInstance(project);
stubStack.push(answer);
@@ -195,7 +197,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
fakeFile.setPhysical(false);
answer.setPsi(fakeFile);
super.generateNamespace(namespace);
super.generateNamespace(fqName, namespace, errorHandler, progress);
final StubElement pop = stubStack.pop();
if (pop != answer) {
LOG.error("Unbalanced stack operations: " + pop);
@@ -78,7 +78,7 @@ public class ArrayGenTest extends CodegenTestCase {
public void testIntGenerics () throws Exception {
loadText("class L<T>(var a : T) {} fun foo() = L<Int>(5).a");
// System.out.println(generateToText());
System.out.println(generateToText());
Method foo = generateFunction();
Object invoke = foo.invoke(null);
System.out.println(invoke.getClass());