/* ************************************************************************ # # 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 java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import divconq.lang.op.FuncResult; import divconq.lang.op.OperationContext; import divconq.struct.CompositeStruct; import divconq.struct.ListStruct; import divconq.struct.Struct; import divconq.struct.RecordStruct; import divconq.util.StringUtil; import divconq.work.TaskRun; public class StackBlockEntry extends StackEntry { protected Map<String, Struct> variables = new HashMap<String, Struct>(); protected StackEntry currEntry = null; protected int currPosition = 0; protected boolean topFlag = true; public int getPosition() { return this.currPosition; } public void setPosition(int v) { this.currPosition = v; } public boolean getTopFlag() { return this.topFlag; } public void setTopFlag(boolean v) { this.topFlag = v; } public StackEntry getChild() { return this.currEntry; } public void setChild(StackEntry v) { this.currEntry = v; } public StackBlockEntry(Activity act, StackEntry parent, Instruction inst) { super(act, parent, inst); } public Collection<Struct> variables() { return this.variables.values(); } @Override public void addVariable(String name, Struct var) { this.variables.put(name, var); if (var instanceof AutoCloseable) { TaskRun run = OperationContext.get().getTaskRun(); if (run != null) run.addCloseable((AutoCloseable) var); } } public void clearVariables() { this.variables.clear(); } @Override public Struct queryVariable(String name) { if (StringUtil.isEmpty(name)) return null; // if variable not here, look in parent block int dotpos = name.indexOf("."); if (dotpos > -1) { String oname = name.substring(0, dotpos); Struct ov = this.variables.containsKey(oname) ? this.variables.get(oname) : null; // if not here, look up blocks until Function level and that catch globals too if (ov == null) ov = super.queryVariable(oname); if (ov == null) { OperationContext.get().errorTr(510, oname); return null; } if (!(ov instanceof CompositeStruct)){ OperationContext.get().errorTr(511, oname); return null; } FuncResult<Struct> sres = ((CompositeStruct)ov).select(name.substring(dotpos + 1)); return sres.getResult(); } else if (this.variables.containsKey(name)) { return this.variables.get(name); } return super.queryVariable(name); } @Override public void debugStack(ListStruct dumpList) { RecordStruct dumpRec = new RecordStruct(); dumpList.addItem(dumpRec); this.collectDebugRecord(dumpRec); RecordStruct subRec = this.inst.collectDebugRecord(this, dumpRec); if (subRec != null) dumpList.addItem(subRec); if (this.currEntry != null) this.currEntry.debugStack(dumpList); } @Override public void collectDebugRecord(RecordStruct rec) { RecordStruct dumpVariables = new RecordStruct(); rec.setField("Variables", dumpVariables); for (Entry<String, Struct> var : this.variables.entrySet()) dumpVariables.setField(var.getKey(), var.getValue()); } @Override public StackBlockEntry queryBlockStack() { return this; } @Override public StackEntry getExecutingStack() { return (this.currEntry != null) ? this.currEntry : this; } }