Skip to content

AdoScript Commands

The following sections contain descriptions of the commands available in AdoScript. These can be roughly categorized as following:

The general structure of commands is as following:

leo-grammar
Keyword { Modifier } [ MainParameter ] { AttributeParameter | Modifier } [ Body ]
# Note: the curly brackets above denote "zero or more" occurrences.

Keyword : UppercaseIdentifier .

Modifier : LowercaseIdentifier .

MainParameter : anyValue .

AttributeParameter : varName:anyValue .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).
Keyword { Modifier } [ MainParameter ] { AttributeParameter | Modifier } [ Body ]
# Note: the curly brackets above denote "zero or more" occurrences.

Keyword : UppercaseIdentifier .

Modifier : LowercaseIdentifier .

MainParameter : anyValue .

AttributeParameter : varName:anyValue .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).

BREAK

Leave the enclosing WHILE or FOR (numeric or token) loop.

Syntax:

leo-grammar
BREAK .
BREAK .

Details:
Simply said it is used to "jump out" of a loop.

CALL

Calls a function in a dynamic link library (DLL).

Syntax:

leo-grammar
CALL dll:strValue function:strValue { InputParameter }
    [ result:varName ] [ freemem:strValue ] .
# Note: the curly brackets above denote "zero or more" occurrences.

InputParameter : varName:DllSupportedValue .

DllSupportedValue : intValue | realValue | strValue .
CALL dll:strValue function:strValue { InputParameter }
    [ result:varName ] [ freemem:strValue ] .
# Note: the curly brackets above denote "zero or more" occurrences.

InputParameter : varName:DllSupportedValue .

DllSupportedValue : intValue | realValue | strValue .

Details:
With CALL a function in a dynamic link library (DLL). The path to the DLL file is specified with dll. The function is specified through function using the C function declaration syntax. A combination of a return value type and (zero, one ore more) parameter value types is called a signature.

Supported return value types of a called DLL function are: void, long, double, char*. Supported parameter value types are: long, double, char*, long*, double*, char**, where the first three are input parameters and the last three are output parameters. All possible signatures for these types are supported.

If the return value type is char* or a parameter value type is char** the DLL is allocating memory to hold the string value. The freeing of this memory has to be done within a function of the DLL too, but the call to that "freemem" function is done by AdoScript. By default AdoScript calls a function freemem(char*) of the DLL if the memory is no longer needed (i.e. the string has been copied to an AdoScript runtime variable). If another function is specified with freemem in the CALL statement, that function is called instead.

All input parameters are passed as attributes with the CALL statement using the same names as the formal parameters in the function declaration, thus the names of the formal parameters must consist of lower case letters only. The output parameters are assigned to runtime variables, also with the same names as the formal parameters in the function declaration. The return value of the called function is assigned to the runtime variable specified with result or to the runtime variable result if the specification is omitted.

A relative path to the DLL file is evaluated according to the operating system. In general this means that system folders are checked and then the path is evaluated in relation to the current working directory. This is the ADOxx installation directory by default, but can be changed with certain commands (see SET_CWD). Note that any dependencies of the called DLL must also be accessible in the same manner.

In a running AdoScript at most one DLL is loaded at a time. At the first execution of a CALL in a running AdoScript the DLL is loaded. For any following CALL with the same DLL the loaded DLL is reused. If another DLL is called, or the running AdoScript terminates, a previously loaded DLL is unloaded. With this behavior data can be build up inside a DLL using multiple calls. Although DLLs are freed at termination of an AdoScript, it is a good style to provide and use a cleanup function if data is stored inside a DLL.

Example calling a DLL with AdoScript (for the relevant C++ code see dll1.cpp):

asc
# Functions returning void with input params only,
CALL dll:"dll1.dll" function:"void f_void_void ()"
CALL dll:"dll1.dll" function:"void f_void_long (long n)" n:4242
CALL dll:"dll1.dll" function:"void f_void_double (double d)" d:3.14
CALL dll:"dll1.dll" function:"void f_void_charptr (char *p)" p:"Hello World"
CALL dll:"dll1.dll" function:"void f_void_long_double_charptr (long n, double d, char* p)" n:4711 d:2.34 p:"Yippie"

# Functions returning long with input params only.
CALL dll:"dll1.dll" function:"long f_long_void ()" result:bla
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"long f_long_long (long n)" result:bla n:4242
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"long f_long_double (double d)" result:bla d:3.14
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"long f_long_charptr (char *p)" result:bla p:"Hello World"
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"long f_long_long_double_charptr (long n, double d, char* p)" result:bla n:4711 d:2.34 p:"Yippie"
CC "AdoScript" INFOBOX (bla)

# Functions returning double with input params only.
CALL dll:"dll1.dll" function:"double f_double_void ()" result:bla
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"double f_double_long (long n)" result:bla n:4242
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"double f_double_double (double d)" result:bla d:3.14
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"double f_double_charptr (char *p)" result:bla p:"Hello World"
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"double f_double_long_double_charptr (long n, double d, char* p)" result:bla n:4711 d:2.34 p:"Yippie"
CC "AdoScript" INFOBOX (bla)

