Basic language reference
This chapter describes the Basic language of TMS Scripter, for the people who write scripts. The language is similar to Visual Basic and VBScript, with the differences described here. Each language of TMS Scripter has its own reference chapter with the same structure: see also the Pascal and JavaScript references.
The objects, functions and libraries available to a script depend on the application that runs it. This chapter describes the language and the routines that are always available; the documentation of your application tells which additional objects and libraries it provides.
A first example
Uses Classes
Dim Names, I
Function Greeting(Name)
Greeting = "Hello, " & Name & "!"
End Function
Names = New TStringList
Try
Names.Add("Anna")
Names.Add("Bruno")
For I = 0 To Names.Count - 1
ShowMessage(Greeting(Names[I]))
Next
Finally
Names.Free
End Try
Script structure
A script is made of these parts, in this order, all of them optional:
- A
Usesclause listing the libraries and other scripts the script uses (see Using libraries and other scripts). - Global declarations:
Dim,Public,PrivateandConst. - Subs and functions.
- The main statements: the statements that run when the script is executed.
Sub SayHello
ShowMessage("Hello")
End Sub
SayHello
Each statement is on its own line. Several statements can be written on the same line, separated by colons:
A = 1 : B = 2 : C = A + B
A script can also contain only subs and functions; then the application calls them directly, for example as event handlers.
Script result
The main statements work like a function named Main: assign a value to Main, or use
Return with a value, to return it to the application. Applications use this to evaluate
expressions and formulas. If no value is assigned, the script returns Null.
Main = (10 + 6) / 4
Lexical elements
Case sensitivity
Basic is not case-sensitive: If, if and IF are the same keyword, and MyVar, myvar and
MYVAR are the same identifier. String values are case-sensitive.
Comments
An apostrophe or the word Rem starts a comment, which ends at the end of the line. Rem must
be at the beginning of the line or after a space or colon.
' a comment line
Total = Price * Quantity ' a comment after a statement
Rem another comment
A line starting with # is also a comment; the #FORM and #CLASS directives use this form
(see Declaring forms in script). Separate a
comment from the code before it with a space, and do not write a comment after Then at the
end of a multi-line If: write it on the next line.
Identifiers and reserved words
Identifiers (names of variables, constants, subs, functions and parameters) start with a letter
or an underscore, followed by letters, digits or underscores. Letters are the ASCII letters
A to Z.
Total _temp Item2 first_name ' valid
2Items first-name my name ' invalid
These reserved words cannot be used as identifiers: And, As, Case, Catch, Const,
Dim, Div, Do, Else, ElseIf, End, Except, Exit, Finally, For, Forward,
Function, If, Imports, Loop, Mod, Next, Not, Or, Private, Public, Return,
Select, Shl, Shr, Step, Sub, Then, To, Try, Until, Uses, While, With,
Xor. They are allowed as member names after a dot (Obj.End). An identifier can start with a
reserved word, like Format or Ending.
Numbers
42 ' integer
-7 ' negative integer
3.25 ' floating-point number
1.5e-2 ' floating-point number with exponent (0.015)
0xFF ' hexadecimal integer (255)
A number without fraction and exponent is an integer; integers are 64-bit values. Hexadecimal
numbers use the 0x prefix (&H is not supported).
Strings
Strings are enclosed in double quotes. Two consecutive double quotes inside a string represent one double quote. Single quotes are ordinary characters inside a string.
S = "Hello, world"
S = "Say ""hi""" ' Say "hi"
S = "It's here"
S = "" ' empty string
To include special characters, use Chr with the character code:
"First line" & Chr(13) & Chr(10) & "Second line".
Special values
| Value | Meaning |
|---|---|
True, False |
Boolean values. |
Nothing |
No object. Object variables that refer to no object are Nothing. |
Null |
The null value. A variable that is never assigned is Null. |
Empty |
The unassigned value (converted to an empty string or zero). |
Variables
Declaring variables
Variables are declared with Dim. A type is optional (As Type): every variable can hold
values of any type (see Values and types). A
variable can be initialized in its declaration.
Dim Count
Dim Name As String
Dim A, B, C
Dim Total = 0
Dim Title As String = "Report"
A declared type documents the variable and, for object types, lets the script editor offer code completion for the members of the object. It does not restrict the values the variable can hold.
Variables must be declared before they are used. Some applications relax this rule: then assigning a value to an undeclared name creates the variable.
Scope
Variables declared outside subs and functions are global: they are visible in the main
statements and in every sub and function. Global variables can be declared with Public or
Private instead of Dim: Private variables are not visible to other scripts that use this
script; Dim and Public variables are.
Variables declared inside a sub or function are local to it, and a local variable hides a global variable with the same name.
Dim Counter ' global
Sub Increment
Dim Stp ' local
Stp = 1
Counter = Counter + Stp
End Sub
Counter = 0
Increment
Increment
ShowMessage(Counter) ' 2
Constants
Constants are declared with Const, globally or inside a sub or function, one per statement.
Their value can be an expression. A constant cannot be changed.
Const MaxItems = 100
Const Title = "Report"
Const HalfMax = MaxItems Div 2
Values and types
Variables, parameters and function results hold values of any type, and the type of the value can change when a new value is assigned. Scripts work with these kinds of values:
- integers (64-bit) and floating-point numbers;
- strings;
- Boolean values (
True,False); - dates and times (floating-point numbers: the integer part is the date, the fraction is the time of day);
- objects (or
Nothing); - arrays;
NullandEmpty.
Values are converted automatically when an operation needs another type, following the rules
of the Delphi Variant type:
&converts its operands to strings and concatenates them:"Total: " & 5is"Total: 5".+between two strings concatenates them. A string that contains a number is converted to a number when added to a number:"1" + 2is3. A string that does not contain a number cannot be added to a number:"Total: " + 5is an error. Use&to concatenate.- Comparisons between strings and numbers compare the numbers:
"10" = 10isTrue. - Arithmetic with
NullgivesNull.
Use the conversion routines (IntToStr, StrToInt, FloatToStr, VarToStr and others, see
Built-in routines) to convert values explicitly.
Expressions and operators
Arithmetic operators
| Operator | Operation | Example | Result |
|---|---|---|---|
+ |
Addition (or string concatenation) | 7 + 2 |
9 |
- |
Subtraction | 7 - 2 |
5 |
* |
Multiplication | 7 * 2 |
14 |
/ |
Division, always a floating-point result | 7 / 2 |
3.5 |
Div |
Integer division, truncated toward zero | 7 Div 2 |
3 |
Mod |
Remainder of the integer division | 7 Mod 2 |
1 |
^ |
Power, always a floating-point result | 2 ^ 3 |
8.0 |
- (unary) |
Negation | -X |
Division by zero with Div or Mod is an error. \ (integer division in VB) is not
supported: use Div.
Comparison operators
| Operator | Meaning |
|---|---|
= |
Equal |
<> |
Not equal |
<, > |
Less than, greater than |
<=, >= |
Less than or equal, greater than or equal |
In an expression, = is a comparison: A = B = 2 assigns to A the result of B = 2.
String comparisons are case-sensitive: "abc" = "ABC" is False. Use CompareText or
UpperCase to compare strings without case sensitivity.
Logical and bitwise operators
| Operator | Operation |
|---|---|
Not |
Logical negation |
And |
Logical and; bitwise and on integers |
Or |
Logical or; bitwise or on integers |
Xor |
Logical exclusive or; bitwise exclusive or on integers |
Shl, Shr |
Bitwise shift left and right |
And and Or are short-circuit operators: when the left operand decides the result, the
right operand is not evaluated. This makes expressions like the following safe:
If (Count > 0) And (Total Div Count > 10) Then ShowMessage("Average above 10")
Warning
Unlike Visual Basic, And and Or have a higher precedence than the comparison operators (see
Operator precedence). Always put comparisons in
parentheses when combining them: write (A > 0) And (B > 0), not A > 0 And B > 0.
Note
And, Or and Xor work as integer operations: with Boolean operands, the result may be the
integer -1 (true) or 0 (false) instead of True or False. Both work in any condition.
Not is always a logical operation: Not X is True when X is False or zero.
String operators
& concatenates two values as strings, converting numbers and other values to text. + also
concatenates two strings.
Msg = "You have " & Count & " new messages"
& has the same precedence as +: put arithmetic in parentheses when mixing them, as in
"Total: " & (A + B).
Object operators
Is tests if an object is an instance of a class, or of a descendant class:
Sender Is TButton.
Operator precedence
Operators with higher precedence are evaluated first. Operators with the same precedence are evaluated from left to right. Use parentheses to change the order.
| Precedence | Operators |
|---|---|
| 1 (highest) | Not, unary - and + |
| 2 | ^, Is |
| 3 | *, /, Div, Mod, And, Shl, Shr |
| 4 | +, -, &, Or, Xor |
| 5 (lowest) | =, <>, <, >, <=, >= |
Write a unary minus or plus right before its operand, without a space: -X, -(A + B).
Statements
Assignment
The assignment operator is =. The target can be a variable, an object property, an array
item or a string character. The Set keyword is optional.
Total = Price * Quantity
Button1.Caption = "OK"
Items[2] = "third"
Set List = New TStringList
If statement
If has a single-line form and a multi-line form.
In the single-line form, the statements follow Then on the same line; several statements are
separated by colons, and an Else part can follow on the same line. End If is optional.
If Total > 100 Then Discount = 10
If Total > 100 Then Discount = 10 Else Discount = 0
If Found Then Count = Count + 1 : ShowMessage("Found")
In the multi-line form, Then ends the line, the statements follow on the next lines, and
End If ends the statement. ElseIf and Else parts are optional.
If Score >= 90 Then
Grade = "A"
ElseIf Score >= 80 Then
Grade = "B"
Else
Grade = "C"
End If
The condition can be a Boolean value or a number (zero is false). Write a space after If
when the condition starts with a parenthesis: If (A > 0) Then.
Select Case statement
Select Case runs the statements of the Case whose value matches the selector. The selector
and the values can be of any type, including strings, and the values can be expressions.
Several values can share a Case, separated by commas. The optional Case Else part runs when
no value matches.
Select Case UpperCase(Fruit)
Case "LIME", "KIWI"
Color = "green"
Case "LEMON"
Color = "yellow"
Case "APPLE"
Color = "red"
Found = True
Case Else
Color = "unknown"
End Select
Only the first matching Case runs, and the selector is evaluated once. Ranges (Case 1 To 5)
and comparisons (Case Is > 5) are not supported: list the values.
For statement
For I = 1 To 10
Sum = Sum + I
Next
For I = 10 To 0 Step -2
ShowMessage(I)
Next
Stepsets the increment, which is 1 when omitted. It must be a number (negative or floating-point numbers are allowed); a negative step counts down.- The initial and final values are evaluated once, before the loop starts.
- If the range is empty (
For I = 5 To 1), the loop body does not run. - After the loop, the counter variable holds the final value plus one step.
Nextis written without the counter name.
Do Loop statement
Do..Loop repeats statements while (While) or until (Until) a condition is true. With the
condition after Do, it is tested before each iteration, so the statements may not run at all.
With the condition after Loop, it is tested after each iteration, so the statements run at
least once.
Do While I < Count
Process(I)
I = I + 1
Loop
Do Until I >= Count
I = I + 1
Loop
Do
K = I Mod J
I = J
J = K
Loop Until J = 0
Do
Line = ReadLn(F)
Loop While Line <> ""
While statement
While..End While repeats statements while a condition is true, tested before each
iteration:
While I < Count
Process(I)
I = I + 1
End While
Exit statements
| Statement | Effect |
|---|---|
Exit For |
Leaves the innermost For loop. |
Exit Do |
Leaves the innermost Do or While loop. |
Exit Sub |
Leaves the current sub. |
Exit Function |
Leaves the current function, which returns the value already assigned. |
For I = 0 To List.Count - 1
If List[I] = "END" Then Exit For
Process(List[I])
Next
Exit For must be used directly in a For loop (not in a Do loop inside it), and Exit Do
directly in a Do or While loop. There is no Continue statement: use an If around the
rest of the loop body.
Return statement
Return leaves the current sub or function. In a function, Return followed by a value on the
same line sets the result of the function. In the main statements, Return ends the script.
Function Max(A, B)
If A > B Then Return A
Return B
End Function
With statement
With gives direct access to the members of an object, without repeating its name:
With Button1
Caption = "OK"
Width = 100
End With
The class of the object must be known when the script is compiled: an object provided by the
application, or a variable declared with a class type (Dim B As TButton).
Subs and functions
Declaring subs and functions
A sub performs an action; a function also returns a value. Declare them before the main
statements. Parameter and result types are optional (As Type).
Sub ShowTotal(Value)
ShowMessage("Total: " & Value)
End Sub
Function Max(A, B)
If A > B Then
Max = A
Else
Max = B
End If
End Function
Function Average(Total As Double, Count As Integer) As Double
Average = Total / Count
End Function
A routine without parameters is declared without parentheses: Sub Refresh. A routine can
declare its own variables with Dim and constants with Const.
Subs and functions are public: other scripts that use this script can call them. Declare them
with Private to make them visible only in this script: Private Function Helper(X).
Returning a value
A function returns the value assigned to the function name, or the value of a Return
statement. The function name can be assigned and read any number of times; if no value is
assigned, the function returns Null.
Function Factorial(N)
Factorial = 1
Do While N > 1
Factorial = Factorial * N
N = N - 1
Loop
End Function
Parameters by value and by reference
Parameters are passed by value (ByVal, the default): the routine receives a copy, and
changing the parameter does not change the variable passed by the caller. Declare a parameter
with ByRef to pass it by reference: then the routine changes the variable of the caller. Only
a variable can be passed to a ByRef parameter (not an expression, an array item or a
property).
Sub Swap(ByRef A, ByRef B)
Dim Temp
Temp = A
A = B
B = Temp
End Sub
Dim X, Y
X = 1
Y = 2
Swap(X, Y) ' now X is 2 and Y is 1
Calling subs and functions
Arguments are always given in parentheses, also when calling a sub: ShowTotal(10). A routine
without parameters is called with or without empty parentheses (Refresh or Refresh()). The
number of arguments must match the declaration.
A routine must be declared before the code that calls it. To call a routine that is declared
later, for example in two routines that call each other, declare it first with Forward:
Function IsOdd(N) Forward
Function IsEven(N)
If N = 0 Then
IsEven = True
Else
IsEven = IsOdd(N - 1)
End If
End Function
Function IsOdd(N)
If N = 0 Then
IsOdd = False
Else
IsOdd = IsEven(N - 1)
End If
End Function
Routines can call themselves (recursion).
Error handling
Try..Catch
The statements between Try and Catch run; if an error occurs, execution continues in the
Catch part. Errors raised by the script, by the routines it calls and by the application are
all handled. Except can be used instead of Catch, and End instead of End Try.
Try
Value = StrToInt(Text)
Catch
ShowMessage("Invalid number: " & LastExceptionMessage)
Value = 0
End Try
Try..Finally
The statements of the Finally part always run, whether an error occurred or not; the error,
if any, continues after the Finally part. Use it to release resources:
List = New TStringList
Try
List.LoadFromFile(FileName)
Process(List)
Finally
List.Free
End Try
A Try block has either a Catch part or a Finally part. Nest two Try blocks to combine
both behaviors.
Raising errors
Raise raises an error with a message. The script stops at that point, unless the error is
handled by a Try..Catch block.
If Quantity <= 0 Then Raise("Quantity must be positive")
Information about the last error
Inside a Catch block, these values describe the error being handled:
| Name | Description |
|---|---|
LastExceptionMessage |
The error message. |
LastExceptionClassName |
The class name of the error (exception class). |
LastExceptionLine, LastExceptionCol |
The script position where the error occurred. |
LastExceptionHelpContext |
The help context number of the error. |
An error that is not handled stops the script, and the application receives it with its message and position.
Arrays
Square brackets create an array from a list of values. Arrays are zero-based, and items can be of any type. Nested arrays give multi-dimensional arrays. Items are accessed with square brackets too (not parentheses).
Dim Primes, Matrix, Item
Primes = [2, 3, 5, 7]
Item = Primes[1] ' 3
Primes[0] = 1
Matrix = [["a", "b"], ["c", "d"]]
Item = Matrix[1, 0] ' "c"
Item = Matrix[1][0] ' also "c"
Length(A)is the number of items;Low(A)andHigh(A)are the first and last indexes.VarArrayCreate([0, 9], 12)creates an array of 10 empty items.- Accessing an index out of the bounds is an error.
Strings
Besides the operators and the string routines (see Built-in routines), strings can be indexed with square brackets to read or change a single character. The first character has index 1:
S = "Hello"
C = S[1] ' "H"
S[1] = "J" ' S is "Jello"
Working with objects
The application makes objects available to scripts: the controls of a form, data objects, or
any other object of the application. Scripts can also create objects of the classes the
application provides, like TStringList.
Properties and methods
Use a dot to access properties and methods. Methods without parameters can be called with or without parentheses.
Edit1.Text = "Hello"
Width = Panel1.Width - 10
Memo1.Lines.Add("New line")
Memo1.Lines.Clear
Creating and destroying objects
New creates an object: it calls the Create method of the class, with the arguments given in
parentheses. Calling Create directly also works. Free destroys the object. To check if a
variable refers to an object, use Assigned(Obj): comparing with Nothing works only for
variables that were set to Nothing or to an object, not for variables never assigned.
Dim List, Lbl
List = New TStringList
Lbl = New TLabel(Form1)
List.Add("one")
List.Free
Default and indexed properties
Indexed properties take the index in square brackets. When a class has a default indexed property, the property name can be omitted:
S = Memo1.Lines.Strings[0]
S = Memo1.Lines[0] ' the same: Strings is the default property
Enumerations and sets
Enumeration values are used by name, like constants. To set a set property, assign an array of
values. Where a routine expects a set, convert the array with SetOf:
Panel1.Align = alClient
Label1.Font.Style = [fsBold, fsItalic]
Answer = MessageDlg("Save changes?", mtConfirmation, SetOf([mbYes, mbNo]), 0)
Events
To handle an event of an object, write a sub with the parameters of the event, and assign the sub name, as a string, to the event property:
Sub Button1Click(Sender)
ShowMessage("Clicked")
End Sub
Sub FormCloseQuery(Sender, ByRef CanClose)
CanClose = Memo1.Lines.Count > 0
End Sub
Button1.OnClick = "Button1Click"
Form1.OnCloseQuery = "FormCloseQuery"
Declare as ByRef the event parameters that the handler changes, like CanClose above.
Using libraries and other scripts
The Uses clause, at the beginning of the script, gives access to libraries: units of the
application (for example Classes, SysUtils, Dialogs or Forms, when the application
provides them) and other scripts.
Uses Classes, Dialogs, MyLibrary
The names of a library can be used directly, or qualified with the library name:
MyLibrary.Calculate(10). Imports loads a library without making its names directly
visible: they must be qualified.
When a script uses another script, the public global variables, constants, subs and functions of the other script are available to it:
' Script "MathLib"
Dim Precision
Function RoundTo2(Value)
RoundTo2 = Round(Value * 100) / 100
End Function
' Main script
Uses MathLib
Precision = 2
ShowMessage(RoundTo2(3.14159))
The main statements of a used script do not run when another script uses it, so its global variables start without a value. Initialize them in a routine of the library that the other scripts call.
The application defines where used scripts are found (another script it manages, or a file). A script used as a library can be written in any of the TMS Scripter languages.
Declaring forms in script
A script can declare a form, designed in a form file (.dfm, or .sfm in the TMS Scripter
IDE), and be used as a class to create and show instances of that form. The #FORM directive
at the beginning of the script gives the form class name and the form file:
#FORM TCustomerForm, customerform.dfm
Dim CustomerId ' a property of each form instance
Sub btSaveClick(Sender)
ShowMessage("Saving customer " & CustomerId & ": " & edName.Text)
Close
End Sub
Sub Init(AId)
CustomerId = AId
btSave.OnClick = "btSaveClick"
End Sub
- The components of the form file are available by name (
edName,btSave), and so are the properties and methods of the form itself (Caption,Close). - The global variables of the form script are properties of the form, and its subs and functions are methods. Each instance of the form has its own variable values.
- The form file must not contain event handlers: assign the events in script, as above.
Another script uses the form script and creates instances of the form class:
Uses Forms, CustomerFormScript
Dim F
F = New TCustomerForm(Application)
F.Init(42)
F.edName.Text = "John"
F.ShowModal
F.Free
Declaring classes in script
A script can declare a class with the #CLASS directive. The global variables of the script
are the properties of the class, its subs and functions are the methods, and its main
statements run when an instance is created (use them to initialize the properties).
#CLASS TCounter
Dim Count, Stp
Sub Increment
Count = Count + Stp
End Sub
Count = 0
Stp = 1
Uses CounterScript
Dim C
C = New TCounter
C.Stp = 5
C.Increment
ShowMessage(C.Count) ' 5
C.Free
Script classes cannot inherit from other classes. Calling Free is optional: objects of
script classes that are not freed are destroyed automatically later.
Calling DLL functions
Scripts can declare and call functions of DLLs (Windows only, when the application allows it). See Calling DLL functions.
Built-in routines
The routines available to every script (strings, conversions, math, date and time, dialogs,
files) are listed in Built-in routines. Applications can also
provide the VBScript library, with functions like MsgBox, InStr and UCase.