/* ************************************************************************
#
# 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.inst;
import divconq.lang.op.OperationContext;
import divconq.script.Activity;
import divconq.script.ExecuteState;
import divconq.script.IInstructionCallback;
import divconq.script.Instruction;
import divconq.script.StackCallEntry;
import divconq.script.StackEntry;
import divconq.script.StackFunctionEntry;
import divconq.struct.Struct;
import divconq.util.StringUtil;
public class CallFunction extends Instruction {
@Override
public void run(StackEntry stack) {
// TODO there is likely a better way to code Done...cleanup
if (stack.getStore().getFieldAsBooleanOrFalse("Done")) {
stack.setState(ExecuteState.Done);
stack.resume();
return;
}
StackCallEntry cstack = (StackCallEntry)stack;
if (stack.getState() == ExecuteState.Ready) {
String name = stack.stringFromSource("Name");
Struct arg = stack.refFromSource("Argument"); // naturally default to string if no type given
Instruction func = stack.getActivity().queryFunction(name);
if (func == null) {
OperationContext.get().errorTr(517, name);
stack.setState(ExecuteState.Done);
}
else {
StackEntry sfunc = func.createStack(stack.getActivity(), stack);
if ((sfunc == null) || !(sfunc instanceof StackFunctionEntry)) {
OperationContext.get().errorTr(518, name);
stack.setState(ExecuteState.Done);
}
else {
StackFunctionEntry sbfunc = (StackFunctionEntry)sfunc;
sbfunc.setParameter(arg);
cstack.setChild(sbfunc);
stack.setState(ExecuteState.Resume);
}
}
stack.resume();
return;
}
if (stack.getState() != ExecuteState.Resume) {
stack.resume();
return;
}
final StackFunctionEntry child = (StackFunctionEntry)cstack.getChild();
if (child == null) {
OperationContext.get().errorTr(519);
stack.setState(ExecuteState.Done);
stack.resume();
return;
}
child.run(new IInstructionCallback() {
@Override
public void resume() {
ExecuteState cstate = child.getState();
if ((cstate != ExecuteState.Ready) && (cstate != ExecuteState.Resume)) {
stack.getStore().setField("Done", true);
Struct result = child.queryVariable("_LastResult");
String name = stack.stringFromSource("ResultName");
if (StringUtil.isNotEmpty(name))
stack.addVariable(name, result);
cstack.setChild(null);
}
stack.resume();
}
});
}
@Override
public StackEntry createStack(Activity act, StackEntry parent) {
return new StackCallEntry(act, parent, this);
}
@Override
public void cancel(StackEntry stack) {
// TODO
}
}