2.4. RD-VBA Type System - Static Types

Note

This specification may be incomplete at this time.

The type system begins with VBType and the abstractions that formalize the implicit classifications in MS-VBAL:

These abstract types and interfaces are very useful for pattern-matching types and values in both static and runtime semantics implemantations.

All representations of a data type inherit the VBType class, often indirectly through other abstract types that semantically specialize it.


2.4.1 VBIntrinsicType

In RD-VBA, a type is an intrinsic type if MS-VBAL mentions it, irrespective of its specified semantics or modelization.

The non-numeric intrinsic types are:

2.4.1.1 VBNumericType

Numeric types are intrinsic types that represent a numeric value, regardless of its representation. All numeric types additionally implement one of the following marker interfaces:

The intrinsic numeric data types are the following (showing the managed/.NET min/max values for simplicity):

Type Interface Description MinValue MaxValue
VBBypeType IIntegralNumericType 8-bit Byte unsigned integer Byte.MinValue (0) Byte.MaxValue (255)
VBIntegerType IIntegralNumericType 16-bit Integer signed integer Int16.MinValue (-32,768) Int16.MaxValue (32,767)
VBLongType IIntegralNumericType 32-bit Long signed integer Int32.MinValue (-2,147,483,648) Int32.MaxValue (2,147,486,647)
VBLongLongType IIntegralNumericType 64-bit LongLong signed integer Int64.MinValue (-9,223,372,036,854,775,808) Int64.MaxValue (9,223,372,036,854,775,807)
VBSingleType IFloatingPointNumericType 32-bit single-precision floating-point Single.MinValue Single.MaxValue
VBDoubleType IFloatingPointNumericType 64-bit double-precision floating-point Double.MinValue Double.MaxValue

2.4.1.2 VBStringType

String types are internally represented using a UTF-16 standard .NET System.String value.

2.4.1.3 VBArrayType

Array types include the following implementations:

Notes:

  • ReDim is illegal to use with any VBFixedSizeArrayValue, but may be use to declare or redimension an already-declared VBResizableArrayValue.
  • If the item type of a resizable array value is VBByteType, the data type of the array is VBResizableByteArrayType. This array type has specific let-coercion semantics attached, allowing implicit conversion to and from VBStringType.
  • The type itself does not encode any dimensions; but the associated value type does. See VBArrayValue and its derived types.

2.4.2 Non-intrinsic Types

These data types are additional RD-VBA internal data types that are not exposed to (or directly usable in) workspace source code but help complete the modelization of the system.

They include:

  • [VBStdModuleType]
  • [VBClassType]
  • [VBCollectionType]
  • [VBEnumType]
  • [VBProjectType]
  • [VBUnknownType]
  • [VBVoidType]

2.4.2.1 VBStdModuleType

Represents a standard module, which is functionally equivalent to a managed static class. Defined by workspace source code or imported from a referenced library.

2.4.2.2 VBClassType

Represents an object type defined by workspace source code in a class module. This type implements IVBMemberOwnerType, which makes it expose an immutable array of VBTypeMemberSymbol where each element describes a member of the class type.

2.4.2.2.1 SuperTypes

While class modules defined in the workspace source code have no means to inherit another class module in the Object-Oriented Programming sense of "Inheritance", all VBA classes still inherit a base class that exposes Initialize and Terminate internal events, respectively fired by the host upon instantiation and destruction of an instance (object) of a given class type.

If a class module specifies any Implements directives, the interfaces specified by such directives are included in this array.

2.4.2.2.1.1 Extensible ("Document") Modules

ℹ️ extensible class modules have host-defined interfaces in their SuperTypes array that require information that is unavailable to the RD-VBA host without a library reference to the library that defines these types. In other words RD-VBA code that depends on for example the Microsoft Excel type library, requires the Microsoft Excel type library to correctly resolve the members and expressions inside such class modules.

Warning

Extensible modules cannot specify any Implements directives. This specification is not strictly enforced in MS-VBA, which can cause host application instabilities, source project corruption, and host application crashes for what should be statically caught early on as normal compile-time errors; RD-VBA must explicitly, statically deny Implements directives in these modules.

2.4.2.2.2 Default Member

Members of a class can contain a VB_UserMemId attribute that can specify a number of flags that modify the behavior. A class can have exactly one member with a VB_UserMemId attribute value of 0, making that member the class type's default member.

The default member of a class type can be implicitly invoked through let-coercion, yielding the data value of the object, recursively as needed if the default member also yields an object data type.

2.4.2.3 VBCollectionType

🧩 Object value types (inheriting VBObjectValue) representing an instance of a collection type should implement IEnumerableObject.

A subclass of VBClassType that exposes a NewEnum member and can be efficiently iterated using a For Each...Next loop structure.

