enum entries which overrides methods

This commit is contained in:
Alex Tkachman
2012-08-15 15:56:34 +03:00
parent 00305ba920
commit 31db3456ca
8 changed files with 658 additions and 365 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -58,7 +59,12 @@ public class ClassCodegen {
} }
for (JetDeclaration declaration : aClass.getDeclarations()) { for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) { if (declaration instanceof JetClass) {
if (declaration instanceof JetEnumEntry && !state.getInjector().getClosureAnnotator().enumEntryNeedSubclass(
(JetEnumEntry) declaration)) {
continue;
}
generate(contextForInners, (JetClass) declaration); generate(contextForInners, (JetClass) declaration);
} }
if (declaration instanceof JetClassObject) { if (declaration instanceof JetClassObject) {
@@ -73,7 +79,13 @@ public class ClassCodegen {
classBuilder.done(); classBuilder.done();
} }
private void generateImplementation(CodegenContext context, JetClassOrObject aClass, OwnerKind kind, HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors, ClassBuilder classBuilder) { private void generateImplementation(
CodegenContext context,
JetClassOrObject aClass,
OwnerKind kind,
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors,
ClassBuilder classBuilder
) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
CodegenContext classContext = context.intoClass(descriptor, kind, jetTypeMapper); CodegenContext classContext = context.intoClass(descriptor, kind, jetTypeMapper);
classContext.copyAccessors(accessors); classContext.copyAccessors(accessors);
@@ -81,7 +93,8 @@ public class ClassCodegen {
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) { if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
ClassBuilder traitBuilder = state.forTraitImplementation(descriptor); ClassBuilder traitBuilder = state.forTraitImplementation(descriptor);
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, jetTypeMapper), traitBuilder, state).generate(); new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, jetTypeMapper), traitBuilder, state)
.generate();
traitBuilder.done(); traitBuilder.done();
} }
} }
@@ -51,6 +51,7 @@ public class ClosureAnnotator {
private BindingContext bindingContext; private BindingContext bindingContext;
private List<JetFile> files; private List<JetFile> files;
private final Map<ClassDescriptor, Boolean> enumEntryNeedSubclass = new HashMap<ClassDescriptor, Boolean>();
@Inject @Inject
public void setBindingContext(BindingContext bindingContext) { public void setBindingContext(BindingContext bindingContext) {
@@ -229,6 +230,16 @@ public class ClosureAnnotator {
return other != null; return other != null;
} }
public boolean enumEntryNeedSubclass(JetEnumEntry enumEntry) {
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, enumEntry);
return enumEntryNeedSubclass.get(descriptor);
}
public boolean enumEntryNeedSubclass(ClassDescriptor enumEntry) {
Boolean aBoolean = enumEntryNeedSubclass.get(enumEntry);
return aBoolean != null && aBoolean;
}
private class MyJetVisitorVoid extends JetVisitorVoid { private class MyJetVisitorVoid extends JetVisitorVoid {
private final LinkedList<ClassDescriptor> classStack = new LinkedList<ClassDescriptor>(); private final LinkedList<ClassDescriptor> classStack = new LinkedList<ClassDescriptor>();
private final LinkedList<String> nameStack = new LinkedList<String>(); private final LinkedList<String> nameStack = new LinkedList<String>();
@@ -285,6 +296,13 @@ public class ClosureAnnotator {
nameStack.pop(); nameStack.pop();
} }
@Override
public void visitEnumEntry(JetEnumEntry enumEntry) {
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, enumEntry);
enumEntryNeedSubclass.put(descriptor, !enumEntry.getDeclarations().isEmpty());
super.visitEnumEntry(enumEntry);
}
@Override @Override
public void visitClassObject(JetClassObject classObject) { public void visitClassObject(JetClassObject classObject) {
JvmClassName name = recordClassObject(classObject); JvmClassName name = recordClassObject(classObject);
@@ -43,7 +43,9 @@ public class ConstructorFrameMap extends FrameMap {
List<Type> explicitArgTypes = callableMethod.getValueParameterTypes(); List<Type> explicitArgTypes = callableMethod.getValueParameterTypes();
if(descriptor != null && descriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS) { if (descriptor != null &&
(descriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS ||
descriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_ENTRY)) {
enterTemp(); // name enterTemp(); // name
enterTemp(); // ordinal enterTemp(); // ordinal
} }
@@ -101,11 +101,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
public ExpressionCodegen(MethodVisitor v, public ExpressionCodegen(
MethodVisitor v,
FrameMap myMap, FrameMap myMap,
Type returnType, Type returnType,
CodegenContext context, CodegenContext context,
GenerationState state) { GenerationState state
) {
this.myFrameMap = myMap; this.myFrameMap = myMap;
this.typeMapper = state.getInjector().getJetTypeMapper(); this.typeMapper = state.getInjector().getJetTypeMapper();
this.returnType = returnType; this.returnType = returnType;
@@ -123,11 +125,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, @Nullable ClassDescriptor required) { StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, @Nullable ClassDescriptor required) {
if (required == null) if (required == null) {
return inner; return inner;
}
if (provided instanceof CallableDescriptor) if (provided instanceof CallableDescriptor) {
provided = ((CallableDescriptor) provided).getReceiverParameter().getType().getConstructor().getDeclarationDescriptor(); provided = ((CallableDescriptor) provided).getReceiverParameter().getType().getConstructor().getDeclarationDescriptor();
}
assert provided instanceof ClassDescriptor; assert provided instanceof ClassDescriptor;
@@ -229,8 +233,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
private static boolean isEmptyExpression(JetElement expr) { private static boolean isEmptyExpression(JetElement expr) {
if (expr == null) if (expr == null) {
return true; return true;
}
if (expr instanceof JetBlockExpression) { if (expr instanceof JetBlockExpression) {
JetBlockExpression blockExpression = (JetBlockExpression) expr; JetBlockExpression blockExpression = (JetBlockExpression) expr;
List<JetElement> statements = blockExpression.getStatements(); List<JetElement> statements = blockExpression.getStatements();
@@ -361,12 +366,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
FunctionDescriptor nextDescriptor = bindingContext.get(BindingContext.LOOP_RANGE_NEXT, loopRange); FunctionDescriptor nextDescriptor = bindingContext.get(BindingContext.LOOP_RANGE_NEXT, loopRange);
DeclarationDescriptor hasNextDescriptor = bindingContext.get(BindingContext.LOOP_RANGE_HAS_NEXT, loopRange); DeclarationDescriptor hasNextDescriptor = bindingContext.get(BindingContext.LOOP_RANGE_HAS_NEXT, loopRange);
if (iteratorDescriptor == null) if (iteratorDescriptor == null) {
throw new IllegalStateException("No iterator() method " + DiagnosticUtils.atLocation(loopRange)); throw new IllegalStateException("No iterator() method " + DiagnosticUtils.atLocation(loopRange));
if (nextDescriptor == null) }
if (nextDescriptor == null) {
throw new IllegalStateException("No next() method " + DiagnosticUtils.atLocation(loopRange)); throw new IllegalStateException("No next() method " + DiagnosticUtils.atLocation(loopRange));
if (hasNextDescriptor == null) }
if (hasNextDescriptor == null) {
throw new IllegalStateException("No hasNext method or property" + DiagnosticUtils.atLocation(loopRange)); throw new IllegalStateException("No hasNext method or property" + DiagnosticUtils.atLocation(loopRange));
}
final JetParameter loopParameter = expression.getLoopParameter(); final JetParameter loopParameter = expression.getLoopParameter();
final VariableDescriptor parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter); final VariableDescriptor parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter);
@@ -647,7 +655,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
else if (stackElement instanceof LoopBlockStackElement) { else if (stackElement instanceof LoopBlockStackElement) {
LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement;
if (labelElement == null || loopBlockStackElement.targetLabel != null && labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { if (labelElement == null ||
loopBlockStackElement.targetLabel != null &&
labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) {
v.goTo(loopBlockStackElement.breakLabel); v.goTo(loopBlockStackElement.breakLabel);
return StackValue.none(); return StackValue.none();
} }
@@ -673,7 +683,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
else if (stackElement instanceof LoopBlockStackElement) { else if (stackElement instanceof LoopBlockStackElement) {
LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement;
if (labelElement == null || loopBlockStackElement.targetLabel != null && labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { if (labelElement == null ||
loopBlockStackElement.targetLabel != null &&
labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) {
v.goTo(loopBlockStackElement.continueLabel); v.goTo(loopBlockStackElement.continueLabel);
return StackValue.none(); return StackValue.none();
} }
@@ -809,7 +821,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (closure.isCaptureReceiver() != null) { if (closure.isCaptureReceiver() != null) {
k++; k++;
v.load(context.getContextDescriptor().getContainingDeclaration() instanceof NamespaceDescriptor ? 0: 1, closure.isCaptureReceiver()); v.load(context.getContextDescriptor().getContainingDeclaration() instanceof NamespaceDescriptor ? 0 : 1,
closure.isCaptureReceiver());
} }
for (int i = 0; i < closure.getArgs().size(); i++) { for (int i = 0; i < closure.getArgs().size(); i++) {
@@ -843,16 +856,22 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closureCodegen.closure.entrySet()) { for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closureCodegen.closure.entrySet()) {
if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) { if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) {
Type sharedVarType = typeMapper.getSharedVarType(entry.getKey()); Type sharedVarType = typeMapper.getSharedVarType(entry.getKey());
if (sharedVarType == null) if (sharedVarType == null) {
sharedVarType = state.getInjector().getJetTypeMapper().mapType(((VariableDescriptor) entry.getKey()).getType(), MapTypeMode.VALUE); sharedVarType = state.getInjector().getJetTypeMapper()
.mapType(((VariableDescriptor) entry.getKey()).getType(), MapTypeMode.VALUE);
}
consArgTypes.add(sharedVarType); consArgTypes.add(sharedVarType);
entry.getValue().getOuterValue().put(sharedVarType, v); entry.getValue().getOuterValue().put(sharedVarType, v);
} }
} }
if (closureCodegen.superCall != null) { if (closureCodegen.superCall != null) {
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, closureCodegen.superCall.getCalleeExpression().getConstructorReferenceExpression()); ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration())); closureCodegen.superCall
.getCalleeExpression()
.getConstructorReferenceExpression());
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION,
typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes(); Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
Collections.addAll(consArgTypes, argumentTypes); Collections.addAll(consArgTypes, argumentTypes);
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, closureCodegen.superCall.getCalleeExpression()); ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, closureCodegen.superCall.getCalleeExpression());
@@ -895,7 +914,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
StackValue answer = StackValue.none(); StackValue answer = StackValue.none();
for (int i = 0, statementsSize = statements.size(); i < statementsSize; i++) { for (int i = 0, statementsSize = statements.size(); i < statementsSize; i++) {
JetElement statement = statements.get(i); JetElement statement = statements.get(i);
if (i == statements.size() - 1 /*&& statement instanceof JetExpression && !bindingContext.get(BindingContext.STATEMENT, statement)*/) { if (i ==
statements.size() -
1 /*&& statement instanceof JetExpression && !bindingContext.get(BindingContext.STATEMENT, statement)*/) {
answer = gen(statement); answer = gen(statement);
} }
else { else {
@@ -1058,15 +1079,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
if (propertyDescriptor.isObjectDeclaration()) { if (propertyDescriptor.isObjectDeclaration()) {
ClassDescriptor classDescriptor = (ClassDescriptor) propertyDescriptor.getReturnType().getConstructor().getDeclarationDescriptor(); ClassDescriptor classDescriptor =
(ClassDescriptor) propertyDescriptor.getReturnType().getConstructor().getDeclarationDescriptor();
assert classDescriptor != null;
if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
ClassDescriptor containing = (ClassDescriptor) classDescriptor.getContainingDeclaration().getContainingDeclaration(); ClassDescriptor containing = (ClassDescriptor) classDescriptor.getContainingDeclaration().getContainingDeclaration();
assert containing != null;
Type type = typeMapper.mapType(containing.getDefaultType(), MapTypeMode.VALUE); Type type = typeMapper.mapType(containing.getDefaultType(), MapTypeMode.VALUE);
StackValue.field(type, JvmClassName.byType(type), classDescriptor.getName().getName(), true).put(TYPE_OBJECT, v); Type entryType = typeMapper.mapType(classDescriptor.getDefaultType(), MapTypeMode.VALUE);
StackValue.field(type, JvmClassName.byType(type), classDescriptor.getName().getName(), true).put(entryType, v);
// todo: for now we don't generate classes for enum entries, so we need this hack return StackValue.onStack(entryType);
type = typeMapper.mapType(classDescriptor.getDefaultType(), MapTypeMode.VALUE);
return StackValue.onStack(type);
} }
else { else {
Type type = typeMapper.mapType(classDescriptor.getDefaultType(), MapTypeMode.VALUE); Type type = typeMapper.mapType(classDescriptor.getDefaultType(), MapTypeMode.VALUE);
@@ -1075,11 +1097,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
boolean isStatic = container instanceof NamespaceDescriptor; boolean isStatic = container instanceof NamespaceDescriptor;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ; final boolean directToField =
expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
JetExpression r = getReceiverForSelector(expression); JetExpression r = getReceiverForSelector(expression);
final boolean isSuper = r instanceof JetSuperExpression; final boolean isSuper = r instanceof JetSuperExpression;
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor); propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor);
final StackValue.Property iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null); final StackValue.Property iValue =
intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null);
if (!directToField && resolvedCall != null && !isSuper) { if (!directToField && resolvedCall != null && !isSuper) {
receiver.put(propertyDescriptor.getReceiverParameter().exists() || isStatic receiver.put(propertyDescriptor.getReceiverParameter().exists() || isStatic
? receiver.type ? receiver.type
@@ -1088,20 +1112,24 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else { else {
if (!isStatic) { if (!isStatic) {
if (receiver == StackValue.none()) { if (receiver == StackValue.none()) {
if (resolvedCall == null) if (resolvedCall == null) {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration()); receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
}
else { else {
if (resolvedCall.getThisObject() instanceof ExtensionReceiver) if (resolvedCall.getThisObject() instanceof ExtensionReceiver) {
receiver = generateReceiver(((ExtensionReceiver) resolvedCall.getThisObject()).getDeclarationDescriptor()); receiver = generateReceiver(((ExtensionReceiver) resolvedCall.getThisObject()).getDeclarationDescriptor());
else }
else {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration()); receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
} }
} }
}
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r); JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
receiver.put(receiverType != null && !isSuper ? asmType(receiverType) : TYPE_OBJECT, v); receiver.put(receiverType != null && !isSuper ? asmType(receiverType) : TYPE_OBJECT, v);
if (receiverType != null) { if (receiverType != null) {
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration(); ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
if (!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) { if (!CodegenUtil.isInterface(propReceiverDescriptor) &&
CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) {
// I hope it happens only in case of required super class for traits // I hope it happens only in case of required super class for traits
assert propReceiverDescriptor != null; assert propReceiverDescriptor != null;
v.checkcast(asmType(propReceiverDescriptor.getDefaultType())); v.checkcast(asmType(propReceiverDescriptor.getDefaultType()));
@@ -1119,7 +1147,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
assert descriptor1 != null; assert descriptor1 != null;
final Type type = typeMapper.mapType(descriptor1.getDefaultType(), MapTypeMode.VALUE); final Type type = typeMapper.mapType(descriptor1.getDefaultType(), MapTypeMode.VALUE);
return StackValue.field(type, return StackValue.field(type,
JvmClassName.byType(typeMapper.mapType(((ClassDescriptor) descriptor).getDefaultType(), MapTypeMode.IMPL)), JvmClassName.byType(typeMapper.mapType(((ClassDescriptor) descriptor).getDefaultType(),
MapTypeMode.IMPL)),
"$classobj", "$classobj",
true); true);
} }
@@ -1149,7 +1178,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (value instanceof StackValue.FieldForSharedVar) { if (value instanceof StackValue.FieldForSharedVar) {
StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
Type sharedType = StackValue.sharedTypeForType(value.type); Type sharedType = StackValue.sharedTypeForType(value.type);
v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name, sharedType.getDescriptor()); v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name,
sharedType.getDescriptor());
} }
return value; return value;
@@ -1219,7 +1249,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
StackValue.onStack(asmType(functionDescriptor.getReturnType())).coerce(type, v); StackValue.onStack(asmType(functionDescriptor.getReturnType())).coerce(type, v);
} }
public StackValue.Property intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, @Nullable JetSuperExpression superExpression) { public StackValue.Property intermediateValueForProperty(
PropertyDescriptor propertyDescriptor,
final boolean forceField,
@Nullable JetSuperExpression superExpression
) {
boolean isSuper = superExpression != null; boolean isSuper = superExpression != null;
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
@@ -1232,19 +1266,23 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
PropertyDescriptor initialDescriptor = propertyDescriptor; PropertyDescriptor initialDescriptor = propertyDescriptor;
propertyDescriptor = initialDescriptor.getOriginal(); propertyDescriptor = initialDescriptor.getOriginal();
boolean isInsideClass = !isFakeOverride && (((containingDeclaration == context.getThisDescriptor()) || boolean isInsideClass = !isFakeOverride && (((containingDeclaration == context.getThisDescriptor()) ||
(context.getParentContext() instanceof CodegenContexts.NamespaceContext) && context.getParentContext().getContextDescriptor() == containingDeclaration) (context.getParentContext() instanceof CodegenContexts.NamespaceContext) &&
context.getParentContext().getContextDescriptor() == containingDeclaration)
&& contextKind() != OwnerKind.TRAIT_IMPL); && contextKind() != OwnerKind.TRAIT_IMPL);
Method getter = null; Method getter = null;
Method setter = null; Method setter = null;
if (!forceField) { if (!forceField) {
//noinspection ConstantConditions //noinspection ConstantConditions
if (isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault() && propertyDescriptor.getGetter().getModality() == Modality.FINAL)) { if (isInsideClass &&
(propertyDescriptor.getGetter() == null ||
propertyDescriptor.getGetter().isDefault() && propertyDescriptor.getGetter().getModality() == Modality.FINAL)) {
getter = null; getter = null;
} }
else { else {
if (isSuper) { if (isSuper) {
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel()); PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement); ClassDescriptor enclosed =
(ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
if (!CodegenUtil.isInterface(containingDeclaration)) { if (!CodegenUtil.isInterface(containingDeclaration)) {
if (enclosed != null && enclosed != context.getThisDescriptor()) { if (enclosed != null && enclosed != context.getThisDescriptor()) {
CodegenContext c = context; CodegenContext c = context;
@@ -1269,14 +1307,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (getter == null && propertyDescriptor.getReceiverParameter().exists()) { if (getter == null && propertyDescriptor.getReceiverParameter().exists()) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
} }
//noinspection ConstantConditions //noinspection ConstantConditions
if (isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault() && propertyDescriptor.getSetter().getModality() == Modality.FINAL)) { if (isInsideClass &&
(propertyDescriptor.getSetter() == null ||
propertyDescriptor.getSetter().isDefault() && propertyDescriptor.getSetter().getModality() == Modality.FINAL)) {
setter = null; setter = null;
} }
else { else {
JvmPropertyAccessorSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION); JvmPropertyAccessorSignature jvmMethodSignature =
typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
setter = jvmMethodSignature != null ? jvmMethodSignature.getJvmMethodSignature().getAsmMethod() : null; setter = jvmMethodSignature != null ? jvmMethodSignature.getJvmMethodSignature().getAsmMethod() : null;
if (propertyDescriptor.getSetter() == null) { if (propertyDescriptor.getSetter() == null) {
@@ -1306,15 +1346,21 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
// TODO ugly // TODO ugly
CallableMethod callableMethod = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper, contextKind()); CallableMethod callableMethod = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper, contextKind());
invokeOpcode = callableMethod.getInvokeOpcode(); invokeOpcode = callableMethod.getInvokeOpcode();
owner = isFakeOverride && !overridesTrait && !CodegenUtil.isInterface(initialDescriptor.getContainingDeclaration()) ? JvmClassName.byType(typeMapper.mapType(((ClassDescriptor)initialDescriptor.getContainingDeclaration()).getDefaultType(), MapTypeMode.IMPL)): callableMethod.getOwner(); owner = isFakeOverride && !overridesTrait && !CodegenUtil.isInterface(initialDescriptor.getContainingDeclaration())
? JvmClassName.byType(typeMapper.mapType(
((ClassDescriptor) initialDescriptor.getContainingDeclaration()).getDefaultType(), MapTypeMode.IMPL))
: callableMethod.getOwner();
ownerParam = callableMethod.getDefaultImplParam(); ownerParam = callableMethod.getDefaultImplParam();
} }
return StackValue.property(propertyDescriptor.getName().getName(), owner, ownerParam, asmType(propertyDescriptor.getType()), isStatic, isInterface, isSuper, getter, setter, invokeOpcode); return StackValue
.property(propertyDescriptor.getName().getName(), owner, ownerParam, asmType(propertyDescriptor.getType()), isStatic,
isInterface, isSuper, getter, setter, invokeOpcode);
} }
private PropertyDescriptor accessablePropertyDescriptor(PropertyDescriptor propertyDescriptor) { private PropertyDescriptor accessablePropertyDescriptor(PropertyDescriptor propertyDescriptor) {
if ((propertyDescriptor.getVisibility() == Visibilities.PRIVATE ||(propertyDescriptor.getSetter() != null && propertyDescriptor.getSetter().getVisibility() == Visibilities.PRIVATE)) if ((propertyDescriptor.getVisibility() == Visibilities.PRIVATE ||
(propertyDescriptor.getSetter() != null && propertyDescriptor.getSetter().getVisibility() == Visibilities.PRIVATE))
&& !DescriptorUtils.isClassObject(propertyDescriptor.getContainingDeclaration()) && !DescriptorUtils.isClassObject(propertyDescriptor.getContainingDeclaration())
&& propertyDescriptor.getContainingDeclaration() instanceof ClassDescriptor) { && propertyDescriptor.getContainingDeclaration() instanceof ClassDescriptor) {
if (context.getClassOrNamespaceDescriptor() != propertyDescriptor.getContainingDeclaration()) { if (context.getClassOrNamespaceDescriptor() != propertyDescriptor.getContainingDeclaration()) {
@@ -1324,11 +1370,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
while (c != null && c.getContextDescriptor() != enclosed) { while (c != null && c.getContextDescriptor() != enclosed) {
c = c.getParentContext(); c = c.getParentContext();
} }
if(c != null) if (c != null) {
propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor);
} }
} }
} }
}
return propertyDescriptor; return propertyDescriptor;
} }
@@ -1376,10 +1423,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
private StackValue invokeFunction(JetCallExpression expression, private StackValue invokeFunction(
JetCallExpression expression,
FunctionDescriptor fd, FunctionDescriptor fd,
StackValue receiver, StackValue receiver,
ResolvedCall<? extends CallableDescriptor> resolvedCall) { ResolvedCall<? extends CallableDescriptor> resolvedCall
) {
boolean superCall = false; boolean superCall = false;
if (expression.getParent() instanceof JetQualifiedExpression) { if (expression.getParent() instanceof JetQualifiedExpression) {
final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression(); final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
@@ -1395,7 +1444,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
if (enclosed != context.getThisDescriptor()) { if (enclosed != context.getThisDescriptor()) {
CodegenContext c = context; CodegenContext c = context;
while(!(c instanceof CodegenContexts.ClassContext) || !DescriptorUtils.isSubclass(c.getThisDescriptor(), enclosed)) { while (!(c instanceof CodegenContexts.ClassContext) ||
!DescriptorUtils.isSubclass(c.getThisDescriptor(), enclosed)) {
c = c.getParentContext(); c = c.getParentContext();
} }
fd = (FunctionDescriptor) c.getAccessor(fd); fd = (FunctionDescriptor) c.getAccessor(fd);
@@ -1483,7 +1533,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else if (fd instanceof ExpressionAsFunctionDescriptor) { else if (fd instanceof ExpressionAsFunctionDescriptor) {
return true; return true;
} }
else if (fd instanceof SimpleFunctionDescriptor && (fd.getContainingDeclaration() instanceof FunctionDescriptor || fd.getContainingDeclaration() instanceof ScriptDescriptor)) { else if (fd instanceof SimpleFunctionDescriptor &&
(fd.getContainingDeclaration() instanceof FunctionDescriptor ||
fd.getContainingDeclaration() instanceof ScriptDescriptor)) {
return true; return true;
} }
else { else {
@@ -1498,7 +1550,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
gen(expression.getCalleeExpression(), calleeType); gen(expression.getCalleeExpression(), calleeType);
} }
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
assert resolvedCall != null; assert resolvedCall != null;
if (resolvedCall instanceof VariableAsFunctionResolvedCall) { if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
@@ -1514,13 +1567,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
int mask = pushMethodArguments(expression, callableMethod.getValueParameterTypes()); int mask = pushMethodArguments(expression, callableMethod.getValueParameterTypes());
if (mask == 0) if (mask == 0) {
callableMethod.invoke(v); callableMethod.invoke(v);
else }
else {
callableMethod.invokeWithDefault(v, mask); callableMethod.invokeWithDefault(v, mask);
} }
}
private void genThisAndReceiverFromResolvedCall(StackValue receiver, ResolvedCall<? extends CallableDescriptor> resolvedCall, CallableMethod callableMethod) { private void genThisAndReceiverFromResolvedCall(
StackValue receiver,
ResolvedCall<? extends CallableDescriptor> resolvedCall,
CallableMethod callableMethod
) {
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod, state); receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod, state);
receiver.put(receiver.type, v); receiver.put(receiver.type, v);
} }
@@ -1533,9 +1592,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) { if (DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) {
ClassDescriptor containingDeclaration = (ClassDescriptor) classReceiverDeclarationDescriptor.getContainingDeclaration(); ClassDescriptor containingDeclaration = (ClassDescriptor) classReceiverDeclarationDescriptor.getContainingDeclaration();
Type classObjType = typeMapper.mapType(containingDeclaration.getDefaultType(), MapTypeMode.IMPL); Type classObjType = typeMapper.mapType(containingDeclaration.getDefaultType(), MapTypeMode.IMPL);
if (context.getContextDescriptor() instanceof ConstructorDescriptor && classReceiverDeclarationDescriptor.getDefaultType().equals(((ConstructorDescriptor)context.getContextDescriptor()).getReturnType())) { if (context.getContextDescriptor() instanceof ConstructorDescriptor &&
classReceiverDeclarationDescriptor.getDefaultType()
.equals(((ConstructorDescriptor) context.getContextDescriptor()).getReturnType())) {
v.load(0, classObjType); v.load(0, classObjType);
} else { }
else {
v.getstatic(classObjType.getInternalName(), "$classobj", exprType.getDescriptor()); v.getstatic(classObjType.getInternalName(), "$classobj", exprType.getDescriptor());
} }
StackValue.onStack(exprType).put(type, v); StackValue.onStack(exprType).put(type, v);
@@ -1596,18 +1658,21 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
cur = context; cur = context;
StackValue result = StackValue.local(0, TYPE_OBJECT); StackValue result = StackValue.local(0, TYPE_OBJECT);
while (cur != null) { while (cur != null) {
if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) {
cur = cur.getParentContext(); cur = cur.getParentContext();
}
if (cur instanceof CodegenContexts.ScriptContext) { if (cur instanceof CodegenContexts.ScriptContext) {
CodegenContexts.ScriptContext scriptContext = (CodegenContexts.ScriptContext) cur; CodegenContexts.ScriptContext scriptContext = (CodegenContexts.ScriptContext) cur;
JvmClassName currentScriptClassName = state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(scriptContext.getScriptDescriptor()); JvmClassName currentScriptClassName =
state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(scriptContext.getScriptDescriptor());
if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) { if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) {
result.put(currentScriptClassName.getAsmType(), v); result.put(currentScriptClassName.getAsmType(), v);
} }
else { else {
JvmClassName className = state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(receiver.getDeclarationDescriptor()); JvmClassName className =
state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(receiver.getDeclarationDescriptor());
String fieldName = state.getInjector().getScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor()); String fieldName = state.getInjector().getScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor());
result.put(currentScriptClassName.getAsmType(), v); result.put(currentScriptClassName.getAsmType(), v);
StackValue.field(className.getAsmType(), currentScriptClassName, fieldName, false).put(className.getAsmType(), v); StackValue.field(className.getAsmType(), currentScriptClassName, fieldName, false).put(className.getAsmType(), v);
@@ -1634,8 +1699,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Type type = asmType(calleeContainingClass.getDefaultType()); Type type = asmType(calleeContainingClass.getDefaultType());
StackValue result = StackValue.local(0, type); StackValue result = StackValue.local(0, type);
while (cur != null) { while (cur != null) {
if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) {
cur = cur.getParentContext(); cur = cur.getParentContext();
}
if (DescriptorUtils.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) { if (DescriptorUtils.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) {
if (!isObject || (cur.getThisDescriptor() == calleeContainingClass)) { if (!isObject || (cur.getThisDescriptor() == calleeContainingClass)) {
@@ -1686,8 +1752,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
else if (resolvedValueArgument instanceof DefaultValueArgument) { else if (resolvedValueArgument instanceof DefaultValueArgument) {
Type type = valueParameterTypes.get(index); Type type = valueParameterTypes.get(index);
if (type.getSort() == Type.OBJECT||type.getSort() == Type.ARRAY) if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
v.aconst(null); v.aconst(null);
}
else if (type.getSort() == Type.FLOAT) { else if (type.getSort() == Type.FLOAT) {
v.aconst(0f); v.aconst(0f);
} }
@@ -1773,7 +1840,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
public int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) { public int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
if (resolvedCall != null) { if (resolvedCall != null) {
return pushMethodArguments(resolvedCall, valueParameterTypes); return pushMethodArguments(resolvedCall, valueParameterTypes);
} }
@@ -1901,7 +1969,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
else { else {
StackValue leftValue = gen(expr); StackValue leftValue = gen(expr);
FunctionDescriptor op = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); FunctionDescriptor op =
(FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
assert op != null; assert op != null;
Type type = asmType(op.getValueParameters().get(0).getType()); Type type = asmType(op.getValueParameters().get(0).getType());
if (type.getSize() == 1) { if (type.getSize() == 1) {
@@ -2015,7 +2084,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
if (isPrimitive(leftType)) // both are primitive if (isPrimitive(leftType)) // both are primitive
{
return generateEqualsForExpressionsOnStack(opToken, leftType, rightType, false, false); return generateEqualsForExpressionsOnStack(opToken, leftType, rightType, false, false);
}
assert leftJetType != null; assert leftJetType != null;
assert rightJetType != null; assert rightJetType != null;
@@ -2038,7 +2109,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return StackValue.onStack(Type.BOOLEAN_TYPE); return StackValue.onStack(Type.BOOLEAN_TYPE);
} }
public StackValue generateEqualsForExpressionsOnStack(IElementType opToken, Type leftType, Type rightType, boolean leftNullable, boolean rightNullable) { public StackValue generateEqualsForExpressionsOnStack(
IElementType opToken,
Type leftType,
Type rightType,
boolean leftNullable,
boolean rightNullable
) {
if ((isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) { if ((isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) {
return compareExpressionsOnStack(opToken, leftType); return compareExpressionsOnStack(opToken, leftType);
} }
@@ -2216,7 +2293,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, final boolean keepReturnValue) { private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, final boolean keepReturnValue) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
assert resolvedCall != null; assert resolvedCall != null;
StackValue value = gen(expression.getLeft()); StackValue value = gen(expression.getLeft());
@@ -2305,7 +2383,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return invokeOperation(expression, (FunctionDescriptor) op, callableMethod); return invokeOperation(expression, (FunctionDescriptor) op, callableMethod);
} }
else { else {
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
assert resolvedCall != null; assert resolvedCall != null;
StackValue value = gen(expression.getBaseExpression()); StackValue value = gen(expression.getBaseExpression());
@@ -2327,7 +2406,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (functionLocalIndex >= 0) { if (functionLocalIndex >= 0) {
stackValueForLocal(op, functionLocalIndex).put(ClosureCodegen.getInternalClassName(op).getAsmType(), v); stackValueForLocal(op, functionLocalIndex).put(ClosureCodegen.getInternalClassName(op).getAsmType(), v);
} }
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
assert resolvedCall != null; assert resolvedCall != null;
genThisAndReceiverFromResolvedCall(StackValue.none(), resolvedCall, callable); genThisAndReceiverFromResolvedCall(StackValue.none(), resolvedCall, callable);
pushMethodArguments(resolvedCall, callable.getValueParameterTypes()); pushMethodArguments(resolvedCall, callable.getValueParameterTypes());
@@ -2350,9 +2430,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(ok); v.mark(ok);
return StackValue.onStack(base.type); return StackValue.onStack(base.type);
} }
else else {
return base; return base;
} }
}
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
if (op instanceof FunctionDescriptor) { if (op instanceof FunctionDescriptor) {
final Type asmType = expressionType(expression); final Type asmType = expressionType(expression);
@@ -2373,7 +2454,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return StackValue.onStack(asmType); // old value return StackValue.onStack(asmType); // old value
} }
else { else {
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
assert resolvedCall != null; assert resolvedCall != null;
final Callable callable = resolveToCallable((FunctionDescriptor) op, false); final Callable callable = resolveToCallable((FunctionDescriptor) op, false);
@@ -2386,24 +2468,30 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
switch (value.receiverSize()) { switch (value.receiverSize()) {
case 0: case 0:
if (type.getSize() == 2) if (type.getSize() == 2) {
v.dup2(); v.dup2();
else }
else {
v.dup(); v.dup();
}
break; break;
case 1: case 1:
if (type.getSize() == 2) if (type.getSize() == 2) {
v.dup2X1(); v.dup2X1();
else }
else {
v.dupX1(); v.dupX1();
}
break; break;
case 2: case 2:
if (type.getSize() == 2) if (type.getSize() == 2) {
v.dup2X2(); v.dup2X2();
else }
else {
v.dupX2(); v.dupX2();
}
break; break;
case -1: case -1:
@@ -2462,7 +2550,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (property.isScriptDeclaration()) { if (property.isScriptDeclaration()) {
JetScript scriptPsi = property.getScript(); JetScript scriptPsi = property.getScript();
JvmClassName scriptClassName = state.getInjector().getClosureAnnotator().classNameForScriptPsi(scriptPsi); JvmClassName scriptClassName = state.getInjector().getClosureAnnotator().classNameForScriptPsi(scriptPsi);
StackValue field = StackValue.field(typeMapper.mapType(variableDescriptor.getType(), MapTypeMode.VALUE), scriptClassName, property.getName(), false); StackValue field = StackValue
.field(typeMapper.mapType(variableDescriptor.getType(), MapTypeMode.VALUE), scriptClassName, property.getName(), false);
return StackValue.none(); return StackValue.none();
} }
else { else {
@@ -2474,7 +2563,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
sharedVarType = typeMapper.getSharedVarType(variableDescriptor); sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
assert variableDescriptor != null; assert variableDescriptor != null;
} }
Type varType = asmType(variableDescriptor.getType()); Type varType = asmType(variableDescriptor.getType());
@@ -2500,13 +2588,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else { else {
v.load(index, TYPE_OBJECT); v.load(index, TYPE_OBJECT);
gen(initializer, varType); gen(initializer, varType);
v.putfield(sharedVarType.getInternalName(), "ref", sharedVarType == TYPE_SHARED_VAR ? "Ljava/lang/Object;" : varType.getDescriptor()); v.putfield(sharedVarType.getInternalName(), "ref",
sharedVarType == TYPE_SHARED_VAR ? "Ljava/lang/Object;" : varType.getDescriptor());
} }
} }
return StackValue.none(); return StackValue.none();
} }
private StackValue generateConstructorCall(JetCallExpression expression, JetSimpleNameExpression constructorReference, StackValue receiver) { private StackValue generateConstructorCall(
JetCallExpression expression,
JetSimpleNameExpression constructorReference,
StackValue receiver
) {
DeclarationDescriptor constructorDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, constructorReference); DeclarationDescriptor constructorDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, constructorReference);
final PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, constructorDescriptor); final PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, constructorDescriptor);
Type type; Type type;
@@ -2533,7 +2626,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
receiver.put(receiver.type, v); receiver.put(receiver.type, v);
} }
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration())); CallableMethod method = typeMapper
.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper
.hasThis0(((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration()));
invokeMethodWithArguments(method, expression, StackValue.none()); invokeMethodWithArguments(method, expression, StackValue.none());
} }
} }
@@ -2563,8 +2658,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public void generateNewArray(JetCallExpression expression, JetType arrayType) { public void generateNewArray(JetCallExpression expression, JetType arrayType) {
List<JetExpression> args = new ArrayList<JetExpression>(); List<JetExpression> args = new ArrayList<JetExpression>();
for(ValueArgument va : expression.getValueArguments()) for (ValueArgument va : expression.getValueArguments()) {
args.add(va.getArgumentExpression()); args.add(va.getArgumentExpression());
}
args.addAll(expression.getFunctionLiteralArguments()); args.addAll(expression.getFunctionLiteralArguments());
boolean isArray = JetStandardLibraryNames.ARRAY.is(arrayType); boolean isArray = JetStandardLibraryNames.ARRAY.is(arrayType);
@@ -2634,7 +2730,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final List<JetExpression> indices = expression.getIndexExpressions(); final List<JetExpression> indices = expression.getIndexExpressions();
FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression); FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
assert operationDescriptor != null; assert operationDescriptor != null;
if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && JetStandardLibraryNames.INT.is(operationDescriptor.getValueParameters().get(0).getType())) { if (arrayType.getSort() == Type.ARRAY &&
indices.size() == 1 &&
JetStandardLibraryNames.INT.is(operationDescriptor.getValueParameters().get(0).getType())) {
gen(array, arrayType); gen(array, arrayType);
for (JetExpression index : indices) { for (JetExpression index : indices) {
gen(index, Type.INT_TYPE); gen(index, Type.INT_TYPE);
@@ -2665,8 +2763,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
int index = 0; int index = 0;
if (isGetter) { if (isGetter) {
Callable callable = resolveToCallable(getterDescriptor, false); Callable callable = resolveToCallable(getterDescriptor, false);
if (callable instanceof CallableMethod) if (callable instanceof CallableMethod) {
genThisAndReceiverFromResolvedCall(receiver, resolvedGetCall, (CallableMethod) callable); genThisAndReceiverFromResolvedCall(receiver, resolvedGetCall, (CallableMethod) callable);
}
else { else {
assert getterDescriptor != null; assert getterDescriptor != null;
gen(array, asmType(((ClassDescriptor) getterDescriptor.getContainingDeclaration()).getDefaultType())); gen(array, asmType(((ClassDescriptor) getterDescriptor.getContainingDeclaration()).getDefaultType()));
@@ -2684,8 +2783,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (callable instanceof CallableMethod) { if (callable instanceof CallableMethod) {
genThisAndReceiverFromResolvedCall(receiver, resolvedSetCall, (CallableMethod) callable); genThisAndReceiverFromResolvedCall(receiver, resolvedSetCall, (CallableMethod) callable);
} }
else else {
gen(array, arrayType); gen(array, arrayType);
}
if (setterDescriptor.getReceiverParameter().exists()) { if (setterDescriptor.getReceiverParameter().exists()) {
index++; index++;
@@ -2877,8 +2977,10 @@ The "returned" value of try expression with no finally is either the last expres
} }
// on entering the function, expressionToMatch is already placed on stack, and we should consume it // on entering the function, expressionToMatch is already placed on stack, and we should consume it
private StackValue generatePatternMatch(JetPattern pattern, boolean negated, StackValue expressionToMatch, private StackValue generatePatternMatch(
boolean expressionToMatchIsNullable, @Nullable Label nextEntry) { JetPattern pattern, boolean negated, StackValue expressionToMatch,
boolean expressionToMatchIsNullable, @Nullable Label nextEntry
) {
if (pattern instanceof JetTypePattern) { if (pattern instanceof JetTypePattern) {
JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference(); JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference();
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
@@ -2911,7 +3013,8 @@ The "returned" value of try expression with no finally is either the last expres
patternIsNullable = condJetType != null && condJetType.isNullable(); patternIsNullable = condJetType != null && condJetType.isNullable();
} }
gen(condExpression, condType); gen(condExpression, condType);
return generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable, patternIsNullable); return generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable,
patternIsNullable);
} }
else { else {
JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression(); JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression();
@@ -2938,8 +3041,10 @@ The "returned" value of try expression with no finally is either the last expres
} }
} }
private StackValue generateTuplePatternMatch(JetTuplePattern pattern, boolean negated, StackValue expressionToMatch, private StackValue generateTuplePatternMatch(
@Nullable Label nextEntry) { JetTuplePattern pattern, boolean negated, StackValue expressionToMatch,
@Nullable Label nextEntry
) {
final List<JetTuplePatternEntry> entries = pattern.getEntries(); final List<JetTuplePatternEntry> entries = pattern.getEntries();
Label lblFail = new Label(); Label lblFail = new Label();
@@ -3068,8 +3173,10 @@ The "returned" value of try expression with no finally is either the last expres
return StackValue.onStack(resultType); return StackValue.onStack(resultType);
} }
private StackValue generateWhenCondition(Type subjectType, int subjectLocal, boolean subjectIsNullable, private StackValue generateWhenCondition(
JetWhenCondition condition, @Nullable Label nextEntry) { Type subjectType, int subjectLocal, boolean subjectIsNullable,
JetWhenCondition condition, @Nullable Label nextEntry
) {
if (condition instanceof JetWhenConditionInRange) { if (condition instanceof JetWhenConditionInRange) {
JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition; JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition;
JetExpression rangeExpression = conditionInRange.getRangeExpression(); JetExpression rangeExpression = conditionInRange.getRangeExpression();
@@ -3081,7 +3188,8 @@ The "returned" value of try expression with no finally is either the last expres
getInIntRange(new StackValue.Local(subjectLocal, subjectType), (JetBinaryExpression) rangeExpression, inverted); getInIntRange(new StackValue.Local(subjectLocal, subjectType), (JetBinaryExpression) rangeExpression, inverted);
} }
else { else {
FunctionDescriptor op = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference()); FunctionDescriptor op =
(FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference());
genToJVMStack(rangeExpression); genToJVMStack(rangeExpression);
new StackValue.Local(subjectLocal, subjectType).put(TYPE_OBJECT, v); new StackValue.Local(subjectLocal, subjectType).put(TYPE_OBJECT, v);
invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v); invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v);
@@ -84,8 +84,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (myClass instanceof JetClass) { if (myClass instanceof JetClass) {
JetClass jetClass = (JetClass) myClass; JetClass jetClass = (JetClass) myClass;
if (jetClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) if (jetClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) {
isAbstract = true; isAbstract = true;
}
if (jetClass.isTrait()) { if (jetClass.isTrait()) {
isAbstract = true; isAbstract = true;
isInterface = true; isInterface = true;
@@ -170,7 +171,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (descriptor.getClassObjectDescriptor() != null) { if (descriptor.getClassObjectDescriptor() != null) {
int innerClassAccess = ACC_PUBLIC | ACC_FINAL | ACC_STATIC; int innerClassAccess = ACC_PUBLIC | ACC_FINAL | ACC_STATIC;
String outerClassInernalName = typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName(); String outerClassInernalName = typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName();
v.visitInnerClass(outerClassInernalName + JvmAbi.CLASS_OBJECT_SUFFIX, outerClassInernalName, JvmAbi.CLASS_OBJECT_CLASS_NAME, innerClassAccess); v.visitInnerClass(outerClassInernalName + JvmAbi.CLASS_OBJECT_SUFFIX, outerClassInernalName, JvmAbi.CLASS_OBJECT_CLASS_NAME,
innerClassAccess);
} }
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor); AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
@@ -245,7 +247,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
signatureVisitor.writeSupersEnd(); signatureVisitor.writeSupersEnd();
return new JvmClassSignature(jvmName(), superClass, superInterfaces, signatureVisitor.makeJavaString(), signatureVisitor.makeKotlinClassSignature()); return new JvmClassSignature(jvmName(), superClass, superInterfaces, signatureVisitor.makeJavaString(),
signatureVisitor.makeKotlinClassSignature());
} }
private String jvmName() { private String jvmName() {
@@ -261,8 +264,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) {
return; return;
}
if (kind != OwnerKind.IMPLEMENTATION) { if (kind != OwnerKind.IMPLEMENTATION) {
throw new IllegalStateException("must be impl to reach this code: " + kind); throw new IllegalStateException("must be impl to reach this code: " + kind);
@@ -282,10 +286,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
if (superClassType == null) { if (superClassType == null) {
if (myClass instanceof JetClass && ((JetClass) myClass).hasModifier(JetTokens.ENUM_KEYWORD)) { if (descriptor.getKind() == ClassKind.ENUM_CLASS) {
superClassType = JetStandardLibrary.getInstance().getEnumType(descriptor.getDefaultType()); superClassType = JetStandardLibrary.getInstance().getEnumType(descriptor.getDefaultType());
superClass = typeMapper.mapType(superClassType, MapTypeMode.VALUE).getInternalName(); superClass = typeMapper.mapType(superClassType, MapTypeMode.VALUE).getInternalName();
} }
if (descriptor.getKind() == ClassKind.ENUM_ENTRY) {
superClassType = descriptor.getTypeConstructor().getSupertypes().iterator().next();
superClass = typeMapper.mapType(superClassType, MapTypeMode.VALUE).getInternalName();
}
} }
} }
@@ -317,12 +325,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateEnumMethods() { private void generateEnumMethods() {
if (myEnumConstants.size() > 0) { if (myEnumConstants.size() > 0) {
{ {
Type type = typeMapper.mapType(JetStandardLibrary.getInstance().getArrayType(descriptor.getDefaultType()), MapTypeMode.IMPL); Type type =
typeMapper.mapType(JetStandardLibrary.getInstance().getArrayType(descriptor.getDefaultType()), MapTypeMode.IMPL);
MethodVisitor mv = MethodVisitor mv =
v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null); v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null);
mv.visitCode(); mv.visitCode();
mv.visitFieldInsn(GETSTATIC, typeMapper.mapType(descriptor.getDefaultType(),MapTypeMode.VALUE).getInternalName(), VALUES, type.getDescriptor()); mv.visitFieldInsn(GETSTATIC, typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(), VALUES,
type.getDescriptor());
mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;"); mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, type.getInternalName()); mv.visitTypeInsn(CHECKCAST, type.getInternalName());
mv.visitInsn(ARETURN); mv.visitInsn(ARETURN);
@@ -393,10 +403,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod(); Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, method.getName(), method.getDescriptor(), null, null); MethodVisitor mv =
v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(),
originalSignature.getJvmMethodSignature().getKotlinTypeParameter(), originalSignature.getJvmMethodSignature().getKotlinTypeParameter(),
original, ((PropertyDescriptor) entry.getValue()).getGetter().getVisibility()); original,
((PropertyDescriptor) entry.getValue()).getGetter().getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); StubCodegen.generateStubCode(mv);
} }
@@ -406,25 +418,30 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
if (original.getVisibility() == Visibilities.PRIVATE) if (original.getVisibility() == Visibilities.PRIVATE) {
iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(), original.getName().getName(), originalMethod.getReturnType().getDescriptor()); iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(), original.getName().getName(),
else originalMethod.getReturnType().getDescriptor());
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(), originalMethod.getName(), originalMethod.getDescriptor()); }
else {
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(),
originalMethod.getName(), originalMethod.getDescriptor());
}
iv.areturn(method.getReturnType()); iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null); FunctionCodegen.endVisit(iv, "accessor", null);
} }
} }
if (bridge.isVar()) if (bridge.isVar()) {
{
Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod(); Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, ACC_STATIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null); MethodVisitor mv =
v.newMethod(null, ACC_STATIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(),
originalSignature2.getJvmMethodSignature().getKotlinTypeParameter(), originalSignature2.getJvmMethodSignature().getKotlinTypeParameter(),
original, ((PropertyDescriptor) entry.getValue()).getSetter().getVisibility()); original,
((PropertyDescriptor) entry.getValue()).getSetter().getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); StubCodegen.generateStubCode(mv);
} }
@@ -441,10 +458,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
//noinspection AssignmentToForLoopParameter //noinspection AssignmentToForLoopParameter
reg += argType.getSize(); reg += argType.getSize();
} }
if (original.getVisibility() == Visibilities.PRIVATE && original.getModality() == Modality.FINAL) if (original.getVisibility() == Visibilities.PRIVATE && original.getModality() == Modality.FINAL) {
iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(), original.getName().getName(), originalMethod.getArgumentTypes()[0].getDescriptor()); iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(), original.getName().getName(),
else originalMethod.getArgumentTypes()[0].getDescriptor());
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(), originalMethod.getName(), originalMethod.getDescriptor()); }
else {
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(),
originalMethod.getName(), originalMethod.getDescriptor());
}
iv.areturn(method.getReturnType()); iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null); FunctionCodegen.endVisit(iv, "accessor", null);
@@ -471,7 +492,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.putstatic(name, "$instance", typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getDescriptor()); v.putstatic(name, "$instance", typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getDescriptor());
} }
}); });
} }
} }
@@ -501,8 +521,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void generatePrimaryConstructor() { protected void generatePrimaryConstructor() {
if (myClass instanceof JetClass) { if (myClass instanceof JetClass) {
JetClass aClass = (JetClass) myClass; JetClass aClass = (JetClass) myClass;
if (aClass.isTrait()) if (aClass.isTrait()) {
return; return;
}
if (aClass.isAnnotation()) { if (aClass.isAnnotation()) {
return; return;
} }
@@ -529,7 +550,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (hasThis0) { if (hasThis0) {
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0); signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
typeMapper.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), signatureWriter, MapTypeMode.VALUE); typeMapper
.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), signatureWriter,
MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd(); signatureWriter.writeParameterTypeEnd();
} }
@@ -538,10 +561,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
signatureWriter.writeVoidReturn(); signatureWriter.writeVoidReturn();
constructorMethod = signatureWriter.makeJvmMethodSignature("<init>"); constructorMethod = signatureWriter.makeJvmMethodSignature("<init>");
callableMethod = new CallableMethod(JvmClassName.byInternalName("Ignored"), null, null, constructorMethod, INVOKESPECIAL, null, null, null); callableMethod =
new CallableMethod(JvmClassName.byInternalName("Ignored"), null, null, constructorMethod, INVOKESPECIAL, null, null,
null);
} }
else { else {
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind,
typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
constructorMethod = callableMethod.getSignature(); constructorMethod = callableMethod.getSignature();
} }
@@ -566,22 +592,28 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ObjectOrClosureCodegen closure = context.closure; ObjectOrClosureCodegen closure = context.closure;
int firstSuperArgument = -1; int firstSuperArgument = -1;
final LinkedList<JvmMethodParameterSignature> consArgTypes = new LinkedList<JvmMethodParameterSignature>(constructorMethod.getKotlinParameterTypes()); final LinkedList<JvmMethodParameterSignature> consArgTypes =
new LinkedList<JvmMethodParameterSignature>(constructorMethod.getKotlinParameterTypes());
int insert = 0; int insert = 0;
if (closure != null) { if (closure != null) {
if (closure.captureThis != null) { if (closure.captureThis != null) {
if (!hasThis0) if (!hasThis0) {
consArgTypes.add(insert, new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName().getName()), "", JvmMethodParameterKind.THIS0)); consArgTypes.add(insert,
new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName().getName()),
"", JvmMethodParameterKind.THIS0));
}
insert++; insert++;
} }
else { else {
if (hasThis0) if (hasThis0) {
insert++; insert++;
} }
}
if (closure.captureReceiver != null) if (closure.captureReceiver != null) {
consArgTypes.add(insert++, new JvmMethodParameterSignature(closure.captureReceiver, "", JvmMethodParameterKind.RECEIVER)); consArgTypes.add(insert++, new JvmMethodParameterSignature(closure.captureReceiver, "", JvmMethodParameterKind.RECEIVER));
}
for (DeclarationDescriptor descriptor : closure.closure.keySet()) { for (DeclarationDescriptor descriptor : closure.closure.keySet()) {
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) { if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
@@ -591,7 +623,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
type = sharedVarType; type = sharedVarType;
} }
else { else {
type = state.getInjector().getJetTypeMapper().mapType(((VariableDescriptor) descriptor).getType(), MapTypeMode.VALUE); type = state.getInjector().getJetTypeMapper()
.mapType(((VariableDescriptor) descriptor).getType(), MapTypeMode.VALUE);
} }
consArgTypes.add(insert++, new JvmMethodParameterSignature(type, "", JvmMethodParameterKind.SHARED_VAR)); consArgTypes.add(insert++, new JvmMethodParameterSignature(type, "", JvmMethodParameterKind.SHARED_VAR));
} }
@@ -603,14 +636,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (myClass instanceof JetObjectDeclaration && ((JetObjectDeclaration) myClass).isObjectLiteral()) { if (myClass instanceof JetObjectDeclaration && ((JetObjectDeclaration) myClass).isObjectLiteral()) {
if (superCall instanceof JetDelegatorToSuperCall) { if (superCall instanceof JetDelegatorToSuperCall) {
if (closure != null) if (closure != null) {
closure.superCall = (JetDelegatorToSuperCall) superCall; closure.superCall = (JetDelegatorToSuperCall) superCall;
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression()); }
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET,
((JetDelegatorToSuperCall) superCall).getCalleeExpression()
.getConstructorReferenceExpression());
if (declarationDescriptor instanceof ClassDescriptor) { if (declarationDescriptor instanceof ClassDescriptor) {
declarationDescriptor = ((ClassDescriptorFromSource) declarationDescriptor).getUnsubstitutedPrimaryConstructor(); declarationDescriptor = ((ClassDescriptorFromSource) declarationDescriptor).getUnsubstitutedPrimaryConstructor();
} }
ConstructorDescriptor superConstructor = (ConstructorDescriptor) declarationDescriptor; ConstructorDescriptor superConstructor = (ConstructorDescriptor) declarationDescriptor;
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration())); CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper
.hasThis0(superConstructor.getContainingDeclaration()));
firstSuperArgument = insert; firstSuperArgument = insert;
for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) { for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR)); consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
@@ -621,7 +658,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
int flags = JetTypeMapper.getAccessModifiers(constructorDescriptor, 0); int flags = JetTypeMapper.getAccessModifiers(constructorDescriptor, 0);
final MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(), constructorMethod.getGenericsSignature(), null); final MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(),
constructorMethod.getGenericsSignature(), null);
if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) return; if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) return;
AnnotationVisitor jetConstructorVisitor = mv.visitAnnotation(JvmStdlibNames.JET_CONSTRUCTOR.getDescriptor(), true); AnnotationVisitor jetConstructorVisitor = mv.visitAnnotation(JvmStdlibNames.JET_CONSTRUCTOR.getDescriptor(), true);
@@ -642,13 +680,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
i++; i++;
} }
if(myClass instanceof JetClass && ((JetClass)myClass).hasModifier(JetTokens.ENUM_KEYWORD)) { if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) {
i += 2; i += 2;
} }
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) { for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
AnnotationCodegen.forParameter(i, mv, state.getInjector().getJetTypeMapper()).genAnnotations(valueParameter); AnnotationCodegen.forParameter(i, mv, state.getInjector().getJetTypeMapper()).genAnnotations(valueParameter);
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i); JetValueParameterAnnotationWriter jetValueParameterAnnotation =
JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
jetValueParameterAnnotation.writeName(valueParameter.getName().getName()); jetValueParameterAnnotation.writeName(valueParameter.getName().getName());
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue()); jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue());
jetValueParameterAnnotation.writeType(constructorMethod.getKotlinParameterType(i)); jetValueParameterAnnotation.writeType(constructorMethod.getKotlinParameterType(i));
@@ -694,7 +733,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (superCall == null) { if (superCall == null) {
iv.load(0, Type.getType("L" + superClass + ";")); iv.load(0, Type.getType("L" + superClass + ";"));
if(descriptor.getKind() == ClassKind.ENUM_CLASS) { if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) {
iv.load(1, JetTypeMapper.JL_STRING_TYPE); iv.load(1, JetTypeMapper.JL_STRING_TYPE);
iv.load(2, Type.INT_TYPE); iv.load(2, Type.INT_TYPE);
iv.invokespecial(superClass, "<init>", "(Ljava/lang/String;I)V"); iv.invokespecial(superClass, "<init>", "(Ljava/lang/String;I)V");
@@ -711,14 +750,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (typeMapper.hasThis0(superClassDescriptor)) { if (typeMapper.hasThis0(superClassDescriptor)) {
iv.load(1, JetTypeMapper.TYPE_OBJECT); iv.load(1, JetTypeMapper.TYPE_OBJECT);
parameterTypes.add(typeMapper.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), MapTypeMode.VALUE)); parameterTypes.add(typeMapper.mapType(
typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), MapTypeMode.VALUE));
} }
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(), "<init>", superCallMethod.getDescriptor()); iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(), "<init>",
superCallMethod.getDescriptor());
} }
else { else {
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression()); ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap, firstSuperArgument); ((JetDelegatorToSuperCall) superCall)
.getCalleeExpression()
.getConstructorReferenceExpression());
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap,
firstSuperArgument);
} }
final ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor); final ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor);
@@ -738,7 +783,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (closure.captureReceiver != null) { if (closure.captureReceiver != null) {
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(1, closure.captureReceiver); iv.load(1, closure.captureReceiver);
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(), "receiver$0", closure.captureReceiver.getDescriptor()); iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(), "receiver$0",
closure.captureReceiver.getDescriptor());
k += closure.captureReceiver.getSize(); k += closure.captureReceiver.getSize();
} }
@@ -752,7 +798,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(k, StackValue.refType(sharedVarType)); iv.load(k, StackValue.refType(sharedVarType));
k += StackValue.refType(sharedVarType).getSize(); k += StackValue.refType(sharedVarType).getSize();
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(), "$" + varDescr.getName(), sharedVarType.getDescriptor()); iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.VALUE).getInternalName(),
"$" + varDescr.getName(), sharedVarType.getDescriptor());
l++; l++;
} }
} }
@@ -760,8 +807,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
int n = 0; int n = 0;
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
if (specifier == superCall) if (specifier == superCall) {
continue; continue;
}
if (specifier instanceof JetDelegatorByExpressionSpecifier) { if (specifier instanceof JetDelegatorByExpressionSpecifier) {
iv.load(0, classType); iv.load(0, classType);
@@ -779,8 +827,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetClass superClass = (JetClass) BindingContextUtils.classDescriptorToDeclaration(bindingContext, superClassDescriptor); JetClass superClass = (JetClass) BindingContextUtils.classDescriptorToDeclaration(bindingContext, superClassDescriptor);
final CodegenContext delegateContext = context.intoClass(superClassDescriptor, final CodegenContext delegateContext = context.intoClass(superClassDescriptor,
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false), new OwnerKind.DelegateKind(StackValue.field(fieldType, classname,
typeMapper.mapType(superClassDescriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName()), state.getInjector().getJetTypeMapper()); delegateField, false),
typeMapper.mapType(superClassDescriptor
.getDefaultType(),
MapTypeMode.IMPL)
.getInternalName()),
state.getInjector().getJetTypeMapper());
generateDelegates(superClass, delegateContext, field); generateDelegates(superClass, delegateContext, field);
} }
} }
@@ -803,12 +856,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitInsn(RETURN); mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "constructor", myClass); FunctionCodegen.endVisit(mv, "constructor", myClass);
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor, OwnerKind.IMPLEMENTATION); FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor,
OwnerKind.IMPLEMENTATION);
} }
private void generateTraitMethods() { private void generateTraitMethods() {
if (myClass instanceof JetClass && (((JetClass)myClass).isTrait() || ((JetClass)myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD))) if (myClass instanceof JetClass &&
(((JetClass) myClass).isTrait() || ((JetClass) myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD))) {
return; return;
}
for (Pair<CallableMemberDescriptor, CallableMemberDescriptor> needDelegates : getTraitImplementations(descriptor)) { for (Pair<CallableMemberDescriptor, CallableMemberDescriptor> needDelegates : getTraitImplementations(descriptor)) {
CallableMemberDescriptor callableDescriptor = needDelegates.first; CallableMemberDescriptor callableDescriptor = needDelegates.first;
@@ -843,11 +899,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
PropertyDescriptor property = ((PropertyAccessorDescriptor) fun).getCorrespondingProperty(); PropertyDescriptor property = ((PropertyAccessorDescriptor) fun).getCorrespondingProperty();
if (fun instanceof PropertyGetterDescriptor) { if (fun instanceof PropertyGetterDescriptor) {
function = typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); function = typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
functionOriginal = typeMapper.mapGetterSignature(property.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); functionOriginal =
typeMapper.mapGetterSignature(property.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature()
.getAsmMethod();
} }
else if (fun instanceof PropertySetterDescriptor) { else if (fun instanceof PropertySetterDescriptor) {
function = typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); function = typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
functionOriginal = typeMapper.mapSetterSignature(property.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); functionOriginal =
typeMapper.mapSetterSignature(property.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature()
.getAsmMethod();
} }
else { else {
throw new IllegalStateException("Accessor is neither getter, nor setter, what is it?"); throw new IllegalStateException("Accessor is neither getter, nor setter, what is it?");
@@ -861,14 +921,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(fun); AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(fun);
JvmMethodSignature jvmSignature = typeMapper.mapToCallableMethod(inheritedFun, false, OwnerKind.IMPLEMENTATION).getSignature(); JvmMethodSignature jvmSignature =
typeMapper.mapToCallableMethod(inheritedFun, false, OwnerKind.IMPLEMENTATION).getSignature();
JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv); JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv);
BitSet kotlinFlags = CodegenUtil.getFlagsForVisibility(fun.getVisibility()); BitSet kotlinFlags = CodegenUtil.getFlagsForVisibility(fun.getVisibility());
if (fun instanceof PropertyAccessorDescriptor) { if (fun instanceof PropertyAccessorDescriptor) {
kotlinFlags.set(JvmStdlibNames.FLAG_PROPERTY_BIT); kotlinFlags.set(JvmStdlibNames.FLAG_PROPERTY_BIT);
aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter()); aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter());
aw.writePropertyType(jvmSignature.getKotlinReturnType()); aw.writePropertyType(jvmSignature.getKotlinReturnType());
} else { }
else {
aw.writeNullableReturnType(fun.getReturnType().isNullable()); aw.writeNullableReturnType(fun.getReturnType().isNullable());
aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter()); aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter());
aw.writeReturnType(jvmSignature.getKotlinReturnType()); aw.writeReturnType(jvmSignature.getKotlinReturnType());
@@ -882,7 +944,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
FrameMap frameMap = context.prepareFrame(state.getInjector().getJetTypeMapper()); FrameMap frameMap = context.prepareFrame(state.getInjector().getJetTypeMapper());
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getAsmMethod().getReturnType(), context, state); ExpressionCodegen codegen =
new ExpressionCodegen(mv, frameMap, jvmSignature.getAsmMethod().getReturnType(), context, state);
codegen.generateThisOrOuter(descriptor); // ??? wouldn't it be a good idea to put it? codegen.generateThisOrOuter(descriptor); // ??? wouldn't it be a good idea to put it?
Type[] argTypes = function.getArgumentTypes(); Type[] argTypes = function.getArgumentTypes();
@@ -905,9 +968,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
String fdescriptor = functionOriginal.getDescriptor().replace("(", "(" + type.getDescriptor()); String fdescriptor = functionOriginal.getDescriptor().replace("(", "(" + type.getDescriptor());
Type type1 = typeMapper.mapType(((ClassDescriptor) fun.getContainingDeclaration()).getDefaultType(), MapTypeMode.TRAIT_IMPL); Type type1 =
typeMapper.mapType(((ClassDescriptor) fun.getContainingDeclaration()).getDefaultType(), MapTypeMode.TRAIT_IMPL);
iv.invokestatic(type1.getInternalName(), function.getName(), fdescriptor); iv.invokestatic(type1.getInternalName(), function.getName(), fdescriptor);
if (function.getReturnType().getSort() == Type.OBJECT && !function.getReturnType().equals(functionOriginal.getReturnType())) { if (function.getReturnType().getSort() == Type.OBJECT &&
!function.getReturnType().equals(functionOriginal.getReturnType())) {
iv.checkcast(function.getReturnType()); iv.checkcast(function.getReturnType());
} }
iv.areturn(function.getReturnType()); iv.areturn(function.getReturnType());
@@ -919,26 +984,36 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall, private void generateDelegatorToConstructorCall(
InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
ConstructorDescriptor constructorDescriptor, ConstructorDescriptor constructorDescriptor,
ConstructorFrameMap frameMap, int firstSuperArgument) { ConstructorFrameMap frameMap, int firstSuperArgument
) {
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration(); ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
iv.load(0, TYPE_OBJECT); iv.load(0, TYPE_OBJECT);
if(classDecl.getKind() == ClassKind.ENUM_CLASS) { if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) {
iv.load(1, JetTypeMapper.TYPE_OBJECT); iv.load(1, JetTypeMapper.TYPE_OBJECT);
iv.load(2, Type.INT_TYPE); iv.load(2, Type.INT_TYPE);
} }
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) { if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
iv.load(frameMap.getOuterThisIndex(), typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), MapTypeMode.IMPL)); iv.load(frameMap.getOuterThisIndex(),
typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), MapTypeMode.IMPL));
} }
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); CallableMethod method = typeMapper
.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
if (myClass instanceof JetObjectDeclaration && superCall instanceof JetDelegatorToSuperCall && ((JetObjectDeclaration) myClass).isObjectLiteral()) { if (myClass instanceof JetObjectDeclaration &&
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression()); superCall instanceof JetDelegatorToSuperCall &&
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration())); ((JetObjectDeclaration) myClass).isObjectLiteral()) {
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
((JetDelegatorToSuperCall) superCall)
.getCalleeExpression()
.getConstructorReferenceExpression());
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION,
typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
int nextVar = firstSuperArgument + 1; int nextVar = firstSuperArgument + 1;
for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) { for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
iv.load(nextVar, t); iv.load(nextVar, t);
@@ -999,7 +1074,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.iconst(ordinal); iv.iconst(ordinal);
// TODO type and constructor parameters // TODO type and constructor parameters
String implClass = typeMapper.mapType(myType, MapTypeMode.IMPL).getInternalName(); ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant);
String implClass = typeMapper.mapType(classDescriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName();
final List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers(); final List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
if (delegationSpecifiers.size() > 1) { if (delegationSpecifiers.size() > 1) {
@@ -1016,8 +1092,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final JetDelegationSpecifier specifier = delegationSpecifiers.get(0); final JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
if (specifier instanceof JetDelegatorToSuperCall) { if (specifier instanceof JetDelegatorToSuperCall) {
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier; final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression()); ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) bindingContext
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); .get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper
.hasThis0(constructorDescriptor.getContainingDeclaration()));
codegen.invokeMethodWithArguments(method, superCall, StackValue.none()); codegen.invokeMethodWithArguments(method, superCall, StackValue.none());
} }
else { else {
@@ -1028,14 +1106,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.invokespecial(implClass, "<init>", "(Ljava/lang/String;I)V"); iv.invokespecial(implClass, "<init>", "(Ljava/lang/String;I)V");
} }
iv.dup(); iv.dup();
iv.putstatic(implClass, enumConstant.getName(), "L" + implClass + ";"); iv.putstatic(myAsmType.getInternalName(), enumConstant.getName(), "L" + myAsmType.getInternalName() + ";");
iv.astore(TYPE_OBJECT); iv.astore(TYPE_OBJECT);
} }
iv.putstatic(myAsmType.getInternalName(), "$VALUES", arrayAsmType.getDescriptor()); iv.putstatic(myAsmType.getInternalName(), "$VALUES", arrayAsmType.getDescriptor());
} }
public static void generateInitializers(@NotNull ExpressionCodegen codegen, @NotNull InstructionAdapter iv, @NotNull List<JetDeclaration> declarations, public static void generateInitializers(
@NotNull BindingContext bindingContext, @NotNull JetTypeMapper typeMapper) { @NotNull ExpressionCodegen codegen, @NotNull InstructionAdapter iv, @NotNull List<JetDeclaration> declarations,
@NotNull BindingContext bindingContext, @NotNull JetTypeMapper typeMapper
) {
for (JetDeclaration declaration : declarations) { for (JetDeclaration declaration : declarations) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, declaration); final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, declaration);
@@ -1049,33 +1129,43 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Type type = typeMapper.mapType(propertyDescriptor.getType(), MapTypeMode.VALUE); Type type = typeMapper.mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
if (JetTypeMapper.isPrimitive(type)) { if (JetTypeMapper.isPrimitive(type)) {
if (!propertyDescriptor.getType().isNullable() && value instanceof Number) { if (!propertyDescriptor.getType().isNullable() && value instanceof Number) {
if (type == Type.INT_TYPE && ((Number)value).intValue() == 0) if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) {
continue;
if (type == Type.BYTE_TYPE && ((Number)value).byteValue() == 0)
continue;
if (type == Type.LONG_TYPE && ((Number)value).longValue() == 0L)
continue;
if (type == Type.SHORT_TYPE && ((Number)value).shortValue() == 0)
continue;
if (type == Type.DOUBLE_TYPE && ((Number)value).doubleValue() == 0d)
continue;
if (type == Type.FLOAT_TYPE && ((Number)value).byteValue() == 0f)
continue; continue;
} }
if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean)value)) if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) {
continue; continue;
if (type == Type.CHAR_TYPE && value instanceof Character && ((Character)value) == 0) }
if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) {
continue; continue;
} }
if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) {
continue;
}
if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) {
continue;
}
if (type == Type.FLOAT_TYPE && ((Number) value).byteValue() == 0f) {
continue;
}
}
if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) {
continue;
}
if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) {
continue;
}
}
else { else {
if (value == null) if (value == null) {
continue; continue;
} }
} }
}
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type type = codegen.expressionType(initializer); Type type = codegen.expressionType(initializer);
if (propertyDescriptor.getType().isNullable()) if (propertyDescriptor.getType().isNullable()) {
type = JetTypeMapper.boxType(type); type = JetTypeMapper.boxType(type);
}
codegen.gen(initializer, type); codegen.gen(initializer, type);
// @todo write directly to the field. Fix test excloset.jet::test6 // @todo write directly to the field. Fix test excloset.jet::test6
JvmClassName owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.IMPLEMENTATION); JvmClassName owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.IMPLEMENTATION);
@@ -1083,7 +1173,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
StackValue.property(propertyDescriptor.getName().getName(), owner, owner, StackValue.property(propertyDescriptor.getName().getName(), owner, owner,
propType, false, false, false, null, null, 0).store(propType, iv); propType, false, false, false, null, null, 0).store(propType, iv);
} }
} }
} }
else if (declaration instanceof JetClassInitializer) { else if (declaration instanceof JetClassInitializer) {
@@ -1105,7 +1194,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) { for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
if (overriddenDescriptor.getContainingDeclaration() == classDescriptor) { if (overriddenDescriptor.getContainingDeclaration() == classDescriptor) {
if (declaration instanceof PropertyDescriptor) { if (declaration instanceof PropertyDescriptor) {
propertyCodegen.genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field); propertyCodegen
.genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field);
} }
else if (declaration instanceof SimpleFunctionDescriptor) { else if (declaration instanceof SimpleFunctionDescriptor) {
functionCodegen.genDelegate((SimpleFunctionDescriptor) declaration, overriddenDescriptor, field); functionCodegen.genDelegate((SimpleFunctionDescriptor) declaration, overriddenDescriptor, field);
@@ -1141,7 +1231,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
continue; continue;
} }
Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor); Collection<CallableMemberDescriptor> overriddenDeclarations =
OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor);
for (CallableMemberDescriptor overriddenDeclaration : overriddenDeclarations) { for (CallableMemberDescriptor overriddenDeclaration : overriddenDeclarations) {
if (overriddenDeclaration.getModality() != Modality.ABSTRACT) { if (overriddenDeclaration.getModality() != Modality.ABSTRACT) {
if (!CodegenUtil.isInterface(overriddenDeclaration.getContainingDeclaration())) { if (!CodegenUtil.isInterface(overriddenDeclaration.getContainingDeclaration())) {
@@ -1159,5 +1250,4 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return r; return r;
} }
} }
@@ -306,11 +306,13 @@ public class JetTypeMapper {
return JvmClassName.byInternalName(r.toString()); return JvmClassName.byInternalName(r.toString());
} }
@NotNull public Type mapReturnType(@NotNull final JetType jetType) { @NotNull
public Type mapReturnType(@NotNull final JetType jetType) {
return mapReturnType(jetType, null); return mapReturnType(jetType, null);
} }
@NotNull private Type mapReturnType(@NotNull final JetType jetType, @Nullable BothSignatureWriter signatureVisitor) { @NotNull
private Type mapReturnType(@NotNull final JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
if (jetType.equals(JetStandardClasses.getUnitType())) { if (jetType.equals(JetStandardClasses.getUnitType())) {
if (signatureVisitor != null) { if (signatureVisitor != null) {
signatureVisitor.writeAsmType(Type.VOID_TYPE, false); signatureVisitor.writeAsmType(Type.VOID_TYPE, false);
@@ -375,9 +377,14 @@ public class JetTypeMapper {
} }
} }
else if (klass.getKind() == ClassKind.ENUM_ENTRY) { else if (klass.getKind() == ClassKind.ENUM_ENTRY) {
if (closureAnnotator.enumEntryNeedSubclass(klass)) {
return getJvmInternalFQName(klass.getContainingDeclaration()) + "$" + klass.getName().getName();
}
else {
return getJvmInternalFQName(klass.getContainingDeclaration()); return getJvmInternalFQName(klass.getContainingDeclaration());
} }
} }
}
DeclarationDescriptor container = descriptor.getContainingDeclaration(); DeclarationDescriptor container = descriptor.getContainingDeclaration();
@@ -511,7 +518,8 @@ public class JetTypeMapper {
Type type = mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind); Type type = mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
if (signatureVisitor != null) { if (signatureVisitor != null) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor(); TypeParameterDescriptor typeParameterDescriptor =
(TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor();
assert typeParameterDescriptor != null; assert typeParameterDescriptor != null;
signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), jetType.isNullable(), type); signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), jetType.isNullable(), type);
} }
@@ -584,7 +592,9 @@ public class JetTypeMapper {
} }
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) { public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
if (functionDescriptor == null) { return null; } if (functionDescriptor == null) {
return null;
}
final DeclarationDescriptor functionParent = functionDescriptor.getOriginal().getContainingDeclaration(); final DeclarationDescriptor functionParent = functionDescriptor.getOriginal().getContainingDeclaration();
@@ -614,7 +624,8 @@ public class JetTypeMapper {
thisClass = null; thisClass = null;
} }
else if (functionParent instanceof ScriptDescriptor) { else if (functionParent instanceof ScriptDescriptor) {
thisClass = owner = ownerForDefaultParam = ownerForDefaultImpl = closureAnnotator.classNameForScriptDescriptor((ScriptDescriptor) functionParent); thisClass = owner =
ownerForDefaultParam = ownerForDefaultImpl = closureAnnotator.classNameForScriptDescriptor((ScriptDescriptor) functionParent);
invokeOpcode = INVOKEVIRTUAL; invokeOpcode = INVOKEVIRTUAL;
} }
else if (functionParent instanceof ClassDescriptor) { else if (functionParent instanceof ClassDescriptor) {
@@ -673,7 +684,9 @@ public class JetTypeMapper {
} }
private static boolean isAccessor(FunctionDescriptor functionDescriptor) { private static boolean isAccessor(FunctionDescriptor functionDescriptor) {
return functionDescriptor instanceof AccessorForFunctionDescriptor || functionDescriptor instanceof AccessorForPropertyDescriptor.Getter || functionDescriptor instanceof AccessorForPropertyDescriptor.Setter; return functionDescriptor instanceof AccessorForFunctionDescriptor ||
functionDescriptor instanceof AccessorForPropertyDescriptor.Getter ||
functionDescriptor instanceof AccessorForPropertyDescriptor.Setter;
} }
@NotNull @NotNull
@@ -763,7 +776,8 @@ public class JetTypeMapper {
} }
private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) { private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) {
signatureVisitor.writeFormalTypeParameter(typeParameterDescriptor.getName().getName(), typeParameterDescriptor.getVariance(), typeParameterDescriptor.isReified()); signatureVisitor.writeFormalTypeParameter(typeParameterDescriptor.getName().getName(), typeParameterDescriptor.getVariance(),
typeParameterDescriptor.isReified());
classBound: classBound:
{ {
@@ -801,7 +815,6 @@ public class JetTypeMapper {
} }
signatureVisitor.writeFormalTypeParameterEnd(); signatureVisitor.writeFormalTypeParameterEnd();
} }
public JvmMethodSignature mapSignature(Name name, FunctionDescriptor f) { public JvmMethodSignature mapSignature(Name name, FunctionDescriptor f) {
@@ -863,7 +876,8 @@ public class JetTypeMapper {
else { else {
if (descriptor instanceof AccessorForPropertyDescriptor) { if (descriptor instanceof AccessorForPropertyDescriptor) {
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS); signatureWriter.writeParameterType(JvmMethodParameterKind.THIS);
mapType(((ClassifierDescriptor)descriptor.getContainingDeclaration()).getDefaultType(), signatureWriter, MapTypeMode.VALUE); mapType(((ClassifierDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), signatureWriter,
MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd(); signatureWriter.writeParameterTypeEnd();
} }
} }
@@ -910,7 +924,8 @@ public class JetTypeMapper {
else { else {
if (descriptor instanceof AccessorForPropertyDescriptor) { if (descriptor instanceof AccessorForPropertyDescriptor) {
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS); signatureWriter.writeParameterType(JvmMethodParameterKind.THIS);
mapType(((ClassifierDescriptor)descriptor.getContainingDeclaration()).getDefaultType(), signatureWriter, MapTypeMode.VALUE); mapType(((ClassifierDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), signatureWriter,
MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd(); signatureWriter.writeParameterTypeEnd();
} }
} }
@@ -930,7 +945,8 @@ public class JetTypeMapper {
signatureWriter.writeVoidReturn(); signatureWriter.writeVoidReturn();
JvmMethodSignature jvmMethodSignature = signatureWriter.makeJvmMethodSignature(name); JvmMethodSignature jvmMethodSignature = signatureWriter.makeJvmMethodSignature(name);
return new JvmPropertyAccessorSignature(jvmMethodSignature, jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1)); return new JvmPropertyAccessorSignature(jvmMethodSignature,
jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1));
} }
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, boolean hasThis0) { private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, boolean hasThis0) {
@@ -947,11 +963,12 @@ public class JetTypeMapper {
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration(); ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (hasThis0) { if (hasThis0) {
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0); signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
mapType(closureAnnotator.getEclosingClassDescriptor(containingDeclaration).getDefaultType(), signatureWriter, MapTypeMode.VALUE); mapType(closureAnnotator.getEclosingClassDescriptor(containingDeclaration).getDefaultType(), signatureWriter,
MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd(); signatureWriter.writeParameterTypeEnd();
} }
if(containingDeclaration.getKind() == ClassKind.ENUM_CLASS) { if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_NAME); signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_NAME);
mapType(JetStandardLibrary.getInstance().getStringType(), signatureWriter, MapTypeMode.VALUE); mapType(JetStandardLibrary.getInstance().getStringType(), signatureWriter, MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd(); signatureWriter.writeParameterTypeEnd();
@@ -983,7 +1000,8 @@ public class JetTypeMapper {
for (ScriptDescriptor importedScript : importedScripts) { for (ScriptDescriptor importedScript : importedScripts) {
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
mapType(closureAnnotator.classDescriptorForScriptDescriptor(importedScript).getDefaultType(), signatureWriter, MapTypeMode.VALUE); mapType(closureAnnotator.classDescriptorForScriptDescriptor(importedScript).getDefaultType(), signatureWriter,
MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd(); signatureWriter.writeParameterTypeEnd();
} }
@@ -1064,19 +1082,22 @@ public class JetTypeMapper {
} }
public static boolean isGenericsArray(JetType type) { public static boolean isGenericsArray(JetType type) {
return JetStandardLibraryNames.ARRAY.is(type) && type.getArguments().get(0).getType().getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor; return JetStandardLibraryNames.ARRAY.is(type) &&
type.getArguments().get(0).getType().getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor;
} }
public Type getSharedVarType(DeclarationDescriptor descriptor) { public Type getSharedVarType(DeclarationDescriptor descriptor) {
if (descriptor instanceof PropertyDescriptor) { if (descriptor instanceof PropertyDescriptor) {
return StackValue.sharedTypeForType(mapType(((PropertyDescriptor) descriptor).getReceiverParameter().getType(), MapTypeMode.VALUE)); return StackValue
.sharedTypeForType(mapType(((PropertyDescriptor) descriptor).getReceiverParameter().getType(), MapTypeMode.VALUE));
} }
else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
return closureAnnotator.classNameForAnonymousClass((JetElement) psiElement).getAsmType(); return closureAnnotator.classNameForAnonymousClass((JetElement) psiElement).getAsmType();
} }
else if (descriptor instanceof FunctionDescriptor) { else if (descriptor instanceof FunctionDescriptor) {
return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType(), MapTypeMode.VALUE)); return StackValue
.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType(), MapTypeMode.VALUE));
} }
else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(descriptor)) { else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(descriptor)) {
JetType outType = ((VariableDescriptor) descriptor).getType(); JetType outType = ((VariableDescriptor) descriptor).getType();
@@ -0,0 +1,10 @@
fun box() = IssueState.DEFAULT.ToString() + IssueState.FIXED.ToString()
open enum class IssueState {
DEFAULT
FIXED {
override fun ToString() = "K"
}
open fun ToString() : String = "O"
}
@@ -100,4 +100,35 @@ public class EnumGenTest extends CodegenTestCase {
public void testInClassObj() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { public void testInClassObj() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
blackBoxFile("enum/inclassobj.kt"); blackBoxFile("enum/inclassobj.kt");
} }
public void testAbstractMethod()
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
blackBoxFile("enum/abstractmethod.kt");
}
public void testNoClassForSimpleEnum()
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
loadFile("enum/name.kt");
Class cls = loadImplementationClass(generateClassesInFile(), "State");
Field field = cls.getField("O");
assertEquals("State", field.get(null).getClass().getName());
}
public void testYesClassForComplexEnum()
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
loadFile("enum/abstractmethod.kt");
Class cls = loadImplementationClass(generateClassesInFile(), "IssueState");
Field field = cls.getField("DEFAULT");
assertEquals("IssueState", field.get(null).getClass().getName());
field = cls.getField("FIXED");
assertEquals("IssueState", field.getType().getName());
assertEquals("IssueState$FIXED", field.get(null).getClass().getName());
assertNotNull(cls.getClassLoader().loadClass("IssueState$FIXED"));
try {
cls.getClassLoader().loadClass("IssueState$DEFAULT");
fail();
}
catch (ClassNotFoundException e) {
}
}
} }