Go to the first, previous, next, last section, table of contents.


Script represents a state transition of an agent in coordination protocols. It is based on an extended finite state machine. Each state machine is defined using the macro define-script, and each state in the state machine (or script) is defined using the define-script-state macro. State transition rules are associated with a state, and they are defined using define-script-state when a state is defined. In addition, a named state transition rule can be defined using the define-script-rule macro. This type of rule is associated with a script, and can be used by including the name of a rule in :rules option of the script-state definition.

A script is executed by dynamically changing active message patterns. In other words, a state in a script is implemented as a set of message patterns to be active when the transition to that state occurs. Thus, a script definition is basically a set of message patterns and their associated message handlers.

In order to use a script facility, the class of an agent should be script-agent or its subclass.

Script Definition

Macro: define-script script-name lambda-list { script-options }*

script-name ::= symbol
script-options ::= :initial-state initial-state-name 
                     | :script-vars ( { script-var | ( script-var initial-value) }*) 
                     | :inherits-from script-name 
                     | :initial-active-states state-name-list 
                     | :on-entry rule-lisp-form 
                     | :documentation doc-string 

The script named script-name is defined. lambda-list specifies the arguments for run-script function. lambda-list has the same syntax as the lambda list of Common Lisp (i.e. &optional, &key, &rest are allowed.) Variables appeared in lambda-list are treated as script-vars, and bound to the arguments passed to the run-script function.

:script-vars defines additional script variables. When initial-value is specified, initial-value is evaluated when a script is invoked. In initial-value, script variables appeared in lambda-list can be used using script variable access macro $. Otherwise the initial value of a script variable is nil. :inherits-from specifies the script from which script definitions such as script states, script variables, script-functions are inherited. If on-entry is specified, on-entry is executed before the state transition to the initial state occurs. Inside on-entry, call-super can be used to call the on-entry function of a super script. :initial-state option specifies the initial state. Note that initial-state-name is evaluated.

As an experimental feature, multiple states can be activated simultaneously. The state transition rules in active states are also checked during the script execution. :initial-active-states option specifies the states which are to be made active initially.


(define-script cnet-manager (task)
  :initial-state 'start
  :script-vars (bid-queue contract-id))

Note: nil is not allowed as a script name.

Macro: define-script-rule (rule-name script-name) &key script-vars-used rule documentation

This macro defines a state transition rule named rule-name which is local to script script-name. Script variables declared in :script-vars-used option can be accessed inside rule without using $ macro.

 rule ::= (:when condition :do action) 
 condition ::= [ msg-condition | timeout-condition ] script-var-condition 
                 |  msg-condition | timeout-condition 
 msg-condition ::= (msg rule-message-pattern) 
 timeout-condition ::= (timeout timeout) 
 script-var-condition ::= (test rule-lisp-form) 
 rule-message-pattern ::= message-class [ sender ] { slot-name rule-pattern-value }* 
 slot-name ::= keyword 
 timeout ::= rule-lisp-form 
 action ::= { rule-action-lisp-form }* 

The syntax of rule-message-pattern is same as that of the message-pattern used in define-message-pattern macro except the followings.

Timeout should be evaluated to a number, and the timeout condition is satisfied after timeout seconds elapsed after the state transition to this state occurs. rule-lisp-form is same as lisp form except that the two rule macros ($ for accessing script variables and ! for invoking script/agent functions) are available. Similarly in rule-lisp-action-form, in addition to $ and ! macros, goto-state, invoke-script and exit-script macros are also available.

Macro: define-script-state (state-name script-name) { script-state-options }*

script-state-options ::= :script-vars-used ({ script-var }*) 
                            | :on-entry rule-lisp-form 
                            | :rules ({ rule-spec }*) 
                            | :priority number 
                            | :documentation doc-string 

This macro defines a state named state-name of a script named script-name. Script variables declared in :script-vars-used option can be accessed inside :on-entry as well as inside rule-spec. When :on-entry is defined, :on-entry rule-lisp-form is called when the state transition to this state occurs. :rules options defines transition rules at this state.

rule-spec ::= rule | (:named rule-name [:here])

A state transition rule can be defined as rule, which is local to this state. In addition, a state transition rule defined using define-script-rule can be specified using :name designation. :here specifies how an inheritance of named rule is handled. Suppose that Script SubScript which inherits Script SuperScript is defined. Suppose also that both scripts defines a rule named Rule1, and Script SuperScript defines State State1, which is inherited in Script SubScript. In Script SubScript, a rule designated as (:name Rule1) defined in State State1 refers to the rule named Rule1 defined in Script SubScript. However, a rule designated as (:name Rule1 : here) defined in State State1 refers to the rule named Rule1 defined in Script SuperScript, not SubScript. Note that the definition of State State1 is inherited from SuperScript.

