tests/fixes
This commit is contained in:
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
@@ -18,9 +19,9 @@ public class CallableMethod implements Callable {
|
||||
private final int invokeOpcode;
|
||||
private final List<Type> valueParameterTypes;
|
||||
private boolean acceptsTypeArguments = false;
|
||||
private boolean needsReceiverOnStack = false;
|
||||
private boolean ownerFromCall = false;
|
||||
private ClassDescriptor receiverClass = null;
|
||||
private DeclarationDescriptor thisClass = null;
|
||||
private DeclarationDescriptor receiverClass = null;
|
||||
private Type generateCalleeType = null;
|
||||
|
||||
public CallableMethod(String owner, Method signature, int invokeOpcode, List<Type> valueParameterTypes) {
|
||||
@@ -58,13 +59,12 @@ public class CallableMethod implements Callable {
|
||||
this.acceptsTypeArguments = acceptsTypeArguments;
|
||||
}
|
||||
|
||||
public void setNeedsReceiver(@Nullable ClassDescriptor receiverClass) {
|
||||
needsReceiverOnStack = true;
|
||||
public void setNeedsReceiver(@Nullable DeclarationDescriptor receiverClass) {
|
||||
this.receiverClass = receiverClass;
|
||||
}
|
||||
|
||||
public boolean needsReceiverOnStack() {
|
||||
return needsReceiverOnStack;
|
||||
public void setNeedsThis(@Nullable DeclarationDescriptor receiverClass) {
|
||||
this.thisClass = receiverClass;
|
||||
}
|
||||
|
||||
public boolean isOwnerFromCall() {
|
||||
@@ -75,10 +75,6 @@ public class CallableMethod implements Callable {
|
||||
this.ownerFromCall = ownerFromCall;
|
||||
}
|
||||
|
||||
public ClassDescriptor getReceiverClass() {
|
||||
return receiverClass;
|
||||
}
|
||||
|
||||
void invoke(InstructionAdapter v) {
|
||||
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getName(), getSignature().getDescriptor());
|
||||
}
|
||||
@@ -98,4 +94,17 @@ public class CallableMethod implements Callable {
|
||||
desc = desc.replace("(", "(L" + getOwner() + ";");
|
||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc);
|
||||
}
|
||||
|
||||
public boolean isNeedsThis() {
|
||||
return thisClass != null;
|
||||
}
|
||||
|
||||
public boolean isNeedsReceiver() {
|
||||
return receiverClass != null;
|
||||
}
|
||||
|
||||
public DeclarationDescriptor getThisClass() {
|
||||
return thisClass;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -260,15 +257,4 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
|
||||
signatureWriter.visitClassType(rawRetType.getInternalName());
|
||||
signatureWriter.visitEnd();
|
||||
}
|
||||
|
||||
public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
|
||||
Method descriptor = erasedInvokeSignature(fd);
|
||||
String owner = getInternalClassName(fd);
|
||||
final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
|
||||
if (fd.getReceiverParameter().exists()) {
|
||||
result.setNeedsReceiver(null);
|
||||
}
|
||||
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author yole
|
||||
@@ -77,6 +79,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
this.intrinsics = state.getIntrinsics();
|
||||
}
|
||||
|
||||
private CallableMethod asCallableMethod(FunctionDescriptor fd) {
|
||||
Method descriptor = ClosureCodegen.erasedInvokeSignature(fd);
|
||||
String owner = ClosureCodegen.getInternalClassName(fd);
|
||||
final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
|
||||
if (fd.getReceiverParameter().exists()) {
|
||||
result.setNeedsReceiver(fd.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor());
|
||||
}
|
||||
result.requestGenerateCallee(Type.getObjectType(ClosureCodegen.getInternalClassName(fd)));
|
||||
return result;
|
||||
}
|
||||
|
||||
public GenerationState getState() {
|
||||
return state;
|
||||
}
|
||||
@@ -983,7 +996,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
callableMethod = typeMapper.mapToCallableMethod((PsiNamedElement) declarationPsiElement, null);
|
||||
}
|
||||
else if (fd instanceof VariableAsFunctionDescriptor) {
|
||||
callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd);
|
||||
callableMethod = asCallableMethod((FunctionDescriptor) fd);
|
||||
}
|
||||
else if (fd instanceof FunctionDescriptor) {
|
||||
callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, null);
|
||||
@@ -1018,13 +1031,27 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (callableMethod.isOwnerFromCall()) {
|
||||
setOwnerFromCall(callableMethod, expression);
|
||||
}
|
||||
if (callableMethod.needsReceiverOnStack()) {
|
||||
if (receiver == StackValue.none()) {
|
||||
ClassDescriptor receiverClass = callableMethod.getReceiverClass();
|
||||
receiver = receiverClass == null ? thisExpression() : generateThisOrOuter(receiverClass);
|
||||
|
||||
if (callableMethod.isNeedsThis()) {
|
||||
if(callableMethod.isNeedsReceiver()) {
|
||||
generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
}
|
||||
else {
|
||||
if (receiver == StackValue.none()) {
|
||||
generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v);;
|
||||
}
|
||||
else {
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
}
|
||||
}
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
}
|
||||
else {
|
||||
if (callableMethod.isNeedsReceiver()) {
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
}
|
||||
}
|
||||
|
||||
int mask = pushMethodArguments(expression, callableMethod.getValueParameterTypes());
|
||||
if (callableMethod.acceptsTypeArguments()) {
|
||||
pushTypeArguments(expression);
|
||||
@@ -1790,23 +1817,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
private void pushTypeArguments(JetCallElement expression) {
|
||||
// todo when frontend calculates
|
||||
// ResolvedCallImpl<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
|
||||
// if(resolvedCall != null) {
|
||||
// Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
||||
// CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||
// for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) {
|
||||
// JetType jetType = typeArguments.get(typeParameterDescriptor);
|
||||
// generateTypeInfo(jetType);
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
||||
// pushTypeArgument(jetTypeArgument);
|
||||
// }
|
||||
// }
|
||||
for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
||||
pushTypeArgument(jetTypeArgument);
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
|
||||
if(resolvedCall != null) {
|
||||
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
||||
CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor();
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) {
|
||||
JetType jetType = typeArguments.get(typeParameterDescriptor);
|
||||
generateTypeInfo(jetType);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
||||
pushTypeArgument(jetTypeArgument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1820,7 +1843,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
Type type = JetTypeMapper.psiClassType(javaClass);
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
final CallableMethod callableMethod = JetTypeMapper.mapToCallableMethod(constructor);
|
||||
final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor);
|
||||
invokeMethodWithArguments(callableMethod, expression);
|
||||
return type;
|
||||
}
|
||||
@@ -1916,7 +1939,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
assert declaration != null : "No declaration found for " + expression.getText();
|
||||
final CallableMethod accessor;
|
||||
if (declaration instanceof PsiMethod) {
|
||||
accessor = JetTypeMapper.mapToCallableMethod((PsiMethod) declaration);
|
||||
accessor = typeMapper.mapToCallableMethod((PsiMethod) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetNamedFunction) {
|
||||
accessor = typeMapper.mapToCallableMethod((JetNamedFunction) declaration, null);
|
||||
|
||||
@@ -63,6 +63,14 @@ public class FunctionCodegen {
|
||||
if (isAbstract) flags |= ACC_ABSTRACT;
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
|
||||
for(int i = 0; i != paramDescrs.size(); ++i) {
|
||||
AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "jet/typeinfo/JetParameterName", true);
|
||||
annotationVisitor.visit("value", paramDescrs.get(i).getName());
|
||||
annotationVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
if (!isAbstract) {
|
||||
mv.visitCode();
|
||||
FrameMap frameMap = context.prepareFrame();
|
||||
|
||||
@@ -162,40 +162,6 @@ public class JetTypeMapper {
|
||||
return new Method(method.isConstructor() ? "<init>" : method.getName(), Type.getMethodDescriptor(returnType, parameterTypes));
|
||||
}
|
||||
|
||||
static CallableMethod mapToCallableMethod(PsiMethod method) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
String owner = jvmName(containingClass);
|
||||
Method signature = getMethodDescriptor(method);
|
||||
List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||
Collections.addAll(valueParameterTypes, signature.getArgumentTypes());
|
||||
int opcode;
|
||||
boolean needsReceiver = false;
|
||||
boolean ownerFromCall = false;
|
||||
if (method.isConstructor()) {
|
||||
opcode = Opcodes.INVOKESPECIAL;
|
||||
}
|
||||
else if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
opcode = Opcodes.INVOKESTATIC;
|
||||
}
|
||||
else {
|
||||
needsReceiver = true;
|
||||
assert containingClass != null;
|
||||
if (containingClass.isInterface()) {
|
||||
opcode = Opcodes.INVOKEINTERFACE;
|
||||
}
|
||||
else {
|
||||
opcode = Opcodes.INVOKEVIRTUAL;
|
||||
}
|
||||
ownerFromCall = true;
|
||||
}
|
||||
final CallableMethod result = new CallableMethod(owner, signature, opcode, valueParameterTypes);
|
||||
if (needsReceiver) {
|
||||
result.setNeedsReceiver(null);
|
||||
}
|
||||
result.setOwnerFromCall(ownerFromCall);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Type getBoxedType(final Type type) {
|
||||
switch (type.getSort()) {
|
||||
case Type.BYTE:
|
||||
@@ -518,18 +484,49 @@ public class JetTypeMapper {
|
||||
return mapToCallableMethod(functionDescriptor, kind);
|
||||
}
|
||||
|
||||
CallableMethod mapToCallableMethod(PsiMethod method) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
String owner = jvmName(containingClass);
|
||||
Method signature = getMethodDescriptor(method);
|
||||
List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||
Collections.addAll(valueParameterTypes, signature.getArgumentTypes());
|
||||
int opcode;
|
||||
boolean ownerFromCall = false;
|
||||
DeclarationDescriptor thisClass = null;
|
||||
if (method.isConstructor()) {
|
||||
opcode = Opcodes.INVOKESPECIAL;
|
||||
}
|
||||
else if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
opcode = Opcodes.INVOKESTATIC;
|
||||
}
|
||||
else {
|
||||
assert containingClass != null;
|
||||
if (containingClass.isInterface()) {
|
||||
opcode = Opcodes.INVOKEINTERFACE;
|
||||
}
|
||||
else {
|
||||
opcode = Opcodes.INVOKEVIRTUAL;
|
||||
}
|
||||
ownerFromCall = true;
|
||||
thisClass = JetStandardClasses.getAny(); // todo - this is hack, correct descriptor needed
|
||||
}
|
||||
final CallableMethod result = new CallableMethod(owner, signature, opcode, valueParameterTypes);
|
||||
result.setNeedsThis(thisClass);
|
||||
result.setOwnerFromCall(ownerFromCall);
|
||||
return result;
|
||||
}
|
||||
|
||||
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
|
||||
final List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
|
||||
String owner;
|
||||
int invokeOpcode;
|
||||
boolean needsReceiver;
|
||||
ClassDescriptor receiverClass = null;
|
||||
ClassDescriptor thisClass;
|
||||
if (functionParent instanceof NamespaceDescriptor) {
|
||||
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
|
||||
invokeOpcode = Opcodes.INVOKESTATIC;
|
||||
needsReceiver = functionDescriptor.getReceiverParameter().exists();
|
||||
thisClass = null;
|
||||
}
|
||||
else if (functionParent instanceof ClassDescriptor) {
|
||||
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||
@@ -537,8 +534,7 @@ public class JetTypeMapper {
|
||||
invokeOpcode = CodegenUtil.isInterface(containingClass)
|
||||
? Opcodes.INVOKEINTERFACE
|
||||
: Opcodes.INVOKEVIRTUAL;
|
||||
needsReceiver = true;
|
||||
receiverClass = containingClass;
|
||||
thisClass = containingClass;
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("unknown function parent");
|
||||
@@ -546,9 +542,11 @@ public class JetTypeMapper {
|
||||
|
||||
final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode, valueParameterTypes);
|
||||
result.setAcceptsTypeArguments(true);
|
||||
if (needsReceiver) {
|
||||
result.setNeedsReceiver(receiverClass);
|
||||
result.setNeedsThis(thisClass);
|
||||
if(functionDescriptor.getReceiverParameter().exists()) {
|
||||
result.setNeedsReceiver(functionDescriptor.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="module" module-name="stdlib" />
|
||||
<orderEntry type="module" module-name="cli" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ trait A {
|
||||
fun bar(arg: Int = 240) : Int = bar2(arg/2)
|
||||
}
|
||||
|
||||
open abstract class B() : A {
|
||||
open abstract class B() : A, java.lang.Object() {
|
||||
fun foo(arg: Int = 239 + 1) : Int = arg
|
||||
|
||||
abstract fun foo2(arg: Int = 239) : Int
|
||||
@@ -23,15 +23,29 @@ open abstract class B() : A {
|
||||
|
||||
class C() : B() {
|
||||
override fun foo2(arg: Int) : Int = arg
|
||||
|
||||
fun Any.toMyPrefixedString(prefix: String = "", suffix: String="") : String = prefix + " " + suffix
|
||||
|
||||
fun testReceiver() : String {
|
||||
val res : String = "mama".toMyPrefixedString("111", "222")
|
||||
System.out?.println(res)
|
||||
return res
|
||||
}
|
||||
|
||||
override fun toString() : String = "CCC"
|
||||
}
|
||||
|
||||
// fun <T> T.toPrefixedString(prefix: String = "") = prefix + (this as java.lang.Object).toString()
|
||||
fun <T> T.toPrefixedString(prefix: String = "", suffix: String="") = prefix + (this as java.lang.Object).toString() + suffix
|
||||
|
||||
fun box() : String {
|
||||
val expected = (true, true, true, " ")
|
||||
|
||||
// if("mama".toPrefixedString("papa") != "papamama") return "fail"
|
||||
// if("mama".toPrefixedString() != "mama") return "fail"
|
||||
if("mama".toPrefixedString(suffix="321", prefix="papa") != "papamama321") return "fail"
|
||||
if("mama".toPrefixedString(prefix="papa") != "papamama") return "fail"
|
||||
if("mama".toPrefixedString("papa", "239") != "papamama239") return "fail"
|
||||
if("mama".toPrefixedString("papa") != "papamama") return "fail"
|
||||
if("mama".toPrefixedString() != "mama") return "fail"
|
||||
if(C().testReceiver() != "111 222") return "fail"
|
||||
if(C().bar(10) != 5) return "fail"
|
||||
if(C().bar() != 120) return "fail"
|
||||
if(C().foo(10) != 10) return "fail"
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
fun reformat(
|
||||
str : String,
|
||||
normalizeCase : Boolean = true,
|
||||
uppercaseFirstLetter : Boolean = true,
|
||||
divideByCamelHumps : Boolean = false,
|
||||
wordSeparator : String = " "
|
||||
) =
|
||||
(normalizeCase, uppercaseFirstLetter, divideByCamelHumps, wordSeparator)
|
||||
|
||||
fun box() : String {
|
||||
val expected = (true, true, false, " ")
|
||||
if(reformat("", true, true, false, " ") != expected) return "fail"
|
||||
// if(reformat(str="", wordSeparator=" ") != expected) return "fail"
|
||||
// if(reformat("", true, true, false) != expected) return "fail"
|
||||
// if(reformat("", true, true) != expected) return "fail"
|
||||
// if(reformat("", true) != expected) return "fail"
|
||||
// if(reformat("") != expected) return "fail"
|
||||
return "OK"
|
||||
}
|
||||
@@ -6,10 +6,7 @@ package org.jetbrains.jet.codegen;
|
||||
public class FunctionGenTest extends CodegenTestCase {
|
||||
public void testDefaultArgs() throws Exception {
|
||||
blackBoxFile("functions/defaultargs.jet");
|
||||
}
|
||||
|
||||
public void testNamedArgs() throws Exception {
|
||||
blackBoxFile("functions/defaultargs.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testNoThisNoClosure() throws Exception {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package jet.typeinfo;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
@Target({ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JetParameterName {
|
||||
String value ();
|
||||
}
|
||||
Reference in New Issue
Block a user