Bash++ v0.7: RTTI and Runtime-Inferred Dynamic Cast Targets
Bash++ v0.7 introduces some expanded usage of RTTI (Run-Time Type Information) in the language. For some time, type information about objects has been stored at runtime (this is necessary, for example, for virtual methods) but mostly inaccessible to the programmer. From the programmer’s perspective, the only direct window into this information has been the @dynamic_cast
operator:
@Object* obj=@dynamic_cast<Object> &@other_obj
And we could then compare @obj
to @nullptr
to see if the cast was successful. This tells you whether @other_obj
’s type is either Object
or some derived type along the inheritance chain. This is useful, but limited.
@typeof
Bash++ v0.7 introduces the @typeof
operator, which allows you to query the exact type of an object at runtime:
The @typeof
operator expects a pointer to an object, and its output is the name of the class as a string. This allows you to perform exact type comparisons, which can be useful in certain scenarios.
Runtime-Inferred Dynamic Cast Targets
This change, to me, is more interesting.
Up until v0.7, the @dynamic_cast
operator has only accepted a class name as its target type. This meant that the target type had to be known at compile time.
With v0.7, the @dynamic_cast
operator can now accept a shell variable or object reference which is expected to contain a class name at runtime:
cast_to_class="MyClass"
In these cases, the compiler simply accepts the reality that it cannot verify the correctness of the target type at compile time.
Previously, if an invalid class name was given to @dynamic_cast
, the compiler would emit an error and halt compilation. This behavior has been changed – the compiler will now emit a warning instead. In the case of a runtime-inferred target type, the compiler cannot verify the correctness of the target type, so it will not emit any warning.
This opens up a lot of new possibilities for us. Immediately with this change, we’re able to introduce Typed containers to the standard library (TypedArray, TypedStack, TypedQueue, etc, as well as Typed versions of all the Shared containers for multi-process concurrency).
The Typed containers work essentially like this:
@class TypedStack : Stack
These typed containers use runtime-inferred cast targets to enforce type constraints on the elements they contain. In other words, they will refuse to accept any primitives which are not pointers to objects of the correct type.
If you’re, for example, using a TypedStack
of @Object
, then it’s completely safe to do something like this:
@Object* top=@stack.top
And use @top
as an @Object*
without any further casting or verification, because the TypedStack
has already guaranteed that everything it contains is an @Object*
or derived type.