# Functions with output params only.
CALL dll:"dll1.dll" function:"void f_get_long (long* bla)"
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"void f_get_double (double* bla)"
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"void f_get_charptr (char** bla)"
CC "AdoScript" INFOBOX (bla)

# Mixture
CALL dll:"dll1.dll" function:"void f_all (long nin, double din, char* pin, long* nout, double* dout, char** pout)" nin:2 din:3.14 pin:"It works!"
CC "AdoScript" INFOBOX ("nout: " + STR nout + "\ndout: " + STR dout + "\npout: " + pout)
# Functions returning void with input params only,
CALL dll:"dll1.dll" function:"void f_void_void ()"
CALL dll:"dll1.dll" function:"void f_void_long (long n)" n:4242
CALL dll:"dll1.dll" function:"void f_void_double (double d)" d:3.14
CALL dll:"dll1.dll" function:"void f_void_charptr (char *p)" p:"Hello World"
CALL dll:"dll1.dll" function:"void f_void_long_double_charptr (long n, double d, char* p)" n:4711 d:2.34 p:"Yippie"

# Functions returning long with input params only.
CALL dll:"dll1.dll" function:"long f_long_void ()" result:bla
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"long f_long_long (long n)" result:bla n:4242
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"long f_long_double (double d)" result:bla d:3.14
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"long f_long_charptr (char *p)" result:bla p:"Hello World"
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"long f_long_long_double_charptr (long n, double d, char* p)" result:bla n:4711 d:2.34 p:"Yippie"
CC "AdoScript" INFOBOX (bla)

# Functions returning double with input params only.
CALL dll:"dll1.dll" function:"double f_double_void ()" result:bla
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"double f_double_long (long n)" result:bla n:4242
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"double f_double_double (double d)" result:bla d:3.14
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"double f_double_charptr (char *p)" result:bla p:"Hello World"
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"double f_double_long_double_charptr (long n, double d, char* p)" result:bla n:4711 d:2.34 p:"Yippie"
CC "AdoScript" INFOBOX (bla)

# Functions with output params only.
CALL dll:"dll1.dll" function:"void f_get_long (long* bla)"
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"void f_get_double (double* bla)"
CC "AdoScript" INFOBOX (bla)
CALL dll:"dll1.dll" function:"void f_get_charptr (char** bla)"
CC "AdoScript" INFOBOX (bla)

# Mixture
CALL dll:"dll1.dll" function:"void f_all (long nin, double din, char* pin, long* nout, double* dout, char** pout)" nin:2 din:3.14 pin:"It works!"
CC "AdoScript" INFOBOX ("nout: " + STR nout + "\ndout: " + STR dout + "\npout: " + pout)

CC

Call an ADOxx API command belonging to a specific MessagePort.

Syntax:

leo-grammar
CC MessagePortName [ var:varName ] [ debug ] [ raw ] Command

MessagePortName : strValue
# Note: the MessagePortName MUST be a Literal.
CC MessagePortName [ var:varName ] [ debug ] [ raw ] Command

MessagePortName : strValue
# Note: the MessagePortName MUST be a Literal.

Details:
The CC (component call) command executes a ADOxx API command from a MessagePort. It is similar to the SEND command, but takes additionally care of handling the creation of the LEOgram necessary to call the MessagePort and processes the resulting answer to directly set variables in the current scope. As such it provides an easier method to send messages to components and get the needed information out of the answers The CC command behaves like a macro.

The Command element after the CC is a "LEO element" and is called a message element. It does not really belong to the AdoScript syntax, i.e. it would cause a syntax error without the leading CC element. The benefit of the CC form above is that the string does not have to be masked. If there are more parameters it is easier to write the "natural" LEO element than to construct a string which will be a LEO element, especially since often the evaluation of expressions is necessary. Expressions in the message element are evaluated before the message is sent.

For details on the available MessagePorts and their commands see the MessagePort documentation.

By default any attributes (variables) returned as part of the command's answer will be set as variables in the local scope. It is recommended to use any relevant result values or store them in a different variable before calling any other MessagePort command. An alternative approach is to specify a variable through var. This will store the received result values in the variable as an object. These can then be accessed by through the variable, for example if the answer is RESULT ecode:0 val:"Madrid", CC with var:result creates an object variable result with properties result.ecode = 0 and result.val = "Madrid". The benefit of this approach is that the current runtime variable set is not polluted with several result variables, making it less error-prone.

If raw is specified, then CC sends the message without previously evaluating expressions and substituting them by their current result value. This is needed when a message shall be sent which contains an AdoScript code, for example to keep variable names / expressions as part of the body provided with the "Application" SET_CMI_SELECT_HDL MessagePort command (and similar command).

