/*
* Copyright (c) 2009 by Kevin Forchione. All rights reserved.
*
* This file is part of the TADS 3 Inherited Multi-Method
* library extension
*
* imm.t
*
* Implements an inherited multi-method mechanism.
*/
#include <tads.h>
/*
* Add a base function lookup to the multi-method registry.
*/
modify _multiMethodRegistry
{
/* table of registered base functions */
baseFuncTab_ = static new LookupTable(128, 256)
}
/*
* Modify the function to store information in the base function Lookup
*/
modify _multiMethodRegister(baseFunc, func, params)
{
_baseMethodRegister(baseFunc, func, params);
replaced(baseFunc, func, params);
}
/*
* This function stores base function and params as values in base function
* lookup, using func as the key.
*/
_baseMethodRegister(baseFunc, func, params)
{
/* if there's no hash entry for the function yet, add one */
local tab = _multiMethodRegistry.baseFuncTab_;
/* set the entry as the base function for this multi-method */
tab[func] = [baseFunc, params];
}
/*
* An analog to "inherited()" this function will attempt to find the
* appropriate multi-method and execute it.
*
* Each parameter value requiring a type should be composed of a 2-element
* list, the 1st element designating the type, the 2nd element the value
* to be passed to the retrieved multi-method.
*
* For instance, to invoke the following multi-method:
*
* functionName(Type1 value1, value2, Type3, value3) {}
*
* You would code the call as following from the calling multi-method:
*
* functionName(TypeX value1, TypeY value2, TypeZ value3)
* {
* inheritedMultiMethod([Type1, value1], value2, [Type3, value3]);
* }
*/
inheritedMultiMethod([params])
{
local func, result, mmFunc, typeList = [], valueList = [];
/* get the invoked function */
func = t3GetStackTrace(2).func_;
/* retrieve the associated entry from the base function lookup */
result = _multiMethodRegistry.baseFuncTab_[func];
if (result)
{
/*
* Build a "types" list and "values" list from the function's
* parameters
*/
params.forEach(new function(elm)
{
switch(dataType(elm))
{
case TypeList:
typeList += elm[1];
valueList += elm[2];
break;
default:
typeList += elm;
valueList += elm;
}
});
/*
* Retrieve the multi-method for the base function and type list
*/
mmFunc = getMultiMethodPointer(result[1], typeList...);
/* if we have a multi-method, invoke it */
if (mmFunc)
return mmFunc(valueList...);
}
/* we don't have a multi-method, return nil */
return nil;
}