Brief: actions
State changes (<-, NEW, DELETE)
The CHANGE operator writes a value into a changeable property, the NEW operator adds an object of a concrete class, and the DELETE and CHANGECLASS operators delete an object or move it to another class:
[CHANGE] propertyId(expr1, ..., exprN) <- valueExpr [WHERE whereExpr]
NEW className WHERE whereExpr [TO propertyId(prm1, ..., prmN)]
NEW [alias =] className [AUTOSET] action
DELETE expr [WHERE whereExpr]
CHANGECLASS expr TO className [WHERE whereExpr]
A change is written for all argument sets satisfying the condition at once, as a single set operation. Analogy: UPDATE ... SET ... WHERE, not an assignment to a variable. On a class change or a deletion the platform clears the stored values of the data properties the object is no longer valid in.
setDiscount () {
discount(Customer c) <- 15 WHERE totalOrders(c) > 100;
NEW o = Order { date(o) <- currentDate(); }
}
Calls and sequencing
An action is dual to a property: a property says what the value is, an action says how it changes. It is declared by the ACTION statement:
name [caption] [(param1, ..., paramN)] { actionBody } [options]
The body in braces is a sequence: nested actions run in the order written; inside the block LOCAL properties can be declared that live only while the block runs. An action call is written as the name with arguments, [EXEC] actionId(expression1, ..., expressionN) [TO toProperty], or substituted directly as a value. Analogy: a procedure call.
Loops (FOR, WHILE)
The FOR operator runs its body once per object set for which the condition is not NULL; the WHILE operator recomputes the condition at every step, so the changes made by the body are taken into account:
FOR expression [ORDER [DESC] orderExpr1, ..., orderExprN]
[TOP topExpr] [OFFSET offsetExpr]
[NEW [alias =] className]
DO action
[ELSE alternativeAction]
WHILE expression [ORDER [DESC] orderExpr1, ..., orderExprN]
[NEW [alias =] className]
DO action
A loop is used when the body is genuinely row-by-row — a dialog, a message, an external call. The mechanisms are described in loop and recursive loop.
createDetails (Order o) {
FOR in(Sku s) NEW d = OrderDetail DO {
order(d) <- o;
sku(d) <- s;
}
}
Branching (CASE, IF)
Branching runs the action matching the condition that holds; a condition holds if its value is not NULL. In the IF ... THEN and CASE operators the condition is written out; in the MULTI operator it is that the call arguments match an action's signature, that is, dispatch by the argument class:
IF condition
THEN action
[ELSE alternativeAction]
CASE [exclusionType]
WHEN condition1 THEN action1
...
WHEN conditionN THEN actionN
[ELSE elseAction]
MULTI [exclusionType] action1, ..., actionN
message (Shape s) { MULTI { message[Square](s); }, { message[Circle](s); } }
The deferred variant is an abstract action, ABSTRACT: a base module declares the extension point and other modules add implementations to it (action extension).
Flow control
BREAKexits the innermost loop,CONTINUEmoves to its next iteration,RETURN [expression]exits the innermost action call with the given value as its result.TRY action [CATCH catchAction] [FINALLY finallyAction]—CATCHswallows the error, giving access to it throughmessageCaughtException[]andlsfStackTraceCaughtException[];FINALLYruns in any case. Analogy:try/catch/finally.NEWTHREAD action [dispatchClause]— execution in a separate thread, at once or on a schedule (SCHEDULE: a delay and a period).NEWEXECUTORpicks where the thread goes: a server pool, where the body runs in the caller's change session, or the client connection (CLIENT), where it gets a new session of its own in that connection's navigator.
Form actions
SHOW— opening a form in the interactive view; the passed objects become the current ones.DIALOG— the same opening as a value-input dialog: every object markedINPUTorCHANGEreturns its last current value to theDOblock.ACTIVATE— activation of a form, a tab, a property, or a set of objects in an object group.EXPAND/COLLAPSE— expanding and collapsing a form container and the nodes of an object tree.MESSAGEandINPUT— a message and a value input without a separate form.
ACTIVATE FORM formName
ACTIVATE TAB formName.componentSelector
ACTIVATE PROPERTY formPropertyId
ACTIVATE [seekDirection] formObjectId = expr
ACTIVATE [seekDirection] formGroupObjectId [OBJECTS formObject1 = expr1, ..., formObjectK = exprK]