Added intrinsic properties of ranges and sequences.

This commit is contained in:
Evgeny Gerashchenko
2013-01-24 01:08:32 +04:00
parent b2e74b1473
commit 000fc55035
4 changed files with 95 additions and 2 deletions
@@ -55,6 +55,7 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.scopes.receivers.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -845,11 +846,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
v.dup(); v.dup();
indexVar = myFrameMap.enterTemp(Type.INT_TYPE); indexVar = myFrameMap.enterTemp(Type.INT_TYPE);
v.invokevirtual(JET_INT_RANGE_TYPE.getInternalName(), "getStart", "()I"); v.invokevirtual(JET_INT_RANGE_TYPE.getInternalName(), "getStart", "()Ljava/lang/Integer;");
StackValue.coerce(Type.getType("Ljava/lang/Integer;"), Type.INT_TYPE, v);
v.store(indexVar, Type.INT_TYPE); v.store(indexVar, Type.INT_TYPE);
endVar = myFrameMap.enterTemp(Type.INT_TYPE); endVar = myFrameMap.enterTemp(Type.INT_TYPE);
v.invokevirtual(JET_INT_RANGE_TYPE.getInternalName(), "getEnd", "()I"); v.invokevirtual(JET_INT_RANGE_TYPE.getInternalName(), "getEnd", "()Ljava/lang/Integer;");
StackValue.coerce(Type.getType("Ljava/lang/Integer;"), Type.INT_TYPE, v);
v.store(endVar, Type.INT_TYPE); v.store(endVar, Type.INT_TYPE);
} }
@@ -156,9 +156,22 @@ public class IntrinsicMethods {
Name.identifier("EMPTY"), -1, new EmptyRange(type)); Name.identifier("EMPTY"), -1, new EmptyRange(type));
} }
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
registerRangeOrSequenceProperty(type.getRangeClassName(), Name.identifier("start"));
registerRangeOrSequenceProperty(type.getRangeClassName(), Name.identifier("end"));
registerRangeOrSequenceProperty(type.getSequenceClassName(), Name.identifier("start"));
registerRangeOrSequenceProperty(type.getSequenceClassName(), Name.identifier("end"));
registerRangeOrSequenceProperty(type.getSequenceClassName(), Name.identifier("increment"));
}
declareArrayMethods(); declareArrayMethods();
} }
private void registerRangeOrSequenceProperty(@NotNull FqName ownerClass, @NotNull Name propertyName) {
intrinsicsMap.registerIntrinsic(ownerClass, propertyName, -1, new PropertyOfSequenceOrRange(ownerClass, propertyName));
}
@NotNull @NotNull
private static FqNameUnsafe getClassObjectFqName(@NotNull Name builtinClassName) { private static FqNameUnsafe getClassObjectFqName(@NotNull Name builtinClassName) {
return KotlinBuiltIns.getInstance().getBuiltInsPackageFqName().child(builtinClassName).toUnsafe().child(getClassObjectName(builtinClassName)); return KotlinBuiltIns.getInstance().getBuiltInsPackageFqName().child(builtinClassName).toUnsafe().child(getClassObjectName(builtinClassName));
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.PropertyCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.List;
public class PropertyOfSequenceOrRange implements IntrinsicMethod {
private final FqName ownerClass;
private final Name propertyName;
public PropertyOfSequenceOrRange(@NotNull FqName ownerClass, @NotNull Name propertyName) {
this.ownerClass = ownerClass;
this.propertyName = propertyName;
}
@Override
public StackValue generate(
ExpressionCodegen codegen,
InstructionAdapter v,
@NotNull Type expectedType,
PsiElement element,
List<JetExpression> arguments,
StackValue receiver,
@NotNull GenerationState state
) {
String ownerInternalName = JvmClassName.byFqNameWithoutInnerClasses(this.ownerClass).getInternalName();
JvmClassName wrapperClass = JvmPrimitiveType.getByAsmType(expectedType).getWrapper();
String getterName = PropertyCodegen.getterName(propertyName);
receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
v.invokevirtual(ownerInternalName, getterName, "()" + wrapperClass.getDescriptor());
StackValue.coerce(wrapperClass.getAsmType(), expectedType, v);
return StackValue.onStack(expectedType);
}
public enum OwnerKind {
SEQUENCE,
RANGE
}
}
@@ -41,6 +41,7 @@ public enum PrimitiveType {
private final FqName className; private final FqName className;
private final FqName arrayClassName; private final FqName arrayClassName;
private final FqName rangeClassName; private final FqName rangeClassName;
private final FqName sequenceClassName;
private PrimitiveType(String typeName) { private PrimitiveType(String typeName) {
this.typeName = Name.identifier(typeName); this.typeName = Name.identifier(typeName);
@@ -50,6 +51,8 @@ public enum PrimitiveType {
this.className = builtInsPackageFqName.child(this.typeName); this.className = builtInsPackageFqName.child(this.typeName);
this.arrayClassName = builtInsPackageFqName.child(this.arrayTypeName); this.arrayClassName = builtInsPackageFqName.child(this.arrayTypeName);
this.rangeClassName = builtInsPackageFqName.child(this.rangeTypeName); this.rangeClassName = builtInsPackageFqName.child(this.rangeTypeName);
this.sequenceClassName = builtInsPackageFqName.child(
Name.identifier((typeName == "Char") ? "CharacterSequence" : typeName + "Sequence"));
} }
@NotNull @NotNull
@@ -81,4 +84,9 @@ public enum PrimitiveType {
public FqName getRangeClassName() { public FqName getRangeClassName() {
return rangeClassName; return rangeClassName;
} }
@NotNull
public FqName getSequenceClassName() {
return sequenceClassName;
}
} }