There are also several options available to help debugging AdoScript code when it comes to calling MessagePort commands:

  • If debug is specified in a CC command, the the RESULT... LEOgram is displayed in a popup after the command has been executed. If it is not specified then the popup does not appear. This is the default debug behavior.
  • If the variable ccdebug is set to "always", then the debug behavior is assumed for every CC command even if debug is not specified.
  • If the variable ccdebug is set to "never", then the debug behavior will not occur even if debug is explicitly specified.
  • If the variable ccdebug has any other value or is undefined, then the default debug behavior is assumed.
  • If the variable ccdebugfile is set, the debug information will be written into a file instead of being shown in a popup. The value of ccdebugfile must either be a filepath (where the debug info is written to) or an empty string (showing popups instead).

Examples for calling "Core" GET_ATTR_VAL:

asc
# Directly setting variables in local scope based on command result / answer.
CC "Core" GET_ATTR_VAL objid:(objid) attrid:(attrid)
IF (ecode) {
  CC "AdoScript" ERRORBOX ("Error: " + errtext)
} ELSE {
  CC "AdoScript" INFOBOX ("Value: " + val)
}

# Setting properties of the result object based on command result / answer.
CC "Core" var:result GET_ATTR_VAL objid:(objid) attrid:(attrid)
IF (result.ecode = 0) {
  CC "AdoScript" ERRORBOX ("Error: " + result.errtext)
} ELSE {
  CC "AdoScript" INFOBOX ("Value: " + result.val)
}
# Directly setting variables in local scope based on command result / answer.
CC "Core" GET_ATTR_VAL objid:(objid) attrid:(attrid)
IF (ecode) {
  CC "AdoScript" ERRORBOX ("Error: " + errtext)
} ELSE {
  CC "AdoScript" INFOBOX ("Value: " + val)
}

# Setting properties of the result object based on command result / answer.
CC "Core" var:result GET_ATTR_VAL objid:(objid) attrid:(attrid)
IF (result.ecode = 0) {
  CC "AdoScript" ERRORBOX ("Error: " + result.errtext)
} ELSE {
  CC "AdoScript" INFOBOX ("Value: " + result.val)
}

Example showing also debug information:

asc
# Showing the debug popup.
CC "Core" debug GET_ATTR_VAL objid:(objid) attrid:(attrid)
# Writing to a debug file.
SETG ccdebugfile:"c:\\ccdebug.log"
CC "AdoScript" debug FILE_COPY from:"ei1.txt" to:"ei2.txt"
# Reverting debug behavior to default.
SETG ccdebugfile:""
# Showing the debug popup.
CC "Core" debug GET_ATTR_VAL objid:(objid) attrid:(attrid)
# Writing to a debug file.
SETG ccdebugfile:"c:\\ccdebug.log"
CC "AdoScript" debug FILE_COPY from:"ei1.txt" to:"ei2.txt"
# Reverting debug behavior to default.
SETG ccdebugfile:""

Examples for CC and SEND commands that would provide the same result:

asc
# Execute "AdoScript" INFOBOX using CC.
CC "AdoScript" INFOBOX "Primroses & elephants"
# Send message to "AdoScript" to execute INFOBOX using SEND.
SEND "INFOBOX \"Primroses & elephants\"" to:"AdoScript"

# Execute "Core" GET_ATTR_VAL using CC.
CC "Core" GET_ATTR_VAL objid:(objid) attrid:(attrid)
# Send message to "AdoScript" to execute GET_ATTR_VAL and process answer.
SEND ("GET_ATTR_VAL objid:" + STR objid + " attrid:" + STR attrid)
    to:"Core" answer:text
LEO parse:(text) get-int-value:ecode:"ecode" get-str-value:val:"val"
# Execute "AdoScript" INFOBOX using CC.
CC "AdoScript" INFOBOX "Primroses & elephants"
# Send message to "AdoScript" to execute INFOBOX using SEND.
SEND "INFOBOX \"Primroses & elephants\"" to:"AdoScript"

# Execute "Core" GET_ATTR_VAL using CC.
CC "Core" GET_ATTR_VAL objid:(objid) attrid:(attrid)
# Send message to "AdoScript" to execute GET_ATTR_VAL and process answer.
SEND ("GET_ATTR_VAL objid:" + STR objid + " attrid:" + STR attrid)
    to:"Core" answer:text
LEO parse:(text) get-int-value:ecode:"ecode" get-str-value:val:"val"

EXECUTE

Executes an AdoScript dynamically which can be read from a file or composed by an expression.

Syntax:

leo-grammar
EXECUTE Source [ scope:ScopeSpecification ] [ result:varName ] .

Source : file:strValue | strValue .

ScopeSpecification : separate | same | child | default .
EXECUTE Source [ scope:ScopeSpecification ] [ result:varName ] .

Source : file:strValue | strValue .

ScopeSpecification : separate | same | child | default .

Details:
The provided AdoScript code is executed at the place where the command is encountered. The code can be either provided through a path to a file by using the file parameter or directly as text through the main parameter.

