# Language Overview (Pascal) - Scripting

The FluidFlow Scripting Module executes scripts written in the Pascal syntax. It currently supports the following Pascal and Basic syntax: ▪begin .. end constructor ▪procedure and function declarations ▪if .. then .. else constructor ▪for .. to .. do .. step constructor ▪while .. do constructor ▪repeat .. until constructor ▪try .. except and try .. finally blocks ▪case statements ▪array constructors (x:=[ 1, 2, 3 ];) ▪^ , * , / , and , + , - , or , <> , >=, <= , = , > , < , div , mod , xor , shl , shr operators ▪Access to object properties and methods (Object.Method and ObjectName.Property) The following pages describe: ▪Script Structure ▪Identifiers ▪Assign Statements ▪Character Strings ▪Comments ▪Variables ▪Indexes ▪Arrays ▪if Statements ▪while Statements ▪repeat Statements ▪for Statements ▪case Statements ▪Function and Procedure Declarations ▪Exception Handling ▪DLL Functions Script Structure A script's structure is made up of two major blocks: a) procedure and function declarations and b) main block. Both of these are optional, but at least one should be present in a script. There is no need for the main block to be within a begin..end. It could be a single statement. Examples: // SCRIPT 1: procedure DoSomething; begin CallSomething; end; begin CallSomethingElse; end; // SCRIPT 2: begin CallSomethingElse; end; // SCRIPT 3: function MyFunction; begin result := 'Ok!'; end; // SCRIPT 4: CallSomethingElse; As in Pascal, statements should be terminated by the ";" character. Begin..end blocks are allowed to group statements. Identifiers Identifier names (variable names, function and procedure names, etc.) follow the most common rules in Pascal: ▪They must begin with a character (a..z or A..Z), or the '_' symbol. ▪They can be followed by alphanumeric characters or the '_' symbol. ▪They cannot contain any other character or spaces. Valid identifiers: VarName _Some V1A2 _____Some____ Invalid identifiers: 2Var My Name Some-more This,is,not,valid Assign Statements To assign a value or expression result to a variable or object property, use ":=". Examples: MyVar := 2; Button.Caption := 'This ' + 'is ok.'; Character Strings Strings (sequence of characters) are declared by using the single quote (') character. Double quotes (") are not used. You can also use #nn to declare a character inside a string, where nn refers to the ASCII code of a character. There is no need to use '+' operator to add a #nn character to a string. Examples: A := 'This is a text'; Str := 'Text ' + 'concat'; B := 'String with CR and LF char at the end'#13#10; C := 'String with '#33#34' characters in the middle'; Comments Comments can be inserted inside scripts using the // characters or (* *) or { } blocks. Using the // characters the comment will finish at the end of line. Examples: //This is a comment before ShowMessage ShowMessage('Ok'); (* This is another comment *) ShowMessage('More ok!'); { And this is a comment with two lines } ShowMessage('End of okays'); Variables You can declare variables using the var directive and its name. It is optional as to whether you include the variable's type in its declaration. Examples: // SCRIPT 1: procedure Msg; var S; begin S := 'Hello world!'; ShowMessage(S); end; // SCRIPT 2: var A; begin A := 0; A := A + 1; end; // SCRIPT 3: var S: string; S := 'Hello World!'; ShowMessage(S); Note you do not need to actually use the var directive, as variables are implicitly declared. The directive is provided to allow clarity in the script. Indexes Strings, arrays, and array properties can be indexed using the "[" and "]" characters. For example, if Str is a string variable, the expression Str[3] returns the third character in the string, while Str[I + 1] returns the character immediately after the one indexed by I. Examples: MyChar := MyStr[2]; MyStr[1] := 'A'; MyArray[1,2] := 1530; Lines.Strings[2] := 'Some text'; Arrays Scripting supports array constructors and variant arrays. To construct an array, use the "[" and "]" characters. You can construct a multi-dimensional (multi-indexed) array nesting array constructors. You can then access arrays using indexes. If an array is multi-indexed, separate the indexes using ",". If a variable is a variant array, the Scripting Module automatically supports indexing in that variable. A variable is a variant array if it was assigned using an array constructor or if it was created using the VarArrayCreate procedure. Note: Arrays are zero-based, i.e., they are indexed from 0. Examples: NewArray := [2, 4, 6, 8]; Num := NewArray[1]; // Num receives "4" // Create a 2-dimensional array MultiArray := [['green','red','blue'] , ['apple','orange','lemon']]; Str := MultiArray[0,2]; // Str receives 'blue' Str := MultiArray[1,0]; // Str receives 'apple' MultiArray[1,1] := 'pineapple'; // Replace 'orange' with 'pineapple' if Statements There are two forms of the if statement: if...then and if...then...else. In the case that the if expression is true, the statement (or block) after it is executed. If there is an else part and the expression is false, the statement (or block) after the else is executed. Examples: if J <> 0 then Result := I / J; if J = 0 then Exit else Result := I / J; if J <> 0 then begin Result := I / J; Count := Count + 1; end else Done := True; while Statements A while statement is used to repeat a statement or a block, while a control condition is evaluated as true. The control condition is evaluated before the statement. Hence, if the condition is false at the first iteration, the statement sequence is never executed. The while statement executes its statement (or block) repeatedly, testing the control condition before each iteration. As long as the condition returns true, execution of the statement (or block) continues. Examples: while Data[I] <> X do I := I + 1; while I > 0 do begin if Odd(I) then Z := Z * X; I := I div 2; X := Sqr(X); end; while not Eof(InputFile) do begin Readln(InputFile, Line); Process(Line); end; repeat Statements A repeat statement is used to repeat a statement or a block, until a control condition is evaluated as true. The repeat statement executes its sequence of constituent statements continually, testing a control condition after each iteration. When the condition returns true, the repeat statement terminates. The sequence is always executed at least once because the condition is not evaluated until after the first iteration. Examples: repeat K := I mod J; I := J; J := K; until J = 0; repeat Write('Enter a value (0..9): '); Readln(I); until (I >= 0) and (I <= 9); for Statements The Scripting Module supports for statements with the following syntax: for counter := initialValue to finalValue do statement The for statement sets counter to initialValue, repeats execution of its statement (or block) and increments the value of counter until counter reaches finalValue. Examples: // SCRIPT 1: for c := 1 to 10 do a := a + c; // SCRIPT 2: for i := a to b do begin j := i ^2; sum := sum + j; end; case Statements The Scripting Module supports case statements with the following syntax: case selectorExpression of caseexpr1: statement1; ... caseexprn: statementn; else elsestatement; end If the selectorExpression matches the result of one of the caseexprn expressions, the respective statement (or block) will be executed. Otherwise, the elsestatement will be executed. The else part of the case statement is optional. Example: case uppercase(Fruit) of 'lime': ShowMessage('green'); 'orange': ShowMessage('orange'); 'apple': ShowMessage('red'); else ShowMessage('black'); end; Function and Procedure Declarations Declaration of functions and procedures are similar to Pascal, with the difference that you don't specify variable types. To return function values, use the implicitly declared result variable. Examples: procedure HelloWorld; begin ShowMessage('Hello world!'); end; procedure UpcaseMessage(Msg); begin ShowMessage(Uppercase(Msg)); end; function TodayAsString; begin result := DateToStr(Date); end; function Max(A,B); begin if A > B then result := A else result := B; end; procedure SwapValues(var A, B); var Temp; begin Temp := A; A := B; B := Temp; end; Exception Handling Exceptions provide a way to trap runtime errors without halting the script and without awkward conditional statements. Exception handling is appropriate for errors whose chances of occurring are low or difficult to assess, but whose consequences are likely to be catastrophic (such as crashing the script); and for error conditions that are complicated or difficult to test for in if...then statements. It is possible to protect any block of code by wrapping it in a try...finally or try...except statement. try..finally is used when you want a block of code to be executed in the finally section, no matter what error has occurred in the main block. try…except is used when you want to take a specific course of action if and only if an error occurs. Examples: // try...finally var myFile; begin // Try to open the Test.txt file for writing to AssignFile(myFile, 'c:\Test.txt'); try ReWrite(myFile); // Write a couple of words to this file WriteLn(myFile, 'Hello'); WriteLn(myFile, 'World'); finally // No matter what happens, close the file. CloseFile(myFile); end; end; // try...except NumberStr := ''; // Prompt the user to enter a number as a string. if InputQuery('Input', 'Type a number from 1 to 5', NumberStr) then begin try // Convert this number to a float variable Number := StrToFloat(NumberStr); except // If an error occurs then display a message. raise('Not a valid number.'); end; end; DLL Functions The Scripting Module allows the importing and calling of external DLL functions. For example, the following declaration: function MyFunction(arg: integer): integer; external 'CustomLib.dll'; imports a function called MyFunction from CustomLib.dll. The Scripting Module also allows you to use a different name for the DLL function, like the following declaration: function MessageBox(hwnd: pointer; text, caption: string; msgtype: integer): integer; stdcall; external 'User32.dll' name 'MessageBoxA'; which imports the 'MessageBoxA' function from User32.dll (a Windows API library), renamed as 'MessageBox' to be used in script. Example: // Declaration of external function function MessageBox(hwnd: pointer; text, caption: string; msgtype: integer): integer; stdcall; external 'User32.dll' name 'MessageBoxA'; // Windows constants const MB_ICONQUESTION = $20; MB_YESNO = $4; IDYES = 6; begin if MessageBox(nil, 'Are you sure?', 'Confirmation', MB_ICONQUESTION + MB_YESNO) = IDYES then ShowMessage('User answered YES') else ShowMessage('User answered NO') end;