diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-12-01 06:42:41 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-12-01 06:42:41 -0800 |
commit | c4619219afbe5eb123322f3d7ddebffa5b3a5dff (patch) | |
tree | 9784d0057653bc8946d1f7109900b93a5ceda5fb | |
parent | 4e92c2d19382340d8e6c8fe71013d02bbc6065f4 (diff) | |
download | txr-c4619219afbe5eb123322f3d7ddebffa5b3a5dff.tar.gz txr-c4619219afbe5eb123322f3d7ddebffa5b3a5dff.tar.bz2 txr-c4619219afbe5eb123322f3d7ddebffa5b3a5dff.zip |
static-slot-ensure always processes subtypes.
* struct.c (static_slot_ensure): Restructured function so that
the subtypes of stype are processed even if stype already has
the static slot. This way static-slot-ensure can be used to
overwrite a static slot value, not only establish one.
And thus defmeth can redefine methods.
* txr.1: Revamped static-slot-ensure doc, and added notes
about redefining to defmeth.
-rw-r--r-- | struct.c | 33 | ||||
-rw-r--r-- | txr.1 | 67 |
2 files changed, 51 insertions, 49 deletions
@@ -764,6 +764,7 @@ val static_slot_ensure(val stype, val sym, val newval, val no_error_p) { val self = lit("static-slot-ensure"); struct struct_type *st = stype_handle(&stype, self); + loc ptr; if (!bindable(sym)) uw_throwf(error_s, lit("~a: ~s isn't a valid slot name"), @@ -774,24 +775,24 @@ val static_slot_ensure(val stype, val sym, val newval, val no_error_p) if (st->eqmslot == -1) st->eqmslot = 0; - { - loc ptr = lookup_static_slot(stype, st, sym); - if (!nullocp(ptr)) - return set(ptr, newval); + if (nullocp((ptr = lookup_static_slot(stype, st, sym)))) { + if (!memq(sym, st->slots)) { + st->stslot = coerce(val *, chk_manage_vec(coerce(mem_t *, st->stslot), + st->nstslots, st->nstslots + 1, + sizeof (val), + coerce(mem_t *, &newval))); + set(mkloc(st->slots, stype), append2(st->slots, cons(sym, nil))); + sethash(slot_hash, cons(sym, num_fast(st->id)), + num(st->nstslots++ + STATIC_SLOT_BASE)); + } else { + if (!no_error_p) + uw_throwf(error_s, lit("~a: ~s is an instance slot of ~s"), + self, sym, stype, nao); + } + } else { + set(ptr, newval); } - if (!no_error_p && memq(sym, st->slots)) - uw_throwf(error_s, lit("~a: ~s is an instance slot of ~s"), - self, sym, stype, nao); - - st->stslot = coerce(val *, chk_manage_vec(coerce(mem_t *, st->stslot), - st->nstslots, st->nstslots + 1, - sizeof (val), - coerce(mem_t *, &newval))); - set(mkloc(st->slots, stype), append2(st->slots, cons(sym, nil))); - sethash(slot_hash, cons(sym, num_fast(st->id)), - num(st->nstslots++ + STATIC_SLOT_BASE)); - { val iter; for (iter = st->dvtypes; iter; iter = cdr(iter)) @@ -18723,6 +18723,16 @@ are applied to the structure as if it were a function, the method is invoked with those arguments, with the object itself inserted into the leftmost argument position. +If +.code defmeth +is used to redefine an existing method, the semantics can be inferred +from that of +.codn static-slot-ensure . +In particular, the method will be imposed into all subtypes which do not +override the method using an instance slot, overwriting any subtype-specific +methods stored in static slots of the same name. These subtype methods +have to be individually reinstated, if they are required. + .coNP Macros @ new and @ lnew .synb .mets (new >> { name | >> ( name << arg *)} >> { slot << init-form }*) @@ -19728,45 +19738,36 @@ must be a static slot of this type. .desc The .code static-slot-ensure -function is similar to -.codn static-slot-set . +first ensures that the struct type +.meta type +and all struct types derived from it have a static slot called +.metn name . +The slot is added as a static slot to every eligible type which doesn't already +have an instance or static slot by that name. -It +Then, .meta new-value -into the static slot named by symbol +is stored into all of the .meta name -of the structure type -.metn type , -if there already exists such a static slot. +static slots of +.meta type +and all its derived types. -If the slot does not exist, it is first added to -the struct type, provided that +If +.meta type +itself already has an instance slot called .meta name -is a bindable symbol. Moreover, -the struct type must not already have -an instance slot by that name, -unless the -.meta no-error-p -parameter is specified and true. -If the -.meta no-error-p -parameter is true, then the function does -not throw an error and does not create a -static slot. - -The function returns -.metn new-value . - -Note: if structure types already exist which are derived from -.metn type , -.code static-slot-ensure -is recursively invoked on each derived type to ensure that these -types also have this static slot and it is given the specified value. The +then an error is thrown, and the function has no effect. If the same situation +is true of the subtypes of +.meta type +then the situation is ignored: for those subtypes, no static slot is added, and +.meta new-value +is not stored. If the .meta no-error-p -parameter is -.code nil -in these recursive calls, so that the static slot is only added -to those structures which do not already have an instance slot. +argument is present, and its value is true, then +.meta type +is treated just like the subtypes: if it has a conflicting instance slot, +then the situation is ignored and the subtypes are processed anyway. .coNP Function @ call-super-method .synb |