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.Type;
|
||||
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.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
@@ -125,7 +125,7 @@ public class ClassBuilderFactories {
|
||||
return super.getCommonSuperClass(type1, type2);
|
||||
}
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
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.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -30,14 +31,14 @@ import java.util.Map;
|
||||
*/
|
||||
public class ClassCodegen {
|
||||
private GenerationState state;
|
||||
private JetTypeMapper jetTypeMapper;
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) private JetTypeMapper jetTypeMapper;
|
||||
|
||||
@Inject
|
||||
public void setState(GenerationState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
@Inject
|
||||
public void setJetTypeMapper(JetTypeMapper jetTypeMapper) {
|
||||
this.jetTypeMapper = jetTypeMapper;
|
||||
@@ -48,13 +49,13 @@ public class ClassCodegen {
|
||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||
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) {
|
||||
// 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
|
||||
// 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()) {
|
||||
@@ -72,7 +73,7 @@ public class ClassCodegen {
|
||||
}
|
||||
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
|
||||
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors, classBuilder);
|
||||
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
|
||||
}
|
||||
|
||||
classBuilder.done();
|
||||
@@ -86,13 +87,14 @@ public class ClassCodegen {
|
||||
ClassBuilder classBuilder
|
||||
) {
|
||||
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);
|
||||
|
||||
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
|
||||
|
||||
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
|
||||
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();
|
||||
traitBuilder.done();
|
||||
}
|
||||
|
||||
@@ -22,15 +22,16 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.Label;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.asm4.commons.Method;
|
||||
import org.jetbrains.asm4.signature.SignatureWriter;
|
||||
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
|
||||
import org.jetbrains.jet.codegen.context.CalculatedClosure;
|
||||
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.lang.descriptors.*;
|
||||
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.BindingContextUtils;
|
||||
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.types.JetType;
|
||||
|
||||
@@ -48,81 +48,42 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
|
||||
public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
public class ClosureCodegen {
|
||||
|
||||
private final BindingContext bindingContext;
|
||||
private final ClosureAnnotator closureAnnotator;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, CodegenContext context) {
|
||||
super(exprContext, context, state);
|
||||
Method constructor;
|
||||
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();
|
||||
typeMapper = this.state.getInjector().getJetTypeMapper();
|
||||
typeMapper = state.getInjector().getJetTypeMapper();
|
||||
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 FunctionDescriptor funDescriptor = bindingContext.get(BindingContext.FUNCTION, fun);
|
||||
|
||||
cv = nameAndVisitor.getSecond();
|
||||
ClassBuilder cv = nameAndVisitor.getSecond();
|
||||
name = nameAndVisitor.getFirst();
|
||||
|
||||
SignatureWriter signatureWriter = new SignatureWriter();
|
||||
|
||||
assert funDescriptor != null;
|
||||
final List<ValueParameterDescriptor> parameters = funDescriptor.getValueParameters();
|
||||
final JvmClassName funClass = getInternalClassName(funDescriptor);
|
||||
final JvmClassName funClass = CodegenUtil.getInternalClassName(funDescriptor);
|
||||
signatureWriter.visitClassType(funClass.getInternalName());
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
appendType(signatureWriter, parameter.getType(), '=');
|
||||
@@ -143,46 +104,27 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
|
||||
|
||||
generateBridge(name.getInternalName(), funDescriptor, fun, cv);
|
||||
captureThis = generateBody(funDescriptor, cv, (JetDeclarationWithBody) fun);
|
||||
generateBody(funDescriptor, cv, (JetDeclarationWithBody) fun, context, expressionCodegen);
|
||||
|
||||
final ClassDescriptor enclosingClass = context.getEnclosingClass();
|
||||
if (enclosingClass == null) {
|
||||
captureThis = null;
|
||||
constructor = generateConstructor(funClass, fun, cv, closure);
|
||||
|
||||
if (CodegenUtil.isConst(closure)) {
|
||||
generateConstInstance(fun, cv);
|
||||
}
|
||||
|
||||
final Method constructor = generateConstructor(funClass, fun, funDescriptor);
|
||||
|
||||
if (captureThis != null) {
|
||||
cv.newField(fun, ACC_FINAL, "this$0", typeMapper.mapType(enclosingClass.getDefaultType(), MapTypeMode.IMPL).getDescriptor(),
|
||||
null, null);
|
||||
}
|
||||
|
||||
if (isConst()) {
|
||||
generateConstInstance(fun);
|
||||
}
|
||||
CodegenUtil.generateClosureFields(closure, cv, state.getInjector().getJetTypeMapper());
|
||||
|
||||
cv.done();
|
||||
|
||||
final GeneratedAnonymousClassDescriptor answer =
|
||||
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;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void generateConstInstance(PsiElement fun) {
|
||||
private void generateConstInstance(PsiElement fun, ClassBuilder cv) {
|
||||
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) {
|
||||
StubCodegen.generateStubCode(mv);
|
||||
}
|
||||
@@ -206,21 +148,29 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private ClassDescriptor generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) {
|
||||
ClassDescriptor function =
|
||||
closureAnnotator.classDescriptorForFunctionDescriptor(funDescriptor);
|
||||
private ClassDescriptor generateBody(
|
||||
FunctionDescriptor funDescriptor,
|
||||
ClassBuilder cv,
|
||||
JetDeclarationWithBody body,
|
||||
CodegenContext context,
|
||||
ExpressionCodegen expressionCodegen
|
||||
) {
|
||||
|
||||
final CodegenContexts.ClosureContext closureContext = context.intoClosure(
|
||||
funDescriptor, function, this, typeMapper);
|
||||
final CodegenContext closureContext = context.intoClosure(funDescriptor, expressionCodegen);
|
||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||
JvmMethodSignature jvmMethodSignature = invokeSignature(funDescriptor);
|
||||
JvmMethodSignature jvmMethodSignature = typeMapper.invokeSignature(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) {
|
||||
final JvmMethodSignature bridge = erasedInvokeSignature(funDescriptor);
|
||||
final Method delegate = invokeSignature(funDescriptor).getAsmMethod();
|
||||
private void generateBridge(
|
||||
String className,
|
||||
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())) {
|
||||
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>>();
|
||||
boolean putFieldForMyself = calculateConstructorParameters(funDescriptor, args);
|
||||
calculateConstructorParameters(args, state, closure);
|
||||
|
||||
final Type[] argTypes = nameAnTypeListToTypeArray(args);
|
||||
|
||||
@@ -293,14 +248,6 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
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);
|
||||
|
||||
FunctionCodegen.endVisit(iv, "constructor", fun);
|
||||
@@ -308,22 +255,24 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
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) {
|
||||
final Type type = typeMapper.mapType(context.getThisDescriptor().getDefaultType(), MapTypeMode.VALUE);
|
||||
args.add(new Pair<String, Type>("this$0", type));
|
||||
final Type type = typeMapper.mapType(captureThis.getDefaultType(), MapTypeMode.VALUE);
|
||||
args.add(new Pair<String, Type>(CodegenUtil.THIS$0, type));
|
||||
}
|
||||
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||
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.keySet()) {
|
||||
if (descriptor == funDescriptor) {
|
||||
putFieldForMyself = true;
|
||||
}
|
||||
else if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
||||
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
|
||||
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
||||
final Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||
|
||||
final Type type = sharedVarType != null
|
||||
@@ -343,7 +292,6 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
assert captureReceiver != null;
|
||||
}
|
||||
}
|
||||
return putFieldForMyself;
|
||||
}
|
||||
|
||||
private static Type[] nameAnTypeListToTypeArray(List<Pair<String, Type>> args) {
|
||||
@@ -354,17 +302,6 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
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) {
|
||||
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;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Type;
|
||||
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.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
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.name.Name;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class CodegenUtil {
|
||||
public static final String RECEIVER$0 = "receiver$0";
|
||||
public static final String THIS$0 = "this$0";
|
||||
|
||||
private CodegenUtil() {
|
||||
}
|
||||
|
||||
@@ -83,6 +91,14 @@ public class CodegenUtil {
|
||||
!(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) {
|
||||
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, fd);
|
||||
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) {
|
||||
InstructionAdapter instructionAdapter = new InstructionAdapter(mv);
|
||||
instructionAdapter.anew(Type.getObjectType(exception));
|
||||
instructionAdapter.dup();
|
||||
instructionAdapter.aconst(message);
|
||||
instructionAdapter.invokespecial(exception, "<init>", "(Ljava/lang/String;)V");
|
||||
instructionAdapter.athrow();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.anew(Type.getObjectType(exception));
|
||||
iv.dup();
|
||||
iv.aconst(message);
|
||||
iv.invokespecial(exception, "<init>", "(Ljava/lang/String;)V");
|
||||
iv.athrow();
|
||||
}
|
||||
|
||||
public static void generateMethodThrow(MethodVisitor mv, String exception, String message) {
|
||||
@@ -140,4 +156,92 @@ public class CodegenUtil {
|
||||
mv.visitMaxs(-1, -1);
|
||||
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.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.ValueParameterDescriptor;
|
||||
|
||||
@@ -32,23 +33,25 @@ import java.util.List;
|
||||
public class ConstructorFrameMap extends FrameMap {
|
||||
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
|
||||
if (descriptor != null) {
|
||||
if (hasThis0) {
|
||||
myOuterThisIndex = enterTemp(JetTypeMapper.OBJECT_TYPE); // outer class instance
|
||||
|
||||
final List<JvmMethodParameterSignature> parameterTypes = callableMethod.getSignature().getKotlinParameterTypes();
|
||||
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();
|
||||
|
||||
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
|
||||
? descriptor.getValueParameters()
|
||||
: Collections.<ValueParameterDescriptor>emptyList();
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.asm4.commons.Method;
|
||||
import org.jetbrains.jet.codegen.context.*;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -63,7 +64,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull;
|
||||
* @author yole
|
||||
* @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_TYPE_CAST_EXCEPTION = "jet/TypeCastException";
|
||||
@@ -78,7 +79,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
private final Type returnType;
|
||||
|
||||
private final BindingContext bindingContext;
|
||||
private final CodegenContext context;
|
||||
final CodegenContext context;
|
||||
|
||||
private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
|
||||
private final Collection<String> localVariableNames = new HashSet<String>();
|
||||
@@ -136,6 +137,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public GenerationState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, @Nullable ClassDescriptor required) {
|
||||
if (required == null) {
|
||||
return inner;
|
||||
@@ -218,14 +223,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
private StackValue visitClassOrObject(JetClassOrObject 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);
|
||||
|
||||
closure.cv = nameAndVisitor.getSecond();
|
||||
closure.name = nameAndVisitor.getFirst();
|
||||
final CodegenContext objectContext = closure.context.intoAnonymousClass(
|
||||
closure, descriptor, OwnerKind.IMPLEMENTATION,
|
||||
typeMapper);
|
||||
final CodegenContext objectContext = context.intoAnonymousClass(descriptor, this);
|
||||
|
||||
new ImplementationBodyCodegen(declaration, objectContext, nameAndVisitor.getSecond(), state).generate();
|
||||
return StackValue.none();
|
||||
@@ -394,13 +396,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
generateForInIterable(expression, loopRangeType);
|
||||
generateForInIterable(expression);
|
||||
return StackValue.none();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private void generateForInIterable(JetForExpression expression, Type loopRangeType) {
|
||||
private void generateForInIterable(JetForExpression expression) {
|
||||
generateForLoop(expression.getBody(), new IteratorForLoopGenerator(expression));
|
||||
}
|
||||
|
||||
@@ -410,9 +412,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
private interface ForLoopGenerator {
|
||||
void beforeLoop();
|
||||
|
||||
void conditionAndJump(@NotNull Label loopExit);
|
||||
|
||||
void beforeBody();
|
||||
|
||||
void afterBody();
|
||||
|
||||
void afterLoop();
|
||||
}
|
||||
|
||||
@@ -457,6 +463,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
@NotNull
|
||||
private JetType getElementType(JetForExpression forExpression) {
|
||||
JetExpression loopRange = forExpression.getLoopRange();
|
||||
assert loopRange != null;
|
||||
ResolvedCall<FunctionDescriptor> nextCall = getNotNull(bindingContext,
|
||||
LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
|
||||
"No next() function " + DiagnosticUtils.atLocation(loopRange));
|
||||
@@ -470,7 +477,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (loopParameter != null) {
|
||||
// E e = tmp<iterator>.next()
|
||||
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);
|
||||
leaveVariableTasks.add(new Runnable() {
|
||||
@Override
|
||||
@@ -510,7 +517,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
for (JetMultiDeclarationEntry variableDeclaration : entries) {
|
||||
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);
|
||||
leaveVariableTasks.add(new Runnable() {
|
||||
@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();
|
||||
Call call = makeFakeCall(new TransientReceiver(elementType));
|
||||
invokeFunction(call, StackValue.local(tmpParameterIndex, asmElementType), resolvedCall);
|
||||
@@ -554,9 +562,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
super(forExpression);
|
||||
|
||||
JetExpression loopRange = forExpression.getLoopRange();
|
||||
assert loopRange != null;
|
||||
this.iteratorCall = getNotNull(bindingContext,
|
||||
LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
|
||||
"No .iterator() function " + DiagnosticUtils.atLocation(loopRange));
|
||||
LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
|
||||
"No .iterator() function " + DiagnosticUtils.atLocation(loopRange));
|
||||
|
||||
JetType iteratorType = iteratorCall.getResultingDescriptor().getReturnType();
|
||||
assert iteratorType != null;
|
||||
@@ -583,10 +592,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
// tmp<iterator>.hasNext()
|
||||
|
||||
JetExpression loopRange = forExpression.getLoopRange();
|
||||
ResolvedCall<FunctionDescriptor> hasNextCall = getNotNull(bindingContext,
|
||||
@SuppressWarnings("ConstantConditions") ResolvedCall<FunctionDescriptor> hasNextCall = getNotNull(bindingContext,
|
||||
LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, 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);
|
||||
|
||||
JetType type = hasNextCall.getResultingDescriptor().getReturnType();
|
||||
@@ -599,9 +608,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
@Override
|
||||
protected void assignToLoopParameter(int parameterIndex) {
|
||||
Call fakeCall =
|
||||
@SuppressWarnings("ConstantConditions") Call fakeCall =
|
||||
makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
|
||||
invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), nextCall);
|
||||
//noinspection ConstantConditions
|
||||
v.store(parameterIndex, asmType(nextCall.getResultingDescriptor().getReturnType()));
|
||||
}
|
||||
|
||||
@@ -763,7 +773,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
@Override
|
||||
protected void generatePrologue() {
|
||||
myIndexVar = lookupLocal(parameterDescriptor);
|
||||
myIndexVar = lookupLocalIndex(parameterDescriptor);
|
||||
myCountVar = myFrameMap.enterTemp(Type.INT_TYPE);
|
||||
myDeltaVar = myFrameMap.enterTemp(Type.INT_TYPE);
|
||||
if (isIntRangeExpr(expression.getLoopRange())) {
|
||||
@@ -977,7 +987,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
StackValue closure = genClosure(function);
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
|
||||
int index = myFrameMap.getIndex(descriptor);
|
||||
int index = lookupLocalIndex(descriptor);
|
||||
closure.put(OBJECT_TYPE, v);
|
||||
v.store(index, OBJECT_TYPE);
|
||||
return StackValue.none();
|
||||
@@ -996,89 +1006,90 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
private StackValue genClosure(JetExpression expression) {
|
||||
ClosureCodegen closureCodegen = new ClosureCodegen(state, this, context);
|
||||
final GeneratedAnonymousClassDescriptor closure = closureCodegen.gen(expression);
|
||||
final FunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, expression);
|
||||
final ClosureAnnotator closureAnnotator = state.getInjector().getClosureAnnotator();
|
||||
final ClassDescriptor classDescriptor = closureAnnotator.classDescriptorForFunctionDescriptor(descriptor);
|
||||
final CalculatedClosure closure = closureAnnotator.getCalculatedClosure(classDescriptor);
|
||||
|
||||
if (closureCodegen.isConst()) {
|
||||
v.invokestatic(closure.getClassname().getInternalName(), "$getInstance", "()" + closure.getClassname().getDescriptor());
|
||||
ClosureCodegen closureCodegen = new ClosureCodegen(state, (MutableClosure) closure).gen(expression, context, this);
|
||||
|
||||
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 {
|
||||
v.anew(closure.getClassname().getAsmType());
|
||||
v.anew(asmType);
|
||||
v.dup();
|
||||
|
||||
final Method cons = closure.getConstructor();
|
||||
|
||||
int k = 0;
|
||||
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());
|
||||
final Method cons = closureCodegen.constructor;
|
||||
pushClosureOnStack(closure, false);
|
||||
v.invokespecial(internalName, "<init>", cons.getDescriptor());
|
||||
}
|
||||
return StackValue.onStack(closure.getClassname().getAsmType());
|
||||
return StackValue.onStack(asmType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) {
|
||||
ObjectOrClosureCodegen closureCodegen = new ObjectOrClosureCodegen(this, context, state);
|
||||
GeneratedAnonymousClassDescriptor closure = state.generateObjectLiteral(expression, closureCodegen);
|
||||
Type type = closure.getClassname().getAsmType();
|
||||
CalculatedClosure closure = state.generateObjectLiteral(expression, this);
|
||||
|
||||
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.dup();
|
||||
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(closure.getConstructor().getArgumentTypes()));
|
||||
final Method cons = constructor.getSignature().getAsmMethod();
|
||||
|
||||
if (consArgTypes.size() > 0) {
|
||||
v.load(0, OBJECT_TYPE);
|
||||
}
|
||||
pushClosureOnStack(closure, false);
|
||||
|
||||
if (closureCodegen.captureReceiver != null) {
|
||||
final Type asmType = typeMapper.mapType(closureCodegen.captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
||||
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) {
|
||||
final JetDelegatorToSuperCall superCall = closure.getSuperCall();
|
||||
if (superCall != null) {
|
||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
|
||||
closureCodegen.superCall
|
||||
superCall
|
||||
.getCalleeExpression()
|
||||
.getConstructorReferenceExpression());
|
||||
assert superConstructor != null;
|
||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor,
|
||||
typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
|
||||
CallableMethod superCallable = typeMapper
|
||||
.mapToCallableMethod(superConstructor, typeMapper.getCalculatedClosure(superConstructor.getContainingDeclaration()));
|
||||
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
|
||||
Collections.addAll(consArgTypes, argumentTypes);
|
||||
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, closureCodegen.superCall.getCalleeExpression());
|
||||
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, superCall.getCalleeExpression());
|
||||
assert resolvedCall != null;
|
||||
pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes));
|
||||
}
|
||||
|
||||
Method cons = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
|
||||
v.invokespecial(closure.getClassname().getInternalName(), "<init>", cons.getDescriptor());
|
||||
return StackValue.onStack(closure.getClassname().getAsmType());
|
||||
v.invokespecial(name.getInternalName(), "<init>", cons.getDescriptor());
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -1301,7 +1312,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
}
|
||||
|
||||
int index = lookupLocal(descriptor);
|
||||
int index = lookupLocalIndex(descriptor);
|
||||
if (index >= 0) {
|
||||
return stackValueForLocal(descriptor, index);
|
||||
}
|
||||
@@ -1379,7 +1390,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
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 instanceof StackValue.Composed) {
|
||||
@@ -1445,39 +1456,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
}
|
||||
|
||||
public int lookupLocal(DeclarationDescriptor descriptor) {
|
||||
return myFrameMap.getIndex(descriptor);
|
||||
@Override
|
||||
public boolean lookupLocal(DeclarationDescriptor descriptor) {
|
||||
return lookupLocalIndex(descriptor) != -1;
|
||||
}
|
||||
|
||||
public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type expectedType, InstructionAdapter v) {
|
||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getOriginal().getContainingDeclaration();
|
||||
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 int lookupLocalIndex(DeclarationDescriptor descriptor) {
|
||||
return myFrameMap.getIndex(descriptor);
|
||||
}
|
||||
|
||||
public StackValue.Property intermediateValueForProperty(
|
||||
@@ -1499,7 +1484,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
boolean isInsideClass = !isFakeOverride &&
|
||||
(((containingDeclaration == null && !context.hasThisDescriptor() ||
|
||||
context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) ||
|
||||
(context.getParentContext() instanceof CodegenContexts.NamespaceContext) &&
|
||||
(context.getParentContext() instanceof CodegenContext.NamespaceContext) &&
|
||||
context.getParentContext().getContextDescriptor() == containingDeclaration)
|
||||
&& contextKind() != OwnerKind.TRAIT_IMPL);
|
||||
Method getter = null;
|
||||
@@ -1681,7 +1666,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (enclosed != context.getThisDescriptor()) {
|
||||
CodegenContext c = context;
|
||||
//noinspection ConstantConditions
|
||||
while (!(c instanceof CodegenContexts.ClassContext) ||
|
||||
while (!(c instanceof CodegenContext.ClassContext) ||
|
||||
!DescriptorUtils.isSubclass(c.getThisDescriptor(), enclosed)) {
|
||||
c = c.getParentContext();
|
||||
assert c != null;
|
||||
@@ -1761,7 +1746,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
//}
|
||||
if (isCallAsFunctionObject(fd)) {
|
||||
SimpleFunctionDescriptor invoke = CodegenUtil.createInvoke(fd);
|
||||
callableMethod = ClosureCodegen.asCallableMethod(invoke, typeMapper);
|
||||
callableMethod = typeMapper.asCallableMethod(invoke);
|
||||
}
|
||||
else {
|
||||
callableMethod = typeMapper.mapToCallableMethod(fd, superCall, OwnerKind.IMPLEMENTATION);
|
||||
@@ -1895,14 +1880,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
private StackValue generateReceiver(DeclarationDescriptor provided) {
|
||||
assert context instanceof CodegenContexts.ReceiverContext;
|
||||
CodegenContexts.ReceiverContext cur = (CodegenContexts.ReceiverContext) context;
|
||||
if (cur.getReceiverDescriptor() == provided) {
|
||||
StackValue result = cur.getReceiverExpression(typeMapper);
|
||||
if (context.getReceiverDescriptor() == provided) {
|
||||
StackValue result = context.getReceiverExpression(typeMapper);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1910,12 +1893,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
CodegenContext cur = context;
|
||||
StackValue result = StackValue.local(0, OBJECT_TYPE);
|
||||
while (cur != null) {
|
||||
if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) {
|
||||
if (cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext)) {
|
||||
cur = cur.getParentContext();
|
||||
}
|
||||
|
||||
if (cur instanceof CodegenContexts.ScriptContext) {
|
||||
CodegenContexts.ScriptContext scriptContext = (CodegenContexts.ScriptContext) cur;
|
||||
if (cur instanceof CodegenContext.ScriptContext) {
|
||||
CodegenContext.ScriptContext scriptContext = (CodegenContext.ScriptContext) cur;
|
||||
|
||||
JvmClassName currentScriptClassName =
|
||||
state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(scriptContext.getScriptDescriptor());
|
||||
@@ -1933,9 +1916,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
assert cur != null;
|
||||
@@ -1953,7 +1936,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
Type type = asmType(calleeContainingClass.getDefaultType());
|
||||
StackValue result = StackValue.local(0, type);
|
||||
while (cur != null) {
|
||||
if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) {
|
||||
if (cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext)) {
|
||||
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();
|
||||
}
|
||||
assert cur != null;
|
||||
@@ -2125,7 +2108,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (typeMapper.isVarCapturedInClosure(declarationDescriptor)) {
|
||||
return -1;
|
||||
}
|
||||
return lookupLocal(declarationDescriptor);
|
||||
return lookupLocalIndex(declarationDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2220,7 +2203,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
private StackValue generateIn(JetBinaryExpression expression) {
|
||||
JetExpression expr = expression.getLeft();
|
||||
boolean inverted = expression.getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IN;
|
||||
if (isIntRangeExpr(expression.getRight())) {
|
||||
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) {
|
||||
int functionLocalIndex = myFrameMap.getIndex(op);
|
||||
int functionLocalIndex = lookupLocalIndex(op);
|
||||
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 =
|
||||
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
|
||||
@@ -2840,7 +2822,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) {
|
||||
return;
|
||||
}
|
||||
int index = lookupLocal(variableDescriptor);
|
||||
int index = lookupLocalIndex(variableDescriptor);
|
||||
|
||||
if (index < 0) {
|
||||
throw new IllegalStateException("Local variable not found for " + variableDescriptor);
|
||||
@@ -2894,15 +2876,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
|
||||
// TODO typechecker must verify that we're the outer class of the instance being created
|
||||
//noinspection ConstantConditions
|
||||
if (!receiver.type.equals(Type.VOID_TYPE)) {
|
||||
receiver.put(receiver.type, v);
|
||||
}
|
||||
|
||||
final ClassDescriptor classDescriptor = ((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration();
|
||||
CallableMethod method = 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());
|
||||
}
|
||||
}
|
||||
@@ -3089,10 +3069,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor);
|
||||
}
|
||||
else {
|
||||
if (descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) {
|
||||
if (descriptor instanceof CallableDescriptor) {
|
||||
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;
|
||||
Type descriptorType = asmType(descriptor.getType());
|
||||
myFrameMap.enter(descriptor, descriptorType);
|
||||
int index = lookupLocal(descriptor);
|
||||
int index = lookupLocalIndex(descriptor);
|
||||
v.store(index, descriptorType);
|
||||
|
||||
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);
|
||||
expressionToMatch.dupReceiver(v);
|
||||
expressionToMatch.put(varType, v);
|
||||
final int varIndex = myFrameMap.getIndex(variableDescriptor);
|
||||
final int varIndex = lookupLocalIndex(variableDescriptor);
|
||||
v.store(varIndex, varType);
|
||||
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() {
|
||||
return context.getContextDescriptor().toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
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.kotlin.JetMethodAnnotationWriter;
|
||||
import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter;
|
||||
@@ -74,7 +75,7 @@ public class FunctionCodegen {
|
||||
@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();
|
||||
generatedMethod(bodyExpression, jvmMethod, needJetAnnotations, propertyTypeSignature, funContext, functionDescriptor, f);
|
||||
@@ -84,7 +85,7 @@ public class FunctionCodegen {
|
||||
JetExpression bodyExpressions,
|
||||
JvmMethodSignature jvmSignature,
|
||||
boolean needJetAnnotations, @Nullable String propertyTypeSignature,
|
||||
CodegenContexts.MethodContext context,
|
||||
CodegenContext.MethodContext context,
|
||||
FunctionDescriptor functionDescriptor,
|
||||
JetDeclarationWithBody fun
|
||||
) {
|
||||
@@ -334,7 +335,6 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
endVisit(mv, null, fun);
|
||||
mv.visitEnd();
|
||||
|
||||
generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
|
||||
}
|
||||
@@ -417,7 +417,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
static void generateDefaultIfNeeded(
|
||||
CodegenContexts.MethodContext owner,
|
||||
CodegenContext.MethodContext owner,
|
||||
GenerationState state,
|
||||
ClassBuilder v,
|
||||
Method jvmSignature,
|
||||
@@ -477,7 +477,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
private static void generateDefaultImpl(
|
||||
CodegenContexts.MethodContext owner,
|
||||
CodegenContext.MethodContext owner,
|
||||
GenerationState state,
|
||||
Method jvmSignature,
|
||||
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.asm4.commons.Method;
|
||||
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.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -56,7 +57,6 @@ public class GenerationState {
|
||||
// out parameter
|
||||
private Method scriptConstructorMethod;
|
||||
private final BindingContext bindingContext;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
|
||||
public GenerationState(Project project, ClassBuilderFactory builderFactory, AnalyzeExhaust analyzeExhaust, List<JetFile> files) {
|
||||
@@ -75,7 +75,6 @@ public class GenerationState {
|
||||
this.injector = new InjectorForJvmCodegen(
|
||||
bindingContext,
|
||||
this.files, builtinToJavaTypesMapping, builderFactory.getClassBuilderMode(), this, builderFactory, project);
|
||||
typeMapper = injector.getJetTypeMapper();
|
||||
}
|
||||
|
||||
private void markUsed() {
|
||||
@@ -195,25 +194,20 @@ public class GenerationState {
|
||||
codegen.generate(errorHandler, progress);
|
||||
}
|
||||
|
||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) {
|
||||
public CalculatedClosure generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen expressionCodegen) {
|
||||
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
||||
Pair<JvmClassName, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
|
||||
|
||||
closure.cv = nameAndVisitor.getSecond();
|
||||
closure.name = nameAndVisitor.getFirst();
|
||||
final CodegenContext objectContext = closure.context.intoAnonymousClass(
|
||||
closure, bindingContext.get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION,
|
||||
typeMapper);
|
||||
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, objectDeclaration);
|
||||
assert classDescriptor != null;
|
||||
|
||||
final CalculatedClosure closure = getInjector().getClosureAnnotator().getCalculatedClosure(classDescriptor);
|
||||
|
||||
final CodegenContext objectContext = expressionCodegen.context.intoAnonymousClass(classDescriptor, expressionCodegen);
|
||||
|
||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
||||
|
||||
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
||||
assert constructorDescriptor != null;
|
||||
CallableMethod callableMethod = typeMapper.mapToCallableMethod(
|
||||
constructorDescriptor,
|
||||
typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature().getAsmMethod(),
|
||||
objectContext.outerWasUsed, null);
|
||||
return closure;
|
||||
}
|
||||
|
||||
public String createText() {
|
||||
|
||||
@@ -26,6 +26,9 @@ import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
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.kotlin.JetMethodAnnotationWriter;
|
||||
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.BindingContextUtils;
|
||||
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.java.JdkNames;
|
||||
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());
|
||||
assert superType != null;
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
assert superClassDescriptor != null;
|
||||
if (!CodegenUtil.isInterface(superClassDescriptor)) {
|
||||
superClassType = superType;
|
||||
assert superClassDescriptor != null;
|
||||
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName();
|
||||
superCall = specifier;
|
||||
}
|
||||
@@ -338,6 +342,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
generateAccessors();
|
||||
|
||||
generateEnumMethods();
|
||||
|
||||
CodegenUtil.generateClosureFields(context.closure, v, state.getInjector().getJetTypeMapper());
|
||||
}
|
||||
|
||||
private void generateEnumMethods() {
|
||||
@@ -373,10 +379,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateAccessors() {
|
||||
if (context.accessors != null) {
|
||||
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.accessors.entrySet()) {
|
||||
genAccessor(entry);
|
||||
}
|
||||
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.getAccessors().entrySet()) {
|
||||
genAccessor(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,73 +555,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
|
||||
|
||||
CodegenContexts.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
|
||||
final CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
||||
|
||||
JvmMethodSignature constructorMethod;
|
||||
CallableMethod callableMethod;
|
||||
boolean hasThis0 = typeMapper.hasThis0(descriptor);
|
||||
if (constructorDescriptor == null) {
|
||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
||||
lookupConstructorExpressionsInClosureIfPresent(constructorContext);
|
||||
|
||||
signatureWriter.writeFormalTypeParametersStart();
|
||||
signatureWriter.writeFormalTypeParametersEnd();
|
||||
MutableClosure closure = context.closure;
|
||||
boolean hasThis0 = closure != null && closure.getCaptureThis() != null;
|
||||
|
||||
signatureWriter.writeParametersStart();
|
||||
|
||||
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);
|
||||
}
|
||||
final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure);
|
||||
final JvmMethodSignature constructorMethod = callableMethod.getSignature();
|
||||
|
||||
assert constructorDescriptor != null;
|
||||
int flags = JetTypeMapper.getAccessModifiers(constructorDescriptor, 0);
|
||||
@@ -643,18 +589,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return;
|
||||
}
|
||||
|
||||
generatePrimiryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, hasThis0, closure,
|
||||
firstSuperArgument, mv);
|
||||
generatePrimiryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, hasThis0, closure, mv);
|
||||
}
|
||||
|
||||
private void generatePrimiryConstructorImpl(
|
||||
ConstructorDescriptor constructorDescriptor,
|
||||
CodegenContexts.ConstructorContext constructorContext,
|
||||
CodegenContext.ConstructorContext constructorContext,
|
||||
JvmMethodSignature constructorMethod,
|
||||
CallableMethod callableMethod,
|
||||
boolean hasThis0,
|
||||
ObjectOrClosureCodegen closure,
|
||||
int firstSuperArgument,
|
||||
MutableClosure closure,
|
||||
MethodVisitor mv
|
||||
) {
|
||||
mv.visitCode();
|
||||
@@ -663,7 +607,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
? constructorDescriptor.getValueParameters()
|
||||
: Collections.<ValueParameterDescriptor>emptyList();
|
||||
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, hasThis0);
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor);
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
|
||||
@@ -678,38 +622,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
genSuperCallToDelegatorToSuperClass(iv);
|
||||
}
|
||||
else {
|
||||
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
|
||||
((JetDelegatorToSuperCall) superCall)
|
||||
.getCalleeExpression()
|
||||
.getConstructorReferenceExpression());
|
||||
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap,
|
||||
firstSuperArgument);
|
||||
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, frameMap);
|
||||
}
|
||||
|
||||
final ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor);
|
||||
final boolean hasOuterThis = typeMapper.hasThis0(descriptor) && outerDescriptor != null;
|
||||
if (hasOuterThis) {
|
||||
final Type type = typeMapper.mapType(outerDescriptor.getDefaultType(), MapTypeMode.VALUE);
|
||||
if (hasThis0) {
|
||||
final Type type = typeMapper
|
||||
.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), MapTypeMode.VALUE);
|
||||
String interfaceDesc = type.getDescriptor();
|
||||
final String fieldName = "this$0";
|
||||
v.newField(myClass, ACC_FINAL, fieldName, interfaceDesc, null, null);
|
||||
iv.load(0, classType);
|
||||
iv.load(frameMap.getOuterThisIndex(), type);
|
||||
iv.putfield(classname.getInternalName(), fieldName, interfaceDesc);
|
||||
iv.putfield(classname.getInternalName(), CodegenUtil.THIS$0, interfaceDesc);
|
||||
}
|
||||
|
||||
if (closure != null) {
|
||||
int k = hasOuterThis ? 2 : 1;
|
||||
if (closure.captureReceiver != null) {
|
||||
int k = hasThis0 ? 2 : 1;
|
||||
final String internalName = typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName();
|
||||
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||
if (captureReceiver != null) {
|
||||
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.putfield(typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(), "receiver$0",
|
||||
asmType.getDescriptor());
|
||||
iv.putfield(internalName, CodegenUtil.RECEIVER$0, asmType.getDescriptor());
|
||||
k += asmType.getSize();
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor varDescr : closure.closure.keySet()) {
|
||||
for (DeclarationDescriptor varDescr : closure.getCaptureVariables().keySet()) {
|
||||
if (varDescr instanceof VariableDescriptor && !(varDescr instanceof PropertyDescriptor)) {
|
||||
Type sharedVarType = typeMapper.getSharedVarType(varDescr);
|
||||
if (sharedVarType == null) {
|
||||
@@ -718,7 +655,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.load(0, JetTypeMapper.OBJECT_TYPE);
|
||||
iv.load(k, StackValue.refType(sharedVarType));
|
||||
k += StackValue.refType(sharedVarType).getSize();
|
||||
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(),
|
||||
iv.putfield(internalName,
|
||||
"$" + varDescr.getName(), sharedVarType.getDescriptor());
|
||||
}
|
||||
}
|
||||
@@ -847,37 +784,30 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
.getDefaultType(),
|
||||
MapTypeMode.IMPL)
|
||||
.getInternalName()),
|
||||
state.getInjector().getJetTypeMapper());
|
||||
state);
|
||||
generateDelegates(superClass, delegateContext, field);
|
||||
}
|
||||
|
||||
private int addClosureToConstructorParameters(
|
||||
boolean hasThis0,
|
||||
ObjectOrClosureCodegen closure,
|
||||
MutableClosure closure,
|
||||
List<JvmMethodParameterSignature> consArgTypes
|
||||
) {
|
||||
int insert = 0;
|
||||
if (closure != null) {
|
||||
if (closure.captureThis != null) {
|
||||
if (!hasThis0) {
|
||||
consArgTypes.add(insert,
|
||||
new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName().getName()),
|
||||
"", JvmMethodParameterKind.THIS0));
|
||||
}
|
||||
if (closure.getCaptureThis() != null) {
|
||||
consArgTypes.add(insert,
|
||||
new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName().getName()),
|
||||
"", JvmMethodParameterKind.OUTER));
|
||||
insert++;
|
||||
}
|
||||
else {
|
||||
if (hasThis0) {
|
||||
insert++;
|
||||
}
|
||||
}
|
||||
|
||||
if (closure.captureReceiver != null) {
|
||||
final Type asmType = typeMapper.mapType(closure.captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
||||
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||
if (captureReceiver != null) {
|
||||
final Type asmType = typeMapper.mapType(captureReceiver.getDefaultType(), MapTypeMode.IMPL);
|
||||
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)) {
|
||||
final Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||
final Type type;
|
||||
@@ -891,30 +821,64 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
consArgTypes.add(insert++, new JvmMethodParameterSignature(type, "", JvmMethodParameterKind.SHARED_VAR));
|
||||
}
|
||||
else if (descriptor instanceof FunctionDescriptor) {
|
||||
assert closure.captureReceiver != null;
|
||||
assert captureReceiver != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return insert;
|
||||
}
|
||||
|
||||
private void lookupDelegateExpressionInClosureIfPresent() {
|
||||
if (context.closure != null) {
|
||||
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier != superCall && specifier instanceof JetDelegatorByExpressionSpecifier) {
|
||||
private void lookupConstructorExpressionsInClosureIfPresent(final CodegenContext.ConstructorContext constructorContext) {
|
||||
final JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||
@Override
|
||||
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();
|
||||
assert delegateExpression != null;
|
||||
delegateExpression.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitJetElement(JetElement e) {
|
||||
e.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSimpleNameExpression(JetSimpleNameExpression expr) {
|
||||
context.closure.lookupInContext(bindingContext.get(BindingContext.REFERENCE_TARGET, expr), null);
|
||||
}
|
||||
});
|
||||
delegateExpression.accept(visitor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (superCall instanceof JetDelegatorToSuperCall) {
|
||||
final JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList();
|
||||
if (argumentList != null) {
|
||||
argumentList.accept(visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1059,48 +1023,63 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateDelegatorToConstructorCall(
|
||||
InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
|
||||
InstructionAdapter iv, ExpressionCodegen codegen,
|
||||
ConstructorDescriptor constructorDescriptor,
|
||||
ConstructorFrameMap frameMap, int firstSuperArgument
|
||||
ConstructorFrameMap frameMap
|
||||
) {
|
||||
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
|
||||
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
iv.load(frameMap.getOuterThisIndex(),
|
||||
typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), MapTypeMode.IMPL));
|
||||
}
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure);
|
||||
|
||||
CallableMethod method = typeMapper
|
||||
.mapToCallableMethod(constructorDescriptor, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
final ResolvedCall<? extends CallableDescriptor> resolvedCall =
|
||||
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 &&
|
||||
superCall instanceof JetDelegatorToSuperCall &&
|
||||
((JetObjectDeclaration) myClass).isObjectLiteral()) {
|
||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
|
||||
((JetDelegatorToSuperCall) superCall)
|
||||
.getCalleeExpression()
|
||||
.getConstructorReferenceExpression());
|
||||
assert superConstructor != null;
|
||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor,
|
||||
typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
|
||||
int nextVar = firstSuperArgument + 1;
|
||||
int nextVar = findFirstSuperArgument(method);
|
||||
for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
||||
iv.load(nextVar, t);
|
||||
nextVar += t.getSize();
|
||||
}
|
||||
method.invoke(codegen.v);
|
||||
superCallable.invoke(codegen.v);
|
||||
}
|
||||
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
|
||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
||||
if (declaration instanceof JetClassObject) {
|
||||
@@ -1171,7 +1150,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
.get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
|
||||
assert constructorDescriptor != null;
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, typeMapper
|
||||
.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
.getCalculatedClosure(constructorDescriptor.getContainingDeclaration()));
|
||||
codegen.invokeMethodWithArguments(method, superCall, StackValue.none());
|
||||
}
|
||||
else {
|
||||
@@ -1206,7 +1185,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
Type type = typeMapper.mapType(jetType, MapTypeMode.VALUE);
|
||||
if (skipDefaultValue(propertyDescriptor, value, type)) continue;
|
||||
}
|
||||
iv.load(0, JetTypeMapper.OBJECT_TYPE);
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
Type type = codegen.expressionType(initializer);
|
||||
if (jetType.isNullable()) {
|
||||
type = JetTypeMapper.boxType(type);
|
||||
|
||||
@@ -21,12 +21,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.Type;
|
||||
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.codegen.signature.JvmPropertyAccessorSignature;
|
||||
import org.jetbrains.jet.codegen.context.CalculatedClosure;
|
||||
import org.jetbrains.jet.codegen.context.ClosureAnnotator;
|
||||
import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor;
|
||||
import org.jetbrains.jet.codegen.signature.*;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
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.JetObjectDeclaration;
|
||||
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 javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
|
||||
@@ -103,7 +101,12 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -856,22 +859,27 @@ public class JetTypeMapper {
|
||||
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);
|
||||
|
||||
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
|
||||
|
||||
// constructor type parmeters are fake
|
||||
writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
|
||||
|
||||
signatureWriter.writeParametersStart();
|
||||
|
||||
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (hasThis0) {
|
||||
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
|
||||
mapType(closureAnnotator.getEclosingClassDescriptor(containingDeclaration).getDefaultType(), signatureWriter,
|
||||
MapTypeMode.VALUE);
|
||||
final ClassDescriptor captureThis = closure != null ? closure.getCaptureThis() : null;
|
||||
if (captureThis != null) {
|
||||
signatureWriter.writeParameterType(JvmMethodParameterKind.OUTER);
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -884,7 +892,46 @@ public class JetTypeMapper {
|
||||
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);
|
||||
mapType(parameter.getType(), signatureWriter, MapTypeMode.VALUE);
|
||||
signatureWriter.writeParameterTypeEnd();
|
||||
@@ -925,8 +972,8 @@ public class JetTypeMapper {
|
||||
return signatureWriter.makeJvmMethodSignature("<init>");
|
||||
}
|
||||
|
||||
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, boolean hasThis0) {
|
||||
final JvmMethodSignature method = mapConstructorSignature(descriptor, hasThis0);
|
||||
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, CalculatedClosure closure) {
|
||||
final JvmMethodSignature method = mapConstructorSignature(descriptor, closure);
|
||||
JetType defaultType = descriptor.getContainingDeclaration().getDefaultType();
|
||||
Type mapped = mapType(defaultType, MapTypeMode.IMPL);
|
||||
if (mapped.getSort() != Type.OBJECT) {
|
||||
@@ -999,4 +1046,23 @@ public class JetTypeMapper {
|
||||
return Boolean.TRUE.equals(bindingContext.get(BindingContext.CAPTURED_IN_CLOSURE, variableDescriptor)) &&
|
||||
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;
|
||||
|
||||
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.JetProperty;
|
||||
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.Type;
|
||||
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.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
@@ -122,19 +123,19 @@ public class NamespaceCodegen {
|
||||
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
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(
|
||||
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
||||
}
|
||||
else if (declaration instanceof JetNamedFunction) {
|
||||
if (!multiFile) {
|
||||
final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor, state.getInjector().getJetTypeMapper());
|
||||
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
|
||||
state.getInjector().getMemberCodegen().generateFunctionOrProperty(
|
||||
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
else if (declaration instanceof JetScript) {
|
||||
@@ -170,13 +171,13 @@ public class NamespaceCodegen {
|
||||
if (declaration instanceof JetNamedFunction) {
|
||||
{
|
||||
final CodegenContext context =
|
||||
CodegenContexts.STATIC.intoNamespace(descriptor, state.getInjector().getJetTypeMapper());
|
||||
CodegenContext.STATIC.intoNamespace(descriptor);
|
||||
state.getInjector().getMemberCodegen()
|
||||
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, builder);
|
||||
}
|
||||
{
|
||||
final CodegenContext context =
|
||||
CodegenContexts.STATIC.intoNamespacePart(className, descriptor, state.getInjector().getJetTypeMapper());
|
||||
CodegenContext.STATIC.intoNamespacePart(className, descriptor);
|
||||
state.getInjector().getMemberCodegen()
|
||||
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
|
||||
}
|
||||
@@ -232,7 +233,7 @@ public class NamespaceCodegen {
|
||||
mv.visitCode();
|
||||
|
||||
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 (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.Type;
|
||||
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.kotlin.JetMethodAnnotationWriter;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
|
||||
@@ -23,6 +23,8 @@ import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.Type;
|
||||
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.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
@@ -99,9 +101,9 @@ public class ScriptCodegen {
|
||||
assert scriptDescriptor != null;
|
||||
ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor);
|
||||
|
||||
CodegenContexts.ScriptContext context =
|
||||
(CodegenContexts.ScriptContext) CodegenContexts.STATIC
|
||||
.intoScript(scriptDescriptor, classDescriptorForScript, state.getInjector().getJetTypeMapper());
|
||||
CodegenContext.ScriptContext context =
|
||||
(CodegenContext.ScriptContext) CodegenContext.STATIC
|
||||
.intoScript(scriptDescriptor, classDescriptorForScript);
|
||||
|
||||
JvmClassName className = closureAnnotator.classNameForClassDescriptor(classDescriptorForScript);
|
||||
|
||||
@@ -117,7 +119,7 @@ public class ScriptCodegen {
|
||||
genMembers(scriptDeclaration, context, classBuilder);
|
||||
genFieldsForParameters(scriptDescriptor, classBuilder);
|
||||
genConstructor(scriptDeclaration, scriptDescriptor, classDescriptorForScript, classBuilder,
|
||||
context.intoFunction(scriptDescriptor.getScriptCodeDescriptor(), state.getInjector().getJetTypeMapper()),
|
||||
context.intoFunction(scriptDescriptor.getScriptCodeDescriptor()),
|
||||
earlierScripts);
|
||||
|
||||
classBuilder.done();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
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.ClassKind;
|
||||
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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.codegen;
|
||||
package org.jetbrains.jet.codegen.context;
|
||||
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
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.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
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.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
@@ -36,15 +39,11 @@ import java.util.*;
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class ClosureAnnotator {
|
||||
private final Map<ClassDescriptor, JvmClassName> classNamesForClassDescriptor = new HashMap<ClassDescriptor, JvmClassName>();
|
||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
||||
private final Map<ClassDescriptor, CalculatedClosure> closuresForClassDescriptor = new HashMap<ClassDescriptor, CalculatedClosure>();
|
||||
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 Map<DeclarationDescriptor, ClassDescriptorImpl> classesForFunctions =
|
||||
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> namespaceName2Files = MultiMap.create();
|
||||
@@ -76,7 +75,7 @@ public class ClosureAnnotator {
|
||||
int arity = funDescriptor.getValueParameters().size();
|
||||
|
||||
classDescriptor = new ClassDescriptorImpl(
|
||||
funDescriptor,
|
||||
funDescriptor.getContainingDeclaration(),
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
Modality.FINAL,
|
||||
Name.special("<closure>"));
|
||||
@@ -107,7 +106,6 @@ public class ClosureAnnotator {
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
Modality.FINAL,
|
||||
Name.special("<script-" + className + ">"));
|
||||
recordName(classDescriptor, className);
|
||||
classDescriptor.initialize(
|
||||
false,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
@@ -116,6 +114,8 @@ public class ClosureAnnotator {
|
||||
Collections.<ConstructorDescriptor>emptySet(),
|
||||
null);
|
||||
|
||||
recordClosure(null, classDescriptor, null, className, false);
|
||||
|
||||
ClassDescriptorImpl oldDescriptor = classesForFunctions.put(scriptDescriptor, classDescriptor);
|
||||
if (oldDescriptor != null) {
|
||||
throw new IllegalStateException("Rewrite at key " + scriptDescriptor + " for class");
|
||||
@@ -150,7 +150,8 @@ public class ClosureAnnotator {
|
||||
|
||||
@NotNull
|
||||
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) {
|
||||
@@ -213,65 +214,90 @@ public class ClosureAnnotator {
|
||||
return classNameForClassDescriptor(descriptor);
|
||||
}
|
||||
|
||||
public ClassDescriptor getEclosingClassDescriptor(ClassDescriptor descriptor) {
|
||||
return enclosing.get(descriptor);
|
||||
public JvmClassName classNameForClassDescriptor(ClassDescriptor descriptor) {
|
||||
final CalculatedClosure closure = closuresForClassDescriptor.get(descriptor);
|
||||
return closure == null ? null : closure.getClassName();
|
||||
}
|
||||
|
||||
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
||||
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS
|
||||
|| classDescriptor.getKind() == ClassKind.ENUM_ENTRY
|
||||
|| classDescriptor.getKind() == ClassKind.CLASS_OBJECT) {
|
||||
public ClassDescriptor getEclosingClassDescriptor(ClassDescriptor descriptor) {
|
||||
final CalculatedClosure closure = closuresForClassDescriptor.get(descriptor);
|
||||
return closure == null ? null : closure.getEnclosingClass();
|
||||
}
|
||||
|
||||
public boolean canHaveOuter(ClassDescriptor classDescriptor) {
|
||||
if (DescriptorUtils.isClassObject(classDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS || classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClassDescriptor other = enclosing.get(classDescriptor);
|
||||
return other != null;
|
||||
return getEclosingClassDescriptor(classDescriptor) != null;
|
||||
}
|
||||
|
||||
public boolean enumEntryNeedSubclass(JetEnumEntry enumEntry) {
|
||||
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, enumEntry);
|
||||
return enumEntryNeedSubclass.get(descriptor);
|
||||
return Boolean.TRUE.equals(enumEntryNeedSubclass.get(bindingContext.get(BindingContext.CLASS, enumEntry)));
|
||||
}
|
||||
|
||||
public boolean enumEntryNeedSubclass(ClassDescriptor enumEntry) {
|
||||
Boolean aBoolean = enumEntryNeedSubclass.get(enumEntry);
|
||||
return aBoolean != null && aBoolean;
|
||||
return Boolean.TRUE.equals(enumEntryNeedSubclass.get(enumEntry));
|
||||
}
|
||||
|
||||
public void recordLocalClass(ClassDescriptor descriptor, LocalClassClosureCodegen codegen) {
|
||||
LocalClassClosureCodegen put = localClassCodegenForClass.put(descriptor, codegen);
|
||||
assert put == null;
|
||||
public CalculatedClosure getCalculatedClosure(@NotNull ClassDescriptor descriptor) {
|
||||
//noinspection SuspiciousMethodCalls
|
||||
return closuresForClassDescriptor.get(descriptor.getOriginal());
|
||||
}
|
||||
|
||||
private class MyJetVisitorVoid extends JetVisitorVoid {
|
||||
private final LinkedList<ClassDescriptor> classStack = new LinkedList<ClassDescriptor>();
|
||||
private final LinkedList<String> nameStack = new LinkedList<String>();
|
||||
private void recordClosure(
|
||||
@Nullable JetElement element,
|
||||
ClassDescriptor classDescriptor,
|
||||
@Nullable ClassDescriptor enclosing,
|
||||
JvmClassName name,
|
||||
boolean functionLiteral
|
||||
) {
|
||||
final JetDelegatorToSuperCall superCall = CodegenUtil.findSuperCall(element, bindingContext);
|
||||
|
||||
private void recordEnclosing(ClassDescriptor classDescriptor) {
|
||||
if (classStack.size() > 0) {
|
||||
ClassDescriptor put = enclosing.put(classDescriptor, classStack.peek());
|
||||
assert put == null;
|
||||
CallableDescriptor enclosingReceiver = null;
|
||||
if (classDescriptor.getContainingDeclaration() instanceof CallableDescriptor) {
|
||||
enclosingReceiver = (CallableDescriptor) classDescriptor.getContainingDeclaration();
|
||||
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();
|
||||
Integer cnt = anonymousSubclassesCount.get(top);
|
||||
if (cnt == null) {
|
||||
cnt = 0;
|
||||
}
|
||||
JvmClassName name = JvmClassName.byInternalName(top + "$" + (cnt + 1));
|
||||
String name = top + "$" + (cnt + 1);
|
||||
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
||||
if (descriptor == null) {
|
||||
if (declaration instanceof JetFunctionLiteralExpression || declaration instanceof JetNamedFunction) {
|
||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.FUNCTION, declaration);
|
||||
assert declarationDescriptor instanceof FunctionDescriptor;
|
||||
descriptor = classDescriptorForFunctionDescriptor((FunctionDescriptor) declarationDescriptor);
|
||||
}
|
||||
else if (declaration instanceof JetObjectLiteralExpression) {
|
||||
descriptor =
|
||||
bindingContext.get(BindingContext.CLASS, ((JetObjectLiteralExpression) declaration).getObjectDeclaration());
|
||||
assert descriptor != null;
|
||||
if (declaration instanceof JetFunctionLiteralExpression ||
|
||||
declaration instanceof JetNamedFunction ||
|
||||
declaration instanceof JetObjectLiteralExpression) {
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
@@ -279,20 +305,11 @@ public class ClosureAnnotator {
|
||||
declaration.getClass().getName());
|
||||
}
|
||||
}
|
||||
recordName(descriptor, name);
|
||||
anonymousSubclassesCount.put(top, cnt + 1);
|
||||
|
||||
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
|
||||
public void visitJetElement(JetElement element) {
|
||||
super.visitJetElement(element);
|
||||
@@ -302,6 +319,8 @@ public class ClosureAnnotator {
|
||||
@Override
|
||||
public void visitJetFile(JetFile file) {
|
||||
if (file.isScript()) {
|
||||
//noinspection ConstantConditions
|
||||
classStack.push(classDescriptorForScriptDescriptor(bindingContext.get(BindingContext.SCRIPT, file.getScript())));
|
||||
//noinspection ConstantConditions
|
||||
nameStack.push(classNameForScriptPsi(file.getScript()).getInternalName());
|
||||
}
|
||||
@@ -310,21 +329,39 @@ public class ClosureAnnotator {
|
||||
}
|
||||
file.acceptChildren(this);
|
||||
nameStack.pop();
|
||||
if (file.isScript()) {
|
||||
classStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnumEntry(JetEnumEntry enumEntry) {
|
||||
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, enumEntry);
|
||||
enumEntryNeedSubclass.put(descriptor, !enumEntry.getDeclarations().isEmpty());
|
||||
super.visitEnumEntry(enumEntry);
|
||||
assert descriptor != null;
|
||||
|
||||
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
|
||||
public void visitClassObject(JetClassObject classObject) {
|
||||
JvmClassName name = recordClassObject(classObject);
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
|
||||
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);
|
||||
nameStack.push(name.getInternalName());
|
||||
super.visitClassObject(classObject);
|
||||
@@ -341,16 +378,12 @@ public class ClosureAnnotator {
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
||||
// working around a problem with shallow analysis
|
||||
if (classDescriptor == null) return;
|
||||
recordEnclosing(classDescriptor);
|
||||
|
||||
String name = getName(classDescriptor);
|
||||
recordClosure(declaration, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false);
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
String base = nameStack.peek();
|
||||
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()));
|
||||
nameStack.push(name);
|
||||
super.visitObjectDeclaration(declaration);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
@@ -362,21 +395,23 @@ public class ClosureAnnotator {
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, klass);
|
||||
// working around a problem with shallow analysis
|
||||
if (classDescriptor == null) return;
|
||||
recordEnclosing(classDescriptor);
|
||||
|
||||
String name = getName(classDescriptor);
|
||||
recordClosure(klass, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), false);
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
String base = nameStack.peek();
|
||||
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()));
|
||||
nameStack.push(name);
|
||||
super.visitClass(klass);
|
||||
nameStack.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
|
||||
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, expression.getObjectDeclaration());
|
||||
@@ -385,8 +420,10 @@ public class ClosureAnnotator {
|
||||
super.visitObjectLiteralExpression(expression);
|
||||
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);
|
||||
nameStack.push(classNameForClassDescriptor(classDescriptor).getInternalName());
|
||||
super.visitObjectLiteralExpression(expression);
|
||||
@@ -400,11 +437,13 @@ public class ClosureAnnotator {
|
||||
(FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression);
|
||||
// working around a problem with shallow analysis
|
||||
if (functionDescriptor == null) return;
|
||||
JvmClassName name = recordAnonymousClass(expression);
|
||||
|
||||
String name = inventAnonymousClassName(expression);
|
||||
ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor);
|
||||
recordEnclosing(classDescriptor);
|
||||
recordClosure(expression, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), true);
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(name.getInternalName());
|
||||
nameStack.push(name);
|
||||
super.visitFunctionLiteralExpression(expression);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
@@ -442,26 +481,16 @@ public class ClosureAnnotator {
|
||||
nameStack.pop();
|
||||
}
|
||||
else {
|
||||
JvmClassName name = recordAnonymousClass(function);
|
||||
String name = inventAnonymousClassName(function);
|
||||
ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor);
|
||||
recordEnclosing(classDescriptor);
|
||||
recordClosure(function, classDescriptor, classStack.peek(), JvmClassName.byInternalName(name), true);
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(name.getInternalName());
|
||||
nameStack.push(name);
|
||||
super.visitNamedFunction(function);
|
||||
nameStack.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
|
||||
*/
|
||||
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;
|
||||
|
||||
public class EnclosedValueDescriptor {
|
||||
public final class EnclosedValueDescriptor {
|
||||
private final DeclarationDescriptor descriptor;
|
||||
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.innerValue = innerValue;
|
||||
this.outerValue = outerValue;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public DeclarationDescriptor getDescriptor() {
|
||||
@@ -40,7 +44,18 @@ public class EnclosedValueDescriptor {
|
||||
return innerValue;
|
||||
}
|
||||
|
||||
public StackValue getOuterValue() {
|
||||
return outerValue;
|
||||
public Type getType() {
|
||||
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 alex.tkachman
|
||||
*/
|
||||
public enum JvmMethodParameterKind {
|
||||
VALUE,
|
||||
THIS,
|
||||
THIS0,
|
||||
OUTER,
|
||||
RECEIVER,
|
||||
SHARED_VAR,
|
||||
ENUM_NAME,
|
||||
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.BuiltinToJavaTypesMapping;
|
||||
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 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.ClassFileFactory;
|
||||
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 javax.annotation.PreDestroy;
|
||||
|
||||
|
||||
@@ -28,30 +28,36 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
}
|
||||
|
||||
public void testKt238 () throws Exception {
|
||||
public void testKt238() throws Exception {
|
||||
blackBoxFile("regressions/kt238.jet");
|
||||
}
|
||||
|
||||
public void testKt326 () throws Exception {
|
||||
// blackBoxFile("regressions/kt326.jet");
|
||||
// System.out.println(generateToText());
|
||||
public void testKt326() throws Exception {
|
||||
// blackBoxFile("regressions/kt326.jet");
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testKt779 () throws Exception {
|
||||
public void testKt779() throws Exception {
|
||||
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}) })");
|
||||
Method foo = generateFunction();
|
||||
Integer[][] invoke = (Integer[][]) foo.invoke(null);
|
||||
assertEquals(invoke[2].length, 2);
|
||||
assertEquals(invoke[4].length, 4);
|
||||
assertEquals(invoke[4][2].intValue(), 239);
|
||||
try {
|
||||
Integer[][] invoke = (Integer[][]) foo.invoke(null);
|
||||
assertEquals(invoke[2].length, 2);
|
||||
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) })");
|
||||
Method foo = generateFunction();
|
||||
Integer[][] invoke = (Integer[][]) foo.invoke(null);
|
||||
@@ -59,7 +65,7 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
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,{\"\"}) })");
|
||||
Method foo = generateFunction();
|
||||
Object invoke = foo.invoke(null);
|
||||
@@ -67,16 +73,16 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
assertTrue(invoke instanceof Object[]);
|
||||
}
|
||||
|
||||
public void testCreateMultiGenerics () throws Exception {
|
||||
// loadText("class L<T>() { val a = Array<T?>(5) } fun foo() = L<Int>.a");
|
||||
// System.out.println(generateToText());
|
||||
// Method foo = generateFunction();
|
||||
// Object invoke = foo.invoke(null);
|
||||
// System.out.println(invoke.getClass());
|
||||
// assertTrue(invoke.getClass() == Object[].class);
|
||||
public void testCreateMultiGenerics() throws Exception {
|
||||
// loadText("class L<T>() { val a = Array<T?>(5) } fun foo() = L<Int>.a");
|
||||
// System.out.println(generateToText());
|
||||
// Method foo = generateFunction();
|
||||
// Object invoke = foo.invoke(null);
|
||||
// System.out.println(invoke.getClass());
|
||||
// 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");
|
||||
//System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
@@ -85,221 +91,222 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
foo.invoke(null);
|
||||
}
|
||||
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
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()) } }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
foo.invoke(null);
|
||||
}
|
||||
|
||||
public void testCollectionPlusAssign () throws Exception {
|
||||
public void testCollectionPlusAssign() throws Exception {
|
||||
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] }");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
assertTrue((Integer)foo.invoke(null) == 12);
|
||||
assertTrue((Integer) foo.invoke(null) == 12);
|
||||
}
|
||||
|
||||
public void testCollectionAssignGetMultiIndex () throws Exception {
|
||||
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 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("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());
|
||||
public void testCollectionAssignGetMultiIndex() throws Exception {
|
||||
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 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("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");
|
||||
assertTrue(foo.invoke(null).equals("5"));
|
||||
}
|
||||
|
||||
public void testArrayGetMultiIndex () throws Exception {
|
||||
public void testArrayGetAssignMultiIndex() throws Exception {
|
||||
loadText(
|
||||
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; return s[-2, 2] }\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());
|
||||
"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");
|
||||
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");
|
||||
assertTrue(foo.invoke(null).equals("5"));
|
||||
}
|
||||
|
||||
public void testMap () throws Exception {
|
||||
public void testArrayGetMultiIndex() throws Exception {
|
||||
loadText(
|
||||
"fun box() : Int? { val s = java.util.HashMap<String,Int?>(); s[\"239\"] = 239; return s[\"239\"] }\n" +
|
||||
"fun java.util.HashMap<String,Int?>.set(index: String, elem: Int?) { this.put(index, elem) }");
|
||||
// System.out.println(generateToText());
|
||||
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; return s[-2, 2] }\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");
|
||||
assertTrue((Integer)foo.invoke(null) == 239);
|
||||
assertTrue(foo.invoke(null).equals("5"));
|
||||
}
|
||||
|
||||
public void testLongDouble () throws Exception {
|
||||
public void testMap() 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());
|
||||
"fun box() : Int? { val s = java.util.HashMap<String,Int?>(); s[\"239\"] = 239; return s[\"239\"] }\n" +
|
||||
"fun java.util.HashMap<String,Int?>.set(index: String, elem: Int?) { this.put(index, elem) }");
|
||||
// System.out.println(generateToText());
|
||||
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() {
|
||||
@@ -308,7 +315,7 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
|
||||
public void testKt602() {
|
||||
blackBoxFile("regressions/kt602.jet");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testKt950() {
|
||||
@@ -317,12 +324,12 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
|
||||
public void testKt594() throws Exception {
|
||||
loadFile("regressions/kt594.jet");
|
||||
// System.out.println(generateToText());
|
||||
// System.out.println(generateToText());
|
||||
blackBox();
|
||||
}
|
||||
|
||||
public void testNonNullArray() throws Exception {
|
||||
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 {
|
||||
createEnvironmentWithFullJdk();
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("classes/selfcreate.kt");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,9 @@
|
||||
|
||||
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.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.Method;
|
||||
|
||||
@@ -89,6 +83,19 @@ public class FunctionGenTest extends CodegenTestCase {
|
||||
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 {
|
||||
loadText("fun foo(x: Any) = x.equals(\"lala\")");
|
||||
// System.out.println(generateToText());
|
||||
@@ -115,6 +122,7 @@ public class FunctionGenTest extends CodegenTestCase {
|
||||
|
||||
public void testKt1199() {
|
||||
blackBoxFile("regressions/kt1199.kt");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testFunction() throws InvocationTargetException, IllegalAccessException {
|
||||
|
||||
@@ -33,7 +33,7 @@ public class LocalClassGenTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
public void testWithClosure() {
|
||||
//blackBoxFile("localcls/withclosure.kt");
|
||||
blackBoxFile("localcls/withclosure.kt");
|
||||
}
|
||||
|
||||
public void testEnum() {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.di;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.jet.codegen.*;
|
||||
import org.jetbrains.jet.codegen.context.ClosureAnnotator;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode;
|
||||
import org.jetbrains.jet.lang.ModuleConfiguration;
|
||||
@@ -163,15 +164,15 @@ public class AllInjectorsGenerator {
|
||||
|
||||
generator.generate("compiler/tests", "org.jetbrains.jet.di", "InjectorForTests");
|
||||
}
|
||||
|
||||
|
||||
private static void generateInjectorForJavaSemanticServices() throws IOException {
|
||||
DependencyInjectorGenerator generator = new DependencyInjectorGenerator(false);
|
||||
|
||||
|
||||
// Fields
|
||||
generator.addPublicField(JavaSemanticServices.class);
|
||||
generator.addPublicField(JavaDescriptorResolver.class);
|
||||
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.addPublicField(PsiClassFinderImpl.class);
|
||||
generator.addField(false, ModuleDescriptor.class, null,
|
||||
@@ -181,7 +182,7 @@ public class AllInjectorsGenerator {
|
||||
|
||||
// Parameters
|
||||
generator.addPublicParameter(Project.class);
|
||||
|
||||
|
||||
generator.generate("compiler/frontend.java/src", "org.jetbrains.jet.di", "InjectorForJavaSemanticServices");
|
||||
}
|
||||
|
||||
@@ -226,5 +227,4 @@ public class AllInjectorsGenerator {
|
||||
generator.addPublicParameter(BodiesResolveContext.class);
|
||||
generator.generate("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForBodyResolve");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user