Source code for /engineering/autohit-2003/src/autohit/creator/compiler/SimCompiler.javaOriginal file SimCompiler.java
   1 /**
   2  * AUTOHIT 2003
   3  * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
   4  * 
   5  * This program is free software; you can redistribute it and/or modify 
   6  * it under the terms of the GNU General Public License as published by 
   7  * the Free Software Foundation; either version 2 of the License, or (at
   8  * your option) any later version.
   9  * This program is distributed in the hope that it will be useful, but
  10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12  * more details.
  13  * 
  14  * You should have received a copy of the GNU General Public License along
  15  * with this program; if not, write to the Free Software Foundation, Inc.,
  16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17  *
  18  * Additional license information can be found in the documentation.
  19  * @author Erich P Gatejen
  20  */
  21 package autohit.creator.compiler;
  22 
  23 //import org.apache.commons.collections.ExtendedProperties;
  24 import java.util.HashMap;
  25 import java.util.ListIterator;
  26 import java.util.Stack;
  27 
  28 import org.w3c.dom.CharacterData;
  29 import org.w3c.dom.Document;
  30 import org.w3c.dom.Element;
  31 import org.w3c.dom.Node;
  32 import org.w3c.dom.NodeList;
  33 
  34 import autohit.common.AutohitErrorCodes;
  35 import autohit.common.NOPair;
  36 import autohit.common.NVPair;
  37 import autohit.creator.SimLanguage;
  38 import autohit.server.SystemContext;
  39 import autohit.vm.VMExecutableWrapper;
  40 import autohit.vm.i.VMICall;
  41 import autohit.vm.i.VMIMethod;
  42 import autohit.vm.i.VMIClear;
  43 import autohit.vm.i.VMIEval;
  44 import autohit.vm.i.VMIExec;
  45 import autohit.vm.i.VMIFault;
  46 import autohit.vm.i.VMIFetch;
  47 import autohit.vm.i.VMIGoto;
  48 import autohit.vm.i.VMIIf;
  49 import autohit.vm.i.VMIJump;
  50 import autohit.vm.i.VMILoad;
  51 import autohit.vm.i.VMIMath;
  52 import autohit.vm.i.VMIMerge;
  53 import autohit.vm.i.VMINew;
  54 import autohit.vm.i.VMINop;
  55 import autohit.vm.i.VMIRScope;
  56 import autohit.vm.i.VMIReduce;
  57 import autohit.vm.i.VMIRight;
  58 import autohit.vm.i.VMIScope;
  59 import autohit.vm.i.VMIStore;
  60 import autohit.vm.i.VMISubr;
  61 import autohit.vm.i.VMIAssert;
  62 
  63 /**
  64  * This is the a Sim compiler.  It will compile xml documents that conform
  65  * to the "%autohit.dtd.location%/sim.dtd" dtd into a Sim object.
  66  * <p>
  67  * WARNING!!!  For the compiler to work, the sim.dtd must be at the location
  68  * specified in the system property autohit.dtd.location.
  69  * <p>
  70  * The private methods translate Token() matches the textual tokens, as defined in the
  71  * dtd to numerics that are used by the rest of the compiler.  Any new tokens
  72  * need to be added to that method.
  73  * <p>
  74  * I can think of several more elegant approaches to making this compiler, but until the
  75  * XML parsers settle a bit, I'm not going to bother...  
  76  * <p>
  77  * IMPORTANT NOTE!!!!  The XML parser WITH DTD ensure instructions are
  78  * coded in the proper order.  ALL of the code below assumes this!!!
  79  * If instructions come out of order or in disallowed places 
  80  * (like a seek outside of a get), I GUARANTEE you'll get a runaway 
  81  * compiler...
  82  * <p>
  83  * Logging will be done to the autohit.creator.sim namespace.  It is set for
  84  * pretty and 
  85  *
  86  * @author Erich P. Gatejen
  87  * @version 1.1
  88  * <i>Version History</i>
  89  * <code>EPG - Initial - 14Apr03<br>
  90  * EPG - Update to add goto and references - 13Jul03</code> 
  91  * 
  92  */
  93 public class SimCompiler extends XmlCompiler implements SimLanguage {
  94 
  95 	private final static String DTD_NAME = "sim.dtd";
  96 	private final static String MY_TYPE_OF_EXEC = "sim1";
  97 
  98 	// We'll do subtractive compares for IF.  This might change.
  99 
 100 	// Lexical elements and attriutes
 101 
 102 	// parse tokens
 103 
 104 	/**
 105 	 *  The work-in-progress object code
 106 	 */
 107 	protected VMExecutableWrapper ob;
 108 
 109 	/**
 110 	 *  Symbol table for lookups
 111 	 */
 112 	protected HashMap symboltable;
 113 
 114 	/**
 115 	 *  Stack for fixups
 116 	 */
 117 	protected Stack fixupstack;
 118 
 119 	/**
 120 	 *  Local name - UID
 121 	 */
 122 	private String localname = "UNKNOWN";
 123 
 124 	
 125 	/**
 126 	 *  Default Constructor.  This is the only and default constructor.
 127 	 *
 128 	 *  @throws Exception any exception invalidates the compiler.
 129 	 */
 130 	public SimCompiler() throws Exception {
 131 		super();
 132 
 133 	}
 134 
 135 	/**
 136 	 *  Constructor.  This is the only and default constructor.
 137 	 *
 138 	 *  @throws Exception any exception invalidates the compiler.
 139 	 */
 140 	public SimCompiler(SystemContext sc) throws Exception {
 141 		super(DTD_NAME, sc);
 142 	}
 143 
 144 	/**
 145 	 * Compile the xml tree into an VMExecutable object.
 146 	 * 
 147 	 * We will create a new log for each run, so that we can uniquely
 148 	 * identify them.
 149 	 *
 150 	 * @param xd   A parsed XML document.
 151 	 * @return a reference to the target object, in this case it will be a VMExecutableWrapper, or null if it failed.
 152 	 * @see autohit.vm.VMExecutableWrapper
 153 	 */
 154 	public Object build(Document xd) {
 155 
 156 		int idx;
 157 		NodeList rootChildren;
 158 		Element itemTree = null;
 159 		Element codeTree = null;
 160 		int numNodes;
 161 		Node scratchNode;
 162 		String scratchString;
 163 
 164 		// Any exception or verification check aborts the compile
 165 		try {
 166 
 167 			// Ok, build our working Sim object
 168 			ob = new VMExecutableWrapper();
 169 			ob.create();
 170 
 171 			// Create our symbol table and fixup stack
 172 			symboltable = new HashMap();
 173 			fixupstack = new Stack();
 174 
 175 			// set defaults attributes
 176 			ob.exec.major = 0;
 177 
 178 			// set any default attributes
 179 			ob.exec.type = MY_TYPE_OF_EXEC;
 180 			ob.exec.minor = 0;
 181 			ob.exec.output = null; // assume there is nothign to return
 182 
 183 			// Get the root element and normalize
 184 			Element root = (Element) xd.getDocumentElement();
 185 			root.normalize();
 186 
 187 			// Peal out the <info> and <code> sub-trees
 188 			rootChildren = (NodeList) root.getChildNodes();
 189 			numNodes = rootChildren.getLength();
 190 			while (numNodes > 0) {
 191 				scratchNode = rootChildren.item(numNodes - 1);
 192 				if (scratchNode instanceof Element) {
 193 					scratchString = scratchNode.getNodeName();
 194 					if (scratchString.charAt(0) == 'i') {
 195 						itemTree = (Element) scratchNode;
 196 					} else if (scratchString.charAt(0) == 'c') {
 197 						codeTree = (Element) scratchNode;
 198 					}
 199 				}
 200 				numNodes--;
 201 			}
 202 
 203 			if (itemTree == null) {
 204 				runtimeError("Missing infomation <info> block.");
 205 			}
 206 
 207 			if (codeTree == null) {
 208 				runtimeError("Missing infomation <code> block.");
 209 				throw new Exception();
 210 			}
 211 
 212 			// Deal with the <info> tree
 213 			NodeList itemTreeChildren = itemTree.getChildNodes();
 214 			for (idx = 0; idx < itemTreeChildren.getLength(); idx++) {
 215 				scratchNode = itemTreeChildren.item(idx);
 216 
 217 				// pull only Elements
 218 				if (scratchNode instanceof Element) {
 219 					processItem((Element) scratchNode);
 220 				}
 221 
 222 			}
 223 
 224 			// Deal with the <code> tree
 225 			// Basicall, I'm gonna go wtih recursion.  I don't think it should
 226 			// get very deep.   
 227 			try {
 228 				processCode(codeTree);
 229 
 230 				// Put a NOP on the end of the executable
 231 				ob.emit(new VMINop());
 232 				ob.clean();
 233 
 234 				// fixup goto symbols
 235 				ListIterator li = fixupstack.listIterator();
 236 				VMIGoto jcandidate;
 237 				NOPair nocandidate;
 238 				Integer currentgoto;
 239 				while (li.hasNext()) {
 240 					nocandidate = (NOPair) li.next();
 241 					if (symboltable.containsKey(nocandidate.n)) {
 242 						jcandidate = (VMIGoto) nocandidate.o;
 243 						currentgoto = (Integer) symboltable.get(nocandidate.n);
 244 						jcandidate.t = currentgoto.intValue();
 245 						runtimeDebug(
 246 							"Fixup GOTO for label="
 247 								+ nocandidate.n
 248 								+ " target="
 249 								+ jcandidate.t);
 250 					} else {
 251 						runtimeError(
 252 							"Broken GOTO.  No label for "
 253 								+ nocandidate.n
 254 								+ ".");
 255 					}
 256 				}
 257 
 258 			} catch (Exception e) {
 259 				// an otherwise uncaught exception.  A runaway compiler...
 260 				runtimeError("FATAL ERROR.  Runaway compilation errors.  Stopping compile.");
 261 				ob = null;
 262 			}
 263 
 264 		} catch (Exception e) {
 265 			myLog.error(
 266 				"CRITICAL ERROR encountered.  Stopping compile of " + localname + ".  "
 267 					+ e.toString(),
 268 				AutohitErrorCodes.CODE_COMPILE_ERROR);
 269 			myLog.error(e.toString());
 270 			ob = null; // leave the objectCode as null;
 271 		}
 272 
 273 		// ditch data as it falls out of scope
 274 		symboltable = null;
 275 		fixupstack = null;
 276 
 277 		// clean up logs
 278 		int err = numberErrors();
 279 		runtimeLog.error("Total errors for " + localname + " : " + err);
 280 		runtimeLog.warning("Total errors for " + localname + " : " + numberWarnings());
 281 		if (err > 0) {
 282 			runtimeLog.info("COMPILE FAILED  " + localname + " DUE TO ERRORS.");
 283 			ob = null;
 284 		}
 285 		return ob;
 286 	}
 287 
 288 	/**
 289 	 *  Processes info section tags. 
 290 	 */
 291 	private void processItem(Element en) throws Exception {
 292 		String tempText;
 293 		String name;
 294 		//runtimeDebug("ENTER --- " + en.getTagName());
 295 		name = en.getTagName().toLowerCase();
 296 		NodeList itemTreeChildren;
 297 		int idx;
 298 		Node sNode;
 299 
 300 		// Parse the token and call a handler
 301 		if (name.charAt(0) == 'n') {
 302 			if (name.charAt(1) == 'a') {
 303 				//NAME
 304 				tempText = getText(en.getFirstChild());
 305 				if (tempText == null) {
 306 					runtimeError("Empty <name> tag.");
 307 				} else {
 308 					ob.exec.name = tempText;
 309 					runtimeDebug("TAG <name> name= " + ob.exec.name);
 310 				}
 311 				// optional uid attribute
 312 				if (en.hasAttribute(ATTR_UID)) {
 313 					ob.exec.uid = en.getAttribute(ATTR_UID);
 314 					localname = ob.exec.uid;
 315 					runtimeDebug("TAG <name> uid= " + ob.exec.uid);
 316 				}
 317 			} else {
 318 				// NOTE - optional
 319 				tempText = getText(en.getFirstChild());
 320 				ob.exec.note = tempText;
 321 			}
 322 		} else if (name.charAt(0) == 'v') {
 323 			// VERSION
 324 			ob.exec.major = 0;
 325 			try {
 326 				if (en.hasAttribute(ATTR_VERSIONNUMBER)) {
 327 					tempText = en.getAttribute(ATTR_VERSIONNUMBER);
 328 					ob.exec.major = Integer.parseInt(tempText);
 329 					runtimeDebug("TAG <version> num= " + ob.exec.major);
 330 				} else {
 331 					runtimeError("ERROR: TAG<version> Attr num not present.");
 332 				}
 333 			} catch (Exception e) {
 334 				runtimeError("ERROR: TAG<version> Could not parse value for Attr num.");
 335 			}
 336 
 337 		} else if (name.charAt(0) == 'i') {
 338 			if (name.charAt(1) == 'o') {
 339 				// IO - Recurse with it's children.
 340 				itemTreeChildren = en.getChildNodes();
 341 				for (idx = 0; idx < itemTreeChildren.getLength(); idx++) {
 342 					sNode = itemTreeChildren.item(idx);
 343 					if (sNode instanceof Element) {
 344 						processItem((Element) sNode);
 345 					}
 346 				}
 347 			} else {
 348 				// INPUT - NOT SUPPORTED
 349 			}
 350 
 351 		} else if (name.charAt(0) == 'b') {
 352 			// BUFFER - NOT SUPPORTED
 353 
 354 		} else if (name.charAt(0) == 'o') {
 355 			ob.exec.output = new NVPair();
 356 			// OUTPUT - Specifies the output variable
 357 			ob.exec.output.name = en.getAttribute(ATTR_NAME);
 358 			if (en.hasAttribute(ATTR_TYPE)) {
 359 				ob.exec.output.value = en.getAttribute(ATTR_TYPE);
 360 			}
 361 
 362 		} else {
 363 			runtimeError(
 364 				"Software Detected Fault: creator.compiler.SimCompiler.processItem().  The textual token ["
 365 					+ en.getNodeName()
 366 					+ "] should have NOT reached this code. Check the XML DTD associated with the SimCompiler.");
 367 			throw (
 368 				new Exception("Software Detected Fault in creator.compiler.SimCompiler.processItem()."));
 369 		}
 370 
 371 		//DEBUG
 372 		//runtimeDebug("EXIT --- " + en.getTagName());
 373 	}
 374 
 375 	/**
 376 	 *  Every raw element will enter here.  Bascially, it dispatches it to it's specific
 377 	 *  handler.  It will do so for every child in the passed node. 
 378 	 */
 379 	private void processCode(Element en) throws Exception {
 380 
 381 		Element child;
 382 		String name;
 383 		int idx;
 384 		Node scratchNode;
 385 		NodeList itemTreeChildren = en.getChildNodes();
 386 
 387 		//DEBUG
 388 		//runtimeDebug("ENTER --- " + en.getTagName());
 389 
 390 		for (idx = 0; idx < itemTreeChildren.getLength(); idx++) {
 391 
 392 			scratchNode = itemTreeChildren.item(idx);
 393 
 394 			// Only process elements
 395 			if (!(scratchNode instanceof Element))
 396 				continue;
 397 
 398 			// Clean it
 399 			child = (Element) scratchNode;
 400 			name = child.getTagName().toLowerCase();
 401 
 402 			// Parse the token and call a handler
 403 			// Just not enough tokens to justify a state translation
 404 			if (name.charAt(0) == 'a') {
 405 				handleAssert(child);
 406 			} else if (name.charAt(0) == 'b') {
 407 				if (name.charAt(1) == 'l') {
 408 					handleBlock(child);
 409 				} else {
 410 					handleBuffer(child);
 411 				}
 412 			} else if (name.charAt(0) == 'c') {
 413 				handleCall(child);
 414 			} else if (name.charAt(0) == 'e') {
 415 				handleExec(child);
 416 			} else if (name.charAt(0) == 'f') {
 417 				handleFor(child);
 418 			} else if (name.charAt(0) == 'g') {
 419 				handleGoto(child);
 420 			} else if (name.charAt(0) == 'i') {
 421 				if (name.charAt(1) == 'n') {
 422 					handleInput(child);
 423 				} else {
 424 					handleIf(child);
 425 				}
 426 			} else if (name.charAt(0) == 'l') {
 427 				handleLabel(child);
 428 			} else if (name.charAt(0) == 'm') {
 429 				if (name.charAt(1) == 'e') {
 430 					handleMethod(child);
 431 				} else {		
 432 					handleMath(child);
 433 				}
 434 			} else if (name.charAt(0) == 's') {
 435 				if (name.charAt(1) == 'e') {
 436 					handleSet(child);
 437 				} else {
 438 					handleSubroutine(child);
 439 				}
 440 			} else if (name.charAt(0) == 'w') {
 441 				handleWhile(child);
 442 			} else if (name.charAt(0) == 'r') {
 443 				handleReturn(child);
 444 			} else {
 445 				runtimeError(
 446 					"Software Detected Fault: autohit.creator.compiler.SimCompiler().  The textual token ["
 447 						+ en.getNodeName()
 448 						+ "] should have NOT reached this code. Check the XML DTD associated with the SimCompiler.");
 449 				throw (
 450 					new Exception("Software Detected Fault in creator.compiler.SimCompiler.processItem()."));
 451 			}
 452 		}
 453 		//DEBUG
 454 		//runtimeDebug("EXIT --- " + en.getTagName());
 455 	}
 456 
 457 	// == ===============================================================================
 458 	// == =                         TOKEN HANDLERS                                      =
 459 	// == ===============================================================================
 460 
 461 	/**
 462 	 *  handle a block.  easy enough.  just scope it!.
 463 	 *  MICROCODE
 464 	 *  1- i.scope
 465 	 *	2- ANY
 466 	 *	3- i.rscope
 467 	 */
 468 	private void handleBlock(Element en) {
 469 
 470 		//runtimeDebug("handleBlock.");
 471 
 472 		// 1- i.scope
 473 		this.emitScope();
 474 
 475 		// 2- ANY
 476 		try {
 477 			processCode(en);
 478 
 479 		} catch (Exception e) {
 480 			// Stop an error unravelling here....    
 481 		}
 482 
 483 		// 3- i.rscope
 484 		this.emitRScope();
 485 	}
 486 
 487 	/**
 488 	 *  handle a Buffer.
 489 	 *  MICROCODE
 490 	 *  1- if (clear exists)	i.clear(name), ALREADY = true
 491 	 *	2- if (eval exists)	i.eval(eval), i.merge(name) 
 492 	 *  3-    else if (value exists) i.left(value), i.merge(name)
 493 	 *  4-    else if (buffer exists)i.reduce(buffer), i.merge(name)
 494 	 *  5-    else CLEAR = true			
 495 	 *  6- if (cdata exists)	 		 i.load(cdata), i.merge(name)
 496 	 *  7- 	  else if (CLEAR true, ALREADY false)		i.clear(name)
 497 	 */
 498 	private void handleBuffer(Element en) {
 499 
 500 		String name = en.getAttribute(ATTR_NAME);
 501 		String cdata;
 502 		boolean clearFlag = false;
 503 		boolean clearAlready = false;
 504 
 505 		//runtimeDebug("handleBuffer.  name=" + name);
 506 
 507 		// 1- if (clear exists)	i.clear(name)
 508 		if (en.hasAttribute(ATTR_CLEAR)) {
 509 			this.emitClear(name);
 510 			clearAlready = true;
 511 		}
 512 
 513 		// 2- if (eval exists)	i.eval(eval), i.merge(name) 
 514 		if (en.hasAttribute(ATTR_EVALUATOR)) {
 515 			this.emitEval(en.getAttribute(ATTR_EVALUATOR));
 516 			this.emitMerge(en.getAttribute(ATTR_NAME));
 517 
 518 			// 3-    else if (value exists) i.load(value), i.merge(name) 	
 519 		} else if (en.hasAttribute(ATTR_VALUE)) {
 520 			this.emitLoad(en.getAttribute(ATTR_VALUE));
 521 			this.emitMerge(en.getAttribute(ATTR_NAME));
 522 
 523 			// 4- else if (buffer exists)i.reduce(buffer), i.merge(name) 
 524 		} else if (en.hasAttribute(ATTR_BUFFER)) {
 525 			this.emitReduce(en.getAttribute(ATTR_BUFFER));
 526 			this.emitMerge(en.getAttribute(ATTR_NAME));
 527 
 528 			// 5-    else 			i.clear(name), done
 529 		} else {
 530 			clearFlag = true;
 531 		}
 532 
 533 		// 6- if (cdata exists)	 i.load(cdata), i.merge(name)
 534 		try {
 535 			cdata = getText(en.getFirstChild());
 536 		} catch (Exception e) {
 537 			cdata = null;
 538 		}
 539 
 540 		if (cdata != null) {
 541 			this.emitLoad(cdata);
 542 			this.emitMerge(en.getAttribute(ATTR_NAME));
 543 
 544 			// 7- else if (CLEAR true, ALREADY false)		i.clear(name)
 545 		} else if ((clearFlag == true) && (clearAlready == false)) {
 546 			this.emitClear(name);
 547 		}
 548 	}
 549 
 550 	/**
 551 	 *  handle call.
 552 	 *  MICROCODE
 553 	 * 1- i.scope
 554 	 * 2- (SET)*
 555 	 * 3- i.call(name)
 556 	 * 4- i.rscope
 557 	 * 5- if (result exist) i.store(result)
 558 	 */
 559 	private void handleCall(Element en) {
 560 
 561 		String name = en.getAttribute(ATTR_NAME);
 562 
 563 		runtimeDebug("handleCall.  call=" + name);
 564 
 565 		// 1- i.scope
 566 		this.emitScope();
 567 
 568 		// 2- (SET)*
 569 		try {
 570 			// recurse into the children
 571 			processCode(en);
 572 
 573 			// 3- i.call(name)
 574 			this.emitCall(name);
 575 
 576 		} catch (Exception e) {
 577 			//	Stop an error unravelling here.  Close the scope and move on
 578 			runtimeError("ERROR handleCall.  Broken call." + name);
 579 			runtimeError(e.toString());
 580 			this.emitRScope();
 581 			return;
 582 		}
 583 
 584 		// 4- i.rscope
 585 		this.emitRScope();
 586 
 587 		// 5- if (result exist) i.store(result)
 588 		if (en.hasAttribute(ATTR_RESULT)) {
 589 			this.emitStore(en.getAttribute(ATTR_RESULT));
 590 		}
 591 	}
 592 	
 593 	/**
 594 	 *  handle call.
 595 	 *  MICROCODE
 596 	 * 1- i.scope
 597 	 * 2- (SET)*
 598 	 * 3- i.eval(name)
 599 	 * 4- i.method(method)
 600 	 * 5- i.rscope
 601 	 * 6- if (result exist) i.store(result)
 602 	 */
 603 	private void handleMethod(Element en) {
 604 
 605 		String name = en.getAttribute(ATTR_NAME);
 606 		String method = en.getAttribute(ATTR_METHOD);
 607 
 608 		runtimeDebug("handleMethod.  name=" + name + " method=" + method);
 609 
 610 		// 1- i.scope
 611 		this.emitScope();
 612 
 613 		// 2- (SET)*
 614 		try {
 615 			// recurse into the children
 616 			processCode(en);
 617 
 618 			// 3- i.call(name)
 619 			this.emitEval(name);
 620 
 621 			// 4- i.call(name)
 622 			this.emitMethod(method);
 623 
 624 		} catch (Exception e) {
 625 			//	Stop an error unravelling here.  Close the scope and move on
 626 			runtimeError("ERROR handleMethod.  Broken call." + name);
 627 			runtimeError(e.toString());
 628 			this.emitRScope();
 629 			return;
 630 		}
 631 
 632 		// 5- i.rscope
 633 		this.emitRScope();
 634 
 635 		// 5- if (result exist) i.store(result)
 636 		if (en.hasAttribute(ATTR_RESULT)) {
 637 			this.emitStore(en.getAttribute(ATTR_RESULT));
 638 		}
 639 	}
 640 
 641 	/**
 642 	 *  handle exec.
 643 	 *  MICROCODE
 644 	 * 1- i.scope
 645 	 * 2- (INPUT)*
 646 	 * 3- i.exec(name)
 647 	 * 4- i.rscope
 648 	 * 5- if (result exist) i.store(result)
 649 	 */
 650 	private void handleExec(Element en) {
 651 
 652 		String name = en.getAttribute(ATTR_NAME);
 653 
 654 		runtimeDebug("handleExec.  exec=" + name);
 655 
 656 		// 1- i.scope
 657 		this.emitScope();
 658 
 659 		// 2- (INPUT)*
 660 		try {
 661 			// recurse into the children
 662 			processCode(en);
 663 
 664 			// 3- i.call(name)
 665 			this.emitExec(name);
 666 
 667 		} catch (Exception e) {
 668 			//	Stop an error unravelling here.  Close the scope and move on
 669 			runtimeError("ERROR handleExec.  Broken exec." + name);
 670 			runtimeError(e.toString());
 671 			this.emitRScope();
 672 			return;
 673 		}
 674 
 675 		// 4- i.rscope
 676 		this.emitRScope();
 677 
 678 		// 5- if (result exist) i.store(result)
 679 		if (en.hasAttribute(ATTR_RESULT)) {
 680 			this.emitStore(en.getAttribute(ATTR_RESULT));
 681 		}
 682 
 683 	}
 684 
 685 	/**
 686 	 *  handle a FOR
 687 	 *  MICROCODE
 688 	 * 1-  TOP:	i.scope
 689 	 * 2- 		if (eval exists)	i.eval(eval)
 690 	 * 3- 			else if (value exists) i.load(value)
 691 	 * 4-			else 			!!ERROR	
 692 	 * 5- 		i.new(count)
 693 	 * 6-  LOOP:	i.if(DONE)
 694 	 * 7-  DO:	(ANY)*
 695 	 * 8- 		i.load("1")
 696 	 * 9- 		i.right	
 697 	 * 10- 		i.fetch(count)
 698 	 * 11-		i.math("-")		// LEFT RESULT will stay in LEFT
 699 	 * 12-		i.store(count)		
 700 	 * 13-		i.jump(LOOP)		
 701 	 * 14- DONE:	i.rscope
 702 	 */
 703 	private void handleFor(Element en) {
 704 
 705 		int loopstop;
 706 
 707 		VMIIf myif;
 708 		VMIJump myjump;
 709 
 710 		//runtimeDebug("handleFor");
 711 
 712 		// 1- i.scope
 713 		this.emitScope();
 714 
 715 		// 2- if (eval exists)	i.eval(eval)
 716 		if (en.hasAttribute(ATTR_EVALUATOR)) {
 717 			this.emitEval(en.getAttribute(ATTR_EVALUATOR));
 718 
 719 			// 3-   else if (value exists) i.load(value) 	
 720 		} else if (en.hasAttribute(ATTR_VALUE)) {
 721 			this.emitLoad(en.getAttribute(ATTR_VALUE));
 722 
 723 			// 4-	else 			!!ERROR	
 724 		} else {
 725 			runtimeError("ERROR Broken for.  No count value defined.");
 726 			this.emitLoad(en.getAttribute(LITERAL_ZERO));
 727 			// use 0 so we can finish compile
 728 		}
 729 
 730 		// 5- 	i.new(count)
 731 		this.emitNew(en.getAttribute("count"));
 732 
 733 		// 6-  LOOP:	i.if(DONE)
 734 		loopstop = ob.nextIP(); // loop stop points to #6
 735 		myif = new VMIIf();
 736 		// FIXUP the IF later
 737 		ob.emit(myif);
 738 		runtimeDebug("EMIT(" + loopstop + ") i.if target= FIXUP LATER");
 739 
 740 		// 7-  DO:	(ANY)*
 741 		try {
 742 			processCode(en);
 743 		} catch (Exception e) {
 744 			//	Stop an error unravelling here.  Close the scope and move on
 745 			runtimeError("ERROR Broken FOR inner.");
 746 			runtimeError(e.toString());
 747 		}
 748 
 749 		// 8-  i.load(LITERAL_ONE)
 750 		this.emitLoad(LITERAL_ONE);
 751 
 752 		// 9-  i.right
 753 		this.emitRight();
 754 
 755 		// 10-  i.fetch(count)
 756 		this.emitFetch(en.getAttribute(ATTR_COUNT));
 757 
 758 		// 11-	i.math("-")
 759 		this.emitMath(MINUS_OPERATION);
 760 
 761 		// 12-  i.store(count)
 762 		this.emitStore(en.getAttribute(ATTR_COUNT));
 763 
 764 		// 13-	i.jump(LOOP)
 765 		this.emitJump(loopstop);
 766 
 767 		// 14- DONE:	i.rscope
 768 		// First fixup the jump
 769 		myif.t = ob.nextIP();
 770 		runtimeDebug("FIXUP IF=" + myif.t);
 771 		this.emitRScope();
 772 	}
 773 
 774 	/**
 775 	 *  handle a Set
 776 	 *  MICROCODE
 777 	 * 1- if (eval exists)			i.eval(eval)
 778 	 * 2- 	 else if (ref exists)	i.fetch(ref)
 779 	 * 3-    else if (value exists) i.load(value)
 780 	 * 4-    else (buffer exists)	i.reduce(buffer)
 781 	 * 5-    else 					!!ERROR	
 782 	 * 6- if (new exists)			i.new(name)
 783 	 * 7-    else					i.store(name)
 784 	 */
 785 	private void handleSet(Element en) {
 786 
 787 		String name = en.getAttribute(ATTR_NAME);
 788 
 789 		//runtimeDebug("handleSet  name=" + name);
 790 
 791 		// 1- if (eval exists)			i.eval(eval)
 792 		if (en.hasAttribute(ATTR_EVALUATOR)) {
 793 			this.emitEval(en.getAttribute(ATTR_EVALUATOR));
 794 
 795 			// 2- else if (ref exists)	i.fetch(ref)	
 796 		} else if (en.hasAttribute(ATTR_REFERENCE)) {
 797 			this.emitFetch(en.getAttribute(ATTR_REFERENCE));
 798 
 799 			// 3- else if (value exists) i.load(value) 	
 800 		} else if (en.hasAttribute(ATTR_VALUE)) {
 801 			this.emitLoad(en.getAttribute(ATTR_VALUE));
 802 
 803 			// 4- else (buffer exists)	i.reduce(buffer) 
 804 		} else if (en.hasAttribute(ATTR_BUFFER)) {
 805 			this.emitReduce(en.getAttribute(ATTR_BUFFER));
 806 
 807 			// 5- else 					!!ERROR	
 808 		} else {
 809 			runtimeError("ERROR.  No source given for SET.");
 810 			return;
 811 		}
 812 
 813 		// 6- if (new exists)			i.new(name)
 814 		if (en.hasAttribute(ATTR_NEW)) {
 815 			this.emitNew(name);
 816 
 817 			// 7-    else		i.store(name)
 818 		} else {
 819 			this.emitStore(name);
 820 		}
 821 	}
 822 
 823 	/**
 824 	 *  handle a Input
 825 	 *  MICROCODE
 826 	 * 1- if (eval exists)			i.eval(eval)
 827 	 * 2-    else if (value exists) i.load(value)
 828 	 * 3-    else (buffer exists)	i.reduce(buffer)
 829 	 * 4-    else 					!!ERROR	
 830 	 * 5- i.new(name)
 831 	 */
 832 	private void handleInput(Element en) {
 833 
 834 		String name = en.getAttribute(ATTR_NAME);
 835 
 836 		//runtimeDebug("handleInput  name=" + name);
 837 
 838 		// 1- if (eval exists)			i.eval(eval)
 839 		if (en.hasAttribute(ATTR_EVALUATOR)) {
 840 			this.emitEval(en.getAttribute(ATTR_EVALUATOR));
 841 
 842 			// 2- else if (value exists) i.load(value) 	
 843 		} else if (en.hasAttribute(ATTR_VALUE)) {
 844 			this.emitLoad(en.getAttribute(ATTR_VALUE));
 845 
 846 			// 3- else (buffer exists)	i.reduce(buffer) 
 847 		} else if (en.hasAttribute(ATTR_BUFFER)) {
 848 			this.emitReduce(en.getAttribute(ATTR_BUFFER));
 849 
 850 			// 4- else 					!!ERROR	
 851 		} else {
 852 			runtimeError("ERROR.  No source given for INPUT.");
 853 			return;
 854 		}
 855 
 856 		// 5- i.new(name)
 857 		this.emitNew(name);
 858 	}
 859 
 860 	/**
 861 	 *  handle goto
 862 	 *  Emit the goto.  Put it in the fixup stack.
 863 	 *  MICROCODE
 864 	 *  1- i.goto(label)
 865 	 */
 866 	private void handleGoto(Element en) {
 867 
 868 		String label = en.getAttribute(ATTR_LABEL);
 869 
 870 		//runtimeDebug("handleGoto  label=" + label);
 871 
 872 		// 1- i.goto(label)
 873 		fixupstack.push(new NOPair(label, (Object) this.emitGoto(0)));
 874 	}
 875 
 876 	/**
 877 	 *  handle a IF
 878 	 * <code>MICROCODE
 879 	 * 1-	  if (oper exists)	OP = oper
 880 	 * 2-	     else			OP = '=' (default)
 881 	 * 3-  	  if (eval exists)			i.eval(eval)
 882 	 * 4-  	     else if (value exists) i.load(value)
 883 	 * 5- 		 else 					!!ERROR	
 884 	 * 6-  	  i.right
 885 	 * 7-  	  i.fetch(item)
 886 	 * 8-  	  i.math(operation)
 887 	 * 9- 	  i.if(OUTER,OP)
 888 	 * 10- INNER:	i.scope
 889 	 * 11-     (ANY)*
 890 	 * 12-    i.rscope
 891 	 * 13- OUTER:	i.nop </code>
 892 	 */
 893 	private void handleIf(Element en) {
 894 
 895 		VMIIf myif;
 896 		int opthang = EQ;  // default is =
 897 
 898 		//runtimeDebug("handleIf");
 899 
 900 		// 1- if (oper exists)	OP = oper
 901 		if (en.hasAttribute(ATTR_OPERATOR)) {
 902 			String ops = en.getAttribute(ATTR_OPERATOR);
 903 			if (ops.equals(EQ_STRING)) {
 904 				opthang = EQ;
 905 			} else if (ops.equals(LT_STRING)) {
 906 				opthang = LT;
 907 			} else if (ops.equals(GT_STRING)) {
 908 				opthang = GT;
 909 			} else if (ops.equals(NOT_STRING)) {
 910 				opthang = NOT;
 911 			} else {
 912 				runtimeWarning("WARNING If has unrecognized operation.  Using default \"eq\"");
 913 				opthang = EQ;
 914 			}	
 915 		} 
 916 			//	2-   else			OP = '=' (default)
 917 			// Implied since it is the default.
 918 
 919 		// 3- if (eval exists)			 i.eval(eval)
 920 		if (en.hasAttribute(ATTR_EVALUATOR)) {
 921 			this.emitEval(en.getAttribute(ATTR_EVALUATOR));
 922 
 923 			// 4- else if (value exists) i.load(value) 	
 924 		} else if (en.hasAttribute(ATTR_VALUE)) {
 925 			this.emitLoad(en.getAttribute(ATTR_VALUE));
 926 
 927 			// 5- else !!ERROR	
 928 		} else {
 929 			runtimeError("ERROR Broken IF.  No right value defined defined.");
 930 			this.emitLoad(en.getAttribute(LITERAL_ZERO));
 931 			// use 0 so we can finish compile
 932 		}
 933 
 934 		// 6- i.right
 935 		this.emitRight();
 936 
 937 		// 7- i.fetch(item)
 938 		this.emitFetch(en.getAttribute(ATTR_ITEM));
 939 
 940 		// 8- i.math(operation)
 941 		this.emitMath(IF_OPERATION);
 942 
 943 		// 9- i.if(OUTER, OP)
 944 		myif = new VMIIf();
 945 		myif.operFlag = opthang;
 946 		ob.emit(myif);
 947 		//runtimeDebug(
 948 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.if target= FIXUP LATER");
 949 
 950 		// 10- INNER:	i.scope
 951 		this.emitScope();
 952 
 953 		// 11- (ANY)*
 954 		try {
 955 			processCode(en);
 956 		} catch (Exception e) {
 957 			//	Stop an error unravelling here.  Close the scope and move on
 958 			runtimeError("ERROR Broken IF inner.");
 959 			runtimeError(e.toString());
 960 		}
 961 
 962 		// 12- i.rscope
 963 		this.emitRScope();
 964 
 965 		// 13- OUTER:	i.nop
 966 		// First fixup the if.  Put a NOP for safety, so there will always be a target
 967 		myif.t = ob.nextIP();
 968 		runtimeDebug("FIXUP if target=" + myif.t);
 969 		this.emitNOP();
 970 	}
 971 
 972 	/**
 973 	 *  handle a ASSERT
 974 	 * <code>MICROCODE
 975 	 * 
 976 	 * 1-    if (oper NOT exists)	OP = NOT
 977      * 2-    else			        OP = EQ
 978      * 3-    i.fetch(item)
 979 	 * 4-    i.assert(OUTER,OP)
 980 	 * 5- INNER:  i.scope
 981 	 * 6-    (ANY)*
 982 	 * 7-    i.rscope
 983 	 * 8- OUTER:   i.nop
 984 	 * </code>
 985 	 */
 986 	private void handleAssert(Element en) {
 987 
 988 		VMIAssert myassert;
 989 		int opthang = EQ;  // default is =
 990 
 991 		//runtimeDebug("handleAssert");
 992 
 993 		// 1- if (oper exists)	OP = oper
 994 		if (en.hasAttribute(ATTR_OPERATOR)) {
 995 			String ops = en.getAttribute(ATTR_OPERATOR);
 996 			if (ops.equals(EQ_STRING)) {
 997 				opthang = EQ;
 998 			} else if (ops.equals(NOT_STRING)) {
 999 				opthang = NOT;
1000 			} else {
1001 				runtimeWarning("WARNING If has unrecognized operation.  Using default \"eq\"");
1002 				opthang = EQ;
1003 			}	
1004 		} 
1005 		//	2-   else			OP = '=' (default)
1006 		// Implied since it is the default.
1007 
1008 		//  3-   i.fetch(item)
1009 		this.emitFetch(en.getAttribute(ATTR_ITEM));
1010 
1011 		//  4-	 i.assert(OUTER,OP)
1012 		myassert = new VMIAssert();
1013 		myassert.operFlag = opthang;
1014 		ob.emit(myassert);
1015 		//runtimeDebug(
1016 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.assert target= FIXUP LATER");
1017 
1018 		// 5- INNER:  i.scope
1019 		this.emitScope();
1020 
1021 		// 6- (ANY)*
1022 		try {
1023 			processCode(en);
1024 		} catch (Exception e) {
1025 			//	Stop an error unravelling here.  Close the scope and move on
1026 			runtimeError("ERROR Broken ASSERT inner.");
1027 			runtimeError(e.toString());
1028 		}
1029 
1030 		// 7- i.rscope
1031 		this.emitRScope();
1032 
1033 		// 8- OUTER:   i.nop
1034 		// First fixup the assert.  Put a NOP for safety, so there will always be a target
1035 		myassert.t = ob.nextIP();
1036 		runtimeDebug("FIXUP assert target=" + myassert.t);
1037 		this.emitNOP();
1038 	}
1039 
1040 	/**
1041 	 *  handle subroutine.
1042 	 *  MICROCODE
1043 	 * 1- i.scope
1044 	 * 2- (SET)*
1045 	 * 3- i.subr(name)
1046 	 * 4- i.rscope
1047 	 * 5- if (result exist) i.store(result)
1048 	 */
1049 	private void handleSubroutine(Element en) {
1050 
1051 		String name = en.getAttribute(ATTR_NAME);
1052 
1053 		runtimeDebug("handleSubroutine.  name=" + name);
1054 
1055 		// 1- i.scope
1056 		this.emitScope();
1057 
1058 		// 2- (SET)*
1059 		try {
1060 			// recurse into the children
1061 			processCode(en);
1062 
1063 			// 3- i.call(name)
1064 			this.emitSubr(name);
1065 
1066 		} catch (Exception e) {
1067 			//	Stop an error unravelling here.  Close the scope and move on
1068 			runtimeError("ERROR handleCall.  Broken call." + name);
1069 			runtimeError(e.toString());
1070 			ob.emit(new VMIRScope());
1071 			return;
1072 		}
1073 
1074 		// 4- i.rscope
1075 		this.emitRScope();
1076 
1077 		// 5- if (result exist) i.store(result)
1078 		if (en.hasAttribute(ATTR_RESULT)) {
1079 			this.emitStore(en.getAttribute(ATTR_RESULT));
1080 		}
1081 	}
1082 
1083 	/**
1084 	 *  handle a label
1085 	 *  MICROCODE
1086 	 * 1- {mark label}
1087 	 */
1088 	private void handleLabel(Element en) {
1089 
1090 		String name = en.getAttribute(ATTR_NAME);
1091 
1092 		//runtimeDebug("handleLabel.  name=" + name);
1093 
1094 		// 1- {mark label}.  Put it in the symboltable with current IP
1095 		// See if there is a duplicate.
1096 		if (symboltable.containsKey(name)) {
1097 			runtimeError("Duplicate label declared.  label=" + name);
1098 		} else {
1099 			symboltable.put(name, new Integer(ob.nextIP()));
1100 		}
1101 	}
1102 
1103 	/**
1104 	 *  handle a WHILE
1105 	 *  MICROCODE
1106 	 * 1- 	i.scope
1107 	 * 2- DO:	i.load(value)
1108 	 * 3- 	i.right
1109 	 * 4-   i.fetch(name)
1110 		 * 5- 	i.math("=")
1111 	 * 6- 	i.if(DONE)
1112 	 * 7-   (ANY)*
1113 	 * 8- 	i.jump(DO)
1114 	 * 9- DONE:	i.rscope
1115 	 */
1116 	private void handleWhile(Element en) {
1117 
1118 		int loopdo;
1119 		VMIIf myif;
1120 		VMIJump myjump;
1121 
1122 		//runtimeDebug("handleWhile");
1123 
1124 		// 1- i.scope
1125 		this.emitScope();
1126 
1127 		// 2- DO:	i.load(value)
1128 		loopdo = ob.nextIP(); // DO points at #2
1129 		this.emitLoad(en.getAttribute(ATTR_VALUE));
1130 
1131 		// 3- 	i.right
1132 		this.emitRight();
1133 
1134 		// 4-   i.fetch(name)
1135 		this.emitFetch(en.getAttribute(ATTR_NAME));
1136 
1137 		// 5- 	i.math("=")
1138 		this.emitMath(EQ_OPERATION);
1139 
1140 		// 6- 	i.if(DONE)
1141 		myif = new VMIIf();
1142 		ob.emit(myif);
1143 		//runtimeDebug(
1144 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.if target= FIXUP LATER");
1145 
1146 		// 7- (ANY)*
1147 		try {
1148 			processCode(en);
1149 		} catch (Exception e) {
1150 			//	Stop an error unravelling here.  Close the scope and move on
1151 			runtimeError("ERROR Broken FOR inner.");
1152 			runtimeError(e.toString());
1153 		}
1154 
1155 		// 8- 	i.jump(DO)
1156 		myjump = new VMIJump();
1157 		myjump.t = loopdo;
1158 		ob.emit(myjump);
1159 		runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.jump target=" + loopdo);
1160 
1161 		// 9- DONE:	i.rscope
1162 		// First fixup the if
1163 		myif.t = ob.nextIP();
1164 		this.emitRScope();
1165 	}
1166 
1167 	/**
1168 	 *  handle a MATH
1169 	 *  MICROCODE
1170 	 * 1- if (eval exists)			i.eval(eval)
1171 	 * 2-    else if (value exists) i.load(value)
1172 	 * 3-    else 					!!ERROR	
1173 	 * 4- i.right()
1174 	 * 5- i.fetch(left)
1175 	 * 6- i.math(oper)
1176 	 * 7- if (output exists)		i.store(output)
1177 	 * 8-    else 					i.store(left)
1178 	 */
1179 	private void handleMath(Element en) {
1180 
1181 		//runtimeDebug("handleMath");
1182 
1183 		// 1- if (eval exists)		i.eval(eval)
1184 		if (en.hasAttribute(ATTR_EVALUATOR)) {
1185 			this.emitEval(en.getAttribute(ATTR_EVALUATOR));
1186 
1187 			// 2- else if (value exists) i.load(value) 	
1188 		} else if (en.hasAttribute(ATTR_VALUE)) {
1189 			this.emitLoad(en.getAttribute(ATTR_VALUE));
1190 
1191 			// 3- else 			!!ERROR	
1192 		} else {
1193 			runtimeError("ERROR Broken Math.  No right value defined.");
1194 			this.emitLoad(LITERAL_ZERO);
1195 			// use 0 so we can finish compile
1196 		}
1197 
1198 		// 4- i.right
1199 		this.emitRight();
1200 
1201 		// 5- i.fetch(item)
1202 		this.emitFetch(en.getAttribute(ATTR_LEFT));
1203 
1204 		// 6- i.math(operation)
1205 		this.emitMath(en.getAttribute(ATTR_OPERATOR));
1206 
1207 		// 7- if (output exists)		i.store(output)
1208 		if (en.hasAttribute(ATTR_OUTPUT)) {
1209 			this.emitStore(en.getAttribute(ATTR_OUTPUT));
1210 
1211 			// else 					i.store(left)
1212 		} else {
1213 			this.emitStore(en.getAttribute(ATTR_LEFT));
1214 		}
1215 
1216 	}
1217 
1218 	/**
1219 	 *  handle a return.  It just emits a fault
1220 	 *  MICROCODE
1221 	 * 1- i.fault
1222 	 */
1223 	private void handleReturn(Element en) {
1224 
1225 		//runtimeDebug("handleReturn");
1226 
1227 		// 1- i.fault
1228 		this.emitFault();
1229 	}
1230 
1231 	// == ===============================================================================
1232 	// == =                             HELPERS                                         =
1233 	// == ===============================================================================
1234 
1235 	/**
1236 	 *  Valid string.
1237 	 * 
1238 	 *  Checks if the reference is not null and the string contains characters.
1239 	 *
1240 	 *  @param s the string to check.
1241 	 *  @return true if valid, otherwise false
1242 	 */
1243 	private boolean isValid(String s) {
1244 		if ((s == null) || (s.length() < 1))
1245 			return false;
1246 		else
1247 			return true;
1248 	}
1249 
1250 	/**
1251 	 *  Get the text out of an XML node.
1252 	 *
1253 	 *  @param cdn XML node.
1254 	 *  @return the text.
1255 	 */
1256 	private String getText(Node cdn) {
1257 
1258 		try {
1259 			if ((cdn.getNodeType() == Node.TEXT_NODE)
1260 				|| (cdn.getNodeType() != Node.CDATA_SECTION_NODE)) {
1261 				CharacterData cdnc = (CharacterData) cdn;
1262 				return cdnc.getData();
1263 			}
1264 		} catch (Exception e) {
1265 		} // ignore.  re are returning empty anyway
1266 		return null;
1267 	}
1268 
1269 	/**
1270 	 *  Get the text out of an XML node.
1271 	 *
1272 	 *  @param where where it was bad.
1273 	 *  @param which which attribute was bad.
1274 	 *  @param tag  which tag.
1275 	 *  @return the text.
1276 	 */
1277 	private void errBadAttribute(String where, String which, String tag) {
1278 		runtimeError(
1279 			"ERROR: Invalid '"
1280 				+ which
1281 				+ "' attribute for <"
1282 				+ tag
1283 				+ ">.  @"
1284 				+ where);
1285 	}
1286 
1287 	/**
1288 	 *  emitClear
1289 	 */
1290 	private void emitClear(String name) {
1291 		VMIClear ic;
1292 		ic = new VMIClear();
1293 		ic.t = name;
1294 		ob.emit(ic);
1295 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.clear name= " + name);
1296 	}
1297 
1298 	/**
1299 	 *  emitEval
1300 	 */
1301 	private void emitEval(String eval) {
1302 		VMIEval ic;
1303 		ic = new VMIEval();
1304 		ic.e = eval;
1305 		ob.emit(ic);
1306 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.eval eval= " + eval);
1307 	}
1308 
1309 	/**
1310 	 *  emitReduce
1311 	 */
1312 	private void emitReduce(String buffer) {
1313 		VMIReduce ic;
1314 		ic = new VMIReduce();
1315 		ic.b = buffer;
1316 		ob.emit(ic);
1317 		//runtimeDebug(
1318 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.reduce name= " + buffer);
1319 	}
1320 
1321 	/**
1322 	 *  emitReduce
1323 	 */
1324 	private void emitLoad(String value) {
1325 		VMILoad ic;
1326 		ic = new VMILoad();
1327 		ic.l = value;
1328 		ob.emit(ic);
1329 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.load value= " + value);
1330 	}
1331 
1332 	/**
1333 	 *  emitMerge
1334 	 */
1335 	private void emitMerge(String buffer) {
1336 		VMIMerge ic;
1337 		ic = new VMIMerge();
1338 		ic.b = buffer;
1339 		ob.emit(ic);
1340 		//runtimeDebug(
1341 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.merge buffer= " + buffer);
1342 	}
1343 
1344 	/**
1345 	 *  emitCall
1346 	 */
1347 	private void emitCall(String target) {
1348 		VMICall ic;
1349 		ic = new VMICall();
1350 		ic.t = target;
1351 		ob.emit(ic);
1352 		//runtimeDebug(
1353 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.call target= " + target);
1354 	}
1355 
1356 	/**
1357 	 *  emitMethod
1358 	 */
1359 	private void emitMethod(String m) {
1360 		VMIMethod ic;
1361 		ic = new VMIMethod();
1362 		ic.m = m;
1363 		ob.emit(ic);
1364 		//runtimeDebug(
1365 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.method method=" + m);
1366 	}
1367 
1368 	/**
1369 	 *  emitSubr
1370 	 */
1371 	private void emitSubr(String target) {
1372 		VMISubr ic;
1373 		ic = new VMISubr();
1374 		ic.t = target;
1375 		ob.emit(ic);
1376 		//runtimeDebug(
1377 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.subr target= " + target);
1378 	}
1379 
1380 	/**
1381 	 *  emitExec
1382 	 */
1383 	private void emitExec(String target) {
1384 		VMIExec ic;
1385 		ic = new VMIExec();
1386 		ic.c = target;
1387 		ob.emit(ic);
1388 		//runtimeDebug(
1389 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.exec target= " + target);
1390 	}
1391 
1392 	/**
1393 	 *  emitNew
1394 	 */
1395 	private void emitNew(String var) {
1396 		VMINew ic;
1397 		ic = new VMINew();
1398 		ic.v = var;
1399 		ob.emit(ic);
1400 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.new variable= " + var);
1401 	}
1402 
1403 	/**
1404 	 *  emitRight
1405 	 */
1406 	private void emitRight() {
1407 		ob.emit(new VMIRight());
1408 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.right");
1409 	}
1410 
1411 	/**
1412 	 *  emitFetch
1413 	 */
1414 	private void emitFetch(String var) {
1415 		VMIFetch ic;
1416 		ic = new VMIFetch();
1417 		ic.v = var;
1418 		ob.emit(ic);
1419 		//runtimeDebug(
1420 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.fetch variable= " + var);
1421 	}
1422 
1423 	/**
1424 	 *  emitMath
1425 	 */
1426 	private void emitMath(String oper) {
1427 		VMIMath ic;
1428 		ic = new VMIMath();
1429 		ic.o = oper;
1430 		ob.emit(ic);
1431 		//runtimeDebug(
1432 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.math operation= " + oper);
1433 	}
1434 
1435 	/**
1436 	 *  emitStore
1437 	 */
1438 	private void emitStore(String var) {
1439 		VMIStore ic;
1440 		ic = new VMIStore();
1441 		ic.v = var;
1442 		ob.emit(ic);
1443 		//runtimeDebug(
1444 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.store variable= " + var);
1445 	}
1446 
1447 	/**
1448 	 *  emitJump
1449 	 */
1450 	private VMIJump emitJump(int target) {
1451 		VMIJump ic;
1452 		ic = new VMIJump();
1453 		ic.t = target;
1454 		ob.emit(ic);
1455 		//runtimeDebug(
1456 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.Jump target= " + target);
1457 		return ic;
1458 	}
1459 
1460 	/**
1461 	 *  emitGoto
1462 	 */
1463 	private VMIGoto emitGoto(int target) {
1464 		VMIGoto ic;
1465 		ic = new VMIGoto();
1466 		ic.t = target;
1467 		ob.emit(ic);
1468 		//runtimeDebug(
1469 		//	"EMIT(" + (ob.nextIP() - 1) + ") i.goto target= " + target);
1470 		return ic;
1471 	}
1472 
1473 	/**
1474 	 *  emitScope
1475 	 */
1476 	private void emitScope() {
1477 		ob.emit(new VMIScope());
1478 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.scope");
1479 	}
1480 
1481 	/**
1482 	 *  emitRScope
1483 	 */
1484 	private void emitRScope() {
1485 		ob.emit(new VMIRScope());
1486 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.rscope");
1487 	}
1488 
1489 	/**
1490 	 *  emitNOP
1491 	 */
1492 	private void emitNOP() {
1493 		ob.emit(new VMINop());
1494 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.nop");
1495 	}
1496 
1497 	/**
1498 	 *  emitNOP
1499 	 */
1500 	private void emitFault() {
1501 		ob.emit(new VMIFault());
1502 		//runtimeDebug("EMIT(" + (ob.nextIP() - 1) + ") i.fault");
1503 	}
1504 
1505 }