/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.script; import divconq.struct.RecordStruct; import divconq.struct.Struct; import divconq.struct.scalar.NullStruct; import divconq.xml.XElement; import divconq.xml.XNode; // for instructions that are composed of multiple operations abstract public class Ops extends Instruction { @Override public void run(StackEntry stack) { if (stack.getState() == ExecuteState.Ready) { stack.getStore().setField("SubAlign", true); stack.getStore().setField("CurrNode", 0); stack.getStore().setField("Target", NullStruct.instance); stack.setState(ExecuteState.Resume); this.prepTarget(stack); } else if (stack.getState() == ExecuteState.Resume) { if (stack.getStore().getFieldAsBooleanOrFalse("SubAlign")) { this.nextOpResume(stack); return; } // next op needs to align stack.getStore().setField("SubAlign", true); Struct var2 = (Struct) stack.getStore().getField("Target"); int cnode = stack.getStore().getFieldAsInteger("CurrNode").intValue(); XNode nod = this.source.getChild(cnode - 1); this.runOp(stack, (XElement)nod, var2); } } public void nextOpResume(StackEntry stack) { // next op needs to run stack.getStore().setField("SubAlign", false); while (true) { int cnode = stack.getStore().getFieldAsInteger("CurrNode").intValue(); if (cnode >= this.source.children()) { stack.setState(ExecuteState.Done); break; } XNode nod = this.source.getChild(cnode); stack.getStore().setField("CurrNode", cnode + 1); if (nod instanceof XElement) { stack.setState(ExecuteState.Resume); break; } } stack.resume(); } public void setTarget(StackEntry stack, Struct v) { stack.getStore().setField("Target", v); stack.setLastResult(v); } // subclass is responsible for resuming stack abstract public void prepTarget(StackEntry stack); // subclass is responsible for resuming stack abstract public void runOp(StackEntry stack, XElement op, Struct target); @Override public RecordStruct collectDebugRecord(StackEntry stack, RecordStruct rec) { RecordStruct sub = super.collectDebugRecord(stack, rec); if (stack.getState() == ExecuteState.Resume) { int cnode = stack.getStore().getFieldAsInteger("CurrNode").intValue() - 1; if (cnode >= this.source.children()) return null; XNode nod = this.source.getChild(cnode); if (! (nod instanceof XElement)) return null; XElement mut = (XElement)nod; sub = new RecordStruct(); sub.setField("Line", mut.getLine()); sub.setField("Column", mut.getCol()); sub.setField("Command", mut.toLocalString()); return sub; } return sub; } }