/
CDC-1.2b/
CDC-1.2b/src/
parent $foundation
object $has_verbs

var $has_verbs verbs #[]
var $root child_index 0
var $root owners [$has_verbs]
var $root fertile 1
var $root inited 1
var $root owned [$has_verbs]
var $root manager $has_verbs
var $root writable [$has_verbs]
var $root readable ['parameters, 'methods, 'code]
var $root info ["$has_verbs defines all the functionality necessary for an object to have verbs, or methods activated by commands typed by a user object which is not this. Verbs are useful for making certain functionality only available when an object is present, and for allowing different objects to have identicle verbs with different internal meanings (turn alarm to 6am vs. turn safe to 10)."]
var $root dbref 'has_verbs

method init_has_verbs
    if (caller() != $root)
        throw(~perm, "Caller is not $root.");
    verbs = #[];
.

method uninit_has_verbs
    var template;
    
    if (caller() != $root)
        throw(~perm, "Caller is not $root.");
    verbs = 0;
    for template in (dict_keys(verbs))
        $verb_cache.object_undefined_verb(template);
.

method verb_templates
    return dict_keys(verbs);
.

method add_verb
    arg template, method, remote;
    var words, pos;
    
    if (!(.is_writable_by(sender())))
        throw(~perm, "Sender is not an owner.");
    
    // Check argument types.
    if (type(template) != 'string)
        throw(~type, "Template is not a string.");
    if (type(method) != 'symbol)
        throw(~type, "Method obj_name is not a symbol.");
    if ((remote != 'remote) && (remote != 'noremote))
        throw(~type, "Remote specifier is neither 'remote nor 'noremote");
    
    // Make sure there's exactly one "%this" in the template, as a word by
    // itself.
    words = explode(template);
    if (((words[1]) == "%this") || (((words[1]) == "*") || ((words[1]) == "*=*")))
        throw(~template, "Template begins with wildcard.");
    pos = "%this" in words;
    if ((!pos) || ("%this" in sublist(words, pos + 1)))
        throw(~template, "Template does not contain exactly one \"%this\".");
    
    // Add the verbs to the dictionary, and notify $verb_cache.
    verbs = dict_add(verbs, template, [method, remote]);
    if (remote == 'remote)
        $verb_cache.del_template(template);
.

method del_verb
    arg template;
    var verb_info;
    
    if (!(.is_writable_by(sender())))
        throw(~perm, "Sender is not an owner.");
    catch ~keynf {
        verb_info = verbs[template];
        verbs = dict_del(verbs, template);
        (| $verb_cache.del_template(template) |);
    } with handler {
        throw(~verbnf, ("No verb with template " + tostr(template)) + ".");
    }
.

method verb_info
    disallow_overrides;
    arg template;
    var verb_info, anc;
    
    if (dict_contains(verbs, template))
        return verbs[template];
    for anc in (ancestors()) {
        verb_info = (| anc.local_verb_info(template) |);
        if (verb_info)
            return verb_info;
    }
    throw(~verbnf, "No verb with template " + template);
.

method local_verb_info
    disallow_overrides;
    arg template;
    
    catch ~keynf {
        return verbs[template];
    } with handler {
        throw(~verbnf, "No verb with template " + template);
    }
.

method verbs
    return verbs;
.

method all_verbs
    var p, vrblist, pv;
    
    vrblist = #[];
    for p in (.ancestors()) {
        pv = (| p.verbs() |);
        if (pv)
            vrblist = vrblist.union(pv);
        if (p == definer())
            break;
    }
    return vrblist;
.