The scope controls the areas in which variables are visible (accessible), both outside the EXECUTE and inside. EXECUTE has three possibilities for the scoping behavior:

  • scope:separate - does the execution in a new scope, in which no access to another scope apart from global variables is possible.
  • scope:child - creates a scope which is a sub-scope of the current scope. Therefore the variables visible where EXECUTE occurs are also visible within the EXECUTE execution.
  • scope:same - does the execution of the EXECUTE code as if the instructions are in the same scope as the EXECUTE command.

In the case of scope:default (or when scope is not specified) the variable xscope will be evaluated and used for the scope. If xscope has the value "child" or "same", then the scope will be scope:child or scope:same. In all other cases, the behavior will be like scope:separate.

Example to dynamically execute text entered by a user as AdoScript:

asc
CC "AdoScript" EDITBOX title:"AdoScript"
IF (endbutton = "cancel") {
  EXIT
}
SETL sUsersText:(text)
EXECUTE (sUsersText)
CC "AdoScript" EDITBOX title:"AdoScript"
IF (endbutton = "cancel") {
  EXIT
}
SETL sUsersText:(text)
EXECUTE (sUsersText)

Example for executing AdoScript code from a file:

asc
# Direct approach.
# Will also display the file name in case of error messages.
EXECUTE file:"d:\\\\test.asc"

# Manually reading the file content and executing.
CC "AdoScript" FREAD file:"d:\\\\test.asc"
EXECUTE (text)
# Direct approach.
# Will also display the file name in case of error messages.
EXECUTE file:"d:\\\\test.asc"

# Manually reading the file content and executing.
CC "AdoScript" FREAD file:"d:\\\\test.asc"
EXECUTE (text)

EXIT

Syntax:

leo-grammar
EXIT [ intValue ] .
EXIT [ intValue ] .

Details:
The EXIT command ends the running of AdoScript. In the case of hierarchical AdoScripts only the lowest running level will be finished. If the AdoScript belongs to a string and was called with the EXECUTE command, then the execution will continue after the EXECUTE command. If the AdoScript is part of a PROCEDURE, then the execution will continue after where the procedure has been called. The following example illustrates this behavior:

asc
PROCEDURE PROC_FOR_EXIT_EXAMPLE {
  CC "AdoScript" INFOBOX ("Inside procedure - before exit")
  EXIT
  # This code is not reached during execution.
  CC "AdoScript" INFOBOX ("Inside procedure - after exit")
}

CC "AdoScript" INFOBOX ("Before calling procedure")
PROC_FOR_EXIT_EXAMPLE
CC "AdoScript" INFOBOX ("After calling procedure")
PROCEDURE PROC_FOR_EXIT_EXAMPLE {
  CC "AdoScript" INFOBOX ("Inside procedure - before exit")
  EXIT
  # This code is not reached during execution.
  CC "AdoScript" INFOBOX ("Inside procedure - after exit")
}

CC "AdoScript" INFOBOX ("Before calling procedure")
PROC_FOR_EXIT_EXAMPLE
CC "AdoScript" INFOBOX ("After calling procedure")

If the intValue is specified, the Exit-Code (default: 0) will be given as the response to the AdoScript call. If the call is the EXECUTE statement, the exit code can be assigned to a variable.

FOR - Numeric

Loop a part of the code while incrementing / decrementing a number from one value to another.

Syntax:

leo-grammar
FOR varName from:NumericValue to:NumericValue [ by:NumericValue ]
    Body .

NumericValue : intValue | realValue .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).
FOR varName from:NumericValue to:NumericValue [ by:NumericValue ]
    Body .

NumericValue : intValue | realValue .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).

Details:
FOR repeats a statement sequence for a variable (provided as the main parameter) running from one value to another. At first, the value of the from expression is assigned to the variable with the given name and the statement sequence is executed. The variable can be used in expressions in the statement sequence. After this first execution of the statement sequence, the value is incremented by the value specified with by (default 1) and the statement sequence is executed again. This is repeated while the value of the running variable is less than or equal to the specified to value.

FOR - Tokens

Loop a part of the code for each token of a token string.

Syntax:

leo-grammar
FOR varName in:strValue [ sep:strValue ] Body .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).
FOR varName in:strValue [ sep:strValue ] Body .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).

Details:
This version of the FOR loop repeats a statement sequence for a variable (provided as the main parameter) running through a sequence of tokens. The token sequence is specified with in. Optionally, a separator can be specified with sep (default is the space character ). As an example, After executing the following code result has the value 69 (= 12 + 23 + 34). Please not that VAL is needed to transform the string value of ei to an integer value.

asc
SETL result:0
FOR ei in:"12 23 34" {
  SETL result:(result + VAL ei)
}
SETL result:0
FOR ei in:"12 23 34" {
  SETL result:(result + VAL ei)
}

FUNCTION

Defines a new function that can be used as part of an expression.

Syntax:

leo-grammar
FUNCTION FunctionNameAndScope { AttributeParameter } return:Expression .
# Note: the curly brackets above denote "zero or more" occurrences.

FunctionNameAndScope : UpperCaseIdentifier [ :global ]

AttributeParameter : varName:TypeName .

TypeName : string | integer | real | measure | time |
    array | map | lambda | object .
