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