comparison src/ov-class.cc @ 9010:f914834836e7

Partial implementation of derived classes using the old form with "@" files.
author rtshort@smoketree.phaselocked.com
date Tue, 24 Mar 2009 11:29:53 -0400
parents eb63fbe60fab
children 5579998f8acf
comparison
equal deleted inserted replaced
9009:da58ec8f62e8 9010:f914834836e7
60 { 60 {
61 t_id = octave_value_typeinfo::register_type 61 t_id = octave_value_typeinfo::register_type
62 (octave_class::t_name, "<unknown>", octave_value (new octave_class ())); 62 (octave_class::t_name, "<unknown>", octave_value (new octave_class ()));
63 } 63 }
64 64
65 octave_class::octave_class (const Octave_map& m, const std::string& id,
66 const octave_value_list& parents)
67 : octave_base_value (), map (m), c_name (id)
68 {
69 octave_idx_type n = parents.length ();
70
71 for (octave_idx_type idx = 0; idx < n; idx++)
72 {
73 octave_value parent = parents(idx);
74
75 if (! parent.is_object ())
76 error ("parents must be objects");
77 else
78 {
79 std::string cnm = parent.class_name ();
80
81 parent_list.push_back (cnm);
82
83 map.assign (cnm, parent);
84 }
85 }
86
87 load_path::add_to_parent_map (id, parent_list);
88 }
89
90 octave_base_value *
91 octave_class::find_parent_class (const std::string& parent_class_name)
92 {
93 octave_base_value* retval = 0;
94 std::string dbg_clsnm = class_name ();
95
96 if (parent_class_name == class_name ())
97 retval = this;
98 else
99 {
100 // Search in the list of immediate parents first, then in the
101 // ancestor tree.
102
103 std::list<std::string>::iterator
104 p = find (parent_list.begin (), parent_list.end (), parent_class_name);
105
106 if (p != parent_list.end ())
107 {
108 Octave_map::const_iterator pmap = map.seek (parent_class_name);
109
110 if (pmap != map.end ())
111 {
112 const Cell& tmp = pmap->second;
113
114 octave_value vtmp = tmp(0);
115
116 retval = vtmp.internal_rep ();
117 }
118 }
119 else
120 {
121 for (std::list<std::string>::iterator pit = parent_list.begin ();
122 pit != parent_list.end ();
123 pit++)
124 {
125 Octave_map::const_iterator smap = map.seek (*pit);
126
127 const Cell& tmp = smap->second;
128
129 octave_value vtmp = tmp(0);
130
131 octave_base_value *obvp = vtmp.internal_rep ();
132
133 retval = obvp->find_parent_class (parent_class_name);
134
135 if (retval)
136 break;
137 }
138 }
139 }
140
141 return retval;
142 }
143
65 Cell 144 Cell
66 octave_class::dotref (const octave_value_list& idx) 145 octave_class::dotref (const octave_value_list& idx)
67 { 146 {
68 Cell retval; 147 Cell retval;
69 148
70 assert (idx.length () == 1); 149 assert (idx.length () == 1);
71 150
151 // FIXME -- Is there a "proper" way to do this?
152 octave_function* fcn = octave_call_stack::current ();
153 std::string my_dir = fcn->dir_name ();
154 int ipos = my_dir.find_last_of ("@");
155 std::string method_class = my_dir.substr (ipos+1);
156
157 // Find the class in which this method resides before attempting to access
158 // the requested field.
159
160 octave_base_value *obvp = find_parent_class (method_class);
161
162 Octave_map my_map;
163
164 my_map = obvp ? obvp->map_value () : map;
165
72 std::string nm = idx(0).string_value (); 166 std::string nm = idx(0).string_value ();
73 167
74 Octave_map::const_iterator p = map.seek (nm); 168 Octave_map::const_iterator p = my_map.seek (nm);
75 169
76 if (p != map.end ()) 170 if (p != my_map.end ())
77 retval = map.contents (p); 171 retval = my_map.contents (p);
78 else 172 else
79 error ("class has no member `%s'", nm.c_str ()); 173 error ("class has no member `%s'", nm.c_str ());
80 174
81 return retval; 175 return retval;
82 } 176 }
1166 1260
1167 DEFUN (class, args, , 1261 DEFUN (class, args, ,
1168 "-*- texinfo -*-\n\ 1262 "-*- texinfo -*-\n\
1169 @deftypefn {Built-in Function} {} class (@var{expr})\n\ 1263 @deftypefn {Built-in Function} {} class (@var{expr})\n\
1170 @deftypefnx {Built-in Function} {} class (@var{s}, @var{id})\n\ 1264 @deftypefnx {Built-in Function} {} class (@var{s}, @var{id})\n\
1171 \n\ 1265 @deftypefnx {Built-in Function} {} class (@var{s}, @var{id}, @var{p}, @dots{})\n\
1172 Return the class of the expression @var{expr}, as a string or\n\ 1266 Return the class of the expression @var{expr} or create a class with\n\
1173 create a class object from the structure @var{s} with name @var{id}.\n\ 1267 fields from structure @var{s} and name (string) @var{id}. Additional\n\
1268 arguments name a list of parent classes from which the new class is\n\
1269 derived.\n\
1174 @end deftypefn") 1270 @end deftypefn")
1175 { 1271 {
1176 octave_value retval; 1272 octave_value retval;
1177 1273
1178 int nargin = args.length (); 1274 int nargin = args.length ();
1179 1275
1180 if (nargin == 1) 1276 if (nargin == 0)
1277 print_usage ();
1278 else if (nargin == 1)
1181 retval = args(0).class_name (); 1279 retval = args(0).class_name ();
1182 else if (nargin == 2) 1280 else
1183 { 1281 {
1184 Octave_map m = args(0).map_value (); 1282 Octave_map m = args(0).map_value ();
1185 1283
1186 if (! error_state) 1284 if (! error_state)
1187 { 1285 {
1190 if (! error_state) 1288 if (! error_state)
1191 { 1289 {
1192 octave_function *fcn = octave_call_stack::caller (); 1290 octave_function *fcn = octave_call_stack::caller ();
1193 1291
1194 if (fcn && fcn->is_class_constructor ()) 1292 if (fcn && fcn->is_class_constructor ())
1195 retval = octave_value (new octave_class (m, id)); 1293 {
1294 if (nargin == 2)
1295 retval = octave_value (new octave_class (m, id));
1296 else
1297 {
1298 octave_value_list parents = args.slice (2, nargin-2);
1299
1300 retval = octave_value (new octave_class (m, id, parents));
1301 }
1302 }
1196 else 1303 else
1197 error ("class: invalid call from outside class constructor"); 1304 error ("class: invalid call from outside class constructor");
1198 } 1305 }
1199 else 1306 else
1200 error ("class: expecting character string as second argument"); 1307 error ("class: expecting character string as second argument");
1201 } 1308 }
1202 else 1309 else
1203 error ("class: expecting structure as first argument"); 1310 error ("class: expecting structure as first argument");
1204 } 1311 }
1312
1313 return retval;
1314 }
1315
1316 DEFUN (__parent_classes__, args, ,
1317 "-*- texinfo -*-\n\
1318 @deftypefn {Built-in Function} {} __parent_classes__ (@var{x})\n\
1319 Undocumented internal function.\n\
1320 @end deftypefn")
1321 {
1322 octave_value retval = Cell ();
1323
1324 if (args.length () == 1)
1325 {
1326 octave_value arg = args(0);
1327
1328 if (arg.is_object ())
1329 retval = Cell (arg.parent_class_names ());
1330 }
1205 else 1331 else
1206 print_usage (); 1332 print_usage ();
1207 1333
1208 return retval; 1334 return retval;
1209 } 1335 }
1210
1211 1336
1212 DEFUN (isobject, args, , 1337 DEFUN (isobject, args, ,
1213 "-*- texinfo -*-\n\ 1338 "-*- texinfo -*-\n\
1214 @deftypefn {Built-in Function} {} isobject (@var{x})\n\ 1339 @deftypefn {Built-in Function} {} isobject (@var{x})\n\
1215 Return true if @var{x} is a class object.\n\ 1340 Return true if @var{x} is a class object.\n\