big codegen rewrite
This commit is contained in:
@@ -20,6 +20,7 @@ import org.jetbrains.asm4.MethodVisitor;
|
|||||||
import org.jetbrains.asm4.Opcodes;
|
import org.jetbrains.asm4.Opcodes;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class ClassBuilderFactories {
|
|||||||
return super.getCommonSuperClass(type1, type2);
|
return super.getCommonSuperClass(type1, type2);
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
// @todo we might need at some point do more sofisticated handling
|
// @todo we might need at some point do more sophisticated handling
|
||||||
return "java/lang/Object";
|
return "java/lang/Object";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -30,14 +31,14 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class ClassCodegen {
|
public class ClassCodegen {
|
||||||
private GenerationState state;
|
private GenerationState state;
|
||||||
private JetTypeMapper jetTypeMapper;
|
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) private JetTypeMapper jetTypeMapper;
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setState(GenerationState state) {
|
public void setState(GenerationState state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedParameters")
|
||||||
@Inject
|
@Inject
|
||||||
public void setJetTypeMapper(JetTypeMapper jetTypeMapper) {
|
public void setJetTypeMapper(JetTypeMapper jetTypeMapper) {
|
||||||
this.jetTypeMapper = jetTypeMapper;
|
this.jetTypeMapper = jetTypeMapper;
|
||||||
@@ -48,13 +49,13 @@ public class ClassCodegen {
|
|||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
ClassBuilder classBuilder = state.forClassImplementation(descriptor);
|
ClassBuilder classBuilder = state.forClassImplementation(descriptor);
|
||||||
|
|
||||||
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, jetTypeMapper);
|
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
|
||||||
|
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) {
|
if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) {
|
||||||
// Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate
|
// Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate
|
||||||
// The same code is present below for the case when we generate real bytecode. This is because the order should be
|
// The same code is present below for the case when we generate real bytecode. This is because the order should be
|
||||||
// different for the case when we compute closures
|
// different for the case when we compute closures
|
||||||
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors, classBuilder);
|
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||||
@@ -72,7 +73,7 @@ public class ClassCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
|
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
|
||||||
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors, classBuilder);
|
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
classBuilder.done();
|
classBuilder.done();
|
||||||
@@ -86,13 +87,14 @@ public class ClassCodegen {
|
|||||||
ClassBuilder classBuilder
|
ClassBuilder classBuilder
|
||||||
) {
|
) {
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
CodegenContext classContext = context.intoClass(descriptor, kind, jetTypeMapper);
|
CodegenContext classContext = context.intoClass(descriptor, kind, state);
|
||||||
classContext.copyAccessors(accessors);
|
classContext.copyAccessors(accessors);
|
||||||
|
|
||||||
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
|
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
|
||||||
|
|
||||||
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
|
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
|
||||||
ClassBuilder traitBuilder = state.forTraitImplementation(descriptor);
|
ClassBuilder traitBuilder = state.forTraitImplementation(descriptor);
|
||||||
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, jetTypeMapper), traitBuilder, state)
|
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state)
|
||||||
.generate();
|
.generate();
|
||||||
traitBuilder.done();
|
traitBuilder.done();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,15 +22,16 @@ package org.jetbrains.jet.codegen;
|
|||||||
|
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.asm4.Label;
|
import org.jetbrains.asm4.Label;
|
||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
import org.jetbrains.asm4.commons.Method;
|
import org.jetbrains.asm4.commons.Method;
|
||||||
import org.jetbrains.asm4.signature.SignatureWriter;
|
import org.jetbrains.asm4.signature.SignatureWriter;
|
||||||
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
|
import org.jetbrains.jet.codegen.context.CalculatedClosure;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
|
import org.jetbrains.jet.codegen.context.ClosureAnnotator;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
|
import org.jetbrains.jet.codegen.context.MutableClosure;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||||
@@ -39,7 +40,6 @@ import org.jetbrains.jet.lang.psi.JetExpression;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
@@ -48,81 +48,42 @@ import java.util.List;
|
|||||||
|
|
||||||
import static org.jetbrains.asm4.Opcodes.*;
|
import static org.jetbrains.asm4.Opcodes.*;
|
||||||
|
|
||||||
public class ClosureCodegen extends ObjectOrClosureCodegen {
|
public class ClosureCodegen {
|
||||||
|
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
private final ClosureAnnotator closureAnnotator;
|
private final ClosureAnnotator closureAnnotator;
|
||||||
private final JetTypeMapper typeMapper;
|
private final JetTypeMapper typeMapper;
|
||||||
|
|
||||||
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, CodegenContext context) {
|
Method constructor;
|
||||||
super(exprContext, context, state);
|
private final GenerationState state;
|
||||||
|
private final MutableClosure closure;
|
||||||
|
JvmClassName name;
|
||||||
|
|
||||||
|
|
||||||
|
public ClosureCodegen(GenerationState state, MutableClosure closure) {
|
||||||
|
this.state = state;
|
||||||
|
this.closure = closure;
|
||||||
bindingContext = state.getBindingContext();
|
bindingContext = state.getBindingContext();
|
||||||
typeMapper = this.state.getInjector().getJetTypeMapper();
|
typeMapper = state.getInjector().getJetTypeMapper();
|
||||||
closureAnnotator = typeMapper.getClosureAnnotator();
|
closureAnnotator = typeMapper.getClosureAnnotator();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JvmMethodSignature erasedInvokeSignature(FunctionDescriptor fd) {
|
public ClosureCodegen gen(JetExpression fun, CodegenContext context, ExpressionCodegen expressionCodegen) {
|
||||||
|
final SimpleFunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, fun);
|
||||||
|
assert descriptor != null;
|
||||||
|
|
||||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
|
||||||
|
|
||||||
signatureWriter.writeFormalTypeParametersStart();
|
|
||||||
signatureWriter.writeFormalTypeParametersEnd();
|
|
||||||
|
|
||||||
boolean isExtensionFunction = fd.getReceiverParameter().exists();
|
|
||||||
int paramCount = fd.getValueParameters().size();
|
|
||||||
if (isExtensionFunction) {
|
|
||||||
paramCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
signatureWriter.writeParametersStart();
|
|
||||||
|
|
||||||
for (int i = 0; i < paramCount; ++i) {
|
|
||||||
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
|
|
||||||
signatureWriter.writeAsmType(JetTypeMapper.OBJECT_TYPE, true);
|
|
||||||
signatureWriter.writeParameterTypeEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
signatureWriter.writeParametersEnd();
|
|
||||||
|
|
||||||
signatureWriter.writeReturnType();
|
|
||||||
signatureWriter.writeAsmType(JetTypeMapper.OBJECT_TYPE, true);
|
|
||||||
signatureWriter.writeReturnTypeEnd();
|
|
||||||
|
|
||||||
return signatureWriter.makeJvmMethodSignature("invoke");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CallableMethod asCallableMethod(FunctionDescriptor fd, @NotNull JetTypeMapper typeMapper) {
|
|
||||||
JvmMethodSignature descriptor = erasedInvokeSignature(fd);
|
|
||||||
JvmClassName owner = getInternalClassName(fd);
|
|
||||||
Type receiverParameterType;
|
|
||||||
if (fd.getReceiverParameter().exists()) {
|
|
||||||
receiverParameterType = typeMapper.mapType(fd.getOriginal().getReceiverParameter().getType(), MapTypeMode.VALUE);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
receiverParameterType = null;
|
|
||||||
}
|
|
||||||
return new CallableMethod(
|
|
||||||
owner, null, null, descriptor, INVOKEVIRTUAL,
|
|
||||||
getInternalClassName(fd), receiverParameterType, getInternalClassName(fd).getAsmType());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JvmMethodSignature invokeSignature(FunctionDescriptor fd) {
|
|
||||||
return typeMapper.mapSignature(Name.identifier("invoke"), fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GeneratedAnonymousClassDescriptor gen(JetExpression fun) {
|
|
||||||
final Pair<JvmClassName, ClassBuilder> nameAndVisitor = state.forAnonymousSubclass(fun);
|
final Pair<JvmClassName, ClassBuilder> nameAndVisitor = state.forAnonymousSubclass(fun);
|
||||||
|
|
||||||
final FunctionDescriptor funDescriptor = bindingContext.get(BindingContext.FUNCTION, fun);
|
final FunctionDescriptor funDescriptor = bindingContext.get(BindingContext.FUNCTION, fun);
|
||||||
|
|
||||||
cv = nameAndVisitor.getSecond();
|
ClassBuilder cv = nameAndVisitor.getSecond();
|
||||||
name = nameAndVisitor.getFirst();
|
name = nameAndVisitor.getFirst();
|
||||||
|
|
||||||
SignatureWriter signatureWriter = new SignatureWriter();
|
SignatureWriter signatureWriter = new SignatureWriter();
|
||||||
|
|
||||||
assert funDescriptor != null;
|
assert funDescriptor != null;
|
||||||
final List<ValueParameterDescriptor> parameters = funDescriptor.getValueParameters();
|
final List<ValueParameterDescriptor> parameters = funDescriptor.getValueParameters();
|
||||||
final JvmClassName funClass = getInternalClassName(funDescriptor);
|
final JvmClassName funClass = CodegenUtil.getInternalClassName(funDescriptor);
|
||||||
signatureWriter.visitClassType(funClass.getInternalName());
|
signatureWriter.visitClassType(funClass.getInternalName());
|
||||||
for (ValueParameterDescriptor parameter : parameters) {
|
for (ValueParameterDescriptor parameter : parameters) {
|
||||||
appendType(signatureWriter, parameter.getType(), '=');
|
appendType(signatureWriter, parameter.getType(), '=');
|
||||||
@@ -143,46 +104,27 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
|
|
||||||
|
|
||||||
generateBridge(name.getInternalName(), funDescriptor, fun, cv);
|
generateBridge(name.getInternalName(), funDescriptor, fun, cv);
|
||||||
captureThis = generateBody(funDescriptor, cv, (JetDeclarationWithBody) fun);
|
generateBody(funDescriptor, cv, (JetDeclarationWithBody) fun, context, expressionCodegen);
|
||||||
|
|
||||||
final ClassDescriptor enclosingClass = context.getEnclosingClass();
|
constructor = generateConstructor(funClass, fun, cv, closure);
|
||||||
if (enclosingClass == null) {
|
|
||||||
captureThis = null;
|
if (CodegenUtil.isConst(closure)) {
|
||||||
|
generateConstInstance(fun, cv);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Method constructor = generateConstructor(funClass, fun, funDescriptor);
|
CodegenUtil.generateClosureFields(closure, cv, state.getInjector().getJetTypeMapper());
|
||||||
|
|
||||||
if (captureThis != null) {
|
|
||||||
cv.newField(fun, ACC_FINAL, "this$0", typeMapper.mapType(enclosingClass.getDefaultType(), MapTypeMode.IMPL).getDescriptor(),
|
|
||||||
null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isConst()) {
|
|
||||||
generateConstInstance(fun);
|
|
||||||
}
|
|
||||||
|
|
||||||
cv.done();
|
cv.done();
|
||||||
|
|
||||||
final GeneratedAnonymousClassDescriptor answer =
|
return this;
|
||||||
new GeneratedAnonymousClassDescriptor(name, constructor, captureThis, captureReceiver);
|
|
||||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
|
||||||
if (descriptor == funDescriptor) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (descriptor instanceof VariableDescriptor || CodegenUtil.isNamedFun(descriptor, state.getBindingContext()) &&
|
|
||||||
descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
|
||||||
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
|
|
||||||
answer.addArg(valueDescriptor.getOuterValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return answer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateConstInstance(PsiElement fun) {
|
private void generateConstInstance(PsiElement fun, ClassBuilder cv) {
|
||||||
String classDescr = name.getDescriptor();
|
String classDescr = name.getDescriptor();
|
||||||
cv.newField(fun, ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "$instance", classDescr, null, null);
|
cv.newField(fun, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, "$instance", classDescr, null, null);
|
||||||
|
|
||||||
MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC, "$getInstance", "()" + classDescr, null, new String[0]);
|
MethodVisitor mv =
|
||||||
|
cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "$getInstance", "()" + classDescr, null, new String[0]);
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||||
StubCodegen.generateStubCode(mv);
|
StubCodegen.generateStubCode(mv);
|
||||||
}
|
}
|
||||||
@@ -206,21 +148,29 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClassDescriptor generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) {
|
private ClassDescriptor generateBody(
|
||||||
ClassDescriptor function =
|
FunctionDescriptor funDescriptor,
|
||||||
closureAnnotator.classDescriptorForFunctionDescriptor(funDescriptor);
|
ClassBuilder cv,
|
||||||
|
JetDeclarationWithBody body,
|
||||||
|
CodegenContext context,
|
||||||
|
ExpressionCodegen expressionCodegen
|
||||||
|
) {
|
||||||
|
|
||||||
final CodegenContexts.ClosureContext closureContext = context.intoClosure(
|
final CodegenContext closureContext = context.intoClosure(funDescriptor, expressionCodegen);
|
||||||
funDescriptor, function, this, typeMapper);
|
|
||||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||||
JvmMethodSignature jvmMethodSignature = invokeSignature(funDescriptor);
|
JvmMethodSignature jvmMethodSignature = typeMapper.invokeSignature(funDescriptor);
|
||||||
fc.generateMethod(body, jvmMethodSignature, false, null, funDescriptor);
|
fc.generateMethod(body, jvmMethodSignature, false, null, funDescriptor);
|
||||||
return closureContext.outerWasUsed;
|
return closureContext.closure.getCaptureThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetExpression fun, ClassBuilder cv) {
|
private void generateBridge(
|
||||||
final JvmMethodSignature bridge = erasedInvokeSignature(funDescriptor);
|
String className,
|
||||||
final Method delegate = invokeSignature(funDescriptor).getAsmMethod();
|
FunctionDescriptor funDescriptor,
|
||||||
|
JetExpression fun,
|
||||||
|
ClassBuilder cv
|
||||||
|
) {
|
||||||
|
final JvmMethodSignature bridge = CodegenUtil.erasedInvokeSignature(funDescriptor);
|
||||||
|
final Method delegate = typeMapper.invokeSignature(funDescriptor).getAsmMethod();
|
||||||
|
|
||||||
if (bridge.getAsmMethod().getDescriptor().equals(delegate.getDescriptor())) {
|
if (bridge.getAsmMethod().getDescriptor().equals(delegate.getDescriptor())) {
|
||||||
return;
|
return;
|
||||||
@@ -265,9 +215,14 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Method generateConstructor(JvmClassName funClass, JetExpression fun, FunctionDescriptor funDescriptor) {
|
private Method generateConstructor(
|
||||||
|
JvmClassName funClass,
|
||||||
|
JetExpression fun,
|
||||||
|
ClassBuilder cv,
|
||||||
|
CalculatedClosure closure
|
||||||
|
) {
|
||||||
final ArrayList<Pair<String, Type>> args = new ArrayList<Pair<String, Type>>();
|
final ArrayList<Pair<String, Type>> args = new ArrayList<Pair<String, Type>>();
|
||||||
boolean putFieldForMyself = calculateConstructorParameters(funDescriptor, args);
|
calculateConstructorParameters(args, state, closure);
|
||||||
|
|
||||||
final Type[] argTypes = nameAnTypeListToTypeArray(args);
|
final Type[] argTypes = nameAnTypeListToTypeArray(args);
|
||||||
|
|
||||||
@@ -293,14 +248,6 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
StackValue.field(type, name, nameAndType.first, false).store(type, iv);
|
StackValue.field(type, name, nameAndType.first, false).store(type, iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (putFieldForMyself) {
|
|
||||||
Type type = name.getAsmType();
|
|
||||||
String fieldName = "$" + funDescriptor.getName();
|
|
||||||
iv.load(0, type);
|
|
||||||
iv.dup();
|
|
||||||
StackValue.field(type, name, fieldName, false).store(type, iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
iv.visitInsn(RETURN);
|
iv.visitInsn(RETURN);
|
||||||
|
|
||||||
FunctionCodegen.endVisit(iv, "constructor", fun);
|
FunctionCodegen.endVisit(iv, "constructor", fun);
|
||||||
@@ -308,22 +255,24 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
return constructor;
|
return constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean calculateConstructorParameters(FunctionDescriptor funDescriptor, List<Pair<String, Type>> args) {
|
private void calculateConstructorParameters(
|
||||||
|
List<Pair<String, Type>> args,
|
||||||
|
GenerationState state,
|
||||||
|
CalculatedClosure closure
|
||||||
|
) {
|
||||||
|
final ClassDescriptor captureThis = closure.getCaptureThis();
|
||||||
if (captureThis != null) {
|
if (captureThis != null) {
|
||||||
final Type type = typeMapper.mapType(context.getThisDescriptor().getDefaultType(), MapTypeMode.VALUE);
|
final Type type = typeMapper.mapType(captureThis.getDefaultType(), MapTypeMode.VALUE);
|
||||||
args.add(new Pair<String, Type>("this$0", type));
|
args.add(new Pair<String, Type>(CodegenUtil.THIS$0, type));
|
||||||
}
|
}
|
||||||
|
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||||
if (captureReceiver != null) {
|
if (captureReceiver != null) {
|
||||||
args.add(new Pair<String, Type>("receiver$0", typeMapper.mapType(captureReceiver.getDefaultType(), MapTypeMode.VALUE)));
|
args.add(new Pair<String, Type>(CodegenUtil.RECEIVER$0,
|
||||||
|
typeMapper.mapType(captureReceiver.getDefaultType(), MapTypeMode.VALUE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean putFieldForMyself = false;
|
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
|
||||||
|
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
||||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
|
||||||
if (descriptor == funDescriptor) {
|
|
||||||
putFieldForMyself = true;
|
|
||||||
}
|
|
||||||
else if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
|
||||||
final Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
final Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||||
|
|
||||||
final Type type = sharedVarType != null
|
final Type type = sharedVarType != null
|
||||||
@@ -343,7 +292,6 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
assert captureReceiver != null;
|
assert captureReceiver != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return putFieldForMyself;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type[] nameAnTypeListToTypeArray(List<Pair<String, Type>> args) {
|
private static Type[] nameAnTypeListToTypeArray(List<Pair<String, Type>> args) {
|
||||||
@@ -354,17 +302,6 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
return argTypes;
|
return argTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JvmClassName getInternalClassName(FunctionDescriptor descriptor) {
|
|
||||||
final int paramCount = descriptor.getValueParameters().size();
|
|
||||||
if (descriptor.getReceiverParameter().exists()) {
|
|
||||||
return JvmClassName.byInternalName("jet/ExtensionFunction" + paramCount);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return JvmClassName.byInternalName("jet/Function" + paramCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendType(SignatureWriter signatureWriter, JetType type, char variance) {
|
private void appendType(SignatureWriter signatureWriter, JetType type, char variance) {
|
||||||
signatureWriter.visitTypeArgument(variance);
|
signatureWriter.visitTypeArgument(variance);
|
||||||
|
|
||||||
|
|||||||
@@ -1,262 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.asm4.Type;
|
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.JetTypeMapper.OBJECT_TYPE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @author max
|
|
||||||
* @author alex.tkachman
|
|
||||||
*/
|
|
||||||
public abstract class CodegenContext {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final DeclarationDescriptor contextDescriptor;
|
|
||||||
|
|
||||||
private final OwnerKind contextKind;
|
|
||||||
@Nullable
|
|
||||||
private final CodegenContext parentContext;
|
|
||||||
public final ObjectOrClosureCodegen closure;
|
|
||||||
private final ClassDescriptor thisDescriptor;
|
|
||||||
|
|
||||||
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
|
||||||
|
|
||||||
protected StackValue outerExpression;
|
|
||||||
|
|
||||||
protected ClassDescriptor outerWasUsed;
|
|
||||||
|
|
||||||
public CodegenContext(
|
|
||||||
JetTypeMapper typeMapper,
|
|
||||||
@NotNull DeclarationDescriptor contextDescriptor,
|
|
||||||
OwnerKind contextKind,
|
|
||||||
@Nullable CodegenContext parentContext,
|
|
||||||
@Nullable ObjectOrClosureCodegen closureCodegen,
|
|
||||||
ClassDescriptor thisDescriptor
|
|
||||||
) {
|
|
||||||
this.contextDescriptor = contextDescriptor;
|
|
||||||
this.contextKind = contextKind;
|
|
||||||
this.parentContext = parentContext;
|
|
||||||
closure = closureCodegen;
|
|
||||||
this.thisDescriptor = thisDescriptor;
|
|
||||||
|
|
||||||
final ClassDescriptor enclosingClass = getEnclosingClass();
|
|
||||||
//outerExpression = enclosingClass != null && hasThisDescriptor() && typeMapper != null
|
|
||||||
// ? StackValue.field(typeMapper.mapType(enclosingClass.getDefaultType(),MapTypeMode.VALUE), typeMapper.getJvmClassName(thisDescriptor), "this$0", false)
|
|
||||||
// : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
protected final ClassDescriptor getThisDescriptor() {
|
|
||||||
if (thisDescriptor == null) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
return thisDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final boolean hasThisDescriptor() {
|
|
||||||
return thisDescriptor != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeclarationDescriptor getClassOrNamespaceDescriptor() {
|
|
||||||
CodegenContext c = this;
|
|
||||||
while (true) {
|
|
||||||
assert c != null;
|
|
||||||
DeclarationDescriptor contextDescriptor = c.getContextDescriptor();
|
|
||||||
if (!(contextDescriptor instanceof ClassDescriptor) && !(contextDescriptor instanceof NamespaceDescriptor)) {
|
|
||||||
c = c.getParentContext();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return contextDescriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CallableDescriptor getReceiverDescriptor() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected StackValue getOuterExpression(@Nullable StackValue prefix) {
|
|
||||||
if (outerExpression == null) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
outerWasUsed = getEnclosingClass();
|
|
||||||
return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public DeclarationDescriptor getContextDescriptor() {
|
|
||||||
return contextDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OwnerKind getContextKind() {
|
|
||||||
return contextKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodegenContext intoNamespace(NamespaceDescriptor descriptor, JetTypeMapper typeMapper) {
|
|
||||||
return new CodegenContexts.NamespaceContext(typeMapper, descriptor, this, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodegenContext intoNamespacePart(String delegateTo, NamespaceDescriptor descriptor, JetTypeMapper typeMapper) {
|
|
||||||
return new CodegenContexts.NamespaceContext(typeMapper, descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo));
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
|
|
||||||
return new CodegenContexts.ClassContext(typeMapper, descriptor, kind, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodegenContext intoAnonymousClass(
|
|
||||||
@NotNull ObjectOrClosureCodegen closure,
|
|
||||||
ClassDescriptor descriptor,
|
|
||||||
OwnerKind kind,
|
|
||||||
JetTypeMapper typeMapper
|
|
||||||
) {
|
|
||||||
return new CodegenContexts.AnonymousClassContext(typeMapper, descriptor, kind, this, closure);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodegenContexts.MethodContext intoFunction(FunctionDescriptor descriptor, JetTypeMapper typeMapper) {
|
|
||||||
return new CodegenContexts.MethodContext(typeMapper, descriptor, getContextKind(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodegenContexts.ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) {
|
|
||||||
if (descriptor == null) {
|
|
||||||
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
|
||||||
.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(),
|
|
||||||
Visibilities.PUBLIC);
|
|
||||||
}
|
|
||||||
return new CodegenContexts.ConstructorContext(typeMapper, descriptor, getContextKind(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodegenContext intoScript(@NotNull ScriptDescriptor script, @NotNull ClassDescriptor classDescriptor, JetTypeMapper typeMapper) {
|
|
||||||
return new CodegenContexts.ScriptContext(typeMapper, script, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodegenContexts.ClosureContext intoClosure(
|
|
||||||
FunctionDescriptor funDescriptor,
|
|
||||||
ClassDescriptor classDescriptor,
|
|
||||||
ClosureCodegen closureCodegen,
|
|
||||||
JetTypeMapper typeMapper
|
|
||||||
) {
|
|
||||||
return new CodegenContexts.ClosureContext(typeMapper, funDescriptor, classDescriptor, this, closureCodegen);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FrameMap prepareFrame(JetTypeMapper mapper) {
|
|
||||||
FrameMap frameMap = new FrameMap();
|
|
||||||
|
|
||||||
if (getContextKind() != OwnerKind.NAMESPACE) {
|
|
||||||
frameMap.enterTemp(OBJECT_TYPE); // 0 slot for this
|
|
||||||
}
|
|
||||||
|
|
||||||
CallableDescriptor receiverDescriptor = getReceiverDescriptor();
|
|
||||||
if (receiverDescriptor != null) {
|
|
||||||
Type type = mapper.mapType(receiverDescriptor.getReceiverParameter().getType(), MapTypeMode.VALUE);
|
|
||||||
frameMap.enterTemp(type); // Next slot for fake this
|
|
||||||
}
|
|
||||||
|
|
||||||
return frameMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public CodegenContext getParentContext() {
|
|
||||||
return parentContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) {
|
|
||||||
final ObjectOrClosureCodegen top = closure;
|
|
||||||
if (top != null) {
|
|
||||||
final StackValue answer = top.lookupInContext(d, result);
|
|
||||||
if (answer != null) {
|
|
||||||
return result == null ? answer : StackValue.composed(result, answer);
|
|
||||||
}
|
|
||||||
|
|
||||||
StackValue outer = getOuterExpression(null);
|
|
||||||
result = result == null ? outer : StackValue.composed(result, outer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parentContext != null ? parentContext.lookupInContext(d, v, result) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassDescriptor getEnclosingClass() {
|
|
||||||
CodegenContext cur = getParentContext();
|
|
||||||
while (cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor)) {
|
|
||||||
cur = cur.getParentContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
return cur == null ? null : (ClassDescriptor) cur.getContextDescriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
DeclarationDescriptor getAccessor(DeclarationDescriptor descriptor) {
|
|
||||||
if (accessors == null) {
|
|
||||||
accessors = new HashMap<DeclarationDescriptor, DeclarationDescriptor>();
|
|
||||||
}
|
|
||||||
descriptor = descriptor.getOriginal();
|
|
||||||
DeclarationDescriptor accessor = accessors.get(descriptor);
|
|
||||||
if (accessor != null) {
|
|
||||||
return accessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
|
||||||
accessor = new AccessorForFunctionDescriptor(descriptor, contextDescriptor, accessors.size());
|
|
||||||
}
|
|
||||||
else if (descriptor instanceof PropertyDescriptor) {
|
|
||||||
accessor = new AccessorForPropertyDescriptor((PropertyDescriptor) descriptor, contextDescriptor, accessors.size());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
accessors.put(descriptor, accessor);
|
|
||||||
return accessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StackValue getReceiverExpression(JetTypeMapper typeMapper) {
|
|
||||||
assert getReceiverDescriptor() != null;
|
|
||||||
Type asmType = typeMapper.mapType(getReceiverDescriptor().getReceiverParameter().getType(), MapTypeMode.VALUE);
|
|
||||||
return hasThisDescriptor() ? StackValue.local(1, asmType) : StackValue.local(0, asmType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean isStatic();
|
|
||||||
|
|
||||||
public void copyAccessors(Map<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
|
||||||
if (accessors != null) {
|
|
||||||
if (this.accessors == null) {
|
|
||||||
this.accessors = new HashMap<DeclarationDescriptor, DeclarationDescriptor>();
|
|
||||||
}
|
|
||||||
this.accessors.putAll(accessors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initOuterExpression(JetTypeMapper typeMapper, ClassDescriptor classDescriptor) {
|
|
||||||
final ClassDescriptor enclosingClass = getEnclosingClass();
|
|
||||||
outerExpression = enclosingClass != null
|
|
||||||
? StackValue
|
|
||||||
.field(typeMapper.mapType(enclosingClass.getDefaultType(), MapTypeMode.VALUE), typeMapper.getJvmClassName(
|
|
||||||
classDescriptor), "this$0",
|
|
||||||
false)
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,290 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
|
||||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author alex.tkachman
|
|
||||||
* @author Stepan Koltsov
|
|
||||||
*/
|
|
||||||
public class CodegenContexts {
|
|
||||||
private CodegenContexts() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class FakeDescriptorForStaticContext implements DeclarationDescriptor {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public DeclarationDescriptor getOriginal() {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeclarationDescriptor getContainingDeclaration() {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeclarationDescriptor substitute(TypeSubstitutor substitutor) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<AnnotationDescriptor> getAnnotations() {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Name getName() {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final CodegenContext STATIC =
|
|
||||||
new CodegenContext(null, new FakeDescriptorForStaticContext(), OwnerKind.NAMESPACE, null, null, null) {
|
|
||||||
@Override
|
|
||||||
public boolean isStatic() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ROOT";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private static final StackValue local1 = StackValue.local(1, JetTypeMapper.OBJECT_TYPE);
|
|
||||||
|
|
||||||
public abstract static class ReceiverContext extends CodegenContext {
|
|
||||||
final CallableDescriptor receiverDescriptor;
|
|
||||||
|
|
||||||
public ReceiverContext(
|
|
||||||
JetTypeMapper typeMapper,
|
|
||||||
CallableDescriptor contextDescriptor,
|
|
||||||
OwnerKind contextKind,
|
|
||||||
CodegenContext parentContext,
|
|
||||||
@Nullable ObjectOrClosureCodegen closureCodegen,
|
|
||||||
ClassDescriptor thisDescriptor
|
|
||||||
) {
|
|
||||||
super(typeMapper, contextDescriptor, contextKind, parentContext, closureCodegen, thisDescriptor);
|
|
||||||
receiverDescriptor = contextDescriptor.getReceiverParameter().exists() ? contextDescriptor : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CallableDescriptor getReceiverDescriptor() {
|
|
||||||
return receiverDescriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MethodContext extends ReceiverContext {
|
|
||||||
|
|
||||||
public MethodContext(
|
|
||||||
JetTypeMapper typeMapper,
|
|
||||||
@NotNull FunctionDescriptor contextType,
|
|
||||||
OwnerKind contextKind,
|
|
||||||
CodegenContext parentContext
|
|
||||||
) {
|
|
||||||
super(typeMapper, contextType instanceof PropertyAccessorDescriptor
|
|
||||||
? ((PropertyAccessorDescriptor) contextType).getCorrespondingProperty()
|
|
||||||
: contextType, contextKind, parentContext, null,
|
|
||||||
parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
return getParentContext().lookupInContext(d, v, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStatic() {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
return getParentContext().isStatic();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected StackValue getOuterExpression(StackValue prefix) {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
return getParentContext().getOuterExpression(prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Method: " + getContextDescriptor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ConstructorContext extends MethodContext {
|
|
||||||
public ConstructorContext(
|
|
||||||
JetTypeMapper typeMapper,
|
|
||||||
ConstructorDescriptor contextDescriptor,
|
|
||||||
OwnerKind kind,
|
|
||||||
CodegenContext parent
|
|
||||||
) {
|
|
||||||
super(typeMapper, contextDescriptor, kind, parent);
|
|
||||||
|
|
||||||
final ClassDescriptor type = getEnclosingClass();
|
|
||||||
outerExpression = type != null ? local1 : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected StackValue getOuterExpression(StackValue prefix) {
|
|
||||||
return outerExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Constructor: " + getContextDescriptor().getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ScriptContext extends CodegenContext {
|
|
||||||
@NotNull
|
|
||||||
private final ScriptDescriptor scriptDescriptor;
|
|
||||||
|
|
||||||
public ScriptContext(
|
|
||||||
JetTypeMapper typeMapper,
|
|
||||||
@NotNull ScriptDescriptor scriptDescriptor,
|
|
||||||
@NotNull ClassDescriptor contextDescriptor,
|
|
||||||
@NotNull OwnerKind contextKind,
|
|
||||||
@Nullable CodegenContext parentContext,
|
|
||||||
@Nullable ObjectOrClosureCodegen closureCodegen
|
|
||||||
) {
|
|
||||||
super(typeMapper, contextDescriptor, contextKind, parentContext, closureCodegen, contextDescriptor);
|
|
||||||
|
|
||||||
this.scriptDescriptor = scriptDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public ScriptDescriptor getScriptDescriptor() {
|
|
||||||
return scriptDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStatic() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ClassContext extends CodegenContext {
|
|
||||||
public ClassContext(
|
|
||||||
JetTypeMapper typeMapper,
|
|
||||||
ClassDescriptor contextDescriptor,
|
|
||||||
OwnerKind contextKind,
|
|
||||||
CodegenContext parentContext
|
|
||||||
) {
|
|
||||||
super(typeMapper, contextDescriptor, contextKind, parentContext, null, contextDescriptor);
|
|
||||||
initOuterExpression(typeMapper, contextDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStatic() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AnonymousClassContext extends CodegenContext {
|
|
||||||
public AnonymousClassContext(
|
|
||||||
JetTypeMapper typeMapper,
|
|
||||||
ClassDescriptor contextDescriptor,
|
|
||||||
OwnerKind contextKind,
|
|
||||||
CodegenContext parentContext,
|
|
||||||
@NotNull ObjectOrClosureCodegen closure
|
|
||||||
) {
|
|
||||||
super(typeMapper, contextDescriptor, contextKind, parentContext, closure, contextDescriptor);
|
|
||||||
initOuterExpression(typeMapper, contextDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStatic() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Anonymous: " + getThisDescriptor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ClosureContext extends ReceiverContext {
|
|
||||||
private final ClassDescriptor classDescriptor;
|
|
||||||
|
|
||||||
public ClosureContext(
|
|
||||||
JetTypeMapper typeMapper,
|
|
||||||
FunctionDescriptor contextDescriptor,
|
|
||||||
ClassDescriptor classDescriptor,
|
|
||||||
CodegenContext parentContext,
|
|
||||||
@NotNull ObjectOrClosureCodegen closureCodegen
|
|
||||||
) {
|
|
||||||
super(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen, classDescriptor);
|
|
||||||
this.classDescriptor = classDescriptor;
|
|
||||||
|
|
||||||
initOuterExpression(typeMapper, classDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public DeclarationDescriptor getContextDescriptor() {
|
|
||||||
return classDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStatic() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Closure: " + classDescriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class NamespaceContext extends CodegenContext {
|
|
||||||
public NamespaceContext(JetTypeMapper typeMapper, NamespaceDescriptor contextDescriptor, CodegenContext parent, OwnerKind kind) {
|
|
||||||
super(typeMapper, contextDescriptor, kind != null ? kind : OwnerKind.NAMESPACE, parent, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStatic() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Namespace: " + getContextDescriptor().getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,31 +16,39 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
|
import org.jetbrains.jet.codegen.context.CalculatedClosure;
|
||||||
|
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
|
||||||
|
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
|
||||||
|
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
|
|
||||||
import java.util.BitSet;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import static org.jetbrains.asm4.Opcodes.*;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class CodegenUtil {
|
public class CodegenUtil {
|
||||||
|
public static final String RECEIVER$0 = "receiver$0";
|
||||||
|
public static final String THIS$0 = "this$0";
|
||||||
|
|
||||||
private CodegenUtil() {
|
private CodegenUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +91,14 @@ public class CodegenUtil {
|
|||||||
!(myClass.getParent() instanceof JetClassObject);
|
!(myClass.getParent() instanceof JetClassObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isObjectLiteral(ClassDescriptor declaration, BindingContext bindingContext) {
|
||||||
|
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, declaration);
|
||||||
|
if (psiElement instanceof JetObjectDeclaration && ((JetObjectDeclaration) psiElement).isObjectLiteral()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isLocalFun(DeclarationDescriptor fd, BindingContext bindingContext) {
|
public static boolean isLocalFun(DeclarationDescriptor fd, BindingContext bindingContext) {
|
||||||
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, fd);
|
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, fd);
|
||||||
if (psiElement instanceof JetNamedFunction && psiElement.getParent() instanceof JetBlockExpression) {
|
if (psiElement instanceof JetNamedFunction && psiElement.getParent() instanceof JetBlockExpression) {
|
||||||
@@ -126,12 +142,12 @@ public class CodegenUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void generateThrow(MethodVisitor mv, String exception, String message) {
|
public static void generateThrow(MethodVisitor mv, String exception, String message) {
|
||||||
InstructionAdapter instructionAdapter = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
instructionAdapter.anew(Type.getObjectType(exception));
|
iv.anew(Type.getObjectType(exception));
|
||||||
instructionAdapter.dup();
|
iv.dup();
|
||||||
instructionAdapter.aconst(message);
|
iv.aconst(message);
|
||||||
instructionAdapter.invokespecial(exception, "<init>", "(Ljava/lang/String;)V");
|
iv.invokespecial(exception, "<init>", "(Ljava/lang/String;)V");
|
||||||
instructionAdapter.athrow();
|
iv.athrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateMethodThrow(MethodVisitor mv, String exception, String message) {
|
public static void generateMethodThrow(MethodVisitor mv, String exception, String message) {
|
||||||
@@ -140,4 +156,92 @@ public class CodegenUtil {
|
|||||||
mv.visitMaxs(-1, -1);
|
mv.visitMaxs(-1, -1);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JvmClassName getInternalClassName(FunctionDescriptor descriptor) {
|
||||||
|
final int paramCount = descriptor.getValueParameters().size();
|
||||||
|
if (descriptor.getReceiverParameter().exists()) {
|
||||||
|
return JvmClassName.byInternalName("jet/ExtensionFunction" + paramCount);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return JvmClassName.byInternalName("jet/Function" + paramCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JvmMethodSignature erasedInvokeSignature(FunctionDescriptor fd) {
|
||||||
|
|
||||||
|
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
||||||
|
|
||||||
|
signatureWriter.writeFormalTypeParametersStart();
|
||||||
|
signatureWriter.writeFormalTypeParametersEnd();
|
||||||
|
|
||||||
|
boolean isExtensionFunction = fd.getReceiverParameter().exists();
|
||||||
|
int paramCount = fd.getValueParameters().size();
|
||||||
|
if (isExtensionFunction) {
|
||||||
|
paramCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
signatureWriter.writeParametersStart();
|
||||||
|
|
||||||
|
for (int i = 0; i < paramCount; ++i) {
|
||||||
|
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
|
||||||
|
signatureWriter.writeAsmType(JetTypeMapper.OBJECT_TYPE, true);
|
||||||
|
signatureWriter.writeParameterTypeEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
signatureWriter.writeParametersEnd();
|
||||||
|
|
||||||
|
signatureWriter.writeReturnType();
|
||||||
|
signatureWriter.writeAsmType(JetTypeMapper.OBJECT_TYPE, true);
|
||||||
|
signatureWriter.writeReturnTypeEnd();
|
||||||
|
|
||||||
|
return signatureWriter.makeJvmMethodSignature("invoke");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isConst(CalculatedClosure closure) {
|
||||||
|
return closure.getCaptureThis() == null && closure.getCaptureReceiver() == null && closure.getCaptureVariables().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JetDelegatorToSuperCall findSuperCall(JetElement classOrObject, BindingContext bindingContext) {
|
||||||
|
if (!(classOrObject instanceof JetClassOrObject)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) {
|
||||||
|
if (specifier instanceof JetDelegatorToSuperCall) {
|
||||||
|
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||||
|
assert superType != null;
|
||||||
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
|
assert superClassDescriptor != null;
|
||||||
|
if (!isInterface(superClassDescriptor)) {
|
||||||
|
return (JetDelegatorToSuperCall) specifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void generateClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) {
|
||||||
|
final ClassifierDescriptor captureThis = closure.getCaptureThis();
|
||||||
|
final int access = ACC_PUBLIC | ACC_SYNTHETIC | ACC_FINAL;
|
||||||
|
if (captureThis != null) {
|
||||||
|
v.newField(null, access, THIS$0, typeMapper.mapType(captureThis.getDefaultType(), MapTypeMode.VALUE).getDescriptor(), null,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||||
|
if (captureReceiver != null) {
|
||||||
|
v.newField(null, access, RECEIVER$0, typeMapper.mapType(captureReceiver.getDefaultType(), MapTypeMode.VALUE).getDescriptor(),
|
||||||
|
null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Pair<String, Type>> fields = closure.getRecordedFields();
|
||||||
|
for (Pair<String, Type> field : fields) {
|
||||||
|
v.newField(null, access, field.first, field.second.getDescriptor(), null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ package org.jetbrains.jet.codegen;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
|
||||||
|
import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature;
|
||||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
|
|
||||||
@@ -32,23 +33,25 @@ import java.util.List;
|
|||||||
public class ConstructorFrameMap extends FrameMap {
|
public class ConstructorFrameMap extends FrameMap {
|
||||||
private int myOuterThisIndex = -1;
|
private int myOuterThisIndex = -1;
|
||||||
|
|
||||||
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, boolean hasThis0) {
|
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor) {
|
||||||
enterTemp(JetTypeMapper.OBJECT_TYPE); // this
|
enterTemp(JetTypeMapper.OBJECT_TYPE); // this
|
||||||
if (descriptor != null) {
|
|
||||||
if (hasThis0) {
|
final List<JvmMethodParameterSignature> parameterTypes = callableMethod.getSignature().getKotlinParameterTypes();
|
||||||
myOuterThisIndex = enterTemp(JetTypeMapper.OBJECT_TYPE); // outer class instance
|
if (parameterTypes != null) {
|
||||||
|
for (JvmMethodParameterSignature parameterType : parameterTypes) {
|
||||||
|
if (parameterType.getKind() == JvmMethodParameterKind.OUTER) {
|
||||||
|
myOuterThisIndex = enterTemp(JetTypeMapper.OBJECT_TYPE); // this0
|
||||||
|
}
|
||||||
|
else if (parameterType.getKind() != JvmMethodParameterKind.VALUE) {
|
||||||
|
enterTemp(parameterType.getAsmType());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Type> explicitArgTypes = callableMethod.getValueParameterTypes();
|
List<Type> explicitArgTypes = callableMethod.getValueParameterTypes();
|
||||||
|
|
||||||
if (descriptor != null &&
|
|
||||||
(descriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS ||
|
|
||||||
descriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_ENTRY)) {
|
|
||||||
enterTemp(JetTypeMapper.OBJECT_TYPE); // name
|
|
||||||
enterTemp(Type.INT_TYPE); // ordinal
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ValueParameterDescriptor> paramDescrs = descriptor != null
|
List<ValueParameterDescriptor> paramDescrs = descriptor != null
|
||||||
? descriptor.getValueParameters()
|
? descriptor.getValueParameters()
|
||||||
: Collections.<ValueParameterDescriptor>emptyList();
|
: Collections.<ValueParameterDescriptor>emptyList();
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.jetbrains.asm4.Opcodes;
|
|||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
import org.jetbrains.asm4.commons.Method;
|
import org.jetbrains.asm4.commons.Method;
|
||||||
|
import org.jetbrains.jet.codegen.context.*;
|
||||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
|
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -63,7 +64,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull;
|
|||||||
* @author yole
|
* @author yole
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup {
|
||||||
|
|
||||||
private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException";
|
private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException";
|
||||||
private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException";
|
private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException";
|
||||||
@@ -78,7 +79,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
private final Type returnType;
|
private final Type returnType;
|
||||||
|
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
private final CodegenContext context;
|
final CodegenContext context;
|
||||||
|
|
||||||
private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
|
private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
|
||||||
private final Collection<String> localVariableNames = new HashSet<String>();
|
private final Collection<String> localVariableNames = new HashSet<String>();
|
||||||
@@ -136,6 +137,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GenerationState getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, @Nullable ClassDescriptor required) {
|
StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, @Nullable ClassDescriptor required) {
|
||||||
if (required == null) {
|
if (required == null) {
|
||||||
return inner;
|
return inner;
|
||||||
@@ -218,14 +223,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private StackValue visitClassOrObject(JetClassOrObject declaration) {
|
private StackValue visitClassOrObject(JetClassOrObject declaration) {
|
||||||
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
||||||
ObjectOrClosureCodegen closure = new LocalClassClosureCodegen(this, context, state, descriptor);
|
assert descriptor != null;
|
||||||
|
|
||||||
Pair<JvmClassName, ClassBuilder> nameAndVisitor = state.forAnonymousSubclass(declaration);
|
Pair<JvmClassName, ClassBuilder> nameAndVisitor = state.forAnonymousSubclass(declaration);
|
||||||
|
|
||||||
closure.cv = nameAndVisitor.getSecond();
|
final CodegenContext objectContext = context.intoAnonymousClass(descriptor, this);
|
||||||
closure.name = nameAndVisitor.getFirst();
|
|
||||||
final CodegenContext objectContext = closure.context.intoAnonymousClass(
|
|
||||||
closure, descriptor, OwnerKind.IMPLEMENTATION,
|
|
||||||
typeMapper);
|
|
||||||
|
|
||||||
new ImplementationBodyCodegen(declaration, objectContext, nameAndVisitor.getSecond(), state).generate();
|
new ImplementationBodyCodegen(declaration, objectContext, nameAndVisitor.getSecond(), state).generate();
|
||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
@@ -394,13 +396,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
|
|
||||||
generateForInIterable(expression, loopRangeType);
|
generateForInIterable(expression);
|
||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
private void generateForInIterable(JetForExpression expression, Type loopRangeType) {
|
private void generateForInIterable(JetForExpression expression) {
|
||||||
generateForLoop(expression.getBody(), new IteratorForLoopGenerator(expression));
|
generateForLoop(expression.getBody(), new IteratorForLoopGenerator(expression));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,9 +412,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private interface ForLoopGenerator {
|
private interface ForLoopGenerator {
|
||||||
void beforeLoop();
|
void beforeLoop();
|
||||||
|
|
||||||
void conditionAndJump(@NotNull Label loopExit);
|
void conditionAndJump(@NotNull Label loopExit);
|
||||||
|
|
||||||
void beforeBody();
|
void beforeBody();
|
||||||
|
|
||||||
void afterBody();
|
void afterBody();
|
||||||
|
|
||||||
void afterLoop();
|
void afterLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,6 +463,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private JetType getElementType(JetForExpression forExpression) {
|
private JetType getElementType(JetForExpression forExpression) {
|
||||||
JetExpression loopRange = forExpression.getLoopRange();
|
JetExpression loopRange = forExpression.getLoopRange();
|
||||||
|
assert loopRange != null;
|
||||||
ResolvedCall<FunctionDescriptor> nextCall = getNotNull(bindingContext,
|
ResolvedCall<FunctionDescriptor> nextCall = getNotNull(bindingContext,
|
||||||
LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
|
LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
|
||||||
"No next() function " + DiagnosticUtils.atLocation(loopRange));
|
"No next() function " + DiagnosticUtils.atLocation(loopRange));
|
||||||
@@ -470,7 +477,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if (loopParameter != null) {
|
if (loopParameter != null) {
|
||||||
// E e = tmp<iterator>.next()
|
// E e = tmp<iterator>.next()
|
||||||
final VariableDescriptor parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter);
|
final VariableDescriptor parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter);
|
||||||
final Type asmTypeForParameter = asmType(parameterDescriptor.getType());
|
@SuppressWarnings("ConstantConditions") final Type asmTypeForParameter = asmType(parameterDescriptor.getType());
|
||||||
final int parameterIndex = myFrameMap.enter(parameterDescriptor, asmTypeForParameter);
|
final int parameterIndex = myFrameMap.enter(parameterDescriptor, asmTypeForParameter);
|
||||||
leaveVariableTasks.add(new Runnable() {
|
leaveVariableTasks.add(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -510,7 +517,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
for (JetMultiDeclarationEntry variableDeclaration : entries) {
|
for (JetMultiDeclarationEntry variableDeclaration : entries) {
|
||||||
final VariableDescriptor componentDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration);
|
final VariableDescriptor componentDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration);
|
||||||
|
|
||||||
final Type componentAsmType = asmType(componentDescriptor.getReturnType());
|
@SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType());
|
||||||
final int componentVarIndex = myFrameMap.enter(componentDescriptor, componentAsmType);
|
final int componentVarIndex = myFrameMap.enter(componentDescriptor, componentAsmType);
|
||||||
leaveVariableTasks.add(new Runnable() {
|
leaveVariableTasks.add(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -524,7 +531,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, variableDeclaration);
|
ResolvedCall<FunctionDescriptor> resolvedCall =
|
||||||
|
bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, variableDeclaration);
|
||||||
assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText();
|
assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText();
|
||||||
Call call = makeFakeCall(new TransientReceiver(elementType));
|
Call call = makeFakeCall(new TransientReceiver(elementType));
|
||||||
invokeFunction(call, StackValue.local(tmpParameterIndex, asmElementType), resolvedCall);
|
invokeFunction(call, StackValue.local(tmpParameterIndex, asmElementType), resolvedCall);
|
||||||
@@ -554,9 +562,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
super(forExpression);
|
super(forExpression);
|
||||||
|
|
||||||
JetExpression loopRange = forExpression.getLoopRange();
|
JetExpression loopRange = forExpression.getLoopRange();
|
||||||
|
assert loopRange != null;
|
||||||
this.iteratorCall = getNotNull(bindingContext,
|
this.iteratorCall = getNotNull(bindingContext,
|
||||||
LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
|
LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
|
||||||
"No .iterator() function " + DiagnosticUtils.atLocation(loopRange));
|
"No .iterator() function " + DiagnosticUtils.atLocation(loopRange));
|
||||||
|
|
||||||
JetType iteratorType = iteratorCall.getResultingDescriptor().getReturnType();
|
JetType iteratorType = iteratorCall.getResultingDescriptor().getReturnType();
|
||||||
assert iteratorType != null;
|
assert iteratorType != null;
|
||||||
@@ -583,10 +592,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
// tmp<iterator>.hasNext()
|
// tmp<iterator>.hasNext()
|
||||||
|
|
||||||
JetExpression loopRange = forExpression.getLoopRange();
|
JetExpression loopRange = forExpression.getLoopRange();
|
||||||
ResolvedCall<FunctionDescriptor> hasNextCall = getNotNull(bindingContext,
|
@SuppressWarnings("ConstantConditions") ResolvedCall<FunctionDescriptor> hasNextCall = getNotNull(bindingContext,
|
||||||
LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, loopRange,
|
LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, loopRange,
|
||||||
"No hasNext() function " + DiagnosticUtils.atLocation(loopRange));
|
"No hasNext() function " + DiagnosticUtils.atLocation(loopRange));
|
||||||
Call fakeCall = makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
|
@SuppressWarnings("ConstantConditions") Call fakeCall = makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
|
||||||
invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), hasNextCall);
|
invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), hasNextCall);
|
||||||
|
|
||||||
JetType type = hasNextCall.getResultingDescriptor().getReturnType();
|
JetType type = hasNextCall.getResultingDescriptor().getReturnType();
|
||||||
@@ -599,9 +608,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assignToLoopParameter(int parameterIndex) {
|
protected void assignToLoopParameter(int parameterIndex) {
|
||||||
Call fakeCall =
|
@SuppressWarnings("ConstantConditions") Call fakeCall =
|
||||||
makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
|
makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
|
||||||
invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), nextCall);
|
invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), nextCall);
|
||||||
|
//noinspection ConstantConditions
|
||||||
v.store(parameterIndex, asmType(nextCall.getResultingDescriptor().getReturnType()));
|
v.store(parameterIndex, asmType(nextCall.getResultingDescriptor().getReturnType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,7 +773,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generatePrologue() {
|
protected void generatePrologue() {
|
||||||
myIndexVar = lookupLocal(parameterDescriptor);
|
myIndexVar = lookupLocalIndex(parameterDescriptor);
|
||||||
myCountVar = myFrameMap.enterTemp(Type.INT_TYPE);
|
myCountVar = myFrameMap.enterTemp(Type.INT_TYPE);
|
||||||
myDeltaVar = myFrameMap.enterTemp(Type.INT_TYPE);
|
myDeltaVar = myFrameMap.enterTemp(Type.INT_TYPE);
|
||||||
if (isIntRangeExpr(expression.getLoopRange())) {
|
if (isIntRangeExpr(expression.getLoopRange())) {
|
||||||
@@ -977,7 +987,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
StackValue closure = genClosure(function);
|
StackValue closure = genClosure(function);
|
||||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
|
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
|
||||||
int index = myFrameMap.getIndex(descriptor);
|
int index = lookupLocalIndex(descriptor);
|
||||||
closure.put(OBJECT_TYPE, v);
|
closure.put(OBJECT_TYPE, v);
|
||||||
v.store(index, OBJECT_TYPE);
|
v.store(index, OBJECT_TYPE);
|
||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
@@ -996,89 +1006,90 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackValue genClosure(JetExpression expression) {
|
private StackValue genClosure(JetExpression expression) {
|
||||||
ClosureCodegen closureCodegen = new ClosureCodegen(state, this, context);
|
final FunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, expression);
|
||||||
final GeneratedAnonymousClassDescriptor closure = closureCodegen.gen(expression);
|
final ClosureAnnotator closureAnnotator = state.getInjector().getClosureAnnotator();
|
||||||
|
final ClassDescriptor classDescriptor = closureAnnotator.classDescriptorForFunctionDescriptor(descriptor);
|
||||||
|
final CalculatedClosure closure = closureAnnotator.getCalculatedClosure(classDescriptor);
|
||||||
|
|
||||||
if (closureCodegen.isConst()) {
|
ClosureCodegen closureCodegen = new ClosureCodegen(state, (MutableClosure) closure).gen(expression, context, this);
|
||||||
v.invokestatic(closure.getClassname().getInternalName(), "$getInstance", "()" + closure.getClassname().getDescriptor());
|
|
||||||
|
final JvmClassName className = closureCodegen.name;
|
||||||
|
final Type asmType = className.getAsmType();
|
||||||
|
final String internalName = className.getInternalName();
|
||||||
|
if (CodegenUtil.isConst(closure)) {
|
||||||
|
v.invokestatic(internalName, "$getInstance", "()" + className.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.anew(closure.getClassname().getAsmType());
|
v.anew(asmType);
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|
||||||
final Method cons = closure.getConstructor();
|
final Method cons = closureCodegen.constructor;
|
||||||
|
pushClosureOnStack(closure, false);
|
||||||
int k = 0;
|
v.invokespecial(internalName, "<init>", cons.getDescriptor());
|
||||||
if (closure.isCaptureThis()) {
|
|
||||||
k++;
|
|
||||||
v.load(0, OBJECT_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closure.isCaptureReceiver()) {
|
|
||||||
k++;
|
|
||||||
v.load(context.getContextDescriptor().getContainingDeclaration() instanceof NamespaceDescriptor ? 0 : 1,
|
|
||||||
typeMapper.mapType(closure.getCaptureReceiver().getDefaultType(), MapTypeMode.IMPL));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < closure.getArgs().size(); i++) {
|
|
||||||
StackValue arg = closure.getArgs().get(i);
|
|
||||||
arg.put(cons.getArgumentTypes()[i + k], v);
|
|
||||||
}
|
|
||||||
|
|
||||||
v.invokespecial(closure.getClassname().getInternalName(), "<init>", cons.getDescriptor());
|
|
||||||
}
|
}
|
||||||
return StackValue.onStack(closure.getClassname().getAsmType());
|
return StackValue.onStack(asmType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) {
|
public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) {
|
||||||
ObjectOrClosureCodegen closureCodegen = new ObjectOrClosureCodegen(this, context, state);
|
CalculatedClosure closure = state.generateObjectLiteral(expression, this);
|
||||||
GeneratedAnonymousClassDescriptor closure = state.generateObjectLiteral(expression, closureCodegen);
|
|
||||||
Type type = closure.getClassname().getAsmType();
|
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, expression.getObjectDeclaration());
|
||||||
|
assert constructorDescriptor != null;
|
||||||
|
CallableMethod constructor = typeMapper.mapToCallableMethod(constructorDescriptor, closure);
|
||||||
|
|
||||||
|
final JvmClassName name = closure.getClassName();
|
||||||
|
Type type = name.getAsmType();
|
||||||
v.anew(type);
|
v.anew(type);
|
||||||
v.dup();
|
v.dup();
|
||||||
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(closure.getConstructor().getArgumentTypes()));
|
final Method cons = constructor.getSignature().getAsmMethod();
|
||||||
|
|
||||||
if (consArgTypes.size() > 0) {
|
pushClosureOnStack(closure, false);
|
||||||
v.load(0, OBJECT_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closureCodegen.captureReceiver != null) {
|
final JetDelegatorToSuperCall superCall = closure.getSuperCall();
|
||||||
final Type asmType = typeMapper.mapType(closureCodegen.captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
if (superCall != null) {
|
||||||
v.load(context.isStatic() ? 0 : 1, asmType);
|
|
||||||
consArgTypes.add(asmType);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closureCodegen.closure.entrySet()) {
|
|
||||||
if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) {
|
|
||||||
Type sharedVarType = typeMapper.getSharedVarType(entry.getKey());
|
|
||||||
if (sharedVarType == null) {
|
|
||||||
sharedVarType = state.getInjector().getJetTypeMapper()
|
|
||||||
.mapType(((VariableDescriptor) entry.getKey()).getType(), MapTypeMode.VALUE);
|
|
||||||
}
|
|
||||||
consArgTypes.add(sharedVarType);
|
|
||||||
entry.getValue().getOuterValue().put(sharedVarType, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closureCodegen.superCall != null) {
|
|
||||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
|
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
|
||||||
closureCodegen.superCall
|
superCall
|
||||||
.getCalleeExpression()
|
.getCalleeExpression()
|
||||||
.getConstructorReferenceExpression());
|
.getConstructorReferenceExpression());
|
||||||
assert superConstructor != null;
|
assert superConstructor != null;
|
||||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor,
|
CallableMethod superCallable = typeMapper
|
||||||
typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
|
.mapToCallableMethod(superConstructor, typeMapper.getCalculatedClosure(superConstructor.getContainingDeclaration()));
|
||||||
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
|
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
|
||||||
Collections.addAll(consArgTypes, argumentTypes);
|
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, superCall.getCalleeExpression());
|
||||||
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, closureCodegen.superCall.getCalleeExpression());
|
|
||||||
assert resolvedCall != null;
|
assert resolvedCall != null;
|
||||||
pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes));
|
pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
Method cons = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
|
v.invokespecial(name.getInternalName(), "<init>", cons.getDescriptor());
|
||||||
v.invokespecial(closure.getClassname().getInternalName(), "<init>", cons.getDescriptor());
|
return StackValue.onStack(type);
|
||||||
return StackValue.onStack(closure.getClassname().getAsmType());
|
}
|
||||||
|
|
||||||
|
protected void pushClosureOnStack(CalculatedClosure closure, boolean ignoreThisAndReceiver) {
|
||||||
|
if (closure != null) {
|
||||||
|
if (!ignoreThisAndReceiver) {
|
||||||
|
final ClassDescriptor captureThis = closure.getCaptureThis();
|
||||||
|
if (captureThis != null) {
|
||||||
|
generateThisOrOuter(captureThis).put(OBJECT_TYPE, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||||
|
if (captureReceiver != null) {
|
||||||
|
final Type asmType = typeMapper.mapType(captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
||||||
|
v.load(context.isStatic() ? 0 : 1, asmType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
|
||||||
|
//if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) {
|
||||||
|
Type sharedVarType = typeMapper.getSharedVarType(entry.getKey());
|
||||||
|
if (sharedVarType == null) {
|
||||||
|
sharedVarType = typeMapper.mapType(((VariableDescriptor) entry.getKey()).getType(), MapTypeMode.VALUE);
|
||||||
|
}
|
||||||
|
entry.getValue().getOuterValue(this).put(sharedVarType, v);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private StackValue generateBlock(List<JetElement> statements) {
|
private StackValue generateBlock(List<JetElement> statements) {
|
||||||
@@ -1301,7 +1312,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = lookupLocal(descriptor);
|
int index = lookupLocalIndex(descriptor);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
return stackValueForLocal(descriptor, index);
|
return stackValueForLocal(descriptor, index);
|
||||||
}
|
}
|
||||||
@@ -1379,7 +1390,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return StackValue.onStack(OBJECT_TYPE);
|
return StackValue.onStack(OBJECT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
StackValue value = context.lookupInContext(descriptor, v, StackValue.local(0, OBJECT_TYPE));
|
StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
|
||||||
if (value instanceof StackValue.Composed) {
|
if (value instanceof StackValue.Composed) {
|
||||||
@@ -1445,39 +1456,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int lookupLocal(DeclarationDescriptor descriptor) {
|
@Override
|
||||||
return myFrameMap.getIndex(descriptor);
|
public boolean lookupLocal(DeclarationDescriptor descriptor) {
|
||||||
|
return lookupLocalIndex(descriptor) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type expectedType, InstructionAdapter v) {
|
public int lookupLocalIndex(DeclarationDescriptor descriptor) {
|
||||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getOriginal().getContainingDeclaration();
|
return myFrameMap.getIndex(descriptor);
|
||||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor;
|
|
||||||
functionDescriptor = functionDescriptor.getOriginal();
|
|
||||||
JvmClassName owner;
|
|
||||||
|
|
||||||
IntrinsicMethod intrinsic = state.getInjector().getIntrinsics().getIntrinsic(functionDescriptor);
|
|
||||||
if (intrinsic != null) {
|
|
||||||
intrinsic.generate(this, v, expectedType, null, null, StackValue.onStack(OBJECT_TYPE), state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isInterface;
|
|
||||||
boolean isInsideClass = containingDeclaration == context.getThisDescriptor();
|
|
||||||
if (isInsideClass || isStatic) {
|
|
||||||
owner = typeMapper.getOwner(functionDescriptor, contextKind());
|
|
||||||
isInterface = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
owner = typeMapper.getOwner(functionDescriptor, OwnerKind.IMPLEMENTATION);
|
|
||||||
isInterface = CodegenUtil.isInterface(containingDeclaration);
|
|
||||||
}
|
|
||||||
|
|
||||||
int opcode = isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL;
|
|
||||||
v.visitMethodInsn(opcode, owner.getInternalName(), functionDescriptor.getName().getName(),
|
|
||||||
typeMapper.mapSignature(functionDescriptor.getName(), functionDescriptor).getAsmMethod().getDescriptor());
|
|
||||||
JetType returnType = functionDescriptor.getReturnType();
|
|
||||||
assert returnType != null;
|
|
||||||
StackValue.onStack(asmType(returnType)).coerce(expectedType, v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue.Property intermediateValueForProperty(
|
public StackValue.Property intermediateValueForProperty(
|
||||||
@@ -1499,7 +1484,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
boolean isInsideClass = !isFakeOverride &&
|
boolean isInsideClass = !isFakeOverride &&
|
||||||
(((containingDeclaration == null && !context.hasThisDescriptor() ||
|
(((containingDeclaration == null && !context.hasThisDescriptor() ||
|
||||||
context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) ||
|
context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) ||
|
||||||
(context.getParentContext() instanceof CodegenContexts.NamespaceContext) &&
|
(context.getParentContext() instanceof CodegenContext.NamespaceContext) &&
|
||||||
context.getParentContext().getContextDescriptor() == containingDeclaration)
|
context.getParentContext().getContextDescriptor() == containingDeclaration)
|
||||||
&& contextKind() != OwnerKind.TRAIT_IMPL);
|
&& contextKind() != OwnerKind.TRAIT_IMPL);
|
||||||
Method getter = null;
|
Method getter = null;
|
||||||
@@ -1681,7 +1666,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if (enclosed != context.getThisDescriptor()) {
|
if (enclosed != context.getThisDescriptor()) {
|
||||||
CodegenContext c = context;
|
CodegenContext c = context;
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
while (!(c instanceof CodegenContexts.ClassContext) ||
|
while (!(c instanceof CodegenContext.ClassContext) ||
|
||||||
!DescriptorUtils.isSubclass(c.getThisDescriptor(), enclosed)) {
|
!DescriptorUtils.isSubclass(c.getThisDescriptor(), enclosed)) {
|
||||||
c = c.getParentContext();
|
c = c.getParentContext();
|
||||||
assert c != null;
|
assert c != null;
|
||||||
@@ -1761,7 +1746,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
//}
|
//}
|
||||||
if (isCallAsFunctionObject(fd)) {
|
if (isCallAsFunctionObject(fd)) {
|
||||||
SimpleFunctionDescriptor invoke = CodegenUtil.createInvoke(fd);
|
SimpleFunctionDescriptor invoke = CodegenUtil.createInvoke(fd);
|
||||||
callableMethod = ClosureCodegen.asCallableMethod(invoke, typeMapper);
|
callableMethod = typeMapper.asCallableMethod(invoke);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
callableMethod = typeMapper.mapToCallableMethod(fd, superCall, OwnerKind.IMPLEMENTATION);
|
callableMethod = typeMapper.mapToCallableMethod(fd, superCall, OwnerKind.IMPLEMENTATION);
|
||||||
@@ -1895,14 +1880,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackValue generateReceiver(DeclarationDescriptor provided) {
|
private StackValue generateReceiver(DeclarationDescriptor provided) {
|
||||||
assert context instanceof CodegenContexts.ReceiverContext;
|
if (context.getReceiverDescriptor() == provided) {
|
||||||
CodegenContexts.ReceiverContext cur = (CodegenContexts.ReceiverContext) context;
|
StackValue result = context.getReceiverExpression(typeMapper);
|
||||||
if (cur.getReceiverDescriptor() == provided) {
|
|
||||||
StackValue result = cur.getReceiverExpression(typeMapper);
|
|
||||||
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
|
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
StackValue result = context.lookupInContext(provided, v, StackValue.local(0, OBJECT_TYPE));
|
StackValue result = context.lookupInContext(provided, StackValue.local(0, OBJECT_TYPE), state, false);
|
||||||
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
|
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1910,12 +1893,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
CodegenContext cur = context;
|
CodegenContext cur = context;
|
||||||
StackValue result = StackValue.local(0, OBJECT_TYPE);
|
StackValue result = StackValue.local(0, OBJECT_TYPE);
|
||||||
while (cur != null) {
|
while (cur != null) {
|
||||||
if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) {
|
if (cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext)) {
|
||||||
cur = cur.getParentContext();
|
cur = cur.getParentContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur instanceof CodegenContexts.ScriptContext) {
|
if (cur instanceof CodegenContext.ScriptContext) {
|
||||||
CodegenContexts.ScriptContext scriptContext = (CodegenContexts.ScriptContext) cur;
|
CodegenContext.ScriptContext scriptContext = (CodegenContext.ScriptContext) cur;
|
||||||
|
|
||||||
JvmClassName currentScriptClassName =
|
JvmClassName currentScriptClassName =
|
||||||
state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(scriptContext.getScriptDescriptor());
|
state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(scriptContext.getScriptDescriptor());
|
||||||
@@ -1933,9 +1916,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert cur != null;
|
assert cur != null;
|
||||||
result = cur.getOuterExpression(result);
|
result = cur.getOuterExpression(result, false);
|
||||||
|
|
||||||
if (cur instanceof CodegenContexts.ConstructorContext) {
|
if (cur instanceof CodegenContext.ConstructorContext) {
|
||||||
cur = cur.getParentContext();
|
cur = cur.getParentContext();
|
||||||
}
|
}
|
||||||
assert cur != null;
|
assert cur != null;
|
||||||
@@ -1953,7 +1936,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
Type type = asmType(calleeContainingClass.getDefaultType());
|
Type type = asmType(calleeContainingClass.getDefaultType());
|
||||||
StackValue result = StackValue.local(0, type);
|
StackValue result = StackValue.local(0, type);
|
||||||
while (cur != null) {
|
while (cur != null) {
|
||||||
if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) {
|
if (cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext)) {
|
||||||
cur = cur.getParentContext();
|
cur = cur.getParentContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1969,9 +1952,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = cur.getOuterExpression(result);
|
result = cur.getOuterExpression(result, false);
|
||||||
|
|
||||||
if (cur instanceof CodegenContexts.ConstructorContext) {
|
if (cur instanceof CodegenContext.ConstructorContext) {
|
||||||
cur = cur.getParentContext();
|
cur = cur.getParentContext();
|
||||||
}
|
}
|
||||||
assert cur != null;
|
assert cur != null;
|
||||||
@@ -2125,7 +2108,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if (typeMapper.isVarCapturedInClosure(declarationDescriptor)) {
|
if (typeMapper.isVarCapturedInClosure(declarationDescriptor)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return lookupLocal(declarationDescriptor);
|
return lookupLocalIndex(declarationDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2220,7 +2203,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackValue generateIn(JetBinaryExpression expression) {
|
private StackValue generateIn(JetBinaryExpression expression) {
|
||||||
JetExpression expr = expression.getLeft();
|
|
||||||
boolean inverted = expression.getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IN;
|
boolean inverted = expression.getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IN;
|
||||||
if (isIntRangeExpr(expression.getRight())) {
|
if (isIntRangeExpr(expression.getRight())) {
|
||||||
StackValue leftValue = StackValue.expression(Type.INT_TYPE, expression.getLeft(), this);
|
StackValue leftValue = StackValue.expression(Type.INT_TYPE, expression.getLeft(), this);
|
||||||
@@ -2651,9 +2633,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) {
|
private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) {
|
||||||
int functionLocalIndex = myFrameMap.getIndex(op);
|
int functionLocalIndex = lookupLocalIndex(op);
|
||||||
if (functionLocalIndex >= 0) {
|
if (functionLocalIndex >= 0) {
|
||||||
stackValueForLocal(op, functionLocalIndex).put(ClosureCodegen.getInternalClassName(op).getAsmType(), v);
|
stackValueForLocal(op, functionLocalIndex).put(CodegenUtil.getInternalClassName(op).getAsmType(), v);
|
||||||
}
|
}
|
||||||
ResolvedCall<? extends CallableDescriptor> resolvedCall =
|
ResolvedCall<? extends CallableDescriptor> resolvedCall =
|
||||||
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
|
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
|
||||||
@@ -2840,7 +2822,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) {
|
if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int index = lookupLocal(variableDescriptor);
|
int index = lookupLocalIndex(variableDescriptor);
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
throw new IllegalStateException("Local variable not found for " + variableDescriptor);
|
throw new IllegalStateException("Local variable not found for " + variableDescriptor);
|
||||||
@@ -2894,15 +2876,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
v.anew(type);
|
v.anew(type);
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|
||||||
// TODO typechecker must verify that we're the outer class of the instance being created
|
final ClassDescriptor classDescriptor = ((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration();
|
||||||
//noinspection ConstantConditions
|
|
||||||
if (!receiver.type.equals(Type.VOID_TYPE)) {
|
|
||||||
receiver.put(receiver.type, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
CallableMethod method = typeMapper
|
CallableMethod method = typeMapper
|
||||||
.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, typeMapper
|
.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, typeMapper
|
||||||
.hasThis0(((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration()));
|
.getCalculatedClosure(classDescriptor));
|
||||||
|
|
||||||
|
receiver.put(receiver.type, v);
|
||||||
|
pushClosureOnStack(typeMapper.getCalculatedClosure(classDescriptor), true);
|
||||||
invokeMethodWithArguments(method, expression, StackValue.none());
|
invokeMethodWithArguments(method, expression, StackValue.none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3089,10 +3069,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor);
|
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof CallableDescriptor) {
|
||||||
return generateReceiver(descriptor);
|
return generateReceiver(descriptor);
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("neither this nor receiver");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3143,7 +3123,7 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
assert descriptor != null;
|
assert descriptor != null;
|
||||||
Type descriptorType = asmType(descriptor.getType());
|
Type descriptorType = asmType(descriptor.getType());
|
||||||
myFrameMap.enter(descriptor, descriptorType);
|
myFrameMap.enter(descriptor, descriptorType);
|
||||||
int index = lookupLocal(descriptor);
|
int index = lookupLocalIndex(descriptor);
|
||||||
v.store(index, descriptorType);
|
v.store(index, descriptorType);
|
||||||
|
|
||||||
gen(clause.getCatchBody(), expectedAsmType);
|
gen(clause.getCatchBody(), expectedAsmType);
|
||||||
@@ -3308,7 +3288,7 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
myFrameMap.enter(variableDescriptor, varType);
|
myFrameMap.enter(variableDescriptor, varType);
|
||||||
expressionToMatch.dupReceiver(v);
|
expressionToMatch.dupReceiver(v);
|
||||||
expressionToMatch.put(varType, v);
|
expressionToMatch.put(varType, v);
|
||||||
final int varIndex = myFrameMap.getIndex(variableDescriptor);
|
final int varIndex = lookupLocalIndex(variableDescriptor);
|
||||||
v.store(varIndex, varType);
|
v.store(varIndex, varType);
|
||||||
return generateWhenCondition(varType, varIndex, false, ((JetBindingPattern) pattern).getCondition(), null);
|
return generateWhenCondition(varType, varIndex, false, ((JetBindingPattern) pattern).getCondition(), null);
|
||||||
}
|
}
|
||||||
@@ -3573,5 +3553,4 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return context.getContextDescriptor().toString();
|
return context.getContextDescriptor().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.jetbrains.asm4.MethodVisitor;
|
|||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
import org.jetbrains.asm4.commons.Method;
|
import org.jetbrains.asm4.commons.Method;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||||
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
||||||
import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter;
|
import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter;
|
||||||
@@ -74,7 +75,7 @@ public class FunctionCodegen {
|
|||||||
@Nullable String propertyTypeSignature, FunctionDescriptor functionDescriptor
|
@Nullable String propertyTypeSignature, FunctionDescriptor functionDescriptor
|
||||||
) {
|
) {
|
||||||
|
|
||||||
CodegenContexts.MethodContext funContext = owner.intoFunction(functionDescriptor, state.getInjector().getJetTypeMapper());
|
CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor);
|
||||||
|
|
||||||
final JetExpression bodyExpression = f.getBodyExpression();
|
final JetExpression bodyExpression = f.getBodyExpression();
|
||||||
generatedMethod(bodyExpression, jvmMethod, needJetAnnotations, propertyTypeSignature, funContext, functionDescriptor, f);
|
generatedMethod(bodyExpression, jvmMethod, needJetAnnotations, propertyTypeSignature, funContext, functionDescriptor, f);
|
||||||
@@ -84,7 +85,7 @@ public class FunctionCodegen {
|
|||||||
JetExpression bodyExpressions,
|
JetExpression bodyExpressions,
|
||||||
JvmMethodSignature jvmSignature,
|
JvmMethodSignature jvmSignature,
|
||||||
boolean needJetAnnotations, @Nullable String propertyTypeSignature,
|
boolean needJetAnnotations, @Nullable String propertyTypeSignature,
|
||||||
CodegenContexts.MethodContext context,
|
CodegenContext.MethodContext context,
|
||||||
FunctionDescriptor functionDescriptor,
|
FunctionDescriptor functionDescriptor,
|
||||||
JetDeclarationWithBody fun
|
JetDeclarationWithBody fun
|
||||||
) {
|
) {
|
||||||
@@ -334,7 +335,6 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
endVisit(mv, null, fun);
|
endVisit(mv, null, fun);
|
||||||
mv.visitEnd();
|
|
||||||
|
|
||||||
generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
|
generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
|
||||||
}
|
}
|
||||||
@@ -417,7 +417,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void generateDefaultIfNeeded(
|
static void generateDefaultIfNeeded(
|
||||||
CodegenContexts.MethodContext owner,
|
CodegenContext.MethodContext owner,
|
||||||
GenerationState state,
|
GenerationState state,
|
||||||
ClassBuilder v,
|
ClassBuilder v,
|
||||||
Method jvmSignature,
|
Method jvmSignature,
|
||||||
@@ -477,7 +477,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void generateDefaultImpl(
|
private static void generateDefaultImpl(
|
||||||
CodegenContexts.MethodContext owner,
|
CodegenContext.MethodContext owner,
|
||||||
GenerationState state,
|
GenerationState state,
|
||||||
Method jvmSignature,
|
Method jvmSignature,
|
||||||
FunctionDescriptor functionDescriptor,
|
FunctionDescriptor functionDescriptor,
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @author max
|
|
||||||
*/
|
|
||||||
package org.jetbrains.jet.codegen;
|
|
||||||
|
|
||||||
import org.jetbrains.asm4.commons.Method;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class GeneratedAnonymousClassDescriptor {
|
|
||||||
private final JvmClassName classname;
|
|
||||||
private final Method constructor;
|
|
||||||
|
|
||||||
private final ClassDescriptor captureThis;
|
|
||||||
private final ClassifierDescriptor captureReceiver;
|
|
||||||
private final List<StackValue> args = new ArrayList<StackValue>();
|
|
||||||
|
|
||||||
public GeneratedAnonymousClassDescriptor(
|
|
||||||
JvmClassName classname,
|
|
||||||
Method constructor,
|
|
||||||
ClassDescriptor captureThis,
|
|
||||||
ClassifierDescriptor captureReceiver
|
|
||||||
) {
|
|
||||||
this.classname = classname;
|
|
||||||
this.constructor = constructor;
|
|
||||||
this.captureThis = captureThis;
|
|
||||||
this.captureReceiver = captureReceiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JvmClassName getClassname() {
|
|
||||||
return classname;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Method getConstructor() {
|
|
||||||
return constructor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addArg(StackValue local) {
|
|
||||||
args.add(local);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<StackValue> getArgs() {
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCaptureThis() {
|
|
||||||
return captureThis != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCaptureReceiver() {
|
|
||||||
return captureReceiver != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassDescriptor getCaptureThis() {
|
|
||||||
return captureThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassifierDescriptor getCaptureReceiver() {
|
|
||||||
return captureReceiver;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,9 +25,10 @@ import com.intellij.util.containers.MultiMap;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.asm4.commons.Method;
|
import org.jetbrains.asm4.commons.Method;
|
||||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||||
|
import org.jetbrains.jet.codegen.context.CalculatedClosure;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.di.InjectorForJvmCodegen;
|
import org.jetbrains.jet.di.InjectorForJvmCodegen;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -56,7 +57,6 @@ public class GenerationState {
|
|||||||
// out parameter
|
// out parameter
|
||||||
private Method scriptConstructorMethod;
|
private Method scriptConstructorMethod;
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
private final JetTypeMapper typeMapper;
|
|
||||||
|
|
||||||
|
|
||||||
public GenerationState(Project project, ClassBuilderFactory builderFactory, AnalyzeExhaust analyzeExhaust, List<JetFile> files) {
|
public GenerationState(Project project, ClassBuilderFactory builderFactory, AnalyzeExhaust analyzeExhaust, List<JetFile> files) {
|
||||||
@@ -75,7 +75,6 @@ public class GenerationState {
|
|||||||
this.injector = new InjectorForJvmCodegen(
|
this.injector = new InjectorForJvmCodegen(
|
||||||
bindingContext,
|
bindingContext,
|
||||||
this.files, builtinToJavaTypesMapping, builderFactory.getClassBuilderMode(), this, builderFactory, project);
|
this.files, builtinToJavaTypesMapping, builderFactory.getClassBuilderMode(), this, builderFactory, project);
|
||||||
typeMapper = injector.getJetTypeMapper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markUsed() {
|
private void markUsed() {
|
||||||
@@ -195,25 +194,20 @@ public class GenerationState {
|
|||||||
codegen.generate(errorHandler, progress);
|
codegen.generate(errorHandler, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) {
|
public CalculatedClosure generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen expressionCodegen) {
|
||||||
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
||||||
Pair<JvmClassName, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
|
Pair<JvmClassName, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
|
||||||
|
|
||||||
closure.cv = nameAndVisitor.getSecond();
|
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, objectDeclaration);
|
||||||
closure.name = nameAndVisitor.getFirst();
|
assert classDescriptor != null;
|
||||||
final CodegenContext objectContext = closure.context.intoAnonymousClass(
|
|
||||||
closure, bindingContext.get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION,
|
final CalculatedClosure closure = getInjector().getClosureAnnotator().getCalculatedClosure(classDescriptor);
|
||||||
typeMapper);
|
|
||||||
|
final CodegenContext objectContext = expressionCodegen.context.intoAnonymousClass(classDescriptor, expressionCodegen);
|
||||||
|
|
||||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
||||||
|
|
||||||
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
return closure;
|
||||||
assert constructorDescriptor != null;
|
|
||||||
CallableMethod callableMethod = typeMapper.mapToCallableMethod(
|
|
||||||
constructorDescriptor,
|
|
||||||
typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
|
||||||
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature().getAsmMethod(),
|
|
||||||
objectContext.outerWasUsed, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createText() {
|
public String createText() {
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ import org.jetbrains.asm4.MethodVisitor;
|
|||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
import org.jetbrains.asm4.commons.Method;
|
import org.jetbrains.asm4.commons.Method;
|
||||||
|
import org.jetbrains.jet.codegen.context.CalculatedClosure;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
|
import org.jetbrains.jet.codegen.context.MutableClosure;
|
||||||
import org.jetbrains.jet.codegen.signature.*;
|
import org.jetbrains.jet.codegen.signature.*;
|
||||||
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
||||||
import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter;
|
import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter;
|
||||||
@@ -34,6 +37,7 @@ import org.jetbrains.jet.lang.psi.*;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JdkNames;
|
import org.jetbrains.jet.lang.resolve.java.JdkNames;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
@@ -294,9 +298,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||||
assert superType != null;
|
assert superType != null;
|
||||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
|
assert superClassDescriptor != null;
|
||||||
if (!CodegenUtil.isInterface(superClassDescriptor)) {
|
if (!CodegenUtil.isInterface(superClassDescriptor)) {
|
||||||
superClassType = superType;
|
superClassType = superType;
|
||||||
assert superClassDescriptor != null;
|
|
||||||
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName();
|
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName();
|
||||||
superCall = specifier;
|
superCall = specifier;
|
||||||
}
|
}
|
||||||
@@ -338,6 +342,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
generateAccessors();
|
generateAccessors();
|
||||||
|
|
||||||
generateEnumMethods();
|
generateEnumMethods();
|
||||||
|
|
||||||
|
CodegenUtil.generateClosureFields(context.closure, v, state.getInjector().getJetTypeMapper());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateEnumMethods() {
|
private void generateEnumMethods() {
|
||||||
@@ -373,10 +379,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateAccessors() {
|
private void generateAccessors() {
|
||||||
if (context.accessors != null) {
|
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.getAccessors().entrySet()) {
|
||||||
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.accessors.entrySet()) {
|
genAccessor(entry);
|
||||||
genAccessor(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,73 +555,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
|
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
|
||||||
|
|
||||||
CodegenContexts.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
|
final CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
||||||
|
|
||||||
JvmMethodSignature constructorMethod;
|
lookupConstructorExpressionsInClosureIfPresent(constructorContext);
|
||||||
CallableMethod callableMethod;
|
|
||||||
boolean hasThis0 = typeMapper.hasThis0(descriptor);
|
|
||||||
if (constructorDescriptor == null) {
|
|
||||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
|
||||||
|
|
||||||
signatureWriter.writeFormalTypeParametersStart();
|
MutableClosure closure = context.closure;
|
||||||
signatureWriter.writeFormalTypeParametersEnd();
|
boolean hasThis0 = closure != null && closure.getCaptureThis() != null;
|
||||||
|
|
||||||
signatureWriter.writeParametersStart();
|
final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure);
|
||||||
|
final JvmMethodSignature constructorMethod = callableMethod.getSignature();
|
||||||
if (hasThis0) {
|
|
||||||
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
|
|
||||||
typeMapper
|
|
||||||
.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), signatureWriter,
|
|
||||||
MapTypeMode.VALUE);
|
|
||||||
signatureWriter.writeParameterTypeEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
signatureWriter.writeParametersEnd();
|
|
||||||
|
|
||||||
signatureWriter.writeVoidReturn();
|
|
||||||
|
|
||||||
constructorMethod = signatureWriter.makeJvmMethodSignature("<init>");
|
|
||||||
callableMethod =
|
|
||||||
new CallableMethod(JvmClassName.byInternalName("Ignored"), null, null, constructorMethod, INVOKESPECIAL, null, null,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor,
|
|
||||||
typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
|
||||||
constructorMethod = callableMethod.getSignature();
|
|
||||||
}
|
|
||||||
|
|
||||||
lookupDelegateExpressionInClosureIfPresent();
|
|
||||||
|
|
||||||
ObjectOrClosureCodegen closure = context.closure;
|
|
||||||
int firstSuperArgument = -1;
|
|
||||||
final List<JvmMethodParameterSignature> consArgTypes =
|
|
||||||
new LinkedList<JvmMethodParameterSignature>(constructorMethod.getKotlinParameterTypes());
|
|
||||||
|
|
||||||
int insert = addClosureToConstructorParameters(hasThis0, closure, consArgTypes);
|
|
||||||
|
|
||||||
if (myClass instanceof JetObjectDeclaration && ((JetObjectDeclaration) myClass).isObjectLiteral()) {
|
|
||||||
if (superCall instanceof JetDelegatorToSuperCall) {
|
|
||||||
if (closure != null) {
|
|
||||||
closure.superCall = (JetDelegatorToSuperCall) superCall;
|
|
||||||
}
|
|
||||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET,
|
|
||||||
((JetDelegatorToSuperCall) superCall).getCalleeExpression()
|
|
||||||
.getConstructorReferenceExpression());
|
|
||||||
if (declarationDescriptor instanceof ClassDescriptorFromSource) {
|
|
||||||
declarationDescriptor = ((ClassDescriptorFromSource) declarationDescriptor).getUnsubstitutedPrimaryConstructor();
|
|
||||||
}
|
|
||||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) declarationDescriptor;
|
|
||||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, typeMapper
|
|
||||||
.hasThis0(superConstructor.getContainingDeclaration()));
|
|
||||||
firstSuperArgument = insert;
|
|
||||||
for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
|
||||||
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructorMethod = JvmMethodSignature.simple("<init>", Type.VOID_TYPE, consArgTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert constructorDescriptor != null;
|
assert constructorDescriptor != null;
|
||||||
int flags = JetTypeMapper.getAccessModifiers(constructorDescriptor, 0);
|
int flags = JetTypeMapper.getAccessModifiers(constructorDescriptor, 0);
|
||||||
@@ -643,18 +589,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
generatePrimiryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, hasThis0, closure,
|
generatePrimiryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, hasThis0, closure, mv);
|
||||||
firstSuperArgument, mv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generatePrimiryConstructorImpl(
|
private void generatePrimiryConstructorImpl(
|
||||||
ConstructorDescriptor constructorDescriptor,
|
ConstructorDescriptor constructorDescriptor,
|
||||||
CodegenContexts.ConstructorContext constructorContext,
|
CodegenContext.ConstructorContext constructorContext,
|
||||||
JvmMethodSignature constructorMethod,
|
JvmMethodSignature constructorMethod,
|
||||||
CallableMethod callableMethod,
|
CallableMethod callableMethod,
|
||||||
boolean hasThis0,
|
boolean hasThis0,
|
||||||
ObjectOrClosureCodegen closure,
|
MutableClosure closure,
|
||||||
int firstSuperArgument,
|
|
||||||
MethodVisitor mv
|
MethodVisitor mv
|
||||||
) {
|
) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
@@ -663,7 +607,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
? constructorDescriptor.getValueParameters()
|
? constructorDescriptor.getValueParameters()
|
||||||
: Collections.<ValueParameterDescriptor>emptyList();
|
: Collections.<ValueParameterDescriptor>emptyList();
|
||||||
|
|
||||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, hasThis0);
|
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor);
|
||||||
|
|
||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
|
||||||
@@ -678,38 +622,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
genSuperCallToDelegatorToSuperClass(iv);
|
genSuperCallToDelegatorToSuperClass(iv);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
|
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, frameMap);
|
||||||
((JetDelegatorToSuperCall) superCall)
|
|
||||||
.getCalleeExpression()
|
|
||||||
.getConstructorReferenceExpression());
|
|
||||||
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap,
|
|
||||||
firstSuperArgument);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor);
|
if (hasThis0) {
|
||||||
final boolean hasOuterThis = typeMapper.hasThis0(descriptor) && outerDescriptor != null;
|
final Type type = typeMapper
|
||||||
if (hasOuterThis) {
|
.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), MapTypeMode.VALUE);
|
||||||
final Type type = typeMapper.mapType(outerDescriptor.getDefaultType(), MapTypeMode.VALUE);
|
|
||||||
String interfaceDesc = type.getDescriptor();
|
String interfaceDesc = type.getDescriptor();
|
||||||
final String fieldName = "this$0";
|
|
||||||
v.newField(myClass, ACC_FINAL, fieldName, interfaceDesc, null, null);
|
|
||||||
iv.load(0, classType);
|
iv.load(0, classType);
|
||||||
iv.load(frameMap.getOuterThisIndex(), type);
|
iv.load(frameMap.getOuterThisIndex(), type);
|
||||||
iv.putfield(classname.getInternalName(), fieldName, interfaceDesc);
|
iv.putfield(classname.getInternalName(), CodegenUtil.THIS$0, interfaceDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closure != null) {
|
if (closure != null) {
|
||||||
int k = hasOuterThis ? 2 : 1;
|
int k = hasThis0 ? 2 : 1;
|
||||||
if (closure.captureReceiver != null) {
|
final String internalName = typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName();
|
||||||
|
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||||
|
if (captureReceiver != null) {
|
||||||
iv.load(0, JetTypeMapper.OBJECT_TYPE);
|
iv.load(0, JetTypeMapper.OBJECT_TYPE);
|
||||||
final Type asmType = typeMapper.mapType(closure.captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
final Type asmType = typeMapper.mapType(captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
||||||
iv.load(1, asmType);
|
iv.load(1, asmType);
|
||||||
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(), "receiver$0",
|
iv.putfield(internalName, CodegenUtil.RECEIVER$0, asmType.getDescriptor());
|
||||||
asmType.getDescriptor());
|
|
||||||
k += asmType.getSize();
|
k += asmType.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DeclarationDescriptor varDescr : closure.closure.keySet()) {
|
for (DeclarationDescriptor varDescr : closure.getCaptureVariables().keySet()) {
|
||||||
if (varDescr instanceof VariableDescriptor && !(varDescr instanceof PropertyDescriptor)) {
|
if (varDescr instanceof VariableDescriptor && !(varDescr instanceof PropertyDescriptor)) {
|
||||||
Type sharedVarType = typeMapper.getSharedVarType(varDescr);
|
Type sharedVarType = typeMapper.getSharedVarType(varDescr);
|
||||||
if (sharedVarType == null) {
|
if (sharedVarType == null) {
|
||||||
@@ -718,7 +655,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
iv.load(0, JetTypeMapper.OBJECT_TYPE);
|
iv.load(0, JetTypeMapper.OBJECT_TYPE);
|
||||||
iv.load(k, StackValue.refType(sharedVarType));
|
iv.load(k, StackValue.refType(sharedVarType));
|
||||||
k += StackValue.refType(sharedVarType).getSize();
|
k += StackValue.refType(sharedVarType).getSize();
|
||||||
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(),
|
iv.putfield(internalName,
|
||||||
"$" + varDescr.getName(), sharedVarType.getDescriptor());
|
"$" + varDescr.getName(), sharedVarType.getDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -847,37 +784,30 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
.getDefaultType(),
|
.getDefaultType(),
|
||||||
MapTypeMode.IMPL)
|
MapTypeMode.IMPL)
|
||||||
.getInternalName()),
|
.getInternalName()),
|
||||||
state.getInjector().getJetTypeMapper());
|
state);
|
||||||
generateDelegates(superClass, delegateContext, field);
|
generateDelegates(superClass, delegateContext, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int addClosureToConstructorParameters(
|
private int addClosureToConstructorParameters(
|
||||||
boolean hasThis0,
|
MutableClosure closure,
|
||||||
ObjectOrClosureCodegen closure,
|
|
||||||
List<JvmMethodParameterSignature> consArgTypes
|
List<JvmMethodParameterSignature> consArgTypes
|
||||||
) {
|
) {
|
||||||
int insert = 0;
|
int insert = 0;
|
||||||
if (closure != null) {
|
if (closure != null) {
|
||||||
if (closure.captureThis != null) {
|
if (closure.getCaptureThis() != null) {
|
||||||
if (!hasThis0) {
|
consArgTypes.add(insert,
|
||||||
consArgTypes.add(insert,
|
new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName().getName()),
|
||||||
new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName().getName()),
|
"", JvmMethodParameterKind.OUTER));
|
||||||
"", JvmMethodParameterKind.THIS0));
|
|
||||||
}
|
|
||||||
insert++;
|
insert++;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (hasThis0) {
|
|
||||||
insert++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closure.captureReceiver != null) {
|
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||||
final Type asmType = typeMapper.mapType(closure.captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
if (captureReceiver != null) {
|
||||||
|
final Type asmType = typeMapper.mapType(captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
||||||
consArgTypes.add(insert++, new JvmMethodParameterSignature(asmType, "", JvmMethodParameterKind.RECEIVER));
|
consArgTypes.add(insert++, new JvmMethodParameterSignature(asmType, "", JvmMethodParameterKind.RECEIVER));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DeclarationDescriptor descriptor : closure.closure.keySet()) {
|
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
|
||||||
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
||||||
final Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
final Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||||
final Type type;
|
final Type type;
|
||||||
@@ -891,30 +821,64 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
consArgTypes.add(insert++, new JvmMethodParameterSignature(type, "", JvmMethodParameterKind.SHARED_VAR));
|
consArgTypes.add(insert++, new JvmMethodParameterSignature(type, "", JvmMethodParameterKind.SHARED_VAR));
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof FunctionDescriptor) {
|
else if (descriptor instanceof FunctionDescriptor) {
|
||||||
assert closure.captureReceiver != null;
|
assert captureReceiver != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return insert;
|
return insert;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lookupDelegateExpressionInClosureIfPresent() {
|
private void lookupConstructorExpressionsInClosureIfPresent(final CodegenContext.ConstructorContext constructorContext) {
|
||||||
if (context.closure != null) {
|
final JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||||
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
@Override
|
||||||
if (specifier != superCall && specifier instanceof JetDelegatorByExpressionSpecifier) {
|
public void visitJetElement(JetElement e) {
|
||||||
|
e.acceptChildren(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitSimpleNameExpression(JetSimpleNameExpression expr) {
|
||||||
|
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr);
|
||||||
|
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
||||||
|
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) constructorContext.getContextDescriptor();
|
||||||
|
for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
if (descriptor.equals(parameterDescriptor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
constructorContext.lookupInContext(descriptor, null, state, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
|
if (declaration instanceof JetProperty) {
|
||||||
|
final JetProperty property = (JetProperty) declaration;
|
||||||
|
final JetExpression initializer = property.getInitializer();
|
||||||
|
if (initializer != null) {
|
||||||
|
initializer.accept(visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (declaration instanceof JetClassInitializer) {
|
||||||
|
final JetClassInitializer initializer = (JetClassInitializer) declaration;
|
||||||
|
initializer.accept(visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||||
|
if (specifier != superCall) {
|
||||||
|
if (specifier instanceof JetDelegatorByExpressionSpecifier) {
|
||||||
JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
||||||
assert delegateExpression != null;
|
assert delegateExpression != null;
|
||||||
delegateExpression.accept(new JetVisitorVoid() {
|
delegateExpression.accept(visitor);
|
||||||
@Override
|
}
|
||||||
public void visitJetElement(JetElement e) {
|
}
|
||||||
e.acceptChildren(this);
|
else {
|
||||||
}
|
if (superCall instanceof JetDelegatorToSuperCall) {
|
||||||
|
final JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList();
|
||||||
@Override
|
if (argumentList != null) {
|
||||||
public void visitSimpleNameExpression(JetSimpleNameExpression expr) {
|
argumentList.accept(visitor);
|
||||||
context.closure.lookupInContext(bindingContext.get(BindingContext.REFERENCE_TARGET, expr), null);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1059,48 +1023,63 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateDelegatorToConstructorCall(
|
private void generateDelegatorToConstructorCall(
|
||||||
InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
|
InstructionAdapter iv, ExpressionCodegen codegen,
|
||||||
ConstructorDescriptor constructorDescriptor,
|
ConstructorDescriptor constructorDescriptor,
|
||||||
ConstructorFrameMap frameMap, int firstSuperArgument
|
ConstructorFrameMap frameMap
|
||||||
) {
|
) {
|
||||||
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
|
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
|
||||||
|
|
||||||
iv.load(0, OBJECT_TYPE);
|
iv.load(0, OBJECT_TYPE);
|
||||||
|
|
||||||
if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) {
|
if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) {
|
||||||
iv.load(1, JetTypeMapper.OBJECT_TYPE);
|
iv.load(1, OBJECT_TYPE);
|
||||||
iv.load(2, Type.INT_TYPE);
|
iv.load(2, Type.INT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
|
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure);
|
||||||
iv.load(frameMap.getOuterThisIndex(),
|
|
||||||
typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), MapTypeMode.IMPL));
|
|
||||||
}
|
|
||||||
|
|
||||||
CallableMethod method = typeMapper
|
final ResolvedCall<? extends CallableDescriptor> resolvedCall =
|
||||||
.mapToCallableMethod(constructorDescriptor, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
bindingContext.get(BindingContext.RESOLVED_CALL, ((JetCallElement) superCall).getCalleeExpression());
|
||||||
|
assert resolvedCall != null;
|
||||||
|
final ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
|
||||||
|
|
||||||
|
final CalculatedClosure closureForSuper = typeMapper.getCalculatedClosure(superConstructor.getContainingDeclaration());
|
||||||
|
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor,
|
||||||
|
closureForSuper);
|
||||||
|
|
||||||
|
if (closureForSuper != null && closureForSuper.getCaptureThis() != null) {
|
||||||
|
iv.load(frameMap.getOuterThisIndex(), OBJECT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
if (myClass instanceof JetObjectDeclaration &&
|
if (myClass instanceof JetObjectDeclaration &&
|
||||||
superCall instanceof JetDelegatorToSuperCall &&
|
superCall instanceof JetDelegatorToSuperCall &&
|
||||||
((JetObjectDeclaration) myClass).isObjectLiteral()) {
|
((JetObjectDeclaration) myClass).isObjectLiteral()) {
|
||||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
|
int nextVar = findFirstSuperArgument(method);
|
||||||
((JetDelegatorToSuperCall) superCall)
|
|
||||||
.getCalleeExpression()
|
|
||||||
.getConstructorReferenceExpression());
|
|
||||||
assert superConstructor != null;
|
|
||||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor,
|
|
||||||
typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
|
|
||||||
int nextVar = firstSuperArgument + 1;
|
|
||||||
for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
||||||
iv.load(nextVar, t);
|
iv.load(nextVar, t);
|
||||||
nextVar += t.getSize();
|
nextVar += t.getSize();
|
||||||
}
|
}
|
||||||
method.invoke(codegen.v);
|
superCallable.invoke(codegen.v);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
codegen.invokeMethodWithArguments(method, constructorCall, StackValue.none());
|
codegen.invokeMethodWithArguments(superCallable, (JetCallElement) superCall, StackValue.none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int findFirstSuperArgument(CallableMethod method) {
|
||||||
|
final List<JvmMethodParameterSignature> types = method.getSignature().getKotlinParameterTypes();
|
||||||
|
if (types != null) {
|
||||||
|
int i = 0;
|
||||||
|
for (JvmMethodParameterSignature type : types) {
|
||||||
|
if (type.getKind() == JvmMethodParameterKind.SUPER_CALL_PARAM) {
|
||||||
|
return i + 1; // because of this
|
||||||
|
}
|
||||||
|
i += type.getAsmType().getSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
||||||
if (declaration instanceof JetClassObject) {
|
if (declaration instanceof JetClassObject) {
|
||||||
@@ -1171,7 +1150,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
.get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
|
.get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
|
||||||
assert constructorDescriptor != null;
|
assert constructorDescriptor != null;
|
||||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, typeMapper
|
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, typeMapper
|
||||||
.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
.getCalculatedClosure(constructorDescriptor.getContainingDeclaration()));
|
||||||
codegen.invokeMethodWithArguments(method, superCall, StackValue.none());
|
codegen.invokeMethodWithArguments(method, superCall, StackValue.none());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1206,7 +1185,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
Type type = typeMapper.mapType(jetType, MapTypeMode.VALUE);
|
Type type = typeMapper.mapType(jetType, MapTypeMode.VALUE);
|
||||||
if (skipDefaultValue(propertyDescriptor, value, type)) continue;
|
if (skipDefaultValue(propertyDescriptor, value, type)) continue;
|
||||||
}
|
}
|
||||||
iv.load(0, JetTypeMapper.OBJECT_TYPE);
|
iv.load(0, OBJECT_TYPE);
|
||||||
Type type = codegen.expressionType(initializer);
|
Type type = codegen.expressionType(initializer);
|
||||||
if (jetType.isNullable()) {
|
if (jetType.isNullable()) {
|
||||||
type = JetTypeMapper.boxType(type);
|
type = JetTypeMapper.boxType(type);
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.asm4.Opcodes;
|
import org.jetbrains.asm4.Opcodes;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
|
import org.jetbrains.jet.codegen.context.CalculatedClosure;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
|
import org.jetbrains.jet.codegen.context.ClosureAnnotator;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
import org.jetbrains.jet.codegen.signature.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetClassObject;
|
import org.jetbrains.jet.lang.psi.JetClassObject;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
|
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -40,10 +41,7 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
|||||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.asm4.Opcodes.*;
|
import static org.jetbrains.asm4.Opcodes.*;
|
||||||
|
|
||||||
@@ -103,7 +101,12 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
||||||
return closureAnnotator.hasThis0(classDescriptor);
|
final CalculatedClosure closure = closureAnnotator.getCalculatedClosure(classDescriptor);
|
||||||
|
return closure != null && closure.getCaptureThis() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CalculatedClosure getCalculatedClosure(ClassDescriptor classDescriptor) {
|
||||||
|
return closureAnnotator.getCalculatedClosure(classDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClosureAnnotator getClosureAnnotator() {
|
public ClosureAnnotator getClosureAnnotator() {
|
||||||
@@ -856,22 +859,27 @@ public class JetTypeMapper {
|
|||||||
jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1));
|
jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, boolean hasThis0) {
|
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, CalculatedClosure closure) {
|
||||||
|
|
||||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
|
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
|
||||||
|
|
||||||
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
|
|
||||||
|
|
||||||
// constructor type parmeters are fake
|
// constructor type parmeters are fake
|
||||||
writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
|
writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
|
||||||
|
|
||||||
signatureWriter.writeParametersStart();
|
signatureWriter.writeParametersStart();
|
||||||
|
|
||||||
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||||
if (hasThis0) {
|
final ClassDescriptor captureThis = closure != null ? closure.getCaptureThis() : null;
|
||||||
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
|
if (captureThis != null) {
|
||||||
mapType(closureAnnotator.getEclosingClassDescriptor(containingDeclaration).getDefaultType(), signatureWriter,
|
signatureWriter.writeParameterType(JvmMethodParameterKind.OUTER);
|
||||||
MapTypeMode.VALUE);
|
mapType(captureThis.getDefaultType(), signatureWriter, MapTypeMode.VALUE);
|
||||||
|
signatureWriter.writeParameterTypeEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ClassifierDescriptor captureReceiver = closure != null ? closure.getCaptureReceiver() : null;
|
||||||
|
if (captureReceiver != null) {
|
||||||
|
signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
|
||||||
|
mapType(captureReceiver.getDefaultType(), signatureWriter, MapTypeMode.VALUE);
|
||||||
signatureWriter.writeParameterTypeEnd();
|
signatureWriter.writeParameterTypeEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -884,7 +892,46 @@ public class JetTypeMapper {
|
|||||||
signatureWriter.writeParameterTypeEnd();
|
signatureWriter.writeParameterTypeEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ValueParameterDescriptor parameter : parameters) {
|
if (closure != null) {
|
||||||
|
for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
|
||||||
|
if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) {
|
||||||
|
Type sharedVarType = getSharedVarType(entry.getKey());
|
||||||
|
if (sharedVarType == null) {
|
||||||
|
sharedVarType = mapType(((VariableDescriptor) entry.getKey()).getType(), MapTypeMode.VALUE);
|
||||||
|
}
|
||||||
|
signatureWriter.writeParameterType(JvmMethodParameterKind.SHARED_VAR);
|
||||||
|
signatureWriter.writeAsmType(sharedVarType, false);
|
||||||
|
signatureWriter.writeParameterTypeEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final JetDelegatorToSuperCall superCall = closure.getSuperCall();
|
||||||
|
if (superCall != null) {
|
||||||
|
DeclarationDescriptor superDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET,
|
||||||
|
superCall
|
||||||
|
.getCalleeExpression()
|
||||||
|
.getConstructorReferenceExpression());
|
||||||
|
|
||||||
|
if(superDescriptor instanceof ConstructorDescriptor) {
|
||||||
|
final ConstructorDescriptor superConstructor = (ConstructorDescriptor) superDescriptor;
|
||||||
|
|
||||||
|
if (CodegenUtil.isObjectLiteral(descriptor.getContainingDeclaration(), bindingContext)) {
|
||||||
|
CallableMethod superCallable = mapToCallableMethod(superConstructor,
|
||||||
|
getCalculatedClosure(superConstructor.getContainingDeclaration()));
|
||||||
|
final List<JvmMethodParameterSignature> types = superCallable.getSignature().getKotlinParameterTypes();
|
||||||
|
if (types != null) {
|
||||||
|
for (JvmMethodParameterSignature type : types) {
|
||||||
|
signatureWriter.writeParameterType(JvmMethodParameterKind.SUPER_CALL_PARAM);
|
||||||
|
signatureWriter.writeAsmType(type.getAsmType(), false);
|
||||||
|
signatureWriter.writeParameterTypeEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ValueParameterDescriptor parameter : descriptor.getOriginal().getValueParameters()) {
|
||||||
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
|
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
|
||||||
mapType(parameter.getType(), signatureWriter, MapTypeMode.VALUE);
|
mapType(parameter.getType(), signatureWriter, MapTypeMode.VALUE);
|
||||||
signatureWriter.writeParameterTypeEnd();
|
signatureWriter.writeParameterTypeEnd();
|
||||||
@@ -925,8 +972,8 @@ public class JetTypeMapper {
|
|||||||
return signatureWriter.makeJvmMethodSignature("<init>");
|
return signatureWriter.makeJvmMethodSignature("<init>");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, boolean hasThis0) {
|
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, CalculatedClosure closure) {
|
||||||
final JvmMethodSignature method = mapConstructorSignature(descriptor, hasThis0);
|
final JvmMethodSignature method = mapConstructorSignature(descriptor, closure);
|
||||||
JetType defaultType = descriptor.getContainingDeclaration().getDefaultType();
|
JetType defaultType = descriptor.getContainingDeclaration().getDefaultType();
|
||||||
Type mapped = mapType(defaultType, MapTypeMode.IMPL);
|
Type mapped = mapType(defaultType, MapTypeMode.IMPL);
|
||||||
if (mapped.getSort() != Type.OBJECT) {
|
if (mapped.getSort() != Type.OBJECT) {
|
||||||
@@ -999,4 +1046,23 @@ public class JetTypeMapper {
|
|||||||
return Boolean.TRUE.equals(bindingContext.get(BindingContext.CAPTURED_IN_CLOSURE, variableDescriptor)) &&
|
return Boolean.TRUE.equals(bindingContext.get(BindingContext.CAPTURED_IN_CLOSURE, variableDescriptor)) &&
|
||||||
variableDescriptor.isVar();
|
variableDescriptor.isVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected JvmMethodSignature invokeSignature(FunctionDescriptor fd) {
|
||||||
|
return mapSignature(Name.identifier("invoke"), fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallableMethod asCallableMethod(FunctionDescriptor fd) {
|
||||||
|
JvmMethodSignature descriptor = CodegenUtil.erasedInvokeSignature(fd);
|
||||||
|
JvmClassName owner = CodegenUtil.getInternalClassName(fd);
|
||||||
|
Type receiverParameterType;
|
||||||
|
if (fd.getReceiverParameter().exists()) {
|
||||||
|
receiverParameterType = mapType(fd.getOriginal().getReceiverParameter().getType(), MapTypeMode.VALUE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
receiverParameterType = null;
|
||||||
|
}
|
||||||
|
return new CallableMethod(
|
||||||
|
owner, null, null, descriptor, INVOKEVIRTUAL,
|
||||||
|
CodegenUtil.getInternalClassName(fd), receiverParameterType, CodegenUtil.getInternalClassName(fd).getAsmType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author alex.tkachman
|
|
||||||
*/
|
|
||||||
public class LocalClassClosureCodegen extends ObjectOrClosureCodegen {
|
|
||||||
public LocalClassClosureCodegen(
|
|
||||||
ExpressionCodegen exprContext,
|
|
||||||
CodegenContext context,
|
|
||||||
@NotNull GenerationState state,
|
|
||||||
ClassDescriptor descriptor
|
|
||||||
) {
|
|
||||||
super(exprContext, context, state);
|
|
||||||
state.getInjector().getClosureAnnotator().recordLocalClass(descriptor, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||||
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner;
|
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||||
@@ -122,19 +123,19 @@ public class NamespaceCodegen {
|
|||||||
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
||||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor, state.getInjector().getJetTypeMapper());
|
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
|
||||||
state.getInjector().getMemberCodegen().generateFunctionOrProperty(
|
state.getInjector().getMemberCodegen().generateFunctionOrProperty(
|
||||||
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetNamedFunction) {
|
else if (declaration instanceof JetNamedFunction) {
|
||||||
if (!multiFile) {
|
if (!multiFile) {
|
||||||
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor, state.getInjector().getJetTypeMapper());
|
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
|
||||||
state.getInjector().getMemberCodegen().generateFunctionOrProperty(
|
state.getInjector().getMemberCodegen().generateFunctionOrProperty(
|
||||||
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetClassOrObject) {
|
else if (declaration instanceof JetClassOrObject) {
|
||||||
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor, state.getInjector().getJetTypeMapper());
|
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
|
||||||
state.getInjector().getClassCodegen().generate(context, (JetClassOrObject) declaration);
|
state.getInjector().getClassCodegen().generate(context, (JetClassOrObject) declaration);
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetScript) {
|
else if (declaration instanceof JetScript) {
|
||||||
@@ -170,13 +171,13 @@ public class NamespaceCodegen {
|
|||||||
if (declaration instanceof JetNamedFunction) {
|
if (declaration instanceof JetNamedFunction) {
|
||||||
{
|
{
|
||||||
final CodegenContext context =
|
final CodegenContext context =
|
||||||
CodegenContexts.STATIC.intoNamespace(descriptor, state.getInjector().getJetTypeMapper());
|
CodegenContext.STATIC.intoNamespace(descriptor);
|
||||||
state.getInjector().getMemberCodegen()
|
state.getInjector().getMemberCodegen()
|
||||||
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, builder);
|
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, builder);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final CodegenContext context =
|
final CodegenContext context =
|
||||||
CodegenContexts.STATIC.intoNamespacePart(className, descriptor, state.getInjector().getJetTypeMapper());
|
CodegenContext.STATIC.intoNamespacePart(className, descriptor);
|
||||||
state.getInjector().getMemberCodegen()
|
state.getInjector().getMemberCodegen()
|
||||||
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
||||||
}
|
}
|
||||||
@@ -232,7 +233,7 @@ public class NamespaceCodegen {
|
|||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
FrameMap frameMap = new FrameMap();
|
FrameMap frameMap = new FrameMap();
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContexts.STATIC, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
|
||||||
|
|
||||||
for (JetFile file : files) {
|
for (JetFile file : files) {
|
||||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.asm4.Opcodes;
|
|
||||||
import org.jetbrains.asm4.Type;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author alex.tkachman
|
|
||||||
*/
|
|
||||||
public class ObjectOrClosureCodegen {
|
|
||||||
protected ClassDescriptor captureThis;
|
|
||||||
protected ClassifierDescriptor captureReceiver;
|
|
||||||
|
|
||||||
public final GenerationState state;
|
|
||||||
private final ExpressionCodegen exprContext;
|
|
||||||
protected final CodegenContext context;
|
|
||||||
protected ClassBuilder cv = null;
|
|
||||||
public JvmClassName name = null;
|
|
||||||
protected final Map<DeclarationDescriptor, EnclosedValueDescriptor> closure =
|
|
||||||
new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
|
||||||
public JetDelegatorToSuperCall superCall;
|
|
||||||
|
|
||||||
public ObjectOrClosureCodegen(ExpressionCodegen exprContext, CodegenContext context, GenerationState state) {
|
|
||||||
this.exprContext = exprContext;
|
|
||||||
this.context = context;
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result) {
|
|
||||||
EnclosedValueDescriptor answer = closure.get(d);
|
|
||||||
if (answer != null) {
|
|
||||||
StackValue innerValue = answer.getInnerValue();
|
|
||||||
return result != null ? innerValue : StackValue.composed(result, innerValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d instanceof VariableDescriptor && !(d instanceof PropertyDescriptor)) {
|
|
||||||
VariableDescriptor vd = (VariableDescriptor) d;
|
|
||||||
|
|
||||||
final int idx = exprContext.lookupLocal(vd);
|
|
||||||
if (idx < 0) return null;
|
|
||||||
|
|
||||||
final Type sharedVarType = state.getInjector().getJetTypeMapper().getSharedVarType(vd);
|
|
||||||
Type localType = state.getInjector().getJetTypeMapper().mapType(vd.getType(), MapTypeMode.VALUE);
|
|
||||||
final Type type = sharedVarType != null ? sharedVarType : localType;
|
|
||||||
|
|
||||||
StackValue outerValue = StackValue.local(idx, type);
|
|
||||||
final String fieldName = "$" + vd.getName();
|
|
||||||
StackValue innerValue = sharedVarType != null
|
|
||||||
? StackValue.fieldForSharedVar(localType, name, fieldName)
|
|
||||||
: StackValue.field(type, name, fieldName, false);
|
|
||||||
|
|
||||||
cv.newField(null, Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
|
|
||||||
|
|
||||||
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
|
|
||||||
closure.put(d, answer);
|
|
||||||
|
|
||||||
return innerValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CodegenUtil.isNamedFun(d, state.getBindingContext()) && d.getContainingDeclaration() instanceof FunctionDescriptor) {
|
|
||||||
FunctionDescriptor vd = (FunctionDescriptor) d;
|
|
||||||
|
|
||||||
final int idx = exprContext.lookupLocal(vd);
|
|
||||||
if (idx < 0) return null;
|
|
||||||
|
|
||||||
JetElement expression = (JetElement) BindingContextUtils.callableDescriptorToDeclaration(state.getBindingContext(), vd);
|
|
||||||
JvmClassName cn = state.getInjector().getJetTypeMapper().getClosureAnnotator().classNameForAnonymousClass(expression);
|
|
||||||
Type localType = cn.getAsmType();
|
|
||||||
|
|
||||||
StackValue outerValue = StackValue.local(idx, localType);
|
|
||||||
final String fieldName = "$" + vd.getName();
|
|
||||||
StackValue innerValue = StackValue.field(localType, name, fieldName, false);
|
|
||||||
|
|
||||||
cv.newField(null, Opcodes.ACC_PUBLIC, fieldName, localType.getDescriptor(), null, null);
|
|
||||||
|
|
||||||
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
|
|
||||||
closure.put(d, answer);
|
|
||||||
|
|
||||||
return innerValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d instanceof FunctionDescriptor) {
|
|
||||||
// we are looking for receiver
|
|
||||||
FunctionDescriptor fd = (FunctionDescriptor) d;
|
|
||||||
|
|
||||||
// we generate method
|
|
||||||
assert context instanceof CodegenContexts.ReceiverContext;
|
|
||||||
|
|
||||||
CodegenContexts.ReceiverContext fcontext = (CodegenContexts.ReceiverContext) context;
|
|
||||||
|
|
||||||
if (fcontext.getReceiverDescriptor() != fd) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type = state.getInjector().getJetTypeMapper()
|
|
||||||
.mapType(fcontext.getReceiverDescriptor().getReceiverParameter().getType(), MapTypeMode.VALUE);
|
|
||||||
boolean isStatic = fcontext.getContextDescriptor().getContainingDeclaration() instanceof NamespaceDescriptor;
|
|
||||||
StackValue outerValue = StackValue.local(isStatic ? 0 : 1, type);
|
|
||||||
final String fieldName = "receiver$0";
|
|
||||||
StackValue innerValue = StackValue.field(type, name, fieldName, false);
|
|
||||||
|
|
||||||
cv.newField(null, Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
|
|
||||||
|
|
||||||
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
|
|
||||||
closure.put(d, answer);
|
|
||||||
|
|
||||||
assert captureReceiver == null;
|
|
||||||
captureReceiver =
|
|
||||||
fcontext.getReceiverDescriptor().getReceiverParameter().getType().getConstructor().getDeclarationDescriptor();
|
|
||||||
|
|
||||||
return innerValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConst() {
|
|
||||||
return captureThis == null && captureReceiver == null && closure.isEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,6 +24,7 @@ import org.jetbrains.asm4.MethodVisitor;
|
|||||||
import org.jetbrains.asm4.Opcodes;
|
import org.jetbrains.asm4.Opcodes;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
||||||
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import org.jetbrains.asm4.MethodVisitor;
|
|||||||
import org.jetbrains.asm4.Opcodes;
|
import org.jetbrains.asm4.Opcodes;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
|
import org.jetbrains.jet.codegen.context.ClosureAnnotator;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||||
@@ -99,9 +101,9 @@ public class ScriptCodegen {
|
|||||||
assert scriptDescriptor != null;
|
assert scriptDescriptor != null;
|
||||||
ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor);
|
ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor);
|
||||||
|
|
||||||
CodegenContexts.ScriptContext context =
|
CodegenContext.ScriptContext context =
|
||||||
(CodegenContexts.ScriptContext) CodegenContexts.STATIC
|
(CodegenContext.ScriptContext) CodegenContext.STATIC
|
||||||
.intoScript(scriptDescriptor, classDescriptorForScript, state.getInjector().getJetTypeMapper());
|
.intoScript(scriptDescriptor, classDescriptorForScript);
|
||||||
|
|
||||||
JvmClassName className = closureAnnotator.classNameForClassDescriptor(classDescriptorForScript);
|
JvmClassName className = closureAnnotator.classNameForClassDescriptor(classDescriptorForScript);
|
||||||
|
|
||||||
@@ -117,7 +119,7 @@ public class ScriptCodegen {
|
|||||||
genMembers(scriptDeclaration, context, classBuilder);
|
genMembers(scriptDeclaration, context, classBuilder);
|
||||||
genFieldsForParameters(scriptDescriptor, classBuilder);
|
genFieldsForParameters(scriptDescriptor, classBuilder);
|
||||||
genConstructor(scriptDeclaration, scriptDescriptor, classDescriptorForScript, classBuilder,
|
genConstructor(scriptDeclaration, scriptDescriptor, classDescriptorForScript, classBuilder,
|
||||||
context.intoFunction(scriptDescriptor.getScriptCodeDescriptor(), state.getInjector().getJetTypeMapper()),
|
context.intoFunction(scriptDescriptor.getScriptCodeDescriptor()),
|
||||||
earlierScripts);
|
earlierScripts);
|
||||||
|
|
||||||
classBuilder.done();
|
classBuilder.done();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.asm4.Opcodes;
|
import org.jetbrains.asm4.Opcodes;
|
||||||
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
||||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.codegen.context;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Pair;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.asm4.Type;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
public interface CalculatedClosure {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
ClassDescriptor getEnclosingClass();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
JvmClassName getClassName();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
JetDelegatorToSuperCall getSuperCall();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
ClassDescriptor getCaptureThis();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
ClassifierDescriptor getCaptureReceiver();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
List<Pair<String, Type>> getRecordedFields();
|
||||||
|
}
|
||||||
+121
-92
@@ -14,14 +14,17 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen.context;
|
||||||
|
|
||||||
import com.intellij.util.containers.MultiMap;
|
import com.intellij.util.containers.MultiMap;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.codegen.CodegenUtil;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
@@ -36,15 +39,11 @@ import java.util.*;
|
|||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class ClosureAnnotator {
|
public class ClosureAnnotator {
|
||||||
private final Map<ClassDescriptor, JvmClassName> classNamesForClassDescriptor = new HashMap<ClassDescriptor, JvmClassName>();
|
private final Map<ClassDescriptor, CalculatedClosure> closuresForClassDescriptor = new HashMap<ClassDescriptor, CalculatedClosure>();
|
||||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
|
||||||
private final Map<ScriptDescriptor, JvmClassName> classNameForScript = new HashMap<ScriptDescriptor, JvmClassName>();
|
private final Map<ScriptDescriptor, JvmClassName> classNameForScript = new HashMap<ScriptDescriptor, JvmClassName>();
|
||||||
private final Map<ClassDescriptor, LocalClassClosureCodegen> localClassCodegenForClass =
|
|
||||||
new HashMap<ClassDescriptor, LocalClassClosureCodegen>();
|
|
||||||
private final Set<JvmClassName> scriptClassNames = new HashSet<JvmClassName>();
|
private final Set<JvmClassName> scriptClassNames = new HashSet<JvmClassName>();
|
||||||
private final Map<DeclarationDescriptor, ClassDescriptorImpl> classesForFunctions =
|
private final Map<DeclarationDescriptor, ClassDescriptorImpl> classesForFunctions =
|
||||||
new HashMap<DeclarationDescriptor, ClassDescriptorImpl>();
|
new HashMap<DeclarationDescriptor, ClassDescriptorImpl>();
|
||||||
private final Map<DeclarationDescriptor, ClassDescriptor> enclosing = new HashMap<DeclarationDescriptor, ClassDescriptor>();
|
|
||||||
|
|
||||||
private final MultiMap<FqName, JetFile> namespaceName2MultiNamespaceFiles = MultiMap.create();
|
private final MultiMap<FqName, JetFile> namespaceName2MultiNamespaceFiles = MultiMap.create();
|
||||||
private final MultiMap<FqName, JetFile> namespaceName2Files = MultiMap.create();
|
private final MultiMap<FqName, JetFile> namespaceName2Files = MultiMap.create();
|
||||||
@@ -76,7 +75,7 @@ public class ClosureAnnotator {
|
|||||||
int arity = funDescriptor.getValueParameters().size();
|
int arity = funDescriptor.getValueParameters().size();
|
||||||
|
|
||||||
classDescriptor = new ClassDescriptorImpl(
|
classDescriptor = new ClassDescriptorImpl(
|
||||||
funDescriptor,
|
funDescriptor.getContainingDeclaration(),
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
Name.special("<closure>"));
|
Name.special("<closure>"));
|
||||||
@@ -107,7 +106,6 @@ public class ClosureAnnotator {
|
|||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
Name.special("<script-" + className + ">"));
|
Name.special("<script-" + className + ">"));
|
||||||
recordName(classDescriptor, className);
|
|
||||||
classDescriptor.initialize(
|
classDescriptor.initialize(
|
||||||
false,
|
false,
|
||||||
Collections.<TypeParameterDescriptor>emptyList(),
|
Collections.<TypeParameterDescriptor>emptyList(),
|
||||||
@@ -116,6 +114,8 @@ public class ClosureAnnotator {
|
|||||||
Collections.<ConstructorDescriptor>emptySet(),
|
Collections.<ConstructorDescriptor>emptySet(),
|
||||||
null);
|
null);
|
||||||
|
|
||||||
|
recordClosure(null, classDescriptor, null, className, false);
|
||||||
|
|
||||||
ClassDescriptorImpl oldDescriptor = classesForFunctions.put(scriptDescriptor, classDescriptor);
|
ClassDescriptorImpl oldDescriptor = classesForFunctions.put(scriptDescriptor, classDescriptor);
|
||||||
if (oldDescriptor != null) {
|
if (oldDescriptor != null) {
|
||||||
throw new IllegalStateException("Rewrite at key " + scriptDescriptor + " for class");
|
throw new IllegalStateException("Rewrite at key " + scriptDescriptor + " for class");
|
||||||
@@ -150,7 +150,8 @@ public class ClosureAnnotator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JvmClassName classNameForScriptDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
|
public JvmClassName classNameForScriptDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
|
||||||
return classNameForClassDescriptor(classDescriptorForScriptDescriptor(scriptDescriptor));
|
final ClassDescriptor classDescriptor = classDescriptorForScriptDescriptor(scriptDescriptor);
|
||||||
|
return closuresForClassDescriptor.get(classDescriptor).getClassName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mapFilesToNamespaces(Collection<JetFile> files) {
|
private void mapFilesToNamespaces(Collection<JetFile> files) {
|
||||||
@@ -213,65 +214,90 @@ public class ClosureAnnotator {
|
|||||||
return classNameForClassDescriptor(descriptor);
|
return classNameForClassDescriptor(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassDescriptor getEclosingClassDescriptor(ClassDescriptor descriptor) {
|
public JvmClassName classNameForClassDescriptor(ClassDescriptor descriptor) {
|
||||||
return enclosing.get(descriptor);
|
final CalculatedClosure closure = closuresForClassDescriptor.get(descriptor);
|
||||||
|
return closure == null ? null : closure.getClassName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
public ClassDescriptor getEclosingClassDescriptor(ClassDescriptor descriptor) {
|
||||||
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS
|
final CalculatedClosure closure = closuresForClassDescriptor.get(descriptor);
|
||||||
|| classDescriptor.getKind() == ClassKind.ENUM_ENTRY
|
return closure == null ? null : closure.getEnclosingClass();
|
||||||
|| classDescriptor.getKind() == ClassKind.CLASS_OBJECT) {
|
}
|
||||||
|
|
||||||
|
public boolean canHaveOuter(ClassDescriptor classDescriptor) {
|
||||||
|
if (DescriptorUtils.isClassObject(classDescriptor)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS || classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassDescriptor other = enclosing.get(classDescriptor);
|
return getEclosingClassDescriptor(classDescriptor) != null;
|
||||||
return other != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean enumEntryNeedSubclass(JetEnumEntry enumEntry) {
|
public boolean enumEntryNeedSubclass(JetEnumEntry enumEntry) {
|
||||||
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, enumEntry);
|
return Boolean.TRUE.equals(enumEntryNeedSubclass.get(bindingContext.get(BindingContext.CLASS, enumEntry)));
|
||||||
return enumEntryNeedSubclass.get(descriptor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean enumEntryNeedSubclass(ClassDescriptor enumEntry) {
|
public boolean enumEntryNeedSubclass(ClassDescriptor enumEntry) {
|
||||||
Boolean aBoolean = enumEntryNeedSubclass.get(enumEntry);
|
return Boolean.TRUE.equals(enumEntryNeedSubclass.get(enumEntry));
|
||||||
return aBoolean != null && aBoolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordLocalClass(ClassDescriptor descriptor, LocalClassClosureCodegen codegen) {
|
public CalculatedClosure getCalculatedClosure(@NotNull ClassDescriptor descriptor) {
|
||||||
LocalClassClosureCodegen put = localClassCodegenForClass.put(descriptor, codegen);
|
//noinspection SuspiciousMethodCalls
|
||||||
assert put == null;
|
return closuresForClassDescriptor.get(descriptor.getOriginal());
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyJetVisitorVoid extends JetVisitorVoid {
|
private void recordClosure(
|
||||||
private final LinkedList<ClassDescriptor> classStack = new LinkedList<ClassDescriptor>();
|
@Nullable JetElement element,
|
||||||
private final LinkedList<String> nameStack = new LinkedList<String>();
|
ClassDescriptor classDescriptor,
|
||||||
|
@Nullable ClassDescriptor enclosing,
|
||||||
|
JvmClassName name,
|
||||||
|
boolean functionLiteral
|
||||||
|
) {
|
||||||
|
final JetDelegatorToSuperCall superCall = CodegenUtil.findSuperCall(element, bindingContext);
|
||||||
|
|
||||||
private void recordEnclosing(ClassDescriptor classDescriptor) {
|
CallableDescriptor enclosingReceiver = null;
|
||||||
if (classStack.size() > 0) {
|
if (classDescriptor.getContainingDeclaration() instanceof CallableDescriptor) {
|
||||||
ClassDescriptor put = enclosing.put(classDescriptor, classStack.peek());
|
enclosingReceiver = (CallableDescriptor) classDescriptor.getContainingDeclaration();
|
||||||
assert put == null;
|
enclosingReceiver = enclosingReceiver instanceof PropertyAccessorDescriptor
|
||||||
|
? ((PropertyAccessorDescriptor) enclosingReceiver).getCorrespondingProperty()
|
||||||
|
: enclosingReceiver;
|
||||||
|
|
||||||
|
if (!enclosingReceiver.getReceiverParameter().exists()) {
|
||||||
|
enclosingReceiver = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private JvmClassName recordAnonymousClass(JetElement declaration) {
|
final MutableClosure closure = new MutableClosure(superCall, enclosing, name, enclosingReceiver);
|
||||||
|
|
||||||
|
final CalculatedClosure old = closuresForClassDescriptor.put(classDescriptor, closure);
|
||||||
|
assert old == null;
|
||||||
|
|
||||||
|
// TODO: this is temporary before we have proper inner classes
|
||||||
|
if (canHaveOuter(classDescriptor) && !functionLiteral) {
|
||||||
|
closure.setCaptureThis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MyJetVisitorVoid extends JetVisitorVoid {
|
||||||
|
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
||||||
|
|
||||||
|
private final LinkedList<ClassDescriptor> classStack = new LinkedList<ClassDescriptor>();
|
||||||
|
private final LinkedList<String> nameStack = new LinkedList<String>();
|
||||||
|
|
||||||
|
private String inventAnonymousClassName(JetElement declaration) {
|
||||||
String top = nameStack.peek();
|
String top = nameStack.peek();
|
||||||
Integer cnt = anonymousSubclassesCount.get(top);
|
Integer cnt = anonymousSubclassesCount.get(top);
|
||||||
if (cnt == null) {
|
if (cnt == null) {
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
}
|
}
|
||||||
JvmClassName name = JvmClassName.byInternalName(top + "$" + (cnt + 1));
|
String name = top + "$" + (cnt + 1);
|
||||||
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
||||||
if (descriptor == null) {
|
if (descriptor == null) {
|
||||||
if (declaration instanceof JetFunctionLiteralExpression || declaration instanceof JetNamedFunction) {
|
if (declaration instanceof JetFunctionLiteralExpression ||
|
||||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.FUNCTION, declaration);
|
declaration instanceof JetNamedFunction ||
|
||||||
assert declarationDescriptor instanceof FunctionDescriptor;
|
declaration instanceof JetObjectLiteralExpression) {
|
||||||
descriptor = classDescriptorForFunctionDescriptor((FunctionDescriptor) declarationDescriptor);
|
|
||||||
}
|
|
||||||
else if (declaration instanceof JetObjectLiteralExpression) {
|
|
||||||
descriptor =
|
|
||||||
bindingContext.get(BindingContext.CLASS, ((JetObjectLiteralExpression) declaration).getObjectDeclaration());
|
|
||||||
assert descriptor != null;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
@@ -279,20 +305,11 @@ public class ClosureAnnotator {
|
|||||||
declaration.getClass().getName());
|
declaration.getClass().getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recordName(descriptor, name);
|
|
||||||
anonymousSubclassesCount.put(top, cnt + 1);
|
anonymousSubclassesCount.put(top, cnt + 1);
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JvmClassName recordClassObject(JetClassObject declaration) {
|
|
||||||
JvmClassName name = JvmClassName.byInternalName(nameStack.peek() + JvmAbi.CLASS_OBJECT_SUFFIX);
|
|
||||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, declaration.getObjectDeclaration());
|
|
||||||
assert classDescriptor != null;
|
|
||||||
recordName(classDescriptor, name);
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitJetElement(JetElement element) {
|
public void visitJetElement(JetElement element) {
|
||||||
super.visitJetElement(element);
|
super.visitJetElement(element);
|
||||||
@@ -302,6 +319,8 @@ public class ClosureAnnotator {
|
|||||||
@Override
|
@Override
|
||||||
public void visitJetFile(JetFile file) {
|
public void visitJetFile(JetFile file) {
|
||||||
if (file.isScript()) {
|
if (file.isScript()) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
classStack.push(classDescriptorForScriptDescriptor(bindingContext.get(BindingContext.SCRIPT, file.getScript())));
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
nameStack.push(classNameForScriptPsi(file.getScript()).getInternalName());
|
nameStack.push(classNameForScriptPsi(file.getScript()).getInternalName());
|
||||||
}
|
}
|
||||||
@@ -310,21 +329,39 @@ public class ClosureAnnotator {
|
|||||||
}
|
}
|
||||||
file.acceptChildren(this);
|
file.acceptChildren(this);
|
||||||
nameStack.pop();
|
nameStack.pop();
|
||||||
|
if (file.isScript()) {
|
||||||
|
classStack.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitEnumEntry(JetEnumEntry enumEntry) {
|
public void visitEnumEntry(JetEnumEntry enumEntry) {
|
||||||
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, enumEntry);
|
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, enumEntry);
|
||||||
enumEntryNeedSubclass.put(descriptor, !enumEntry.getDeclarations().isEmpty());
|
assert descriptor != null;
|
||||||
super.visitEnumEntry(enumEntry);
|
|
||||||
|
final boolean trivial = enumEntry.getDeclarations().isEmpty();
|
||||||
|
if (!trivial) {
|
||||||
|
enumEntryNeedSubclass.put(descriptor, Boolean.TRUE);
|
||||||
|
|
||||||
|
classStack.push(descriptor);
|
||||||
|
nameStack.push(nameStack.peek() + "$" + descriptor.getName().getName());
|
||||||
|
super.visitEnumEntry(enumEntry);
|
||||||
|
nameStack.pop();
|
||||||
|
classStack.pop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.visitEnumEntry(enumEntry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitClassObject(JetClassObject classObject) {
|
public void visitClassObject(JetClassObject classObject) {
|
||||||
JvmClassName name = recordClassObject(classObject);
|
|
||||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
|
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
|
||||||
assert classDescriptor != null;
|
assert classDescriptor != null;
|
||||||
recordEnclosing(classDescriptor);
|
|
||||||
|
JvmClassName name = JvmClassName.byInternalName(nameStack.peek() + JvmAbi.CLASS_OBJECT_SUFFIX);
|
||||||
|
recordClosure(classObject, classDescriptor, classStack.peek(), name, false);
|
||||||
|
|
||||||
classStack.push(classDescriptor);
|
classStack.push(classDescriptor);
|
||||||
nameStack.push(name.getInternalName());
|
nameStack.push(name.getInternalName());
|
||||||
super.visitClassObject(classObject);
|
super.visitClassObject(classObject);
|
||||||
@@ -341,16 +378,12 @@ public class ClosureAnnotator {
|
|||||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
||||||
// working around a problem with shallow analysis
|
// working around a problem with shallow analysis
|
||||||
if (classDescriptor == null) return;
|
if (classDescriptor == null) return;
|
||||||
recordEnclosing(classDescriptor);
|
|
||||||
|
String name = getName(classDescriptor);
|
||||||
|
recordClosure(declaration, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false);
|
||||||
|
|
||||||
classStack.push(classDescriptor);
|
classStack.push(classDescriptor);
|
||||||
String base = nameStack.peek();
|
nameStack.push(name);
|
||||||
if (classDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
|
|
||||||
nameStack.push(base.isEmpty() ? classDescriptor.getName().getName() : base + '/' + classDescriptor.getName());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nameStack.push(base + '$' + classDescriptor.getName());
|
|
||||||
}
|
|
||||||
recordName(classDescriptor, JvmClassName.byInternalName(nameStack.peek()));
|
|
||||||
super.visitObjectDeclaration(declaration);
|
super.visitObjectDeclaration(declaration);
|
||||||
nameStack.pop();
|
nameStack.pop();
|
||||||
classStack.pop();
|
classStack.pop();
|
||||||
@@ -362,21 +395,23 @@ public class ClosureAnnotator {
|
|||||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, klass);
|
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, klass);
|
||||||
// working around a problem with shallow analysis
|
// working around a problem with shallow analysis
|
||||||
if (classDescriptor == null) return;
|
if (classDescriptor == null) return;
|
||||||
recordEnclosing(classDescriptor);
|
|
||||||
|
String name = getName(classDescriptor);
|
||||||
|
recordClosure(klass, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false);
|
||||||
|
|
||||||
classStack.push(classDescriptor);
|
classStack.push(classDescriptor);
|
||||||
String base = nameStack.peek();
|
nameStack.push(name);
|
||||||
if (classDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
|
|
||||||
nameStack.push(base.isEmpty() ? classDescriptor.getName().getName() : base + '/' + classDescriptor.getName());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nameStack.push(base + '$' + classDescriptor.getName());
|
|
||||||
}
|
|
||||||
recordName(classDescriptor, JvmClassName.byInternalName(nameStack.peek()));
|
|
||||||
super.visitClass(klass);
|
super.visitClass(klass);
|
||||||
nameStack.pop();
|
nameStack.pop();
|
||||||
classStack.pop();
|
classStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getName(ClassDescriptor classDescriptor) {
|
||||||
|
String base = nameStack.peek();
|
||||||
|
return classDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor ? base.isEmpty() ? classDescriptor.getName()
|
||||||
|
.getName() : base + '/' + classDescriptor.getName() : base + '$' + classDescriptor.getName();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
||||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, expression.getObjectDeclaration());
|
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, expression.getObjectDeclaration());
|
||||||
@@ -385,8 +420,10 @@ public class ClosureAnnotator {
|
|||||||
super.visitObjectLiteralExpression(expression);
|
super.visitObjectLiteralExpression(expression);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
recordAnonymousClass(expression.getObjectDeclaration());
|
|
||||||
recordEnclosing(classDescriptor);
|
final String name = inventAnonymousClassName(expression.getObjectDeclaration());
|
||||||
|
recordClosure(expression.getObjectDeclaration(), classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false);
|
||||||
|
|
||||||
classStack.push(classDescriptor);
|
classStack.push(classDescriptor);
|
||||||
nameStack.push(classNameForClassDescriptor(classDescriptor).getInternalName());
|
nameStack.push(classNameForClassDescriptor(classDescriptor).getInternalName());
|
||||||
super.visitObjectLiteralExpression(expression);
|
super.visitObjectLiteralExpression(expression);
|
||||||
@@ -400,11 +437,13 @@ public class ClosureAnnotator {
|
|||||||
(FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression);
|
(FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression);
|
||||||
// working around a problem with shallow analysis
|
// working around a problem with shallow analysis
|
||||||
if (functionDescriptor == null) return;
|
if (functionDescriptor == null) return;
|
||||||
JvmClassName name = recordAnonymousClass(expression);
|
|
||||||
|
String name = inventAnonymousClassName(expression);
|
||||||
ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor);
|
ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor);
|
||||||
recordEnclosing(classDescriptor);
|
recordClosure(expression, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), true);
|
||||||
|
|
||||||
classStack.push(classDescriptor);
|
classStack.push(classDescriptor);
|
||||||
nameStack.push(name.getInternalName());
|
nameStack.push(name);
|
||||||
super.visitFunctionLiteralExpression(expression);
|
super.visitFunctionLiteralExpression(expression);
|
||||||
nameStack.pop();
|
nameStack.pop();
|
||||||
classStack.pop();
|
classStack.pop();
|
||||||
@@ -442,26 +481,16 @@ public class ClosureAnnotator {
|
|||||||
nameStack.pop();
|
nameStack.pop();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JvmClassName name = recordAnonymousClass(function);
|
String name = inventAnonymousClassName(function);
|
||||||
ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor);
|
ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor);
|
||||||
recordEnclosing(classDescriptor);
|
recordClosure(function, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), true);
|
||||||
|
|
||||||
classStack.push(classDescriptor);
|
classStack.push(classDescriptor);
|
||||||
nameStack.push(name.getInternalName());
|
nameStack.push(name);
|
||||||
super.visitNamedFunction(function);
|
super.visitNamedFunction(function);
|
||||||
nameStack.pop();
|
nameStack.pop();
|
||||||
classStack.pop();
|
classStack.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recordName(@NotNull ClassDescriptor classDescriptor, @NotNull JvmClassName name) {
|
|
||||||
JvmClassName old = classNamesForClassDescriptor.put(classDescriptor, name);
|
|
||||||
if (old != null) {
|
|
||||||
throw new IllegalStateException("rewrite at key " + classDescriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public JvmClassName classNameForClassDescriptor(@NotNull ClassDescriptor classDescriptor) {
|
|
||||||
return classNamesForClassDescriptor.get(classDescriptor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,544 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.codegen.context;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.asm4.Type;
|
||||||
|
import org.jetbrains.jet.codegen.*;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
|
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.codegen.JetTypeMapper.OBJECT_TYPE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author max
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
public abstract class CodegenContext {
|
||||||
|
|
||||||
|
public static final CodegenContext STATIC =
|
||||||
|
new CodegenContext(new FakeDescriptorForStaticContext(), OwnerKind.NAMESPACE, null, null, null, null) {
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ROOT";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private static final StackValue local1 = StackValue.local(1, OBJECT_TYPE);
|
||||||
|
@NotNull
|
||||||
|
private final DeclarationDescriptor contextDescriptor;
|
||||||
|
|
||||||
|
private final OwnerKind contextKind;
|
||||||
|
@Nullable
|
||||||
|
private final CodegenContext parentContext;
|
||||||
|
private final ClassDescriptor thisDescriptor;
|
||||||
|
|
||||||
|
public final MutableClosure closure;
|
||||||
|
|
||||||
|
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
||||||
|
|
||||||
|
protected StackValue outerExpression;
|
||||||
|
private final LocalLookup enclosingLocalLookup;
|
||||||
|
|
||||||
|
public CodegenContext(
|
||||||
|
@NotNull DeclarationDescriptor contextDescriptor,
|
||||||
|
OwnerKind contextKind,
|
||||||
|
@Nullable CodegenContext parentContext,
|
||||||
|
@Nullable MutableClosure closure,
|
||||||
|
@Nullable ClassDescriptor thisDescriptor,
|
||||||
|
@Nullable LocalLookup expressionCodegen
|
||||||
|
) {
|
||||||
|
this.contextDescriptor = contextDescriptor;
|
||||||
|
this.contextKind = contextKind;
|
||||||
|
this.parentContext = parentContext;
|
||||||
|
this.closure = closure;
|
||||||
|
this.thisDescriptor = thisDescriptor;
|
||||||
|
this.enclosingLocalLookup = expressionCodegen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final ClassDescriptor getThisDescriptor() {
|
||||||
|
if (thisDescriptor == null) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
return thisDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean hasThisDescriptor() {
|
||||||
|
return thisDescriptor != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeclarationDescriptor getClassOrNamespaceDescriptor() {
|
||||||
|
CodegenContext c = this;
|
||||||
|
while (true) {
|
||||||
|
assert c != null;
|
||||||
|
DeclarationDescriptor contextDescriptor = c.getContextDescriptor();
|
||||||
|
if (!(contextDescriptor instanceof ClassDescriptor) && !(contextDescriptor instanceof NamespaceDescriptor)) {
|
||||||
|
c = c.getParentContext();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return contextDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallableDescriptor getReceiverDescriptor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue getOuterExpression(@Nullable StackValue prefix, boolean ignoreNoOuter) {
|
||||||
|
if (outerExpression == null) {
|
||||||
|
if (ignoreNoOuter) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closure.setCaptureThis();
|
||||||
|
return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public DeclarationDescriptor getContextDescriptor() {
|
||||||
|
return contextDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OwnerKind getContextKind() {
|
||||||
|
return contextKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoNamespace(NamespaceDescriptor descriptor) {
|
||||||
|
return new NamespaceContext(descriptor, this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoNamespacePart(String delegateTo, NamespaceDescriptor descriptor) {
|
||||||
|
return new NamespaceContext(descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
|
||||||
|
return new ClassContext(state.getInjector().getJetTypeMapper(), descriptor, kind, this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoAnonymousClass(
|
||||||
|
ClassDescriptor descriptor,
|
||||||
|
ExpressionCodegen expressionCodegen
|
||||||
|
) {
|
||||||
|
final JetTypeMapper typeMapper = expressionCodegen.getState().getInjector().getJetTypeMapper();
|
||||||
|
return new AnonymousClassContext(typeMapper, descriptor, OwnerKind.IMPLEMENTATION, this,
|
||||||
|
expressionCodegen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||||
|
return new MethodContext(descriptor, getContextKind(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
|
||||||
|
if (descriptor == null) {
|
||||||
|
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
||||||
|
.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(),
|
||||||
|
Visibilities.PUBLIC);
|
||||||
|
}
|
||||||
|
return new ConstructorContext(descriptor, getContextKind(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoScript(@NotNull ScriptDescriptor script, @NotNull ClassDescriptor classDescriptor) {
|
||||||
|
return new ScriptContext(script, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoClosure(
|
||||||
|
FunctionDescriptor funDescriptor,
|
||||||
|
ExpressionCodegen expressionCodegen
|
||||||
|
) {
|
||||||
|
final JetTypeMapper typeMapper = expressionCodegen.getState().getInjector().getJetTypeMapper();
|
||||||
|
return new ClosureContext(typeMapper, funDescriptor,
|
||||||
|
typeMapper.getClosureAnnotator().classDescriptorForFunctionDescriptor(funDescriptor),
|
||||||
|
this, expressionCodegen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameMap prepareFrame(JetTypeMapper mapper) {
|
||||||
|
FrameMap frameMap = new FrameMap();
|
||||||
|
|
||||||
|
if (getContextKind() != OwnerKind.NAMESPACE) {
|
||||||
|
frameMap.enterTemp(OBJECT_TYPE); // 0 slot for this
|
||||||
|
}
|
||||||
|
|
||||||
|
CallableDescriptor receiverDescriptor = getReceiverDescriptor();
|
||||||
|
if (receiverDescriptor != null) {
|
||||||
|
Type type = mapper.mapType(receiverDescriptor.getReceiverParameter().getType(), MapTypeMode.VALUE);
|
||||||
|
frameMap.enterTemp(type); // Next slot for receiver
|
||||||
|
}
|
||||||
|
|
||||||
|
return frameMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public CodegenContext getParentContext() {
|
||||||
|
return parentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassDescriptor getEnclosingClass() {
|
||||||
|
CodegenContext cur = getParentContext();
|
||||||
|
while (cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor)) {
|
||||||
|
cur = cur.getParentContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur == null ? null : (ClassDescriptor) cur.getContextDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeclarationDescriptor getAccessor(DeclarationDescriptor descriptor) {
|
||||||
|
if (accessors == null) {
|
||||||
|
accessors = new HashMap<DeclarationDescriptor, DeclarationDescriptor>();
|
||||||
|
}
|
||||||
|
descriptor = descriptor.getOriginal();
|
||||||
|
DeclarationDescriptor accessor = accessors.get(descriptor);
|
||||||
|
if (accessor != null) {
|
||||||
|
return accessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor instanceof SimpleFunctionDescriptor) {
|
||||||
|
accessor = new AccessorForFunctionDescriptor(descriptor, contextDescriptor, accessors.size());
|
||||||
|
}
|
||||||
|
else if (descriptor instanceof PropertyDescriptor) {
|
||||||
|
accessor = new AccessorForPropertyDescriptor((PropertyDescriptor) descriptor, contextDescriptor, accessors.size());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
accessors.put(descriptor, accessor);
|
||||||
|
return accessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue getReceiverExpression(JetTypeMapper typeMapper) {
|
||||||
|
assert getReceiverDescriptor() != null;
|
||||||
|
Type asmType = typeMapper.mapType(getReceiverDescriptor().getReceiverParameter().getType(), MapTypeMode.VALUE);
|
||||||
|
return hasThisDescriptor() ? StackValue.local(1, asmType) : StackValue.local(0, asmType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean isStatic();
|
||||||
|
|
||||||
|
public void copyAccessors(Map<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
|
if (accessors != null) {
|
||||||
|
if (this.accessors == null) {
|
||||||
|
this.accessors = new HashMap<DeclarationDescriptor, DeclarationDescriptor>();
|
||||||
|
}
|
||||||
|
this.accessors.putAll(accessors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initOuterExpression(JetTypeMapper typeMapper, ClassDescriptor classDescriptor) {
|
||||||
|
final ClassDescriptor enclosingClass = getEnclosingClass();
|
||||||
|
outerExpression = enclosingClass != null
|
||||||
|
? StackValue
|
||||||
|
.field(typeMapper.mapType(enclosingClass.getDefaultType(), MapTypeMode.VALUE), typeMapper.getJvmClassName(
|
||||||
|
classDescriptor), CodegenUtil.THIS$0,
|
||||||
|
false)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue lookupInContext(DeclarationDescriptor d, StackValue result, GenerationState state, boolean ignoreNoOuter) {
|
||||||
|
final MutableClosure top = closure;
|
||||||
|
if (top != null) {
|
||||||
|
EnclosedValueDescriptor answer = closure.getCaptureVariables().get(d);
|
||||||
|
if (answer != null) {
|
||||||
|
StackValue innerValue = answer.getInnerValue();
|
||||||
|
return result == null ? innerValue : StackValue.composed(result, innerValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) {
|
||||||
|
if (aCase.isCase(d, state)) {
|
||||||
|
StackValue innerValue = aCase.innerValue(d, enclosingLocalLookup, state, closure);
|
||||||
|
if (innerValue == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return result == null ? innerValue : StackValue.composed(result, innerValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StackValue outer = getOuterExpression(null, ignoreNoOuter);
|
||||||
|
result = result == null ? outer : StackValue.composed(result, outer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentContext != null ? parentContext.lookupInContext(d, result, state, ignoreNoOuter) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Map<DeclarationDescriptor, DeclarationDescriptor> getAccessors() {
|
||||||
|
return accessors == null ? Collections.<DeclarationDescriptor, DeclarationDescriptor>emptyMap() : accessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FakeDescriptorForStaticContext implements DeclarationDescriptor {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public DeclarationDescriptor getOriginal() {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeclarationDescriptor getContainingDeclaration() {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeclarationDescriptor substitute(TypeSubstitutor substitutor) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AnnotationDescriptor> getAnnotations() {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Name getName() {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract static class ReceiverContext extends CodegenContext {
|
||||||
|
final CallableDescriptor receiverDescriptor;
|
||||||
|
|
||||||
|
public ReceiverContext(
|
||||||
|
CallableDescriptor contextDescriptor,
|
||||||
|
OwnerKind contextKind,
|
||||||
|
CodegenContext parentContext,
|
||||||
|
@Nullable MutableClosure closure,
|
||||||
|
ClassDescriptor thisDescriptor,
|
||||||
|
@Nullable LocalLookup localLookup
|
||||||
|
) {
|
||||||
|
super(contextDescriptor, contextKind, parentContext, closure, thisDescriptor, localLookup);
|
||||||
|
receiverDescriptor = contextDescriptor.getReceiverParameter().exists() ? contextDescriptor : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CallableDescriptor getReceiverDescriptor() {
|
||||||
|
return receiverDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MethodContext extends ReceiverContext {
|
||||||
|
public MethodContext(
|
||||||
|
@NotNull FunctionDescriptor contextType,
|
||||||
|
OwnerKind contextKind,
|
||||||
|
CodegenContext parentContext
|
||||||
|
) {
|
||||||
|
super(contextType instanceof PropertyAccessorDescriptor
|
||||||
|
? ((PropertyAccessorDescriptor) contextType).getCorrespondingProperty()
|
||||||
|
: contextType, contextKind, parentContext, null,
|
||||||
|
parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackValue lookupInContext(DeclarationDescriptor d, StackValue result, GenerationState state, boolean ignoreNoOuter) {
|
||||||
|
if (getContextDescriptor() == d) {
|
||||||
|
return StackValue.local(0, JetTypeMapper.OBJECT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return getParentContext().lookupInContext(d, result, state, ignoreNoOuter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return getParentContext().isStatic();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return getParentContext().getOuterExpression(prefix, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Method: " + getContextDescriptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConstructorContext extends MethodContext {
|
||||||
|
public ConstructorContext(
|
||||||
|
ConstructorDescriptor contextDescriptor,
|
||||||
|
OwnerKind kind,
|
||||||
|
CodegenContext parent
|
||||||
|
) {
|
||||||
|
super(contextDescriptor, kind, parent);
|
||||||
|
|
||||||
|
final ClassDescriptor type = getEnclosingClass();
|
||||||
|
outerExpression = type != null ? local1 : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) {
|
||||||
|
return outerExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Constructor: " + getContextDescriptor().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ScriptContext extends CodegenContext {
|
||||||
|
@NotNull
|
||||||
|
private final ScriptDescriptor scriptDescriptor;
|
||||||
|
|
||||||
|
public ScriptContext(
|
||||||
|
@NotNull ScriptDescriptor scriptDescriptor,
|
||||||
|
@NotNull ClassDescriptor contextDescriptor,
|
||||||
|
@NotNull OwnerKind contextKind,
|
||||||
|
@Nullable CodegenContext parentContext,
|
||||||
|
@Nullable MutableClosure closure
|
||||||
|
) {
|
||||||
|
super(contextDescriptor, contextKind, parentContext, closure, contextDescriptor, null);
|
||||||
|
|
||||||
|
this.scriptDescriptor = scriptDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ScriptDescriptor getScriptDescriptor() {
|
||||||
|
return scriptDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ClassContext extends CodegenContext {
|
||||||
|
public ClassContext(
|
||||||
|
JetTypeMapper typeMapper,
|
||||||
|
ClassDescriptor contextDescriptor,
|
||||||
|
OwnerKind contextKind,
|
||||||
|
CodegenContext parentContext,
|
||||||
|
LocalLookup localLookup
|
||||||
|
) {
|
||||||
|
super(contextDescriptor, contextKind, parentContext, (MutableClosure) typeMapper.getCalculatedClosure(contextDescriptor),
|
||||||
|
contextDescriptor,
|
||||||
|
localLookup);
|
||||||
|
initOuterExpression(typeMapper, contextDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnonymousClassContext extends CodegenContext {
|
||||||
|
public AnonymousClassContext(
|
||||||
|
JetTypeMapper typeMapper,
|
||||||
|
ClassDescriptor contextDescriptor,
|
||||||
|
OwnerKind contextKind,
|
||||||
|
CodegenContext parentContext,
|
||||||
|
LocalLookup localLookup
|
||||||
|
) {
|
||||||
|
super(contextDescriptor, contextKind, parentContext, (MutableClosure) typeMapper.getCalculatedClosure(contextDescriptor),
|
||||||
|
contextDescriptor,
|
||||||
|
localLookup);
|
||||||
|
initOuterExpression(typeMapper, contextDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Anonymous: " + getThisDescriptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ClosureContext extends ReceiverContext {
|
||||||
|
private final ClassDescriptor classDescriptor;
|
||||||
|
|
||||||
|
public ClosureContext(
|
||||||
|
JetTypeMapper typeMapper,
|
||||||
|
FunctionDescriptor contextDescriptor,
|
||||||
|
ClassDescriptor classDescriptor,
|
||||||
|
CodegenContext parentContext,
|
||||||
|
LocalLookup localLookup
|
||||||
|
) {
|
||||||
|
super(contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext,
|
||||||
|
(MutableClosure) typeMapper.getCalculatedClosure(classDescriptor), classDescriptor, localLookup);
|
||||||
|
this.classDescriptor = classDescriptor;
|
||||||
|
|
||||||
|
initOuterExpression(typeMapper, classDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public DeclarationDescriptor getContextDescriptor() {
|
||||||
|
return classDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Closure: " + classDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NamespaceContext extends CodegenContext {
|
||||||
|
public NamespaceContext(NamespaceDescriptor contextDescriptor, CodegenContext parent, OwnerKind kind) {
|
||||||
|
super(contextDescriptor, kind != null ? kind : OwnerKind.NAMESPACE, parent, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Namespace: " + getContextDescriptor().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
-7
@@ -17,19 +17,23 @@
|
|||||||
/*
|
/*
|
||||||
* @author max
|
* @author max
|
||||||
*/
|
*/
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen.context;
|
||||||
|
|
||||||
|
import org.jetbrains.asm4.Type;
|
||||||
|
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||||
|
import org.jetbrains.jet.codegen.GenerationState;
|
||||||
|
import org.jetbrains.jet.codegen.StackValue;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
|
||||||
public class EnclosedValueDescriptor {
|
public final class EnclosedValueDescriptor {
|
||||||
private final DeclarationDescriptor descriptor;
|
private final DeclarationDescriptor descriptor;
|
||||||
private final StackValue innerValue;
|
private final StackValue innerValue;
|
||||||
private final StackValue outerValue;
|
private final Type type;
|
||||||
|
|
||||||
public EnclosedValueDescriptor(DeclarationDescriptor descriptor, StackValue innerValue, StackValue outerValue) {
|
public EnclosedValueDescriptor(DeclarationDescriptor descriptor, StackValue innerValue, Type type) {
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
this.innerValue = innerValue;
|
this.innerValue = innerValue;
|
||||||
this.outerValue = outerValue;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeclarationDescriptor getDescriptor() {
|
public DeclarationDescriptor getDescriptor() {
|
||||||
@@ -40,7 +44,18 @@ public class EnclosedValueDescriptor {
|
|||||||
return innerValue;
|
return innerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue getOuterValue() {
|
public Type getType() {
|
||||||
return outerValue;
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue getOuterValue(ExpressionCodegen expressionCodegen) {
|
||||||
|
final GenerationState state = expressionCodegen.getState();
|
||||||
|
for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) {
|
||||||
|
if (aCase.isCase(descriptor, state)) {
|
||||||
|
return aCase.outerValue(this, expressionCodegen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.codegen.context;
|
||||||
|
|
||||||
|
import org.jetbrains.asm4.Type;
|
||||||
|
import org.jetbrains.jet.codegen.*;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
public interface LocalLookup {
|
||||||
|
boolean lookupLocal(DeclarationDescriptor descriptor);
|
||||||
|
|
||||||
|
enum LocalLookupCase {
|
||||||
|
VAR {
|
||||||
|
@Override
|
||||||
|
public boolean isCase(DeclarationDescriptor d, GenerationState state) {
|
||||||
|
return (d instanceof VariableDescriptor) && !(d instanceof PropertyDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackValue innerValue(DeclarationDescriptor d, LocalLookup localLookup, GenerationState state, MutableClosure closure) {
|
||||||
|
VariableDescriptor vd = (VariableDescriptor) d;
|
||||||
|
|
||||||
|
final boolean idx = localLookup != null && localLookup.lookupLocal(vd);
|
||||||
|
if (!idx) return null;
|
||||||
|
|
||||||
|
final Type sharedVarType = state.getInjector().getJetTypeMapper().getSharedVarType(vd);
|
||||||
|
Type localType = state.getInjector().getJetTypeMapper().mapType(vd.getType(), MapTypeMode.VALUE);
|
||||||
|
final Type type = sharedVarType != null ? sharedVarType : localType;
|
||||||
|
|
||||||
|
final String fieldName = "$" + vd.getName();
|
||||||
|
StackValue innerValue = sharedVarType != null
|
||||||
|
? StackValue.fieldForSharedVar(localType, closure.getClassName(), fieldName)
|
||||||
|
: StackValue.field(type, closure.getClassName(), fieldName, false);
|
||||||
|
|
||||||
|
closure.recordField(fieldName, type);
|
||||||
|
closure.captureVariable(new EnclosedValueDescriptor(d, innerValue, type));
|
||||||
|
|
||||||
|
return innerValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
LOCAL_NAMED_FUNCTION {
|
||||||
|
@Override
|
||||||
|
public boolean isCase(DeclarationDescriptor d, GenerationState state) {
|
||||||
|
return CodegenUtil.isNamedFun(d, state.getBindingContext()) && (d.getContainingDeclaration() instanceof FunctionDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackValue innerValue(DeclarationDescriptor d, LocalLookup localLookup, GenerationState state, MutableClosure closure) {
|
||||||
|
FunctionDescriptor vd = (FunctionDescriptor) d;
|
||||||
|
|
||||||
|
final boolean idx = localLookup.lookupLocal(vd);
|
||||||
|
if (!idx) return null;
|
||||||
|
|
||||||
|
JetElement expression = (JetElement) BindingContextUtils.callableDescriptorToDeclaration(state.getBindingContext(), vd);
|
||||||
|
JvmClassName cn = state.getInjector().getJetTypeMapper().getClosureAnnotator().classNameForAnonymousClass(expression);
|
||||||
|
Type localType = cn.getAsmType();
|
||||||
|
|
||||||
|
final String fieldName = "$" + vd.getName();
|
||||||
|
StackValue innerValue = StackValue.field(localType, closure.getClassName(), fieldName, false);
|
||||||
|
|
||||||
|
closure.recordField(fieldName, localType);
|
||||||
|
closure.captureVariable(new EnclosedValueDescriptor(d, innerValue, localType));
|
||||||
|
|
||||||
|
return innerValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
RECEIVER {
|
||||||
|
@Override
|
||||||
|
public boolean isCase(DeclarationDescriptor d, GenerationState state) {
|
||||||
|
return d instanceof FunctionDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackValue innerValue(
|
||||||
|
DeclarationDescriptor d,
|
||||||
|
LocalLookup enclosingLocalLookup,
|
||||||
|
GenerationState state,
|
||||||
|
MutableClosure closure
|
||||||
|
) {
|
||||||
|
if (closure.getEnclosingReceiverDescriptor() != d) return null;
|
||||||
|
|
||||||
|
final JetType receiverType = ((CallableDescriptor) d).getReceiverParameter().getType();
|
||||||
|
Type type = state.getInjector().getJetTypeMapper().mapType(receiverType, MapTypeMode.VALUE);
|
||||||
|
StackValue innerValue = StackValue.field(type, closure.getClassName(), CodegenUtil.RECEIVER$0, false);
|
||||||
|
closure.setCaptureReceiver();
|
||||||
|
|
||||||
|
return innerValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackValue outerValue(EnclosedValueDescriptor d, ExpressionCodegen expressionCodegen) {
|
||||||
|
CallableDescriptor descriptor = (FunctionDescriptor) d.getDescriptor();
|
||||||
|
return StackValue.local(descriptor.getExpectedThisObject().exists() ? 1 : 0, d.getType());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public abstract boolean isCase(DeclarationDescriptor d, GenerationState state);
|
||||||
|
|
||||||
|
public abstract StackValue innerValue(
|
||||||
|
DeclarationDescriptor d,
|
||||||
|
LocalLookup localLookup,
|
||||||
|
GenerationState state,
|
||||||
|
MutableClosure closure
|
||||||
|
);
|
||||||
|
|
||||||
|
public StackValue outerValue(EnclosedValueDescriptor d, ExpressionCodegen expressionCodegen) {
|
||||||
|
final int idx = expressionCodegen.lookupLocalIndex(d.getDescriptor());
|
||||||
|
assert idx != -1;
|
||||||
|
|
||||||
|
return StackValue.local(idx, d.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.codegen.context;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Pair;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.asm4.Type;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
public final class MutableClosure implements CalculatedClosure {
|
||||||
|
private final JetDelegatorToSuperCall superCall;
|
||||||
|
|
||||||
|
private final ClassDescriptor enclosingClass;
|
||||||
|
private final CallableDescriptor enclosingReceiverDescriptor;
|
||||||
|
|
||||||
|
private final JvmClassName name;
|
||||||
|
|
||||||
|
private boolean captureThis;
|
||||||
|
private boolean captureReceiver;
|
||||||
|
|
||||||
|
private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables;
|
||||||
|
private List<Pair<String, Type>> recordedFields;
|
||||||
|
|
||||||
|
MutableClosure(
|
||||||
|
JetDelegatorToSuperCall superCall,
|
||||||
|
ClassDescriptor enclosingClass,
|
||||||
|
JvmClassName className,
|
||||||
|
CallableDescriptor enclosingReceiverDescriptor
|
||||||
|
) {
|
||||||
|
this.superCall = superCall;
|
||||||
|
this.enclosingClass = enclosingClass;
|
||||||
|
this.enclosingReceiverDescriptor = enclosingReceiverDescriptor;
|
||||||
|
this.name = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ClassDescriptor getEnclosingClass() {
|
||||||
|
return enclosingClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public JvmClassName getClassName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetDelegatorToSuperCall getSuperCall() {
|
||||||
|
return superCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassDescriptor getCaptureThis() {
|
||||||
|
return captureThis ? enclosingClass : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCaptureThis() {
|
||||||
|
this.captureThis = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassifierDescriptor getCaptureReceiver() {
|
||||||
|
return captureReceiver
|
||||||
|
? enclosingReceiverDescriptor.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor()
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCaptureReceiver() {
|
||||||
|
if (enclosingReceiverDescriptor == null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
this.captureReceiver = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables() {
|
||||||
|
return captureVariables != null ? captureVariables : Collections.<DeclarationDescriptor, EnclosedValueDescriptor>emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<Pair<String, Type>> getRecordedFields() {
|
||||||
|
return recordedFields != null ? recordedFields : Collections.<Pair<String, Type>>emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recordField(String name, Type type) {
|
||||||
|
if (recordedFields == null) {
|
||||||
|
recordedFields = new LinkedList<Pair<String, Type>>();
|
||||||
|
}
|
||||||
|
recordedFields.add(new Pair<String, Type>(name, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void captureVariable(EnclosedValueDescriptor value) {
|
||||||
|
if (captureVariables == null) {
|
||||||
|
captureVariables = new HashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
||||||
|
}
|
||||||
|
captureVariables.put(value.getDescriptor(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallableDescriptor getEnclosingReceiverDescriptor() {
|
||||||
|
return enclosingReceiverDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -18,13 +18,15 @@ package org.jetbrains.jet.codegen.signature;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Stepan Koltsov
|
* @author Stepan Koltsov
|
||||||
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public enum JvmMethodParameterKind {
|
public enum JvmMethodParameterKind {
|
||||||
VALUE,
|
VALUE,
|
||||||
THIS,
|
THIS,
|
||||||
THIS0,
|
OUTER,
|
||||||
RECEIVER,
|
RECEIVER,
|
||||||
SHARED_VAR,
|
SHARED_VAR,
|
||||||
ENUM_NAME,
|
ENUM_NAME,
|
||||||
ENUM_ORDINAL,
|
ENUM_ORDINAL,
|
||||||
|
SUPER_CALL_PARAM
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
|||||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||||
import org.jetbrains.jet.codegen.BuiltinToJavaTypesMapping;
|
import org.jetbrains.jet.codegen.BuiltinToJavaTypesMapping;
|
||||||
import org.jetbrains.jet.codegen.ClassBuilderMode;
|
import org.jetbrains.jet.codegen.ClassBuilderMode;
|
||||||
import org.jetbrains.jet.codegen.ClosureAnnotator;
|
import org.jetbrains.jet.codegen.context.ClosureAnnotator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.ScriptCodegen;
|
|||||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||||
import org.jetbrains.jet.codegen.MemberCodegen;
|
import org.jetbrains.jet.codegen.MemberCodegen;
|
||||||
import org.jetbrains.jet.codegen.ClosureAnnotator;
|
import org.jetbrains.jet.codegen.context.ClosureAnnotator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
|
|||||||
@@ -28,30 +28,36 @@ public class ArrayGenTest extends CodegenTestCase {
|
|||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testKt238 () throws Exception {
|
public void testKt238() throws Exception {
|
||||||
blackBoxFile("regressions/kt238.jet");
|
blackBoxFile("regressions/kt238.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testKt326 () throws Exception {
|
public void testKt326() throws Exception {
|
||||||
// blackBoxFile("regressions/kt326.jet");
|
// blackBoxFile("regressions/kt326.jet");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testKt779 () throws Exception {
|
public void testKt779() throws Exception {
|
||||||
blackBoxFile("regressions/kt779.jet");
|
blackBoxFile("regressions/kt779.jet");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateMultiInt () throws Exception {
|
public void testCreateMultiInt() throws Exception {
|
||||||
loadText("fun foo() = Array<Array<Int>> (5, { Array<Int>(it, {239}) })");
|
loadText("fun foo() = Array<Array<Int>> (5, { Array<Int>(it, {239}) })");
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
Integer[][] invoke = (Integer[][]) foo.invoke(null);
|
try {
|
||||||
assertEquals(invoke[2].length, 2);
|
Integer[][] invoke = (Integer[][]) foo.invoke(null);
|
||||||
assertEquals(invoke[4].length, 4);
|
assertEquals(invoke[2].length, 2);
|
||||||
assertEquals(invoke[4][2].intValue(), 239);
|
assertEquals(invoke[4].length, 4);
|
||||||
|
assertEquals(invoke[4][2].intValue(), 239);
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
System.out.println(generateToText());
|
||||||
|
throw ((e instanceof RuntimeException)) ? (RuntimeException) e : new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateMultiIntNullable () throws Exception {
|
public void testCreateMultiIntNullable() throws Exception {
|
||||||
loadText("fun foo() = Array<Array<Int?>> (5, { arrayOfNulls<Int>(it) })");
|
loadText("fun foo() = Array<Array<Int?>> (5, { arrayOfNulls<Int>(it) })");
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
Integer[][] invoke = (Integer[][]) foo.invoke(null);
|
Integer[][] invoke = (Integer[][]) foo.invoke(null);
|
||||||
@@ -59,7 +65,7 @@ public class ArrayGenTest extends CodegenTestCase {
|
|||||||
assertEquals(invoke[4].length, 4);
|
assertEquals(invoke[4].length, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateMultiString () throws Exception {
|
public void testCreateMultiString() throws Exception {
|
||||||
loadText("fun foo() = Array<Array<String>> (5, { Array<String>(0,{\"\"}) })");
|
loadText("fun foo() = Array<Array<String>> (5, { Array<String>(0,{\"\"}) })");
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
Object invoke = foo.invoke(null);
|
Object invoke = foo.invoke(null);
|
||||||
@@ -67,16 +73,16 @@ public class ArrayGenTest extends CodegenTestCase {
|
|||||||
assertTrue(invoke instanceof Object[]);
|
assertTrue(invoke instanceof Object[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateMultiGenerics () throws Exception {
|
public void testCreateMultiGenerics() throws Exception {
|
||||||
// loadText("class L<T>() { val a = Array<T?>(5) } fun foo() = L<Int>.a");
|
// loadText("class L<T>() { val a = Array<T?>(5) } fun foo() = L<Int>.a");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
// Method foo = generateFunction();
|
// Method foo = generateFunction();
|
||||||
// Object invoke = foo.invoke(null);
|
// Object invoke = foo.invoke(null);
|
||||||
// System.out.println(invoke.getClass());
|
// System.out.println(invoke.getClass());
|
||||||
// assertTrue(invoke.getClass() == Object[].class);
|
// assertTrue(invoke.getClass() == Object[].class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIntGenerics () throws Exception {
|
public void testIntGenerics() throws Exception {
|
||||||
loadText("class L<T>(var a : T) {} fun foo() = L<Int>(5).a");
|
loadText("class L<T>(var a : T) {} fun foo() = L<Int>(5).a");
|
||||||
//System.out.println(generateToText());
|
//System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
@@ -85,221 +91,222 @@ public class ArrayGenTest extends CodegenTestCase {
|
|||||||
assertTrue(invoke instanceof Integer);
|
assertTrue(invoke instanceof Integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIterator () throws Exception {
|
public void testIterator() throws Exception {
|
||||||
loadText("fun box() { val x = Array<Int>(5, { it } ).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = Array<Int>(5, { it } ).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIterator () throws Exception {
|
public void testPrimitiveIterator() throws Exception {
|
||||||
loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.nextByte()) } }");
|
loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.nextByte()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIteratorByte () throws Exception {
|
public void testPrimitiveIteratorByte() throws Exception {
|
||||||
loadText("fun box() { for(x in ByteArray(5)) { java.lang.System.out?.println(x) } }");
|
loadText("fun box() { for(x in ByteArray(5)) { java.lang.System.out?.println(x) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIteratorShort () throws Exception {
|
public void testPrimitiveIteratorShort() throws Exception {
|
||||||
loadText("fun box() { for(x in ShortArray(5)) { java.lang.System.out?.println(x) } }");
|
loadText("fun box() { for(x in ShortArray(5)) { java.lang.System.out?.println(x) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIteratorInt () throws Exception {
|
public void testPrimitiveIteratorInt() throws Exception {
|
||||||
loadText("fun box() { for(x in IntArray(5)) { java.lang.System.out?.println(x) } }");
|
loadText("fun box() { for(x in IntArray(5)) { java.lang.System.out?.println(x) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIteratorLong () throws Exception {
|
public void testPrimitiveIteratorLong() throws Exception {
|
||||||
loadText("fun box() { for(x in LongArray(5)) { java.lang.System.out?.println(x) } }");
|
loadText("fun box() { for(x in LongArray(5)) { java.lang.System.out?.println(x) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIteratorFloat () throws Exception {
|
public void testPrimitiveIteratorFloat() throws Exception {
|
||||||
loadText("fun box() { for(x in FloatArray(5)) { java.lang.System.out?.println(x) } }");
|
loadText("fun box() { for(x in FloatArray(5)) { java.lang.System.out?.println(x) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIteratorDouble () throws Exception {
|
public void testPrimitiveIteratorDouble() throws Exception {
|
||||||
loadText("fun box() { for(x in DoubleArray(5)) { java.lang.System.out?.println(x) } }");
|
loadText("fun box() { for(x in DoubleArray(5)) { java.lang.System.out?.println(x) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIteratorChar () throws Exception {
|
public void testPrimitiveIteratorChar() throws Exception {
|
||||||
loadText("fun box() { for(x in CharArray(5)) { java.lang.System.out?.println(x) } }");
|
loadText("fun box() { for(x in CharArray(5)) { java.lang.System.out?.println(x) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIteratorBoolean () throws Exception {
|
public void testPrimitiveIteratorBoolean() throws Exception {
|
||||||
loadText("fun box() { for(x in BooleanArray(5)) { java.lang.System.out?.println(x) } }");
|
loadText("fun box() { for(x in BooleanArray(5)) { java.lang.System.out?.println(x) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLongIterator () throws Exception {
|
public void testLongIterator() throws Exception {
|
||||||
loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.nextLong()) } }");
|
loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.nextLong()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCharIterator () throws Exception {
|
public void testCharIterator() throws Exception {
|
||||||
loadText("fun box() { val x = CharArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = CharArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testByteIterator () throws Exception {
|
public void testByteIterator() throws Exception {
|
||||||
loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testShortIterator () throws Exception {
|
public void testShortIterator() throws Exception {
|
||||||
loadText("fun box() { val x = ShortArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = ShortArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIntIterator () throws Exception {
|
public void testIntIterator() throws Exception {
|
||||||
loadText("fun box() { val x = IntArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = IntArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLongIterator2 () throws Exception {
|
public void testLongIterator2() throws Exception {
|
||||||
loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFloatIterator () throws Exception {
|
public void testFloatIterator() throws Exception {
|
||||||
loadText("fun box() { val x = FloatArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = FloatArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDoubleIterator () throws Exception {
|
public void testDoubleIterator() throws Exception {
|
||||||
loadText("fun box() { val x = ShortArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = ShortArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBooleanIterator () throws Exception {
|
public void testBooleanIterator() throws Exception {
|
||||||
loadText("fun box() { val x = BooleanArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = BooleanArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testArrayIndices () throws Exception {
|
public void testArrayIndices() throws Exception {
|
||||||
loadText("fun box() { val x = Array<Int>(5, {it}).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText(
|
||||||
// System.out.println(generateToText());
|
"fun box() { val x = Array<Int>(5, {it}).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCharIndices () throws Exception {
|
public void testCharIndices() throws Exception {
|
||||||
loadText("fun box() { val x = CharArray(5).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
loadText("fun box() { val x = CharArray(5).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
foo.invoke(null);
|
foo.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCollectionPlusAssign () throws Exception {
|
public void testCollectionPlusAssign() throws Exception {
|
||||||
blackBoxFile("regressions/kt33.jet");
|
blackBoxFile("regressions/kt33.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testArrayPlusAssign () throws Exception {
|
public void testArrayPlusAssign() throws Exception {
|
||||||
loadText("fun box() : Int { val s = IntArray(1); s [0] = 5; s[0] += 7; return s[0] }");
|
loadText("fun box() : Int { val s = IntArray(1); s [0] = 5; s[0] += 7; return s[0] }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction();
|
Method foo = generateFunction();
|
||||||
assertTrue((Integer)foo.invoke(null) == 12);
|
assertTrue((Integer) foo.invoke(null) == 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCollectionAssignGetMultiIndex () throws Exception {
|
public void testCollectionAssignGetMultiIndex() throws Exception {
|
||||||
loadText("import java.util.ArrayList\n" +
|
loadText("import java.util.ArrayList\n" +
|
||||||
"fun box() : String { val s = ArrayList<String>(1); s.add(\"\"); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[2,-2] }\n" +
|
"fun box() : String { val s = ArrayList<String>(1); s.add(\"\"); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[2,-2] }\n" +
|
||||||
"fun ArrayList<String>.get(index1: Int, index2 : Int) = this[index1+index2]!!\n" +
|
"fun ArrayList<String>.get(index1: Int, index2 : Int) = this[index1+index2]!!\n" +
|
||||||
"fun ArrayList<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n");
|
"fun ArrayList<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction("box");
|
|
||||||
assertTrue(foo.invoke(null).equals("57"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testArrayGetAssignMultiIndex () throws Exception {
|
|
||||||
loadText(
|
|
||||||
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[-3,3] }\n" +
|
|
||||||
"fun Array<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
|
|
||||||
"fun Array<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }");
|
|
||||||
// System.out.println(generateToText());
|
|
||||||
Method foo = generateFunction("box");
|
Method foo = generateFunction("box");
|
||||||
assertTrue(foo.invoke(null).equals("57"));
|
assertTrue(foo.invoke(null).equals("57"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCollectionGetMultiIndex () throws Exception {
|
public void testArrayGetAssignMultiIndex() throws Exception {
|
||||||
loadText("import java.util.ArrayList\n" +
|
|
||||||
"fun box() : String { val s = ArrayList<String>(1); s.add(\"\"); s [1, -1] = \"5\"; return s[2, -2] }\n" +
|
|
||||||
"fun ArrayList<String>.get(index1: Int, index2 : Int) = this[index1+index2]!!\n" +
|
|
||||||
"fun ArrayList<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n");
|
|
||||||
// System.out.println(generateToText());
|
|
||||||
Method foo = generateFunction("box");
|
|
||||||
assertTrue(foo.invoke(null).equals("5"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testArrayGetMultiIndex () throws Exception {
|
|
||||||
loadText(
|
loadText(
|
||||||
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; return s[-2, 2] }\n" +
|
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[-3,3] }\n" +
|
||||||
"fun Array<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
|
"fun Array<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
|
||||||
"fun Array<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }");
|
"fun Array<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
|
Method foo = generateFunction("box");
|
||||||
|
assertTrue(foo.invoke(null).equals("57"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCollectionGetMultiIndex() throws Exception {
|
||||||
|
loadText("import java.util.ArrayList\n" +
|
||||||
|
"fun box() : String { val s = ArrayList<String>(1); s.add(\"\"); s [1, -1] = \"5\"; return s[2, -2] }\n" +
|
||||||
|
"fun ArrayList<String>.get(index1: Int, index2 : Int) = this[index1+index2]!!\n" +
|
||||||
|
"fun ArrayList<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n");
|
||||||
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction("box");
|
Method foo = generateFunction("box");
|
||||||
assertTrue(foo.invoke(null).equals("5"));
|
assertTrue(foo.invoke(null).equals("5"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMap () throws Exception {
|
public void testArrayGetMultiIndex() throws Exception {
|
||||||
loadText(
|
loadText(
|
||||||
"fun box() : Int? { val s = java.util.HashMap<String,Int?>(); s[\"239\"] = 239; return s[\"239\"] }\n" +
|
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; return s[-2, 2] }\n" +
|
||||||
"fun java.util.HashMap<String,Int?>.set(index: String, elem: Int?) { this.put(index, elem) }");
|
"fun Array<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
|
||||||
// System.out.println(generateToText());
|
"fun Array<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }");
|
||||||
|
// System.out.println(generateToText());
|
||||||
Method foo = generateFunction("box");
|
Method foo = generateFunction("box");
|
||||||
assertTrue((Integer)foo.invoke(null) == 239);
|
assertTrue(foo.invoke(null).equals("5"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLongDouble () throws Exception {
|
public void testMap() throws Exception {
|
||||||
loadText(
|
loadText(
|
||||||
"fun box() : Int { var l = IntArray(1); l[0.toLong()] = 4; l[0.toLong()] += 6; return l[0.toLong()];}\n" +
|
"fun box() : Int? { val s = java.util.HashMap<String,Int?>(); s[\"239\"] = 239; return s[\"239\"] }\n" +
|
||||||
"fun IntArray.set(index: Long, elem: Int) { this[index.toInt()] = elem }\n" +
|
"fun java.util.HashMap<String,Int?>.set(index: String, elem: Int?) { this.put(index, elem) }");
|
||||||
"fun IntArray.get(index: Long) = this[index.toInt()]");
|
// System.out.println(generateToText());
|
||||||
// System.out.println(generateToText());
|
|
||||||
Method foo = generateFunction("box");
|
Method foo = generateFunction("box");
|
||||||
assertTrue((Integer)foo.invoke(null) == 10);
|
assertTrue((Integer) foo.invoke(null) == 239);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLongDouble() throws Exception {
|
||||||
|
loadText(
|
||||||
|
"fun box() : Int { var l = IntArray(1); l[0.toLong()] = 4; l[0.toLong()] += 6; return l[0.toLong()];}\n" +
|
||||||
|
"fun IntArray.set(index: Long, elem: Int) { this[index.toInt()] = elem }\n" +
|
||||||
|
"fun IntArray.get(index: Long) = this[index.toInt()]");
|
||||||
|
// System.out.println(generateToText());
|
||||||
|
Method foo = generateFunction("box");
|
||||||
|
assertTrue((Integer) foo.invoke(null) == 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testKt503() {
|
public void testKt503() {
|
||||||
@@ -308,7 +315,7 @@ public class ArrayGenTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testKt602() {
|
public void testKt602() {
|
||||||
blackBoxFile("regressions/kt602.jet");
|
blackBoxFile("regressions/kt602.jet");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testKt950() {
|
public void testKt950() {
|
||||||
@@ -317,12 +324,12 @@ public class ArrayGenTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testKt594() throws Exception {
|
public void testKt594() throws Exception {
|
||||||
loadFile("regressions/kt594.jet");
|
loadFile("regressions/kt594.jet");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
blackBox();
|
blackBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNonNullArray() throws Exception {
|
public void testNonNullArray() throws Exception {
|
||||||
blackBoxFile("classes/nonnullarray.jet");
|
blackBoxFile("classes/nonnullarray.jet");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ public class ClassGenTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testSelfCreate() throws Exception {
|
public void testSelfCreate() throws Exception {
|
||||||
createEnvironmentWithFullJdk();
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
blackBoxFile("classes/selfcreate.kt");
|
blackBoxFile("classes/selfcreate.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.CompileCompilerDependenciesTest;
|
|
||||||
import org.jetbrains.jet.ConfigurationKind;
|
import org.jetbrains.jet.ConfigurationKind;
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
|
||||||
import org.jetbrains.jet.TestJdkKind;
|
|
||||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
@@ -89,6 +83,19 @@ public class FunctionGenTest extends CodegenTestCase {
|
|||||||
assertFalse((Boolean) foo.invoke(null, "mama"));
|
assertFalse((Boolean) foo.invoke(null, "mama"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNoRefToOuter() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
|
||||||
|
loadText("class A() { fun f() : ()->String { val s = \"OK\"; return { -> s } } }");
|
||||||
|
// System.out.println(generateToText());
|
||||||
|
Class foo = generateClass("A");
|
||||||
|
final Object obj = foo.newInstance();
|
||||||
|
final Method f = foo.getMethod("f");
|
||||||
|
final Object closure = f.invoke(obj);
|
||||||
|
final Class<? extends Object> aClass = closure.getClass();
|
||||||
|
final Field[] fields = aClass.getFields();
|
||||||
|
assertEquals(1, fields.length);
|
||||||
|
assertEquals("$s", fields[0].getName());
|
||||||
|
}
|
||||||
|
|
||||||
public void testAnyEquals() throws InvocationTargetException, IllegalAccessException {
|
public void testAnyEquals() throws InvocationTargetException, IllegalAccessException {
|
||||||
loadText("fun foo(x: Any) = x.equals(\"lala\")");
|
loadText("fun foo(x: Any) = x.equals(\"lala\")");
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
@@ -115,6 +122,7 @@ public class FunctionGenTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testKt1199() {
|
public void testKt1199() {
|
||||||
blackBoxFile("regressions/kt1199.kt");
|
blackBoxFile("regressions/kt1199.kt");
|
||||||
|
System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFunction() throws InvocationTargetException, IllegalAccessException {
|
public void testFunction() throws InvocationTargetException, IllegalAccessException {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class LocalClassGenTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testWithClosure() {
|
public void testWithClosure() {
|
||||||
//blackBoxFile("localcls/withclosure.kt");
|
blackBoxFile("localcls/withclosure.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEnum() {
|
public void testEnum() {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.di;
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import org.jetbrains.jet.codegen.*;
|
import org.jetbrains.jet.codegen.*;
|
||||||
|
import org.jetbrains.jet.codegen.context.ClosureAnnotator;
|
||||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||||
import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode;
|
import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode;
|
||||||
import org.jetbrains.jet.lang.ModuleConfiguration;
|
import org.jetbrains.jet.lang.ModuleConfiguration;
|
||||||
@@ -171,7 +172,7 @@ public class AllInjectorsGenerator {
|
|||||||
generator.addPublicField(JavaSemanticServices.class);
|
generator.addPublicField(JavaSemanticServices.class);
|
||||||
generator.addPublicField(JavaDescriptorResolver.class);
|
generator.addPublicField(JavaDescriptorResolver.class);
|
||||||
generator.addField(true, BindingTrace.class, null,
|
generator.addField(true, BindingTrace.class, null,
|
||||||
new GivenExpression("new org.jetbrains.jet.lang.resolve.BindingTraceContext()"));
|
new GivenExpression("new org.jetbrains.jet.lang.resolve.BindingTraceContext()"));
|
||||||
generator.addField(JavaBridgeConfiguration.class);
|
generator.addField(JavaBridgeConfiguration.class);
|
||||||
generator.addPublicField(PsiClassFinderImpl.class);
|
generator.addPublicField(PsiClassFinderImpl.class);
|
||||||
generator.addField(false, ModuleDescriptor.class, null,
|
generator.addField(false, ModuleDescriptor.class, null,
|
||||||
@@ -226,5 +227,4 @@ public class AllInjectorsGenerator {
|
|||||||
generator.addPublicParameter(BodiesResolveContext.class);
|
generator.addPublicParameter(BodiesResolveContext.class);
|
||||||
generator.generate("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForBodyResolve");
|
generator.generate("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForBodyResolve");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user