X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Floop.c;h=ebe5ed2257a1f9eaff83b804b8a5b9933296281e;hb=f62199cac6213ed1c03ffe48450a583da0fadc68;hp=1ccd1a5631f69faab42ba0452c1d17f0565e27b4;hpb=fcb9e49b2a2d57af7c001ae5d2eda9ac443ba36b;p=pspp-builds.git diff --git a/src/loop.c b/src/loop.c index 1ccd1a56..ebe5ed22 100644 --- a/src/loop.c +++ b/src/loop.c @@ -18,21 +18,22 @@ 02111-1307, USA. */ #include -#include +#include "error.h" #include "alloc.h" -#include "approx.h" +#include "case.h" #include "command.h" +#include "dictionary.h" #include "do-ifP.h" #include "error.h" #include "expr.h" #include "lexer.h" +#include "misc.h" #include "settings.h" #include "str.h" #include "var.h" #include "debug-print.h" -/* *INDENT-OFF* */ /* LOOP strategy: Each loop causes 3 different transformations to be output. The @@ -43,42 +44,40 @@ transformation to -1. This ensures that the pass number is set to -1 every time the loop is encountered, before the first iteration. - The second transformation increments the pass number. If there is - no indexing or test clause on either LOOP or END LOOP, then the - pass number is checked against MXLOOPS and control may pass out of - the loop; otherwise the indexing or test clause(s) on LOOP are - checked, and again control may pass out of the loop. + The second transformation increments the pass number. If + there is no indexing or test clause on either LOOP or END + LOOP, then the pass number is checked against MXLOOPS and + control may pass out of the loop. Otherwise the indexing or + test clause(s) on LOOP are checked, and again control may pass + out of the loop. - After the second transformation the body of the loop is executed. + After the second transformation the body of the loop is + executed. The last transformation checks the test clause if present and - either jumps back up to the second transformation or terminates the - loop. - - Flow of control: (The characters ^V<> represents arrows.) - - 1. LOOP (sets pass # to -1) - V - V - >>2. LOOP (increment pass number) - ^ (test optional indexing clause) - ^ (test optional IF clause) - ^ if we need another trip if we're done with the loop>>V - ^ V V - ^ V V - ^ *. execute loop body V - ^ . V - ^ . (any number of transformations) V - ^ . V - ^ V - ^ 3. END LOOP (test optional IF clause) V - ^<<<>V - V - V - *. transformations after loop body<<<<<<<<<<<<<<<<<<<<<<<<<<< + either jumps back up to the second transformation or + terminates the loop. + + Flow of control: + + 1. LOOP. Sets pass number to -1 and continues to next + transformation. + + 2. LOOP. Increments pass number. Tests optional indexing + clause and optional IF clause. If we're done with the + loop, we jump to the transformation just after LOOP + transformation 3. + Otherwise, we continue through the transformations in the + loop body. + + 3. END LOOP. We test the optional IF clause. If we need to + make another pass through the loop, we jump to LOOP + transformation 2. + + Otherwise, we continue with the transformation jump after + the loop. */ -/* *INDENT-ON* */ /* Types of limits on loop execution. */ enum @@ -140,13 +139,9 @@ static struct loop_3_trns *thr; static int internal_cmd_loop (void); static int internal_cmd_end_loop (void); -static int break_trns_proc (struct trns_header *, struct ccase *); -static int loop_1_trns_proc (struct trns_header *, struct ccase *); -static void loop_1_trns_free (struct trns_header *); -static int loop_2_trns_proc (struct trns_header *, struct ccase *); -static void loop_2_trns_free (struct trns_header *); -static int loop_3_trns_proc (struct trns_header *, struct ccase *); -static void loop_3_trns_free (struct trns_header *); +static trns_proc_func break_trns_proc; +static trns_proc_func loop_1_trns_proc, loop_2_trns_proc, loop_3_trns_proc; +static trns_free_func loop_1_trns_free, loop_2_trns_free, loop_3_trns_free; static void pop_ctl_stack (void); /* LOOP. */ @@ -173,8 +168,6 @@ internal_cmd_loop (void) /* Name of indexing variable if applicable. */ char name[9]; - lex_match_id ("LOOP"); - /* Create and initialize transformations to facilitate error-handling. */ two = xmalloc (sizeof *two); @@ -192,7 +185,7 @@ internal_cmd_loop (void) /* Parse indexing clause. */ if (token == T_ID && lex_look_ahead () == '=') { - struct variable *v = find_variable (tokid); + struct variable *v = dict_lookup_var (default_dict, tokid); two->flags |= LPC_INDEX; @@ -207,7 +200,7 @@ internal_cmd_loop (void) assert (token == '='); lex_get (); - one->init = expr_parse (PXP_NUMERIC); + one->init = expr_parse (EXPR_NUMERIC); if (!one->init) return 0; @@ -216,7 +209,7 @@ internal_cmd_loop (void) expr_free (one->init); return 0; } - one->term = expr_parse (PXP_NUMERIC); + one->term = expr_parse (EXPR_NUMERIC); if (!one->term) { expr_free (one->init); @@ -225,7 +218,7 @@ internal_cmd_loop (void) if (lex_match (T_BY)) { - one->incr = expr_parse (PXP_NUMERIC); + one->incr = expr_parse (EXPR_NUMERIC); if (!one->incr) return 0; } @@ -238,7 +231,7 @@ internal_cmd_loop (void) { two->flags |= LPC_COND; - two->cond = expr_parse (PXP_BOOLEAN); + two->cond = expr_parse (EXPR_BOOLEAN); if (!two->cond) return 0; } @@ -252,14 +245,9 @@ internal_cmd_loop (void) /* Find variable; create if necessary. */ if (name[0]) { - two->index = find_variable (name); + two->index = dict_lookup_var (default_dict, name); if (!two->index) - { - two->index = force_create_variable (&default_dict, name, NUMERIC, 0); -#if DEBUGGING - envector (two->index); -#endif - } + two->index = dict_create_var (default_dict, name, 0); } /* Push on control stack. */ @@ -273,15 +261,6 @@ internal_cmd_loop (void) add_transformation ((struct trns_header *) one); add_transformation ((struct trns_header *) two); -#if DEBUGGING - printf ("LOOP"); - if (two->flags & LPC_INDEX) - printf ("(INDEX)"); - if (two->flags & LPC_COND) - printf ("(IF)"); - printf ("\n"); -#endif - return 1; } @@ -327,7 +306,7 @@ internal_cmd_end_loop (void) /* Parse the expression if any. */ if (lex_match_id ("IF")) { - thr->cond = expr_parse (PXP_BOOLEAN); + thr->cond = expr_parse (EXPR_BOOLEAN); if (!thr->cond) return 0; } @@ -342,19 +321,13 @@ internal_cmd_end_loop (void) /* Pop off the top of stack. */ ctl_stack = ctl_stack->down; -#if DEBUGGING - printf ("END LOOP"); - if (thr->cond) - printf ("(IF)"); - printf ("\n"); -#endif - return 1; } /* Performs transformation 1. */ static int -loop_1_trns_proc (struct trns_header * trns, struct ccase * c) +loop_1_trns_proc (struct trns_header * trns, struct ccase * c, + int case_num) { struct loop_1_trns *one = (struct loop_1_trns *) trns; struct loop_2_trns *two = one->two; @@ -364,20 +337,19 @@ loop_1_trns_proc (struct trns_header * trns, struct ccase * c) { union value t1, t2, t3; - expr_evaluate (one->init, c, &t1); + expr_evaluate (one->init, c, case_num, &t1); if (one->incr) - expr_evaluate (one->incr, c, &t2); + expr_evaluate (one->incr, c, case_num, &t2); else t2.f = 1.0; - expr_evaluate (one->term, c, &t3); + expr_evaluate (one->term, c, case_num, &t3); /* Even if the loop is never entered, force the index variable to assume the initial value. */ - c->data[two->index->fv].f = t1.f; + case_data_rw (c, two->index->fv)->f = t1.f; /* Throw out various pathological cases. */ - if (!finite (t1.f) || !finite (t2.f) || !finite (t3.f) - || approx_eq (t2.f, 0.0)) + if (!finite (t1.f) || !finite (t2.f) || !finite (t3.f) || t2.f == 0.0) return two->loop_term; debug_printf (("LOOP %s=%g TO %g BY %g.\n", two->index->name, t1.f, t3.f, t2.f)); @@ -387,7 +359,7 @@ loop_1_trns_proc (struct trns_header * trns, struct ccase * c) two->flags &= ~LPC_RINDEX; /* incr>0 but init>term */ - if (approx_gt (t1.f, t3.f)) + if (t1.f > t3.f) return two->loop_term; } else @@ -396,7 +368,7 @@ loop_1_trns_proc (struct trns_header * trns, struct ccase * c) two->flags |= LPC_RINDEX; /* incr<0 but initloop_term; } @@ -421,7 +393,8 @@ loop_1_trns_free (struct trns_header * trns) /* Performs transformation 2. */ static int -loop_2_trns_proc (struct trns_header * trns, struct ccase * c) +loop_2_trns_proc (struct trns_header * trns, struct ccase * c, + int case_num UNUSED) { struct loop_2_trns *two = (struct loop_2_trns *) trns; @@ -429,7 +402,7 @@ loop_2_trns_proc (struct trns_header * trns, struct ccase * c) if (two->flags == 0) { two->pass++; - if (two->pass > set_mxloops) + if (two->pass > get_mxloops() ) return two->loop_term; } @@ -437,11 +410,11 @@ loop_2_trns_proc (struct trns_header * trns, struct ccase * c) if (two->flags & LPC_RINDEX) { /* Test if we're at the end of the looping. */ - if (approx_lt (two->curr, two->term)) + if (two->curr < two->term) return two->loop_term; /* Set the current value into the case. */ - c->data[two->index->fv].f = two->curr; + case_data_rw (c, two->index->fv)->f = two->curr; /* Decrement the current value. */ two->curr += two->incr; @@ -450,11 +423,11 @@ loop_2_trns_proc (struct trns_header * trns, struct ccase * c) else if (two->flags & LPC_INDEX) { /* Test if we're at the end of the looping. */ - if (approx_gt (two->curr, two->term)) + if (two->curr > two->term) return two->loop_term; /* Set the current value into the case. */ - c->data[two->index->fv].f = two->curr; + case_data_rw (c, two->index->fv)->f = two->curr; /* Increment the current value. */ two->curr += two->incr; @@ -462,7 +435,7 @@ loop_2_trns_proc (struct trns_header * trns, struct ccase * c) /* Conditional clause limiter. */ if ((two->flags & LPC_COND) - && expr_evaluate (two->cond, c, NULL) != 1.0) + && expr_evaluate (two->cond, c, case_num, NULL) != 1.0) return two->loop_term; return -1; @@ -479,13 +452,14 @@ loop_2_trns_free (struct trns_header * trns) /* Performs transformation 3. */ static int -loop_3_trns_proc (struct trns_header * trns, struct ccase * c) +loop_3_trns_proc (struct trns_header * trns, struct ccase * c, + int case_num) { struct loop_3_trns *thr = (struct loop_3_trns *) trns; /* Note that it breaks out of the loop if the expression is true *or missing*. This is conformant. */ - if (thr->cond && expr_evaluate (two->cond, c, NULL) != 0.0) + if (thr->cond && expr_evaluate (two->cond, c, case_num, NULL) != 0.0) return -1; return thr->loop_start; @@ -512,8 +486,6 @@ cmd_break (void) /* New transformation. */ struct break_trns *t; - lex_match_id ("BREAK"); - for (loop = ctl_stack; loop; loop = loop->down) if (loop->type == CST_LOOP) break; @@ -538,7 +510,8 @@ cmd_break (void) } static int -break_trns_proc (struct trns_header * trns, struct ccase * c unused) +break_trns_proc (struct trns_header * trns, struct ccase * c UNUSED, + int case_num UNUSED) { return ((struct break_trns *) trns)->loop_term; }