Constructors in objects
This commit is contained in:
@@ -2,22 +2,26 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class CodegenUtil {
|
||||
public static boolean isInterface(DeclarationDescriptor descriptor, BindingContext bindingContext) {
|
||||
PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
|
||||
if(psiElement instanceof JetClass) {
|
||||
return ((JetClass)psiElement).isTrait();
|
||||
}
|
||||
if(psiElement instanceof PsiClass) {
|
||||
return ((PsiClass)psiElement).isInterface();
|
||||
}
|
||||
return false;
|
||||
private CodegenUtil() {
|
||||
}
|
||||
|
||||
public static boolean isInterface(DeclarationDescriptor descriptor) {
|
||||
return descriptor instanceof ClassDescriptor && ((ClassDescriptor)descriptor).getKind() == ClassKind.TRAIT;
|
||||
}
|
||||
|
||||
public static boolean isInterface(JetType type) {
|
||||
return isInterface(type.getConstructor().getDeclarationDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
receiver.put(receiverType != null ? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
|
||||
if(receiverType != null) {
|
||||
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
|
||||
if(!CodegenUtil.isInterface(propReceiverDescriptor, bindingContext) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor(), bindingContext)) {
|
||||
if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) {
|
||||
// I hope it happens only in case of required super class for traits
|
||||
v.checkcast(typeMapper.mapType(propReceiverDescriptor.getDefaultType()));
|
||||
}
|
||||
@@ -2026,7 +2026,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
JetType defaultType = descriptor.getDefaultType();
|
||||
Type ownerType = typeMapper.mapType(defaultType);
|
||||
ownerType = JetTypeMapper.boxType(ownerType);
|
||||
if(!typeMapper.isInterface(descriptor)) {
|
||||
if(!CodegenUtil.isInterface(descriptor)) {
|
||||
if (descriptor.getTypeConstructor().getParameters().size() > 0) {
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -47,33 +46,6 @@ public class FunctionCodegen {
|
||||
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor);
|
||||
}
|
||||
|
||||
private void generateBridgeMethod(Method function, Method overriden)
|
||||
{
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(flags, function.getName(), overriden.getDescriptor(), null, null);
|
||||
mv.visitCode();
|
||||
|
||||
Type[] argTypes = function.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
|
||||
iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), function.getName(), function.getDescriptor());
|
||||
if(JetTypeMapper.isPrimitive(function.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
|
||||
StackValue.valueOf(iv, function.getReturnType());
|
||||
if(function.getReturnType() == Type.VOID_TYPE)
|
||||
iv.aconst(null);
|
||||
iv.areturn(overriden.getReturnType());
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generatedMethod(JetExpression bodyExpressions,
|
||||
Method jvmSignature,
|
||||
ClassContext context,
|
||||
@@ -86,10 +58,13 @@ public class FunctionCodegen {
|
||||
|
||||
OwnerKind kind = context.getContextKind();
|
||||
|
||||
if(kind == OwnerKind.TRAIT_IMPL && bodyExpressions == null)
|
||||
return;
|
||||
|
||||
boolean isStatic = kind == OwnerKind.NAMESPACE || kind == OwnerKind.TRAIT_IMPL;
|
||||
if (isStatic) flags |= Opcodes.ACC_STATIC;
|
||||
|
||||
boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration(), state.getBindingContext()));
|
||||
boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
|
||||
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||
@@ -122,21 +97,58 @@ public class FunctionCodegen {
|
||||
iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||
iv.areturn(jvmSignature.getReturnType());
|
||||
}
|
||||
else if (!isAbstract) {
|
||||
else {
|
||||
codegen.returnExpression(bodyExpressions);
|
||||
}
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
|
||||
if(overriddenFunctions.size() > 0) {
|
||||
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
||||
// TODO should we check params here as well?
|
||||
if(!TypeUtils.equalClasses(overriddenFunction.getOriginal().getReturnType(), functionDescriptor.getReturnType())) {
|
||||
generateBridgeMethod(jvmSignature, state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()));
|
||||
}
|
||||
}
|
||||
generateBridgeIfNeeded(owner, state, v, jvmSignature, functionDescriptor, kind);
|
||||
}
|
||||
}
|
||||
|
||||
static void generateBridgeIfNeeded(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||
Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
|
||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
||||
// TODO should we check params here as well?
|
||||
checkOverride(owner, state, v, jvmSignature, functionDescriptor, overriddenFunction);
|
||||
}
|
||||
checkOverride(owner, state, v, jvmSignature, functionDescriptor, functionDescriptor.getOriginal());
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkOverride(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
|
||||
Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
|
||||
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
|
||||
if(!type1.equals(type2)) {
|
||||
Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal());
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
|
||||
mv.visitCode();
|
||||
|
||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
if(argType.getSort() == Type.OBJECT) {
|
||||
iv.checkcast(argType);
|
||||
}
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
|
||||
iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
|
||||
StackValue.valueOf(iv, jvmSignature.getReturnType());
|
||||
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
|
||||
iv.aconst(null);
|
||||
iv.areturn(overriden.getReturnType());
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
@@ -314,74 +315,60 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait() || ((JetClass)myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD))
|
||||
return;
|
||||
|
||||
HashSet<FunctionDescriptor> set = new HashSet<FunctionDescriptor>();
|
||||
getAbstractMethods(descriptor.getDefaultType(), set);
|
||||
for(FunctionDescriptor fun: set) {
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
for (CallableDescriptor callableDescriptor : OverridingUtil.getEffectiveMembers(descriptor)) {
|
||||
if(callableDescriptor instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor fun = (FunctionDescriptor) callableDescriptor;
|
||||
DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration();
|
||||
if(containingDeclaration instanceof ClassDescriptor) {
|
||||
ClassDescriptor declaration = (ClassDescriptor) containingDeclaration;
|
||||
PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaration);
|
||||
if(psiElement instanceof JetClass) {
|
||||
JetClass jetClass = (JetClass) psiElement;
|
||||
if(jetClass.isTrait()) {
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
|
||||
Method function = state.getTypeMapper().mapSignature(fun.getName(), fun);
|
||||
Method function = state.getTypeMapper().mapSignature(fun.getName(), fun);
|
||||
Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal());
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(flags, function.getName(), function.getDescriptor(), null, null);
|
||||
mv.visitCode();
|
||||
final MethodVisitor mv = v.visitMethod(flags, function.getName(), function.getDescriptor(), null, null);
|
||||
mv.visitCode();
|
||||
|
||||
codegen.generateThisOrOuter(descriptor);
|
||||
codegen.generateThisOrOuter(descriptor);
|
||||
|
||||
Type[] argTypes = function.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
Type[] argTypes = function.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) fun.getContainingDeclaration();
|
||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, state.getBindingContext());
|
||||
Type type = state.getTypeMapper().mapType(jetType);
|
||||
if(type.getInternalName().equals("java/lang/Object")) {
|
||||
jetType = containingDeclaration.getDefaultType();
|
||||
type = state.getTypeMapper().mapType(jetType);
|
||||
}
|
||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, state.getBindingContext());
|
||||
Type type = state.getTypeMapper().mapType(jetType);
|
||||
if(type.getInternalName().equals("java/lang/Object")) {
|
||||
jetType = declaration.getDefaultType();
|
||||
type = state.getTypeMapper().mapType(jetType);
|
||||
}
|
||||
|
||||
String fdescriptor = function.getDescriptor().replace("(","(" + type.getDescriptor());
|
||||
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
|
||||
iv.areturn(function.getReturnType());
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void getAbstractMethods(JetType type, Set<FunctionDescriptor> set) {
|
||||
if(type.equals(JetStandardClasses.getAny())) {
|
||||
return;
|
||||
}
|
||||
String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor());
|
||||
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
|
||||
if(function.getReturnType().getSort() == Type.OBJECT) {
|
||||
iv.checkcast(function.getReturnType());
|
||||
}
|
||||
iv.areturn(function.getReturnType());
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
for(JetType superType : type.getConstructor().getSupertypes()) {
|
||||
getAbstractMethods(superType, set);
|
||||
}
|
||||
|
||||
PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, type.getConstructor().getDeclarationDescriptor());
|
||||
if(psiElement instanceof JetClass) {
|
||||
JetClass jetClass = (JetClass) psiElement;
|
||||
for(JetDeclaration decl : jetClass.getDeclarations()) {
|
||||
if(decl instanceof JetNamedFunction) {
|
||||
JetNamedFunction jetNamedFunction = (JetNamedFunction) decl;
|
||||
FunctionDescriptor funDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, decl);
|
||||
set.removeAll(funDescriptor.getOverriddenDescriptors());
|
||||
|
||||
if(jetNamedFunction.getBodyExpression() == null || jetClass.isTrait()) {
|
||||
set.add(funDescriptor);
|
||||
FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(psiElement instanceof PsiClass) {
|
||||
// todo
|
||||
PsiClass psiClass = (PsiClass) psiElement;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getOuterClassDescriptor() {
|
||||
if (myClass.getParent() instanceof JetClassObject) {
|
||||
@@ -762,9 +749,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
|
||||
public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
|
||||
if(!exceptOwn) {
|
||||
if(!state.getTypeMapper().isInterface((ClassDescriptor) type.getConstructor().getDeclarationDescriptor()))
|
||||
if(!CodegenUtil.isInterface(type))
|
||||
if(isParametrizedClass(type))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -222,14 +222,6 @@ public class JetTypeMapper {
|
||||
return jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
|
||||
public boolean isInterface(ClassDescriptor jetClass) {
|
||||
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetClass);
|
||||
if (declaration instanceof JetObjectDeclaration) {
|
||||
return false;
|
||||
}
|
||||
return declaration instanceof JetClass && ((JetClass) declaration).isTrait();
|
||||
}
|
||||
|
||||
private static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
||||
if (jetClass.getKind() == ClassKind.OBJECT) {
|
||||
return jvmNameForImplementation(jetClass);
|
||||
@@ -496,7 +488,7 @@ public class JetTypeMapper {
|
||||
else if (functionParent instanceof ClassDescriptor) {
|
||||
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
|
||||
invokeOpcode = isInterface(containingClass)
|
||||
invokeOpcode = CodegenUtil.isInterface(containingClass)
|
||||
? Opcodes.INVOKEINTERFACE
|
||||
: Opcodes.INVOKEVIRTUAL;
|
||||
needsReceiver = true;
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class MethodCodeGen {
|
||||
|
||||
}
|
||||
@@ -2,9 +2,7 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
@@ -52,6 +50,10 @@ public class PropertyCodegen {
|
||||
|
||||
private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||
if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
if(CodegenUtil.isInterface(containingDeclaration))
|
||||
return;
|
||||
|
||||
Object value = null;
|
||||
final JetExpression initializer = p.getInitializer();
|
||||
if (initializer != null) {
|
||||
|
||||
@@ -131,7 +131,7 @@ public class DeclarationResolver {
|
||||
if (!klass.hasPrimaryConstructor() && classDescriptor.getKind() != ClassKind.OBJECT) return;
|
||||
|
||||
if (classDescriptor.getKind() == ClassKind.TRAIT) {
|
||||
// context.getTrace().getErrorHandler().genericError(klass.getPrimaryConstructorParameterList().getNode(), "A trait may not have a constructor");
|
||||
// context.getTrace().getErrorHandler().genericError(klass.getPrimaryConstructorParameterList().getNode(), "A trait may not have a constructor");
|
||||
context.getTrace().report(CONSTRUCTOR_IN_TRAIT.on(klass.getPrimaryConstructorParameterList()));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ import java.util.Set;
|
||||
*/
|
||||
public class OverridingUtil {
|
||||
|
||||
private OverridingUtil() {
|
||||
}
|
||||
|
||||
public static Set<CallableDescriptor> getEffectiveMembers(@NotNull ClassDescriptor classDescriptor) {
|
||||
Collection<DeclarationDescriptor> allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors();
|
||||
Set<CallableDescriptor> allMembers = Sets.newLinkedHashSet();
|
||||
|
||||
@@ -31,7 +31,7 @@ public class TypeProjection {
|
||||
@Override
|
||||
public String toString() {
|
||||
if (projection == Variance.INVARIANT) {
|
||||
return type + "";
|
||||
return type.toString();
|
||||
}
|
||||
return projection + " " + type;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
trait ISized {
|
||||
val size : Int
|
||||
}
|
||||
|
||||
trait ReadOnlyArray<out T> : ISized, Iterable<T> {
|
||||
fun get(index : Int) : T
|
||||
|
||||
override fun iterator () : Iterator<T> = object : Iterator<T> {
|
||||
private var index = 0
|
||||
|
||||
override fun hasNext() : Boolean = index < size
|
||||
|
||||
val next : T
|
||||
get() = get(index++)
|
||||
}
|
||||
}
|
||||
|
||||
trait WriteOnlyArray<in T> : ISized {
|
||||
fun set(index : Int, value : T) : Unit
|
||||
|
||||
fun set(from: Int, count: Int, value: T) {
|
||||
for(i in 0..(count-1)) {
|
||||
set(i, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MutableArray<T>(length: Int) : ReadOnlyArray<T>, WriteOnlyArray<T> {
|
||||
private val array = Array<T>(length)
|
||||
|
||||
override fun get(index : Int) : T = array[index]
|
||||
override fun set(index : Int, value : T) : Unit { array[index] = value }
|
||||
|
||||
override val size : Int
|
||||
get() = array.size
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
var a = MutableArray<Int> (4)
|
||||
a [0] = 10
|
||||
a.set(1, 2, 13)
|
||||
a [3] = 40
|
||||
return "OK"
|
||||
}
|
||||
@@ -20,4 +20,9 @@ public class TraitsTest extends CodegenTestCase {
|
||||
blackBoxFile("traits/multiple.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testStdlib () throws Exception {
|
||||
blackBoxFile("traits/stdlib.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package jet.typeinfo;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.generic.MethodGen;
|
||||
import jet.JetObject;
|
||||
import jet.Tuple0;
|
||||
|
||||
@@ -92,7 +91,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
nullable = false;
|
||||
}
|
||||
|
||||
public TypeInfoVar(boolean nullable, Integer varIndex) {
|
||||
public TypeInfoVar(boolean nullable, int varIndex) {
|
||||
this.nullable = nullable;
|
||||
this.varIndex = varIndex;
|
||||
}
|
||||
@@ -474,11 +473,12 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
|
||||
public List<TypeInfoProjection> parseVars() {
|
||||
List<TypeInfoProjection> list = null;
|
||||
while(cur != string.length && string[cur] == 'T') {
|
||||
while(cur < string.length && string[cur] == 'T') {
|
||||
if(list == null) {
|
||||
list = new LinkedList<TypeInfoProjection>();
|
||||
variables = new HashMap<String, Integer>();
|
||||
}
|
||||
cur++;
|
||||
list.add(parseVar());
|
||||
}
|
||||
return list == null ? Collections.<TypeInfoProjection>emptyList() : list;
|
||||
@@ -508,7 +508,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
|
||||
private String parseName() {
|
||||
int c = ++cur; // skip 'T'
|
||||
int c = cur;
|
||||
while (string[c] != ';') {
|
||||
c++;
|
||||
}
|
||||
@@ -522,7 +522,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
cur += 3;
|
||||
return TypeInfoVariance.IN_VARIANCE;
|
||||
}
|
||||
else if (string[cur] == 'o' && string[cur+1] == 'u' && string[cur+2] == 't' && string[cur+2] == ' ') {
|
||||
else if (string[cur] == 'o' && string[cur+1] == 'u' && string[cur+2] == 't' && string[cur+3] == ' ') {
|
||||
cur += 4;
|
||||
return TypeInfoVariance.OUT_VARIANCE;
|
||||
}
|
||||
@@ -545,6 +545,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
private TypeInfo parseType() {
|
||||
switch (string[cur]) {
|
||||
case 'L':
|
||||
cur++;
|
||||
String name = parseName();
|
||||
Class<?> aClass;
|
||||
try {
|
||||
@@ -572,6 +573,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
return new TypeInfoImpl(aClass, nullable,proj.toArray(new TypeInfoProjection[proj.size()]));
|
||||
|
||||
case 'T':
|
||||
cur++;
|
||||
return parseTypeVar();
|
||||
|
||||
default:
|
||||
@@ -580,6 +582,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
|
||||
private TypeInfo parseTypeVar() {
|
||||
TypeInfoVariance variance = parseVariance();
|
||||
String name = parseName();
|
||||
boolean nullable = false;
|
||||
if(string[cur] == '?') {
|
||||
|
||||
Reference in New Issue
Block a user