For every TclObject that is created, establishes the instance procedure, []cmd, as a hook to executing methods through the compiled shadow object. The procedure []cmd invokes the method []command of the shadow object automatically, passing the arguments to []cmd as an argument vector to the []command method.
The user can invoke the []cmd method in one of two ways: by explicitly invoking the procedure, specifying the desired operation as the first argument, or implicitly, as if there were an instance procedure of the same name as the desired operation. Most simulation scripts will use the latter form, hence, we will describe that mode of invocation first.
Consider the that the distance computation in SRM is done by the compiled object; however, it is often used by the interpreted object. It is usually invoked as:
$srmObject distance? \tup{agentAddress}If there is no instance procedure called distance?, the interpreter will invoke the instance procedure []unknown, defined in the base class TclObject. The unknown procedure then invokes
$srmObject cmd distance? \tup{agentAddress}to execute the operation through the compiled object's []command procedure.
Ofcourse, the user could explicitly invoke the operation directly. One reason for this might be to overload the operation by using an instance procedure of the same name. For example,
Agent/SRM/Adaptive instproc distance? addr { $self instvar distanceCache_ if ![info exists distanceCache_($addr)] { set distanceCache_($addr) [{\bfseries{}$self cmd distance? $addr}] } set distanceCache_($addr) }
We now illustrate how the []command method using []ASRMAgent::command as an example.
int ASRMAgent::command(int argc, const char*const*argv) { Tcl& tcl = Tcl::instance(); if (argc == 3) { if (strcmp(argv[1], "distance?") == 0) { int sender = atoi(argv[2]); SRMinfo* sp = get_state(sender); tcl.tesultf("%f", sp-\>distance_); return TCL_OK; } } return (SRMAgent::command(argc, argv)); }We can make the following observations from this piece of code:
The command line arguments vector (argv) consists of -- argv[0] contains the name of the method, ``cmd''.
-- argv[1] specifies the desired operation.
-- If the user specified any arguments, then they are placed in argv[2...(argc - 1)].
The arguments are passed as strings; they must be converted to the appropriate data type.
This permits the user to concieve of operations as having the same inheritance properties as instance procedures or compiled methods.
In the event that this command method is defined for a class with multiple inheritance, the programmer has the liberty to choose one of two implementations:
1) Either they can invoke one of the parent's command method, and return the result of that invocation, or
2) They can each of the parent's command methods in some sequence, and return the result of the first invocation that is successful. If none of them are successful, then they should return an error.