diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-12-12 18:10:17 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-12-13 08:19:53 -0800 |
commit | b1fe95fef05b7e8d26ff82645d373c2ef0b5c449 (patch) | |
tree | 7220391285ce26f06a969d7087396275e50d2e46 /struct.c | |
parent | 2eaa8bdbb3a6d426a9de4d916dad63f77fd54092 (diff) | |
download | txr-b1fe95fef05b7e8d26ff82645d373c2ef0b5c449.tar.gz txr-b1fe95fef05b7e8d26ff82645d373c2ef0b5c449.tar.bz2 txr-b1fe95fef05b7e8d26ff82645d373c2ef0b5c449.zip |
multiple-inheritance: super-method loose ends.
* struct.c (do_super): New function. Now the common
implementation for call_super_method, call_super_fun and
super_method.
(call_super_method, call_super_fun): Reduced to small wrappers
around do_super.
(super_method): Drill into the object to geet the struct_type
handle, and then use do_super to get the method.
* tests/012/oop-mi.tl: New tests for call-super-fun and
call-super-method.
* tests/012/oop-mi.expected: Updated.
* txr.1: Updated.
Diffstat (limited to 'struct.c')
-rw-r--r-- | struct.c | 71 |
1 files changed, 45 insertions, 26 deletions
@@ -1396,39 +1396,56 @@ val static_slot_home(val stype, val sym) no_such_static_slot(self, stype, sym); } -static val call_super_method(val inst, val sym, struct args *args) +static val do_super(struct struct_type *st, + val inst, val sym, val self, + struct args *args) { - val type = struct_type(inst); - val suptype = super(type, zero); + val type = st->self; + cnum i; - if (suptype) { - val meth = static_slot(suptype, sym); - args_decl(args_copy, max(args->fill + 1, ARGS_MIN)); - args_add(args_copy, inst); - args_cat_zap(args_copy, args); - return generic_funcall(meth, args_copy); + for (i = 0; i < st->nsupers; i++) { + struct struct_type *su = st->sus[i]; + loc ptr = lookup_static_slot_load(su, sym); + if (!nullocp(ptr)) { + val meth = deref(ptr); + if (inst == t) { + return meth; + } else if (inst) { + args_decl(args_copy, max(args->fill + 1, ARGS_MIN)); + args_add(args_copy, inst); + args_cat_zap(args_copy, args); + return generic_funcall(meth, args_copy); + } else { + return generic_funcall(meth, args); + } + } } - uw_throwf(error_s, lit("call-super-method: ~s has no supertype"), - suptype, nao); + if (st->nsupers) + if (bindable(sym)) + uw_throwf(error_s, lit("~s: slot ~s not found among supertypes of ~s"), + self, sym, type, nao); + else + uw_throwf(error_s, lit("~s: ~s isn't a valid slot name"), + self, sym); + else + uw_throwf(error_s, lit("~s: ~s has no supertype"), + type, nao); +} + +static val call_super_method(val inst, val sym, struct args *args) +{ + val type = struct_type(inst); + val self = lit("call-super-method"); + struct struct_type *st = stype_handle(&type, self); + return do_super(st, inst, sym, self, args); } static val call_super_fun(val type, val sym, struct args *args) { val self = lit("call-super-fun"); struct struct_type *st = stype_handle(&type, self); - - if (st->nsupers) { - val suptype = st->sus[0]->self; - - if (suptype) { - val fun = static_slot(suptype, sym); - return generic_funcall(fun, args); - } - } - - uw_throwf(error_s, lit("~a: ~s has no supertype"), - self, type, nao); + return do_super(st, nil, sym, self, args); } val slotp(val type, val sym) @@ -1540,11 +1557,13 @@ val method_args(val strct, val slotsym, struct args *args) cons(slot(strct, slotsym), strct)), method_args_fun); } - val super_method(val strct, val slotsym) { - val super_slot = static_slot(super(struct_type(strct), zero), slotsym); - return func_f0v(cons(super_slot, strct), method_fun); + val type = struct_type(strct); + val self = lit("super-method"); + struct struct_type *st = stype_handle(&type, self); + val meth = do_super(st, t, slotsym, self, 0); + return func_f0v(cons(meth, strct), method_fun); } static val uslot_fun(val sym, val strct) |