Table of Contents

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