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.vm;
22  
23  import org.millscript.commons.alert.Alert;
24  import org.millscript.commons.alert.AlertDecorator;
25  import org.millscript.commons.util.IList;
26  import org.millscript.commons.util.IMap;
27  import org.millscript.commons.util.MapIterator;
28  import org.millscript.millscript.alert.Output;
29  import org.millscript.millscript.conf.Configuration;
30  import org.millscript.millscript.datatypes.Binding;
31  import org.millscript.millscript.datatypes.DatabaseSource;
32  import org.millscript.millscript.datatypes.Fragment;
33  import org.millscript.millscript.datatypes.Image;
34  import org.millscript.millscript.datatypes.SpiceClass;
35  import org.millscript.millscript.datatypes.SpiceObject;
36  import org.millscript.millscript.datatypes.XmlComment;
37  import org.millscript.millscript.datatypes.XmlElement;
38  import org.millscript.millscript.functions.Function;
39  import org.millscript.millscript.functions.Page;
40  import org.millscript.millscript.tools.CastLibrary;
41  import org.millscript.millscript.tools.FormatPrint;
42  
43  import java.io.PrintWriter;
44  import java.util.Calendar;
45  import java.util.regex.Pattern;
46  
47  /**
48   * This class implements the MillScript machine.
49   */
50  public final class Machine extends BasicMachine implements AlertDecorator {
51  
52      /**
53       * This machines configuration.
54       */
55      private final Configuration config;
56  
57      /**
58       * Constructs a new machine with the specified configuration.
59       *
60       * @param c the configuration for this machine
61       */
62      public Machine( final Configuration c ) {
63          this.config = c;
64      }
65  
66      /**
67       * @see org.millscript.commons.alert.AlertDecorator#decorate(org.millscript.commons.alert.Alert)
68       */
69      public Alert decorate( final Alert alert ) {
70          final MapIterator it2 = this.doingList().iterator( true );
71          String current = null;
72          String peek = null;
73          if ( it2.hasNext() ) {
74              it2.nextValue().toString();        
75          }
76          while ( peek != null ) {
77              current = peek;
78              peek = null;
79              int count = 1;
80              while ( it2.hasNext() ) {
81                  peek = it2.nextValue().toString();
82                  if ( current.equals( peek ) ) {
83                      count++;
84                  } else {
85                      break;
86                  }
87              }
88              alert.culprit(
89                  "doing",
90                  Output.keepShort( current ) +
91                  ( count > 1 ? " * " + count : "" )
92              );
93          }
94          return alert;
95      }
96  
97      /**
98       * Returns this machines configuration.
99       *
100      * @return  this machines configuration
101      */
102     public Configuration getConfig() {
103         return config;
104     }
105 
106     /**
107      * Pops a regular expression Binding off the stack and returns it.
108      *
109      * @return  a Binding from the top of the stack
110      * @throws  AlertException  if the stack item cannot be cast to a Binding
111      */
112     public Binding popBinding() {
113         return CastLibrary.toBinding( this.popObject() );
114     }
115 
116     /**
117      * Pops a Boolean off the stack and returns it.
118      *
119      * @return  a Boolean from the top of the stack
120      * @throws  AlertException  if the stack item cannot be cast to a Boolean
121      */
122     public Boolean popBoolean() {
123         return CastLibrary.toBoolean( this.popObject() );
124     }
125 
126     /**
127      * Pops a Calendar off the stack and returns it.
128      *
129      * @return  a {@link java.util.Calendar} from the top of the stack
130      * @throws  AlertException  if the stack item cannot be cast to a Calendar
131      */
132     public Calendar popCalendar() {
133         return CastLibrary.toCalendar( this.popObject() );
134     }
135 
136     /**
137      * Pops a Character off the stack and returns it.
138      *
139      * @return  an {@link Character} from the top of the stack
140      * @throws  AlertException  if the stack item cannot be cast to a Character
141      */
142     public Character popCharacter() {
143         return CastLibrary.toCharacter( this.popObject() );
144     }
145 
146     /**
147      * Pops a DatabaseSource off the stack and returns it.
148      *
149      * @return  an {@link DatabaseSource} from the top of the stack
150      * @throws  AlertException  if the stack item cannot be cast to a
151      * DatabaseSource
152      */
153     public DatabaseSource popDatabaseSource() {
154         return CastLibrary.toDatabaseSource( this.popObject() );
155     }
156 
157     /**
158      * Pops a Fragment off the stack and returns it.
159      *
160      * @return  an {@link Fragment} from the top of the stack
161      * @throws  AlertException  if the stack item cannot be cast to a Fragment
162      */
163     public Fragment popFragment() {
164         return CastLibrary.toFragment( this.popObject() );
165     }
166 
167     /**
168      * Pops a Function off the stack and returns it.
169      *
170      * @return  an {@link Function} from the top of the stack
171      * @throws  AlertException  if the stack item cannot be cast to a Function
172      */
173     public Function popFunction() {
174         return CastLibrary.toFunction( this.popObject() );
175     }
176 
177     /**
178      * Pops a List off the stack and returns it.
179      *
180      * @return  an {@link IList} from the top of the stack
181      * @throws  AlertException  if the stack item cannot be cast to a List
182      */
183     public IList popIList() {
184         return CastLibrary.toIList( this.popObject() );
185     }
186 
187     /**
188      * Pops an Image off the stack and returns it.
189      *
190      * @return  an {@link Image} from the top of the stack
191      * @throws  AlertException  if the stack item cannot be cast to an Image
192      */
193     public Image popImage() {
194         return CastLibrary.toImage( this.popObject() );
195     }
196 
197     /**
198      * Pops a Map off the stack and returns it.
199      *
200      * @return  an {@link IMap} from the top of the stack
201      * @throws  AlertException  if the stack item cannot be cast to a
202      * MapWithDefault
203      */
204     public IMap popIMap() {
205         return CastLibrary.toIMap( this.popObject() );
206     }
207 
208     /**
209      * Pops an int off the stack and returns it.
210      *
211      * @return  an Integers int value from the top of the stack
212      * @throws  AlertException  if the stack item cannot be cast to an integer
213      */
214     public int popInt() {
215         return CastLibrary.toInt( this.popObject() );
216     }
217 
218     /**
219      * Pops an Integer off the stack and returns it.
220      *
221      * @return  an {@link Integer} from the top of the stack
222      * @throws  AlertException  if the stack item cannot be cast to an Integer
223      */
224     public Integer popInteger() {
225         return CastLibrary.toInteger( this.popObject() );
226     }
227 
228     /**
229      * Pops an object array off the stack and returns it.
230      *
231      * @return  a object array from the top of the stack
232      * @throws  AlertException  if the stack item cannot be cast to an object
233      * array
234      */
235     public Object[] popObjectArray() {
236         return CastLibrary.toObjectArray( this.popObject() );
237     }
238 
239     /**
240      * Pops a traditional regular expression Pattern off the stack and returns
241      * it.
242      *
243      * @return  a Pattern from the top of the stack
244      * @throws  AlertException  if the stack item cannot be cast to a Pattern
245      */
246     public Pattern popPattern() {
247         return CastLibrary.toPattern( this.popObject() );
248     }
249 
250     /**
251      * Pops a Spice Class off the stack and returns it.
252      *
253      * @return  an {@link org.millscript.millscript.datatypes.SpiceClass} from
254      * the top of the stack
255      * @throws  AlertException  if the stack item cannot be cast to a
256      * SpiceClass
257      */
258     public SpiceClass popSpiceClass() {
259         return CastLibrary.toSpiceClass( this.popObject() );
260     }
261 
262     /**
263      * Pops a Spice Object off the stack and returns it.
264      *
265      * @return  an {@link org.millscript.millscript.datatypes.SpiceObject} from
266      * the top of the stack
267      * @throws  AlertException  if the stack item cannot be cast to a
268      * SpiceObject
269      */
270     public SpiceObject popSpiceObject() {
271         return CastLibrary.toSpiceObject( this.popObject() );
272     }
273 
274     /**
275      * Pops a String off the stack and returns it.
276      *
277      * @return  an {@link String} from the top of the stack
278      * @throws  AlertException  if the stack item cannot be cast to a String
279      */
280     public String popString() {
281         return CastLibrary.toString( this.popObject() );
282     }
283 
284     /**
285      * Pops a URL off the stack and returns it.
286      *
287      * @return  an {@link org.millscript.millscript.functions.Page} from the
288      * top of the stack
289      * @throws  AlertException  if the stack item cannot be cast to a URL
290      */
291     public Page popURL() {
292         return CastLibrary.toURL( this.popObject() );
293     }
294 
295     /**
296      * Pops an XmlComment off the stack and returns it.
297      *
298      * @return  an {@link XmlComment} from the top of the stack
299      * @throws  AlertException  if the stack item cannot be cast to an
300      * XmlComment
301      */
302     public XmlComment popXmlComment() {
303         return CastLibrary.toXmlComment( this.popObject() );
304     }
305 
306     /**
307      * Pops an XmlElement off the stack and returns it.
308      *
309      * @return  an {@link XmlElement} from the top of the stack
310      * @throws  AlertException  if the stack item cannot be cast to an
311      * XmlElement
312      */
313     public XmlElement popXmlElement() {
314         return CastLibrary.toXmlElement( this.popObject() );
315     }
316 
317     /**
318      * Clears the value stack, optionally printing all the objects left on it.
319      * The remaining objects will only be printed if we are in an interactive
320      * mode, such as the interpreter.
321      *
322      * @param   interactive a boolean indicating if we are in an interactive
323      *                      mode
324      */
325     public void printResults( final boolean interactive ) {
326         int n = this.getCount();
327         if ( interactive || n > 0 ) {
328             System.out.print( "There " + ( n == 1 ? "is " : "are " ) + n + " result" );
329             System.out.println( n == 1 ? "" : "s" );
330             PrintWriter out = new PrintWriter( System.out, true );
331             for ( int i = 0; i < n; i++ ) {
332                 FormatPrint.show( out, this.getIndex( i ) );
333                 out.println( "" );
334             }
335         }
336         this.setCount( 0 );
337     }
338 
339 }