Mercurial > hg > octave-lyh
changeset 9151:d8f9588c6ba1
object exemplars
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 23 Apr 2009 16:05:52 -0400 |
parents | e716cafee800 |
children | 4c9aff0c9a61 |
files | src/ChangeLog src/ov-base.cc src/ov-base.h src/ov-class.cc src/ov-class.h src/ov.h src/symtab.cc |
diffstat | 7 files changed, 210 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,24 @@ +2009-04-23 John W. Eaton <jwe@octave.org> + + * ov-class.cc (Fclass): Check newly constructed classes against + the first constructed object of the class. + + * ov-class.h, ov-class.cc (octave_class::exmplar_info): New class. + (exemplar_map): New static data member. + (exemplar_iterator, exemplar_const_iterator): New typedefs. + + * ov-class.h (octave_class::nparents, + octave_class::parent_class_name_list): New functions. + * ov.h (octave_base_value::nparents, + octave_base_value::parent_class_name_list): New functions. + * ov-base.h, ov-base.cc (octave_base_value::nparents, + octave_base_value::parent_class_name_list): New functions. + (parent_class_names): Error if called for wrong type argument. + + * symtab.cc (load_out_of_date_fcn): New arg, dispatch_type. + (out_of_date_check_internal): Pass dispatch type to + load_out_of_date_fcn. + 2009-04-22 John W. Eaton <jwe@octave.org> * ov-base-int.cc (octave_base_int_helper<T, false,
--- a/src/ov-base.cc +++ b/src/ov-base.cc @@ -851,6 +851,32 @@ return retval; } +size_t +octave_base_value::nparents (void) const +{ + size_t retval = 0; + gripe_wrong_type_arg ("octave_base_value::nparents()", type_name ()); + return retval; +} + +std::list<std::string> +octave_base_value::parent_class_name_list (void) const +{ + std::list<std::string> retval; + gripe_wrong_type_arg ("octave_base_value::parent_class_name_list()", + type_name ()); + return retval; +} + +string_vector +octave_base_value::parent_class_names (void) const +{ + string_vector retval; + gripe_wrong_type_arg ("octave_base_value::parent_class_names()", + type_name ()); + return retval; +} + octave_function * octave_base_value::function_value (bool silent) {
--- a/src/ov-base.h +++ b/src/ov-base.h @@ -452,8 +452,11 @@ virtual string_vector map_keys (void) const; - virtual string_vector parent_class_names (void) const - { return string_vector (); } + virtual size_t nparents (void) const; + + virtual std::list<std::string> parent_class_name_list (void) const; + + virtual string_vector parent_class_names (void) const; // FIXME -- should this warn if called for a non-class type? virtual octave_base_value *find_parent_class (const std::string&)
--- a/src/ov-class.cc +++ b/src/ov-class.cc @@ -1284,6 +1284,87 @@ && fcn->dispatch_class () == class_name ()); } +octave_class::exemplar_info::exemplar_info (const octave_value& obj) + : field_names (), parent_class_names () +{ + if (obj.is_object ()) + { + Octave_map m = obj.map_value (); + field_names = m.keys (); + + parent_class_names = obj.parent_class_name_list (); + } + else + error ("invalid call to exmplar_info constructor"); +} + + +// A map from class names to lists of fields. +std::map<std::string, octave_class::exemplar_info> octave_class::exemplar_map; + +bool +octave_class::exemplar_info::compare (const octave_value& obj) const +{ + bool retval = true; + + if (obj.is_object ()) + { + if (nfields () == obj.nfields ()) + { + Octave_map obj_map = obj.map_value (); + string_vector obj_fnames = obj_map.keys (); + string_vector fnames = fields (); + + for (octave_idx_type i = 0; i < nfields (); i++) + { + if (obj_fnames[i] != fnames[i]) + { + retval = false; + error ("mismatch in field names"); + break; + } + } + + if (nparents () == obj.nparents ()) + { + std::list<std::string> obj_parents + = obj.parent_class_name_list (); + std::list<std::string> pnames = parents (); + + std::list<std::string>::const_iterator p = obj_parents.begin (); + std::list<std::string>::const_iterator q = pnames.begin (); + + while (p != obj_parents.end ()) + { + if (*p++ != *q++) + { + retval = false; + error ("mismatch in parent classes"); + break; + } + } + } + else + { + retval = false; + error ("mismatch in number of parent classes"); + } + } + else + { + retval = false; + error ("mismatch in number of fields"); + } + } + else + { + retval = false; + error ("inavlid comparison of class exemplar to non-class object"); + } + + return retval; +} + DEFUN (class, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} class (@var{expr})\n\ @@ -1325,6 +1406,18 @@ retval = octave_value (new octave_class (m, id, parents)); } + + if (! error_state) + { + octave_class::exemplar_const_iterator it + = octave_class::exemplar_map.find (id); + + if (it == octave_class::exemplar_map.end ()) + octave_class::exemplar_map[id] + = octave_class::exemplar_info (retval); + else if (! it->second.compare (retval)) + error ("class: object of class `%s' does not match previously constructed objects", id.c_str ()); + } } else error ("class: invalid call from outside class constructor");
--- a/src/ov-class.h +++ b/src/ov-class.h @@ -109,6 +109,8 @@ octave_idx_type nfields (void) const { return map.nfields (); } + size_t nparents (void) const { return parent_list.size (); } + octave_value reshape (const dim_vector& new_dims) const { return map.reshape (new_dims); } @@ -125,6 +127,9 @@ string_vector map_keys (void) const; + std::list<std::string> parent_class_name_list (void) const + { return parent_list; } + string_vector parent_class_names (void) const { return string_vector (parent_list); } @@ -180,6 +185,53 @@ std::list<std::string> parent_list; bool in_class_method (void) const; + +public: + // The list of field names and parent classes defines a class. We + // keep track of each class that has been created so that we know + class exemplar_info + { + public: + + exemplar_info (void) : field_names (), parent_class_names () { } + + exemplar_info (const octave_value& obj); + + exemplar_info (const exemplar_info& x) + : field_names (x.field_names), + parent_class_names (x.parent_class_names) { } + + exemplar_info& operator = (const exemplar_info& x) + { + if (&x != this) + { + field_names = x.field_names; + parent_class_names = x.parent_class_names; + } + return *this; + } + + octave_idx_type nfields (void) const { return field_names.length (); } + + size_t nparents (void) const { return parent_class_names.size (); } + + string_vector fields (void) const { return field_names; } + + std::list<std::string> parents (void) const { return parent_class_names; } + + bool compare (const octave_value& obj) const; + + private: + + string_vector field_names; + std::list<std::string> parent_class_names; + }; + + // A map from class names to lists of fields. + static std::map<std::string, exemplar_info> exemplar_map; + + typedef std::map<std::string, exemplar_info>::iterator exemplar_iterator; + typedef std::map<std::string, exemplar_info>::const_iterator exemplar_const_iterator; }; #endif
--- a/src/ov.h +++ b/src/ov.h @@ -830,6 +830,12 @@ string_vector map_keys (void) const { return rep->map_keys (); } + size_t nparents (void) const + { return rep->nparents (); } + + std::list<std::string> parent_class_name_list (void) const + { return rep->parent_class_name_list (); } + string_vector parent_class_names (void) const { return rep->parent_class_names (); }
--- a/src/symtab.cc +++ b/src/symtab.cc @@ -132,11 +132,12 @@ static inline bool load_out_of_date_fcn (const std::string& ff, const std::string& dir_name, - octave_value& function) + octave_value& function, + const std::string& dispatch_type = std::string ()) { bool retval = false; - octave_function *fcn = load_fcn_from_file (ff, dir_name); + octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type); if (fcn) { @@ -229,7 +230,8 @@ if (fs.is_newer (tp)) { retval = load_out_of_date_fcn (ff, dir_name, - function); + function, + dispatch_type); clear_breakpoints = true; } @@ -247,7 +249,8 @@ // Not the same file, so load the new file in // place of the old. - retval = load_out_of_date_fcn (file, dir_name, function); + retval = load_out_of_date_fcn (file, dir_name, function, + dispatch_type); clear_breakpoints = true; }