# HG changeset patch # User Michael Goffioul # Date 1390245042 18000 # Node ID 06eb893b9db688d11fb15ab04d0782f0d13e20ed # Parent 9d62b5f041ee2795bab6aab8dec9fc31fd58e3c9 Implement subsref overloading in classdef. * ov-class.cc (sanitize, make_idx_args): Moved function to ov-base.cc. * ov-base.cc (sanitize, make_idx_args): Moved from ov-class.cc. * ov-base.h (make_udx_args): New API function declaration. * ov-classdef.cc (in_class_method): New utility static function. (octave_classdef::subsref): Use overloaded subsref method if present, only when not already in a class method. diff -r 9d62b5f041ee -r 06eb893b9db6 libinterp/octave-value/ov-base.cc --- a/libinterp/octave-value/ov-base.cc Mon Jan 20 01:41:26 2014 -0500 +++ b/libinterp/octave-value/ov-base.cc Mon Jan 20 14:10:42 2014 -0500 @@ -1536,6 +1536,97 @@ return new octave_cell (); } +static inline octave_value_list +sanitize (const octave_value_list& ovl) +{ + octave_value_list retval = ovl; + + for (octave_idx_type i = 0; i < ovl.length (); i++) + { + if (retval(i).is_magic_colon ()) + retval(i) = ":"; + } + + return retval; +} + +octave_value +make_idx_args (const std::string& type, + const std::list& idx, + const std::string& who) +{ + octave_value retval; + + size_t len = type.length (); + + if (len == idx.size ()) + { + Cell type_field (1, len); + Cell subs_field (1, len); + + std::list::const_iterator p = idx.begin (); + + for (size_t i = 0; i < len; i++) + { + char t = type[i]; + + switch (t) + { + case '(': + type_field(i) = "()"; + subs_field(i) = Cell (sanitize (*p++)); + break; + + case '{': + type_field(i) = "{}"; + subs_field(i) = Cell (sanitize (*p++)); + break; + + case '.': + { + type_field(i) = "."; + + octave_value_list vlist = *p++; + + if (vlist.length () == 1) + { + octave_value val = vlist(0); + + if (val.is_string ()) + subs_field(i) = val; + else + { + error ("expecting character string argument for '.' index"); + return retval; + } + } + else + { + error ("expecting single argument for '.' index"); + return retval; + } + } + break; + + default: + panic_impossible (); + break; + } + } + + octave_map m; + + m.assign ("type", type_field); + m.assign ("subs", subs_field); + + retval = m; + } + else + error ("invalid index for %s", who.c_str ()); + + return retval; +} + void install_base_type_conversions (void) { diff -r 9d62b5f041ee -r 06eb893b9db6 libinterp/octave-value/ov-base.h --- a/libinterp/octave-value/ov-base.h Mon Jan 20 01:41:26 2014 -0500 +++ b/libinterp/octave-value/ov-base.h Mon Jan 20 14:10:42 2014 -0500 @@ -828,4 +828,12 @@ // is memory to be saved extern OCTINTERP_API bool Vsparse_auto_mutate; +// Utility function to convert C++ arguments used in subsref/subsasgn into an +// octave_value_list object that can be used to call a function/method in the +// interpreter. +extern OCTINTERP_API octave_value +make_idx_args (const std::string& type, + const std::list& idx, + const std::string& who); + #endif diff -r 9d62b5f041ee -r 06eb893b9db6 libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Mon Jan 20 01:41:26 2014 -0500 +++ b/libinterp/octave-value/ov-class.cc Mon Jan 20 14:10:42 2014 -0500 @@ -268,97 +268,6 @@ error ("assignment to class element failed"); } -static inline octave_value_list -sanitize (const octave_value_list& ovl) -{ - octave_value_list retval = ovl; - - for (octave_idx_type i = 0; i < ovl.length (); i++) - { - if (retval(i).is_magic_colon ()) - retval(i) = ":"; - } - - return retval; -} - -static inline octave_value -make_idx_args (const std::string& type, - const std::list& idx, - const std::string& who) -{ - octave_value retval; - - size_t len = type.length (); - - if (len == idx.size ()) - { - Cell type_field (1, len); - Cell subs_field (1, len); - - std::list::const_iterator p = idx.begin (); - - for (size_t i = 0; i < len; i++) - { - char t = type[i]; - - switch (t) - { - case '(': - type_field(i) = "()"; - subs_field(i) = Cell (sanitize (*p++)); - break; - - case '{': - type_field(i) = "{}"; - subs_field(i) = Cell (sanitize (*p++)); - break; - - case '.': - { - type_field(i) = "."; - - octave_value_list vlist = *p++; - - if (vlist.length () == 1) - { - octave_value val = vlist(0); - - if (val.is_string ()) - subs_field(i) = val; - else - { - error ("expecting character string argument for '.' index"); - return retval; - } - } - else - { - error ("expecting single argument for '.' index"); - return retval; - } - } - break; - - default: - panic_impossible (); - break; - } - } - - octave_map m; - - m.assign ("type", type_field); - m.assign ("subs", subs_field); - - retval = m; - } - else - error ("invalid index for %s", who.c_str ()); - - return retval; -} - Cell octave_class::dotref (const octave_value_list& idx) { diff -r 9d62b5f041ee -r 06eb893b9db6 libinterp/octave-value/ov-classdef.cc --- a/libinterp/octave-value/ov-classdef.cc Mon Jan 20 01:41:26 2014 -0500 +++ b/libinterp/octave-value/ov-classdef.cc Mon Jan 20 14:10:42 2014 -0500 @@ -305,6 +305,14 @@ } static bool +in_class_method (const cdef_class& cls) +{ + cdef_class ctx = get_class_context (); + + return (ctx.ok () && is_superclass (ctx, cls)); +} + +static bool check_access (const cdef_class& cls, const octave_value& acc, const std::string& meth_name = std::string (), const std::string& prop_name = std::string (), @@ -885,14 +893,38 @@ size_t skip = 0; octave_value_list retval; - // FIXME: should check "subsref" method first + cdef_class cls = object.get_class (); + + if (! in_class_method (cls)) + { + cdef_method meth = cls.find_method ("subsref"); + + if (meth.ok ()) + { + octave_value_list args; + + args(1) = make_idx_args (type, idx, "subsref"); + + if (! error_state) + { + count++; + args(0) = octave_value (this); + + retval = meth.execute (args, nargout, true, "subsref"); + } + + return retval; + } + } + + // At this point, the default subsref mechanism must be used. retval = object.subsref (type, idx, nargout, skip, cdef_class ()); if (! error_state) { if (type.length () > skip && idx.size () > skip) - retval = retval(0).next_subsref (nargout, type, idx, skip); + retval = retval(0).next_subsref (nargout, type, idx, skip); } return retval; @@ -906,8 +938,10 @@ size_t skip = 0; octave_value_list retval; - // FIXME: should check "subsref" method first - // ? not sure this still applied with auto_add version of subsref + // This variant of subsref is used to create temporary values when doing + // assignment with multi-level indexing. AFAIK this is only used for internal + // purpose (not sure we should even implement this) and any overload subsref + // should not be called. retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add);