예제 #1
0
  private ClassDescriptor recordClassForFunction(FunctionDescriptor funDescriptor) {
    ClassDescriptor classDescriptor;
    int arity = funDescriptor.getValueParameters().size();

    classDescriptor =
        new ClassDescriptorImpl(
            funDescriptor.getContainingDeclaration(),
            Collections.<AnnotationDescriptor>emptyList(),
            Modality.FINAL,
            Name.special("<closure>"));
    ((ClassDescriptorImpl) classDescriptor)
        .initialize(
            false,
            Collections.<TypeParameterDescriptor>emptyList(),
            Collections.singleton(
                (funDescriptor.getReceiverParameter().exists()
                        ? JetStandardClasses.getReceiverFunction(arity)
                        : JetStandardClasses.getFunction(arity))
                    .getDefaultType()),
            JetScope.EMPTY,
            Collections.<ConstructorDescriptor>emptySet(),
            null);

    assert PsiCodegenPredictor.checkPredictedClassNameForFun(
        bindingContext, funDescriptor, classDescriptor);
    bindingTrace.record(CLASS_FOR_FUNCTION, funDescriptor, classDescriptor);
    return classDescriptor;
  }
예제 #2
0
      @Override
      public StackValue innerValue(
          DeclarationDescriptor d,
          LocalLookup localLookup,
          GenerationState state,
          MutableClosure closure,
          Type classType) {
        FunctionDescriptor vd = (FunctionDescriptor) d;

        boolean idx = localLookup != null && localLookup.lookupLocal(vd);
        if (!idx) return null;

        BindingContext bindingContext = state.getBindingContext();
        Type localType = asmTypeForAnonymousClass(bindingContext, vd);

        MutableClosure localFunClosure =
            bindingContext.get(CLOSURE, bindingContext.get(CLASS_FOR_FUNCTION, vd));
        if (localFunClosure != null && JvmCodegenUtil.isConst(localFunClosure)) {
          // This is an optimization: we can obtain an instance of a const closure simply by
          // GETSTATIC ...$instance
          // (instead of passing this instance to the constructor and storing as a field)
          return StackValue.field(localType, localType, JvmAbi.INSTANCE_FIELD, true);
        }

        String fieldName = "$" + vd.getName();
        StackValue innerValue = StackValue.field(localType, classType, fieldName, false);

        closure.recordField(fieldName, localType);
        closure.captureVariable(new EnclosedValueDescriptor(fieldName, d, innerValue, localType));

        return innerValue;
      }
예제 #3
0
  @Override
  public void visitNamedFunction(JetNamedFunction function) {
    FunctionDescriptor functionDescriptor =
        (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, function);
    // working around a problem with shallow analysis
    if (functionDescriptor == null) return;
    DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
    if (containingDeclaration instanceof ClassDescriptor) {
      nameStack.push(peekFromStack(nameStack) + '$' + function.getName());
      super.visitNamedFunction(function);
      nameStack.pop();
    } else if (containingDeclaration instanceof NamespaceDescriptor) {
      String peek = peekFromStack(nameStack);
      if (peek.isEmpty()) {
        peek = JvmAbi.PACKAGE_CLASS;
      } else {
        peek += "/" + JvmAbi.PACKAGE_CLASS;
      }
      nameStack.push(peek + '$' + function.getName());
      super.visitNamedFunction(function);
      nameStack.pop();
    } else {
      String name = inventAnonymousClassName(function);
      ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor);
      recordClosure(
          bindingTrace,
          function,
          classDescriptor,
          peekFromStack(classStack),
          JvmClassName.byInternalName(name),
          true);

      classStack.push(classDescriptor);
      nameStack.push(name);
      super.visitNamedFunction(function);
      nameStack.pop();
      classStack.pop();
    }
  }