5.4.2.3 For Statement
Note
This section describes the implementation of MS-VBAL §5.4.2.3 For Statement.
Syntax
| AST node | Instruction kind(s) | Notes |
|---|---|---|
| ForStatementNode | ForOpener |
The For opener. Its End is the offset right past the Next closer. |
| — (synthesized) | ForNext |
The Next closer; Node is null. Its Target is the body's first instruction; its Matching is the offset of its ForOpener. |
Next has no AST node of its own: the whole For...Next construct is one ForStatementNode with a Body
(RD-VBAL §3.4.1 Block Statements). The instruction fields are described in
RD-VBAL §3.5.2 Instruction.
Static Semantics
Reassigning a For loop counter inside the loop body is legal VBA.
Performance-related diagnostics should be issued when a
VBCollectionType is accessed by index within the body
of a For...Next loop (RD-VBAL §2.4.2 Non-intrinsic Types).
Runtime Semantics
A For loop needs per-activation state. Its opener stores a
ForLoopState on the activation, and its closer reads it back.
ForOpener
- Evaluate
start-value,end-valueandstep-incrementonce each, in that order. A missingstep-clausedefaults to the integer value1; that default is never itself evaluated as a source expression. - Let-assign the counter to
start-value, through the same Let-assignment machinery aLetstatement uses (RD-VBAL §5.4.3.8 Let Statement). - Store
endandstep, together with the counter symbol and the counter's own expression node, as aForLoopState, for every later step to reuse. - Check steps 1 and 2 of the MS-VBAL §5.4.2.3 algorithm immediately: "if step is zero or positive and the counter already exceeds end", and "if step is negative and the counter already falls short".
- When the counter is already out of range, branch to
Instruction
.End, right past the loop. Otherwise, fall through into the body.
ForNext
- Read the stored
ForLoopStateback viaInstruction.Matching. - Read the counter's current value. The body may have reassigned the counter directly.
- Add
stepto it through the addition operator (MS-VBAL §5.6.9.3 Arithmetic Operators; RD-VBAL §5.6.9.3 Arithmetic Operators). The addition is an overflow-checked operation, not an unchecked CLR addition. - Let-assign the sum back to the counter.
- Re-test the counter in the same way as
ForOpener: branch back to the body (Instruction.Target) while the counter is still in range, and fall through past the loop otherwise.
Range Test
The range checks of ForOpener and ForNext use the relational operators > and <
(MS-VBAL §5.6.9.5 Relational Operators;
RD-VBAL §5.6.9.5 Relational Operators), not a raw numeric
comparison. The counter's declared type (Currency, Decimal, Date as Double, …) has comparison semantics
specified by MS-VBAL, which a CLR > or < comparison does not implement.
Only the sign of step is read directly from its numeric value. The MS-VBAL §5.4.2.3 algorithm treats the
step's sign as a classification, not as a VBA-visible comparison expression.
| Step | Out of range when |
|---|---|
| Zero or positive | The counter exceeds end (counter > end). |
| Negative | The counter falls short of end (counter < end). |
Errors
A label is scoped to the whole procedure, so a GoTo can land directly on the Next closer
(RD-VBAL §5.4.1.1 Statement Labels). When ForNext finds no stored
state for its Matching offset, its ForOpener never ran in this activation.
| Condition | Run-time error |
|---|---|
ForNext finds no stored ForLoopState for its Matching offset (a GoTo landed directly on the closer). |
92 — For loop not initialized |
The addition of step to the counter overflows. |
6 — Overflow |
Run-time error 92 is VBRuntimeErrorId.ForLoopNotInitialized
(RD-VBAL §2.6.3 Runtime Errors).
Implementation
ProcedureExecutordispatchesForOpenerandForNext.- The
Nextcloser increments and tests the counter, so lowering synthesizes an instruction (Node = null) to hold that work (RD-VBAL §3.5.3 Lowering Block Statements). ForOpenerstoresend,step, the counter symbol and the counter's own expression node as aRDCore.SDK.Runtime.Shared.ForLoopState. The state is read back via ICallStackFrame.TryGetForLoopState, and written viaCallStackFrame.SetForLoopState.- A
Forloop's state holds more than a single value: counter symbol, counter expression, end and step. It therefore has its own SDK type,ForLoopState, rather than the single block-state value thatWithandSelect Caseuse (RD-VBAL §3.5.4 Execution). ForNextuses the sameInstruction.Matchingfield that aCaseheader uses for its back-reference to itsSelect(RD-VBAL §5.4.2.10 Select Case Statement).- The range test uses
RDCore.Runtime.Semantics.Operators.Relational.BinaryGtRelationalOperatorRuntimeSemanticsandBinaryLtRelationalOperatorRuntimeSemantics. The increment usesRDCore.Runtime.Semantics.Operators.Arithmetic.BinaryAdditionOperatorRuntimeSemantics. - Every location-bearing node passed to the loop's operator calls is a node the loop already has, never a synthesized
one: the counter's own expression or, for the first assignment, the loop's start expression.
The same rule applies to
Caseclause matching, which relies on the operator node parameter being typed ExpressionNode (RD-VBAL §5.4.2.10 Select Case Statement). - The verbose message of
ForLoopNotInitialized, when aNextcloser runs without its opener, is the resx entryVBForLoopNotInitialized_Verbose, provided in both languages.
⏮️ RD-VBAL §5.4.2.2 While Statement | ⏭️ RD-VBAL §5.4.2.4 For Each Statement