rewrite of closure capturing for object literals

This commit is contained in:
Alex Tkachman
2011-11-22 12:35:42 +02:00
parent ed4dc03b16
commit efceb12f3b
27 changed files with 435 additions and 133 deletions
@@ -98,7 +98,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral()); captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
ClassDescriptor thisDescriptor = context.getThisDescriptor(); ClassDescriptor thisDescriptor = context.getThisDescriptor();
final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName()); final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName());
if (enclosingType == null) captureThis = false; if (enclosingType == null)
captureThis = false;
final Method constructor = generateConstructor(funClass, fun); final Method constructor = generateConstructor(funClass, fun);
@@ -208,14 +209,14 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) { private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) {
int argCount = captureThis ? 1 : 0; int argCount = captureThis ? 1 : 0;
argCount += (captureReceiver != null ? 1 : 0);
for (DeclarationDescriptor descriptor : closure.keySet()) { for (DeclarationDescriptor descriptor : closure.keySet()) {
if(descriptor instanceof VariableDescriptor) { if(descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
argCount++; argCount++;
} }
else if(descriptor instanceof FunctionDescriptor) { else if(descriptor instanceof FunctionDescriptor) {
captureReceiver = state.getTypeMapper().mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()); assert captureReceiver != null;
argCount++;
} }
} }
@@ -231,8 +232,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
} }
for (DeclarationDescriptor descriptor : closure.keySet()) { for (DeclarationDescriptor descriptor : closure.keySet()) {
if(descriptor instanceof VariableDescriptor) { if(descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
final Type sharedVarType = exprContext.getSharedVarType(descriptor); final Type sharedVarType = exprContext.getTypeMapper().getSharedVarType(descriptor);
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()); final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
argTypes[i++] = type; argTypes[i++] = type;
} }
@@ -21,6 +21,11 @@ public abstract class CodegenContext {
protected ClassDescriptor getThisDescriptor() { protected ClassDescriptor getThisDescriptor() {
return null; return null;
} }
@Override
public boolean isStatic() {
return true;
}
}; };
protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
@@ -244,6 +249,8 @@ public abstract class CodegenContext {
return getThisDescriptor() != null ? StackValue.local(1, asmType) : StackValue.local(0, asmType); return getThisDescriptor() != null ? StackValue.local(1, asmType) : StackValue.local(0, asmType);
} }
public abstract boolean isStatic();
public abstract static class ReceiverContext extends CodegenContext { public abstract static class ReceiverContext extends CodegenContext {
final CallableDescriptor receiverDescriptor; final CallableDescriptor receiverDescriptor;
@@ -276,6 +283,11 @@ public abstract class CodegenContext {
return getParentContext().enclosingClassType(); return getParentContext().enclosingClassType();
} }
@Override
public boolean isStatic() {
return getParentContext().isStatic();
}
protected StackValue getOuterExpression(StackValue prefix) { protected StackValue getOuterExpression(StackValue prefix) {
return getParentContext().getOuterExpression(prefix); return getParentContext().getOuterExpression(prefix);
} }
@@ -310,6 +322,11 @@ public abstract class CodegenContext {
protected ClassDescriptor getThisDescriptor() { protected ClassDescriptor getThisDescriptor() {
return (ClassDescriptor) getContextDescriptor(); return (ClassDescriptor) getContextDescriptor();
} }
@Override
public boolean isStatic() {
return false;
}
} }
public static class AnonymousClassContext extends CodegenContext { public static class AnonymousClassContext extends CodegenContext {
@@ -326,6 +343,11 @@ public abstract class CodegenContext {
protected ClassDescriptor getThisDescriptor() { protected ClassDescriptor getThisDescriptor() {
return (ClassDescriptor) getContextDescriptor(); return (ClassDescriptor) getContextDescriptor();
} }
@Override
public boolean isStatic() {
return false;
}
} }
public static class ClosureContext extends ReceiverContext { public static class ClosureContext extends ReceiverContext {
@@ -350,6 +372,11 @@ public abstract class CodegenContext {
public DeclarationDescriptor getContextDescriptor() { public DeclarationDescriptor getContextDescriptor() {
return classDescriptor; return classDescriptor;
} }
@Override
public boolean isStatic() {
return false;
}
} }
public static class NamespaceContext extends CodegenContext { public static class NamespaceContext extends CodegenContext {
@@ -361,5 +388,10 @@ public abstract class CodegenContext {
protected ClassDescriptor getThisDescriptor() { protected ClassDescriptor getThisDescriptor() {
return null; return null;
} }
@Override
public boolean isStatic() {
return true;
}
} }
} }
@@ -89,6 +89,9 @@ public class CodegenUtil {
} }
public static boolean hasTypeInfoField(JetType type) { public static boolean hasTypeInfoField(JetType type) {
if(isInterface(type))
return false;
List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters(); List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
for (TypeParameterDescriptor parameter : parameters) { for (TypeParameterDescriptor parameter : parameters) {
if(parameter.isReified()) if(parameter.isReified())
@@ -81,7 +81,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
this.intrinsics = state.getIntrinsics(); this.intrinsics = state.getIntrinsics();
} }
StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, ClassDescriptor required) { StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, @Nullable ClassDescriptor required) {
if(required == null) if(required == null)
return inner; return inner;
@@ -640,13 +640,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.load(0, JetTypeMapper.TYPE_OBJECT); v.load(0, JetTypeMapper.TYPE_OBJECT);
} }
for (DeclarationDescriptor descriptor : closureCodegen.closure.keySet()) { if(closureCodegen.captureReceiver != null) {
Type sharedVarType = getSharedVarType(descriptor); v.load(context.isStatic() ? 0 : 1, closureCodegen.captureReceiver);
if(sharedVarType == null) consArgTypes.add(closureCodegen.captureReceiver);
sharedVarType = state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()); }
consArgTypes.add(sharedVarType);
final EnclosedValueDescriptor valueDescriptor = closureCodegen.closure.get(descriptor); for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closureCodegen.closure.entrySet()) {
valueDescriptor.getOuterValue().put(sharedVarType, v); if(entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) {
Type sharedVarType = typeMapper.getSharedVarType(entry.getKey());
if(sharedVarType == null)
sharedVarType = state.getTypeMapper().mapType(((VariableDescriptor) entry.getKey()).getOutType());
consArgTypes.add(sharedVarType);
entry.getValue().getOuterValue().put(sharedVarType, v);
}
} }
Method cons = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()])); Method cons = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
@@ -654,20 +660,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return StackValue.onStack(Type.getObjectType(closure.getClassname())); return StackValue.onStack(Type.getObjectType(closure.getClassname()));
} }
Type getSharedVarType(DeclarationDescriptor variableDescriptor) {
if(!(variableDescriptor instanceof VariableDescriptor))
return null;
Boolean aBoolean = bindingContext.get(BindingContext.MUST_BE_WRAPPED_IN_A_REF, (VariableDescriptor) variableDescriptor);
if (aBoolean != null && aBoolean) {
JetType outType = ((VariableDescriptor) variableDescriptor).getOutType();
return StackValue.sharedTypeForType(typeMapper.mapType(outType));
}
else {
return null;
}
}
private StackValue generateBlock(List<JetElement> statements) { private StackValue generateBlock(List<JetElement> statements) {
Label blockStart = new Label(); Label blockStart = new Label();
v.mark(blockStart); v.mark(blockStart);
@@ -677,7 +669,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, statement); final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, statement);
assert variableDescriptor != null; assert variableDescriptor != null;
final Type sharedVarType = getSharedVarType(variableDescriptor); final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
myFrameMap.enter(variableDescriptor, type.getSize()); myFrameMap.enter(variableDescriptor, type.getSize());
} }
@@ -705,7 +697,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
int index = myFrameMap.leave(variableDescriptor); int index = myFrameMap.leave(variableDescriptor);
final Type sharedVarType = getSharedVarType(variableDescriptor); final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
if(sharedVarType != null) { if(sharedVarType != null) {
v.aconst(null); v.aconst(null);
@@ -819,7 +811,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else { else {
int index = lookupLocal(descriptor); int index = lookupLocal(descriptor);
if (index >= 0) { if (index >= 0) {
Type sharedVarType = getSharedVarType(descriptor); Type sharedVarType = typeMapper.getSharedVarType(descriptor);
final JetType outType = ((VariableDescriptor) descriptor).getOutType(); final JetType outType = ((VariableDescriptor) descriptor).getOutType();
if(sharedVarType != null) { if(sharedVarType != null) {
return StackValue.shared(index, typeMapper.mapType(outType)); return StackValue.shared(index, typeMapper.mapType(outType));
@@ -914,7 +906,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration()); receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
else { else {
if(resolvedCall.getThisObject() instanceof ExtensionReceiver) if(resolvedCall.getThisObject() instanceof ExtensionReceiver)
receiver = generateReceiver(((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor(), null); receiver = generateReceiver(((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor());
else else
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration()); receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
} }
@@ -992,6 +984,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
functionDescriptor = functionDescriptor.getOriginal(); functionDescriptor = functionDescriptor.getOriginal();
String owner; String owner;
IntrinsicMethod intrinsic = intrinsics.getIntrinsic(functionDescriptor);
if(intrinsic != null) {
intrinsic.generate(this, v, type, null, null, StackValue.onStack(JetTypeMapper.TYPE_OBJECT));
return;
}
boolean isInterface; boolean isInterface;
boolean isInsideClass = containingDeclaration == context.getThisDescriptor(); boolean isInsideClass = containingDeclaration == context.getThisDescriptor();
if (isInsideClass || isStatic) { if (isInsideClass || isStatic) {
@@ -1247,7 +1245,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
else if(descriptor instanceof ExtensionReceiver) { else if(descriptor instanceof ExtensionReceiver) {
ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor; ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor;
generateReceiver(extensionReceiver.getDeclarationDescriptor(), null).put(typeMapper.mapType(descriptor.getType()), v); generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(typeMapper.mapType(descriptor.getType()), v);
} }
else if(descriptor instanceof ExpressionReceiver) { else if(descriptor instanceof ExpressionReceiver) {
ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor; ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor;
@@ -1266,16 +1264,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return null; return null;
} }
private StackValue generateReceiver(DeclarationDescriptor provided, ClassDescriptor required) { private StackValue generateReceiver(DeclarationDescriptor provided) {
assert context instanceof CodegenContext.ReceiverContext; assert context instanceof CodegenContext.ReceiverContext;
CodegenContext.ReceiverContext cur = (CodegenContext.ReceiverContext) context; CodegenContext.ReceiverContext cur = (CodegenContext.ReceiverContext) context;
if (cur.getReceiverDescriptor() == provided) { if (cur.getReceiverDescriptor() == provided) {
StackValue result = cur.getReceiverExpression(typeMapper); StackValue result = cur.getReceiverExpression(typeMapper);
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, required); return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
} }
StackValue result = context.lookupInContext(provided, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT)); StackValue result = context.lookupInContext(provided, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT));
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, required); return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
} }
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) { public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
@@ -1939,7 +1937,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
assert index >= 0; assert index >= 0;
final Type sharedVarType = getSharedVarType(variableDescriptor); final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
assert variableDescriptor != null; assert variableDescriptor != null;
Type varType = typeMapper.mapType(variableDescriptor.getOutType()); Type varType = typeMapper.mapType(variableDescriptor.getOutType());
if(sharedVarType != null) { if(sharedVarType != null) {
@@ -2217,8 +2215,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return generateThisOrOuter((ClassDescriptor) descriptor); return generateThisOrOuter((ClassDescriptor) descriptor);
} }
else { else {
if(descriptor instanceof FunctionDescriptor) { if(descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) {
return generateReceiver(descriptor, null); return generateReceiver(descriptor);
} }
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@@ -110,7 +110,7 @@ public class FunctionCodegen {
} }
else { else {
for (ValueParameterDescriptor parameter : paramDescrs) { for (ValueParameterDescriptor parameter : paramDescrs) {
Type sharedVarType = codegen.getSharedVarType(parameter); Type sharedVarType = state.getTypeMapper().getSharedVarType(parameter);
Type localVarType = state.getTypeMapper().mapType(parameter.getOutType()); Type localVarType = state.getTypeMapper().mapType(parameter.getOutType());
if (sharedVarType != null) { if (sharedVarType != null) {
int index = frameMap.getIndex(parameter); int index = frameMap.getIndex(parameter);
@@ -1,6 +1,5 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
@@ -39,43 +38,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private Set<String> getSuperInterfaces(JetClassOrObject aClass) { private Set<String> getSuperInterfaces(JetClassOrObject aClass) {
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers(); List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
String superClassName = null;
Set<String> superInterfaces = new LinkedHashSet<String>(); Set<String> superInterfaces = new LinkedHashSet<String>();
for (JetDelegationSpecifier specifier : delegationSpecifiers) { for (JetDelegationSpecifier specifier : delegationSpecifiers) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null; assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
PsiElement superPsi = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor); if(CodegenUtil.isInterface(superClassDescriptor)) {
superInterfaces.add(typeMapper.getFQName(superClassDescriptor));
if (superPsi instanceof PsiClass) {
PsiClass psiClass = (PsiClass) superPsi;
String fqn = psiClass.getQualifiedName();
assert fqn != null;
if (psiClass.isInterface()) {
superInterfaces.add(fqn.replace('.', '/'));
}
else {
if (superClassName == null) {
superClassName = fqn.replace('.', '/');
while (psiClass != null) {
for (PsiClass ifs : psiClass.getInterfaces()) {
String qualifiedName = ifs.getQualifiedName();
assert qualifiedName != null;
superInterfaces.add(qualifiedName.replace('.', '/'));
}
psiClass = psiClass.getSuperClass();
}
}
else {
throw new RuntimeException("Cannot determine single class to inherit from");
}
}
}
else {
if(superPsi == null || ((JetClass)superPsi).isTrait())
superInterfaces.add(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName());
} }
} }
return superInterfaces; return superInterfaces;
@@ -137,21 +107,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null; assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor); if(!CodegenUtil.isInterface(superClassDescriptor)) {
if (declaration != null) { superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
if (declaration instanceof PsiClass) { superCall = specifier;
if (!((PsiClass) declaration).isInterface()) {
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
superCall = specifier;
return;
}
}
else if(declaration instanceof JetClass) {
if(!((JetClass) declaration).isTrait()) {
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
superCall = specifier;
}
}
} }
} }
} }
@@ -332,16 +290,33 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
method = callableMethod.getSignature(); method = callableMethod.getSignature();
} }
int firstClosureIndex = -1; ObjectOrClosureCodegen closure = context.closure;
if(context.closure != null) { if(closure != null) {
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(method.getArgumentTypes())); final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(method.getArgumentTypes()));
firstClosureIndex = consArgTypes.size()+1; int insert = 0;
if(closure.captureThis) {
if(!CodegenUtil.hasThis0(descriptor))
consArgTypes.add(insert, Type.getObjectType(context.getThisDescriptor().getName()));
insert++;
}
else {
if(CodegenUtil.hasThis0(descriptor))
insert++;
}
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure; if(closure.captureReceiver != null)
for (DeclarationDescriptor descriptor : closure.keySet()) { consArgTypes.add(insert++, closure.captureReceiver);
final Type sharedVarType = context.closure.exprContext.getSharedVarType(descriptor);
consArgTypes.add(sharedVarType != null ? sharedVarType : typeMapper.mapType(((VariableDescriptor) descriptor).getOutType())); for (DeclarationDescriptor descriptor : closure.closure.keySet()) {
if(descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
final Type sharedVarType = typeMapper.getSharedVarType(descriptor);
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
consArgTypes.add(insert++, type);
}
else if(descriptor instanceof FunctionDescriptor) {
assert closure.captureReceiver != null;
}
} }
method = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()])); method = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
@@ -450,17 +425,28 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv); generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
} }
if(context.closure != null) { if(closure != null) {
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure; int k = outerDescriptor != null && outerDescriptor.getKind() != ClassKind.OBJECT ? 2 : 1;
int k = 0; if(closure.captureReceiver != null) {
for (DeclarationDescriptor varDescr : closure.keySet()) {
Type sharedVarType = context.closure.exprContext.getSharedVarType(varDescr);
if(sharedVarType == null) {
sharedVarType = typeMapper.mapType(((VariableDescriptor) varDescr).getOutType());
}
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(firstClosureIndex + k, StackValue.refType(sharedVarType)); iv.load(1, closure.captureReceiver);
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$" + (k+1), sharedVarType.getDescriptor()); iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "receiver$0", closure.captureReceiver.getDescriptor());
k += closure.captureReceiver.getSize();
}
int l = 0;
for (DeclarationDescriptor varDescr : closure.closure.keySet()) {
if(varDescr instanceof VariableDescriptor && !(varDescr instanceof PropertyDescriptor)) {
Type sharedVarType = typeMapper.getSharedVarType(varDescr);
if(sharedVarType == null) {
sharedVarType = typeMapper.mapType(((VariableDescriptor) varDescr).getOutType());
}
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(k, StackValue.refType(sharedVarType));
k += StackValue.refType(sharedVarType).getSize();
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$" + (l+1), sharedVarType.getDescriptor());
l++;
}
} }
} }
@@ -664,4 +664,24 @@ public class JetTypeMapper {
JetType type = arrayType.getArguments().get(0).getType(); JetType type = arrayType.getArguments().get(0).getType();
return isGenericsArray(type) ? type : null; return isGenericsArray(type) ? type : null;
} }
public Type getSharedVarType(DeclarationDescriptor descriptor) {
if(descriptor instanceof PropertyDescriptor) {
return StackValue.sharedTypeForType(mapType(((PropertyDescriptor) descriptor).getReceiverParameter().getType()));
}
else if (descriptor instanceof FunctionDescriptor) {
return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()));
}
else if (descriptor instanceof VariableDescriptor) {
Boolean aBoolean = bindingContext.get(BindingContext.MUST_BE_WRAPPED_IN_A_REF, (VariableDescriptor) descriptor);
if (aBoolean != null && aBoolean) {
JetType outType = ((VariableDescriptor) descriptor).getOutType();
return StackValue.sharedTypeForType(mapType(outType));
}
else {
return null;
}
}
return null;
}
} }
@@ -34,13 +34,13 @@ public class ObjectOrClosureCodegen {
return result != null ? innerValue : StackValue.composed(result, innerValue); return result != null ? innerValue : StackValue.composed(result, innerValue);
} }
if (d instanceof VariableDescriptor) { if (d instanceof VariableDescriptor && !(d instanceof PropertyDescriptor)) {
VariableDescriptor vd = (VariableDescriptor) d; VariableDescriptor vd = (VariableDescriptor) d;
final int idx = exprContext.lookupLocal(vd); final int idx = exprContext.lookupLocal(vd);
if (idx < 0) return null; if (idx < 0) return null;
final Type sharedVarType = exprContext.getSharedVarType(vd); final Type sharedVarType = state.getTypeMapper().getSharedVarType(vd);
Type localType = state.getTypeMapper().mapType(vd.getOutType()); Type localType = state.getTypeMapper().mapType(vd.getOutType());
final Type type = sharedVarType != null ? sharedVarType : localType; final Type type = sharedVarType != null ? sharedVarType : localType;
@@ -79,6 +79,9 @@ public class ObjectOrClosureCodegen {
answer = new EnclosedValueDescriptor(d, innerValue, outerValue); answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer); closure.put(d, answer);
assert captureReceiver == null;
captureReceiver = type;
return innerValue; return innerValue;
} }
@@ -19,6 +19,8 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
//todo not needed when frontend will be able to calculate properly //todo not needed when frontend will be able to calculate properly
static JetType getSuperClass(ClassDescriptor myClassDescr, BindingContext bindingContext) { static JetType getSuperClass(ClassDescriptor myClassDescr, BindingContext bindingContext) {
JetClassOrObject myClass = (JetClassOrObject) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, myClassDescr); JetClassOrObject myClass = (JetClassOrObject) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, myClassDescr);
if(myClass == null)
return JetStandardClasses.getAnyType();
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
for (JetDelegationSpecifier specifier : delegationSpecifiers) { for (JetDelegationSpecifier specifier : delegationSpecifiers) {
@@ -35,6 +35,7 @@ public class IntrinsicMethods {
public static final IntrinsicMethod ARRAY_SIZE = new ArraySize(); public static final IntrinsicMethod ARRAY_SIZE = new ArraySize();
public static final IntrinsicMethod ARRAY_INDICES = new ArrayIndices(); public static final IntrinsicMethod ARRAY_INDICES = new ArrayIndices();
public static final Equals EQUALS = new Equals(); public static final Equals EQUALS = new Equals();
public static final IteratorNext ITERATOR_NEXT = new IteratorNext();
private final Project myProject; private final Project myProject;
private final JetStandardLibrary myStdLib; private final JetStandardLibrary myStdLib;
@@ -83,6 +84,15 @@ public class IntrinsicMethods {
declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS); declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus()); declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("IntIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("LongIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("CharIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("BooleanIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("FloatIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("DoubleIterator", "next", 0, ITERATOR_NEXT);
// declareIntrinsicFunction("Any", "equals", 1, new Equals()); // declareIntrinsicFunction("Any", "equals", 1, new Equals());
// //
declareIntrinsicStringMethods(); declareIntrinsicStringMethods();
@@ -168,7 +178,11 @@ public class IntrinsicMethods {
private void declareIntrinsicFunction(String className, String functionName, int arity, IntrinsicMethod implementation) { private void declareIntrinsicFunction(String className, String functionName, int arity, IntrinsicMethod implementation) {
JetScope memberScope = getClassMemberScope(className); JetScope memberScope = getClassMemberScope(className);
final Set<FunctionDescriptor> group = memberScope.getFunctions(functionName); final Set<FunctionDescriptor> group = memberScope.getFunctions(functionName);
declareOverload(group, arity, implementation); for (FunctionDescriptor descriptor : group) {
if (className.equals(descriptor.getContainingDeclaration().getName()) && descriptor.getValueParameters().size() == arity) {
myMethods.put(descriptor.getOriginal(), implementation);
}
}
} }
private void declareOverload(Set<FunctionDescriptor> group, int arity, IntrinsicMethod implementation) { private void declareOverload(Set<FunctionDescriptor> group, int arity, IntrinsicMethod implementation) {
@@ -0,0 +1,42 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
/**
* @author alex.tkachman
*/
public class IteratorNext implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
String name;
if(expectedType == Type.CHAR_TYPE)
name = "Char";
else if(expectedType == Type.BOOLEAN_TYPE)
name = "Boolean";
else if(expectedType == Type.BYTE_TYPE)
name = "Byte";
else if(expectedType == Type.SHORT_TYPE)
name = "Short";
else if(expectedType == Type.INT_TYPE)
name = "Int";
else if(expectedType == Type.LONG_TYPE)
name = "Long";
else if(expectedType == Type.FLOAT_TYPE)
name = "Float";
else if(expectedType == Type.DOUBLE_TYPE)
name = "Double";
else
throw new UnsupportedOperationException();
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
v.invokevirtual("jet/" + name + "Iterator", "next" + name, "()" + expectedType.getDescriptor());
return StackValue.onStack(expectedType);
}
}
+33 -17
View File
@@ -34,7 +34,7 @@ namespace io {
fun readLine() : String? fun readLine() : String?
} }
fun Any?.identityEquals(other : Any?) // = this === other fun Any?.identityEquals(other : Any?) : Boolean // = this === other
// Can't write a body due to a bootstrapping problem (see JET-74) // Can't write a body due to a bootstrapping problem (see JET-74)
fun Any?.equals(other : Any?) : Boolean// = this === other fun Any?.equals(other : Any?) : Boolean// = this === other
@@ -53,36 +53,52 @@ trait Iterator<out T> {
val hasNext : Boolean val hasNext : Boolean
} }
abstract open class ByteIterator : Iterator<Byte> { abstract open class ByteIterator() : Iterator<Byte> {
fun nextByte() : Byte abstract open fun nextByte() : Byte
override fun next() : Byte
} }
abstract open class ShortIterator : Iterator<Short> { abstract open class ShortIterator() : Iterator<Short> {
fun nextShort() : Short abstract open fun nextShort() : Short
override fun next() : Short
} }
abstract open class CharIterator : Iterator<Char> { abstract open class CharIterator() : Iterator<Char> {
fun nextChar() : Char abstract open fun nextChar() : Char
override fun next() : Char
} }
abstract open class IntIterator : Iterator<Int> { abstract open class IntIterator() : Iterator<Int> {
fun nextInt() : Int abstract open fun nextInt() : Int
override fun next() : Int
} }
abstract open class LongIterator : Iterator<Long> { abstract open class LongIterator() : Iterator<Long> {
fun nextLong() : Long abstract open fun nextLong() : Long
override fun next() : Long
} }
abstract open class FloatIterator : Iterator<Float> { abstract open class FloatIterator() : Iterator<Float> {
fun nextFloat() : Float abstract open fun nextFloat() : Float
override fun next() : Float
} }
abstract open class DoubleIterator : Iterator<Double> { abstract open class DoubleIterator() : Iterator<Double> {
fun nextDouble() : Double abstract open fun nextDouble() : Double
override fun next() : Double
} }
abstract open class BooleanIterator : Iterator<Boolean> { abstract open class BooleanIterator() : Iterator<Boolean> {
fun nextBoolean() : Boolean abstract open fun nextBoolean() : Boolean
override fun next() : Boolean
} }
trait Iterable<out T> { trait Iterable<out T> {
@@ -0,0 +1,26 @@
import java.io.*
val ByteArray.inputStream : ByteArrayInputStream
get() = ByteArrayInputStream(this)
fun InputStream.iterator() : ByteIterator =
object: ByteIterator() {
override val hasNext : Boolean
get() = available() > 0
override fun nextByte() = read().byt
}
fun box() : String {
val x = ByteArray (10)
for(index in 0..9) {
x [index] = index.byt
}
for(b in x.inputStream) {
System.out?.println(b)
}
return "OK"
}
@@ -139,6 +139,55 @@ public class ArrayGenTest extends CodegenTestCase {
foo.invoke(null); foo.invoke(null);
} }
public void testByteIterator () throws Exception {
loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testShortIterator () throws Exception {
loadText("fun box() { val x = ShortArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testIntIterator () throws Exception {
loadText("fun box() { val x = IntArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testLongIterator2 () throws Exception {
loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testFloatIterator () throws Exception {
loadText("fun box() { val x = FloatArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testDoubleIterator () throws Exception {
loadText("fun box() { val x = ShortArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testBooleanIterator () throws Exception {
loadText("fun box() { val x = BooleanArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testArrayIndices () throws Exception { public void testArrayIndices () throws Exception {
loadText("fun box() { val x = Array<Int>(5, {it}).indices.iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }"); loadText("fun box() { val x = Array<Int>(5, {it}).indices.iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText()); System.out.println(generateToText());
@@ -24,7 +24,7 @@ public class ClassGenTest extends CodegenTestCase {
loadFile("classes/inheritingFromArrayList.jet"); loadFile("classes/inheritingFromArrayList.jet");
final Class aClass = loadClass("Foo", generateClassesInFile()); final Class aClass = loadClass("Foo", generateClassesInFile());
checkInterface(aClass, List.class); assertInstanceOf(aClass.newInstance(), List.class);
} }
public void testInheritanceAndDelegation_DelegatingDefaultConstructorProperties() throws Exception { public void testInheritanceAndDelegation_DelegatingDefaultConstructorProperties() throws Exception {
@@ -47,13 +47,6 @@ public class ClassGenTest extends CodegenTestCase {
blackBoxFile("classes/rightHandOverride.jet"); blackBoxFile("classes/rightHandOverride.jet");
} }
private static void checkInterface(Class aClass, Class ifs) {
for (Class anInterface : aClass.getInterfaces()) {
if (anInterface == ifs) return;
}
fail(aClass.getName() + " must have " + ifs.getName() + " in its interfaces");
}
public void testNewInstanceExplicitConstructor() throws Exception { public void testNewInstanceExplicitConstructor() throws Exception {
loadFile("classes/newInstanceDefaultConstructor.jet"); loadFile("classes/newInstanceDefaultConstructor.jet");
System.out.println(generateToText()); System.out.println(generateToText());
@@ -0,0 +1,10 @@
package org.jetbrains.jet.codegen;
/**
* @author alex.tkachman
*/
public class StdlibTest extends CodegenTestCase {
public void testInputStreamIterator () {
blackBoxFile("inputStreamIterator.jet");
}
}
+36
View File
@@ -26,6 +26,42 @@ namespace io {
inline fun println(message : CharArray) { System.out?.println(message) } inline fun println(message : CharArray) { System.out?.println(message) }
inline fun println() { System.out?.println() } inline fun println() { System.out?.println() }
val ByteArray.inputStream : ByteArrayInputStream
get() = ByteArrayInputStream(this)
inline fun ByteArray.inputStream(offset: Int, length: Int) : ByteArrayInputStream = ByteArrayInputStream(this, offset, length)
val InputStream.buffered : BufferedInputStream
get() = if(this instanceof BufferedInputStream) this else BufferedInputStream(this)
inline fun InputStream.buffered(bufferSize: Int) = BufferedInputStream(this, bufferSize)
val InputStream.reader : InputStreamReader
get() = InputStreamReader(this)
val InputStream.bufferedReader : BufferedReader
get() = buffered.reader
inline fun val InputStream.reader(charset: Charset) : InputStreamReader = InputStreamReader(this, charset)
inline fun val InputStream.reader(charsetName: String) = InputStreamReader(this, charsetNme)
inline fun val InputStream.reader(charset: Charset) = InputStreamReader(this, charset)
inline fun val InputStream.reader(charsetDecoder: CharsetDecoder) = InputStreamReader(this, charsetDecoder)
fun InputStream.iterator() : ByteIterator = object: ByteIterator() {
override val hasNext : Boolean
get() = available() > 0
override fun nextByte() = read().byt
}
val Reader.buffered : BufferedReader
get() = if(this instanceof BufferedReader) this else BufferedReader(this)
inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize)
private val stdin : BufferedReader = BufferedReader(InputStreamReader(object : InputStream() { private val stdin : BufferedReader = BufferedReader(InputStreamReader(object : InputStream() {
override fun read() : Int { override fun read() : Int {
return System.`in`?.read() ?: -1 return System.`in`?.read() ?: -1
+8
View File
@@ -1,9 +1,17 @@
package jet; package jet;
import jet.typeinfo.TypeInfo;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class BooleanIterator implements Iterator<Boolean> { public abstract class BooleanIterator implements Iterator<Boolean> {
private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(BooleanIterator.class, false);
public TypeInfo getTypeInfo () {
return typeInfo;
}
public final Boolean next() { public final Boolean next() {
return nextBoolean(); return nextBoolean();
} }
+8
View File
@@ -1,9 +1,17 @@
package jet; package jet;
import jet.typeinfo.TypeInfo;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class ByteIterator implements Iterator<Byte> { public abstract class ByteIterator implements Iterator<Byte> {
private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(ByteIterator.class, false);
public TypeInfo getTypeInfo () {
return typeInfo;
}
public final Byte next() { public final Byte next() {
return nextByte(); return nextByte();
} }
+8
View File
@@ -1,9 +1,17 @@
package jet; package jet;
import jet.typeinfo.TypeInfo;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class CharIterator implements Iterator<Character> { public abstract class CharIterator implements Iterator<Character> {
private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(CharIterator.class, false);
public TypeInfo getTypeInfo () {
return typeInfo;
}
public final Character next() { public final Character next() {
return nextChar(); return nextChar();
} }
+7
View File
@@ -8,10 +8,17 @@ import jet.typeinfo.TypeInfo;
public class DefaultJetObject implements JetObject { public class DefaultJetObject implements JetObject {
private TypeInfo<?> typeInfo; private TypeInfo<?> typeInfo;
protected DefaultJetObject() {
}
protected DefaultJetObject(TypeInfo<?> typeInfo) { protected DefaultJetObject(TypeInfo<?> typeInfo) {
this.typeInfo = typeInfo; this.typeInfo = typeInfo;
} }
protected final void $setTypeInfo(TypeInfo typeInfo) {
this.typeInfo = typeInfo;
}
@Override @Override
public final TypeInfo<?> getTypeInfo() { public final TypeInfo<?> getTypeInfo() {
return typeInfo; return typeInfo;
+8
View File
@@ -1,9 +1,17 @@
package jet; package jet;
import jet.typeinfo.TypeInfo;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class DoubleIterator implements Iterator<Double> { public abstract class DoubleIterator implements Iterator<Double> {
private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(DoubleIterator.class, false);
public TypeInfo getTypeInfo () {
return typeInfo;
}
public final Double next() { public final Double next() {
return nextDouble(); return nextDouble();
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package jet;
import jet.typeinfo.TypeInfo; import jet.typeinfo.TypeInfo;
public abstract class ExtensionFunction0<E, R> extends DefaultJetObject{ public abstract class ExtensionFunction0<E, R> extends DefaultJetObject {
protected ExtensionFunction0(TypeInfo<?> typeInfo) { protected ExtensionFunction0(TypeInfo<?> typeInfo) {
super(typeInfo); super(typeInfo);
} }
+8
View File
@@ -1,9 +1,17 @@
package jet; package jet;
import jet.typeinfo.TypeInfo;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class FloatIterator implements Iterator<Float> { public abstract class FloatIterator implements Iterator<Float> {
private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(FloatIterator.class, false);
public TypeInfo getTypeInfo () {
return typeInfo;
}
public final Float next() { public final Float next() {
return nextFloat(); return nextFloat();
} }
+8
View File
@@ -1,9 +1,17 @@
package jet; package jet;
import jet.typeinfo.TypeInfo;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class IntIterator implements Iterator<Integer> { public abstract class IntIterator implements Iterator<Integer> {
private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(IntIterator.class, false);
public TypeInfo getTypeInfo () {
return typeInfo;
}
public final Integer next() { public final Integer next() {
return nextInt(); return nextInt();
} }
+8
View File
@@ -1,9 +1,17 @@
package jet; package jet;
import jet.typeinfo.TypeInfo;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class LongIterator implements Iterator<Long> { public abstract class LongIterator implements Iterator<Long> {
private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(LongIterator.class, false);
public TypeInfo getTypeInfo () {
return typeInfo;
}
public final Long next() { public final Long next() {
return nextLong(); return nextLong();
} }
+8
View File
@@ -1,9 +1,17 @@
package jet; package jet;
import jet.typeinfo.TypeInfo;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class ShortIterator implements Iterator<Short> { public abstract class ShortIterator implements Iterator<Short> {
private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(ShortIterator.class, false);
public TypeInfo getTypeInfo () {
return typeInfo;
}
public final Short next() { public final Short next() {
return nextShort(); return nextShort();
} }