5.0 Semantics
The role of semantics is to encode the meaning of the language into a set of deterministic rules and specified sequences of operations.
There are two types of abstract semantics explicitly defined in RDCore.SDK:
The environment host may provide additional semantics through external providers (extensions); static semantics are effective in design-time and fully available to the semantic analysis layer.
Runtime semantics are partially available to the semantic analysis layer (for simulated execution pipelines), but generally unavailable in a static context.
5.0.1 Static Semantics
The role of static semantics is to determine a declared type for a given bound expression, given the determined static declared type of its inputs.
Static semantics always yield a StaticSemanticsEvaluationResult that represents either:
- a
Successresult encapsulating a VBType; - an
Errorresult encapsulating a VBCompileErrorInfo.
👉 In most error cases, the compile-time error metadata returned is for a TypeMismatch error.
Every rule is evaluated against a StaticEvaluationContext — the ISymbolResolver and the LexicalScope an expression is lexically found in (see §2.3.1.2 for how a scope is resolved). Module-level facts a rule needs — today, whether the enclosing module declares Option Explicit — are not parameters of this context; they live on ModuleDirectives, reachable from any scope via LexicalScope.EnclosingModuleDirectives(). This keeps the context's shape stable as the directive surface MS-VBAL and RD-VBA both define (Option Compare, Attribute declarations, …) grows over time.
5.0.1.1 Simple Name Expressions
Note
This section describes the implementation of MS-VBAL §5.6.10 Simple Name Expressions.
The declared type of a simple name expression is the declared type of the entity its identifier
resolves to, per the ordered lookup of §2.3.1.2: a Symbol that determines its own declared type
(ITypedSymbol, unifying bound and unbound
typed symbols) yields that type directly — a bare procedure reference yields its return type (or
VBVoidType for a Sub, already the type its own symbol carries).
Three outcomes fork on the resolver's result:
- Ambiguous (
Duplicate/Ambiguous, see §2.3.1.2) → anErrorcarrying AmbiguousName or DuplicateDeclaration. - Unresolved, under
Option Explicit→ anErrorcarrying VariableNotDefined. - Unresolved, otherwise →
Success(VBUnknownType). MS-VBA permits an implicitVariantdeclaration here; RD-VBA defers the actual guess to a later type-inference pass (IVBInferableType) rather than deciding it in this rule.
5.0.2 Runtime Semantics
The role of runtime semantics depends on the type of node being evaluated:
- Directives and literal or constant expressions evaluate to their static / compile-time value;
- Operators evaluate a VBTypedValue from their operands;
- Statements induce side-effects to program, global, or host environment state.
5.0.2.1 Operator Evaluation
Note
This section describes the implementation of MS-VBAL §5.6.9.2 Simple Data Operators.
The evaluation pipeline of all operators follows a clear sequence:
- The effective type of the operation is determined, based on the declared type of its operands;
- Validation: all non-null operands are let-coerced to the determined effective type of the operation;
- Evaluation: a templated method evaluates a result from the validated operands.
The sequence may be aborted at any point to return an error result that encapsulates VBRuntimeErrorInfo error metadata.
Computation in the effective type. The result of step 3 is computed in the effective type's own
representation — Long arithmetic in 64-bit integers, Currency/Decimal in decimal, Single in
float, and so on — never through a Double intermediate. Arithmetic runs in a checked context, so
an integral or fixed-point result that does not fit the effective type raises
Overflow rather than wrapping or silently
narrowing; an integral division or Mod by zero raises
DivisionByZero. The ^ operator is the sole
exception — its effective type is always Double, and it is evaluated as IEEE-754 exponentiation.
Relational operators compare in the effective type (integral comparisons in 64-bit integers,
fixed-point in decimal) and yield a VBBooleanValue;
a NaN operand raises Overflow. Logical
operators compute bitwise in the effective integral type (Boolean over its -1/0 representation).
5.0.2.2 Let-Coercion
Note
This section describes the implementation of MS-VBAL §5.5.1.2 Let-coercion (run-time semantics).
Let-coercion is the implicit conversion applied to an operand (or an assignment RHS) so that its
value fits a required destination declared type. It is driven by a let-coercion provider that
dispatches to a per-destination-type strategy resolved by walking the destination
VBType's base-type chain — one strategy keyed
on VBNumericType serves every concrete numeric type. The
provider maintains a coercion frame stack so that a recursive let-coercion (a strategy that must
coerce through an intermediate type, e.g. Date → Double → Integer) is detected and reported as
OutOfStackSpace rather than overflowing the
call stack. Each step yields a LetCoercionResult
that is Success (a coerced VBTypedValue),
Error (TypeMismatch or Overflow), or
NotApplicable.
Numeric let-coercion (MS-VBAL §5.5.1.2.1). Coercion between numeric types validates that the
source value is within the destination's representable range (Overflow otherwise), then:
- widening, and narrowing to a wider-or-equal integral type: the value is copied, converted to the destination's representation;
- narrowing a floating-point or fixed-point value to an integral type: the value is rounded to the nearest integer using round-half-to-even ("banker's rounding", MS-VBAL §5.5.1.2.1.1) before conversion.
Note
RD-VBAL diverges from MS-VBAL in the integral → floating-point block of §5.5.1.2.1: the MS document specifies it as a verbatim copy of the preceding (narrowing) block, including the finite-value and banker's-rounding checks — conditions no integer value can meet, for a conversion that is unambiguously widening. RD-VBAL treats it as a plain widening copy. Divergences of this kind (obvious copy/paste and transcription errors in the MS specification, and anything that implicitly depends on the Windows Registry, ActiveX, or MSForms — all out of scope for the run-time) are resolved in favour of the evident intent.
5.0.2.3 Statement Evaluation
Note
The specification of this section is currently a work in progress.
5.0.3 Semantic Analysis
The analysis pipeline of all operators follows a clear sequence:
- The effective type of the operation is determined, based on the declared type of its operands and invoking the same methods as runtime semantics;
- Validation: all non-null operands are let-coerced to the determined effective type of the operation, using the same runtime semantics let-coercion provider as the evaluation pipeline;
- Semantic evaluation: a templated method evaluates a semantic result, having the execution context and the validated operands to work with but without inducing any side-effects.
The Analyze method then yields a builder that builds a semantic context for this specific expression node that includes the results of each evaluation step:
- A DetermineOperatorEffectiveTypeResult encapsulating the result of the first step;
- A LetCoercionAnalysisContext encapsulating the aggregated evaluation stack and outcome of all let-coercion operations, with their respective semantic flags;
- A RuntimeSemanticsEvaluationResult encapsulating the result of the operation.
👉 The role of the
Analyzemethod at this level is simply to report the semantic facts of an operation, that usually cannot be inferred from the operands or effective type alone. These flags are pure facts, not opinions.
🧩 The role of analyzers in extensions like RDCore.Diagnostics is to inspect the flags and errors in these _semantic contexts, and issue diagnostics. While error diagnostics are reserved for coded syntax/compilation and runtime/application errors, a hint or suggestion diagnostic can be as opiniated as needed.
Note
Warning diagnostics should be used carefully, for flagging potential bugs or logical errors causing unexpected or unintended behavior, or perhaps severe performance issues. Always consider the possibility of there being a treat warnings as errors host environment configuration setting: if a diagnostic is not worth breaking a build over, then it's not a warning.
RDCore implements the MS-VBAL type-coercion rules through pattern-matching against its type system, verbatim except for the resolved specification errors noted in §5.0.2.2.
⏮️ RD-VBAL §4.0 Program Structure | ⏭️ RD-VBAL §6.0 Standard Library