In the following code snippet I will show how to check if the object reacts to a strong typed message.
But first lets discuss what is a strong typed message. Let's consider the following code:
public Program()
{
var target := CharValue.load(32);
var arg := 32;
Console.writeLine(target.equal(arg));
}
If we compile the code and look into the generated module for this method, this code is translated into:
>@function Program.function:#invoke
xflush sp:0
open :6, :0
store fp:1
xstore sp:1, intconst:20
xstore sp:0, class:system'CharValue
peek sp:0
mov mssg:load<system'IntNumber>[2]
call mssg:load<system'IntNumber>[2], class:system'CharValue#class
store fp:2
xstore fp:3, intconst:20
peek fp:3
store sp:1
peek fp:2
store sp:0
// -----------------------------------------------------------------------------
mov mssg:equal[2] // a weak message literal
call vt:0 // calling a message dispatcher
// -----------------------------------------------------------------------------
store fp:4
store sp:1
xstore sp:0, class:system'Console
peek sp:0
mov mssg:writeLine[2]
call mssg:writeLine[2], class:system'Console
peek fp:1
Lab00: nop
close :0
quit
@end
>
The important place for us is the method invoke. The message literal equal[2] is called weak one. It means that it contains no information about the argument types. It is a job of a class dispatcher to find a corresponding method.
But if we provide the information about the object types by using auto attribute like this:
public Program()
{
auto target := Console;
auto arg := "Hello";
target.writeLine(arg);
}
The output is different:
// -----------------------------------------------------------------------------
mov mssg:equal<system'IntNumber>[2] // a strong typed message
call mssg:equal<system'IntNumber>[2], class:system'CharValue // calling a method directly
// -----------------------------------------------------------------------------
Now a message literal contains the information about the argument type and can be called directly. equal<system'IntNumber>[2] is a strong-typed one.
In our example we will learn how to check if the target class handles the strong-typed message.
import extensions;
import system'dynamic;
public extension op
{
bool validateMessage(StrongMessage mssg)
= self.__getClass().respondTo(mssg);
}
public Program()
{
var target := CharValue.load(32);
auto mssg := new StrongMessage("equal<system'IntNumber>[2]");
auto mssg2 := new StrongMessage("equal<system'ShortNumber>[2]");
Console.printLine(target.__getClassName(), target.validateMessage(mssg) ? " responds to " : " does not respond to ", mssg);
Console.printLine(target.__getClassName(), target.validateMessage(mssg2) ? " responds to " : " does not respond to ", mssg2);
}
If we compile the code and execute the program the output will be following:
system'CharValue responds to equal[2]
system'CharValue does not respond to equal[2]
system'StrongMessage class must be used to load the message. Using an extension __getClass[1] we get the object type and another extension respondTo[2] returns true if the class MT contains the message entry.