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());
ClassDescriptor thisDescriptor = context.getThisDescriptor();
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);
@@ -208,14 +209,14 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) {
int argCount = captureThis ? 1 : 0;
argCount += (captureReceiver != null ? 1 : 0);
for (DeclarationDescriptor descriptor : closure.keySet()) {
if(descriptor instanceof VariableDescriptor) {
if(descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
argCount++;
}
else if(descriptor instanceof FunctionDescriptor) {
captureReceiver = state.getTypeMapper().mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType());
argCount++;
assert captureReceiver != null;
}
}
@@ -231,8 +232,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
}
for (DeclarationDescriptor descriptor : closure.keySet()) {
if(descriptor instanceof VariableDescriptor) {
final Type sharedVarType = exprContext.getSharedVarType(descriptor);
if(descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
final Type sharedVarType = exprContext.getTypeMapper().getSharedVarType(descriptor);
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
argTypes[i++] = type;
}
@@ -21,6 +21,11 @@ public abstract class CodegenContext {
protected ClassDescriptor getThisDescriptor() {
return null;
}
@Override
public boolean isStatic() {
return true;
}
};
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);
}
public abstract boolean isStatic();
public abstract static class ReceiverContext extends CodegenContext {
final CallableDescriptor receiverDescriptor;
@@ -276,6 +283,11 @@ public abstract class CodegenContext {
return getParentContext().enclosingClassType();
}
@Override
public boolean isStatic() {
return getParentContext().isStatic();
}
protected StackValue getOuterExpression(StackValue prefix) {
return getParentContext().getOuterExpression(prefix);
}
@@ -310,6 +322,11 @@ public abstract class CodegenContext {
protected ClassDescriptor getThisDescriptor() {
return (ClassDescriptor) getContextDescriptor();
}
@Override
public boolean isStatic() {
return false;
}
}
public static class AnonymousClassContext extends CodegenContext {
@@ -326,6 +343,11 @@ public abstract class CodegenContext {
protected ClassDescriptor getThisDescriptor() {
return (ClassDescriptor) getContextDescriptor();
}
@Override
public boolean isStatic() {
return false;
}
}
public static class ClosureContext extends ReceiverContext {
@@ -350,6 +372,11 @@ public abstract class CodegenContext {
public DeclarationDescriptor getContextDescriptor() {
return classDescriptor;
}
@Override
public boolean isStatic() {
return false;
}
}
public static class NamespaceContext extends CodegenContext {
@@ -361,5 +388,10 @@ public abstract class CodegenContext {
protected ClassDescriptor getThisDescriptor() {
return null;
}
@Override
public boolean isStatic() {
return true;
}
}
}
@@ -89,6 +89,9 @@ public class CodegenUtil {
}
public static boolean hasTypeInfoField(JetType type) {
if(isInterface(type))
return false;
List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
for (TypeParameterDescriptor parameter : parameters) {
if(parameter.isReified())
@@ -81,7 +81,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
this.intrinsics = state.getIntrinsics();
}
StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, ClassDescriptor required) {
StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, @Nullable ClassDescriptor required) {
if(required == null)
return inner;
@@ -640,13 +640,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.load(0, JetTypeMapper.TYPE_OBJECT);
}
for (DeclarationDescriptor descriptor : closureCodegen.closure.keySet()) {
Type sharedVarType = getSharedVarType(descriptor);
if(sharedVarType == null)
sharedVarType = state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
consArgTypes.add(sharedVarType);
final EnclosedValueDescriptor valueDescriptor = closureCodegen.closure.get(descriptor);
valueDescriptor.getOuterValue().put(sharedVarType, v);
if(closureCodegen.captureReceiver != null) {
v.load(context.isStatic() ? 0 : 1, closureCodegen.captureReceiver);
consArgTypes.add(closureCodegen.captureReceiver);
}
for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closureCodegen.closure.entrySet()) {
if(entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) {
Type sharedVarType = typeMapper.getSharedVarType(entry.getKey());
if(sharedVarType == null)
sharedVarType = state.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()]));
@@ -654,20 +660,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
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) {
Label blockStart = new Label();
v.mark(blockStart);
@@ -677,7 +669,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, statement);
assert variableDescriptor != null;
final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
myFrameMap.enter(variableDescriptor, type.getSize());
}
@@ -705,7 +697,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
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());
if(sharedVarType != null) {
v.aconst(null);
@@ -819,7 +811,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else {
int index = lookupLocal(descriptor);
if (index >= 0) {
Type sharedVarType = getSharedVarType(descriptor);
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
final JetType outType = ((VariableDescriptor) descriptor).getOutType();
if(sharedVarType != null) {
return StackValue.shared(index, typeMapper.mapType(outType));
@@ -914,7 +906,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
else {
if(resolvedCall.getThisObject() instanceof ExtensionReceiver)
receiver = generateReceiver(((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor(), null);
receiver = generateReceiver(((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor());
else
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
}
@@ -992,6 +984,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
functionDescriptor = functionDescriptor.getOriginal();
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 isInsideClass = containingDeclaration == context.getThisDescriptor();
if (isInsideClass || isStatic) {
@@ -1247,7 +1245,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else if(descriptor instanceof ExtensionReceiver) {
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) {
ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor;
@@ -1266,16 +1264,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return null;
}
private StackValue generateReceiver(DeclarationDescriptor provided, ClassDescriptor required) {
private StackValue generateReceiver(DeclarationDescriptor provided) {
assert context instanceof CodegenContext.ReceiverContext;
CodegenContext.ReceiverContext cur = (CodegenContext.ReceiverContext) context;
if (cur.getReceiverDescriptor() == provided) {
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));
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, required);
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
}
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
@@ -1939,7 +1937,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
assert index >= 0;
final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
assert variableDescriptor != null;
Type varType = typeMapper.mapType(variableDescriptor.getOutType());
if(sharedVarType != null) {
@@ -2217,8 +2215,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return generateThisOrOuter((ClassDescriptor) descriptor);
}
else {
if(descriptor instanceof FunctionDescriptor) {
return generateReceiver(descriptor, null);
if(descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) {
return generateReceiver(descriptor);
}
throw new UnsupportedOperationException();
}
@@ -110,7 +110,7 @@ public class FunctionCodegen {
}
else {
for (ValueParameterDescriptor parameter : paramDescrs) {
Type sharedVarType = codegen.getSharedVarType(parameter);
Type sharedVarType = state.getTypeMapper().getSharedVarType(parameter);
Type localVarType = state.getTypeMapper().mapType(parameter.getOutType());
if (sharedVarType != null) {
int index = frameMap.getIndex(parameter);
@@ -1,6 +1,5 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -39,43 +38,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private Set<String> getSuperInterfaces(JetClassOrObject aClass) {
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
String superClassName = null;
Set<String> superInterfaces = new LinkedHashSet<String>();
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
PsiElement superPsi = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, 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());
if(CodegenUtil.isInterface(superClassDescriptor)) {
superInterfaces.add(typeMapper.getFQName(superClassDescriptor));
}
}
return superInterfaces;
@@ -137,21 +107,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (declaration != null) {
if (declaration instanceof PsiClass) {
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;
}
}
if(!CodegenUtil.isInterface(superClassDescriptor)) {
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
superCall = specifier;
}
}
}
@@ -332,16 +290,33 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
method = callableMethod.getSignature();
}
int firstClosureIndex = -1;
if(context.closure != null) {
ObjectOrClosureCodegen closure = context.closure;
if(closure != null) {
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;
for (DeclarationDescriptor descriptor : closure.keySet()) {
final Type sharedVarType = context.closure.exprContext.getSharedVarType(descriptor);
consArgTypes.add(sharedVarType != null ? sharedVarType : typeMapper.mapType(((VariableDescriptor) descriptor).getOutType()));
if(closure.captureReceiver != null)
consArgTypes.add(insert++, closure.captureReceiver);
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()]));
@@ -450,17 +425,28 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
}
if(context.closure != null) {
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure;
int k = 0;
for (DeclarationDescriptor varDescr : closure.keySet()) {
Type sharedVarType = context.closure.exprContext.getSharedVarType(varDescr);
if(sharedVarType == null) {
sharedVarType = typeMapper.mapType(((VariableDescriptor) varDescr).getOutType());
}
if(closure != null) {
int k = outerDescriptor != null && outerDescriptor.getKind() != ClassKind.OBJECT ? 2 : 1;
if(closure.captureReceiver != null) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(firstClosureIndex + k, StackValue.refType(sharedVarType));
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$" + (k+1), sharedVarType.getDescriptor());
iv.load(1, closure.captureReceiver);
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();
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);
}
if (d instanceof VariableDescriptor) {
if (d instanceof VariableDescriptor && !(d instanceof PropertyDescriptor)) {
VariableDescriptor vd = (VariableDescriptor) d;
final int idx = exprContext.lookupLocal(vd);
if (idx < 0) return null;
final Type sharedVarType = exprContext.getSharedVarType(vd);
final Type sharedVarType = state.getTypeMapper().getSharedVarType(vd);
Type localType = state.getTypeMapper().mapType(vd.getOutType());
final Type type = sharedVarType != null ? sharedVarType : localType;
@@ -79,6 +79,9 @@ public class ObjectOrClosureCodegen {
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer);
assert captureReceiver == null;
captureReceiver = type;
return innerValue;
}
@@ -19,6 +19,8 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
//todo not needed when frontend will be able to calculate properly
static JetType getSuperClass(ClassDescriptor myClassDescr, BindingContext bindingContext) {
JetClassOrObject myClass = (JetClassOrObject) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, myClassDescr);
if(myClass == null)
return JetStandardClasses.getAnyType();
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
@@ -35,6 +35,7 @@ public class IntrinsicMethods {
public static final IntrinsicMethod ARRAY_SIZE = new ArraySize();
public static final IntrinsicMethod ARRAY_INDICES = new ArrayIndices();
public static final Equals EQUALS = new Equals();
public static final IteratorNext ITERATOR_NEXT = new IteratorNext();
private final Project myProject;
private final JetStandardLibrary myStdLib;
@@ -83,6 +84,15 @@ public class IntrinsicMethods {
declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS);
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());
//
declareIntrinsicStringMethods();
@@ -168,7 +178,11 @@ public class IntrinsicMethods {
private void declareIntrinsicFunction(String className, String functionName, int arity, IntrinsicMethod implementation) {
JetScope memberScope = getClassMemberScope(className);
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) {
@@ -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 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)
fun Any?.equals(other : Any?) : Boolean// = this === other
@@ -53,36 +53,52 @@ trait Iterator<out T> {
val hasNext : Boolean
}
abstract open class ByteIterator : Iterator<Byte> {
fun nextByte() : Byte
abstract open class ByteIterator() : Iterator<Byte> {
abstract open fun nextByte() : Byte
override fun next() : Byte
}
abstract open class ShortIterator : Iterator<Short> {
fun nextShort() : Short
abstract open class ShortIterator() : Iterator<Short> {
abstract open fun nextShort() : Short
override fun next() : Short
}
abstract open class CharIterator : Iterator<Char> {
fun nextChar() : Char
abstract open class CharIterator() : Iterator<Char> {
abstract open fun nextChar() : Char
override fun next() : Char
}
abstract open class IntIterator : Iterator<Int> {
fun nextInt() : Int
abstract open class IntIterator() : Iterator<Int> {
abstract open fun nextInt() : Int
override fun next() : Int
}
abstract open class LongIterator : Iterator<Long> {
fun nextLong() : Long
abstract open class LongIterator() : Iterator<Long> {
abstract open fun nextLong() : Long
override fun next() : Long
}
abstract open class FloatIterator : Iterator<Float> {
fun nextFloat() : Float
abstract open class FloatIterator() : Iterator<Float> {
abstract open fun nextFloat() : Float
override fun next() : Float
}
abstract open class DoubleIterator : Iterator<Double> {
fun nextDouble() : Double
abstract open class DoubleIterator() : Iterator<Double> {
abstract open fun nextDouble() : Double
override fun next() : Double
}
abstract open class BooleanIterator : Iterator<Boolean> {
fun nextBoolean() : Boolean
abstract open class BooleanIterator() : Iterator<Boolean> {
abstract open fun nextBoolean() : Boolean
override fun next() : Boolean
}
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);
}
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 {
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());
@@ -24,7 +24,7 @@ public class ClassGenTest extends CodegenTestCase {
loadFile("classes/inheritingFromArrayList.jet");
final Class aClass = loadClass("Foo", generateClassesInFile());
checkInterface(aClass, List.class);
assertInstanceOf(aClass.newInstance(), List.class);
}
public void testInheritanceAndDelegation_DelegatingDefaultConstructorProperties() throws Exception {
@@ -47,13 +47,6 @@ public class ClassGenTest extends CodegenTestCase {
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 {
loadFile("classes/newInstanceDefaultConstructor.jet");
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() { 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() {
override fun read() : Int {
return System.`in`?.read() ?: -1
+8
View File
@@ -1,9 +1,17 @@
package jet;
import jet.typeinfo.TypeInfo;
/**
* @author alex.tkachman
*/
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() {
return nextBoolean();
}
+8
View File
@@ -1,9 +1,17 @@
package jet;
import jet.typeinfo.TypeInfo;
/**
* @author alex.tkachman
*/
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() {
return nextByte();
}
+8
View File
@@ -1,9 +1,17 @@
package jet;
import jet.typeinfo.TypeInfo;
/**
* @author alex.tkachman
*/
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() {
return nextChar();
}
+7
View File
@@ -8,10 +8,17 @@ import jet.typeinfo.TypeInfo;
public class DefaultJetObject implements JetObject {
private TypeInfo<?> typeInfo;
protected DefaultJetObject() {
}
protected DefaultJetObject(TypeInfo<?> typeInfo) {
this.typeInfo = typeInfo;
}
protected final void $setTypeInfo(TypeInfo typeInfo) {
this.typeInfo = typeInfo;
}
@Override
public final TypeInfo<?> getTypeInfo() {
return typeInfo;
+8
View File
@@ -1,9 +1,17 @@
package jet;
import jet.typeinfo.TypeInfo;
/**
* @author alex.tkachman
*/
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() {
return nextDouble();
}
+1 -1
View File
@@ -5,7 +5,7 @@ package jet;
import jet.typeinfo.TypeInfo;
public abstract class ExtensionFunction0<E, R> extends DefaultJetObject{
public abstract class ExtensionFunction0<E, R> extends DefaultJetObject {
protected ExtensionFunction0(TypeInfo<?> typeInfo) {
super(typeInfo);
}
+8
View File
@@ -1,9 +1,17 @@
package jet;
import jet.typeinfo.TypeInfo;
/**
* @author alex.tkachman
*/
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() {
return nextFloat();
}
+8
View File
@@ -1,9 +1,17 @@
package jet;
import jet.typeinfo.TypeInfo;
/**
* @author alex.tkachman
*/
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() {
return nextInt();
}
+8
View File
@@ -1,9 +1,17 @@
package jet;
import jet.typeinfo.TypeInfo;
/**
* @author alex.tkachman
*/
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() {
return nextLong();
}
+8
View File
@@ -1,9 +1,17 @@
package jet;
import jet.typeinfo.TypeInfo;
/**
* @author alex.tkachman
*/
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() {
return nextShort();
}