:priority specifies the priority of this state. This value is used to choose a rule to be fired when multiple states are active at the same time. The rule in the state with a higher priority has precedence.

Note: nil is not allowed as a state name.


(define-script-state (start cnet-manager)
  :script-vars-used (task contract-id)
  :on-entry (progn (setf contract-id (! announce-task task))
                   (goto-state 'announced)))

(define-script-state (announced cnet-manager)
  :script-vars-used (task bid-queue contract-id)
  ((:when (msg bid :contract-id !contract-id)
    :do (if (! send-award-immediately-if-possible msg bid-queue)
            (goto-state 'success)
            (push msg bid-queue)))
   (:when (timeout (task-expiration task))
    :do (if (! send-award-if-possible bid-queue)
            (goto-state 'success)
            (goto-state 'failure)))))

(define-script-state (success cnet-manager)
    :on-entry (exit-script t))

(define-script-state (failure cnet-manager)
    :on-entry (exit-script nil))

Function: remove-script-state script-name state-name

This function removes a state state-name from a script script-name. Note that state transition rules associated with this state are also removed.

Generic Function: run-script agent script-name &rest args

Primary Method: run-script (agent script-agent) script-name &rest args

This function invokes the script script-name. The arguments should match the lambda-list of the script script-name. The function returns a newly created context (see section Script Execution Context).

Note: This function can only invoke a toplevel script (i.e. no parent context exists). When a script is to be invoked inside a transition rule, use invoke-script instead.

Script Execution Context

When a script is invoked, a context is created. The context holds the various information regarding a script execution. The following macros are defined to access the context information. The default value of context is a current context.

Macro: current-state &optional context

current-state returns a name of a current state. If the script is exited, nil is returned.

Macro: exited-state &optional context

exited-state returns a name of the state when the script is exited. If the script is not exited, nil is returned.

Macro: parent-context &optional context

parent-context returns a parent context. If context is toplevel, nil is returned.

Macro: child-contexts &optional context

child-contexts returns a list of child contexts.

Rule Primitives

The following macros can be used inside a rule definition.

Rule Macro: $ script-var-name &optional context

This macro is used to access a script variable script-var-name. setf can be used with this $ macro.

Rule Macro: ! function-name &rest args

The agent function function-name is invoked with arguments specified by args. When such an agent function does not exist, a script function with the same name is searched for. If it is found, that script function is invoked instead. If there are no agent function nor script function is defined, an error is signaled.

The following macros can be used only inside rule-action-lisp-form.

Rule Action: goto-state state-name &optional context

This macro causes the state transition to the state state-name to occur.

Rule Action: invoke-script script-name &rest args

The script script-name is invoked with arguments given by args. The newly created context of an invoked script is considered as a child context of the current context. This action returns a newly created context.

Rule Action: call-script script-name &rest args

The script script-name is invoked with arguments given by args. Whereas invoke-script does not suspend the execution of a caller script, call-script does not return until the invoked script executes the exit-script rule action. The return value of call-script is the value of result argument given to exit-script.

Rule Action: exit-script &optional result context

The execution of a current script is exited. Internally, the script execution context is deleted if there is no child context of context. If there is a child context still executing, the context is deleted only after all the child contexts are deleted (by exiting each child script). The default value of result is nil.

Script/Agent Function

The agent function interface is provided to customize the script behavior for a particular agent. When an agent/script function is called (by a rule macro !), an agent function (function local to an agent which invoked the script) with the same name is searched for first. If it is found, this agent function is called. If not, the script function is called. Thus, the script function defines a default behavior of a script.

You can change the behavior of a script either by defining a new script inheriting the original script and defining script functions, or by defining an agent function for a particular agent.

Macro: define-agent-function (function-name agent-name) lambda-list { rule-form }*

The agent function function-name is defined for the agent agent-name.

Macro: define-script-function (function-name script-name) lambda-list { rule-form }*

The script function function-name is defined for the script script-name.

Macro: with-script-vars ({ script-var }*) { rule-form }+

Script variable script-var can be accessed without $ macro in rule-form. The with-script-vars macro can be used in define-agent-function, define-script-function, and transition rule definitions.

Function: call-super &rest args

This function can be used inside the definition of define-script-function to call the script function defined in the super script. If args is not given, the original arguments are passed to the super script function as the case with call-next-method in CLOS.

Generic Function: remove-agent-function agent-or-name function-name

Primary Method: remove-agent-function (agent script-agent) function-name

Primary Method: remove-agent-function (agent-name symbol) function-name

This method removes the agent function function-name defined in agent or defined in the agent agent-name.

Function: remove-script-function script-name function-name

This function removes the script function function-name from the script script-name.

Go to the first, previous, next, last section, table of contents.