FUNCTION FunctionNameAndScope { AttributeParameter } return:Expression .
# Note: the curly brackets above denote "zero or more" occurrences.

FunctionNameAndScope : UpperCaseIdentifier [ :global ]

AttributeParameter : varName:TypeName .

TypeName : string | integer | real | measure | time |
    array | map | lambda | object .

Details:
The scope where the function is available can be changed by specifying :global after its name. By default a function is only available in the AdoScript where it is defined. When :global is specified it is available in every AdoScript.

Example for defining and calling a factorial function:

asc
FUNCTION factorial:global n:integer
    return:(cond(n <= 1, 1, n * factorial(n - 1)))
SETL m:(factorial(10))
CC "AdoScript" INFOBOX (m)
FUNCTION factorial:global n:integer
    return:(cond(n <= 1, 1, n * factorial(n - 1)))
SETL m:(factorial(10))
CC "AdoScript" INFOBOX (m)

IF

Create one or several conditional branches.

Syntax:

leo-grammar
IF boolValue Body
[ ELSIF boolValue Body ]
...
[ ELSE Body ] .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).
IF boolValue Body
[ ELSIF boolValue Body ]
...
[ ELSE Body ] .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).

Details:
With IF a conditional branch can be programmed. First, the IF condition is evaluated. If its value is non-zero, the following statement sequence is executed. Otherwise if there is an ELSIF clause, the associated condition is evaluated in the same way and so on. If none of the IF/ELSIF conditions is evaluated to a non-zero value, the ELSE statement sequence is executed (if one exists). After one of the construction parts was executed, no further conditions of the IF condition will be evaluated, but the AdoScript continues after the IF condition. Any number of ELSIF blocks may be used, but at most one ELSE block may be used.

LEO

Parse a LEOgram provided as a stiring.

Syntax:

leo-grammar
LEO parse:strValue { AccessCommand } .
# Note: the curly brackets above denote "zero or more" occurrences.

AccessCommand : get-elem-count:varName |
    set-cur-elem-index:intValue |
    get-keyword:varName |
    is-contained:varName [ :AttributeName ] |
    get-str-value:varName [ :AttributeName ] |
    get-int-value:varName [ :AttributeName ] |
    get-real-value:varName [ :AttributeName ] |
    get-tmm-value:varName [ :AttributeName ] |
    get-time-value:varName [ :AttributeName ] |
    get-modifier:varName:AttributeName .

AttributeName : strValue .
LEO parse:strValue { AccessCommand } .
# Note: the curly brackets above denote "zero or more" occurrences.

AccessCommand : get-elem-count:varName |
    set-cur-elem-index:intValue |
    get-keyword:varName |
    is-contained:varName [ :AttributeName ] |
    get-str-value:varName [ :AttributeName ] |
    get-int-value:varName [ :AttributeName ] |
    get-real-value:varName [ :AttributeName ] |
    get-tmm-value:varName [ :AttributeName ] |
    get-time-value:varName [ :AttributeName ] |
    get-modifier:varName:AttributeName .

AttributeName : strValue .

Details:
With LEO a LEOgram can be parsed which is given as a string. This can be useful if an external call delivers structured data in LEO format. A LEOgram is a string that follows the structure of a LEO-Program, except that it doesn't use functions or variables. The string containing the LEOgram is passed with parse. With get-elem-count the number of elements can be assigned to a variable. With set-cur-elem-index a current element can be set (element numbers run from 0 to n-1). The following read statements are related to the current element:

  • get-keyword - Get the element's keyword.
  • is-contained - Check if an attribute is specified.
  • get-_T_-value - Get the value of an attribute specified through AttributeName of type _T_ and store it in the variable provided through varName. If no attribute name is specified with, then the element's own value (main parameter) is taken. For _T_ one of the following types can be inserted: str, int, real, tmm (measure), time.
  • get-modifier - Get the modifier of an attribute.

Example with a LEOgram containing multiple elements:

asc
# A simple LEOgram as a string.
SETL leotext:"PERSON \"Liao\"   firstname:\"Sun-Tsu\" age:(25)
              PERSON \"Davion\" firstname:\"Victor\"  age:30"

# Parse the LEOgram the first time to get the number of elements in it.
LEO parse:(leotext) get-elem-count:elemcount

# Go through each element in the LEO text and show the users its values.
FOR curelem from:0 to:(elemcount - 1) {
  # Access the information of the current element
  LEO set-cur-elem-index:(curelem)
      get-str-value:fname:"firstname"
      get-str-value:lname
      get-int-value:age:"age"
  CC "AdoScript" INFOBOX (fname + " " + lname + " " + STR age)
}
# A simple LEOgram as a string.
SETL leotext:"PERSON \"Liao\"   firstname:\"Sun-Tsu\" age:(25)
              PERSON \"Davion\" firstname:\"Victor\"  age:30"

# Parse the LEOgram the first time to get the number of elements in it.
LEO parse:(leotext) get-elem-count:elemcount

