4.4.3 Runtime type information

Many modern languages provide the ability for programs to examine and even modify the behavior of themselves. Java, for instance, has elaborate support for reflection, enabling programs to locate classes, iterate over their methods, and invoke methods—all at runtime. With such elaborate support for reflection built into the platform itself, supporting scripting languages is trivial. There would be no need for a Scriptable interface; a script interpreter would use the reflection services of the platform to reflectively verify the correctness of invocations before dispatching them.

Providing this level of support for reflective operations requires that type information normally only available at compile-time is available at runtime. In the solution presented in Listing 4.8, some of this data is indeed present, embedded in the imperative code that makes up the implementation of Scriptable::InvokeOperation(). In order to provide a fuller reflection service, such data would need to be available as part of a generic data structure. With an interface description language and an IDL compiler, this data structure could be populated by generated code.

If every class makes type information on itself available at runtime, perhaps by adding an operation to that effect to the Fundamental interface, it is possible to write class-agnostic implementations of Fundamental::SwitchInterface() and Scriptable::InvokeOperation() that could be shipped as part of the runtime system of a component model implementation. The former operation would consult the type information to see if a requested interface was implemented by the object, and if so, return a proper reference. The latter operation would check the validity of invocations against the type information before invoking calls. Relying on class-agnostic, generic implementations that use runtime-accessible type information saves on code size compared to generating class-specific code.

A class-agnostic implementation of Scriptable::InvokeOperation() would be somewhat more complex to write than simply generating class-specific code, though. In particular, a class-specific implementation can perform a normal C function call to invoke an operation after verifying the correctness of the call, whereas a class-agnostic implementation would not have the luxury of having the C compiler generate the machine instructions performing the invocation. Instead, a class-agnostic implementation would manually have to construct a stack frame to be pushed onto the call stack, and this part would need to be written in architecture-specific assembly language.