State machine shorthand: class definitions

From Tekkotsu Wiki

Jump to: navigation, search

Simple Examples

Here is a node that uses a doStart method. (Since this node doesn't complete, you would typically exit it using a null transition.)

$nodeclass ReportTime : StateNode : doStart {
  cout << "Time is now " << get_time() << " milliseconds." << endl;

Here is a node that takes a constructor argument:

$nodeclass ForwardBy(float distance) : PilotRequest($,PilotTypes::walk) : constructor {
  pilotreq.dx = distance;

Full Syntax

The full syntax for defining a new node class is:

$nodeclass ClassName(parameters) : ParentName(args) : initializers : methodname {
  • Only a Classname is required; all other elements are optional. If an element is omitted, the colon preceding it should also be omitted.
  • The $nodeclass must be the first thing on the line, after any whitespace.
  • ClassName should begin with a capital letter.
  • parameters, if supplied, should be a list of parameter definitions of form 'type name' or 'type name=value', e.g., int x=5. Parameters will be automatically cached as member variables and can be referenced by initializers or in the bodies of any methods.
  • ParentName is the name of the parent class; it defaults to StateNode. Multiple parents can be specified by separating them with commas.
  • args is a list of arguments to the parent's constructor. In a previous version of the state machine language, the first argument had to be $, to supply the name of the node as a string, but now the $ is inserted automatically if it is missing, so don't worry about it. If no parent constructor argument list is supplied, the argument list defaults to ($).
  • initializers is a list of initializer expressions of form 'name(value)', where name is a user-defined member variable. The initializers for caching the node's constructor parameters are generated automatically and should not be included here.
  • methodname can be one of doStart, doStop, doEvent, setup, or constructor. If a methodname is supplied, the body in $nodeclass...{body} is taken as the body of that method. If a methodname is not supplied, the body is taken as the body of the class definition; this is useful if you need to define new data members, or multiple methods. In this case, methods can be defined in the usual way by writing, e.g., virtual void doStart() {...}.
  • If a methodname was specified and you want to close the method body so you can add lines to the class body, use a $endnodemethod; directive. For most methods (e.g., doStart) you could simply omit the methodname and write virtual void doStart(){...} instead, but that option is not available for the constructor method, so this is the only way to specify the body for the class constructor and also add to the class definition. Example:
$nodeclass MyExample : StateNode : x(0) : constructor {
  cout << "Constructor called: x = " << x << endl;
  int x;
  virtual void doStart() {
    cout << "doStart called: x = " << ++x << endl;
  • Use $nodeclass* instead of $nodeclass if the class contains pointer data members and you want to generate a dummy copy constructor and assignment operator to prevent compiler warnings.
  • Inside the setup method, use $statemachine{...} to construct a state machine using the shorthand notation. Note: the closing brace for the state machine must be on a line by itself.

Additional Examples

A node that simply specializes its superclass by supplying a constructor argument:

$nodeclass SayHello : SpeechNode("Hello") {}