Tip

For Each...Next enumeration is intended to be used with collections containing objects. Performance-related diagnostics should be issued when a VBCollectionType is being accessed by index within the body of a For...Next loop.

Note

The VBA language specification (MS-VBAL) sometimes refers to the elements (or items) of a collection as "data members". This term sometimes appears in error messages (see VBR00461 MethodOrDataMemberNotFound), but is objectively confusing terminology that RD-VBAL is discarding: in RD-VBA a "member" is always a direct child symbol of a module, user-defined type, or enum. Regardless of the message content, RD-VBA must still raise the MS-VBA equivalent error code in the relevant contexts.

2.4.2.4 VBProjectType

The symbol at the top of the abstract syntax tree (AST) of an entire VBA project is of a type inherited from VBProjectType. These correspond to the project types defined in MS-VBAL§4.1:

2.4.2.4.1 VBSourceProject

This type corresponds to the RD-VBA workspace folder (.rdproj) content, representing the workspace source code of a VBA project.

2.4.2.4.2 VBLibraryProject

This type corresponds to a referenced library, referenced by a VBSourceProjectType (source project). A project of this type is defined in an implementation-defined manner and exposes the types and members of the library to RD-VBA source code through the means available to any other VBA source code, making it feel as though workspace source code is manipulating objects and members defined in VBA source code - but the library itself may or may not have been compiled from such.

2.4.2.4.3 VBHostProjectType

This type of project can be introduced into the RD-VBA environment by the host (rdc.exe) in an implementation-defined manner. Additional workspace source code may be added to this project if it is open ("an open host project"), by agents other than the host application.

👉 RDCoreReference for references of this type must have the "unremovable" flag set.

2.4.2.5 VBUnknownType

A special data type that represents an unresolved type. This is the fallback data type used when type resolution semantics fail to identity a valid data type for a given value.

Warning

Unknown types represent a compile-time binding failure and should raise error RDC009311 UserDefinedTypeNotDefined (which is arguably a confusing wording; verbose messages should help clarify the meaning).

2.4.2.6 VBVoidType

A special data type that represents the absence of return value semantics; this is the data type returned by Sub, Property Let, and Property Set procedures.

👉 The internal representation of this type being a managed Int32 value (0), because the intent is to ultimately support HRESULT interoperability.


2.4.3 Meta and Advanced Types

These data types are introspective types that can reflectively describe the type system itself, and as such MUST NOT BE EXPOSED directly to RD-VBA source code: doing so would BREAK THE LANGUAGE on a fundamental level.

🧩 They DO, however, provide extremely powerful language-level extension possibilities.

These types include:

2.4.3.1 VBTypeDesc

Represents (describes) a VBType within the type system.

👉 A value (see VBTypeDescValue) of this meta-type is notably used in the implementation of the Is relational operator and of let-coercion, where semantics demand knowledge of a data type where a value is normally required.

None of the other descriptor types are currently in use, but language core or future language extension features may eventually use them as needed.

2.4.3.2 VBMemberDesc

An abstract descriptor that represents (describes) any VBTypeMemberSymbol.

2.4.3.2.1 VBProcedureMemberDesc

A descriptor that represents (describes) any VBProcedureMemberSymbol.

2.4.3.2.2 VBPropertyLetMemberDesc

A descriptor that represents (describes) a VBProprertyLetMemberSymbol.

2.4.3.2.3 VBPropertySetMemberDesc

A descriptor that represents (describes) a VBProprertySetMemberSymbol.

2.4.3.2.4 VBReturningMemberDesc

An abstract descriptor that represents (describes) any VBReturningMemberSymbol.

2.4.3.2.4.1 VBFunctionProcedureDesc

A descriptor that represents (describes) a VBFunctionMemberSymbol.

2.4.3.2.4.2 VBPropertyGetProcedureDesc

A descriptor that represents (describes) a VBFunctionMemberSymbol.

2.4.3.3 VBParameterDesc

A descriptor that represents (describes) a VBParameterSymbol.


2.4.4 Deferred Types

The RD-VBA type system defines a category of deferred data types. These types are not currently in use, but their presence intends to prepare the ground for supporting IntelliSense and other features in late-bound and other cases where MS-VBA would fail to resolve a valid compile-time data type.

A deferred type is a valid RD-VBA data type representing an undefined type that may statically be one of the following data types:

An undefined type is a workspace-defined data type that does not have any associated source code.

