2.3.1.2 Session Services
An execution session's services are rooted at an IRuntimeSession.
IRuntimeSession
IRuntimeSession exposes:
| Exposes | Description |
|---|---|
Environment.Is64Bit |
The environment bitness, on the session's IRuntimeEnvironmentProfile. It also sets the default value of the #If Win64 pre-compiler constant. #If VBA7 does not depend on it: the environment host defaults VBA7 to true in either bitness. A .rdproj #Const or a --define argument overrides these defaults. |
References |
The workspace's project and library references (References, below). |
| The three session services | ISessionMemoryAllocator, ISessionSymbols and ISessionObjects (Services, below). |
Services
| Service | Responsibility | Members |
|---|---|---|
| ISessionMemoryAllocator | Allocates and frees blocks in the session's memory space, and reports allocation / fragmentation statistics. | TryAllocate, TryDeallocate, Info |
| ISessionSymbols | The session's symbol table. | TryDefine defines a Symbol in a scope. TryResolveValue resolves a name visible from a scope; TryResolveType is its type binding context counterpart. Resolver is the session's symbol resolver. |
| ISessionObjects | Object lifetime. | CreateObject; AddRef / RemoveRef (reference counting); TryRemoveObject removes an instance whose reference count has reached zero. |
ISessionMemoryAllocator is an accounting layer: it tracks sizes and addresses, in the manner of MSVBVM. It does
not hold the values themselves.
ISessionSymbols mirrors the ISymbolResolver.ResolveValue / ResolveType pair as TryResolveValue and
TryResolveType. ISessionSymbols.Resolver is a ScopeTreeSymbolResolver over the session's own symbols, rebuilt
as symbols are defined. See RD-VBAL §2.3.1.3 Name Resolution.
For object values and their lifetime, see RD-VBAL §2.5.2.1.4 Object Values.
References
IRuntimeSession.References is the workspace's project and library references, as an ordered
IReadOnlyList<ReferencePriorityInfo>. It is the runtime-facing view of the .rdproj RDCoreReference list
(RD-VBAL §2.2.3.2 RDCoreReference).
Each ReferencePriorityInfo entry carries only:
| Member | Description |
|---|---|
Name |
The reference's source-visible name. |
Priority |
The reference's rank in the IRuntimeSession.References list. |
The list is the reference priority order defined for global-scope name resolution (RD-VBAL §2.3.1.3 Name Resolution). It keeps the order in which the language server provides the references.
A referenced library's own members are not taken from this list: they are contributed by an
ISymbolProvider (see below)
and resolved through ISymbolResolver.
Name resolution across referenced projects and libraries shall consult the ordering to disambiguate a global-scope name. The name-resolution algorithm itself is a separate concern from the list (RD-VBAL §2.3.1.3 Name Resolution).
Note
Not implemented. Reference-priority ordering within the global scope is not implemented. The ordering is
carried on IRuntimeSession.References, but nothing consults it. A name that matches symbols from more than one
reference is reported as VBC09301 Ambiguous name (see
Duplicate and ambiguous names).
ISymbolProvider
ISymbolProvider exposes a single ProvideSymbols method, which yields the Symbols its source defines. The
composition root (RD-VBAL §2.3.1 Composition Root) then defines each provided Symbol:
| Context | Each provided Symbol is defined into |
|---|---|
| Static | The semantic layer. |
| Runtime | The session symbol table, through ISessionSymbols.TryDefine. |
ISymbolProvider is the abstraction behind the several symbol providers a session is composed from:
| Symbol provider source |
|---|
| Configuration flags. |
| AST declarations. |
| Reflected referenced libraries. |
| The environment host's own runtime and standard library (RD-VBAL §6.0 Standard Library). |
Heaps
The session's ISessionSymbols and ISessionObjects implementations should maintain the following internal
structures:
| Internal structure | Holds |
|---|---|
| Global heap | An IBindingHandle for any globally-scoped Symbol. |
| Workspace heap | An IBindingHandle for any workspace-scoped Symbol. |
| Static locals heap | An IBindingHandle for any module-scoped Symbol. |
| Object heap | The Symbol references and their associated bindings for any VBObjectValue. |
| Symbol table | A map of a Uri to its associated Symbol. |
| Name table | The current representation (casing) of all loaded symbols. |
A Symbol's scope kind determines how, and whether, the symbol is allocated in memory: a
ScopeKind.Global symbol lives in the globals heap, a ScopeKind.Module symbol in the workspace statics heap, and
a ScopeKind.Instance symbol in the object heap. A Static local's storage lives in the same heap tier a module
field uses (RD-VBAL §5.4.3.1 Local Variable Declarations).
See RD-VBAL §2.5.1 Runtime Entities for ScopeKind and the allocation scopes.
The order in which names are looked up in these heaps is specified in RD-VBAL §2.3.1.3 Name Resolution.
Memory addressing
ISessionMemoryAllocator maintains an internal address pointer that tracks the current memory offset.
The current memory address pointer should be incremented by a host-defined IntPtrSize, which represents the
size of a pointer in the current environment (32 or 64 bits).
The memory map (MemoryAddress → IBindingHandle) is held by the session storage (SessionStorage, below):
it binds the IBindingHandle of a value to the
MemoryAddress reserved for it.
Note
Not implemented. The raw address map (MemoryAddress → Uri) is not implemented.
Session storage
Note
Not implemented. A bound value is not stored as a byte block at its address: an IBindingHandle is itself
the value bound to a Symbol.
A symbol's storage allocation is performed by SymbolAddressTable, which
ICallStackFrame and the module/global resolver
share (RD-VBAL §2.5.2.1.2 Array Values).
SymbolAddressTable.FreshBinding re-boxes a Variant's wrapped value into a fresh
VBRuntimeVariantValue on every store
(RD-VBAL §2.5.2.1.5 Variant Values).
Zero-size storage
ISessionMemoryAllocator refuses a zero-size allocation, as an enforced invariant: a 0-byte
bump-pointer/free-list allocation would hand the same address to the next caller.
For a non-positive size, SessionStorage.TryAllocate mints its own address and never passes the request to the
session memory allocator. The following values have a non-positive storage size, and all of them take this path:
| Value with a non-positive storage size |
|---|
Nothing |
Null |
Empty |
| An uninitialized array |
An empty ParamArray array |
Such a value still gets a binding that resolves by name, but never gets memory from the session memory allocator.
The addresses SessionStorage.TryAllocate mints for non-positive sizes are negative, so that they can never collide
with, or be mistaken for, an allocator address.
Zero-size storage is supported because a ParamArray call with nothing left over is the most common
ParamArray call shape: Call Callee(100) against a ParamArray rest() parameter with no arguments left over
collects an empty array whose Size is 0
(RD-VBAL §5.3.1.11 Procedure Invocation Argument Processing).
Call stack and file channels
The session's call stack, RuntimeCallStack, enforces a call-depth limit, in OnBeforeTryPush
(RD-VBAL §5.3.1.11 Procedure Invocation Argument Processing).
Of the GoSub Resumption List, the SDK interface ICallStackFrame exposes only GoSubDepth, the number of its
entries; it does not expose the list's push/pop mutators (RD-VBAL §3.5.4 Execution).
All file statements run through one session-level shim, the IFileChannels / IFileChannel interfaces (RD-VBAL §5.4.5 File Statements).
Thread safety
The RDCore implementations (⚖️ GPLv3) of the session services are intended to be thread-safe.
RD-VBA normally executes on a single thread, but the RD-VBA runtime implementation is not inherently single-threaded. Whether an RD-VBA environment host supports the concurrent execution of RD-VBA execution threads is host-dependent.
⏮️ RD-VBAL §2.3.1.1 Execution Session | ⏭️ RD-VBAL §2.3.1.3 Name Resolution