# Go through each element in the LEO text and show the users its values.
FOR curelem from:0 to:(elemcount - 1) {
  # Access the information of the current element
  LEO set-cur-elem-index:(curelem)
      get-str-value:fname:"firstname"
      get-str-value:lname
      get-int-value:age:"age"
  CC "AdoScript" INFOBOX (fname + " " + lname + " " + STR age)
}

NEXT

Proceed to the next iteration of the enclosing loop.

Syntax:

leo-grammar
NEXT .
NEXT .

Details:
With NEXT, the current execution of the statement sequence of a loop is stopped and the enclosing WHILE or FOR (numeric or token) command is evaluated again.

PROCEDURE

Defines a new procedure that can be then used like a command in other parts of the code.

Syntax:

leo-grammar
PROCEDURE [ global ] ProcedureName [ MainParameter ] { AttributeParameter }
    Body .
# Note: the curly brackets above denote "zero or more" occurrences.

ProcedureName : UpperCaseIdentifier

MainParameter : TypeName:varName .

AttributeParameter : varName:TypeNameOrReference .

TypeNameOrReference : TypeName | reference .

TypeName : string | integer | real | measure | time |
    array | map | lambda | object .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).
PROCEDURE [ global ] ProcedureName [ MainParameter ] { AttributeParameter }
    Body .
# Note: the curly brackets above denote "zero or more" occurrences.

ProcedureName : UpperCaseIdentifier

MainParameter : TypeName:varName .

AttributeParameter : varName:TypeNameOrReference .

TypeNameOrReference : TypeName | reference .

TypeName : string | integer | real | measure | time |
    array | map | lambda | object .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).

Details:
With PROCEDURE sub programs with parameters can be defined. Longer scripts can so be structured and repeating code fragments can be avoided. Furthermore, the execution time is reduced as less code has to be parsed. A procedure defines a new AdoScript command. So the name of the procedure is a keyword (written in upper-case letters, see uc_identifier). It can then be used similar to other commands in AdoScript in accordance to its definition.

A procedure definition begins with the key word PROCEDURE, followed by the procedure name. After that, formal parameters and - enclosed in curly braces - the procedure body follow. The formal parameters define which parameters have to be specified for a procedure call. The procedure body contains the AdoScript code which is executed when the procedure is called. The scope where the procedure is available can be changed with the global modifier between the PROCEDURE keyword and the procedure's name. By default a procedure is only available in the AdoScript where it is defined. When global is specified it is available in every AdoScript

To define a main parameter specify its type followed by a colon and the name to be used as in the procedure's body. To define an attribute parameter, first its name has to be specified, followed by a colon and the type of the parameter. If the parameter is a reference parameter, reference has to be specified as the type.

Parameters are divided on the one hand into main parameters and attribute parameters and on the other hand into value parameters and reference parameters:

  • A main parameter appears in a procedure call as a nameless parameter directly after the keyword. They do however require a name for the definition, which allows to access them in the procedure's body. Attribute parameters always have to be specified together with their names. Such a name always begins with a lower-case letter. The specification of attribute parameters for a procedure call can be done in any order.
  • Value parameters are passing values to the procedure. This can well be done in form of an expression from which the passed value is evaluated at calling time. With a reference parameter a procedure can modify a given variable. Reference parameters can also be used to let a procedure return a value ("output parameter"). A reference parameter always has to be defined as an attribute parameter.

Example for a procedure definition and parameter types of a procedure call:

asc
# Defining the procedure.
PROCEDURE MYPROC integer:n val:string outval:reference
{
  SETL outval:(val + STR n)
}

# Calling the procedure.
MYPROC 123 val:"test" outval:a
# Showing the value of variable a to the user, which will be "test123".
CC "AdoScript" INFOBOX (a)
# Defining the procedure.
PROCEDURE MYPROC integer:n val:string outval:reference
{
  SETL outval:(val + STR n)
}

# Calling the procedure.
MYPROC 123 val:"test" outval:a
# Showing the value of variable a to the user, which will be "test123".
CC "AdoScript" INFOBOX (a)

First the procedure MYPROC is defined with an integer main parameter, a string parameter val and a reference parameter outval. The main parameter is accessed in the procedure's body through the variable name n. The value of outval is assigned to the variable passed at at the procedure call. This happens when the execution leaves the procedure body.

Afterwards the procedure MYPROC is called, where 123 is passed as the main parameter and "test" as an attribute parameter for val. The procedure can also directly access and modify the variable a, which has been passed through the outval attribute parameter of type reference. Therefore any changes to the value of the variable a inside the procedure are also available after the procedure has finished.

Hint

While Value parameters can be specified through literals or expressions, reference parameters must be specified by directly providing the variable name without any parentheses.

SEND

Send a message to a MessagePort to execute an ADOxx API command.

Syntax:

leo-grammar
SEND strValue to:MessagePortName [ answer:varName ]

MessagePortName : strValue
SEND strValue to:MessagePortName [ answer:varName ]

MessagePortName : strValue

