View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2001-2004 Open World Ltd
4   //
5   // This file is part of MillScript.
6   //
7   // MillScript is free software; you can redistribute it and/or modify it under
8   // the terms of the GNU General Public License as published by the Free
9   // Software Foundation; either version 2 of the License, or (at your option)
10  // any later version.
11  //
12  // MillScript 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 for
15  // more details.
16  //
17  // You should have received a copy of the GNU General Public License along with
18  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
19  // Place, Suite 330, Boston, MA  02111-1307  USA
20  ////////////////////////////////////////////////////////////////////////////////
21  package org.millscript.millscript.action;
22  
23  import org.millscript.millscript.vm.Machine;
24  
25  /**
26   * This class represents a For loop action. A for loop action may contain
27   * multiple condition/binding expressions and a single body expression. The
28   * loop conditions are represented as ForIterators, which produce and bind
29   * values as necessary. When the condition produces no more values, a check is
30   * made to see if the condition terminates the loop and it's terminate action is
31   * executed accordingly.
32   *
33   * @see ForConditionAction.ForIterator
34   */
35  public final class ForAction extends Action {
36  
37      /**
38       * The number of condition/binding expressions for this loop.
39       */
40      private int numberOfBindings;
41  
42      /**
43       * The array of for loop condition actions(including bindings) in the order
44       * they should be executed.
45       */
46      private ForConditionAction[] bindings;
47  
48      /**
49       * The body action.
50       */
51      private Action body;
52  
53      /**
54       * Constructs a new for loop action, with the supplied conditon and body
55       * actions.
56       *
57       * @param   x   array of for loop condition actions
58       * @param   b   the for loop body action
59       */
60      public ForAction( final ForConditionAction[] x, final Action b ) {
61          numberOfBindings = x.length;
62          bindings = x;
63          body = b;
64      }
65  
66      /**
67       * @see org.millscript.millscript.action.Action#action(org.millscript.millscript.vm.Machine)
68       */
69      @Override
70      public void action( final Machine mc ) {
71  
72          // Build an array of for loop iterators, for this for loops conditions
73          ForConditionAction.ForIterator[] enums = new ForConditionAction.ForIterator[ numberOfBindings ];
74          for ( int i = 0; i < numberOfBindings; i++ ) {
75              enums[ i ] = bindings[ i ].getForIterator( mc );
76          }
77  
78          main_loop:
79          for (;;) {
80              mc.startSaving();
81              for ( int i = 0; i < numberOfBindings; i++ ) {
82                 ForConditionAction.ForIterator it = enums[ i ];
83                  // If the iterator has another item, bind it and continue, else
84                  // check if the iterator terminates the loop.
85                  if ( it.hasNext() ) {
86                      // The current for condition is a binding condition, so
87                      // perform the binding.
88                      it.bindAction( mc );
89                  } else if ( it.terminatesLoop() ) {
90                      // The iterator has no more items and it terminates the
91                      // loop, so restore the saved refs and break out of the
92                      // loop.
93                      it.terminateAction( mc );
94                      mc.restoreSaved();
95                      break main_loop;
96                  } else {
97                      // The iterator had no more items and it didn't terminate
98                      // the loop, so continue to the next iteration.
99                      mc.restoreSaved();
100                     continue main_loop;
101                 }
102             }
103             body.act( mc );
104             mc.restoreSaved();
105         }
106     }
107 }