multi-file namespace compilation
This commit is contained in:
@@ -106,7 +106,11 @@ public abstract class CodegenContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CodegenContext intoNamespace(NamespaceDescriptor descriptor) {
|
public CodegenContext intoNamespace(NamespaceDescriptor descriptor) {
|
||||||
return new CodegenContexts.NamespaceContext(descriptor, this);
|
return new CodegenContexts.NamespaceContext(descriptor, this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoNamespacePart(String delegateTo, NamespaceDescriptor descriptor) {
|
||||||
|
return new CodegenContexts.NamespaceContext(descriptor, this, new OwnerKind.StaticDelegateKind(StackValue.none(), delegateTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
|
public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
|
||||||
|
|||||||
@@ -272,8 +272,8 @@ public class CodegenContexts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class NamespaceContext extends CodegenContext {
|
public static class NamespaceContext extends CodegenContext {
|
||||||
public NamespaceContext(NamespaceDescriptor contextDescriptor, CodegenContext parent) {
|
public NamespaceContext(NamespaceDescriptor contextDescriptor, CodegenContext parent, OwnerKind kind) {
|
||||||
super(contextDescriptor, OwnerKind.NAMESPACE, parent, null);
|
super(contextDescriptor, kind != null ? kind : OwnerKind.NAMESPACE, parent, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public class FunctionCodegen {
|
|||||||
ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
|
ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
|
||||||
|
|
||||||
if (kind != OwnerKind.TRAIT_IMPL || bodyExpressions != null) {
|
if (kind != OwnerKind.TRAIT_IMPL || bodyExpressions != null) {
|
||||||
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
boolean isStatic = kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind;
|
||||||
if (isStatic || kind == OwnerKind.TRAIT_IMPL)
|
if (isStatic || kind == OwnerKind.TRAIT_IMPL)
|
||||||
flags |= ACC_STATIC;
|
flags |= ACC_STATIC;
|
||||||
|
|
||||||
@@ -199,13 +199,24 @@ public class FunctionCodegen {
|
|||||||
frameMap.enter(parameter, argTypes[i+add].getSize());
|
frameMap.enter(parameter, argTypes[i+add].getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((kind instanceof OwnerKind.DelegateKind) != (functionDescriptor.getKind() == FunctionDescriptor.Kind.DELEGATION)) {
|
if (!isStatic && (kind instanceof OwnerKind.DelegateKind) != (functionDescriptor.getKind() == FunctionDescriptor.Kind.DELEGATION)) {
|
||||||
throw new IllegalStateException("mismatching kind in " + functionDescriptor);
|
throw new IllegalStateException("mismatching kind in " + functionDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Name, Label> mapLabelsToDivideLocalVarVisibilityForSharedVar = new HashMap<Name, Label>();
|
Map<Name, Label> mapLabelsToDivideLocalVarVisibilityForSharedVar = new HashMap<Name, Label>();
|
||||||
|
|
||||||
if (kind instanceof OwnerKind.DelegateKind) {
|
if (kind instanceof OwnerKind.StaticDelegateKind) {
|
||||||
|
OwnerKind.StaticDelegateKind dk = (OwnerKind.StaticDelegateKind) kind;
|
||||||
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
for (int i = 0, k = 0; i < argTypes.length; i++) {
|
||||||
|
Type argType = argTypes[i];
|
||||||
|
iv.load(k, argType);
|
||||||
|
k += argType.getSize();
|
||||||
|
}
|
||||||
|
iv.invokestatic(dk.getOwnerClass(), jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor());
|
||||||
|
iv.areturn(jvmSignature.getAsmMethod().getReturnType());
|
||||||
|
}
|
||||||
|
else if (kind instanceof OwnerKind.DelegateKind) {
|
||||||
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
@@ -355,7 +366,7 @@ public class FunctionCodegen {
|
|||||||
if(needed) {
|
if(needed) {
|
||||||
ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
|
ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
|
||||||
boolean hasReceiver = receiverParameter.exists();
|
boolean hasReceiver = receiverParameter.exists();
|
||||||
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
boolean isStatic = kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind;
|
||||||
|
|
||||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||||
String correctedDescr = "(" + jvmSignature.getDescriptor().substring(jvmSignature.getDescriptor().indexOf(";") + 1);
|
String correctedDescr = "(" + jvmSignature.getDescriptor().substring(jvmSignature.getDescriptor().indexOf(";") + 1);
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ public class GenerationState {
|
|||||||
return getFactory().newVisitor(getInjector().getJetTypeMapper().mapType(aClass.getDefaultType(), MapTypeMode.IMPL).getInternalName() + ".class");
|
return getFactory().newVisitor(getInjector().getJetTypeMapper().mapType(aClass.getDefaultType(), MapTypeMode.IMPL).getInternalName() + ".class");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClassBuilder forNamespacepart(String name, JetFile file) {
|
||||||
|
return getFactory().newVisitor(name + ".class");
|
||||||
|
}
|
||||||
|
|
||||||
public ClassBuilder forTraitImplementation(ClassDescriptor aClass) {
|
public ClassBuilder forTraitImplementation(ClassDescriptor aClass) {
|
||||||
return getFactory().newVisitor(getInjector().getJetTypeMapper().mapType(aClass.getDefaultType(), MapTypeMode.TRAIT_IMPL).getInternalName() + ".class");
|
return getFactory().newVisitor(getInjector().getJetTypeMapper().mapType(aClass.getDefaultType(), MapTypeMode.TRAIT_IMPL).getInternalName() + ".class");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static MapTypeMode ownerKindToMapTypeMode(OwnerKind kind) {
|
public static MapTypeMode ownerKindToMapTypeMode(OwnerKind kind) {
|
||||||
if (kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.NAMESPACE) {
|
if (kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind) {
|
||||||
return MapTypeMode.IMPL;
|
return MapTypeMode.IMPL;
|
||||||
}
|
}
|
||||||
else if (kind == OwnerKind.TRAIT_IMPL) {
|
else if (kind == OwnerKind.TRAIT_IMPL) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.codegen;
|
|||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||||
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -34,6 +35,7 @@ import org.objectweb.asm.MethodVisitor;
|
|||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
@@ -46,6 +48,7 @@ public class NamespaceCodegen {
|
|||||||
@NotNull private final FqName name;
|
@NotNull private final FqName name;
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
private final Collection<JetFile> files;
|
private final Collection<JetFile> files;
|
||||||
|
private int nextMultiFile = 0;
|
||||||
|
|
||||||
public NamespaceCodegen(ClassBuilder v, @NotNull FqName fqName, GenerationState state, Collection<JetFile> files) {
|
public NamespaceCodegen(ClassBuilder v, @NotNull FqName fqName, GenerationState state, Collection<JetFile> files) {
|
||||||
this.v = v;
|
this.v = v;
|
||||||
@@ -67,12 +70,27 @@ public class NamespaceCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generate(CompilationErrorHandler errorHandler, Progress progress) {
|
public void generate(CompilationErrorHandler errorHandler, Progress progress) {
|
||||||
|
ArrayList<Pair<JetFile, Collection<JetDeclaration>>> byFile = new ArrayList<Pair<JetFile, Collection<JetDeclaration>>>();
|
||||||
|
|
||||||
|
for (JetFile file : files) {
|
||||||
|
ArrayList<JetDeclaration> fileFunctions = new ArrayList<JetDeclaration>();
|
||||||
|
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||||
|
if (declaration instanceof JetNamedFunction) {
|
||||||
|
fileFunctions.add(declaration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fileFunctions.size() > 0)
|
||||||
|
byFile.add(new Pair<JetFile, Collection<JetDeclaration>>(file, fileFunctions));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean multiFile = byFile.size() > 1;
|
||||||
|
|
||||||
for (JetFile file : files) {
|
for (JetFile file : files) {
|
||||||
VirtualFile vFile = file.getVirtualFile();
|
VirtualFile vFile = file.getVirtualFile();
|
||||||
try {
|
try {
|
||||||
String path = vFile != null ? vFile.getPath() : "no_virtual_file/" + file.getName();
|
String path = vFile != null ? vFile.getPath() : "no_virtual_file/" + file.getName();
|
||||||
if(progress != null) progress.log("For source: " + path);
|
if(progress != null) progress.log("For source: " + path);
|
||||||
generate(file);
|
generate(file, multiFile);
|
||||||
}
|
}
|
||||||
catch (ProcessCanceledException e) {
|
catch (ProcessCanceledException e) {
|
||||||
throw e;
|
throw e;
|
||||||
@@ -91,14 +109,22 @@ public class NamespaceCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generate(JetFile file) {
|
private void generate(JetFile file, boolean multiFile) {
|
||||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
|
if (declaration instanceof JetProperty) {
|
||||||
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
||||||
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor);
|
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor);
|
||||||
state.getInjector().getMemberCodegen().generateFunctionOrProperty(
|
state.getInjector().getMemberCodegen().generateFunctionOrProperty(
|
||||||
(JetTypeParameterListOwner) declaration, context, v);
|
(JetTypeParameterListOwner) declaration, context, v);
|
||||||
}
|
}
|
||||||
|
else if (declaration instanceof JetNamedFunction) {
|
||||||
|
if(!multiFile) {
|
||||||
|
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
||||||
|
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor);
|
||||||
|
state.getInjector().getMemberCodegen().generateFunctionOrProperty(
|
||||||
|
(JetTypeParameterListOwner) declaration, context, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (declaration instanceof JetClassOrObject) {
|
else if (declaration instanceof JetClassOrObject) {
|
||||||
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
||||||
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor);
|
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor);
|
||||||
@@ -108,6 +134,47 @@ public class NamespaceCodegen {
|
|||||||
state.getInjector().getScriptCodegen().generate((JetScript) declaration);
|
state.getInjector().getScriptCodegen().generate((JetScript) declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(multiFile) {
|
||||||
|
int k = 0;
|
||||||
|
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||||
|
if (declaration instanceof JetNamedFunction) {
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(k > 0) {
|
||||||
|
PsiFile containingFile = file.getContainingFile();
|
||||||
|
String className = name.getFqName().replace('.','/') + "namespace$src$" + (nextMultiFile++);
|
||||||
|
ClassBuilder builder = state.forNamespacepart(className, file);
|
||||||
|
|
||||||
|
builder.defineClass(containingFile, V1_6,
|
||||||
|
ACC_PUBLIC/*|ACC_SUPER*/,
|
||||||
|
className,
|
||||||
|
null,
|
||||||
|
//"jet/lang/Namespace",
|
||||||
|
"java/lang/Object",
|
||||||
|
new String[0]
|
||||||
|
);
|
||||||
|
builder.visitSource(containingFile.getName(), null);
|
||||||
|
|
||||||
|
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||||
|
if (declaration instanceof JetNamedFunction) {
|
||||||
|
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
||||||
|
{
|
||||||
|
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor);
|
||||||
|
state.getInjector().getMemberCodegen().generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, builder);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
final CodegenContext context = CodegenContexts.STATIC.intoNamespacePart(className, descriptor);
|
||||||
|
state.getInjector().getMemberCodegen().generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateStaticInitializers() {
|
private void generateStaticInitializers() {
|
||||||
|
|||||||
@@ -49,6 +49,25 @@ public class OwnerKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class StaticDelegateKind extends OwnerKind {
|
||||||
|
private final StackValue delegate;
|
||||||
|
private final String ownerClass;
|
||||||
|
|
||||||
|
public StaticDelegateKind(StackValue delegate, String ownerClass) {
|
||||||
|
super("staticDelegateKind");
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.ownerClass = ownerClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue getDelegate() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOwnerClass() {
|
||||||
|
return ownerClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "OwnerKind(" + name + ")";
|
return "OwnerKind(" + name + ")";
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
fun ok() = "OK"
|
fun ok(res: String = "OK") = res
|
||||||
Reference in New Issue
Block a user