Details:
The main parameter contains the command and any relevant parameters as a LEOgram to be sent to the MessagePort. The values returned from the MessagePort command can be stored in a variable specified through answer. The returned value is again a LEOgram with the keyword RESULT. A LEOgram is a string that follows the structure of a LEO-Program, except that it doesn't use functions or variables.

It is recommended to use the CC command instead if possible, as it takes care of handling the LEOgram data in both directions, reducing the complexity of calling the MessagePort commands and processing their results.

For details on the available MessagePorts and their commands see the MessagePort documentation.

Example for calling the GET_ATTR_VAL command of the "Core" MessagePort:

asc
SEND ("GET_ATTR_VAL objid:" + STR objid + " attrid:" + STR attrid) to:"Core" answer:text
LEO parse:(text) get-int-value:ecode:"ecode" get-str-value:val:"val"
IF (ecode) {
  # Error handling code
}
SEND ("GET_ATTR_VAL objid:" + STR objid + " attrid:" + STR attrid) to:"Core" answer:text
LEO parse:(text) get-int-value:ecode:"ecode" get-str-value:val:"val"
IF (ecode) {
  # Error handling code
}

SETL / SETG / SET

Assign values to new or existing AdoScript runtime variables in different scopes.

Syntax:

leo-grammar
SETL { VariableAssignment } .
SETG { VariableAssignment } .
SET { VariableAssignment } .
# Note: the curly brackets above denote "zero or more" occurrences.

VariableAssignment : varName:anyValue | ArrayLValue:anyValue | MapLValue:anyValue .

ArrayLValue : varName [ intValue ] .
# Note: the square brackets of the ArrayLValue are needed (terminal symbols).

MapLValue : varName [ anyValue ] .
# Note: the square brackets of the ArrayLValue are needed (terminal symbols).
SETL { VariableAssignment } .
SETG { VariableAssignment } .
SET { VariableAssignment } .
# Note: the curly brackets above denote "zero or more" occurrences.

VariableAssignment : varName:anyValue | ArrayLValue:anyValue | MapLValue:anyValue .

ArrayLValue : varName [ intValue ] .
# Note: the square brackets of the ArrayLValue are needed (terminal symbols).

MapLValue : varName [ anyValue ] .
# Note: the square brackets of the ArrayLValue are needed (terminal symbols).

Details:
The three available commands assign values to new or existing AdoScript runtime variables. They differ in what scope the variable will be placed. SETG changes / creates variables in the global scope, where they exist for the whole ADOxx session (until ADOxx is closed / reloaded), that it can be re-used in succeeding executions of the same or other AdoScripts. SETL changes / creates variables in the local scope, where they exist for the duration for the execution of the current AdoScript or procedure. SET uses both scopes:

  • If a variable exists in the local scope, then SET overwrites the local variable's value.
  • If a variable does not exist in the local scope, but exists in the global scope, then SET overwrites the global variable's value.
  • If a variable does not exist in either scope, then SET creates a new local variable.

It is recommended to use SETL or SETG instead of SET unless there is a good reason not to do so. Otherwise there is the risk of changing a variable which you did not think of with this command.

It is also possible to change the values of an array by using ArrayLValue and specifying the index between square brackets ([]). However, it is not possible to change the size of the array with this command, as the index must be within the range of the array size (from 0 to n-1). To manipulate the size of the array use the available Array functions.

Furthermore the value assigned to a key of a map can also be changed with this command by using MapLValue and specifying the key between square brackets ([]). It is possible to add new keys to the map this way. However, it is not possible to remove existing keys with this command. Instead use the corresponding Map functions.

Example using a global variable to count the number of executions:

asc
IF (type(numcalls) = "undefined") {
  SETG numcalls:1
} ELSE {
  SETG numcalls:(numcalls + 1)
}
CC "AdoScript" INFOBOX ("Number of calls: " + STR numcalls)
IF (type(numcalls) = "undefined") {
  SETG numcalls:1
} ELSE {
  SETG numcalls:(numcalls + 1)
}
CC "AdoScript" INFOBOX ("Number of calls: " + STR numcalls)

Example showing the different scopes:

asc
# Declares the global variable 'a' and inits it with '0'
SETG a:0    # global a
CC "AdoScript" INFOBOX ("Before SCOPE_TEST: " + STR a)  # Prints '0'
SCOPE_TEST
CC "AdoScript" INFOBOX ("After SCOPE_TEST: " + STR a)   # Prints '1'

EXIT

PROCEDURE SCOPE_TEST {
  # Changes the value of the global variable 'a' to '1'
  SET a:1     # global a
  CC "AdoScript" INFOBOX ("SCOPE_TEST - 1st SET: " + STR a)   # Prints '1'
  # Declares the local variable 'a' and inits it with '2'
  SETL a:2    # local a
  CC "AdoScript" INFOBOX ("SCOPE_TEST - SETL: " + STR a)      # Prints '2'
  # Changes the value of the local variable 'a' to '3'
  SET a:3     # local a
  CC "AdoScript" INFOBOX ("SCOPE_TEST - 2nd SET: " + STR a)   # Prints '3'
}
# Declares the global variable 'a' and inits it with '0'
SETG a:0    # global a
CC "AdoScript" INFOBOX ("Before SCOPE_TEST: " + STR a)  # Prints '0'
SCOPE_TEST
CC "AdoScript" INFOBOX ("After SCOPE_TEST: " + STR a)   # Prints '1'