Deferred names

  • The name of a deferred type is a candidate name that can change depending on how the deferred type is being used.
  • The name of a deferred member is the identifier name identifying it in the workspace source code. Any given two symbols should be resolved to the same deferred member if the resolved qualifying module is the same for both symbols. Without a qualifier, the deferred symbol is deemed to be an undeclared local variable as per MS-VBAL scoping rules, meaning if a global-scope deferred symbol with the same identifier name exists, then the undeclared local variable should resolve to the global-scope deferred symbol.
  • The name of a deferred parameter is Arg followed by its 1-based position in the deferred member signature, in sequence such that the first parameter is named Arg1, the second is named Arg2, and so on. If a call site supplies a named argument that is not a defined deferred paraemter, then a deferred parameter with that name is defined at the end of the deferred member signature (multiple such named parameters would then be materialized in alphabetical order), and deemed Optional.
Tip

Deferred types cannot implement IVBMemberOwnerType, because the related symbols are unbound. Instead they implement IVBInferableType, exposing an immutable hashset of candidate types that would be legal to materialize the type with.

2.4.4.1 VBDeferredModuleType

Represents a deferred VBStdModuleType.

A deferred member is presumed to belong to a deferred module unless it is qualified, in which case it is added to the resolved module type's IVBMemberOwnerType.DeferredMembers array if the resolved module has a bound symbol. If the symbol is unbound, then it's a named deferred module. Only ONE single unnamed deferred module may be semantically (but not statically) defined at any given time in a source project.

2.4.4.2 VBDeferredClassType

Represents a deferred VBClassType.

👉 Deferred class types cannot be presumed to have a default instance (set by a VB_PreDeclaredId module attribute with the value True).

A deferred class is semantically defined when an unbound member call is made against an object variable of a class type that may or may not be defined in the workspace source code. The default name of a deferred class is the word Class followed by as many numeric digits as needed to make the class name unique in the workspace, in numerical order. In other words the default name of a deferred class type is Class1, unless there's already a Class1 module in the workspace, in which case the default name of the deferred class type is Class2, and so on until a unique, non-existing name is found.

⚠️ The names of any deferred type defined in workspace source code must be considered as "in use" for all operations involving the naming of a module, including the addition of new (bound) modules in the workspace or project.

2.4.4.3 VBDeferredTypeDesc

Represents (describes) a VBDeferredType within the type system.

👉 A value (see VBTypeDescValue) of this meta-type is used in the implementation of the Is relational operator, where semantics demand knowledge of a data type where a value is normally required.

None of the other descriptor types are currently in use, but language core or future language extension features may eventually use them as needed. All deferred descriptor types inherit the corresponding non-deferred descriptor type and explicitly shadow (hide) the static TypeInfo property (when the descriptor describes a type).

2.4.4.4 VBDeferredMemberDesc

A descriptor that represents (describes) any VBDeferredTypeMemberSymbol.

2.4.4.4.1 VBDeferredProcedureMemberDesc

A descriptor that represents (describes) a non-returning VBDeferredProcedureMemberSymbol.

2.4.4.4.2 VBDeferredPropertyLetProcedureDesc

A descriptor that represents (describes) a deferred Property Let member.

2.4.4.4.3 VBDeferredPropertySetProcedureDesc

A descriptor that represents (describes) a deferred Property Set member.

2.4.4.4.4 VBDeferredFunctionProcedureDesc

A descriptor that represents (describes) a deferred Function member.

2.4.4.4.5 VBDeferredPropertyGetProcedureDesc

A descriptor that represents (describes) a deferred Function member.

2.4.4.4.6 VBDeferredParameterDesc

A descriptor that represents (describes) a single parameter of a deferred member.

👉 Deferred parameters are inferred from the arguments provided at the call sites of deferred members.

The data type of a deferred parameter depends on how many call sites supply an argument for it, and the data types of these arguments.

  • Given only VBBooleanValue values, the data type is VBBooleanType;
  • Given only VBObjectValue values, the data type is VBObjectType;
    • If the class type is resolvable (whether deferred or not), the data type is of that specific class type.
  • Given any number of VBStringType values, the data type is VBStringType;
  • Given any number of VBEnumType values, the data type is VBIntegerType;
  • Given any number of IIntegralNumericType values, the data type is the largest of the candidate types;
  • Given any number of IFixedPointNumericType values, the data type is VBCurrencyType;
  • Given any number of IFloatingPointNumericType values, the data type is VBDoubleType;

All of the above define a deferred ByVal parameter that is passed by value; the following define a ByRef parameter that must be passed by reference:

  • Given a specific VBUserDefinedTypeValue, the data type is that of the specified UDT.
  • Given any number of VBArrayValue or any mixed-bag heterogenous call site arguments, the data type is Variant. This case may not be materializable and should issue semantic flags as appropriate to signal it to any listening language-level extensions.

⏮️ RD-VBAL §2.3 Application Host | ⏭️ RD-VBAL§2.5 Runtime Values