refactoring of codegen contexts, and proper this/outer/super/receiver support

This commit is contained in:
Alex Tkachman
2011-11-08 11:11:42 +01:00
parent aa1ebbe445
commit 509ffb2fde
17 changed files with 523 additions and 379 deletions
@@ -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<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();
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;
@@ -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<DeclarationDescriptor, DeclarationDescriptor> accessors) {
private void generateImplementation(CodegenContext context, JetClassOrObject aClass, OwnerKind kind, HashMap<DeclarationDescriptor, DeclarationDescriptor> 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);
}
}
}
@@ -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<JetType,Integer> typeInfoConstants;
HashMap<DeclarationDescriptor, DeclarationDescriptor> 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<JetType, Integer>();
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<DeclarationDescriptor,DeclarationDescriptor>();
}
descriptor = descriptor.getOriginal();
DeclarationDescriptor accessor = accessors.get(descriptor);
if(accessor != null)
return accessor;
if(descriptor instanceof FunctionDescriptor) {
FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType,
Collections.<AnnotationDescriptor>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.<AnnotationDescriptor>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.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
myAccessor.getVisibility(),
myAccessor.getOutType(), false, false);
PropertySetterDescriptor psd = new PropertySetterDescriptor(
myAccessor.getModality(),
myAccessor.getVisibility(),
myAccessor,
Collections.<AnnotationDescriptor>emptyList(),
false, false);
myAccessor.initialize(Collections.<TypeParameterDescriptor>emptyList(), pgd, psd);
accessor = myAccessor;
}
else {
throw new UnsupportedOperationException();
}
accessors.put(descriptor, accessor);
return accessor;
}
}
@@ -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.<AnnotationDescriptor>emptyList(),
name);
function = function.initialize(
false,
Collections.<TypeParameterDescriptor>emptyList(),
Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.<FunctionDescriptor>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()) {
@@ -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<JetType,Integer> typeInfoConstants;
HashMap<DeclarationDescriptor, DeclarationDescriptor> 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.<AnnotationDescriptor>emptyList(), true)
.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>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<JetType, Integer>();
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<DeclarationDescriptor,DeclarationDescriptor>();
}
descriptor = descriptor.getOriginal();
DeclarationDescriptor accessor = accessors.get(descriptor);
if(accessor != null)
return accessor;
if(descriptor instanceof FunctionDescriptor) {
FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType,
Collections.<AnnotationDescriptor>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.<AnnotationDescriptor>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.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
myAccessor.getVisibility(),
myAccessor.getOutType(), false, false);
PropertySetterDescriptor psd = new PropertySetterDescriptor(
myAccessor.getModality(),
myAccessor.getVisibility(),
myAccessor,
Collections.<AnnotationDescriptor>emptyList(),
false, false);
myAccessor.initialize(Collections.<TypeParameterDescriptor>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;
}
}
}
@@ -51,7 +51,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
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<StackValue, StackValue> {
private final BindingContext bindingContext;
private final Map<TypeParameterDescriptor, StackValue> typeParameterExpressions = new HashMap<TypeParameterDescriptor, StackValue>();
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<StackValue, StackValue> {
// return generateThisOrOuter((ClassDescriptor) descriptor);
// }
// else {
// return thisExpression();
// return local0();
// }
return StackValue.none();
}
@@ -333,10 +333,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
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<StackValue, StackValue> {
@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<StackValue, StackValue> {
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<StackValue, StackValue> {
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<StackValue, StackValue> {
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<StackValue, StackValue> {
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<StackValue, StackValue> {
}
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<StackValue, StackValue> {
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<StackValue, StackValue> {
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);
@@ -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<ValueParameterDescriptor> 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<? extends FunctionDescriptor> 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)) {
@@ -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<String, ClassBuilder> 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);
@@ -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<JetParameter> 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<FunctionDescriptor> overriden) {
protected void generateDelegates(JetClass toClass, CodegenContext delegateContext, Set<FunctionDescriptor> overriden) {
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state);
@@ -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<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>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;");
@@ -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<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
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;
@@ -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;
@@ -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);
}
}
}
@@ -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);
}
@@ -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"
@@ -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");
}
}
@@ -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));