starting to look like it works
[pspp] / src / language / control / loop.c
index 604af4556940bb2156c0048ce641b17d0cd73579..f081c761c78f01e2b596194eb9810930567fd166 100644 (file)
@@ -51,12 +51,12 @@ struct loop_trns
     struct expression *end_loop_condition;
 
     /* Inner transformations. */
-    struct transformation *xforms;
-    size_t n_xforms;
+    struct trns_chain xforms;
   };
 
-static trns_proc_func loop_trns_proc;
-static trns_free_func loop_trns_free;
+static struct trns_class loop_trns_class;
+
+static int in_loop;
 
 static bool parse_if_clause (struct lexer *, struct dataset *,
                              struct expression **);
@@ -83,6 +83,7 @@ cmd_loop (struct lexer *lexer, struct dataset *ds)
   lex_end_of_command (lexer);
 
   proc_push_transformations (ds);
+  in_loop++;
   for (;;)
     {
       if (lex_token (lexer) == T_STOP)
@@ -100,18 +101,37 @@ cmd_loop (struct lexer *lexer, struct dataset *ds)
       else
         cmd_parse_in_state (lexer, ds, CMD_STATE_NESTED);
     }
-  proc_pop_transformations (ds, &loop->xforms, &loop->n_xforms);
+  in_loop--;
+  proc_pop_transformations (ds, &loop->xforms);
+  printf ("%zu loop transvformations\n", loop->xforms.n);
 
-  add_transformation (ds, loop_trns_proc, loop_trns_free, loop);
+  add_transformation (ds, &loop_trns_class, loop);
 
   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
 }
 
+static enum trns_result
+break_trns_proc (void *aux UNUSED, struct ccase **c UNUSED,
+                 casenumber case_num UNUSED)
+{
+  return TRNS_BREAK;
+}
+
 /* Parses BREAK. */
 int
-cmd_break (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
+cmd_break (struct lexer *lexer UNUSED, struct dataset *ds)
 {
-  //add_transformation (ds, break_trns_proc, NULL, NULL);
+  if (!in_loop)
+    {
+      msg (SE, _("BREAK cannot appear outside LOOP...END LOOP."));
+      return CMD_FAILURE;
+    }
+
+  static const struct trns_class trns_class = {
+    .name = "BREAK",
+    .execute = break_trns_proc
+  };
+  add_transformation (ds, &trns_class, NULL);
 
   return CMD_SUCCESS;
 }
@@ -221,15 +241,14 @@ loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num)
   else
     cur = by = last = 0.0;
 
-  int max_pass = loop->index_var ? settings_get_mxloops () : -1;
-  for (int i = 0; max_pass < 0 || i < max_pass; i++)
+  for (int i = 0; loop->index_var || i < settings_get_mxloops (); i++)
     {
+      printf ("loop %g %g %g\n", cur, by, last);
       if (loop->loop_condition
           && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
         break;
 
-      enum trns_result r = transformations_execute (
-        loop->xforms, loop->n_xforms, c, case_num);
+      enum trns_result r = trns_chain_execute (&loop->xforms, case_num, c);
       if (r != TRNS_CONTINUE)
         return r == TRNS_BREAK ? TRNS_CONTINUE : r;
 
@@ -263,8 +282,14 @@ loop_trns_free (void *loop_)
   expr_free (loop->loop_condition);
   expr_free (loop->end_loop_condition);
 
-  transformations_destroy (loop->xforms, loop->n_xforms);
+  trns_chain_uninit (&loop->xforms);
 
   free (loop);
   return true;
 }
+
+static struct trns_class loop_trns_class = {
+  .name = "LOOP",
+  .execute = loop_trns_proc,
+  .destroy = loop_trns_free,
+};