summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-12-01 06:42:41 -0800
committerKaz Kylheku <kaz@kylheku.com>2015-12-01 06:42:41 -0800
commitc4619219afbe5eb123322f3d7ddebffa5b3a5dff (patch)
tree9784d0057653bc8946d1f7109900b93a5ceda5fb
parent4e92c2d19382340d8e6c8fe71013d02bbc6065f4 (diff)
downloadtxr-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.c33
-rw-r--r--txr.167
2 files changed, 51 insertions, 49 deletions
diff --git a/struct.c b/struct.c
index 9ac312aa..b55c57be 100644
--- a/struct.c
+++ b/struct.c
@@ -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))
diff --git a/txr.1 b/txr.1
index 9d6faf8b..f5971170 100644
--- a/txr.1
+++ b/txr.1
@@ -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