visitFor method

  1. @override
dynamic visitFor(
  1. ForStatement node
)

Implementation

@override
visitFor(ForStatement node) {
  final String? loopLabel = _nextStatementLabel;
  _nextStatementLabel = null;
  final List<String> loopLetNames = node.init is VariableDeclaration &&
          (node.init as VariableDeclaration).kind == 'let'
      ? (node.init as VariableDeclaration)
          .declarations
          .expand((declaration) => _bindingNames(declaration.name))
          .map((name) => name.value)
          .toList()
      : <String>[];
  if (node.init != null) {
    node.init!.visitBy(this);
  }
  while (node.condition == null ||
      toBoolean(getValueFromNode(node.condition!))) {
    _LexicalContext? iterationContext;
    if (loopLetNames.isNotEmpty) {
      iterationContext = _snapshotLoopBindings(loopLetNames);
      _lexicalContexts.add(iterationContext);
    }
    try {
      node.body.visitBy(this);
    } on ControlFlowBreakException catch (e) {
      if (iterationContext != null) {
        _copyLoopBindings(iterationContext, loopLetNames);
        _lexicalContexts.removeLast();
      }
      if (e.label == loopLabel) break;
      if (e.label != null) rethrow;
      break;
    } on ControlFlowContinueException catch (e) {
      if (e.label == loopLabel) {
        // continue to update
      } else if (e.label != null) {
        rethrow;
      }
      //skip as we are executing the update anyway
    } finally {
      if (iterationContext != null &&
          identical(_lexicalContexts.last, iterationContext)) {
        _copyLoopBindings(iterationContext, loopLetNames);
        _lexicalContexts.removeLast();
      }
    }
    // Execute the update expression after each loop iteration
    // see https://github.com/EnsembleUI/ensemble/issues/1704
    if (node.update != null) {
      node.update!.visitBy(this);
    }
  }
}