#charset "us-ascii" /* * 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 /* * 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; }