I created a simple scripting language to use on a Unity3D game. My parser generates an AST with nodes for every type of operation, and to run the script all I need to do is call Execute() on the root of the tree, which propagates recursively to every node in it.
To run functions from my script, I first create a dictionary linking function names to delegates, and the function node simply needs to look it up run it.
But I have ran into a problem now... Some of the functions I need to call from the script are coroutines that take time to execute, such as WalkTo or WaitNSeconds, and for those coroutines I need to halt the script execution until they are done.
I'm stuck on figuring a way to halt the script execution, as once I call Execute()
on the root node, the script gets executed recursively all the way.
Just to provide some more context, here are some examples of a few possible types of nodes and how they operate (not the actual nodes from my language, but close enough). Some nodes simply call Execute() on their children and return nothing. Some nodes simply return values directly. Other nodes get values from their children and modify it in some way.
abstract class Node
{
object Execute();
}
class RootNode: Node {
List<Node> Children;
object Execute() {
foreach(Node node in Children)
node.Execute();
return null;
}
}
class NumberNode : Node {
int Value;
object Execute() { return Value; }
}
class SumNode : Node {
Node Left;
Node right;
object Execute() {
return (int)Left.Execute() + (int)Right.Execute();
}
}
class PrintNode : Node {
Node Expression;
object Execute() {
Console.WriteLine(Expression.Execute().ToString();
return null;
}
}
class FunctionNode: Node {
string Name;
object Execute() {
return SymbolTable.FindFunction(Name)();
}
}
yield return StartCoroutine(function());
will wait for the given coroutine to finish before continuing execution. It's a place to start at least. – XGundam05 May 24 '13 at 18:36object Execute()
toIEnumerator Execute()
and replace every call to Execute() with areturn yield new StartCoroutine(Execute())
. Few problems with this. First I would lose the return value, so I would need to do something like pass a callback to write the value to on everyExecute
. Worse, everyyield return StartCoroutine
will execute in the next frame. But I only want to wait extra frames on coroutine call nodes, not on every other type of operation. – David Gouveia May 25 '13 at 7:39