Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2011-09-07 11:34:37 +04:00
14 changed files with 542 additions and 114 deletions
@@ -11,6 +11,8 @@ import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import java.util.HashMap;
public class ClassContext { public class ClassContext {
public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null, null); public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null, null);
private final DeclarationDescriptor contextType; private final DeclarationDescriptor contextType;
@@ -20,6 +22,8 @@ public class ClassContext {
private final ClosureCodegen closure; private final ClosureCodegen closure;
private boolean thisWasUsed = false; private boolean thisWasUsed = false;
HashMap<JetType,Integer> typeInfoConstants;
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, ClosureCodegen closureCodegen) { public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, ClosureCodegen closureCodegen) {
this.contextType = contextType; this.contextType = contextType;
this.contextKind = contextKind; this.contextKind = contextKind;
@@ -32,6 +36,13 @@ public class ClassContext {
return contextType; return contextType;
} }
public String getNamespaceClassName() {
if(parentContext != STATIC)
return parentContext.getNamespaceClassName();
return NamespaceCodegen.getJVMClassName(contextType.getName());
}
public OwnerKind getContextKind() { public OwnerKind getContextKind() {
return contextKind; return contextKind;
} }
@@ -164,4 +175,19 @@ public class ClassContext {
final ClassContext parent = getParentContext(); final ClassContext parent = getParentContext();
return parent != null ? parent.enclosingClassType(mapper) : null; 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 = Integer.valueOf(typeInfoConstants.size());
typeInfoConstants.put(type, index);
}
return index;
}
} }
@@ -15,10 +15,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor; import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label; import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -1478,7 +1475,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
public void generateStringBuilderConstructor() { public void generateStringBuilderConstructor() {
Type type = Type.getObjectType(CLASS_STRING_BUILDER); Type type = JetTypeMapper.JL_STRING_BUILDER;
v.anew(type); v.anew(type);
v.dup(); v.dup();
Method method = new Method("<init>", Type.VOID_TYPE, new Type[0]); Method method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
@@ -1500,7 +1497,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
public void invokeAppendMethod(Type exprType) { public void invokeAppendMethod(Type exprType) {
Method appendDescriptor = new Method("append", Type.getObjectType(CLASS_STRING_BUILDER), Method appendDescriptor = new Method("append", JetTypeMapper.JL_STRING_BUILDER,
new Type[] { exprType.getSort() == Type.OBJECT ? JetTypeMapper.TYPE_OBJECT : exprType}); new Type[] { exprType.getSort() == Type.OBJECT ? JetTypeMapper.TYPE_OBJECT : exprType});
v.invokevirtual(CLASS_STRING_BUILDER, "append", appendDescriptor.getDescriptor()); v.invokevirtual(CLASS_STRING_BUILDER, "append", appendDescriptor.getDescriptor());
} }
@@ -1938,18 +1935,33 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
private void generateTypeInfo(JetType jetType) { private void generateTypeInfo(JetType jetType) {
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
if(knownTypeInfo != null) {
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
return;
}
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) { if (declarationDescriptor instanceof TypeParameterDescriptor) {
loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor); loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor);
return; return;
} }
final Type jvmType = typeMapper.mapType(jetType, OwnerKind.INTERFACE); if(jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor)) {
if (jvmType.getSort() <= Type.DOUBLE) { // TODO: we need some better checks here
v.getstatic("jet/typeinfo/TypeInfo", PRIMITIVE_TYPE_INFO_FIELDS[jvmType.getSort()], "Ljet/typeinfo/TypeInfo;"); v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
return; return;
} }
boolean hasUnsubstituted = TypeUtils.hasUnsubstitutedTypeParameters(jetType);
if(!hasUnsubstituted) {
int typeInfoConstantIndex = context.getTypeInfoConstantIndex(jetType);
v.invokestatic(context.getNamespaceClassName(), "$getCachedTypeInfo$" + typeInfoConstantIndex, "()Ljet/typeinfo/TypeInfo;");
return;
}
final Type jvmType = typeMapper.mapType(jetType, OwnerKind.INTERFACE);
v.aconst(jvmType); v.aconst(jvmType);
v.iconst(jetType.isNullable()?1:0); v.iconst(jetType.isNullable()?1:0);
List<TypeProjection> arguments = jetType.getArguments(); List<TypeProjection> arguments = jetType.getArguments();
@@ -1974,7 +1986,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public static void genTypeInfoToProjection(InstructionAdapter v, Variance variance) { public static void genTypeInfoToProjection(InstructionAdapter v, Variance variance) {
if(variance == Variance.INVARIANT) if(variance == Variance.INVARIANT)
v.invokestatic("jet/typeinfo/TypeInfo", "invariantProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;"); v.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
else if(variance == Variance.IN_VARIANCE) else if(variance == Variance.IN_VARIANCE)
v.invokestatic("jet/typeinfo/TypeInfo", "inProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;"); v.invokestatic("jet/typeinfo/TypeInfo", "inProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;");
else if(variance == Variance.OUT_VARIANCE) else if(variance == Variance.OUT_VARIANCE)
@@ -94,7 +94,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateFieldForTypeInfo() { private void generateFieldForTypeInfo() {
final boolean typeInfoIsStatic = descriptor.getTypeConstructor().getParameters().size() == 0; final boolean typeInfoIsStatic = descriptor.getTypeConstructor().getParameters().size() == 0;
v.visitField(Opcodes.ACC_PRIVATE | (typeInfoIsStatic ? Opcodes.ACC_STATIC : 0), "$typeInfo", v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | (typeInfoIsStatic ? Opcodes.ACC_STATIC : 0), "$typeInfo",
"Ljet/typeinfo/TypeInfo;", null, null); "Ljet/typeinfo/TypeInfo;", null, null);
if (typeInfoIsStatic) { if (typeInfoIsStatic) {
staticInitializerChunks.add(new CodeChunk() { staticInitializerChunks.add(new CodeChunk() {
@@ -7,26 +7,6 @@ import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
public class InstructionAdapterEx extends InstructionAdapter { public class InstructionAdapterEx extends InstructionAdapter {
private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
private static final Type BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean");
private static final Type SHORT_TYPE = Type.getObjectType("java/lang/Short");
private static final Type CHARACTER_TYPE = Type.getObjectType("java/lang/Character");
private static final Type INTEGER_TYPE = Type.getObjectType("java/lang/Integer");
private static final Type FLOAT_TYPE = Type.getObjectType("java/lang/Float");
private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
private static final Type DOUBLE_TYPE = Type.getObjectType("java/lang/Double");
private static final Type NUMBER_TYPE = Type.getObjectType("java/lang/Number");
private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object");
private static final Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()"); private static final Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()");
private static final Method CHAR_VALUE = Method.getMethod("char charValue()"); private static final Method CHAR_VALUE = Method.getMethod("char charValue()");
@@ -46,21 +26,21 @@ public class InstructionAdapterEx extends InstructionAdapter {
private static Type getBoxedType(final Type type) { private static Type getBoxedType(final Type type) {
switch (type.getSort()) { switch (type.getSort()) {
case Type.BYTE: case Type.BYTE:
return BYTE_TYPE; return JetTypeMapper.JL_BYTE_TYPE;
case Type.BOOLEAN: case Type.BOOLEAN:
return BOOLEAN_TYPE; return JetTypeMapper.JL_BOOLEAN_TYPE;
case Type.SHORT: case Type.SHORT:
return SHORT_TYPE; return JetTypeMapper.JL_SHORT_TYPE;
case Type.CHAR: case Type.CHAR:
return CHARACTER_TYPE; return JetTypeMapper.JL_CHAR_TYPE;
case Type.INT: case Type.INT:
return INTEGER_TYPE; return JetTypeMapper.JL_INTEGER_TYPE;
case Type.FLOAT: case Type.FLOAT:
return FLOAT_TYPE; return JetTypeMapper.JL_FLOAT_TYPE;
case Type.LONG: case Type.LONG:
return LONG_TYPE; return JetTypeMapper.JL_LONG_TYPE;
case Type.DOUBLE: case Type.DOUBLE:
return DOUBLE_TYPE; return JetTypeMapper.JL_DOUBLE_TYPE;
} }
return type; return type;
} }
@@ -78,17 +58,17 @@ public class InstructionAdapterEx extends InstructionAdapter {
} }
public void unbox(final Type type) { public void unbox(final Type type) {
Type t = NUMBER_TYPE; Type t = JetTypeMapper.JL_NUMBER_TYPE;
Method sig = null; Method sig = null;
switch (type.getSort()) { switch (type.getSort()) {
case Type.VOID: case Type.VOID:
return; return;
case Type.CHAR: case Type.CHAR:
t = CHARACTER_TYPE; t = JetTypeMapper.JL_CHAR_TYPE;
sig = CHAR_VALUE; sig = CHAR_VALUE;
break; break;
case Type.BOOLEAN: case Type.BOOLEAN:
t = BOOLEAN_TYPE; t = JetTypeMapper.JL_BOOLEAN_TYPE;
sig = BOOLEAN_VALUE; sig = BOOLEAN_VALUE;
break; break;
case Type.DOUBLE: case Type.DOUBLE:
@@ -28,6 +28,16 @@ public class JetTypeMapper {
public static final Type TYPE_JET_OBJECT = Type.getType(JetObject.class); public static final Type TYPE_JET_OBJECT = Type.getType(JetObject.class);
public static final Type TYPE_CLASS = Type.getType(Class.class); public static final Type TYPE_CLASS = Type.getType(Class.class);
public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing"); public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing");
public static final Type JL_INTEGER_TYPE = Type.getObjectType("java/lang/Integer");
public static final Type JL_LONG_TYPE = Type.getObjectType("java/lang/Long");
public static final Type JL_SHORT_TYPE = Type.getObjectType("java/lang/Short");
public static final Type JL_BYTE_TYPE = Type.getObjectType("java/lang/Byte");
public static final Type JL_CHAR_TYPE = Type.getObjectType("java/lang/Character");
public static final Type JL_FLOAT_TYPE = Type.getObjectType("java/lang/Float");
public static final Type JL_DOUBLE_TYPE = Type.getObjectType("java/lang/Double");
public static final Type JL_BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean");
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder");
private final JetStandardLibrary standardLibrary; private final JetStandardLibrary standardLibrary;
private final BindingContext bindingContext; private final BindingContext bindingContext;
@@ -298,50 +308,50 @@ public class JetTypeMapper {
if (jetType.equals(standardLibrary.getIntType())) { if (jetType.equals(standardLibrary.getIntType())) {
return Type.INT_TYPE; return Type.INT_TYPE;
} }
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getIntType()))) { if (jetType.equals(standardLibrary.getNullableIntType())) {
return Type.getObjectType("java/lang/Integer"); return JL_INTEGER_TYPE;
} }
if (jetType.equals(standardLibrary.getLongType())) { if (jetType.equals(standardLibrary.getLongType())) {
return Type.LONG_TYPE; return Type.LONG_TYPE;
} }
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getLongType()))) { if (jetType.equals(standardLibrary.getNullableLongType())) {
return Type.getObjectType("java/lang/Long"); return JL_LONG_TYPE;
} }
if (jetType.equals(standardLibrary.getShortType())) { if (jetType.equals(standardLibrary.getShortType())) {
return Type.SHORT_TYPE; return Type.SHORT_TYPE;
} }
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getShortType()))) { if (jetType.equals(standardLibrary.getNullableShortType())) {
return Type.getObjectType("java/lang/Short"); return JL_SHORT_TYPE;
} }
if (jetType.equals(standardLibrary.getByteType())) { if (jetType.equals(standardLibrary.getByteType())) {
return Type.BYTE_TYPE; return Type.BYTE_TYPE;
} }
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getByteType()))) { if (jetType.equals(standardLibrary.getNullableByteType())) {
return Type.getObjectType("java/lang/Byte"); return JL_BYTE_TYPE;
} }
if (jetType.equals(standardLibrary.getCharType())) { if (jetType.equals(standardLibrary.getCharType())) {
return Type.CHAR_TYPE; return Type.CHAR_TYPE;
} }
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getCharType()))) { if (jetType.equals(standardLibrary.getNullableCharType())) {
return Type.getObjectType("java/lang/Char"); return JL_CHAR_TYPE;
} }
if (jetType.equals(standardLibrary.getFloatType())) { if (jetType.equals(standardLibrary.getFloatType())) {
return Type.FLOAT_TYPE; return Type.FLOAT_TYPE;
} }
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getFloatType()))) { if (jetType.equals(standardLibrary.getNullableFloatType())) {
return Type.getObjectType("java/lang/Float"); return JL_FLOAT_TYPE;
} }
if (jetType.equals(standardLibrary.getDoubleType())) { if (jetType.equals(standardLibrary.getDoubleType())) {
return Type.DOUBLE_TYPE; return Type.DOUBLE_TYPE;
} }
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getDoubleType()))) { if (jetType.equals(standardLibrary.getNullableDoubleType())) {
return Type.getObjectType("java/lang/Double"); return JL_DOUBLE_TYPE;
} }
if (jetType.equals(standardLibrary.getBooleanType())) { if (jetType.equals(standardLibrary.getBooleanType())) {
return Type.BOOLEAN_TYPE; return Type.BOOLEAN_TYPE;
} }
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getBooleanType()))) { if (jetType.equals(standardLibrary.getNullableBooleanType())) {
return Type.getObjectType("java/lang/Boolean"); return JL_BOOLEAN_TYPE;
} }
if (jetType.equals(standardLibrary.getStringType()) || jetType.equals(standardLibrary.getNullableStringType())) { if (jetType.equals(standardLibrary.getStringType()) || jetType.equals(standardLibrary.getNullableStringType())) {
return Type.getType(String.class); return Type.getType(String.class);
@@ -374,23 +384,23 @@ public class JetTypeMapper {
public Type boxType(Type asmType) { public Type boxType(Type asmType) {
switch (asmType.getSort()) { switch (asmType.getSort()) {
case Type.VOID: case Type.VOID:
return Type.getObjectType("java/lang/Void"); return Type.VOID_TYPE;
case Type.BYTE: case Type.BYTE:
return Type.getObjectType("java/lang/Byte"); return JL_BYTE_TYPE;
case Type.BOOLEAN: case Type.BOOLEAN:
return Type.getObjectType("java/lang/Boolean"); return JL_BOOLEAN_TYPE;
case Type.SHORT: case Type.SHORT:
return Type.getObjectType("java/lang.Short"); return JL_SHORT_TYPE;
case Type.CHAR: case Type.CHAR:
return Type.getObjectType("java/lang/Character"); return JL_CHAR_TYPE;
case Type.INT: case Type.INT:
return Type.getObjectType("java/lang/Integer"); return JL_INTEGER_TYPE;
case Type.FLOAT: case Type.FLOAT:
return Type.getObjectType("java/lang/Float"); return JL_FLOAT_TYPE;
case Type.LONG: case Type.LONG:
return Type.getObjectType("java/lang/Long"); return JL_LONG_TYPE;
case Type.DOUBLE: case Type.DOUBLE:
return Type.getObjectType("java/lang/Double"); return JL_DOUBLE_TYPE;
} }
return asmType; return asmType;
@@ -618,4 +628,68 @@ public class JetTypeMapper {
} }
return result; return result;
} }
public String isKnownTypeInfo(JetType jetType) {
if (jetType.equals(standardLibrary.getIntType())) {
return "INT_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableIntType())) {
return "NULLABLE_INT_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getLongType())) {
return "LONG_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableLongType())) {
return "NULLABLE_LONG_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getShortType())) {
return "SHORT_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableShortType())) {
return "NULLABLE_SHORT_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getByteType())) {
return "BYTE_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableByteType())) {
return "NULLABLE_BYTE_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getCharType())) {
return "CHAR_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableCharType())) {
return "NULLABLE_CHAR_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getFloatType())) {
return "FLOAT_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableFloatType())) {
return "NULLABLE_FLOAT_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getDoubleType())) {
return "DOUBLE_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableDoubleType())) {
return "NULLABLE_DOUBLE_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getBooleanType())) {
return "BOOLEAN_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableBooleanType())) {
return "NULLABLE_BOOLEAN_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getStringType())) {
return "STRING_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableStringType())) {
return "NULLABLE_STRING_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getTuple0Type())) {
return "TUPLE0_TYPE_INFO";
}
if (jetType.equals(standardLibrary.getNullableTuple0Type())) {
return "NULLABLE_TUPLE0_TYPE_INFO";
}
return null;
}
} }
@@ -1,15 +1,22 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor; import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
import org.objectweb.asm.MethodVisitor; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.Opcodes; import org.jetbrains.jet.lang.types.TypeProjection;
import org.objectweb.asm.Type; import org.jetbrains.jet.lang.types.TypeUtils;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import java.util.*;
import static org.objectweb.asm.Opcodes.*;
/** /**
* @author max * @author max
*/ */
@@ -21,8 +28,8 @@ public class NamespaceCodegen {
this.v = v; this.v = v;
this.state = state; this.state = state;
v.visit(Opcodes.V1_6, v.visit(V1_6,
Opcodes.ACC_PUBLIC, ACC_PUBLIC,
getJVMClassName(fqName), getJVMClassName(fqName),
null, null,
//"jet/lang/Namespace", //"jet/lang/Namespace",
@@ -42,10 +49,6 @@ public class NamespaceCodegen {
GenerationState.prepareAnonymousClasses(namespace, state.getTypeMapper()); GenerationState.prepareAnonymousClasses(namespace, state.getTypeMapper());
if (hasNonConstantPropertyInitializers(namespace)) {
generateStaticInitializers(namespace);
}
for (JetDeclaration declaration : namespace.getDeclarations()) { for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
propertyCodegen.gen((JetProperty) declaration); propertyCodegen.gen((JetProperty) declaration);
@@ -65,10 +68,16 @@ public class NamespaceCodegen {
state.forNamespace(childNamespace).generate(childNamespace); state.forNamespace(childNamespace).generate(childNamespace);
} }
} }
if (hasNonConstantPropertyInitializers(namespace, context)) {
generateStaticInitializers(namespace, context);
}
generateTypeInfoFields(namespace, context);
} }
private void generateStaticInitializers(JetNamespace namespace) { private void generateStaticInitializers(JetNamespace namespace, ClassContext context) {
MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, MethodVisitor mv = v.visitMethod(ACC_PUBLIC | ACC_STATIC,
"<clinit>", "()V", null, null); "<clinit>", "()V", null, null);
mv.visitCode(); mv.visitCode();
@@ -85,12 +94,85 @@ public class NamespaceCodegen {
} }
} }
} }
mv.visitInsn(Opcodes.RETURN);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
mv.visitEnd(); mv.visitEnd();
} }
private static boolean hasNonConstantPropertyInitializers(JetNamespace namespace) { private void generateTypeInfoFields(JetNamespace namespace, ClassContext 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()) {
String fieldName = "$typeInfoCache$" + e.getValue();
v.visitField(ACC_PRIVATE|ACC_STATIC|ACC_SYNTHETIC, fieldName, "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mmv = v.visitMethod(ACC_PUBLIC|ACC_STATIC|ACC_SYNTHETIC, "$getCachedTypeInfo$" + e.getValue(), "()Ljet/typeinfo/TypeInfo;", null, null);
InstructionAdapterEx v = new InstructionAdapterEx(mmv);
v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
v.visitInsn(DUP);
Label end = new Label();
v.visitJumpInsn(IFNONNULL, end);
v.pop();
generateTypeInfo(context, v, e.getKey(), state.getTypeMapper(), e.getKey());
v.dup();
v.visitFieldInsn(PUTSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
v.visitLabel(end);
v.visitInsn(ARETURN);
v.visitMaxs(0, 0);
v.visitEnd();
}
}
}
private void generateTypeInfo(ClassContext context, InstructionAdapterEx v, JetType jetType, JetTypeMapper typeMapper, JetType root) {
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
if(knownTypeInfo != null) {
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
return;
}
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
if(!jetType.equals(root) && jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor)) {
// TODO: we need some better checks here
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
return;
}
boolean hasUnsubstituted = TypeUtils.hasUnsubstitutedTypeParameters(jetType);
if(!jetType.equals(root) && !hasUnsubstituted) {
int typeInfoConstantIndex = context.getTypeInfoConstantIndex(jetType);
v.invokestatic(context.getNamespaceClassName(), "$getCachedTypeInfo$" + typeInfoConstantIndex, "()Ljet/typeinfo/TypeInfo;");
return;
}
final Type jvmType = typeMapper.mapType(jetType, OwnerKind.INTERFACE);
v.aconst(jvmType);
v.iconst(jetType.isNullable() ? 1 : 0);
List<TypeProjection> arguments = jetType.getArguments();
if (arguments.size() > 0) {
v.iconst(arguments.size());
v.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
for (int i = 0, argumentsSize = arguments.size(); i < argumentsSize; i++) {
TypeProjection argument = arguments.get(i);
v.dup();
v.iconst(i);
generateTypeInfo(context, v, argument.getType(), typeMapper, root);
ExpressionCodegen.genTypeInfoToProjection(v, argument.getProjectionKind());
v.astore(JetTypeMapper.TYPE_OBJECT);
}
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
}
else {
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
}
}
private static boolean hasNonConstantPropertyInitializers(JetNamespace namespace, ClassContext context) {
for (JetDeclaration declaration : namespace.getDeclarations()) { for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer(); final JetExpression initializer = ((JetProperty) declaration).getInitializer();
@@ -183,10 +183,10 @@ public abstract class StackValue {
else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) { else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
if (this.type.equals(JetTypeMapper.TYPE_OBJECT)) { if (this.type.equals(JetTypeMapper.TYPE_OBJECT)) {
if (type.getSort() == Type.BOOLEAN) { if (type.getSort() == Type.BOOLEAN) {
v.checkcast(Type.getObjectType("java/lang/Boolean")); v.checkcast(JetTypeMapper.JL_BOOLEAN_TYPE);
} }
else { else {
v.checkcast(Type.getObjectType("java/lang/Number")); v.checkcast(JetTypeMapper.JL_NUMBER_TYPE);
} }
} }
unbox(type, v); unbox(type, v);
@@ -56,16 +56,32 @@ public class JetStandardLibrary {
private final ClassDescriptor arrayClass; private final ClassDescriptor arrayClass;
private final ClassDescriptor iterableClass; private final ClassDescriptor iterableClass;
private final ClassDescriptor typeInfoClass; private final ClassDescriptor typeInfoClass;
private final ClassDescriptor tuple0Class;
private final JetType byteType; private final JetType byteType;
private final JetType nullableByteType;
private final JetType charType; private final JetType charType;
private final JetType nullableCharType;
private final JetType shortType; private final JetType shortType;
private final JetType nullableShortType;
private final JetType intType; private final JetType intType;
private final JetType nullableIntType;
private final JetType longType; private final JetType longType;
private final JetType nullableLongType;
private final JetType floatType; private final JetType floatType;
private final JetType nullableFloatType;
private final JetType doubleType; private final JetType doubleType;
private final JetType nullableDoubleType;
private final JetType booleanType; private final JetType booleanType;
private final JetType nullableBooleanType;
private final JetType stringType; private final JetType stringType;
private final JetType nullableTuple0Type;
public JetType getTuple0Type() {
return tuple0Type;
}
private final JetType tuple0Type;
private final JetType nullableStringType; private final JetType nullableStringType;
private final NamespaceDescriptor typeInfoNamespace; private final NamespaceDescriptor typeInfoNamespace;
@@ -100,6 +116,7 @@ public class JetStandardLibrary {
this.stringClass = (ClassDescriptor) libraryScope.getClassifier("String"); this.stringClass = (ClassDescriptor) libraryScope.getClassifier("String");
this.arrayClass = (ClassDescriptor) libraryScope.getClassifier("Array"); this.arrayClass = (ClassDescriptor) libraryScope.getClassifier("Array");
this.iterableClass = (ClassDescriptor) libraryScope.getClassifier("Iterable"); this.iterableClass = (ClassDescriptor) libraryScope.getClassifier("Iterable");
this.tuple0Class = (ClassDescriptor) libraryScope.getClassifier("Tuple0");
typeInfoNamespace = libraryScope.getNamespace("typeinfo"); typeInfoNamespace = libraryScope.getNamespace("typeinfo");
this.typeInfoClass = (ClassDescriptor) typeInfoNamespace.getMemberScope().getClassifier("TypeInfo"); this.typeInfoClass = (ClassDescriptor) typeInfoNamespace.getMemberScope().getClassifier("TypeInfo");
typeInfoFunction = typeInfoNamespace.getMemberScope().getFunctionGroup("typeinfo"); typeInfoFunction = typeInfoNamespace.getMemberScope().getFunctionGroup("typeinfo");
@@ -113,7 +130,18 @@ public class JetStandardLibrary {
this.doubleType = new JetTypeImpl(getDouble()); this.doubleType = new JetTypeImpl(getDouble());
this.booleanType = new JetTypeImpl(getBoolean()); this.booleanType = new JetTypeImpl(getBoolean());
this.stringType = new JetTypeImpl(getString()); this.stringType = new JetTypeImpl(getString());
this.tuple0Type = new JetTypeImpl(getTuple0());
this.nullableByteType = TypeUtils.makeNullable(byteType);
this.nullableCharType = TypeUtils.makeNullable(charType);
this.nullableShortType = TypeUtils.makeNullable(shortType);
this.nullableIntType = TypeUtils.makeNullable(intType);
this.nullableLongType = TypeUtils.makeNullable(longType);
this.nullableFloatType = TypeUtils.makeNullable(floatType);
this.nullableDoubleType = TypeUtils.makeNullable(doubleType);
this.nullableBooleanType = TypeUtils.makeNullable(booleanType);
this.nullableStringType = TypeUtils.makeNullable(stringType); this.nullableStringType = TypeUtils.makeNullable(stringType);
this.nullableTuple0Type = TypeUtils.makeNullable(tuple0Type);
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
@@ -178,6 +206,10 @@ public class JetStandardLibrary {
return iterableClass; return iterableClass;
} }
public ClassDescriptor getTuple0() {
return tuple0Class;
}
public NamespaceDescriptor getTypeInfoNamespace() { public NamespaceDescriptor getTypeInfoNamespace() {
return typeInfoNamespace; return typeInfoNamespace;
} }
@@ -275,4 +307,40 @@ public class JetStandardLibrary {
public JetType getNullableStringType() { public JetType getNullableStringType() {
return nullableStringType; return nullableStringType;
} }
public JetType getNullableByteType() {
return nullableByteType;
}
public JetType getNullableCharType() {
return nullableCharType;
}
public JetType getNullableShortType() {
return nullableShortType;
}
public JetType getNullableIntType() {
return nullableIntType;
}
public JetType getNullableLongType() {
return nullableLongType;
}
public JetType getNullableFloatType() {
return nullableFloatType;
}
public JetType getNullableDoubleType() {
return nullableDoubleType;
}
public JetType getNullableBooleanType() {
return nullableBooleanType;
}
public JetType getNullableTuple0Type() {
return nullableTuple0Type;
}
} }
@@ -96,7 +96,7 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType {
JetTypeImpl type = (JetTypeImpl) o; JetTypeImpl type = (JetTypeImpl) o;
// TODO // TODO
return equalTypes(this, type, EMPTY_AXIOMS); return nullable == type.nullable && equalTypes(this, type, EMPTY_AXIOMS);
// if (nullable != type.nullable) return false; // if (nullable != type.nullable) return false;
// if (arguments != null ? !arguments.equals(type.arguments) : type.arguments != null) return false; // if (arguments != null ? !arguments.equals(type.arguments) : type.arguments != null) return false;
// if (constructor != null ? !constructor.equals(type.constructor) : type.constructor != null) return false; // if (constructor != null ? !constructor.equals(type.constructor) : type.constructor != null) return false;
@@ -320,4 +320,17 @@ public class TypeUtils {
if (declarationDescriptor2 == null) return false; // Class of type1 is not null if (declarationDescriptor2 == null) return false; // Class of type1 is not null
return declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal()); return declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal());
} }
public static boolean hasUnsubstitutedTypeParameters(JetType type) {
if(type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor)
return true;
for(TypeProjection proj : type.getArguments()) {
if(hasUnsubstitutedTypeParameters(proj.getType())) {
return true;
}
}
return false;
}
} }
@@ -70,6 +70,11 @@ public class JetStructureViewElement implements StructureViewTreeElement {
: null; : null;
} }
@Override
public TextAttributesKey getTextAttributesKey() {
return null;
}
}; };
} }
+183 -29
View File
@@ -8,52 +8,143 @@ class B<T>() {
fun t1() : Boolean { fun t1() : Boolean {
val a = A() val a = A()
if(a !is A) return false if(a !is A) return false
return true
}
fun t2() : Boolean {
val a = A()
if(a !is A?) return false if(a !is A?) return false
return true
}
fun t3() : Boolean {
val a = A()
if(null !is A?) return false if(null !is A?) return false
return true return true
} }
fun t2 () : Boolean { fun t4 () : Boolean {
val b = B<String>() val b = B<String>()
if(b !is B<String>) return false if(b !is B<String>) return false
return true
}
fun t5 () : Boolean {
val b = B<String>()
if(b !is B<String>?) return false if(b !is B<String>?) return false
return true
}
fun t6 () : Boolean {
if(null !is B<String>?) return false if(null !is B<String>?) return false
return true
}
val v = b as B<String> //ok fun t7 () : Boolean {
val u = b as B<String>? //TypeCastException val b = B<String>()
if(!b.isT("aaa")) return false
return true
}
fun t8 () : Boolean {
val b = B<String>()
if(b.isT(10)) return false
return true
}
fun t9 () : Boolean {
val b = B<String>()
if(b.isT(null)) return false
return true
}
fun t10 () : Boolean {
val d = B<String?>()
if(!d.isT("aaa")) return false
return true
}
fun t11 () : Boolean {
val d = B<String?>()
if(d.isT(10)) return false
return true
}
fun t12 () : Boolean {
val d = B<String?>()
if(!d.isT(null)) return false
return true
}
fun t13 () : Boolean {
val f = B<java.lang.String?>()
if(!f.isT("aaa")) return false
return true
}
fun t14 () : Boolean {
val f = B<java.lang.String?>()
if(f.isT(10)) return false
return true
}
fun t15 () : Boolean {
val f = B<java.lang.String?>()
if(!f.isT(null)) return false
return true
}
fun t16 () : Boolean {
val c = B<Int>()
if(c.isT("aaa")) return false
return true
}
fun t17 () : Boolean {
val c = B<Int>()
if(!c.isT(10)) return false
return true
}
fun t18 () : Boolean {
val c = B<Int>()
if(c.isT(null)) return false
return true
}
fun t19 () : Boolean {
val e = B<Int?>()
if(e.isT("aaa")) return false
return true
}
fun t20 () : Boolean {
val e = B<Int?>()
if(!e.isT(10)) return false
return true
}
fun t21 () : Boolean {
val e = B<Int?>()
if(!e.isT(null)) return false
return true
}
fun t22 () : Boolean {
val b = B<String>()
val w : B<String>? = b as B<String> //ok val w : B<String>? = b as B<String> //ok
val x = w as B<String>? //TypeCastException val x = w as B<String>? //TypeCastException
return true return true
} }
fun t3 () : Boolean { fun t23 () : Boolean {
val b = B<String>() val b = B<String>()
if(!b.isT("aaa")) return false val v = b as B<String> //ok
return true
if(b.isT(10)) return false }
if(b.isT(null)) return false
val d = B<String?>()
if(!d.isT("aaa")) return false
if(d.isT(10)) return false
if(!d.isT(null)) return false
val f = B<java.lang.String?>()
if(!f.isT("aaa")) return false
if(f.isT(10)) return false
if(!f.isT(null)) return false
val c = B<Int>()
if(c.isT("aaa")) return false
if(!c.isT(10)) return false
if(c.isT(null)) return false
val e = B<Int?>()
if(e.isT("aaa")) return false
if(!e.isT(10)) return false
if(!e.isT(null)) return false
fun t24 () : Boolean {
val b = B<String>()
val u = b as B<String>? //TypeCastException
return true return true
} }
@@ -67,5 +158,68 @@ fun box() : String {
if(!t3()) { if(!t3()) {
return "t3 failed" return "t3 failed"
} }
return "OK" if(!t4()) {
return "t4 failed"
}
if(!t5()) {
return "t5 failed"
}
if(!t6()) {
return "t6 failed"
}
if(!t7()) {
return "t7 failed"
}
if(!t8()) {
return "t8 failed"
}
if(!t9()) {
return "t9 failed"
}
if(!t10()) {
return "t10 failed"
}
if(!t11()) {
return "t11 failed"
}
if(!t12()) {
return "t12 failed"
}
if(!t13()) {
return "t13 failed"
}
if(!t14()) {
return "t14 failed"
}
if(!t15()) {
return "t15 failed"
}
if(!t16()) {
return "t16 failed"
}
if(!t17()) {
return "t17 failed"
}
if(!t18()) {
return "t18 failed"
}
if(!t19()) {
return "t19 failed"
}
if(!t20()) {
return "t10 failed"
}
if(!t21()) {
return "t21 failed"
}
if(!t22()) {
return "t22 failed"
}
if(!t23()) {
return "t23 failed"
}
if(!t24()) {
return "t24 failed"
}
return "OK"
} }
@@ -49,8 +49,8 @@ public class PatternMatchingTest extends CodegenTestCase {
public void testIs() throws Exception { public void testIs() throws Exception {
loadFile(); loadFile();
blackBox();
System.out.println(generateToText()); System.out.println(generateToText());
blackBox();
} }
public void testRange() throws Exception { public void testRange() throws Exception {
+14
View File
@@ -1,6 +1,7 @@
package jet.typeinfo; package jet.typeinfo;
import jet.JetObject; import jet.JetObject;
import jet.Tuple0;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Arrays; import java.util.Arrays;
@@ -19,6 +20,19 @@ public abstract class TypeInfo<T> implements JetObject {
public static final TypeInfo<Boolean> BOOL_TYPE_INFO = getTypeInfo(Boolean.class, false); public static final TypeInfo<Boolean> BOOL_TYPE_INFO = getTypeInfo(Boolean.class, false);
public static final TypeInfo<Float> FLOAT_TYPE_INFO = getTypeInfo(Float.class, false); public static final TypeInfo<Float> FLOAT_TYPE_INFO = getTypeInfo(Float.class, false);
public static final TypeInfo<Double> DOUBLE_TYPE_INFO = getTypeInfo(Double.class, false); public static final TypeInfo<Double> DOUBLE_TYPE_INFO = getTypeInfo(Double.class, false);
public static final TypeInfo<String> STRING_TYPE_INFO = getTypeInfo(String.class, false);
public static final TypeInfo<Tuple0> TUPLE0_TYPE_INFO = getTypeInfo(Tuple0.class, false);
public static final TypeInfo<Byte> NULLABLE_BYTE_TYPE_INFO = getTypeInfo(Byte.class, true);
public static final TypeInfo<Short> NULLABLE_SHORT_TYPE_INFO = getTypeInfo(Short.class, true);
public static final TypeInfo<Integer> NULLABLE_INT_TYPE_INFO = getTypeInfo(Integer.class, true);
public static final TypeInfo<Long> NULLABLE_LONG_TYPE_INFO = getTypeInfo(Long.class, true);
public static final TypeInfo<Character> NULLABLE_CHAR_TYPE_INFO = getTypeInfo(Character.class, true);
public static final TypeInfo<Boolean> NULLABLE_BOOL_TYPE_INFO = getTypeInfo(Boolean.class, true);
public static final TypeInfo<Float> NULLABLE_FLOAT_TYPE_INFO = getTypeInfo(Float.class, true);
public static final TypeInfo<Double> NULLABLE_DOUBLE_TYPE_INFO = getTypeInfo(Double.class, true);
public static final TypeInfo<String> NULLABLE_STRING_TYPE_INFO = getTypeInfo(String.class, true);
public static final TypeInfo<Tuple0> NULLABLE_TUPLE0_TYPE_INFO = getTypeInfo(Tuple0.class, true);
private TypeInfo<?> typeInfo; private TypeInfo<?> typeInfo;
private final Class<T> theClass; private final Class<T> theClass;