Mercurial > hg > octave-lyh
comparison src/pt-loop.cc @ 2982:20f5cec4f11c
[project @ 1997-05-16 03:29:26 by jwe]
author | jwe |
---|---|
date | Fri, 16 May 1997 03:30:14 +0000 |
parents | |
children | aa9d0c0e0458 |
comparison
equal
deleted
inserted
replaced
2981:38365813950d | 2982:20f5cec4f11c |
---|---|
1 /* | |
2 | |
3 Copyright (C) 1996, 1997 John W. Eaton | |
4 | |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with Octave; see the file COPYING. If not, write to the Free | |
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | |
21 */ | |
22 | |
23 #if defined (__GNUG__) | |
24 #pragma implementation | |
25 #endif | |
26 | |
27 #ifdef HAVE_CONFIG_H | |
28 #include <config.h> | |
29 #endif | |
30 | |
31 // Nonzero means we're breaking out of a loop or function body. | |
32 extern int breaking; | |
33 | |
34 // Nonzero means we're jumping to the end of a loop. | |
35 extern int continuing; | |
36 | |
37 // Nonzero means we're returning from a function. Global because it | |
38 // is also needed in tree-expr.cc. | |
39 extern int returning; | |
40 | |
41 #include "error.h" | |
42 #include "gripes.h" | |
43 #include "oct-map.h" | |
44 #include "oct-lvalue.h" | |
45 #include "ov.h" | |
46 #include "pt-arg-list.h" | |
47 #include "pt-cmd.h" | |
48 #include "pt-exp.h" | |
49 #include "pt-loop.h" | |
50 #include "pt-stmt.h" | |
51 #include "pt-walk.h" | |
52 | |
53 // Decide if it's time to quit a for or while loop. | |
54 static inline bool | |
55 quit_loop_now (void) | |
56 { | |
57 // Maybe handle `continue N' someday... | |
58 | |
59 if (continuing) | |
60 continuing--; | |
61 | |
62 bool quit = (error_state || returning || breaking || continuing); | |
63 | |
64 if (breaking) | |
65 breaking--; | |
66 | |
67 return quit; | |
68 } | |
69 | |
70 // While. | |
71 | |
72 tree_while_command::~tree_while_command (void) | |
73 { | |
74 delete expr; | |
75 delete list; | |
76 } | |
77 | |
78 void | |
79 tree_while_command::eval (void) | |
80 { | |
81 if (error_state) | |
82 return; | |
83 | |
84 if (! expr) | |
85 panic_impossible (); | |
86 | |
87 for (;;) | |
88 { | |
89 if (expr->is_logically_true ("while")) | |
90 { | |
91 if (list) | |
92 { | |
93 list->eval (); | |
94 | |
95 if (error_state) | |
96 { | |
97 eval_error (); | |
98 return; | |
99 } | |
100 } | |
101 | |
102 if (quit_loop_now ()) | |
103 break; | |
104 } | |
105 else | |
106 break; | |
107 } | |
108 } | |
109 | |
110 void | |
111 tree_while_command::eval_error (void) | |
112 { | |
113 if (error_state > 0) | |
114 ::error ("evaluating while command near line %d, column %d", | |
115 line (), column ()); | |
116 } | |
117 | |
118 void | |
119 tree_while_command::accept (tree_walker& tw) | |
120 { | |
121 tw.visit_while_command (*this); | |
122 } | |
123 | |
124 // For. | |
125 | |
126 tree_simple_for_command::~tree_simple_for_command (void) | |
127 { | |
128 delete expr; | |
129 delete list; | |
130 } | |
131 | |
132 inline void | |
133 tree_simple_for_command::do_for_loop_once (octave_lvalue& ult, | |
134 const octave_value& rhs, | |
135 bool& quit) | |
136 { | |
137 quit = false; | |
138 | |
139 ult.assign (octave_value::asn_eq, rhs); | |
140 | |
141 if (! error_state) | |
142 { | |
143 if (list) | |
144 { | |
145 list->eval (); | |
146 | |
147 if (error_state) | |
148 eval_error (); | |
149 } | |
150 } | |
151 else | |
152 eval_error (); | |
153 | |
154 quit = quit_loop_now (); | |
155 } | |
156 | |
157 #define DO_LOOP(arg) \ | |
158 do \ | |
159 { \ | |
160 for (int i = 0; i < steps; i++) \ | |
161 { \ | |
162 octave_value val (arg); \ | |
163 \ | |
164 bool quit = false; \ | |
165 \ | |
166 do_for_loop_once (ult, val, quit); \ | |
167 \ | |
168 if (quit) \ | |
169 break; \ | |
170 } \ | |
171 } \ | |
172 while (0) | |
173 | |
174 void | |
175 tree_simple_for_command::eval (void) | |
176 { | |
177 if (error_state) | |
178 return; | |
179 | |
180 octave_value rhs = expr->rvalue (); | |
181 | |
182 if (error_state || rhs.is_undefined ()) | |
183 { | |
184 eval_error (); | |
185 return; | |
186 } | |
187 | |
188 octave_lvalue ult = lhs->lvalue (); | |
189 | |
190 if (error_state) | |
191 { | |
192 eval_error (); | |
193 return; | |
194 } | |
195 | |
196 if (rhs.is_scalar_type ()) | |
197 { | |
198 bool quit = false; | |
199 | |
200 do_for_loop_once (ult, rhs, quit); | |
201 } | |
202 else if (rhs.is_matrix_type ()) | |
203 { | |
204 Matrix m_tmp; | |
205 ComplexMatrix cm_tmp; | |
206 | |
207 int nr; | |
208 int steps; | |
209 | |
210 if (rhs.is_real_matrix ()) | |
211 { | |
212 m_tmp = rhs.matrix_value (); | |
213 nr = m_tmp.rows (); | |
214 steps = m_tmp.columns (); | |
215 } | |
216 else | |
217 { | |
218 cm_tmp = rhs.complex_matrix_value (); | |
219 nr = cm_tmp.rows (); | |
220 steps = cm_tmp.columns (); | |
221 } | |
222 | |
223 if (rhs.is_real_matrix ()) | |
224 { | |
225 if (nr == 1) | |
226 DO_LOOP (m_tmp (0, i)); | |
227 else | |
228 DO_LOOP (m_tmp.extract (0, i, nr-1, i)); | |
229 } | |
230 else | |
231 { | |
232 if (nr == 1) | |
233 DO_LOOP (cm_tmp (0, i)); | |
234 else | |
235 DO_LOOP (cm_tmp.extract (0, i, nr-1, i)); | |
236 } | |
237 } | |
238 else if (rhs.is_string ()) | |
239 { | |
240 gripe_string_invalid (); | |
241 } | |
242 else if (rhs.is_range ()) | |
243 { | |
244 Range rng = rhs.range_value (); | |
245 | |
246 int steps = rng.nelem (); | |
247 double b = rng.base (); | |
248 double increment = rng.inc (); | |
249 | |
250 for (int i = 0; i < steps; i++) | |
251 { | |
252 double tmp_val = b + i * increment; | |
253 | |
254 octave_value val (tmp_val); | |
255 | |
256 bool quit = false; | |
257 | |
258 do_for_loop_once (ult, val, quit); | |
259 | |
260 if (quit) | |
261 break; | |
262 } | |
263 } | |
264 else if (rhs.is_map ()) | |
265 { | |
266 Octave_map tmp_val (rhs.map_value ()); | |
267 | |
268 for (Pix p = tmp_val.first (); p != 0; tmp_val.next (p)) | |
269 { | |
270 octave_value val = tmp_val.contents (p); | |
271 | |
272 bool quit = false; | |
273 | |
274 do_for_loop_once (ult, val, quit); | |
275 | |
276 if (quit) | |
277 break; | |
278 } | |
279 } | |
280 else | |
281 { | |
282 ::error ("invalid type in for loop expression near line %d, column %d", | |
283 line (), column ()); | |
284 } | |
285 } | |
286 | |
287 void | |
288 tree_simple_for_command::eval_error (void) | |
289 { | |
290 if (error_state > 0) | |
291 ::error ("evaluating for command near line %d, column %d", | |
292 line (), column ()); | |
293 } | |
294 | |
295 void | |
296 tree_simple_for_command::accept (tree_walker& tw) | |
297 { | |
298 tw.visit_simple_for_command (*this); | |
299 } | |
300 | |
301 tree_complex_for_command::~tree_complex_for_command (void) | |
302 { | |
303 delete expr; | |
304 delete list; | |
305 } | |
306 | |
307 void | |
308 tree_complex_for_command::do_for_loop_once (octave_lvalue &val_ref, | |
309 octave_lvalue &key_ref, | |
310 const octave_value& val, | |
311 const octave_value& key, | |
312 bool& quit) | |
313 { | |
314 quit = false; | |
315 | |
316 val_ref.assign (octave_value::asn_eq, val); | |
317 key_ref.assign (octave_value::asn_eq, key); | |
318 | |
319 if (! error_state) | |
320 { | |
321 if (list) | |
322 { | |
323 list->eval (); | |
324 | |
325 if (error_state) | |
326 eval_error (); | |
327 } | |
328 } | |
329 else | |
330 eval_error (); | |
331 | |
332 quit = quit_loop_now (); | |
333 } | |
334 | |
335 void | |
336 tree_complex_for_command::eval (void) | |
337 { | |
338 if (error_state) | |
339 return; | |
340 | |
341 octave_value rhs = expr->rvalue (); | |
342 | |
343 if (error_state || rhs.is_undefined ()) | |
344 { | |
345 eval_error (); | |
346 return; | |
347 } | |
348 | |
349 if (rhs.is_map ()) | |
350 { | |
351 // Cycle through structure elements. First element of id_list | |
352 // is set to value and the second is set to the name of the | |
353 // structure element. | |
354 | |
355 Pix p = lhs->first (); | |
356 tree_expression *elt = lhs->operator () (p); | |
357 octave_lvalue val_ref = elt->lvalue (); | |
358 | |
359 lhs->next (p); | |
360 elt = lhs->operator () (p); | |
361 octave_lvalue key_ref = elt->lvalue (); | |
362 | |
363 Octave_map tmp_val (rhs.map_value ()); | |
364 | |
365 for (p = tmp_val.first (); p != 0; tmp_val.next (p)) | |
366 { | |
367 octave_value key = tmp_val.key (p); | |
368 octave_value val = tmp_val.contents (p); | |
369 | |
370 bool quit = false; | |
371 | |
372 do_for_loop_once (key_ref, val_ref, key, val, quit); | |
373 | |
374 if (quit) | |
375 break; | |
376 } | |
377 } | |
378 else | |
379 error ("in statement `for [X, Y] = VAL', VAL must be a structure"); | |
380 } | |
381 | |
382 void | |
383 tree_complex_for_command::eval_error (void) | |
384 { | |
385 if (error_state > 0) | |
386 ::error ("evaluating for command near line %d, column %d", | |
387 line (), column ()); | |
388 } | |
389 | |
390 void | |
391 tree_complex_for_command::accept (tree_walker& tw) | |
392 { | |
393 tw.visit_complex_for_command (*this); | |
394 } | |
395 | |
396 /* | |
397 ;;; Local Variables: *** | |
398 ;;; mode: C++ *** | |
399 ;;; End: *** | |
400 */ |