5.4.2.10 Select Case Statement
Note
This section describes the implementation of MS-VBAL §5.4.2.10 Select Case Statement.
Syntax
| AST node | Instruction kind(s) | Notes |
|---|---|---|
| SelectCaseStatementNode | Select |
The Select Case opener. Its End is right past the block. |
| CaseExpressionStatementNode | ConditionalBranch |
A Case header. Its Matching names the offset of its Select opener. Its Else is the offset to go to on no match: the next header in the chain, the first instruction of the Case Else body, or right past the whole construct. |
| CaseElseClauseStatementNode | — | Case Else needs no condition. |
| — (synthesized) | Jump |
The trailing jump at the end of each branch's body. Node is null; Target is right past the whole construct. |
Each Case line's comma-separated conditions form their own node hierarchy under the abstract
CaseRangeClauseNode. The three condition forms
of MS-VBAL §5.4.2.10 are modelled independently, as three node types:
| Condition form | Example | AST node |
|---|---|---|
| Single value | Case 5 |
CaseValueRangeClauseNode |
| Comparison | Case Is > 5 |
CaseComparisonRangeClauseNode |
| Inclusive range | Case 1 To 10 |
CaseToRangeClauseNode |
See RD-VBAL §3.4.1 Block Statements and RD-VBAL §3.5.2 Instruction.
Runtime Semantics
Select
- Evaluate the header expression (the selector) once.
- Store the selector on the activation, keyed by the
Selectinstruction's own offset. - Fall through into the body, to the first
Caseheader.
MS-VBAL §5.4.2.10 says "the select-expression is immediately evaluated": the selector is evaluated once, ahead of every case-clause. RD-VBA passes the evaluated selector to every clause comparison, in accordance with this.
Case Header
The executor dispatches ConditionalBranch separately for a Case header: a Case header has
Instruction.Matching set instead of a Boolean
condition.
- Read the enclosing
Select's stored selector, through the header'sMatchingoffset. - If the selector is a
Variant, unwrap it. - If the selector is
Null, go directly to the header'sElseoffset without evaluating any range clause. EveryCaseheader does the same, so control reachesCase Else. - Otherwise, match the header's range clauses against the selector, as a comparison or logical expression.
- On a match, fall through into the branch's body. Otherwise, go to the header's
Elseoffset: the next header in the chain, the first instruction of theCase Elsebody, or right past the whole construct. - After the branch's body runs, the synthesized trailing
Jumpgoes right past the whole construct.
MS-VBAL §5.4.2.10: "If select-expression is the data value Null, only the case-else-clause is executed". A
Null can reach Select Case only through a Variant selector: a local declared Long can never hold Null.
Range Clause Matching
A Case header's range clauses are matched as a comparison or logical expression, the way
MS-VBAL §5.4.2.10 phrases its own runtime semantics:
| Range clause | Example | Matched as |
|---|---|---|
| Value | Case 5 |
selector = 5 |
| Comparison | Case Is > 5 |
selector > 5. The clause's own, already-normalized comparison-operator token selects the relational operator strategy directly. |
To |
Case 1 To 10 |
(selector >= 1) And (selector <= 10) |
Each comparison is evaluated through the same operator strategies every other expression uses
(BinaryRelationalOperatorRuntimeSemantics, BinaryAndLogicalOperatorRuntimeSemantics;
RD-VBAL §5.6.9.5 Relational Operators,
RD-VBAL §5.6.9.8 Logical Operators).
The already-evaluated selector is passed to each clause comparison as an operand value. It is not re-evaluated per clause.
Implementation
ProcedureExecutordispatchesSelect, and theConditionalBranchof aCaseheader.- The selector is stored through
CallStackFrame.SetBlockStateand read back through ICallStackFrame.TryGetBlockState, keyed by the opener's offset. A single block-state value is enough for the selector. There is no separate closer instruction to pop the stored state on exit (RD-VBAL §3.5.4 Execution). - A
Caseheader'sMatchingis the same field aForNextinstruction uses for its back-reference to its opener (RD-VBAL §5.4.2.3 For Statement). Select Caseneeds no synthesized closer: leaving the last branch, orCase Else, already reaches the offset that the construct's ownEnd/Elsechaining designates (RD-VBAL §3.5.3 Lowering Block Statements).ProcedureExecutor.ExecuteCaseHeader'sNull-selector short-circuit unwraps aVariantselector before testing it forNull.RDCore.Runtime.Execution.CaseMatchEvaluatormatches the range clauses against the selector. It calls the specific operator strategy directly rather than going throughOperatorRuntimeSemanticsProvider's token dispatch, because the range clause already determines the operator strategy.CaseMatchEvaluatorpasses the clause's own operand expression as the location-bearing node of each operator call, never a fabricated node standing in for the already-evaluated selector.- This relies on the node parameter of
OperatorRuntimeSemantics<TContext,TFlags>being typed ExpressionNode (RD-VBAL §5.6.9.2 Simple Data Operators).
⏮️ RD-VBAL §5.4.2.9 Single-line If Statement | ⏭️ RD-VBAL §5.4.2.11 Stop Statement