Mercurial > hg > octave-nkf
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\ |