1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 }