backend refactoring from extension properties and proper naming scheme of inner classes and objects

This commit is contained in:
Alex Tkachman
2011-11-13 21:08:35 +02:00
parent 1927eeef2c
commit 3904b91e4c
25 changed files with 453 additions and 370 deletions
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
@@ -22,7 +23,7 @@ public class CallableMethod implements Callable {
private final List<Type> valueParameterTypes;
private ClassDescriptor thisClass = null;
private FunctionDescriptor receiverFunction = null;
private CallableDescriptor receiverFunction = null;
private Type generateCalleeType = null;
public CallableMethod(String owner, Method signature, int invokeOpcode, List<Type> valueParameterTypes) {
@@ -48,7 +49,7 @@ public class CallableMethod implements Callable {
return valueParameterTypes;
}
public void setNeedsReceiver(@Nullable FunctionDescriptor receiverClass) {
public void setNeedsReceiver(@Nullable CallableDescriptor receiverClass) {
this.receiverFunction = receiverClass;
}
@@ -88,7 +89,7 @@ public class CallableMethod implements Callable {
return thisClass;
}
public FunctionDescriptor getReceiverFunction() {
public CallableDescriptor getReceiverFunction() {
return receiverFunction;
}
}
@@ -23,7 +23,7 @@ public class ClassCodegen {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state.getTypeMapper());
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
generate(contextForInners, (JetClass) declaration);
@@ -36,12 +36,12 @@ public class ClassCodegen {
private void generateImplementation(CodegenContext context, JetClassOrObject aClass, OwnerKind kind, HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
ClassBuilder v = state.forClassImplementation(descriptor);
CodegenContext classContext = context.intoClass(descriptor, kind);
CodegenContext classContext = context.intoClass(descriptor, kind, state.getTypeMapper());
new ImplementationBodyCodegen(aClass, classContext, v, state).generate(accessors);
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
v = state.forTraitImplementation(descriptor);
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(null);
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state.getTypeMapper()), v, state).generate(null);
}
}
}
@@ -29,8 +29,11 @@ import static org.objectweb.asm.Opcodes.*;
public class ClosureCodegen extends ObjectOrClosureCodegen {
private final BindingContext bindingContext;
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, CodegenContext context) {
super(exprContext, context, state);
bindingContext = state.getBindingContext();
}
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
@@ -63,7 +66,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
final Pair<String, ClassBuilder> nameAndVisitor = state.forAnonymousSubclass(fun);
final FunctionDescriptor funDescriptor = (FunctionDescriptor) state.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, fun);
final FunctionDescriptor funDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, fun);
cv = nameAndVisitor.getSecond();
name = nameAndVisitor.getFirst();
@@ -5,7 +5,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -49,7 +48,7 @@ public abstract class CodegenContext {
protected abstract ClassDescriptor getThisDescriptor ();
protected FunctionDescriptor getReceiverDescriptor() {
protected CallableDescriptor getReceiverDescriptor() {
return null;
}
@@ -80,8 +79,8 @@ public abstract class CodegenContext {
return new NamespaceContext(descriptor, this);
}
public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind) {
return new ClassContext(descriptor, kind, this);
public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
return new ClassContext(descriptor, kind, this, typeMapper);
}
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
@@ -124,7 +123,7 @@ public abstract class CodegenContext {
public Type jvmType(JetTypeMapper mapper) {
if (contextType instanceof ClassDescriptor) {
return mapper.jvmType((ClassDescriptor) contextType, contextKind);
return mapper.mapType(((ClassDescriptor) contextType).getDefaultType(), contextKind);
}
else if (closure != null) {
return Type.getObjectType(closure.name);
@@ -232,33 +231,23 @@ public abstract class CodegenContext {
return getThisDescriptor() != null ? StackValue.local(1, asmType) : StackValue.local(0, asmType);
}
public abstract static class FunctionContext extends CodegenContext {
final FunctionDescriptor receiverDescriptor;
public abstract static class ReceiverContext extends CodegenContext {
final CallableDescriptor receiverDescriptor;
public FunctionContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
public ReceiverContext(CallableDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
super(contextType, contextKind, parentContext, closureCodegen);
receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType : null;
}
@Override
protected FunctionDescriptor getReceiverDescriptor() {
protected CallableDescriptor getReceiverDescriptor() {
return receiverDescriptor;
}
public FunctionContext getOuterFunction() {
CodegenContext c = getParentContext();
while(c != null) {
if(c instanceof FunctionContext)
return (FunctionContext) c;
c = c.getParentContext();
}
return null;
}
}
public static class MethodContext extends FunctionContext {
public static class MethodContext extends ReceiverContext {
public MethodContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) {
super(contextType, contextKind, parentContext, null);
super(contextType instanceof PropertyAccessorDescriptor ? ((PropertyAccessorDescriptor)contextType).getCorrespondingProperty() : contextType, contextKind, parentContext, null);
}
@Override
@@ -295,12 +284,12 @@ public abstract class CodegenContext {
}
public static class ClassContext extends CodegenContext {
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) {
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) {
super(contextType, contextKind, parentContext, null);
final Type type = enclosingClassType();
outerExpression = type != null
? StackValue.field(type, DescriptorRenderer.getFQName(contextType).replace('.', '/'), "this$0", false)
? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false)
: null;
}
@@ -316,7 +305,7 @@ public abstract class CodegenContext {
final Type type = enclosingClassType();
outerExpression = type != null
? StackValue.field(type, closure.state.getTypeMapper().jvmName(contextType, OwnerKind.IMPLEMENTATION), "this$0", false)
? StackValue.field(type, closure.state.getTypeMapper().mapType(contextType.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "this$0", false)
: null;
}
@@ -326,7 +315,7 @@ public abstract class CodegenContext {
}
}
public static class ClosureContext extends FunctionContext {
public static class ClosureContext extends ReceiverContext {
private ClassDescriptor classDescriptor;
public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName) {
@@ -169,4 +169,5 @@ public class CodegenUtil {
addSuperTypes(jetType, set);
}
}
}
@@ -3,6 +3,7 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.objectweb.asm.Type;
@@ -25,6 +26,19 @@ public class ConstructorFrameMap extends FrameMap {
}
}
if (classDescriptor != null) {
List<TypeParameterDescriptor> parameters = classDescriptor.getTypeConstructor().getParameters();
for (TypeParameterDescriptor parameter : parameters) {
if(parameter.isReified()) {
int index = enterTemp();
myTypeParameterCount++;
if(myFirstTypeParameter == -1) {
myFirstTypeParameter = index;
}
}
}
}
List<Type> explicitArgTypes = callableMethod.getValueParameterTypes();
List<ValueParameterDescriptor> paramDescrs = descriptor != null
@@ -34,18 +48,6 @@ public class ConstructorFrameMap extends FrameMap {
ValueParameterDescriptor parameter = paramDescrs.get(i);
enter(parameter, explicitArgTypes.get(i).getSize());
}
if (classDescriptor != null) {
myTypeParameterCount = classDescriptor.getTypeConstructor().getParameters().size();
if (kind == OwnerKind.IMPLEMENTATION) {
if (myTypeParameterCount > 0) {
myFirstTypeParameter = enterTemp();
for (int i = 1; i < myTypeParameterCount; i++) {
enterTemp();
}
}
}
}
}
public int getOuterThisIndex() {
@@ -79,6 +79,22 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
this.intrinsics = state.getIntrinsics();
}
StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, ClassDescriptor required) {
if(required == null)
return inner;
if(provided instanceof CallableDescriptor)
provided = ((CallableDescriptor)provided).getReceiverParameter().getType().getConstructor().getDeclarationDescriptor();
assert provided instanceof ClassDescriptor;
if(!CodegenUtil.isInterface(provided) && CodegenUtil.isInterface(required)) {
v.checkcast(typeMapper.mapType(required.getDefaultType()));
}
return inner;
}
public GenerationState getState() {
return state;
}
@@ -265,7 +281,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final JetParameter loopParameter = expression.getLoopParameter();
final VariableDescriptor parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter);
JetType iteratorType = parameterDescriptor.getOutType();
JetType iteratorType = iteratorDescriptor.getReturnType();
Type asmIterType = JetTypeMapper.boxType(typeMapper.mapType(iteratorType));
JetType paramType = parameterDescriptor.getOutType();
@@ -802,8 +818,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (declaration instanceof JetObjectDeclarationName) {
JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(declaration, JetObjectDeclaration.class);
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, objectDeclaration);
return StackValue.field(typeMapper.jvmType(classDescriptor, OwnerKind.IMPLEMENTATION),
typeMapper.jvmName(classDescriptor, OwnerKind.IMPLEMENTATION),
return StackValue.field(typeMapper.mapType(classDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION),
typeMapper.mapType(classDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(),
"$instance",
true);
}
@@ -813,25 +829,59 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetExpression r = getReceiverForSelector(expression);
final boolean isSuper = r instanceof JetSuperExpression;
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null);
if (!isStatic) {
if (receiver == StackValue.none()) {
if(resolvedCall == null)
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
if(!directToField && resolvedCall != null && !isSuper) {
if (resolvedCall.getThisObject().exists()) {
if(resolvedCall.getReceiverArgument().exists()) {
generateFromResolvedCall(resolvedCall.getThisObject());
if(receiver == StackValue.none()) {
generateFromResolvedCall(resolvedCall.getReceiverArgument());
}
else {
receiver.put(typeMapper.mapType(resolvedCall.getReceiverArgument().getType()), v);
}
}
else {
if(resolvedCall.getThisObject() instanceof ExtensionReceiver)
receiver = generateReceiver((FunctionDescriptor) ((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor());
else
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
if (receiver == StackValue.none()) {
generateFromResolvedCall(resolvedCall.getThisObject());
}
else {
receiver.put(typeMapper.mapType(((ClassDescriptor)resolvedCall.getResultingDescriptor().getContainingDeclaration()).getDefaultType()), v);
}
}
}
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
receiver.put(receiverType != null && !isSuper? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
if(receiverType != null) {
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) {
// I hope it happens only in case of required super class for traits
assert propReceiverDescriptor != null;
v.checkcast(typeMapper.mapType(propReceiverDescriptor.getDefaultType()));
else {
if (resolvedCall.getReceiverArgument().exists()) {
if (receiver == StackValue.none()) {
generateFromResolvedCall(resolvedCall.getReceiverArgument());
}
else {
receiver.put(typeMapper.mapType(resolvedCall.getReceiverArgument().getType()), v);
}
}
}
pushTypeArguments(resolvedCall);
}
else {
if (!isStatic) {
if (receiver == StackValue.none()) {
if(resolvedCall == null)
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
else {
if(resolvedCall.getThisObject() instanceof ExtensionReceiver)
receiver = generateReceiver(((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor(), null);
else
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
}
}
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
receiver.put(receiverType != null && !isSuper? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
if(receiverType != null) {
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) {
// I hope it happens only in case of required super class for traits
assert propReceiverDescriptor != null;
v.checkcast(typeMapper.mapType(propReceiverDescriptor.getDefaultType()));
}
}
}
}
@@ -844,9 +894,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (classObject == null) {
throw new UnsupportedOperationException("trying to reference a class which doesn't have a class object");
}
final String type = typeMapper.jvmName(classObject);
final ClassDescriptor descriptor1 = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
final String type = typeMapper.mapType(descriptor1.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
return StackValue.field(Type.getObjectType(type),
typeMapper.jvmName((ClassDescriptor) descriptor, OwnerKind.IMPLEMENTATION),
typeMapper.mapType(((ClassDescriptor) descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(),
"$classobj",
true);
}
@@ -1102,10 +1153,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
assert resolvedCall != null;
FunctionDescriptor callableDescriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
boolean hasThis = resolvedCall.getThisObject().exists();
boolean hasReceiver = resolvedCall.getReceiverArgument().exists();
if (callableMethod.isNeedsThis()) {
if(callableMethod.isNeedsReceiver()) {
generateFromResolvedCall(resolvedCall.getThisObject());
@@ -1113,7 +1160,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
generateFromResolvedCall(resolvedCall.getReceiverArgument());
}
else {
receiver.put(typeMapper.mapType(callableMethod.getReceiverFunction().getReceiverParameter().getType()), v);
receiver.put(typeMapper.mapType(resolvedCall.getReceiverArgument().getType()), v);
}
}
else {
@@ -1135,8 +1182,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
pushTypeArguments(resolvedCall);
int mask = pushMethodArguments(expression, callableMethod.getValueParameterTypes());
pushTypeArguments(expression);
if(mask == 0)
callableMethod.invoke(v);
else
@@ -1150,7 +1197,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else if(descriptor instanceof ExtensionReceiver) {
ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor;
generateReceiver((FunctionDescriptor) extensionReceiver.getDeclarationDescriptor()).put(typeMapper.mapType(descriptor.getType()), v);
generateReceiver(extensionReceiver.getDeclarationDescriptor(), null).put(typeMapper.mapType(descriptor.getType()), v);
}
else if(descriptor instanceof ExpressionReceiver) {
ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor;
@@ -1169,14 +1216,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return null;
}
private StackValue generateReceiver(FunctionDescriptor descriptor) {
assert context instanceof CodegenContext.FunctionContext;
CodegenContext.FunctionContext cur = (CodegenContext.FunctionContext) context;
if (cur.getReceiverDescriptor() == descriptor) {
return cur.getReceiverExpression(typeMapper);
private StackValue generateReceiver(DeclarationDescriptor provided, ClassDescriptor required) {
assert context instanceof CodegenContext.ReceiverContext;
CodegenContext.ReceiverContext cur = (CodegenContext.ReceiverContext) context;
if (cur.getReceiverDescriptor() == provided) {
StackValue result = cur.getReceiverExpression(typeMapper);
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, required);
}
return context.lookupInContext(descriptor, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT));
StackValue result = context.lookupInContext(provided, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT));
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, required);
}
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
@@ -1190,7 +1239,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (CodegenUtil.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) {
Type type = typeMapper.mapType(calleeContainingClass.getDefaultType());
result.put(JetTypeMapper.TYPE_OBJECT, v);
return StackValue.onStack(type);
return castToRequiredTypeOfInterfaceIfNeeded(StackValue.onStack(type), cur.getThisDescriptor(), calleeContainingClass);
}
result = cur.getOuterExpression(result);
@@ -1213,64 +1262,66 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return false;
}
private int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
List<? extends ValueArgument> args = expression.getValueArguments();
if(resolvedCall != null) {
Map<ValueParameterDescriptor,ResolvedValueArgument> valueArguments = resolvedCall.getValueArguments();
CallableDescriptor fd = resolvedCall.getResultingDescriptor();
private int pushMethodArguments(ResolvedCall resolvedCall, List<Type> valueParameterTypes) {
Map<ValueParameterDescriptor,ResolvedValueArgument> valueArguments = resolvedCall.getValueArguments();
CallableDescriptor fd = resolvedCall.getResultingDescriptor();
int index = 0;
int mask = 0;
for (ValueParameterDescriptor valueParameterDescriptor : fd.getValueParameters()) {
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameterDescriptor);
if(resolvedValueArgument instanceof ExpressionValueArgument) {
ExpressionValueArgument valueArgument = (ExpressionValueArgument) resolvedValueArgument;
gen(valueArgument.getExpression(), valueParameterTypes.get(index));
int index = 0;
int mask = 0;
for (ValueParameterDescriptor valueParameterDescriptor : fd.getValueParameters()) {
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameterDescriptor);
if(resolvedValueArgument instanceof ExpressionValueArgument) {
ExpressionValueArgument valueArgument = (ExpressionValueArgument) resolvedValueArgument;
gen(valueArgument.getExpression(), valueParameterTypes.get(index));
}
else if(resolvedValueArgument instanceof DefaultValueArgument) {
Type type = valueParameterTypes.get(index);
if(type.getSort() == Type.OBJECT||type.getSort() == Type.ARRAY)
v.aconst(null);
else if(type.getSort() == Type.FLOAT) {
v.aconst(0f);
}
else if(resolvedValueArgument instanceof DefaultValueArgument) {
Type type = valueParameterTypes.get(index);
if(type.getSort() == Type.OBJECT||type.getSort() == Type.ARRAY)
v.aconst(null);
else if(type.getSort() == Type.FLOAT) {
v.aconst(0f);
}
else if(type.getSort() == Type.DOUBLE) {
v.aconst(0d);
}
else {
v.iconst(0);
}
mask |= (1 << index);
}
else if(resolvedValueArgument instanceof VarargValueArgument) {
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
JetType outType = valueParameterDescriptor.getOutType();
Type type = typeMapper.mapType(outType);
assert type.getSort() == Type.ARRAY;
Type elementType = type.getElementType();
int size = valueArgument.getArgumentExpressions().size();
v.iconst(valueArgument.getArgumentExpressions().size());
v.newarray(elementType);
for(int i = 0; i != size; ++i) {
v.dup();
v.iconst(i);
gen(valueArgument.getArgumentExpressions().get(i), elementType);
StackValue.arrayElement(elementType, false).store(v);
}
// throw new UnsupportedOperationException("Varargs are not supported yet");
else if(type.getSort() == Type.DOUBLE) {
v.aconst(0d);
}
else {
throw new UnsupportedOperationException();
v.iconst(0);
}
index++;
mask |= (1 << index);
}
return mask;
else if(resolvedValueArgument instanceof VarargValueArgument) {
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
JetType outType = valueParameterDescriptor.getOutType();
Type type = typeMapper.mapType(outType);
assert type.getSort() == Type.ARRAY;
Type elementType = type.getElementType();
int size = valueArgument.getArgumentExpressions().size();
v.iconst(valueArgument.getArgumentExpressions().size());
v.newarray(elementType);
for(int i = 0; i != size; ++i) {
v.dup();
v.iconst(i);
gen(valueArgument.getArgumentExpressions().get(i), elementType);
StackValue.arrayElement(elementType, false).store(v);
}
}
else {
throw new UnsupportedOperationException();
}
index++;
}
return mask;
}
private int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
if(resolvedCall != null) {
return pushMethodArguments(resolvedCall, valueParameterTypes);
}
else {
List<? extends ValueArgument> args = expression.getValueArguments();
for (int i = 0, argsSize = args.size(); i < argsSize; i++) {
ValueArgument arg = args.get(i);
gen(arg.getArgumentExpression(), valueParameterTypes.get(i));
@@ -1898,7 +1949,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else {
// this$0 need to be put on stack
v.dup();
v.load(0, typeMapper.jetImplementationType(classDecl));
v.load(0, typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION));
}
}
else {
@@ -1916,9 +1967,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return StackValue.onStack(type);
}
private void pushTypeArguments(JetCallElement expression) {
JetExpression calleeExpression = expression.getCalleeExpression();
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, calleeExpression);
private void pushTypeArguments(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
if(resolvedCall != null) {
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor();
@@ -2100,7 +2149,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else {
if(descriptor instanceof FunctionDescriptor) {
return generateReceiver((FunctionDescriptor) descriptor);
return generateReceiver(descriptor, null);
}
throw new UnsupportedOperationException();
}
@@ -4,6 +4,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
@@ -52,7 +53,7 @@ public class FunctionCodegen {
FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
{
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
List<TypeParameterDescriptor> typeParameters = (functionDescriptor instanceof PropertyAccessorDescriptor ? ((PropertyAccessorDescriptor)functionDescriptor).getCorrespondingProperty(): functionDescriptor).getTypeParameters();
int flags = ACC_PUBLIC; // TODO.
@@ -83,16 +84,18 @@ public class FunctionCodegen {
Type[] argTypes = jvmSignature.getArgumentTypes();
int add = functionDescriptor.getReceiverParameter().exists() ? state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize() : 0;
for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i);
frameMap.enter(parameter, argTypes[i+add].getSize());
}
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
int slot = frameMap.enterTemp();
add++;
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
}
for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i);
frameMap.enter(parameter, argTypes[i+add].getSize());
}
if (kind instanceof OwnerKind.DelegateKind) {
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -150,7 +153,7 @@ public class FunctionCodegen {
}
static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
DeclarationDescriptor contextClass = ((FunctionDescriptor)owner.getContextDescriptor()).getContainingDeclaration();
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
if(kind != OwnerKind.TRAIT_IMPL) {
// we don't generate defaults for traits but do for traitImpl
@@ -184,8 +187,8 @@ public class FunctionCodegen {
int flags = ACC_PUBLIC; // TODO.
String ownerInternalName = contextClass instanceof NamespaceDescriptor ?
JetTypeMapper.jvmName((NamespaceDescriptor) contextClass) :
state.getTypeMapper().jvmName((ClassDescriptor) contextClass, OwnerKind.IMPLEMENTATION);
NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(contextClass)) :
state.getTypeMapper().mapType(((ClassDescriptor) contextClass).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
String descriptor = jvmSignature.getDescriptor().replace(")","I)");
if(!isStatic)
@@ -210,6 +213,13 @@ public class FunctionCodegen {
var++;
}
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
int slot = frameMap.enterTemp();
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
var++;
}
Type[] argTypes = jvmSignature.getArgumentTypes();
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
for (int i = 0; i < paramDescrs.size(); i++) {
@@ -219,13 +229,6 @@ public class FunctionCodegen {
frameMap.enter(parameter, size);
}
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
int slot = frameMap.enterTemp();
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
var++;
}
frameMap.enterTemp();
int maskIndex = var;
@@ -236,14 +239,22 @@ public class FunctionCodegen {
}
if(hasReceiver) {
mv.visitVarInsn(ALOAD, var++);
mv.visitVarInsn(ALOAD, var++); // todo - Long etc.
}
int extra = hasReceiver ? 1 : 0;
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
if(typeParameterDescriptor.isReified()) {
iv.load(var++, JetTypeMapper.TYPE_OBJECT);
extra++;
}
}
Type[] argumentTypes = jvmSignature.getArgumentTypes();
for (int index = 0; index < paramDescrs.size(); index++) {
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index);
Type t = argumentTypes[(hasReceiver ? 1 : 0) + index];
Type t = argumentTypes[extra + index];
Label endArg = null;
if (parameterDescriptor.hasDefaultValue()) {
iv.load(maskIndex, Type.INT_TYPE);
@@ -270,11 +281,6 @@ public class FunctionCodegen {
}
}
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
if(typeParameterDescriptor.isReified())
iv.load(var++, JetTypeMapper.TYPE_OBJECT);
}
if(!isStatic) {
if(kind == OwnerKind.TRAIT_IMPL) {
iv.invokeinterface(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor());
@@ -318,7 +324,7 @@ public class FunctionCodegen {
reg += argType.getSize();
}
iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), jvmSignature.getName(), jvmSignature.getDescriptor());
iv.invokevirtual(state.getTypeMapper().mapType(((ClassDescriptor) owner.getContextDescriptor()).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), jvmSignature.getName(), jvmSignature.getDescriptor());
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
StackValue.valueOf(iv, jvmSignature.getReturnType());
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
@@ -64,11 +64,11 @@ public class GenerationState {
}
public ClassBuilder forClassImplementation(ClassDescriptor aClass) {
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.IMPLEMENTATION) + ".class");
return factory.newVisitor(typeMapper.mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName() + ".class");
}
public ClassBuilder forTraitImplementation(ClassDescriptor aClass) {
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.TRAIT_IMPL) + ".class");
return factory.newVisitor(typeMapper.mapType(aClass.getDefaultType(), OwnerKind.TRAIT_IMPL).getInternalName() + ".class");
}
public Pair<String, ClassBuilder> forAnonymousSubclass(JetExpression expression) {
@@ -28,9 +28,13 @@ import java.util.*;
public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JetDelegationSpecifier superCall;
private String superClass = "java/lang/Object";
private final JetTypeMapper typeMapper;
private final BindingContext bindingContext;
public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
super(aClass, context, v, state);
typeMapper = state.getTypeMapper();
bindingContext = state.getBindingContext();
}
private Set<String> getSuperInterfaces(JetClassOrObject aClass) {
@@ -39,10 +43,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Set<String> superInterfaces = new LinkedHashSet<String>();
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
PsiElement superPsi = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
PsiElement superPsi = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (superPsi instanceof PsiClass) {
PsiClass psiClass = (PsiClass) superPsi;
@@ -71,7 +75,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
else {
if(superPsi == null || ((JetClass)superPsi).isTrait())
superInterfaces.add(state.getTypeMapper().jvmNameForImplementation(superClassDescriptor, OwnerKind.IMPLEMENTATION));
superInterfaces.add(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName());
}
}
return superInterfaces;
@@ -108,18 +112,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.visitSource(myClass.getContainingFile().getName(), null);
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
v.visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
v.visitOuterClass(typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
}
if(myClass instanceof JetClass) {
AnnotationVisitor annotationVisitor = v.newAnnotation(myClass, "Ljet/typeinfo/JetSignature;", true);
annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, state.getBindingContext(), state.getTypeMapper()));
annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, bindingContext, typeMapper));
annotationVisitor.visitEnd();
}
}
private String jvmName() {
return state.getTypeMapper().jvmName(descriptor, kind);
return typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName();
}
protected void getSuperClass() {
@@ -130,21 +134,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
final PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (declaration != null) {
if (declaration instanceof PsiClass) {
if (!((PsiClass) declaration).isInterface()) {
superClass = state.getTypeMapper().jvmName(superClassDescriptor, kind);
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
superCall = specifier;
return;
}
}
else if(declaration instanceof JetClass) {
if(!((JetClass) declaration).isTrait()) {
superClass = state.getTypeMapper().jvmName(superClassDescriptor, kind);
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
superCall = specifier;
}
}
@@ -176,8 +180,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
Method method = state.getTypeMapper().mapSignature(bridge.getName(), bridge);
Method originalMethod = state.getTypeMapper().mapSignature(original.getName(), original);
Method method = typeMapper.mapSignature(bridge.getName(), bridge);
Method originalMethod = typeMapper.mapSignature(original.getName(), original);
Type[] argTypes = method.getArgumentTypes();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
@@ -193,7 +197,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
}
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
mv.visitMaxs(0,0);
@@ -204,8 +208,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
Method method = state.getTypeMapper().mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION);
Method originalMethod = state.getTypeMapper().mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION);
Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
InstructionAdapter iv = null;
if (v.generateCode()) {
@@ -214,15 +218,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
mv.visitMaxs(0,0);
mv.visitEnd();
}
method = state.getTypeMapper().mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION);
originalMethod = state.getTypeMapper().mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION);
originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
if (v.generateCode()) {
mv.visitCode();
@@ -237,7 +241,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
}
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
mv.visitMaxs(0,0);
@@ -253,7 +257,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateFieldForObjectInstance() {
if (isNonLiteralObject()) {
Type type = state.getTypeMapper().jetImplementationType(descriptor);
Type type = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION);
v.newField(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
staticInitializerChunks.add(new CodeChunk() {
@@ -263,7 +267,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.anew(Type.getObjectType(name));
v.dup();
v.invokespecial(name, "<init>", "()V");
v.putstatic(name, "$instance", state.getTypeMapper().jetImplementationType(descriptor).getDescriptor());
v.putstatic(name, "$instance", typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getDescriptor());
}
});
@@ -273,18 +277,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateFieldForClassObject() {
final JetClassObject classObject = getClassObject();
if (classObject != null) {
Type type = Type.getObjectType(state.getTypeMapper().jvmName(classObject));
final ClassDescriptor descriptor1 = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
Type type = Type.getObjectType(typeMapper.mapType(descriptor1.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName());
v.newField(classObject, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$classobj", type.getDescriptor(), null, null);
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
String name = state.getTypeMapper().jvmName(classObject);
final ClassDescriptor descriptor1 = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
String name = typeMapper.mapType(descriptor1.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
final Type classObjectType = Type.getObjectType(name);
v.anew(classObjectType);
v.dup();
v.invokespecial(name, "<init>", "()V");
v.putstatic(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$classobj",
v.putstatic(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$classobj",
classObjectType.getDescriptor());
}
});
@@ -295,7 +301,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
return;
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass);
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
@@ -304,7 +310,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (constructorDescriptor == null) {
List<Type> parameterTypes = new ArrayList<Type>();
if (CodegenUtil.hasThis0(descriptor)) {
parameterTypes.add(state.getTypeMapper().jvmType(CodegenUtil.getOuterClassDescriptor(descriptor), OwnerKind.IMPLEMENTATION));
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
@@ -316,7 +322,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
}
else {
callableMethod = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
method = callableMethod.getSignature();
}
@@ -329,7 +335,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure;
for (DeclarationDescriptor descriptor : closure.keySet()) {
final Type sharedVarType = context.closure.exprContext.getSharedVarType(descriptor);
consArgTypes.add(sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()));
consArgTypes.add(sharedVarType != null ? sharedVarType : typeMapper.mapType(((VariableDescriptor) descriptor).getOutType()));
}
method = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
@@ -357,13 +363,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
}
String classname = state.getTypeMapper().jvmName(descriptor, kind);
String classname = typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName();
final Type classType = Type.getType("L" + classname + ";");
HashSet<FunctionDescriptor> overridden = new HashSet<FunctionDescriptor>();
for (JetDeclaration declaration : myClass.getDeclarations()) {
if (declaration instanceof JetFunction) {
FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, declaration);
FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, declaration);
assert functionDescriptor != null;
overridden.addAll(functionDescriptor.getOverriddenDescriptors());
}
@@ -375,25 +381,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.invokespecial(superClass, "<init>", "()V");
}
else {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, superCall.getTypeReference());
JetType superType = bindingContext.get(BindingContext.TYPE, superCall.getTypeReference());
List<Type> parameterTypes = new ArrayList<Type>();
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (CodegenUtil.hasThis0(superClassDescriptor)) {
iv.load(1, JetTypeMapper.TYPE_OBJECT);
parameterTypes.add(state.getTypeMapper().jvmType(CodegenUtil.getOuterClassDescriptor(descriptor), OwnerKind.IMPLEMENTATION));
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
for(TypeProjection typeParameterDescriptor : superType.getArguments()) {
codegen.generateTypeInfo(typeParameterDescriptor.getType());
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
}
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
iv.invokespecial(state.getTypeMapper().jvmName(superClassDescriptor, OwnerKind.IMPLEMENTATION), "<init>", superCallMethod.getDescriptor());
iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "<init>", superCallMethod.getDescriptor());
}
}
else {
iv.load(0, classType);
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap);
}
@@ -406,26 +412,26 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(0, classType);
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
String delegateField = "$delegate_" + n;
Type fieldType = state.getTypeMapper().jetImplementationType(superClassDescriptor);
Type fieldType = typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION);
String fieldDesc = fieldType.getDescriptor();
v.newField(specifier, Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
iv.putfield(classname, delegateField, fieldDesc);
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
JetClass superClass = (JetClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
final CodegenContext delegateContext = context.intoClass(superClassDescriptor,
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
state.getTypeMapper().jvmNameForImplementation(superClassDescriptor, OwnerKind.IMPLEMENTATION)));
typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName()), state.getTypeMapper());
generateDelegates(superClass, delegateContext, overridden);
}
}
final ClassDescriptor outerDescriptor = getOuterClassDescriptor();
if (outerDescriptor != null && outerDescriptor.getKind() != ClassKind.OBJECT) {
final Type type = state.getTypeMapper().jetImplementationType(outerDescriptor);
final Type type = typeMapper.mapType(outerDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION);
String interfaceDesc = type.getDescriptor();
final String fieldName = "this$0";
v.newField(myClass, Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
@@ -444,11 +450,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (DeclarationDescriptor varDescr : closure.keySet()) {
Type sharedVarType = context.closure.exprContext.getSharedVarType(varDescr);
if(sharedVarType == null) {
sharedVarType = state.getTypeMapper().mapType(((VariableDescriptor) varDescr).getOutType());
sharedVarType = typeMapper.mapType(((VariableDescriptor) varDescr).getOutType());
}
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(firstClosureIndex + k, StackValue.refType(sharedVarType));
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$" + (k+1), sharedVarType.getDescriptor());
iv.putfield(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$" + (k+1), sharedVarType.getDescriptor());
}
}
@@ -457,7 +463,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (JetParameter parameter : constructorParameters) {
if (parameter.getValOrVarNode() != null) {
VariableDescriptor descriptor = paramDescrs.get(curParam);
Type type = state.getTypeMapper().mapType(descriptor.getOutType());
Type type = typeMapper.mapType(descriptor.getOutType());
iv.load(0, classType);
iv.load(frameMap.getIndex(descriptor), type);
iv.putfield(classname, descriptor.getName(), type.getDescriptor());
@@ -484,14 +490,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration();
if(containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor declaration = (ClassDescriptor) containingDeclaration;
PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaration);
PsiElement psiElement = bindingContext.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 functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal());
Method function = typeMapper.mapSignature(fun.getName(), fun);
Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal());
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
if (v.generateCode()) {
@@ -509,15 +515,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
reg += argType.getSize();
}
JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, state.getBindingContext());
Type type = state.getTypeMapper().mapType(jetType);
JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, bindingContext);
Type type = typeMapper.mapType(jetType);
if(type.getInternalName().equals("java/lang/Object")) {
jetType = declaration.getDefaultType();
type = state.getTypeMapper().mapType(jetType);
type = typeMapper.mapType(jetType);
}
String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor());
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
iv.invokestatic(typeMapper.mapType(((ClassDescriptor) fun.getContainingDeclaration()).getDefaultType(), OwnerKind.TRAIT_IMPL).getInternalName(), function.getName(), fdescriptor);
if(function.getReturnType().getSort() == Type.OBJECT) {
iv.checkcast(function.getReturnType());
}
@@ -548,15 +554,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ConstructorFrameMap frameMap) {
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
Type type;
type = state.getTypeMapper().jetImplementationType(classDecl);
type = typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION);
iv.load(0, type);
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
iv.load(frameMap.getOuterThisIndex(), state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION));
iv.load(frameMap.getOuterThisIndex(), typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
codegen.invokeMethodWithArguments(method, constructorCall, StackValue.none());
}
@@ -570,7 +576,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) {
String name = declaration.getName();
final String desc = "L" + state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION) + ";";
final String desc = "L" + typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName() + ";";
v.newField(declaration, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, name, desc, null, null);
if (myEnumConstants.isEmpty()) {
staticInitializerChunks.add(new CodeChunk() {
@@ -593,7 +599,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
for (JetEnumEntry enumConstant : myEnumConstants) {
// TODO type and constructor parameters
String implClass = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
String implClass = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
final List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
if (delegationSpecifiers.size() > 1) {
@@ -607,8 +613,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
if (specifier instanceof JetDelegatorToSuperCall) {
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
codegen.invokeMethodWithArguments(method, superCall, StackValue.none());
}
else {
@@ -623,11 +629,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void generateSecondaryConstructor(JetSecondaryConstructor constructor) {
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, constructor);
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, constructor);
if (constructorDescriptor == null) {
throw new UnsupportedOperationException("failed to get descriptor for secondary constructor");
}
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getDescriptor(), null, null);
if (v.generateCode()) {
@@ -641,7 +647,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
if (initializer instanceof JetDelegatorToThisCall) {
JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer;
DeclarationDescriptor thisDescriptor = state.getBindingContext().get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference());
DeclarationDescriptor thisDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference());
if (!(thisDescriptor instanceof ConstructorDescriptor)) {
throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor");
}
@@ -666,7 +672,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.IMPLEMENTATION));
iv.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION));
iv.iconst(0);
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
@@ -700,21 +706,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
}
iv.invokevirtual(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
iv.invokevirtual(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
}
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
for (JetDeclaration declaration : myClass.getDeclarations()) {
if (declaration instanceof JetProperty) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, declaration);
if (bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null) {
CompileTimeConstant<?> compileTimeValue = state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer);
CompileTimeConstant<?> compileTimeValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, initializer);
if(compileTimeValue != null) {
assert compileTimeValue != null;
Object value = compileTimeValue.getValue();
Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
Type type = typeMapper.mapType(propertyDescriptor.getOutType());
if(JetTypeMapper.isPrimitive(type)) {
if( !propertyDescriptor.getOutType().isNullable() && value instanceof Number) {
if(type == Type.INT_TYPE && ((Number)value).intValue() == 0)
@@ -765,7 +771,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
propertyCodegen.gen((JetProperty) declaration);
}
else if (declaration instanceof JetNamedFunction) {
if (!overriden.contains(state.getBindingContext().get(BindingContext.FUNCTION, declaration))) {
if (!overriden.contains(bindingContext.get(BindingContext.FUNCTION, declaration))) {
functionCodegen.gen((JetNamedFunction) declaration);
}
}
@@ -773,7 +779,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (JetParameter p : toClass.getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) {
@@ -808,7 +814,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
InstructionAdapter iv = null;
if (v.generateCode()) {
iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
iv.areturn(JetTypeMapper.TYPE_TYPEINFO);
@@ -820,7 +826,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (v.generateCode()) {
mv.visitCode();
iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(1, JetTypeMapper.TYPE_OBJECT);
iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
@@ -841,7 +847,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (v.generateCode()) {
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
mv.visitMaxs(0, 0);
@@ -854,18 +860,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
JetTypeMapper typeMapper = state.getTypeMapper();
v.aconst(typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
v.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION));
v.iconst(0);
ClassDescriptor outerClassDescriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
if(outerClassDescriptor == null) {
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
}
else {
v.getstatic(state.getTypeMapper().jvmName(outerClassDescriptor, OwnerKind.IMPLEMENTATION), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
v.getstatic(typeMapper.mapType(outerClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
}
v.putstatic(typeMapper.jvmName(descriptor, kind), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
v.putstatic(typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
}
});
}
@@ -1,6 +1,5 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import jet.JetObject;
import jet.typeinfo.TypeInfo;
@@ -9,6 +8,8 @@ import org.jetbrains.annotations.NotNull;
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.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JavaNamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
@@ -120,73 +121,11 @@ public class JetTypeMapper {
return type;
}
public String jvmName(ClassDescriptor jetClass, OwnerKind kind) {
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetClass);
if (declaration instanceof JetObjectDeclaration && ((JetObjectDeclaration) declaration).isObjectLiteral()) {
final PsiElement parent = declaration.getParent();
if (parent instanceof JetClassObject) {
JetClass containingClass = PsiTreeUtil.getParentOfType(parent, JetClass.class);
final ClassDescriptor containingClassDescriptor = bindingContext.get(BindingContext.CLASS, containingClass);
return jvmName(containingClassDescriptor, OwnerKind.IMPLEMENTATION) + "$$ClassObj";
}
@SuppressWarnings("SuspiciousMethodCalls") String className = classNamesForAnonymousClasses.get(declaration);
if (className == null) {
throw new UnsupportedOperationException("Unexpected forward reference to anonymous class " + declaration);
}
return className;
}
return jetJvmName(jetClass, kind);
}
public String jvmName(JetClassObject classObject) {
final ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
return jvmName(descriptor, OwnerKind.IMPLEMENTATION);
}
private String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
if (jetClass.getKind() == ClassKind.OBJECT) {
return jvmNameForImplementation(jetClass, OwnerKind.IMPLEMENTATION);
}
else if (kind == OwnerKind.IMPLEMENTATION) {
return jvmNameForImplementation(jetClass, OwnerKind.IMPLEMENTATION);
}
else if (kind == OwnerKind.TRAIT_IMPL) {
return jvmNameForImplementation(jetClass, OwnerKind.IMPLEMENTATION) + "$$TImpl";
}
else {
assert false : "Unsuitable kind";
return "java/lang/Object";
}
}
public Type jvmType(ClassDescriptor jetClass, OwnerKind kind) {
if (jetClass == standardLibrary.getString()) {
return Type.getType(String.class);
}
return Type.getType("L" + jvmName(jetClass, kind) + ";");
}
Type jetImplementationType(ClassDescriptor classDescriptor) {
return Type.getType("L" + jvmNameForImplementation(classDescriptor, OwnerKind.IMPLEMENTATION) + ";");
}
public static String jvmName(JetNamespace namespace) {
return NamespaceCodegen.getJVMClassName(CodegenUtil.getFQName(namespace));
}
static String jvmName(NamespaceDescriptor namespace) {
return NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(namespace));
}
public String jvmNameForImplementation(ClassDescriptor descriptor, OwnerKind kind) {
return mapType(descriptor.getDefaultType(), kind).getInternalName();
}
public String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) {
String owner;
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration instanceof NamespaceDescriptor) {
owner = jvmName((NamespaceDescriptor) containingDeclaration);
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName((NamespaceDescriptor) containingDeclaration));
}
else if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
@@ -198,7 +137,7 @@ public class JetTypeMapper {
kind = OwnerKind.IMPLEMENTATION;
}
}
owner = jvmName(classDescriptor, kind);
owner = mapType(classDescriptor.getDefaultType(), kind).getInternalName();
}
else {
throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration);
@@ -216,6 +155,43 @@ public class JetTypeMapper {
return mapType(jetType, OwnerKind.IMPLEMENTATION);
}
private HashMap<DeclarationDescriptor,Map<DeclarationDescriptor,String>> naming = new HashMap<DeclarationDescriptor, Map<DeclarationDescriptor, String>>();
public String getFQName(DeclarationDescriptor descriptor) {
descriptor = descriptor.getOriginal();
DeclarationDescriptor container = descriptor.getContainingDeclaration();
String name = descriptor.getName();
if(JetPsiUtil.NO_NAME_PROVIDED.equals(name)) {
// create and store name
Map<DeclarationDescriptor, String> map = naming.get(container);
if(map == null) {
map = new HashMap<DeclarationDescriptor, String>();
naming.put(container, map);
}
name = map.get(descriptor);
if(name == null) {
name = getFQName(container) + "$" + (map.size()+1);
map.put(descriptor, name);
}
return name;
}
if (container != null) {
if (container instanceof ModuleDescriptor) {
return name;
}
if(container instanceof JavaNamespaceDescriptor && JavaDescriptorResolver.JAVA_ROOT.equals(container.getName())) {
return name;
}
String baseName = getFQName(container);
if (!baseName.isEmpty()) {
return baseName + (container instanceof JavaNamespaceDescriptor || container instanceof NamespaceDescriptor ? "/" : "$") + name;
}
}
return name;
}
@NotNull public Type mapType(final JetType jetType) {
return mapType(jetType, OwnerKind.IMPLEMENTATION);
}
@@ -236,14 +212,13 @@ public class JetTypeMapper {
else
return ARRAY_GENERIC_TYPE;
}
if (JetStandardClasses.getAny().equals(descriptor)) {
return Type.getType(Object.class);
return TYPE_OBJECT;
}
if (descriptor instanceof ClassDescriptor) {
String name = DescriptorRenderer.getFQName(descriptor).replace('.', '/');
if(name.startsWith("<java_root>"))
name = name.substring("<java_root>".length()+1);
String name = getFQName(descriptor);
return Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : ""));
}
@@ -327,14 +302,15 @@ public class JetTypeMapper {
else if (functionDescriptor instanceof ConstructorDescriptor) {
assert !superCall;
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
owner = mapType(containingClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
invokeOpcode = INVOKESPECIAL;
thisClass = null;
}
else if (functionParent instanceof ClassDescriptor) {
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
boolean isInterface = CodegenUtil.isInterface(containingClass);
owner = jvmName(containingClass, isInterface && superCall ? OwnerKind.TRAIT_IMPL : OwnerKind.IMPLEMENTATION);
OwnerKind kind1 = isInterface && superCall ? OwnerKind.TRAIT_IMPL : OwnerKind.IMPLEMENTATION;
owner = mapType(containingClass.getDefaultType(), kind1).getInternalName();
invokeOpcode = isInterface
? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE)
: (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL);
@@ -375,16 +351,16 @@ public class JetTypeMapper {
valueParameterTypes.add(type);
parameterTypes.add(type);
}
for (ValueParameterDescriptor parameter : parameters) {
Type type = mapType(parameter.getOutType());
valueParameterTypes.add(type);
parameterTypes.add(type);
}
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
if(parameterDescriptor.isReified()) {
parameterTypes.add(TYPE_TYPEINFO);
}
}
for (ValueParameterDescriptor parameter : parameters) {
Type type = mapType(parameter.getOutType());
valueParameterTypes.add(type);
parameterTypes.add(type);
}
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType());
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
}
@@ -435,29 +411,53 @@ public class JetTypeMapper {
public Method mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
Type returnType = mapType(descriptor.getOutType());
if(kind != OwnerKind.TRAIT_IMPL)
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
else {
String name = PropertyCodegen.getterName(descriptor.getName());
ArrayList<Type> params = new ArrayList<Type>();
if(kind == OwnerKind.TRAIT_IMPL) {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
assert containingDeclaration != null;
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[] { mapType(containingDeclaration.getDefaultType()) });
params.add(mapType(containingDeclaration.getDefaultType()));
}
if(descriptor.getReceiverParameter().exists()) {
params.add(mapType(descriptor.getReceiverParameter().getType()));
}
for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
params.add(TYPE_TYPEINFO);
}
}
return new Method(name, returnType, params.toArray(new Type[params.size()]));
}
public Method mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
final JetType inType = descriptor.getInType();
if (inType == null) {
JetType inType = descriptor.getInType();
if(inType == null)
return null;
}
Type paramType = mapType(inType);
if(kind != OwnerKind.TRAIT_IMPL) {
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { paramType });
}
else {
String name = PropertyCodegen.setterName(descriptor.getName());
ArrayList<Type> params = new ArrayList<Type>();
if(kind == OwnerKind.TRAIT_IMPL) {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
assert containingDeclaration != null;
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { mapType(containingDeclaration.getDefaultType()), paramType });
params.add(mapType(containingDeclaration.getDefaultType()));
}
if(descriptor.getReceiverParameter().exists()) {
params.add(mapType(descriptor.getReceiverParameter().getType()));
}
for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
params.add(TYPE_TYPEINFO);
}
}
params.add(mapType(inType));
return new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()]));
}
private Method mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
@@ -465,29 +465,28 @@ public class JetTypeMapper {
List<Type> parameterTypes = new ArrayList<Type>();
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
if (CodegenUtil.hasThis0(classDescriptor)) {
parameterTypes.add(jvmType(CodegenUtil.getOuterClassDescriptor(classDescriptor), OwnerKind.IMPLEMENTATION));
parameterTypes.add(mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
for (TypeParameterDescriptor typeParameter : typeParameters) {
if(typeParameter.isReified())
parameterTypes.add(TYPE_TYPEINFO);
}
for (ValueParameterDescriptor parameter : parameters) {
final Type type = mapType(parameter.getOutType());
parameterTypes.add(type);
valueParameterTypes.add(type);
}
PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
if(!(psiElement instanceof PsiClass)) {
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
for (int n = typeParameters.size(); n > 0; n--) {
parameterTypes.add(TYPE_TYPEINFO);
}
}
return new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
}
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
List<Type> valueParameterTypes = new ArrayList<Type>();
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
String owner = jvmName(descriptor.getContainingDeclaration(), kind);
String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName();
return new CallableMethod(owner, method, INVOKESPECIAL, valueParameterTypes);
}
@@ -506,6 +505,15 @@ public class JetTypeMapper {
}
String classNameForAnonymousClass(JetExpression expression) {
if(expression instanceof JetObjectLiteralExpression) {
JetObjectLiteralExpression jetObjectLiteralExpression = (JetObjectLiteralExpression) expression;
expression = jetObjectLiteralExpression.getObjectDeclaration();
}
if(expression instanceof JetObjectDeclaration) {
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression);
return getFQName(declarationDescriptor);
}
String name = classNamesForAnonymousClasses.get(expression);
if (name != null) {
return name;
@@ -519,7 +527,7 @@ public class JetTypeMapper {
}
else {
ClassDescriptor aClass = bindingContext.get(BindingContext.CLASS, container);
baseName = jvmNameForImplementation(aClass, OwnerKind.IMPLEMENTATION);
baseName = mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
}
Integer count = anonymousSubclassesCount.get(baseName);
@@ -536,7 +544,7 @@ public class JetTypeMapper {
Set<String> result = new HashSet<String>();
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass);
if (classDescriptor != null) {
result.add(jvmName(classDescriptor, OwnerKind.IMPLEMENTATION));
result.add(mapType(classDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName());
}
return result;
}
@@ -93,6 +93,10 @@ public class NamespaceCodegen {
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
assert descriptor != null;
if(descriptor.getReceiverParameter().exists()) {
continue;
}
codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
}
@@ -1,11 +1,9 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -63,9 +61,9 @@ public class ObjectOrClosureCodegen {
FunctionDescriptor fd = (FunctionDescriptor) d;
// we generate method
assert context instanceof CodegenContext.FunctionContext;
assert context instanceof CodegenContext.ReceiverContext;
CodegenContext.FunctionContext fcontext = (CodegenContext.FunctionContext) context;
CodegenContext.ReceiverContext fcontext = (CodegenContext.ReceiverContext) context;
if(fcontext.getReceiverDescriptor() != fd)
return null;
@@ -196,7 +196,11 @@ public abstract class StackValue {
v.checkcast(type);
}
else if (type.getSort() == Type.OBJECT) {
box(this.type, type, v);
if(this.type.getSort() == Type.OBJECT && !type.equals(JetTypeMapper.TYPE_OBJECT)) {
v.checkcast(type);
}
else
box(this.type, type, v);
}
else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
if (this.type.equals(JetTypeMapper.TYPE_OBJECT)) {
@@ -56,6 +56,6 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
}
private String jvmName() {
return state.getTypeMapper().jvmName(descriptor, OwnerKind.TRAIT_IMPL);
return state.getTypeMapper().mapType(descriptor.getDefaultType(), OwnerKind.TRAIT_IMPL).getInternalName();
}
}
@@ -34,6 +34,7 @@ public class IntrinsicMethods {
private static final List<String> PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double");
public static final IntrinsicMethod ARRAY_SIZE = new ArraySize();
public static final IntrinsicMethod ARRAY_INDICES = new ArrayIndices();
public static final Equals EQUALS = new Equals();
private final Project myProject;
private final JetStandardLibrary myStdLib;
@@ -77,7 +78,8 @@ public class IntrinsicMethods {
declareIntrinsicFunction("String", "plus", 1, new Concat());
declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString());
declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, new Equals());
declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
// declareIntrinsicFunction("Any", "equals", 1, new Equals());
+2
View File
@@ -34,6 +34,8 @@ namespace io {
fun readLine() : String?
}
fun Any?.identityEquals(other : Any?) // = this === other
// Can't write a body due to a bootstrapping problem (see JET-74)
fun Any?.equals(other : Any?) : Boolean// = this === other
@@ -13,6 +13,9 @@ import java.util.Set;
* @author abreslav
*/
public class JetPsiUtil {
public static final String NO_NAME_PROVIDED = "<no name provided>";
@Nullable
public static JetExpression deparenthesize(@NotNull JetExpression expression) {
if (expression instanceof JetBinaryExpressionWithTypeRHS) {
@@ -38,7 +41,7 @@ public class JetPsiUtil {
@NotNull
public static String safeName(String name) {
return name == null ? "<no name provided>" : name;
return name == null ? NO_NAME_PROVIDED : name;
}
@NotNull
@@ -1,7 +1,6 @@
namespace x
class Outer() {
class object {
class Inner() {
}
+14 -14
View File
@@ -176,21 +176,21 @@ fun t12(x: Int) : Int {
fun box(): String {
/*
if (!s0()) return "fail"
if (!s1()) return "fail"
if (!t1()) return "fail"
if (!t2()) return "fail"
if (!t3()) return "fail"
if (!t4()) return "fail"
if (!t5()) return "fail"
if (!t6()) return "fail"
if (!t7()) return "fail"
if (!t8()) return "fail"
if (!t9(0)) return "fail"
if (!t10()) return "fail"
if (t11(1) != 104) return "fail"
if (!s0()) return "s0 fail"
if (!s1()) return "s1 fail"
if (!t1()) return "t1 fail"
if (!t2()) return "t2 fail"
if (!t3()) return "t3 fail"
if (!t4()) return "t4 fail"
if (!t5()) return "t5 fail"
if (!t6()) return "t6 fail"
if (!t7()) return "t7 fail"
if (!t8()) return "t8 fail"
if (!t9(0)) return "t9 fail"
if (!t10()) return "t10 fail"
if (t11(1) != 104) return "t11 fail"
*/
if (t12(0) != 100) return "fail"
if (t12(0) != 100) return "t12 fail"
return "OK"
}
@@ -1,14 +1,18 @@
import java.math.BigDecimal
import java.util.ArrayList
fun box() : String {
// Easy to make BigDecimals user-friendly
System.out?.println(
"2.00".bd - "1.00"
)
return "OK"
val array = ArrayList<String>()
array.add("0")
array.add("1")
array.add("2")
array.last = "5"
return if(array.length == 3 && array.last == "5") "OK" else "fail"
}
val String.bd = BigDecimal(this)
var <T> ArrayList<T>.length : Int
get() = size()
set(value: Int) = throw java.lang.Error()
fun BigDecimal.minus(other : BigDecimal) = this.subtract(other)
fun BigDecimal.minus(other : String) = subtract(other.bd) // this can be omitted
var <T> ArrayList<T>.last : T
get() = get(size()-1)
set(el : T) { set(size()-1, el) }
@@ -1,4 +1,5 @@
import java.util.ArrayList
trait Tr {
fun extra() : String = "_"
}
@@ -34,6 +34,6 @@ public class ExtensionFunctionsTest extends CodegenTestCase {
}
public void testKt475() throws Exception {
// blackBoxFile("regressions/kt475.jet");
blackBoxFile("regressions/kt475.jet");
}
}
@@ -501,7 +501,7 @@ public class NamespaceGenTest extends CodegenTestCase {
loadText("fun <E,D> E.foo(extra: java.util.List<D>) = (1, \"foo\", this, extra)");
System.out.println(generateToText());
final Method main = generateFunction();
Tuple4 tuple4 = (Tuple4) main.invoke(null, "aaa", Arrays.asList(10), TypeInfo.STRING_TYPE_INFO, TypeInfo.INT_TYPE_INFO);
Tuple4 tuple4 = (Tuple4) main.invoke(null, "aaa", TypeInfo.STRING_TYPE_INFO, TypeInfo.INT_TYPE_INFO, Arrays.asList(10));
assertEquals(1, tuple4._1);
assertEquals("foo", tuple4._2);
assertEquals("aaa", tuple4._3);
@@ -17,8 +17,10 @@ import com.sun.jdi.ReferenceType;
import com.sun.jdi.request.ClassPrepareRequest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.NamespaceCodegen;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
@@ -111,10 +113,10 @@ public class JetPositionManager implements PositionManager {
else {
JetNamespace namespace = PsiTreeUtil.getParentOfType(sourcePosition.getElementAt(), JetNamespace.class);
if (namespace != null) {
names.add(JetTypeMapper.jvmName(namespace));
names.add(NamespaceCodegen.getJVMClassName(CodegenUtil.getFQName(namespace)));
}
else {
names.add(JetTypeMapper.jvmName(file.getRootNamespace()));
names.add(NamespaceCodegen.getJVMClassName(CodegenUtil.getFQName(file.getRootNamespace())));
}
}
return names;