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 */