Repository: apple/pkl
File: pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java (Java)

Code before:

    return GeneratorPredicateMemberNodeGen.create(keyNode, member);
  }

  @Override
  public GeneratorMemberNode visitObjectEntry(ObjectEntryContext ctx) {
    var keyNodeAndMember = doVisitObjectEntry(ctx);
    var keyNode = keyNodeAndMember.first;
    var member = keyNodeAndMember.second;
    insertWriteForGeneratorVarsToFrameSlotsNode(member.getMemberNode());

    return GeneratorEntryNodeGen.create(keyNode, member);
  }

  @Override
  public GeneratorMemberNode visitObjectSpread(ObjectSpreadContext ctx) {
    var scope = symbolTable.getCurrentScope();
    var visitingIterable = scope.isVisitingIterable();
    scope.setVisitingIterable(true);
    var expr = visitExpr(ctx.expr());
    scope.setVisitingIterable(visitingIterable);
    return GeneratorSpreadNodeGen.create(
        createSourceSection(ctx),
        expr,
        ctx.QSPREAD() != null,
        symbolTable.getCurrentScope().isVisitingIterable());
  }

  private void insertWriteForGeneratorVarsToFrameSlotsNode(@Nullable MemberNode memberNode) {
    if (memberNode == null) return; // member has constant value

    var descriptor = memberNode.getFrameDescriptor();
    var forGeneratorVars = symbolTable.getCurrentScope().getForGeneratorVariables();
    if (forGeneratorVars.isEmpty()) {
      return; // node is not within a for generator
    }
    var slots = new int[forGeneratorVars.size()];
    var i = 0;
    for (var variable : forGeneratorVars) {
      slots[i] = descriptor.findOrAddAuxiliarySlot(variable);
      i++;
    }
    memberNode.replaceBody((bodyNode) -> new WriteForVariablesNode(slots, bodyNode));
  }

  @Override
  public GeneratorElementNode visitObjectElement(ObjectElementContext ctx) {
    var member = doVisitObjectElement(ctx);
    insertWriteForGeneratorVarsToFrameSlotsNode(member.getMemberNode());
    return GeneratorElementNodeGen.create(member);
  }

Review comment (bug):
If this scope is not aligned with the above, something went wrong, no?
```suggestion
        visitingIterable);
```

Code after:
  public GeneratorMemberNode visitObjectEntry(ObjectEntryContext ctx) {
    var keyNodeAndMember = doVisitObjectEntry(ctx);
    var keyNode = keyNodeAndMember.first;
    var member = keyNodeAndMember.second;
    insertWriteForGeneratorVarsToFrameSlotsNode(member.getMemberNode());

    return GeneratorEntryNodeGen.create(keyNode, member);
  }

  @Override
  public GeneratorMemberNode visitObjectSpread(ObjectSpreadContext ctx) {
    var scope = symbolTable.getCurrentScope();
    var visitingIterable = scope.isVisitingIterable();
    scope.setVisitingIterable(true);
    var expr = visitExpr(ctx.expr());
    scope.setVisitingIterable(visitingIterable);
    return GeneratorSpreadNodeGen.create(createSourceSection(ctx), expr, ctx.QSPREAD() != null);
  }

  private void insertWriteForGeneratorVarsToFrameSlotsNode(@Nullable MemberNode memberNode) {
    if (memberNode == null) return; // member has constant value

    var descriptor = memberNode.getFrameDescriptor();
    var forGeneratorVars = symbolTable.getCurrentScope().getForGeneratorVariables();
    if (forGeneratorVars.isEmpty()) {
      return; // node is not within a for generator
    }
    var slots = new int[forGeneratorVars.size()];
    var i = 0;
    for (var variable : forGeneratorVars) {
      slots[i] = descriptor.findOrAddAuxiliarySlot(variable);
      i++;
    }
    memberNode.replaceBody((bodyNode) -> new WriteForVariablesNode(slots, bodyNode));
  }

  @Override
  public GeneratorElementNode visitObjectElement(ObjectElementContext ctx) {
    var member = doVisitObjectElement(ctx);
    insertWriteForGeneratorVarsToFrameSlotsNode(member.getMemberNode());
    return GeneratorElementNodeGen.create(member);
  }

  private GeneratorMemberNode[] doVisitForWhenBody(ObjectBodyContext ctx) {
    if (!ctx.ps.isEmpty()) {
      throw exceptionBuilder()
          .evalError("forWhenBodyCannotHaveParameters")
          .withSourceSection(createSourceSection(ctx.ps.get(0)))
          .build();
    }
    return doVisitGeneratorMemberNodes(ctx.objectMember());