EXIT

PROCEDURE SCOPE_TEST {
  # Changes the value of the global variable 'a' to '1'
  SET a:1     # global a
  CC "AdoScript" INFOBOX ("SCOPE_TEST - 1st SET: " + STR a)   # Prints '1'
  # Declares the local variable 'a' and inits it with '2'
  SETL a:2    # local a
  CC "AdoScript" INFOBOX ("SCOPE_TEST - SETL: " + STR a)      # Prints '2'
  # Changes the value of the local variable 'a' to '3'
  SET a:3     # local a
  CC "AdoScript" INFOBOX ("SCOPE_TEST - 2nd SET: " + STR a)   # Prints '3'
}

Example for changing array and map elements:

asc
# One dimensional array.
SETL array1:({"Bonn", "Köln", "Leverkusen", "Wuppertal"})
SETL array1[2]:"Siegburg"   # replaces "Leverkusen"

# Two dimensional array.
SETL array2:({ {4711, 4712}, {6006, 6007} })
SETL array2[0, 1]:2011         # replaces 4712
SETL array2[1]:({7755, 7756})  # replaces {6006, 6007}
#SETL array2[0][1]:2012        # syntax error! [][] just allowed in expressions.

# Map.
SETL map1:({"a":1, "b":"two", 7: "seven"})
SETL map1["a"]:(array1[1])     # replaces value of key "a"
SETL map1[7]:("still seven")   # replaces value of key 7
SETL map1[5]:("something new") # adds new key-value pair
# One dimensional array.
SETL array1:({"Bonn", "Köln", "Leverkusen", "Wuppertal"})
SETL array1[2]:"Siegburg"   # replaces "Leverkusen"

# Two dimensional array.
SETL array2:({ {4711, 4712}, {6006, 6007} })
SETL array2[0, 1]:2011         # replaces 4712
SETL array2[1]:({7755, 7756})  # replaces {6006, 6007}
#SETL array2[0][1]:2012        # syntax error! [][] just allowed in expressions.

# Map.
SETL map1:({"a":1, "b":"two", 7: "seven"})
SETL map1["a"]:(array1[1])     # replaces value of key "a"
SETL map1[7]:("still seven")   # replaces value of key 7
SETL map1[5]:("something new") # adds new key-value pair

START

Asynchronously start an application in the operating system's environment.

Syntax:

leo-grammar
START strValue [ cmdshow:WindowState ] .

WindowState : showmaximized | showminimized | showminnoactive | shownormal .
START strValue [ cmdshow:WindowState ] .

WindowState : showmaximized | showminimized | showminnoactive | shownormal .

Details:
Starts an application in the operating system's environment. The call is asynchronous, so the AdoScript process continues immediately while the called application is running in parallel. The optional cmdshow parameter specifies the initial state of the application's main window.

Example to start Notepad as a maximised window:

asc
START ("notepad") cmdshow:showmaximized
START ("notepad") cmdshow:showmaximized

SYSTEM

Synchronously executes a command in the operating system's environment.

Syntax:

leo-grammar
SYSTEM strValue [ with-console-window ] [ hide ] [ result:varName ] .
SYSTEM strValue [ with-console-window ] [ hide ] [ result:varName ] .

Details:
Executes a command in the operating system's environment. The call is synchronous, so the AdoScript process waits until the execution of the command is terminated. The result of the executed command can be assigned to an AdoScript runtime variable specified with result. By default no shell window appears. If one is needed, then specify with-console-window. Using hide lets an existent shell window appear in the background, not in the foreground.

If you want to use features of the command shell directly call the command shell with "cmd /c [command]". Features of the command shell are built-in commands like del and writing output to a file using command line redirection > [filename] .

Example letting a user edit a file filepath:

asc
SYSTEM ("notepad " + filepath)
SYSTEM ("notepad " + filepath)

Example for deleting a file through the command shell:

asc
SYSTEM ("cmd /c del " + filepath) result:rc
IF (rc != 0) {
  # ...
}
SYSTEM ("cmd /c del " + filepath) result:rc
IF (rc != 0) {
  # ...
}

WHILE

Loop a part of the code as long as a condition evaluates to non-zero.

Syntax:

leo-grammar
WHILE boolValue Body .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).
WHILE boolValue Body .

Body : { StatementSequence } .
# Note: the curly brackets of the Body are needed (terminal symbols).

Details:
With WHILE a conditional loop can be programmed. At first the entry condition is evaluated. If its value is non-zero, the following statement sequence is executed and afterwards the condition is evaluated again. Otherwise the execution of the AdoScript is continued with the next element (following the closing curly brace of the WHILE element).