diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index d16da2e54b1..36eed72bf4a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -4,7 +4,6 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -28,11 +27,11 @@ public abstract class ClassBodyCodegen { protected final OwnerKind kind; protected final ClassDescriptor descriptor; protected final ClassBuilder v; - protected final ClassContext context; + protected final CodegenContext context; protected final List staticInitializerChunks = new ArrayList(); - public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) { + public ClassBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) { this.state = state; descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); myClass = aClass; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index ef3c7bfc6fd..3bb8e9bcc2f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -19,12 +18,12 @@ public class ClassCodegen { this.state = state; } - public void generate(ClassContext context, JetClassOrObject aClass) { + public void generate(CodegenContext context, JetClassOrObject aClass) { GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper()); ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); - final ClassContext contextForInners = context.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION); + final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION); for (JetDeclaration declaration : aClass.getDeclarations()) { if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) { generate(contextForInners, (JetClass) declaration); @@ -34,17 +33,15 @@ public class ClassCodegen { generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors); } - private void generateImplementation(ClassContext context, JetClassOrObject aClass, OwnerKind kind, HashMap accessors) { + private void generateImplementation(CodegenContext context, JetClassOrObject aClass, OwnerKind kind, HashMap accessors) { ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); ClassBuilder v = state.forClassImplementation(descriptor); - ClassContext classContext = context.intoClass(null, descriptor, kind); + CodegenContext classContext = context.intoClass(descriptor, kind); new ImplementationBodyCodegen(aClass, classContext, v, state).generate(accessors); if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) { v = state.forTraitImplementation(descriptor); - new TraitImplBodyCodegen(aClass, context.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(null); + new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(null); } } - - } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java deleted file mode 100644 index 74e12a5228e..00000000000 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java +++ /dev/null @@ -1,258 +0,0 @@ -package org.jetbrains.jet.codegen; - -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.psi.JetTypeReference; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; -import org.jetbrains.jet.lang.types.JetType; -import org.objectweb.asm.Type; -import org.objectweb.asm.commons.InstructionAdapter; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_GETTER_RETURN_TYPE; - -/* - * @author max - * @author alex.tkachman - */ -public class ClassContext { - public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null, null); - private final DeclarationDescriptor contextType; - private final OwnerKind contextKind; - private final StackValue thisExpression; - final ClassContext parentContext; - public final FunctionOrClosureCodegen closure; - private boolean thisWasUsed = false; - - HashMap typeInfoConstants; - HashMap accessors; - - public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) { - this.contextType = contextType; - this.contextKind = contextKind; - this.thisExpression = thisExpression; - this.parentContext = parentContext; - closure = closureCodegen; - } - - public DeclarationDescriptor getContextDescriptor() { - return contextType; - } - - public String getNamespaceClassName() { - if(parentContext != STATIC) - return parentContext.getNamespaceClassName(); - - return NamespaceCodegen.getJVMClassName(contextType.getName()); - } - - public OwnerKind getContextKind() { - return contextKind; - } - - public StackValue getThisExpression() { - if (parentContext == null) return StackValue.none(); - - thisWasUsed = true; - if (thisExpression != null) return thisExpression; - return parentContext.getThisExpression(); - } - - public ClassContext intoNamespace(NamespaceDescriptor descriptor) { - return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this, null); - } - - public ClassContext intoClass(@Nullable FunctionOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) { - final StackValue thisValue; - thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); - - return new ClassContext(descriptor, kind, thisValue, this, closure); - } - - public ClassContext intoFunction(FunctionDescriptor descriptor) { - int thisIdx = -1; - if (getContextKind() != OwnerKind.NAMESPACE) { - thisIdx++; - } - - final boolean hasReceiver = descriptor.getReceiverParameter().exists(); - if (hasReceiver) { - thisIdx++; - } - - return new ClassContext(descriptor, getContextKind(), hasReceiver ? StackValue.local(thisIdx, JetTypeMapper.TYPE_OBJECT) : null, this, null); - } - - public ClassContext intoClosure(String internalClassName, ClosureCodegen closureCodegen) { - final Type type = enclosingClassType(closureCodegen.state.getTypeMapper()); - StackValue outerClass = type != null - ? StackValue.instanceField(type, internalClassName, "this$0") - : StackValue.local(0, JetTypeMapper.TYPE_OBJECT); - return new ClassContext(null, OwnerKind.IMPLEMENTATION, outerClass, this, closureCodegen); - } - - public FrameMap prepareFrame() { - FrameMap frameMap = new FrameMap(); - - if (getContextKind() != OwnerKind.NAMESPACE) { - frameMap.enterTemp(); // 0 slot for this - } - - if (hasReceiver()) { - frameMap.enterTemp(); // Next slot for fake this - } - - return frameMap; - } - - private ReceiverDescriptor receiver() { - return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverParameter() : ReceiverDescriptor.NO_RECEIVER; - } - - private boolean hasReceiver() { - return receiver().exists(); - } - - public ClassContext getParentContext() { - return parentContext; - } - - public Type jvmType(JetTypeMapper mapper) { - if (contextType instanceof ClassDescriptor) { - return mapper.jvmType((ClassDescriptor) contextType, contextKind); - } - else if (closure != null) { - return Type.getObjectType(closure.name); - } - else { - return parentContext != null ? parentContext.jvmType(mapper) : JetTypeMapper.TYPE_OBJECT; - } - } - - public DeclarationDescriptor getContextClass() { - DeclarationDescriptor descriptor = getContextDescriptor(); - if (descriptor == null || descriptor instanceof ClassDescriptor || descriptor instanceof NamespaceDescriptor) return descriptor; - - final ClassContext parent = getParentContext(); - return parent != null ? parent.getContextClass() : null; - } - - public boolean isThisWasUsed() { - return thisWasUsed; - } - - public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) { - final FunctionOrClosureCodegen top = closure; - if (top != null) { - final StackValue answer = top.lookupInContext(d); - if (answer != null) return answer; - - final StackValue thisContext = getThisExpression(); - if(thisContext instanceof StackValue.Local) { - } - else if(thisContext instanceof StackValue.InstanceField) { - StackValue.InstanceField instanceField = (StackValue.InstanceField) thisContext; - v.getfield(instanceField.owner, instanceField.name, instanceField.type.getDescriptor()); - } - else { - throw new UnsupportedOperationException(); - } - } - - return parentContext != null ? parentContext.lookupInContext(d, v) : null; - } - - public Type enclosingClassType(JetTypeMapper mapper) { - DeclarationDescriptor descriptor = getContextDescriptor(); - if (descriptor instanceof ClassDescriptor) { - return Type.getObjectType(mapper.jvmName((ClassDescriptor) descriptor, OwnerKind.IMPLEMENTATION)); - } - - if (descriptor instanceof NamespaceDescriptor) { - return null; - } - - if (closure != null) { - return Type.getObjectType(closure.name); - } - - final ClassContext parent = getParentContext(); - return parent != null ? parent.enclosingClassType(mapper) : null; - } - - public int getTypeInfoConstantIndex(JetType type) { - if(parentContext != STATIC) - return parentContext.getTypeInfoConstantIndex(type); - - if(typeInfoConstants == null) - typeInfoConstants = new HashMap(); - - Integer index = typeInfoConstants.get(type); - if(index == null) { - index = typeInfoConstants.size(); - typeInfoConstants.put(type, index); - } - return index; - } - - DeclarationDescriptor getAccessor(DeclarationDescriptor descriptor) { - if(accessors == null) { - accessors = new HashMap(); - } - descriptor = descriptor.getOriginal(); - DeclarationDescriptor accessor = accessors.get(descriptor); - if(accessor != null) - return accessor; - - if(descriptor instanceof FunctionDescriptor) { - FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType, - Collections.emptyList(), - descriptor.getName() + "$bridge$" + accessors.size()); - FunctionDescriptor fd = (FunctionDescriptor) descriptor; - myAccessor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null, - fd.getExpectedThisObject(), - fd.getTypeParameters(), - fd.getValueParameters(), - fd.getReturnType(), - fd.getModality(), - fd.getVisibility()); - accessor = myAccessor; - } - else if(descriptor instanceof PropertyDescriptor) { - PropertyDescriptor pd = (PropertyDescriptor) descriptor; - PropertyDescriptor myAccessor = new PropertyDescriptor(contextType, - Collections.emptyList(), - pd.getModality(), - pd.getVisibility(), - pd.isVar(), - pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null, - pd.getExpectedThisObject(), - pd.getName() + "$bridge$" + accessors.size(), - pd.getInType(), - pd.getOutType()); - PropertyGetterDescriptor pgd = new PropertyGetterDescriptor( - myAccessor, Collections.emptyList(), myAccessor.getModality(), - myAccessor.getVisibility(), - myAccessor.getOutType(), false, false); - PropertySetterDescriptor psd = new PropertySetterDescriptor( - myAccessor.getModality(), - myAccessor.getVisibility(), - myAccessor, - Collections.emptyList(), - false, false); - myAccessor.initialize(Collections.emptyList(), pgd, psd); - accessor = myAccessor; - } - else { - throw new UnsupportedOperationException(); - } - accessors.put(descriptor, accessor); - return accessor; - } -} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 9217feb4cce..6f3ec66699d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -5,14 +5,14 @@ package org.jetbrains.jet.codegen; import com.intellij.openapi.util.Pair; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; -import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.JetFunctionLiteral; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; @@ -22,13 +22,14 @@ import org.objectweb.asm.commons.Method; import org.objectweb.asm.signature.SignatureWriter; import java.util.Arrays; +import java.util.Collections; import java.util.List; import static org.objectweb.asm.Opcodes.*; -public class ClosureCodegen extends FunctionOrClosureCodegen { +public class ClosureCodegen extends ObjectOrClosureCodegen { - public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) { + public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, CodegenContext context) { super(exprContext, context, state); } @@ -80,7 +81,8 @@ public class ClosureCodegen extends FunctionOrClosureCodegen { generateBridge(name, funDescriptor, fun, cv); captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral()); - final Type enclosingType = context.enclosingClassType(state.getTypeMapper()); + ClassDescriptor thisDescriptor = context.getThisDescriptor(); + final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName()); if (enclosingType == null) captureThis = false; final Method constructor = generateConstructor(funClass, captureThis, fun, funDescriptor.getReturnType()); @@ -128,10 +130,21 @@ public class ClosureCodegen extends FunctionOrClosureCodegen { } private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) { - final ClassContext closureContext = context.intoClosure(name, this); + int arity = funDescriptor.getValueParameters().size(); + + ClassDescriptorImpl function = new ClassDescriptorImpl( + funDescriptor, + Collections.emptyList(), + name); + function = function.initialize( + false, + Collections.emptyList(), + Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.emptySet(), null); + + final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor); - return closureContext.isThisWasUsed(); + return closureContext.isOuterWasUsed(); } private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) { @@ -185,7 +198,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen { int i = 0; if (captureThis) { i = 1; - argTypes[0] = context.enclosingClassType(state.getTypeMapper()); + argTypes[0] = Type.getObjectType(context.getThisDescriptor().getName()); } for (DeclarationDescriptor descriptor : closure.keySet()) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java new file mode 100644 index 00000000000..49013ecafb3 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -0,0 +1,364 @@ +package org.jetbrains.jet.codegen; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.resolve.DescriptorRenderer; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.Collections; +import java.util.HashMap; + +/* + * @author max + * @author alex.tkachman + */ +public abstract class CodegenContext { + public static final CodegenContext STATIC = new CodegenContext(null, OwnerKind.NAMESPACE, null, null) { + @Override + protected ClassDescriptor getThisDescriptor() { + return null; + } + }; + + protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); + protected static final StackValue local1 = StackValue.local(1, JetTypeMapper.TYPE_OBJECT); + + private final DeclarationDescriptor contextType; + + private final OwnerKind contextKind; + private final CodegenContext parentContext; + public final ObjectOrClosureCodegen closure; + + HashMap typeInfoConstants; + HashMap accessors; + + protected DeclarationDescriptor outerDescriptor; + protected DeclarationDescriptor outerReceiverDescriptor; + + protected StackValue outerExpression; + + protected StackValue outerReceiverExpression; + + protected boolean outerWasUsed = false; + + public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) { + this.contextType = contextType; + this.contextKind = contextKind; + this.parentContext = parentContext; + closure = closureCodegen; + } + + protected abstract ClassDescriptor getThisDescriptor (); + + protected DeclarationDescriptor getReceiverDescriptor() { + return null; + } + + protected StackValue getOuterExpression(@Nullable StackValue prefix) { + if(outerExpression == null) + throw new UnsupportedOperationException(); + + outerWasUsed = true; + return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression; + } + + public DeclarationDescriptor getContextDescriptor() { + return contextType; + } + + public String getNamespaceClassName() { + if(parentContext != STATIC) + return parentContext.getNamespaceClassName(); + + return NamespaceCodegen.getJVMClassName(contextType.getName()); + } + + public OwnerKind getContextKind() { + return contextKind; + } + + public CodegenContext intoNamespace(NamespaceDescriptor descriptor) { + return new NamespaceContext(descriptor, this); + } + + public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind) { + return new ClassContext(descriptor, kind, this); + } + + public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) { + return new AnonymousClassContext(descriptor, kind, this, closure); + } + + public MethodContext intoFunction(FunctionDescriptor descriptor) { + return new MethodContext(descriptor, getContextKind(), this); + } + + public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) { + if(descriptor == null) { + descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.emptyList(), true) + .initialize(Collections.emptyList(), Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC); + } + return new ConstructorContext(descriptor, getContextKind(), this); + } + + public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen) { + return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName); + } + + public FrameMap prepareFrame() { + FrameMap frameMap = new FrameMap(); + + if (getContextKind() != OwnerKind.NAMESPACE) { + frameMap.enterTemp(); // 0 slot for this + } + + if (getReceiverDescriptor() != null) { + frameMap.enterTemp(); // Next slot for fake this + } + + return frameMap; + } + + public CodegenContext getParentContext() { + return parentContext; + } + + public Type jvmType(JetTypeMapper mapper) { + if (contextType instanceof ClassDescriptor) { + return mapper.jvmType((ClassDescriptor) contextType, contextKind); + } + else if (closure != null) { + return Type.getObjectType(closure.name); + } + else { + return parentContext != null ? parentContext.jvmType(mapper) : JetTypeMapper.TYPE_OBJECT; + } + } + + public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) { + final ObjectOrClosureCodegen top = closure; + if (top != null) { + final StackValue answer = top.lookupInContext(d); + if (answer != null) return answer; + + getOuterExpression(null).put(JetTypeMapper.TYPE_OBJECT, v); + } + + return parentContext != null ? parentContext.lookupInContext(d, v) : null; + } + + public Type enclosingClassType() { + CodegenContext cur = getParentContext(); + while(cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor)) + cur = cur.getParentContext(); + + return cur == null ? null : Type.getObjectType(cur.getContextDescriptor().getName()); + } + + public int getTypeInfoConstantIndex(JetType type) { + if(parentContext != STATIC) + return parentContext.getTypeInfoConstantIndex(type); + + if(typeInfoConstants == null) + typeInfoConstants = new HashMap(); + + Integer index = typeInfoConstants.get(type); + if(index == null) { + index = typeInfoConstants.size(); + typeInfoConstants.put(type, index); + } + return index; + } + + DeclarationDescriptor getAccessor(DeclarationDescriptor descriptor) { + if(accessors == null) { + accessors = new HashMap(); + } + descriptor = descriptor.getOriginal(); + DeclarationDescriptor accessor = accessors.get(descriptor); + if(accessor != null) + return accessor; + + if(descriptor instanceof FunctionDescriptor) { + FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType, + Collections.emptyList(), + descriptor.getName() + "$bridge$" + accessors.size()); + FunctionDescriptor fd = (FunctionDescriptor) descriptor; + myAccessor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null, + fd.getExpectedThisObject(), + fd.getTypeParameters(), + fd.getValueParameters(), + fd.getReturnType(), + fd.getModality(), + fd.getVisibility()); + accessor = myAccessor; + } + else if(descriptor instanceof PropertyDescriptor) { + PropertyDescriptor pd = (PropertyDescriptor) descriptor; + PropertyDescriptor myAccessor = new PropertyDescriptor(contextType, + Collections.emptyList(), + pd.getModality(), + pd.getVisibility(), + pd.isVar(), + pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null, + pd.getExpectedThisObject(), + pd.getName() + "$bridge$" + accessors.size(), + pd.getInType(), + pd.getOutType()); + PropertyGetterDescriptor pgd = new PropertyGetterDescriptor( + myAccessor, Collections.emptyList(), myAccessor.getModality(), + myAccessor.getVisibility(), + myAccessor.getOutType(), false, false); + PropertySetterDescriptor psd = new PropertySetterDescriptor( + myAccessor.getModality(), + myAccessor.getVisibility(), + myAccessor, + Collections.emptyList(), + false, false); + myAccessor.initialize(Collections.emptyList(), pgd, psd); + accessor = myAccessor; + } + else { + throw new UnsupportedOperationException(); + } + accessors.put(descriptor, accessor); + return accessor; + } + + public boolean isOuterWasUsed() { + return outerWasUsed; + } + + public StackValue getReceiverExpression() { + assert getReceiverDescriptor() != null; + return getThisDescriptor() != null ? local1 : local0; + } + + public StackValue getThisExpression() { + assert getThisDescriptor() != null; + return local0; + } + + public abstract static class FunctionContext extends CodegenContext { + final DeclarationDescriptor receiverDescriptor; + + public FunctionContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) { + super(contextType, contextKind, parentContext, closureCodegen); + receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor() : null; + } + + @Override + protected DeclarationDescriptor getReceiverDescriptor() { + return receiverDescriptor; + } + } + + public static class MethodContext extends FunctionContext { + public MethodContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) { + super(contextType, contextKind, parentContext, null); + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return getParentContext().getThisDescriptor(); + } + + public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) { + return getParentContext().lookupInContext(d, v); + } + + public Type enclosingClassType() { + return getParentContext().enclosingClassType(); + } + + protected StackValue getOuterExpression(StackValue prefix) { + return getParentContext().getOuterExpression(prefix); + } + } + + public static class ConstructorContext extends MethodContext { + public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent) { + super(contextType, kind, parent); + + final Type type = enclosingClassType(); + outerExpression = type != null + ? local1 + : null; + } + + protected StackValue getOuterExpression(StackValue prefix) { + return outerExpression; + } + } + + public static class ClassContext extends CodegenContext { + public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) { + super(contextType, contextKind, parentContext, null); + + final Type type = enclosingClassType(); + outerExpression = type != null + ? StackValue.field(type, DescriptorRenderer.getFQName(contextType).replace('.', '/'), "this$0", false) + : null; + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return (ClassDescriptor) getContextDescriptor(); + } + } + + public static class AnonymousClassContext extends CodegenContext { + public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure) { + super(contextType, contextKind, parentContext, closure); + + final Type type = enclosingClassType(); + outerExpression = type != null + ? StackValue.field(type, closure.state.getTypeMapper().jvmName(contextType, OwnerKind.IMPLEMENTATION), "this$0", false) + : null; + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return (ClassDescriptor) getContextDescriptor(); + } + } + + public static class ClosureContext extends FunctionContext { + private ClassDescriptor classDescriptor; + + public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName) { + super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen); + this.classDescriptor = classDescriptor; + + final Type type = enclosingClassType(); + outerExpression = type != null + ? StackValue.field(type, internalClassName, "this$0", false) + : null; + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return classDescriptor; + } + + @Override + public DeclarationDescriptor getContextDescriptor() { + return classDescriptor; + } + } + + public static class NamespaceContext extends CodegenContext { + public NamespaceContext(NamespaceDescriptor contextType, CodegenContext parent) { + super(contextType, OwnerKind.NAMESPACE, parent, null); + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return null; + } + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e1417c28c82..45682099f46 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -51,7 +51,7 @@ public class ExpressionCodegen extends JetVisitor { private int myLastLineNumber = -1; - private final InstructionAdapter v; + final InstructionAdapter v; private final FrameMap myFrameMap; private final JetTypeMapper typeMapper; @@ -60,13 +60,13 @@ public class ExpressionCodegen extends JetVisitor { private final BindingContext bindingContext; private final Map typeParameterExpressions = new HashMap(); - private final ClassContext context; + private final CodegenContext context; private final IntrinsicMethods intrinsics; public ExpressionCodegen(MethodVisitor v, FrameMap myMap, Type returnType, - ClassContext context, + CodegenContext context, GenerationState state) { this.myFrameMap = myMap; this.typeMapper = state.getTypeMapper(); @@ -140,7 +140,7 @@ public class ExpressionCodegen extends JetVisitor { // return generateThisOrOuter((ClassDescriptor) descriptor); // } // else { -// return thisExpression(); +// return local0(); // } return StackValue.none(); } @@ -333,10 +333,6 @@ public class ExpressionCodegen extends JetVisitor { return context.getContextKind(); } - private StackValue thisExpression() { - return context.getThisExpression(); - } - private abstract class ForLoopGenerator { protected JetForExpression expression; protected Type loopRangeType; @@ -601,7 +597,7 @@ public class ExpressionCodegen extends JetVisitor { @Override public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) { - FunctionOrClosureCodegen closureCodegen = new FunctionOrClosureCodegen(this, context, state); + ObjectOrClosureCodegen closureCodegen = new ObjectOrClosureCodegen(this, context, state); GeneratedAnonymousClassDescriptor closure = state.generateObjectLiteral(expression, closureCodegen); Type type = Type.getObjectType(closure.getClassname()); v.anew(type); @@ -888,7 +884,7 @@ public class ExpressionCodegen extends JetVisitor { String owner; boolean isInterface; - boolean isInsideClass = containingDeclaration == context.getContextClass(); + boolean isInsideClass = containingDeclaration == context.getThisDescriptor(); if (isInsideClass || isStatic) { owner = typeMapper.getOwner(functionDescriptor, contextKind()); isInterface = false; @@ -915,10 +911,12 @@ public class ExpressionCodegen extends JetVisitor { public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, @Nullable JetSuperExpression superExpression) { boolean isSuper = superExpression != null; - DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); + DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration().getOriginal(); boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl; propertyDescriptor = propertyDescriptor.getOriginal(); - boolean isInsideClass = containingDeclaration == context.getContextClass() && contextKind() != OwnerKind.TRAIT_IMPL; + boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) || + (context.getParentContext() instanceof CodegenContext.NamespaceContext) && context.getParentContext().getContextDescriptor() == containingDeclaration) + && contextKind() != OwnerKind.TRAIT_IMPL; Method getter; Method setter; if (forceField) { @@ -935,8 +933,8 @@ public class ExpressionCodegen extends JetVisitor { PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel()); ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement); if(!CodegenUtil.isInterface(propertyDescriptor.getContainingDeclaration())) { - if(enclosed != null && enclosed != context.getContextClass()) { - ClassContext c = context; + if(enclosed != null && enclosed != context.getThisDescriptor()) { + CodegenContext c = context; while(c.getContextDescriptor() != enclosed) { c = c.getParentContext(); } @@ -1002,12 +1000,12 @@ public class ExpressionCodegen extends JetVisitor { PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel()); ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement); if(!CodegenUtil.isInterface(fd.getContainingDeclaration())) { - if(enclosed != null && enclosed != context.getContextClass()) { - ClassContext c = context; + if(enclosed != null && enclosed != context.getThisDescriptor()) { + CodegenContext c = context; while(c.getContextDescriptor() != enclosed) { c = c.getParentContext(); } - fd = c.getAccessor((FunctionDescriptor) fd); + fd = c.getAccessor(fd); superCall = false; } } @@ -1150,41 +1148,31 @@ public class ExpressionCodegen extends JetVisitor { } public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) { - boolean thisDone = false; - StackValue result = null; + CodegenContext cur = context; + if(cur.getReceiverDescriptor() == calleeContainingClass) { + return cur.getReceiverExpression(); + } - ClassContext cur = context; - while (true) { - ClassContext parentContext = cur.getParentContext(); - if (parentContext == null) break; + StackValue result = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); + while (cur != null) { + if(cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext)) + cur = cur.getParentContext(); - final DeclarationDescriptor curContextType = cur.getContextDescriptor(); - if (curContextType instanceof ClassDescriptor) { - if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break; - - final StackValue outer; - if (!thisDone && myFrameMap instanceof ConstructorFrameMap) { - outer = StackValue.local(((ConstructorFrameMap) myFrameMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT); - } - else { - thisToStack(); - outer = StackValue.field(parentContext.jvmType(typeMapper), - cur.jvmType(typeMapper).getInternalName(), - "this$0", - false); - } - - thisDone = true; - result = outer; + if (isSubclass(cur.getThisDescriptor(), calleeContainingClass)) { + Type type = typeMapper.mapType(calleeContainingClass.getDefaultType()); + result.put(JetTypeMapper.TYPE_OBJECT, v); + return StackValue.onStack(type); } - cur = parentContext; - } + result = cur.getOuterExpression(result); - if (!thisDone) { - return thisExpression(); + if(cur instanceof CodegenContext.ConstructorContext) { + cur = cur.getParentContext(); + } + cur = cur.getParentContext(); } - return result; + + throw new UnsupportedOperationException(); } private static boolean isReceiver(PsiElement expression) { @@ -2082,15 +2070,15 @@ public class ExpressionCodegen extends JetVisitor { return generateThisOrOuter((ClassDescriptor) descriptor); } else { - // estension function or ??? - return thisExpression(); + if(descriptor instanceof FunctionDescriptor) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; + Type type = typeMapper.mapType(functionDescriptor.getReceiverParameter().getType()); + return StackValue.local(descriptor.getContainingDeclaration() instanceof NamespaceDescriptor ? 0 : 1, type); + } + throw new UnsupportedOperationException(); } } - public void thisToStack() { - thisExpression().put(JetTypeMapper.TYPE_OBJECT, v); - } - @Override public StackValue visitTryExpression(JetTryExpression expression, StackValue receiver) { Label tryStart = new Label(); @@ -2374,13 +2362,13 @@ public class ExpressionCodegen extends JetVisitor { return; } DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); - if (context.getContextClass() instanceof ClassDescriptor) { - ClassDescriptor descriptor = (ClassDescriptor) context.getContextClass(); + if (context.getThisDescriptor() instanceof ClassDescriptor) { + ClassDescriptor descriptor = (ClassDescriptor) context.getThisDescriptor(); assert containingDeclaration != null; JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType(); Type ownerType = typeMapper.mapType(defaultType); ownerType = JetTypeMapper.boxType(ownerType); - if (containingDeclaration == context.getContextClass()) { + if (containingDeclaration == context.getThisDescriptor()) { if(!CodegenUtil.isInterface(descriptor)) { if (CodegenUtil.hasTypeInfoField(defaultType)) { v.load(0, JetTypeMapper.TYPE_OBJECT); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 36520f2170b..b2fae930c34 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -22,11 +22,11 @@ import static org.objectweb.asm.Opcodes.*; * @author alex.tkachman */ public class FunctionCodegen { - private final ClassContext owner; + private final CodegenContext owner; private final ClassBuilder v; private final GenerationState state; - public FunctionCodegen(ClassContext owner, ClassBuilder v, GenerationState state) { + public FunctionCodegen(CodegenContext owner, ClassBuilder v, GenerationState state) { this.owner = owner; this.v = v; this.state = state; @@ -40,7 +40,7 @@ public class FunctionCodegen { } public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) { - ClassContext funContext = owner.intoFunction(functionDescriptor); + CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor); final JetExpression bodyExpression = f.getBodyExpression(); generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f); @@ -48,7 +48,7 @@ public class FunctionCodegen { private void generatedMethod(JetExpression bodyExpressions, Method jvmSignature, - ClassContext context, + CodegenContext.MethodContext context, FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun) { List paramDescrs = functionDescriptor.getValueParameters(); @@ -67,9 +67,8 @@ public class FunctionCodegen { if (isAbstract) flags |= ACC_ABSTRACT; final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null); - boolean hasReceiver = functionDescriptor.getReceiverParameter().exists(); if(kind != OwnerKind.TRAIT_IMPL) { - int start = hasReceiver ? 1 : 0; + int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0; for(int i = 0; i != paramDescrs.size(); ++i) { AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "jet/typeinfo/JetParameterName", true); annotationVisitor.visit("value", paramDescrs.get(i).getName()); @@ -78,16 +77,12 @@ public class FunctionCodegen { } if (!isAbstract) { mv.visitCode(); - Label methodStart = new Label(); - mv.visitLabel(methodStart); - FrameMap frameMap = context.prepareFrame(); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state); Type[] argTypes = jvmSignature.getArgumentTypes(); - int receiverSize = !hasReceiver ? 0 : state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize(); - int add = hasReceiver ? 1 : 0; + int add = functionDescriptor.getReceiverParameter().exists() ? state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize() : 0; for (int i = 0; i < paramDescrs.size(); i++) { ValueParameterDescriptor parameter = paramDescrs.get(i); frameMap.enter(parameter, argTypes[i+add].getSize()); @@ -128,18 +123,8 @@ public class FunctionCodegen { codegen.returnExpression(bodyExpressions); } - - Label methodEnd = new Label(); - mv.visitLabel(methodEnd); - int index = ((flags & ACC_STATIC) != 0 ? 0 : 1) + receiverSize; - for (int i = 0; i < paramDescrs.size(); i++) { - ValueParameterDescriptor parameter = paramDescrs.get(i); - mv.visitLocalVariable(parameter.getName(), state.getTypeMapper().mapType(parameter.getOutType()).getDescriptor(), null, methodStart, methodEnd, index); - index += argTypes[i+add].getSize(); - } - try { - mv.visitMaxs(0, 0); + mv.visitMaxs(0, 0); } catch (Throwable t) { System.out.println(t); @@ -153,7 +138,7 @@ public class FunctionCodegen { generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind); } - static void generateBridgeIfNeeded(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { + static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { Set overriddenFunctions = functionDescriptor.getOverriddenDescriptors(); if(kind != OwnerKind.TRAIT_IMPL) { for (FunctionDescriptor overriddenFunction : overriddenFunctions) { @@ -164,8 +149,8 @@ public class FunctionCodegen { } } - static void generateDefaultIfNeeded(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { - DeclarationDescriptor contextClass = owner.getContextClass(); + static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { + DeclarationDescriptor contextClass = ((FunctionDescriptor)owner.getContextDescriptor()).getContainingDeclaration(); if(kind != OwnerKind.TRAIT_IMPL) { // we don't generate defaults for traits but do for traitImpl @@ -307,7 +292,7 @@ public class FunctionCodegen { } } - private static void checkOverride(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) { + private static void checkOverride(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) { Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType()); Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType()); if(!type1.equals(type2)) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index a517e32fe52..7b9ddd28fab 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -114,13 +114,13 @@ public class GenerationState { } } - public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) { + public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) { JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); Pair nameAndVisitor = forAnonymousSubclass(objectDeclaration); closure.cv = nameAndVisitor.getSecond(); closure.name = nameAndVisitor.getFirst(); - final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION); + final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION); new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 3b49f22f643..660aaa8206b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -29,7 +29,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private JetDelegationSpecifier superCall; private String superClass = "java/lang/Object"; - public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) { + public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) { super(aClass, context, v, state); } @@ -290,6 +290,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass); + CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor); + Method method; CallableMethod callableMethod; if (constructorDescriptor == null) { @@ -337,7 +339,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, descriptor, kind); final InstructionAdapter iv = new InstructionAdapter(mv); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state); + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state); for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) { if(constructorDescriptor != null) @@ -405,7 +407,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.putfield(classname, delegateField, fieldDesc); JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor); - final ClassContext delegateContext = context.intoClass(null, superClassDescriptor, + final CodegenContext delegateContext = context.intoClass(superClassDescriptor, new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false), state.getTypeMapper().jvmNameForImplementation(superClassDescriptor, OwnerKind.IMPLEMENTATION))); generateDelegates(superClass, delegateContext, overridden); @@ -441,10 +443,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - generateInitializers(codegen, iv); - - generateTraitMethods(codegen); - int curParam = 0; List constructorParameters = getPrimaryConstructorParameters(); for (JetParameter parameter : constructorParameters) { @@ -458,6 +456,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { curParam++; } + generateInitializers(codegen, iv); + + generateTraitMethods(codegen); + mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); @@ -741,7 +743,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - protected void generateDelegates(JetClass toClass, ClassContext delegateContext, Set overriden) { + protected void generateDelegates(JetClass toClass, CodegenContext delegateContext, Set overriden) { final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state); final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index f0ea12f8ae3..06fcb015ad1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -44,7 +44,7 @@ public class NamespaceCodegen { } public void generate(JetNamespace namespace) { - final ClassContext context = ClassContext.STATIC.intoNamespace(state.getBindingContext().get(BindingContext.NAMESPACE, namespace)); + final CodegenContext context = CodegenContext.STATIC.intoNamespace(state.getBindingContext().get(BindingContext.NAMESPACE, namespace)); final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state); final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state); @@ -85,7 +85,7 @@ public class NamespaceCodegen { mv.visitCode(); FrameMap frameMap = new FrameMap(); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, ClassContext.STATIC, state); + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state); for (JetDeclaration declaration : namespace.getDeclarations()) { if (declaration instanceof JetProperty) { @@ -103,7 +103,7 @@ public class NamespaceCodegen { mv.visitEnd(); } - private void generateTypeInfoFields(JetNamespace namespace, ClassContext context) { + private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) { if(context.typeInfoConstants != null) { String jvmClassName = getJVMClassName(namespace.getName()); for(Map.Entry e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.emptyMap()).entrySet()) { @@ -130,7 +130,7 @@ public class NamespaceCodegen { } } - private static void generateTypeInfo(ClassContext context, InstructionAdapter v, JetType jetType, JetTypeMapper typeMapper, JetType root) { + private static void generateTypeInfo(CodegenContext context, InstructionAdapter v, JetType jetType, JetTypeMapper typeMapper, JetType root) { String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType); if(knownTypeInfo != null) { v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;"); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionOrClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java similarity index 85% rename from compiler/backend/src/org/jetbrains/jet/codegen/FunctionOrClosureCodegen.java rename to compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java index 2a0bd3be23f..f2b2f2302a6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionOrClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java @@ -1,27 +1,30 @@ package org.jetbrains.jet.codegen; +import org.jetbrains.jet.lang.descriptors.ClassDescriptorImpl; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; /** * @author alex.tkachman */ -public class FunctionOrClosureCodegen { +public class ObjectOrClosureCodegen { protected boolean captureThis; public final GenerationState state; protected final ExpressionCodegen exprContext; - protected final ClassContext context; + protected final CodegenContext context; protected ClassBuilder cv = null; public String name = null; protected Map closure = new LinkedHashMap(); - public FunctionOrClosureCodegen(ExpressionCodegen exprContext, ClassContext context, GenerationState state) { + public ObjectOrClosureCodegen(ExpressionCodegen exprContext, CodegenContext context, GenerationState state) { this.exprContext = exprContext; this.context = context; this.state = state; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index ddb3f9ed8fd..278edf168be 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -24,7 +24,7 @@ public class PropertyCodegen { private final ClassBuilder v; private final OwnerKind kind; - public PropertyCodegen(ClassContext context, ClassBuilder v, FunctionCodegen functionCodegen, GenerationState state) { + public PropertyCodegen(CodegenContext context, ClassBuilder v, FunctionCodegen functionCodegen, GenerationState state) { this.v = v; this.functionCodegen = functionCodegen; this.state = state; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 402aee6463e..a0404d2d404 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -235,6 +235,10 @@ public abstract class StackValue { return new FieldForSharedVar(type, name, fieldName); } + public static StackValue composed(StackValue prefix, StackValue suffix) { + return new Composed(prefix, suffix); + } + private static class None extends StackValue { public static None INSTANCE = new None(); private None() { @@ -790,4 +794,21 @@ public abstract class StackValue { v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor()); } } + + private static class Composed extends StackValue { + private StackValue prefix; + private StackValue suffix; + + public Composed(StackValue prefix, StackValue suffix) { + super(suffix.type); + this.prefix = prefix; + this.suffix = suffix; + } + + @Override + public void put(Type type, InstructionAdapter v) { + prefix.put(prefix.type, v); + suffix.put(type, v); + } + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java index 6856689b2de..cdd5f7e3a48 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java @@ -12,7 +12,7 @@ import org.objectweb.asm.Opcodes; import java.util.List; public class TraitImplBodyCodegen extends ClassBodyCodegen { - public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) { + public TraitImplBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) { super(aClass, context, v, state); } diff --git a/compiler/testData/codegen/extensionFunctions/virtual.jet b/compiler/testData/codegen/extensionFunctions/virtual.jet new file mode 100644 index 00000000000..18a774867ac --- /dev/null +++ b/compiler/testData/codegen/extensionFunctions/virtual.jet @@ -0,0 +1,24 @@ +class Request(val path: String) { + +} + +class Handler() { + fun Int.times(op: fun(): Unit) { + for(i in 0..this) + op() + } + +// fun Request.getPath() : String { +// val sb = java.lang.StringBuilder() +// 10.times { +// sb.append(path)?.append(this) +// } +// return sb.toString() as String +// } + + fun Request.getPath() = path + + fun test(request: Request) = request.getPath() +} + +fun box() : String = if(Handler().test(Request("239")) == "239") "OK" else "fail" diff --git a/compiler/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java b/compiler/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java index 7151adcbc12..16487d292f1 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java @@ -4,6 +4,7 @@ import java.lang.reflect.Method; /** * @author yole + * @author alex.tkachman */ public class ExtensionFunctionsTest extends CodegenTestCase { @Override @@ -27,4 +28,8 @@ public class ExtensionFunctionsTest extends CodegenTestCase { public void testGeneric() throws Exception { blackBoxFile("extensionFunctions/generic.jet"); } + + public void testVirtual() throws Exception { + blackBoxFile("extensionFunctions/virtual.jet"); + } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java index ed9beaf4e74..096bd9e1c03 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java @@ -64,6 +64,7 @@ public class PropertyGenTest extends CodegenTestCase { public void testFieldPropertyAccess() throws Exception { loadFile("properties/fieldPropertyAccess.jet"); + System.out.println(generateToText()); final Method method = generateFunction(); assertEquals(1, method.invoke(null)); assertEquals(2, method.invoke(null));