default params of constructors (untested because frontend is not ready yet)

This commit is contained in:
Alex Tkachman
2011-12-06 12:42:18 +02:00
parent 36c0ab6642
commit b9f1ddd14c
3 changed files with 37 additions and 29 deletions
@@ -81,9 +81,14 @@ public class CallableMethod implements Callable {
public void invokeWithDefault(InstructionAdapter v, int mask) {
v.iconst(mask);
String desc = getSignature().getDescriptor().replace(")", "I)");
if(getInvokeOpcode() != Opcodes.INVOKESTATIC)
desc = desc.replace("(", "(L" + getOwner() + ";");
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc);
if("<init>".equals(getSignature().getName())) {
v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "<init>", desc);
}
else {
if(getInvokeOpcode() != Opcodes.INVOKESTATIC)
desc = desc.replace("(", "(L" + getOwner() + ";");
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc);
}
}
public boolean isNeedsThis() {
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -226,7 +227,7 @@ public class FunctionCodegen {
}
}
static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, @Nullable FunctionDescriptor functionDescriptor, OwnerKind kind) {
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
if(kind != OwnerKind.TRAIT_IMPL) {
@@ -242,15 +243,18 @@ public class FunctionCodegen {
}
boolean needed = false;
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
if(parameterDescriptor.hasDefaultValue()) {
needed = true;
break;
if(functionDescriptor != null) {
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
if(parameterDescriptor.hasDefaultValue()) {
needed = true;
break;
}
}
}
if(needed) {
boolean hasReceiver = functionDescriptor.getReceiverParameter().exists();
ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
boolean hasReceiver = receiverParameter.exists();
boolean isStatic = kind == OwnerKind.NAMESPACE;
if(kind == OwnerKind.TRAIT_IMPL) {
@@ -265,9 +269,10 @@ public class FunctionCodegen {
state.getTypeMapper().mapType(((ClassDescriptor) contextClass).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
String descriptor = jvmSignature.getDescriptor().replace(")","I)");
if(!isStatic)
boolean isConstructor = "<init>".equals(jvmSignature.getName());
if(!isStatic && !isConstructor)
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null);
final MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC), isConstructor ? "<init>" : jvmSignature.getName() + "$default", descriptor, null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
if (v.generateCode()) {
mv.visitCode();
@@ -278,33 +283,28 @@ public class FunctionCodegen {
int var = 0;
if(!isStatic) {
frameMap.enterTemp();
var++;
}
Type receiverType = receiverParameter.exists() ? state.getTypeMapper().mapType(receiverParameter.getType()) : Type.DOUBLE_TYPE;
if(hasReceiver) {
frameMap.enterTemp();
var++;
var += receiverType.getSize();
}
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
int slot = frameMap.enterTemp();
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
var++;
if(typeParameterDescriptor.isReified()) {
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(var++, JetTypeMapper.TYPE_TYPEINFO));
}
}
Type[] argTypes = jvmSignature.getArgumentTypes();
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i);
int size = argTypes[i + (hasReceiver ? 1 : 0)].getSize();
var += size;
frameMap.enter(parameter, size);
}
frameMap.enterTemp();
int maskIndex = var;
var = 0;
@@ -313,7 +313,8 @@ public class FunctionCodegen {
}
if(hasReceiver) {
mv.visitVarInsn(ALOAD, var++); // todo - Long etc.
iv.load(var, receiverType);
var += receiverType.getSize();
}
int extra = hasReceiver ? 1 : 0;
@@ -269,7 +269,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
Method method;
Method constructorMethod;
CallableMethod callableMethod;
if (constructorDescriptor == null) {
List<Type> parameterTypes = new ArrayList<Type>();
@@ -282,17 +282,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
}
method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
constructorMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
callableMethod = new CallableMethod("", constructorMethod, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
}
else {
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
method = callableMethod.getSignature();
constructorMethod = callableMethod.getSignature();
}
ObjectOrClosureCodegen closure = context.closure;
if(closure != null) {
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(method.getArgumentTypes()));
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(constructorMethod.getArgumentTypes()));
int insert = 0;
if(closure.captureThis) {
@@ -319,11 +319,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
method = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
constructorMethod = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
}
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", method.getDescriptor(), null, null);
final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", constructorMethod.getDescriptor(), null, null);
if (!v.generateCode()) return;
mv.visitCode();
@@ -470,6 +470,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION );
}
private void generateTraitMethods(ExpressionCodegen codegen) {