diff --git a/.idea/modules.xml b/.idea/modules.xml index 335a959bed2..8958a9581db 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -6,6 +6,7 @@ + diff --git a/idea/idea.iml b/idea/idea.iml index fcc6e7e360a..d01e54ca4d0 100644 --- a/idea/idea.iml +++ b/idea/idea.iml @@ -10,6 +10,7 @@ + diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java index c62c45cd104..a7e4872dff8 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -5,10 +5,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.types.ClassDescriptor; -import org.jetbrains.jet.lang.types.JetStandardLibrary; -import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.PropertyDescriptor; +import org.jetbrains.jet.lang.types.*; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -27,11 +24,15 @@ public class ClassCodegen { private final Project project; private final BindingContext bindingContext; private final Codegens factory; + private final JetTypeMapper typeMapper; public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) { this.project = project; this.factory = factory; this.bindingContext = bindingContext; + + final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); + typeMapper = new JetTypeMapper(standardLibrary, bindingContext); } public void generate(JetClass aClass) { @@ -68,7 +69,7 @@ public class ClassCodegen { ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ? factory.forClassImplementation(descriptor) : factory.forClassDelegatingImplementation(descriptor); v.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, - JetTypeMapper.jvmNameForImplementation(descriptor), + JetTypeMapper.jvmName(descriptor, kind), null, superClass, new String[] {JetTypeMapper.jvmNameForInterface(descriptor)} @@ -158,31 +159,133 @@ public class ClassCodegen { } private void generatePrimaryConstructor(JetClass aClass, ClassVisitor v, OwnerKind kind) { + ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor(aClass); + if (constructorDescriptor == null) return; + + ClassDescriptor classDescriptor = bindingContext.getClassDescriptor(aClass); + + Method method = typeMapper.mapConstructorSignature(constructorDescriptor, kind); int flags = Opcodes.ACC_PUBLIC; // TODO - Method method = new Method("", Type.VOID_TYPE, new Type[0]); final MethodVisitor mv = v.visitMethod(flags, "", method.getDescriptor(), null, null); mv.visitCode(); + Type[] argTypes = method.getArgumentTypes(); + List paramDescrs = constructorDescriptor.getUnsubstitutedValueParameters(); + FrameMap frameMap = new FrameMap(); frameMap.enterTemp(); // this final InstructionAdapter iv = new InstructionAdapter(mv); - String superClass = getSuperClass(aClass, kind); - iv.load(0, Type.getType("L" + superClass + ";")); - iv.invokespecial(superClass, "", method.getDescriptor()); + ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, classDescriptor, kind); - final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); - final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext); - ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, - typeMapper, Type.VOID_TYPE); - generateInitializers(aClass, kind, codegen, iv, typeMapper); + String classname = JetTypeMapper.jvmName(classDescriptor, kind); + final Type classType = Type.getType("L" + classname + ";"); + + if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) { + String interfaceDesc = JetTypeMapper.jetInterfaceType(classDescriptor).getDescriptor(); + v.visitField(Opcodes.ACC_PRIVATE, "$this", interfaceDesc, /*TODO*/null, null); + iv.load(1, argTypes[0]); + iv.putfield(classname, "$this", interfaceDesc); + frameMap.enterTemp(); + } + + for (int i = 0; i < paramDescrs.size(); i++) { + ValueParameterDescriptor parameter = paramDescrs.get(i); + frameMap.enter(parameter, argTypes[i].getSize()); + } + + List specifiers = aClass.getDelegationSpecifiers(); + + if (specifiers.isEmpty() || !(specifiers.get(0) instanceof JetDelegatorToSuperCall)) { + String superClass = getSuperClass(aClass, kind); + iv.load(0, Type.getType("L" + superClass + ";")); + iv.invokespecial(superClass, "", /* TODO super constructor descriptor */"()V"); + } + + int n = 0; + for (JetDelegationSpecifier specifier : specifiers) { + boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 || + specifier instanceof JetDelegatorByExpressionSpecifier ; + + if (delegateOnStack) { + iv.load(0, classType); + } + + if (specifier instanceof JetDelegatorToSuperCall) { + JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier; + ConstructorDescriptor constructorDescriptor1 = bindingContext.resolveSuperConstructor(superCall, this); + + ClassDescriptor classDecl = constructorDescriptor1.getContainingDeclaration(); + boolean isDelegating = kind == OwnerKind.DELEGATING_IMPLEMENTATION; + Type type = isDelegating ? JetTypeMapper.jetDelegatingImplementationType(classDecl) : JetTypeMapper.jetImplementationType(classDecl); + + if (n > 0) { + if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) { + codegen.thisToStack(); + } + } + + if (n == 0) { + iv.load(0, type); + } + else { + iv.anew(type); + iv.dup(); + } + + Method method1 = typeMapper.mapConstructorSignature(constructorDescriptor1, kind); + final Type[] argTypes1 = method1.getArgumentTypes(); + List args = superCall.getValueArguments(); + for (int i = 0, argsSize = args.size(); i < argsSize; i++) { + JetArgument arg = args.get(i); + codegen.gen(arg.getArgumentExpression(), argTypes1[i]); + } + + iv.invokespecial(type.getClassName(), "", method1.getDescriptor()); + } + else if (specifier instanceof JetDelegatorByExpressionSpecifier) { + codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression()); + } + + if (delegateOnStack) { + JetType superType = bindingContext.resolveTypeReference(specifier.getTypeReference()); + ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); + String delegateField = "$delegate_" + n; + Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor); + String fieldDesc = fieldType.getDescriptor(); + v.visitField(Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null); + iv.putfield(classname, delegateField, fieldDesc); + + JetClass superClass = (JetClass) bindingContext.getDeclarationPsiElement(superClassDescriptor); + generateDelegates(aClass, superClass, v, + new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false), + JetTypeMapper.jvmNameForInterface(superClassDescriptor))); + } + + n++; + } + + generateInitializers(aClass, kind, codegen, iv); + + int curParam = 0; + List constructorParameters = aClass.getPrimaryConstructorParameters(); + for (JetParameter parameter : constructorParameters) { + if (parameter.getValOrVarNode() != null) { + VariableDescriptor descriptor = paramDescrs.get(curParam); + Type type = typeMapper.mapType(descriptor.getOutType()); + iv.load(0, classType); + iv.load(frameMap.getIndex(descriptor), type); + iv.putfield(classname, descriptor.getName(), type.getDescriptor()); + } + curParam++; + } iv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } - private void generateInitializers(JetClass aClass, OwnerKind kind, ExpressionCodegen codegen, InstructionAdapter iv, JetTypeMapper typeMapper) { + private void generateInitializers(JetClass aClass, OwnerKind kind, ExpressionCodegen codegen, InstructionAdapter iv) { for (JetDeclaration declaration : aClass.getDeclarations()) { if (declaration instanceof JetProperty) { final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration); @@ -201,7 +304,7 @@ public class ClassCodegen { private void generateClassBody(JetClass aClass, ClassVisitor v, OwnerKind kind) { final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); - final FunctionCodegen functionCodegen = new FunctionCodegen(v, standardLibrary, bindingContext); + final FunctionCodegen functionCodegen = new FunctionCodegen(aClass, v, standardLibrary, bindingContext); final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen); for (JetDeclaration declaration : aClass.getDeclarations()) { @@ -212,5 +315,56 @@ public class ClassCodegen { functionCodegen.gen((JetFunction) declaration, kind); } } + + for (JetParameter p : aClass.getPrimaryConstructorParameters()) { + if (p.getValOrVarNode() != null) { + VariableDescriptor descriptor = bindingContext.getParameterDescriptor(p); + if (descriptor instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; + propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + if (propertyDescriptor.isVar()) { + propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + } + + if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && bindingContext.hasBackingField(propertyDescriptor)) { + v.visitField(Opcodes.ACC_PRIVATE, p.getName(), typeMapper.mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null); + } + } + } + } + } + + private void generateDelegates(JetClass inClass, JetClass toClass, ClassVisitor v, OwnerKind kind) { + final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); + final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, standardLibrary, bindingContext); + final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen); + +/* TODO + for (JetDeclaration declaration : toClass.getDeclarations()) { + if (declaration instanceof JetProperty) { + propertyCodegen.gen((JetProperty) declaration, kind); + } + else if (declaration instanceof JetFunction) { + functionCodegen.gen((JetFunction) declaration, kind); + } + } +*/ + + for (JetParameter p : toClass.getPrimaryConstructorParameters()) { + if (p.getValOrVarNode() != null) { + VariableDescriptor descriptor = bindingContext.getParameterDescriptor(p); + if (descriptor instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; + propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + if (propertyDescriptor.isVar()) { + propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); + } + + if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && bindingContext.hasBackingField(propertyDescriptor)) { + v.visitField(Opcodes.ACC_PRIVATE, p.getName(), typeMapper.mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null); + } + } + } + } } } diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 93e0df63f92..ea00ced7f68 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1,7 +1,11 @@ package org.jetbrains.jet.codegen; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.search.ProjectScope; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import jet.IntRange; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -15,6 +19,7 @@ import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.Method; +import java.util.Iterator; import java.util.List; import java.util.Stack; @@ -26,6 +31,18 @@ public class ExpressionCodegen extends JetVisitor { private static final String CLASS_STRING = "java/lang/String"; private static final String CLASS_STRING_BUILDER = "java/lang/StringBuilder"; private static final String CLASS_COMPARABLE = "java/lang/Comparable"; + private static final String CLASS_ITERABLE = "java/lang/Iterable"; + private static final String CLASS_ITERATOR = "java/util/Iterator"; + + private static final String CLASS_INT_RANGE = "jet/IntRange"; + + private static final String ITERABLE_ITERATOR_DESCRIPTOR = "()Ljava/util/Iterator;"; + private static final String ITERATOR_HASNEXT_DESCRIPTOR = "()Z"; + private static final String ITERATOR_NEXT_DESCRIPTOR = "()Ljava/lang/Object;"; + private static final String INT_RANGE_CONSTRUCTOR_DESCRIPTOR = "(II)V"; + + private static final Type ITERATOR_TYPE = Type.getType(Iterator.class); + private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class); private final Stack