UniScript Manual

UniScript Manual
Release R2016
Uniplot Software GmbH
June 08, 2017
Contents
1
What is UniScript?
2
UniScript in Examples
2.1 Matrix algebra . . . . . . . .
2.2 Command Line editing . . . .
2.3 Using an Editor . . . . . . . .
2.4 Temperature table - 1. Version
2.5 Temperature table - 2. Version
2.6 Temperature table - 3. Version
2.7 Temperature table - 4. Version
2.8 Plot the Temperature Table . .
3
4
5
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Elements of UniScript
3.1 Comments in UniScript . . . . .
3.2 Continuation Line . . . . . . . .
3.3 Constant Expressions . . . . . . .
3.4 Numeric Constants . . . . . . . .
3.5 Hexadecimal and Octal Constants
3.6 Complex Constants . . . . . . . .
3.7 String Constants . . . . . . . . .
3.8 “Long” strings . . . . . . . . . .
3.9 Null-characters in Strings . . . .
3.10 Variables . . . . . . . . . . . . .
3.11 Vectors and Matrices . . . . . . .
3.12 Index Expressions . . . . . . . .
Operators
4.1 Arithmetic Operators .
4.2 Comparison Operators
4.3 Boolean Expressions .
4.4 Bitwise Operators . .
4.5 Operator Precedence .
Control Statements
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
4
5
5
6
9
9
10
11
.
.
.
.
.
.
.
.
.
.
.
.
13
13
14
14
14
15
16
16
17
17
17
19
20
.
.
.
.
.
23
23
27
28
28
29
31
i
5.1
5.2
5.3
5.4
5.5
The if-else Statement . . . . . . .
The for Statement . . . . . . . .
The while Statement . . . . . . .
The break and continue Statement
The try-except Statement . . . . .
.
.
.
.
.
.
.
.
.
.
6
Functions for Vectors and Matrices
7
Functions
7.1 Function Syntax . . . . . . . . . . .
7.2 Function Parameters and Arguments .
7.3 Global and Local Variables . . . . .
7.4 The return Statement . . . . . . . . .
7.5 Multiple Return Values . . . . . . . .
7.6 Calling Functions from DLL‘s . . . .
7.7 COM-Interface . . . . . . . . . . . .
7.8 The Debugger . . . . . . . . . . . .
7.9 Some Annotations about Functions .
8
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
31
32
33
34
35
37
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
41
41
42
43
43
44
45
49
57
58
UniScript Objects
8.1 Introduction . . . . . . . . . . . . . .
8.2 Object-Constructor Syntax . . . . . . .
8.3 Standard Methods . . . . . . . . . . .
8.4 Methods for Objects . . . . . . . . . .
8.5 Operator Overloading . . . . . . . . .
8.6 Inheritance . . . . . . . . . . . . . . .
8.7 Functions calls with UniScript Objects
8.8 Example . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
61
61
63
64
65
66
72
73
74
Index
ii
.
.
.
.
.
77
CHAPTER 1
What is UniScript?
UniScript is a programming language which is integrated into UniPlot and can be used to perform the
following tasks:
• Extend UniPlot with new functions: For example, the data import and the legend functions are programmed with UniScript. You can tailor these functions to your own needs.
• Automate the creation of complete reports: You can write UniScript functions to automate these steps
among others - Load Data, Transform Data - Create Diagrams - Save and Print Reports.
• Perform complex mathematical operations with your data: UniScript has powerful functions to convert your data (for example, Search functions, Sort functions, FFT and other functions) and to display
the results in 2D or 3D plots.
For all of these tasks, UniScript is more suitable than programming languages like BASIC, FORTRAN
or C. UniScript is an interpreter language. You do not have to compile and link the programs as with C or
FORTRAN. Of course an interpreter is slower to execute a program than a compiler like C, but for some tasks
UniScript is almost as fast as some of these languages because most of UniScript’s operators can be applied
on vectors and matrices. These and some other characteristics, like transparent memory management, make
UniScript programs much shorter than programs written in C or in one of the other programming languages
mentioned.
UniScript is a small, compact language. It knows only three different data types (real numbers, complex
numbers and strings). Only the most important flow control structures are supported, but a great number of
operators are available.
If you are familiar with the C programming language you will notice the syntax of UniScript is similar to it
and you won’t have any problems to write your own programs with UniScript. If UniScript can not supply
the functions you need, you can integrate the functions into a Dynamic Link Library (DLL) written in C or
FORTRAN and load them into UniScript.
1
UniScript Manual, Release R2016
2
Chapter 1. What is UniScript?
CHAPTER 2
UniScript in Examples
The following examples will show you how to use UniScript. Start UniPlot and type in the examples
yourself.
Start UniPlot by double-clicking the UniPlot icon in the Program Manager. After UniPlot is started, click on
the calculator
button in the toolbar or select viewcommand-window. The UniScript command window
will look similar to this:
The asterisk * is the UniScript prompt. The prompt indicates that UniScript is ready for your input.
Now enter some of the following line expressions:
* 7+12
19.0000
5-7
*
-2.0000
3
* *5
15.0000
1/2
*
0.5000
(2+5)
*
*5
3
UniScript Manual, Release R2016
35.0000
* y = sin(0.5)
* y
0.4794
* y+2
2.4794
*
You can use UniScript as a powerful calculator. However, UniScript is also a matrix based system for
scientific and engineering calculations, as the next example will illustrate.
2.1 Matrix algebra
We want to solve this linear system
(︂
)︂ (︂ )︂ (︂ )︂
𝑥1
1
4 7
·
=
4
2 5
𝑥2
Type:
* a = [4,7;2,5]
* a
4.0000
7.0000
2.0000
5.0000
* b = [1;4]
* b
1.0000
4.0000
* x = a\b
* x
-3.8333
2.3333
* a * x
1.0000
4.0000
The arguments of a matrix must be enclosed in square brackets. Columns are separated by a comma and
rows are separated by a semicolon. The expression line x = a\b solves the linear system. UniScript uses
the powerful LAPACK-Library to solve the equation so that even large linear systems can be solved quickly
and stability.
UniScript has other matrix functions that compute the determinants, inverse or eigenvalues.
* det(a)
6.0000
a^-1
*
0.8333 -1.1667
-0.3333
0.6667
eig(a)
*
8.2749 + 0.0000i
0.7251 + 0.0000i
4
Chapter 2. UniScript in Examples
UniScript Manual, Release R2016
Eigenvalues will be computed as complex numbers. UniScript uses i to represent the imaginary part of a
complex number.
* (3 + 5i) * (2 + 7i)
-29.0000 + 31.0000i
Almost all math functions in UniScript can be used with complex numbers. Try sqrt(-1) as an example.
2.2 Command Line editing
• You can recall a previous command to edit or correct errors. To recall the command use the up or
down arrow keys (command history).
• The F7 key opens the command history dialog box.
• The F8 key recalls all the command lines which start with the same characters before the cursor.
• The ESC key clears the command line. The ESC key can also be used to interrupt a running function.
• The INSERT key switches from insert to the overtype mode and vice versa.
• The BACKSPACE key deletes the character before the insertion point.
• The DELETE key deletes the characters after the insertion point.
The command window is mainly used to test a command or to view the values of variables. In all other
cases, you should use an editor.
2.3 Using an Editor
You can create an editor by typing the command EdCreate(). To arrange the command window and the
editor window choose windowtile-vertical .
Type the following lines into the editor
a = [4, 7; 2, 5]
b = [1; 4]
print "The determinant of", a
print "is", det(a)
print "The solution of the equation"
print "a*x = b, with a = ", a
print "and b = ", b, "is", a\b
Save the new file under a name with the extension .ic (e.g. test.ic) and then choose uniscript-saveexecute. UniScript will execute the commands you typed into the editor. The output of the print commands
will be displayed in the command window.
To get help for a function, position the cursor on the function name and press the F1 key. If you place the
cursor on the function det, you will get the following help page:
2.2. Command Line editing
5
UniScript Manual, Release R2016
2.4 Temperature table - 1. Version
In the next example, we want to write a program that prints out a temperature table. In the first column,
we want the temperature to appear in degrees Fahrenheit. In the second column, we want the temperature
shown in Celsius. To convert the Fahrenheit temperature into Celsius, we use the equation C = 5 / 9 *
(F - 32).
0
20
40
...
260
280
300
-17.8
-6.7
4.4
...
126.7
137.8
148.9
First, delete the contents of the editor. Choose Edit=>Select All and then press the Delete key.
This example is taken from a book about the programming language C (Kernighan, Brian W., und Ritchie,
Dennis M.: Programming in C, Hanser, München, 1983). Besides highlighting the similarity of UniScript
and C, this example will show you some important aspects of programming which are as valid for UniScript
as for C.
The program that will print the temperature table looks like the following:
/* Converts
for f =
def main()
{
lower =
upper =
6
Fahrenheit to Celsius
0, 20, ..., 300 */
0;
/* lower boundary of the Temp. Table */
300; /* upper boundary */
Chapter 2. UniScript in Examples
UniScript Manual, Release R2016
step = 20;
/* step size */
fahr = lower;
while (fahr <= upper) {
celsius = (5.0 / 9.0) * (fahr - 32.0);
printf("%4.0f %6.1f\n", fahr, celsius);
fahr = fahr + step;
}
}
The first two lines are comments
/* Converts Fahrenheit to Celsius
for f = 0, 20, ..., 300 */
All characters between the comment characters /* and */ will be ignored by UniScript.
With
def main()
{
...
}
a program (a function) will be defined. The keyword def does not exist in C. In UniScript, a function
always starts with the keyword def. In C, the function name main indicates that this is the main function.
In UniScript, main has no special meaning and is a valid name like any other name.
The function name, main, is followed by parentheses () which usually contain a parameter list. In our
example, this list is empty. The parentheses are still necessary to indicate to UniScript (and the programmer)
that main is a function name. Braces { and } designate the beginning and the end of the function main.
They have the same meaning as begin and end as in other programming languages.
A declaration of the variables follows the open brace { in C. In UniScript you do not have to declare
variables.
The first statement is
lower = 0;
In this statement, the variable lower is assigned the value 0 as a double precision real number. In the C
program, lower was declared as an integer. UniScript does not know integer data types. UniScript knows
only three data types:
• Double-precision floating point values.
• Complex numbers as a pair of double-precision floating point values.
• Strings (sequence of characters).
You can create vectors and matrices for all three data types, as shown later in this manual.
The lines
upper = 0;
step = 20;
2.4. Temperature table - 1. Version
7
UniScript Manual, Release R2016
fahr = lower;
assign start values for the other variables. It follows a so called while statement:
while (fahr <= upper) {
...
fahr = fahr + step;
}
The while statement tests the expression in parentheses. In our example, it is the expression fahr <=
upper. If the expression is true, it executes the statements enclosed within the braces. After the statement
body has been executed, the expression is tested again, and if it is still true, the statements are executed once
more. This process is repeated until the expression is no longer true. If the expression is initially false, the
statement body of the loop is never executed.
The statement fahr = fahr + step increments fahr by step (by 20 in our example).
Note: When formatting functions, you could write all function statements justified to the left margin but the
program is easier to read if the statements are indented one tab position. Statements inside of loops or if
statements should be indented one more tab position. You can define tab sizes in the Editor. We recommend
a tab size of 4 blank spaces.
Inside the braces are two other statements
celsius = (5.0 / 9.0) * (fahr - 32.0);
printf("%4.0f %6.1f\n", fahr, celsius);
The first statement converts Fahrenheit to Celsius and the second statement prints the values for fahr and
celsius into the UniScript command window. The f character at the end of the function printf stands for
formatted.
In our example, printf has three arguments. The first argument is the format string "%4.0f %6.1f\n".
This string determines how printf should print the arguments fahr and celsius. For this purpose, the
format string contains the elements %4.0f and %6.1f. A format element starts with the % character. %4.0f
means that the parameter fahr will be printed with 4 digits and no decimal places. The f means that the
value will be printed as a float number. The format element %6.1f will print the celsius values with 6
digits. One of the digits will be a decimal place. Characters outside the format elements will be printed
directly like the blank character between the format elements in our example. The two characters, \n, cause
the next character to be printed into the new line.
The main function uses 5 variables: lower, upper, step, fahr and celsius. These variables were
created when the function was called up and they will be destroyed just before the function finishes.
You should type the program into an editor now. Save the file under celsius.ic. After you save the file,
choose the uniscript-save-execute.
You can execute the function by typing the name into the UniScript command window:
* main()
Take the time to experiment with this function. For example, change the format string of the printf function.
After you have changed something, choose the Save/Execute command and execute the function from the
command line.
8
Chapter 2. UniScript in Examples
UniScript Manual, Release R2016
2.5 Temperature table - 2. Version
In the next example, we want to write a new function which will have the same output as main() but
uses the for statement instead of the while statement. We call the function main2(). You can type the
function in the same file as main(). In UniScript, a file can contain more than one function.
/* Converts Fahrenheit to Celsius
for f = 0, 20, ..., 300
- 2. version - */
def main2()
{
for (fahr in 0:20:300) {
printf("%4d %6.1f\n", fahr, 5/9 * (fahr-32));
}
}
The for statement has the following syntax:
for (var in vector) {
...
}
for and in are keywords. var can be any valid variable name. vector stands for the name of a vector
or a constant vector. Vectors in UniScript can be created in different ways. One possibility is to separate the
elements by a comma and enclose them in square brackets:
vector = [0,20,40,60,80]
You can also generate a vector with an ":" operator in the following manner:
vector = start:step:end
step can be omitted (vector = start:end). In this case step is 1.0. The expression 0:2:10 will
generate a vector with the elements [0, 2, 4, 6, 8, 10].
The for statement
for (fahr in 0:20:300) {
printf("%4d %6.1f\n", fahr, (5/9)*(fahr-32.0));
}
first creates the vector, 0:20:300, and executes the statement body for each element of the vector. fahr
will be 0, 20, 40 to 300.
Counting the number of iterations is very common in loops. If you know how often you want to execute the
statements of a loop, the for statement is both less work to type and more natural to think of. Therefore,
main2() is a better solution than main().
2.6 Temperature table - 3. Version
But UniScript provides a more simple way to solve our temperature problem. In the following example, we
can do without a loop statement:
2.5. Temperature table - 2. Version
9
UniScript Manual, Release R2016
def main3()
{
fahr = (0:20:300)';
printf("%4.0f %6.1f\n", fahr, (5/9)*(fahr-32));
}
In main() and main2() we passed the scalar values 0, 20, 40 etc. to the printf function. In main3(),
we generate a column vector with the statement
fahr = (0:20:300)';
The transpose operator (’) transposes the row vector to a column vector. Because the fahr variable is a
column vector, the expression, (5/9)*(fahr-32), will create a column vector with as many elements
as the fahr variable. The printf function will execute the "%4.0f %6.1f\n" format string as often as
the vector has elements. printf has a built in for loop.
UniScript has many functions with built in for loops. The statement
y = sin(0:2*PI/100:2*PI)
will generate the y vector with 100 elements. This enables you to write very compact programs with
UniScript.
2.7 Temperature table - 4. Version
Now we want to print the temperature table as a single line statement. You can type the line directly into the
UniScript command window or into an editor.
For each uniscript-save-execute command, the statement will be executed and the table will be displayed in
the command window:
printf("%4d %6.1f\n", fahr = (0:20:300)', 5/9*(fahr-32));
The statement above demonstrates another example of UniScript’s ability to write compact programs. As in
C, the assignment operator can be used inside the statement.
As well as the printf function, UniScript provides another simpler output function. The print statement
does not need a format string or parentheses because it is not a function.
The statement
print [fahr = (0:20:300)', 5/9*(fahr-32)];
first generates a matrix with two columns from the two vectors and then prints it out in standard format.
If the statement would be typed without the square brackets,
print fahr = (0:20:300)', 5/9*(fahr-32)
then print would print one vector after the other.
10
Chapter 2. UniScript in Examples
UniScript Manual, Release R2016
The disadvantage of the print statement is that you do not have full control over the output. Secondly,
the print statement cannot write directly into a file, but this is possible with a special version of the printf
function, namely fprintf.
2.8 Plot the Temperature Table
As a last example, we will create a plot of the Fahrenheit/Celsius data with the plot function.
h = plot(fahr = 0:20:300, 5/9 * (fahr - 32))
The plot function itself is programmed in UniScript. The function draws the x- and y-axis and displays data
as a line plot. In the following screen you can see the result of the plot function call.
160
140
120
y-Title
100
80
60
40
20
0
-20
0
50
100
150
200
250
300
x - Title
The plot on your monitor might not look exactly like this; the plot function uses the standard settings (see
tools-options).
The plot function has created a new window, drawn a diagram with one x- and one y-axis into the window
and plotted the x- and y-coordinates as a line graph.
We will use the terms document, page, layer and dataset to describe the elements of a plot. A window
represents a page from a document. A document contains one or more pages. A page contains one or more
layers and each layer can hold one or more datasets and drawing objects (text objects, rectangles, lines,
arrows etc). A dataset contains the coordinates of the data points as well as information as to how the data
should be displayed inside of the coordinate system.
UniPlot is programmed in the object oriented programming language C++. Documents, pages, layers and
datasets are the objects created and manipulated by UniPlot/UniScript. UniScript itself is not an object
oriented programming language. UniScript uses handles to access the objects. A handle is a number that is
associated with the object. The handle is valid as long as the object exists.
The statement
h = plot(fahr = 0:20:300, 5/9 * (fahr - 32))
returns a vector of handles.
• h[1] is the handle of the page,
2.8. Plot the Temperature Table
11
UniScript Manual, Release R2016
• h[2] is the handle of the layer and
• h[3] is the handle of the dataset.
Choose windowtile-vertical to arrange the command and plot windows on the monitor.
Type the following into the command window:
PagePrint(h[1])
This command will send the document to your standard printer. All functions that work with plot documents
have the prefix Doc. To receive a list of all function names beginning with Doc, type what("Doc*").
* what ("Doc*")
DocAddPage
DocCanPaste
DocCopyPage
DocCreate
DocDataZoom
...
DocSetProtectionFlags
DocSetReadOnly
DocSetSummaryInfo
DocSetTitle
DocShow
54 function(s) defined
The what() function lists the names of all loaded functions.
what("Layer*") and what("XY*").
Try what(), what("Page*"),
Look for the description of the what function in the help system. To receive help for a certain function, type
the function name inside the command window, move the cursor one character to the left and press the F1
key. To clear the command line, press the ESC key.
To finish the plot, we need to change the axis titles:
LayerSetAxisTitle(h[2], "X", "Celsius")
LayerSetAxisTitle(h[2], "Y", "Fahrenheit")
PageReplot(h[1])
Normally, you would make these changes interactively with UniPlot. But if you want to write a program
that, for example, reads the axis title from a file, you need functions to access the different elements of the
plot an UniScript easily enables you to do this.
12
Chapter 2. UniScript in Examples
CHAPTER 3
Elements of UniScript
3.1 Comments in UniScript
A comment is text that is included in a program to explain what the program does and how it works. You
should add comments to your programs in order that you or another person understands the program at a
later time.
As in C, UniScript language comments start with the characters, /*, and end with */. UniScript also
supports the C++ comment format. This comment starts with a double-slash (//) sequence. Wherever this
sequence appears (unless it is inside a string), everything to the end of the current line is a comment.
Example:
/*
This is a comment
in C format.
*/
Comments in C format can appear wherever a blank is allowed, e.g.:
rvSignal = [1.4, 1.45, 133254.4 /* Error ? */, 1.53];
Comments in C format cannot be nested. This means that the character sequence, */, is not allowed inside
a /* */ comment.
If you add comments to your program, keep in mind the following hints: It is better to choose a descriptive
function name than to add a comment to a bad function name:
ssFilename = GetOpenFileName();
is easier to understand than
f = getname();
Comments are frequently used ignore source code lines as shown in the following example:
def hilb(n)
{
/*
h = zeros(n, n);
13
UniScript Manual, Release R2016
for (i in 1:n) {
for (j in 1:n) {
h[i;j] = 1/(i+j-1);
}
}
return h;
*/
// this is much faster than two for loops
x = 1:n;
x = x[ones(1,n); /* all columns */ ];
return 1./(x+x.'-1);
}
3.2 Continuation Line
If you do not have enough room on the line to type a statement, you can use .. to continue a statement on
the next line. UniScript will ignore all characters that appear after the two dots:
return (ones(1,m) .* 10) .^ ..
[s1+(0:m-2) * (S2-s1) ./ (m-1), S2];
Continuation characters can be used wherever a blank character is allowed. You cannot use them inside a
name or a constant.
To write a string in several lines use the .. continuation characters as shown here:
"This is a long constant string" + ..
" written in two lines"
Beginning with UniPlot R2013.11 the continuation characters can be omitted after a comma, a Semicolon
or a binary operator. That means the two colons .. in the example above are redundant.
3.3 Constant Expressions
Constants are static values UniScript uses during the execution of your program. There are two types of
constants: String constants and numeric constants. A constant may be a scalar, a vector or a matrix. A
numeric constant may contain complex values.
3.4 Numeric Constants
A simple numeric constant is a single number that can be an integer, a decimal fraction, a number in exponential notation or a complex number. Note that all numeric values are represented within UniScript in
double-precision floating point format. Complex numbers are stored as pairs of double-precision floating
point values.
Here are some examples:
14
Chapter 3. Elements of UniScript
UniScript Manual, Release R2016
123
12.8
+13.01e-3
12E3
The following numbers are not valid:
Incorrect
.03
12.
13.9D8
Correct
0.03
12.0
13.9E8
3,82
3.82
Number cannot start with a period
Number cannot end with a period
Character D as the exponent
character is incorrect
Decimal sign is a period and not a comma
UniScript uses the same rules as the programming language C.
If you want to use a name for a constant expression, you can use the #define statement. The #define
statement has the following syntax:
#define constant-name replace-text
Every time the UniScript interpreter finds the expression constant-name (except inside a string or a comment) it will be replaced by the replace text. The constant name must be a valid UniScript name, the replace
text can be any length.
Example for the constant pi
#define PI
3.1415926535897931
The constant PI can be used in a statement like u = 2 * PI * r. Constant names appear normally in
capital letters to distinguish them from variable names.
After the definition of the name PI, the constant can be used in every file, not only in the file where the
definition is located.
In the UniScript Editor numeric constants are colored dark red.
3.5 Hexadecimal and Octal Constants
As in C, integer constants can be written as hexadecimal or octal numbers. A hexadecimal number (Base
16) has the prefix 0x or 0X. For hexadecimal numbers, the digits 0...9 and the characters a...f (or
A...F) are allowed. Examples:
Hexadecimal Decimal
0x10
16
0xFF
255
0x0d
13
0x5
5
An octal number (Base 8) has the prefix 0. For octal numbers, only the digits 0...7 are allowed.
Examples:
3.5. Hexadecimal and Octal Constants
15
UniScript Manual, Release R2016
Octal
034
0377
Decimal
28
255
In the UniScript Editor hexadecimal constants are colored dark red.
3.6 Complex Constants
To specify complex constants, expressions can be written in the following forms: 3i, or 1.23e-8i, or
0xFFi. The letter i stands for the pure imaginary constant, defined as sqrt(-1). A space is not allowed
between the number and the i.
3.7 String Constants
A string constant consists of a sequence of characters in double quotes. Example:
"This is a string constant"
Some characters cannot be included literally in a string constant. Instead, they can be represented with
escape sequences, which are character sequences beginning with a backslash ("\"). For instance, the
escape sequence \n represents a newline. In the following example, the words "string constant"
will be printed into a new line:
"This is a\nstring constant"
Here is a table of all the escape sequences used in UniScript. They are the same as those used in the C
programming language.
Code
\\
\n
\r
\b
\f
\t
\a
\"
\zzz
Meaning
Represents a literal backslash, \
a newline
a carriage return
a backspace
a formfeed
a horizontal tab
the “alert” character
a literal double-quote character "
an integer
The number zzz represents a decimal, hexadecimal or octal number in the range 0...255 (decimal).
It defines the ASCII-Code for the appropriate character. For example, the following strings are identical:
"Hello\n", "Hello\10" and "Hello\0x0a".
The length of a constant string is limited to 255 characters. A variable can hold a string of unlimited length.
In the UniScript Editor string constants are colored red.
In hexadecimal form the character \x or \0x must be followed by exactly two hexadecimal characters (0 ..
16
Chapter 3. Elements of UniScript
UniScript Manual, Release R2016
f).
In decimal an octal form all decimal (0 .. 9) or octal (0 .. 7) numbers will be read. If the number is greater
than 255 (decimal) the number will be reduced to one byte. Example: "\300a" is not identical to "\30"
+ "0a".
If a string has a prefix r, e.g. r"Hello\10" all backslashes will be left in the string. r"Hello\10" is
identical to "Hallo\\10". Inside a simple string with the r prefix the "-character cannot be used.
3.8 “Long” strings
As of UniScript 4.0 so called “long strings” are available. These strings start with "[[ and end with ]]".
Example:
a = "[[
This is a long
string constant
]]"
is identical to:
a = "\nThis is a long\nstring constant\n"
In long string constants the “-character can be used with or without the leading backslash. The r prefix can
be used.
3.9 Null-characters in Strings
Beginning with UniScript 4.2.0 character strings can contain Null characters (eight-bit clean Strings). The
advantage is that UniScript-Strings can contain binary data. The + operation can be used for strings containing Null characters. The comparison operators only compare the strings to the first Null character:
"Hello\x00Hello" == "Hello"
returns TRUE (1). To compare the complete character string the mem_compare function can be used.
Many string functions will only use the string to the first Null character, for example:
strlen("Hello\x00Hello")
returns 5. The function mem_len("Hello\x00Hello") will return 11.
3.10 Variables
Variables are the names that you have chosen to represent values used in an UniScript program. Variables
may represent either numeric values or strings. Variables may not be used before they have been given a
value. Doing so results in an error.
The following statement will assign the value 1 to the variable a:
3.8. “Long” strings
17
UniScript Manual, Release R2016
a = 1
If a already exists, the old variable will be destroyed and a new variable will be created. The statement will
allocate memory for the constant value and then copy the value 1 into the memory. The old value of a could
be a string matrix or anything else. A variable in UniScript can change its type.
The name of a variable must be a sequence of letters, digits and underscores, but it may not begin with a
digit. The length of variable names is not limited in UniScript, however, only the first 80 characters are
significant. Case is also significant in variable names. For example var is not the same as Var.
The following identifiers are keywords and may not be used as variable or function names:
break
continue
def
else
except
for
global
if
in
print
return
try
while
Variable names should also be distinct from function names: sin = sin(1) is incorrect, but Sin =
sin(1) is correct.
Valid names for variables are:
_test
var1
This_is_a_valid_name
__
a1
Return
The following names are invalid:
1a
This is not a name
a?3
In larger programs it is recommended to choose names that indicate the data type they hold. Therefore, most
of the names used in UniScript functions have one of the following prefixes:
Example:
Name
ssFilename
svFilename
18
Meaning
ss stands for scalar string. ssFilename might therefore hold
only one file name.
sv stands for string vector. svFilename holds probably
more than one file name.
Chapter 3. Elements of UniScript
UniScript Manual, Release R2016
smSorted
rsXValue
rvMin
rmSize
bVisible
sm stands for string matrix.
rs stands for real scalar.
rv stands for real vector.
rm stands for real matrix.
b stands for boolean. A variable with this prefix should
only be assigned the values TRUE (1) or FALSE (0).
h stands for handle.
hv stands for handle vector.
n stands for numbers. The variable should only hold integers, e.g. 123.
hLayer
hvLayer
nLayer
3.11 Vectors and Matrices
The following statement will generate a row vector with the three elements 6, 4 and 13 and assign the vector
to the variable a:
a = [6, 4, 13]
If the variable was already used, the old value of a will be replaced by the new vector. a is a real vector with
three elements.
Once a variable has been given a value, it can be used in statements. The statement
b = a + 5
adds the value 5 to each element of the vector a and assigns the result to the variable b. b will then have the
value [11, 9, 18].
A range is a convenient way to create a row vector with evenly spaced elements. Example: [1, 2, 3,
4, 5, ..., n] or [1, 1.5, 2, ...]. Use the : operator in one of the following manners:
start:end
and
start:step:end
A range constant is defined by the value of the first element in the range, a maximum value which the
elements of the range will not exceed, and an optional value for the increment between elements. start,
step and end are separated by colons (:).
Example:
1:5
1.3:4
1:0.5:2
1:0.5:2.4
defines
defines
defines
defines
the
the
the
the
set
set
set
set
of
of
of
of
values
values
values
values
[1, 2, 3, 4, 5]
[1.3, 2.3, 3.3]
[1, 1.5, 2.0]
[1, 1.5, 2.0]
start can be greater than end
3.11. Vectors and Matrices
19
UniScript Manual, Release R2016
5:1
defines the set of values [5, 4, 3, 2, 1]
A vector in UniScript is a special form of a matrix. [6, 4, 13] is a 1 * 3 matrix. That means the
matrix has one row and three columns.
To create a column vector, the elements must be separated by a semicolon:
a = [1;2;3]
To change a column vector to a row vector (and vice versa), use the transpose operator (’):
b = a'
The following matrix, for example, can be seen as a combination of the row vectors [1,2,3], [4,5,6]
and [7,8,9].
⎛
⎞
1 2 3
⎝4 5 6 ⎠
7 8 9
A matrix in UniScript can be defined as the following:
m = [1,2,3; 4,5,6; 7,8,9]
A matrix can also be created from a combination of vectors and matrices, e.g.
⎡
⎤
1 2 3 10 11 16
⎣ 4 5 6 12 13 17 ⎦
7 8 9 14 15 18
m1
m2
v1
v2
=
=
=
=
[1,2,3; 4,5,6; 7,8,9]
[10,11; 12,13]
[14,15]
[16;17;18]
m = [m1, [m2;v1], v2]
3.12 Index Expressions
An index expression allows you to reference or extract elements of a matrix or vector.
If a = [1.5, 3.8, 6.3], then a[1] is the value 1.5, a[2] the value 3.8 and a[3] the value 6.3.
Indices are integers beginning with 1. Instead of a scalar index, you can also use an index vector. The
expression a[1, 3] will extract the values [1.5, 6.3] and a[1, 3, 1] will extract [1.5, 6.3,
1.5]. Single indices can be used more than once.
A vector variable with a index vector can stand on both sides of the assignment operator:
a = [1, 2, 3, 4, 5]
a[1, 4] = [-1, 66]
20
Chapter 3. Elements of UniScript
UniScript Manual, Release R2016
In this statement, the element a[1] will be assigned the value -1 and a[4] the value 66. In any case, the
index vector on both sides of the assignment operator must have the same number of elements.
After the statement is executed, the variable a is [-1, 2, 3, 66, 5].
The statement
a[1, 4] = a[4, 1]
will exchange the first and the fourth element of the vector without changing any other element.
The second line of the following statements
a = [1, 2, 3, 4, 5]
a[6] = 100
will result in an runtime error. The vector a contains 5 elements. The following statement will add a sixth
element to the vector a.
a = [a, 100]
A matrix can be accessed by two index vectors separated by one semicolon. The first vector is a row index
vector and the second is a column index vector. If the matrix a is [5,6;7,8] then a[1;1] is 5 and
a[1;2] is 6. The result of the expression a[1,2;1] is [5, 6], the first column of the matrix a.
If a row or column index vector is complete, it can be omitted. Instead of a[1,2;1], you can write a[;1]
to access the first row of the matrix a.
A matrix in UniScript is stored columnwise as a vector with one dimension. The elements of the following
matrix
are saved in the order [1, 4, 7, 2, 5, 8, 3, 6, 9]. The internal representation can be accessed
when the matrix is accessed with a one dimensional vector. Instead of a[2;3] (second row, third column),
this element can be accessed with the expression a[8]. To access all elements of the matrix a, you can
write a[1:9], this is equivalent to a[:].
Summary
var = start:step:end creates a row vector.
var = start:end creates a row vector with the increment 1.0.
var = [e1, e2, e3] creates a row vector.
var = [e1; e2; e3] creates a column vector.
var = [e1, e2; e3, e4] creates a matrix.
var[index-vector] references elements of a vector.
var[row-index-vector; column-index-vector] references elements of a matrix.
var[row-index-vector ; ] references the row elements of a matrix.
var[ ; column-index-vector] references the column elements of a matrix.
var[:] changes a matrix to a row vector.
3.12. Index Expressions
21
UniScript Manual, Release R2016
22
Chapter 3. Elements of UniScript
CHAPTER 4
Operators
Operators perform mathematical or logical operations on values. The operators provided by UniScript are
divided into three categories:
• Arithmetic
• Relational
• Logical
Operators in UniScript can be applied on scalar values, vectors and matrices. The following matrices have
special names:
Row * Column
1*1
1*m
n*1
n*m
n*n
Name
scalar
row vector
column vector
matrix
square matrix
4.1 Arithmetic Operators
4.1.1 Additive Operators
Most of the operators are performed on an element by element basis, e.g.:
(︂
)︂ (︂
)︂ (︂
)︂
1 2
5 6
6 8
+
=
3 4
7 8
10 12
The dimension of both operands must be equal. That means the number of rows and columns must be the
same, except in the case where one operand is a scalar.
(︂
)︂
(︂
)︂
1 2
6 7
+5=
3 4
8 9
or
(︂
)︂ (︂
)︂
1 2
6 7
5+
=
3 4
8 9
23
UniScript Manual, Release R2016
This is the only exception. Therefore, you cannot add a row vector to a column vector.
The + operator concatenates single strings to one string.
(︂
)︂
(︂
)︂
”𝑎𝑙𝑝ℎ”
”𝑏𝑒𝑡”
”𝑎𝑙𝑝ℎ𝑎”
”𝑏𝑒𝑡𝑎”
+ ”𝑎” =
”𝑔𝑎𝑚𝑚” ”𝑑𝑒𝑙𝑡”
”𝑔𝑎𝑚𝑚𝑎” ”𝑑𝑒𝑙𝑡𝑎”
Note:
["a", "b"] is a row vector with two elements,
"a" + "b" is the scalar string "ab".
4.1.2 Multiplication Operators
UniScript provides two multiplication operators: The matrix multiplication operator * and the multiplication
operator .* for an element by element multiplication denoted by placing a period (.) ahead of the *.
(︂
)︂ (︂
)︂ (︂
)︂
1 2
5 6
5 12
.*
=
3 4
7 8
21 32
The * matrix multiplication operator requires that the second dimension of the first operand be the same as
the first dimension of the second operand. Example:
)︂
)︂ (︂
)︂ (︂
(︂
19 22
5 6
1 2
=
*
43 50
7 8
3 4
If the first operand is a n * m matrix and the second operand is a m * q matrix, the resulting matrix will
have the dimension n * q.
2
3
*
6
5
9
8
5 3 8 100 94
2 5 1 43 39
4.1.3 Division Operators
UniScript provides three different matrix division operators. The ./ operator works on an element by
element basis like the .* or the + operator.
(︂
)︂ (︂
)︂ (︂
)︂
1 2
5 6
0.20 0.33
./
=
3 4
7 8
0.42 0.50
The matrix division operator / (right-hand division) performs the operation
x / y = x * y^-1 = (y' \ x')' = ((y')^-1 * x')'.
If the system is not square, a minimum norm solution will be calculated.
The matrix left division x\y is equivalent to the expression
24
Chapter 4. Operators
UniScript Manual, Release R2016
x\y = x^-1 * y
but it is computed without forming the inverse of x. Again, if the system is not square, a minimum norm
solution will be calculated.
An example:
* a = [4,7;2,5]
* a
4.0000
7.0000
2.0000
5.0000
b
=
[1;4]
*
* b
1.0000
4.0000
x
= a\b
*
x
*
-3.8333
2.3333
a
*
* x
1.0000
4.0000
a
= [1,2;3,4;5,6]
*
a
*
1.0000
2.0000
3.0000
4.0000
5.0000
6.0000
b
=
[7,8,9]'
*
* b
7.0000
8.0000
9.0000
x
= a\b
*
a
*
* x // check
7.0000
8.0000
9.0000
4.1.4 Modulus Operator
The % operator (which works like the + operator on an element by element basis) returns an integer value
that is the remainder of an integer division.
In the first step, both operands will be converted to integers (5.9999 will result in the number 5):
* 5 % 2
1.0000
5.999
% 2
*
1.0000
4.1. Arithmetic Operators
25
UniScript Manual, Release R2016
4.1.5 Power Operator
For the power operation x^y, x must be a scalar or a square matrix and y must be a scalar. If y is an
integer, the operation will be performed by multiplication. Otherwise, the operation will be performed by
computing the eigenvalues and eigenvectors of x (with the matrix of eigenvectors and the diagonal matrix
of the eigenvalues w).
* a = [1,2;3,4]
* a
1.0000
2.0000
3.0000
4.0000
* a^-1
-2.0000
1.0000
1.5000 -0.5000
* a*a^-1
1.0000
0.0000
0.0000
1.0000
* a^-1.1
-2.1088 + 0.6974i
1.5549 - 0.4785i
1.0366 - 0.3190i
-0.5539 + 0.2189i
The power operator works like the + operator on an element by element basis. That means that both operands
need to have the same dimension or that one operand is a scalar.
4.1.6 Transpose Operator
This unary operator performs the matrix transpose operation. Both transpose operators ’ and .’ have the
same result for real matrices. For a matrix with complex elements, a complex conjugate transpose operation
is performed.
* a = [1,2;3,4]
* a
1.0000
2.0000
3.0000
4.0000
* a'
1.0000
3.0000
2.0000
4.0000
* a.'
1.0000
3.0000
2.0000
4.0000
* a = a + 3i
* a
1.0000 + 3.0000i
3.0000 + 3.0000i
a'
*
1.0000 - 3.0000i
2.0000 - 3.0000i
a.'
*
1.0000 + 3.0000i
2.0000 + 3.0000i
26
2.0000 + 3.0000i
4.0000 + 3.0000i
3.0000 - 3.0000i
4.0000 - 3.0000i
3.0000 + 3.0000i
4.0000 + 3.0000i
Chapter 4. Operators
UniScript Manual, Release R2016
4.1.7 Summary
Operator
x+y
x-y
x*y
x .* y
x/y
x ./ y
xy
x%y
x^y
x .^ y
x’
x.’
Meaning
Addition of real and complex numbers as well as concatenate strings.
Subtraction of real and complex numbers.
Matrix multiplication of real and complex numbers.
Multiplication of real and complex numbers.
For scalars normal division. For matrices the division x/y
is equivalent to the operation x * y^-1. If x is a scalar, x is
divided by y on a element by element basis.
Element by element division of real and complex numbers.
Left division. Computes the solution of the system x^-1 *
y.
Modulus arithmetic is denoted by the operator %. It gives
the integer value that is the remainder of an integer division. Example: 10.4 % 2 is 2.
Power operator for real and complex numbers.
Element by element power operator for real and complex
numbers.
Transpose. The elements will be conjugated for complex
matrices.
Transpose.
4.2 Comparison Operators
All comparison operators work on an element by element basis. The result of the comparison is either TRUE
(1) or FALSE (0). This result can then be used to make decisions regarding program flow.
)︂
)︂
(︂
(︂
1 1
1 2
< 2.5 =
0 0
3 4
Strings are compared lexicographically on a character by character base. Examples:
"a " == "a" is 0 (FALSE)
"a" < "b" is 1 (TRUE)
"Hello" == "hello" is 0 (FALSE)
In the first line, the left string contains blank characters. Tn the second line the character a is less than b. In
the third line, the left string starts with a capital letter.
If you do not to want compare strings in this manner, you can use the functions strtrim and strlower (or
strupper).
strtrim("a ") == strtrim("a") is 1 (TRUE)
strlower("Hello") == strlower("hello") is 1 (TRUE)
For complex numbers, only the operators == and != are defined.
4.2. Comparison Operators
27
UniScript Manual, Release R2016
Summary
Operator
x<y
x <= y
x == y
x != y
x>y
x >= y
Meaning
True if x is less than y.
True if x is less than or equal to y.
True if x is equal to y.
True if x is not equal to y.
True if x is greater than y.
True if x is greater or equal to y.
4.3 Boolean Expressions
Boolean operators are often used in conjunction with comparison operators, as in the following example:
(a < 5) && (b > 8)
This expression returns 1 (TRUE) if a is less than 5 and b is greater than 8.
The AND operator (&&) has a lower precedence than all other comparison operators, therefore we do not
have to use parentheses. But parentheses help to avoid precedence mistakes and should be used when you
have an unusual combination.
Summary
Operator
x && y
x || y
!x
Meaning
True if both x and y are true (AND).
True if at least one of x or y is true (OR).
True if x is false (not x).
4.4 Bitwise Operators
UniScript uses the same binary operators as the programming language C. The bitwise operators perform
the bitwise-AND (&), bitwise-exclusive-OR (@), and the bitwise-OR (|) operations.
The operands for bitwise operators must be of integer type. Therefore, the operands are converted to integers
with 32 Bits. Example: 9.56 and 10.89 are first converted to 9 and 10. To perform a bitwise-AND operation,
9 & 10 can be expressed in binary as
1 0 0 1 = 9
& 1 0 1 0 = 10
1 0 0 0 = 8
The bits in the result are 1 if the appropriate bits in the operands are 1, otherwise the bits are 0. The bitwise
operators can be applied as the arithmetic + operator on vectors and matrices.
The bitwise-AND (&) operator is frequently used to set single bits to 0.
Example: rvSignal contains a signal from a 12-Bit data acquisition system. All bits of rvSignal
should be set to 0 except for the lower 12 bits. This can be performed by an AND operation between
28
Chapter 4. Operators
UniScript Manual, Release R2016
rvSignal and 0x0FFF (rvSignal & 0x0FFF).
The bitwise-OR (|) operator compares each bit of its first operand to the corresponding bit of its second
operand. If either bit is 1, the corresponding bit is set to 1, otherwise it is set to 0.
Example:
1 0 0 1 = 9
| 1 0 1 0 = 10
1 0 1 1 = 11
The bitwise-exclusive-OR @ operator compares each bit of its first operand to the corresponding bit of its
second operand. If one bit is 0 and the other bit is 1, the corresponding result bit is set to 1, otherwise it is
set to 0.
Example:
1 0 0 1 = 9
@ 1 0 1 0 = 10
0 0 1 1 = 3
The shift operator shifts the bits of the left operator to the left or to the right.
For example: The expression 01001 (binary) << 1 results in 10010 (binary) (this is equivalent
to a multiplication by 2).
The bitwise-NOT (~) operator produces the bitwise complement of its operand.
Example:
~01001 (binary) is 10110 (binary).
Summary
Operator
x&y
x|y
x@y
x << y
x >> y
~x
Meaning
Bitwise AND operator.
Bitwise OR operator.
Exclusive OR operator.
Shift left.
Shift right.
Binary complement.
4.5 Operator Precedence
The following table lists UniScript operators in order of increasing precedence. Operators in the same row
have the same precedence. To change the precedence of the operators, use parentheses or square brackets
for index operations.
Example
4.5. Operator Precedence
29
UniScript Manual, Release R2016
*
*
*
*
m1 = [1, 2]
m2 = [3, 4]
m3 = [5; 6]
m = [m1;m2,m3]
>>> (E0000015) Operand format incompatible
* m = [[m1;m2],m3]
* m
1.0000
2.0000
3.0000
4.0000
5.0000
6.0000
The expression [m1;m2] must be enclosed in square brackets because the , operator has a higher precedence than the ; operator.
Operator
=
;
,
||
&&
|
@
&
== !=
<= < > >= >
<< >>
+* .* / % ./ \
:
!~-+
^ .^ ’ .’
30
Group order
(assignment) right to left
(column separator) left to right
(row separator) left to right
(logical or) left to right
(logical and) left to right
(binary or) left to right
(binary exclusive or) left to right
(binary and) left to right
(comparison)left to right
(comparison) left to right
(shift left, shift right) left to right
(addition and subtraction) left to right
(multiplication) left to right
(vector creation) left to right
(unary operators) left to right
(power, transpose) right to left
Chapter 4. Operators
CHAPTER 5
Control Statements
Control statements determine the order in which the UniScript program is executed.
5.1 The if-else Statement
The if-else statement is a conditional statement. It has the following syntax:
if (condition) {
if statements
} else {
else statements
}
The expression condition has to be a real scalar. The if statement will be executed if the condition is true.
This means that the expression is not equal to 0. The else statement will be executed if the condition is
false. else is optional.
if (condition) {
if statements
}
If the if and else statements consist of only one statement, the braces are not necessary.
a = 1;
if (a == 1) print "a equal 1" else print "a not equal 1"
It is easier to read if you write the statements in separate lines:
a = 1
if (a == 1) {
print "a equal 1"
} else {
print "a not equal 1"
}
The following syntax is not allowed in UniScript and will result in a syntax error. The second brace will be
interpreted as the end of the if-else statement.
31
UniScript Manual, Release R2016
a = 1;
if (a == 1)
{
print "a equal 1";
}
else
{
print "a not equal 1";
}
As mentioned previously, the condition must be a real scalar. The expression string == "Hello" returns a real scalar if string is a scalar. The expression will return 1 if string holds the string "Hello".
Otherwise, it will return 0. If string is a vector or a matrix of strings, the expression will return a real vector or a real matrix. For example, if string is a vector with the three elements ["Hello", "HELLO",
"hello"], the expression will return a real vector with the elements [1, 0, 0]. To convert this vector
to a real scalar you can use one of the UniScript functions all and any. The function all returns TRUE (1)
if all elements of the input vector are not zero, otherwise the function returns the value 0. The any function
returns 1 if at least one of the elements of the input vector is not zero, otherwise the function returns the
value 0. If the argument of the function all or any is a real matrix, the matrix will be evaluated columnwise.
In this case, the return value is a row vector. When the argument is a matrix and you use all or any twice,
the return value is a scalar.
The following example will execute the if statements if all elements of the string variable have the value
"Hello", no matter if string is a scalar, vector or matrix.
if (all(all(string == "Hello"))) {
if statements
} else {
else statement
}
The if-else statements can be used to make a decision out of multiple choices:
if (condition-1) {
statements-1
} else if (condition-2) {
statements-2
} else if (condition-3) {
statements-3
} else {
Statements-n
}
The conditions will be checked one after the other until one condition is true. After the statements are
executed, the else-if chain is finished. If no condition is true, the last else case will be executed.
5.2 The for Statement
The for statement is used to iterate the overall elements of a vector. The general form of the for statement
is
32
Chapter 5. Control Statements
UniScript Manual, Release R2016
for (i in vector) {
statements
}
If vector has the value [1, 3, 6, 4], then i takes the values 1, 3, 6, 4 one after the other. vector
can also be a string vector or a complex vector.
The vector will only be evaluated once at the beginning of the for loop. The following example
a = [1,2,3]
for (i in a) {
a = 0;
printf("a = %d, i = %d\n", a, i);
}
generates the output
a = 0, i = 1
a = 0, i = 2
a = 0, i = 3
The following example will open two UniScript files:
svFilename = ["plot.ic", "alias.ic"];
svFilename = GetRootDirectory() + "script/" + ..
svFilename;
for (ssName in svFilename) {
EdCreate(ssName);
}
5.3 The while Statement
The while statement is used to execute one or more statements repeatedly. A while statement has the
following syntax:
while (condition) {
statements
}
The condition expression must be a real scalar. The statements will be executed as long the condition is true,
i.e. a value not equal to 0.
while (1) {
print "Hello"
}
would print the word "Hello" indefinitely, because the condition will never be 0. This loop can only be
interrupted by pressing the ESCAPE key (ESC). The while(1) statement can also be interrupted by a
break or return statement.
The following while loop will print the word "Hello" 10 times and then print the number 11.
5.3. The while Statement
33
UniScript Manual, Release R2016
i = 1;
while (i <= 10) {
print "Hello";
i = i + 1;
}
print i;
5.4 The break and continue Statement
The break statement is used to terminate within an iteration statement. break can be used in the statement
body of a while or for loop.
Some programming languages have iteration statements which check the condition at the end of the loop (the
repeat statement in Pascal or the do statement in C). In UniScript, the behavior of such control statements
can be simulated with the break statement. The following example will print the string "Hello" 10 times
and will then print the number 10.
i = 1;
while (1)
print
if (i
i = i
}
print i;
{
"Hello";
== 10) break;
+ 1;
The continue statement is used inside a while or for loop to skip over the rest of the statements and to
continue with the next loop cycle immediately. The next example opens all files with the extension .ipw.
ssPath = "c:/uniplot/samples/";
svFiles = FindFiles(ssPath + "*.*");
for (ssName in ssPath + svFiles[;1]) {
if (strupper(SplitPath(ssName)[4]) != ".IPW") {
continue;
}
if (DocCreate(ssName) == 0) break;
}
The function call FindFiles(ssPath + "*.*") returns a string matrix of the files in the ssPath
directory. The first column holds the file names, the second column the file size, and the third column holds
the file attributes. In our example, we are only interested in the file names. The expression svFiles[;1]
selects all elements of the first column.
The function SplitPath splits a complete file name into items: drive, path, name and extension. Therefore, the
call SplitPath(ssName)[4] returns the extension of the file ssName. strupper converts its argument
into upper case characters.
If the condition is true, i.e. the file does not have the extension ".ipw", the continue statement will
be executed and the next file name will be evaluated. If the condition is false, the function DocCreate will
load the file. If the file cannot be opened, DocCreate returns 0. The loop will be terminated because of the
break statement.
34
Chapter 5. Control Statements
UniScript Manual, Release R2016
If we had called the FindFiles function with the search pattern "*.ipw", we would have found all wanted
files without using the for loop and the continue statement.
5.5 The try-except Statement
The try-except statement can be used to handle programming errors. It has the following syntax:
try {
try statements
} except (condition) {
except statements
}
In contrast to the if-else statement, the second block in the try-except statement is not optional.
Every try block has exactly one except block. try-except statements can be nested.
Normally, only the try statement is executed. The condition and the except statement will only be
executed in case of an error in the try statement. There are many reasons why a problem can occur while
executing a statement.
Examples:
• Not enough memory is available to execute the statement.
• The user pressed the ESC key inside a try statement.
• A vector element that does not exist was accessed.
• An error occurs inside a function call within a try statement body.
• The error function was called inside the function body.
1 and 2 are problems which the programmer cannot avoid but 3 and 4 are programming errors. In case 5
(call of the error function) an exception was created deliberately.
Example:
def GetTextFile(ssFileName)
{
fp = fopen(ssFileName, "rt");
ssText = fread(fp, "char");
fclose(fp);
return ssText;
}
The function fopen opens a file for reading, fread reads the file, and fclose closes the file. It is important to
close the file as soon as possible, because the operating system only allows a limited number of simultaneous
open files.
If you call GetTextFile("d:\\test.txt"), the function will return the contents of the file
d:\test.txt as a string, if it exists, if all function calls are error free, if enough memory is available
and if the user did not press the ESC key. If one of these exceptions occurs before the call of the function
fclose, a so called resource loss will occur.
5.5. The try-except Statement
35
UniScript Manual, Release R2016
This problem can be solved by protecting the statements with a try-except statement.
def GetTextFile(ssFileName)
{
fp = 0;
try {
fp = fopen(ssFileName, "rt");
ssText = fread(fp, "char");
if (isreal(ssText)) error();
fclose(fp);
return ssText;
} except (1) {
if (fp != 0) {
fclose(fp);
}
MessageBox("File cannot be loaded!");
return "";
}
}
If an exception occurs inside the try body, the program branches into the except body to clean up the
function. In our example, the open file will be closed and an error message will be displayed.
The keyword except is followed by a condition expression in parentheses. If the condition is false (0), the
exception statements are not executed. If the condition is true (equal 1), the except statement is executed.
With the function GetExceptionCode, the exception type can be received.
Example:
def TestException(a, b)
{
try {
i = 0;
while (1) {
x = a + b;
i = i + 1;
}
} except (GetExceptionCode() == ICERR_INTERRUPT) {
MessageBox(..
sprintf("User Abort (i = %d", i"));
}
}
If the function is called with the parameters "a" and 1.6 (TestException("a", 1.6)), an exception
will occur and the exception condition will be evaluated.
GetExceptionCode() == ICERR_INTERRUPT, ICERR_OPERATOR_TYPE
GetExceptionCode returns an error code - in this case the error code with the name
ICERR_OPERATOR_TYPE. Because the error code is not ICERR_INTERRUPT, the except statement
will not be executed. The exception will only be handled if the user presses the ESC key to produce an
ICERR_INTERRUPT exception. (UniScript error codes are listed in the file alias.ic.)
36
Chapter 5. Control Statements
CHAPTER 6
Functions for Vectors and Matrices
This chapter introduces some important vector and matrix functions. More information about these functions
is available through the online help system.
The zeros and ones functions create a vector or a matrix where all elements have the value 0 or 1. The
function call zeros(nr, nc) returns a zero matrix with nr rows and nc columns. zeros(1, 10) +
1.0 is equivalent to the expression ones(1, 10). The rand function (rand(nr, nc)) function returns
a matrix with random numbers in the range 0 to 1.
The size(x) function returns the size of the variable x. The size is a 1 * 2 vector. The first element is the
number of rows and the second is the number of columns. Example:
* size(rand(3, 4))
3 4
The function nr returns the number of rows of a matrix or a vector. The function nc returns the number of
columns of a matrix or a vector. The function len returns the number of elements of a matrix or vector. The
expression len(x) == nr(x) * nc(x) is true. Some examples:
v[len(v):1] = v[1:len(v)]
changes the element order of a vector. In the same way, the statement
m[1:nr(m);] = m[nr(m):1;]
changes the row order of a matrix and
m[;1:nc(m)] = m[;nc(m):1]
changes the column order.
The statement
m = m[; 2:nc(m), 1]
“rotates” the matrix columns, i.e. moves the first column behind the last column of the matrix m.
v = v[1:3-1, 3+1:len(v)]
removes the 3rd element from a vector. The following statement removes the first element of a vector
37
UniScript Manual, Release R2016
v = v[2:len(v)]
and
v = v[1:len(v)-1]
removes the last element.
The matrix data type can be retrieved with the function type. The function returns one of the following
strings: "real", "complex", "string", "undef", or "function".
The min function returns the minimum of its argument vector. If the argrument is a matrix, min returns a
row vector with the minimum of the matrix columns. The max function returns the maximum of a vector or
matrix:
* m = rand(2,2)
* m
0.3237
0.2887
0.3244
0.3530
min(m)
*
0.3237
0.1540
max(m)
*
0.4934
0.3530
Double use of the function returns the smallest or largest of all matrix elements: min(min(m)) or
max(max(m)).
The sort function can sort the elements of a vector or a matrix. If the function argument is a matrix, all rows
will be sorted by the first column.
* srand() // Sets the seed to the standard value
1.0000
m
= rand(3,4)
*
m
*
0.7744
0.2484 0.1606 0.6082
0.3925
0.7937 0.4888 0.1344
0.6235
0.9313 0.6486 0.8489
sort(m)
*
0.3925
0.7937 0.4888 0.1344
0.6235
0.9313 0.6486 0.8489
0.7744
0.2484 0.1606 0.6082
The find function returns the indices of all values which are not equal to 0. find is mainly used in conjunction
with comparison operators:
* a = [1,7,5,22]
* a <= 5
1.0000
0.0000
* find(a <= 5)
1.0000
3.0000
1.0000
0.0000
The next statement will set all elements of the vector a which are less than 5 to the value 9:
38
Chapter 6. Functions for Vectors and Matrices
UniScript Manual, Release R2016
a[find(a < 5)] = 9;
39
UniScript Manual, Release R2016
40
Chapter 6. Functions for Vectors and Matrices
CHAPTER 7
Functions
A function is a name for a sequence of statements. You can use functions as a black box. You do not need
to know how the function works. For example, to use the sin function you only need to know the name and
the interface of the function.
7.1 Function Syntax
In UniScript, a function is easily defined. Example:
def dB(rvSignal)
{
return 20.0 .* log10(rvSignal);
}
The keyword def is followed by the function name. The function name is followed by a list of commaseparated arguments enclosed in parentheses. In our example, the function name is dB and the argument
has the name rvSignal. The function has one statement which returns the result to the caller of the dB
function. The function call can look like this:
rvdB = dB(1:100);
The values 1 to 100 will be converted into dB (Decibel) values.
A function in UniScript has the following syntax:
def name (parameter-list)
{
statements
}
The rules for function names are the same as for variable names. The name must be a sequence of letters,
digits and underscores, however, it may not begin with a digit. The length of names is not limited in
UniScript, but only the first 80 characters are significant. Case is also significant in names. The name must
be distinct from all variables or built in function names. A built in function is a function written in in C, C++
or FORTRAN. They are located in Dynamic Link Libraries (DLLs) and are loaded when UniScript starts.
A list of all built in functions can be received with the function call symbols(SYM_BUILTIN).
41
UniScript Manual, Release R2016
The function name is followed by a comma separated parameter list enclosed in parentheses. The parameter
list can have between 0 and 32 elements. The shortest form of a function in UniScript is:
def f() { }
The parentheses and the braces are necessary for syntax reasons. When this function is called, it returns the
value 0.0.
7.2 Function Parameters and Arguments
Values which are passed to a function are called arguments. Parameters are the names of the arguments. In
UniScript, the number of function parameters is limited to 32. Example:
def dB(rvSignal)
{
return 20.0 .* log10(rvSignal);
}
db(1:100)
The value 1:100 is an argument, rvSignal is the function parameter.
A function can be called with less arguments than the function has parameters. Example:
def Test(a, b, c)
{
return 1;
}
Test();
Test(1);
Test(1,2);
Test(1,2,3);
Test(1,2,3,4);
Except for the last function call, all of the function calls above are valid.
The number of arguments can be checked inside a function with the function nargsin:
def Test(a, b, c, d, e, f, g)
{
nArgs = nargsin();
printf("The function was called with %d out of 7" + ..
" possible arguments\n", nArgs);
}
Function parameters which have not been passed to the function cannot be accessed. To do so will produce
an error message. If the function call is Test(1, 2, 3), the parameters d - g are not available and
should not be used.
42
Chapter 7. Functions
UniScript Manual, Release R2016
7.3 Global and Local Variables
Normally, all variables used inside a function are local variables. These variables will be created when the
function is called and will be destroyed when the function is finished. Local variables are not known outside
the function. A variable can be declared as global to avoid this behavior. Global variables can be accessed
from any UniScript function. The global variable must be declared at the beginning of the function in order
to access it. Example:
def Test()
{
global Glob1, Glob2;
Glob1 = 1;
Glob2 = 2;
Local1 = 3;
Local2 = 4;
print Glob1, Glob2, Local1, Local2;
}
Glob1 = 5;
Glob2 = 6;
Local1 = 7;
Local2 = 8;
print Global1, Global2, Local1, Local2;
Test();
print Global1, Global2, Local1, Local2;
If you execute this program, it will print the numbers 5, 6, 7, 8. In the function Test(), it will print the
numbers 1, 2, 3, 4 and in the last print statement, the numbers 1, 2, 7, 8 will be printed. The function
Test() has changed the variables Glob1 and Glob2. The variables Local1 and Local2 were not
changed by the program Test().
7.4 The return Statement
The return statement returns values to the calling function and terminates the execution of the called
function. The return statement has the following syntax:
return expression;
If the expression is empty, the function returns the value 0.0. A function without a return statement
returns the default return value 0.0. Example:
def Test(x)
{
if ((x % 2) == 0) {
return "x is divisible by 2 without a remainder";
}
return "x is NOT divisible by 2 without a remainder";
}
7.3. Global and Local Variables
43
UniScript Manual, Release R2016
Test(4)
Test(5)
If the argument of the function Test() is divisible by 2, the first return statement will be executed and the
function terminated. Otherwise, the second return statement will be executed.
7.5 Multiple Return Values
All of the functions we have used so far, such as sin, have only one return value. However, functions in
UniScript can return multiple values. Example:
If you call the eig function in the form
* m = [4,7;2,5]
* eig(m)
8.2749 + 0.0000i
0.7251 + 0.0000i
it returns the eigenvalues of the matrix m. If you call the function in the following form
* <e, v> = eig(m)
it will return 2 variables (the eigenvalue e and the eigenvector v).
The syntax for defining functions that return multiple values is
def <return list> = name(argument list)
{
statements
}
The return list is a list of variable names separated by commas.
The function nargsout returns the number of values that are expected to return. Return variables which have
not been passed to the function cannot be accessed. To do so will produce an error message.
def <a,b,c,d> = Test(e,f,g,h,i)
{
nArgsIn = nargsin(); nArgsOut = nargsout();
printf("The function was called with %d out of 5 " + ..
"possible arguments\n", nArgsIn);
printf("The function was called with %d out of 4 " + ..
"possible return variables\n", ..
nArgsOut);
}
Instead of using multiple return values an object can be returned as shown in the following example (see
also UniScript Objects). Example:
def Test(p1, p2)
{
o = [.]; // Create objekt
44
Chapter 7. Functions
UniScript Manual, Release R2016
o.a = 123;
o.b = "Hello";
return o;
}
Note: The return variables enclosed in angle brackets < > cannot be used in the argument list of the function
definition.
Two or more return values should not be used. Instead an object can be returned (see UniScript Objects).
Example:
def Test(p1, p2)
{
o = [.]; // Objekt erzeugen
o.a = 123;
o.b = "Hello";
return o;
}
7.6 Calling Functions from DLL‘s
DLL is an abbreviation for Dynamic Link Library. A DLL is a collection of functions created with a
compiler. With UniScript, functions located in DLLs can be called directly except when the function’s
parameter list contains structures or pointers to functions. In this case, you still have to use a C or FORTRAN
compiler to create a DLL to enable UniScript to call this function.
We would like to show you the use of the interface with some examples.
7.6.1 FindWindow
The first example is the function FindWindow(). This function is located in a DLL which belongs to
the Windows Operating System. The function can be used to check if a certain program has already been
started. Before the function can be used, it must be registered. This means, we have to tell UniScript in
which DLL the function is located, what the internal name of the function is and what function parameter
and return values the function has. The data types of the parameters are needed so that UniScript can convert
the values passed to the function to the correct type.
To register a new function, use RegisterFunction. This function must be called only once for each new
function. A good place to invoke the function is the startup file startup.ic.
RegisterFunction("USER32", "FindWindowA", ..
"uint", "FindWindow", char* , char*);
The first parameter is the name of the DLL. The function FindWindow() is located in the DLL
USER32.DLL in one of the Windows directories. To find the DLL in which a function is located, refer to the Windows Software Development Kits (SDK) documentation. SDK documentation is part of a
Windows compiler documentation.
7.6. Calling Functions from DLL‘s
45
UniScript Manual, Release R2016
The second parameter is the internal name of the function. The FindWindow() function has the internal
name FindWindowA. This information is also found in the SDK documentation.
The third parameter is a string which specifies the data type of the return value. The SDK documentation
specifies the data type of the return value as a HWND (handle to a Window). Because the RegisterFunction
does not know this data type, we use the data type "uint". An "uint" is an unsigned 32 Bits integer.
The data types that can be used for the RegisterFunction are specified in the UniScript Reference.
The fourth parameter is the name of the function you want to call from UniScript. You can specify any name
that meets the rules of UniScript function names.
The fifth parameter is a string vector which specifies the data types of the function parameters. The function
FindWindow has two parameters.
The first one is a pointer to a string which specifies the internal name of the window, and the second parameter is a pointer to a string which specifies the window title. The internal window name for Excel is, for
example, "XLMAIN". For MS-WORD it is "OpusApp" and for UniPlot it is ":UniPlot:".
After we have registered the new function, we are able to call it. When the function returns a value not equal
to 0, it means that Excel has already been started. If the return value is 0, Excel has not been started.
// Find the Excel Window. The second parameter
// can be set to 0 (see SDK documentation)
h = FindWindow("XLMAIN", 0);
if (h == 0) {
// Window not found, i.e. Excel not started
// Start Excel:
system("excel", SW_SHOW, TRUE);
}
// at this point Excel is running
7.6.2 DGEMM
The next example is a more complicated call of a mathematical function which is located in the UniScript
DLL rs_math.dll. The function evaluates the following term:
C = alpha * A * B + beta * C
alpha and beta are scalar values, A, B and C are vectors or matrices.
The function is only an example to show how FORTRAN functions can be called from UniScript because
the term
C = alpha * A * B + beat * C
can also be evaluated directly by UniScript without calling a function. However, it is a good example to
show the calling of functions of this kind.
The FORTRAN function has the following form:
SUBROUTINE DGEMM (TRANSA, TRANSB, M, N, K, ALPHA, A, LDA,
BETA, C, LDC)
46
B,
LDB,
Chapter 7. Functions
UniScript Manual, Release R2016
The function belongs to the BLAS Library (Basic Linear Algebra System).
Functions in DLLs must have a so called C interface which looks like the following:
int dgemm_(char *transa, char *transb, int *m,
int *n, int *k, double *alpha, double *a,
int *lda, double *b, int *ldb, double *beta,
double *c, int *ldc);
The corresponding UniScript registration call for this function has the following form:
RegisterFunction("rs_math.dll", "dgemm_", "int", ..
"dgemm", ..
"char *transa", "char *transb", "int *m",
"int *n", ..
"int *k", "double *alpha", "double *a", ..
"int *lda", "double *b", "int *ldb", ..
"double *beta", "double *c", "int *ldc");
We do not call the _dgemm() function directly because UniScript can only perform a very limited number
of error checks when calling external DLL functions.
A faulty function call can lead to a “crash” of UniPlot, a so called “Memory Access Violation”. Under
Windows 95/98 it can also lead to a crash of Windows itself so that you have to reboot your computer.
Under Windows NT, the applications run in a protected mode so that such an error will only affect UniPlot.
To avoid such a problem, we will write a wrapper function for _dgemm().
To simplify the problem we set alpha to 1 and beta to 0 in our formula:
C = alpha * A * B + beta * C
// C = A * B
def Multiply(a, b)
{
if (nargsin() != 2) {
error("number of args");
}
if (type(a) != "real" || type(b) != "real") {
error("type error");
}
nra = nr(a);
nrb = nr(b);
nca = nc(a);
ncb = nc(b);
if (nra != ncb) {
error("dimensions must match");
}
c = zeros(nra, ncb);
_dgemm("N", "N", nra, ncb, nca, 1.0, ..
a, nra, b, nrb, 0.0, c, nra);
return c;
}
The following lines are a test of the new interface and will compare the result with the built in multiplication
operator.
7.6. Calling Functions from DLL‘s
47
UniScript Manual, Release R2016
a = rand(2, 3);
b = rand(3, 2);
x1 = Multiply(a, b)
x2 = a * b;
print x1-x2;
7.6.3 GetCurrentDirectory, SetCurrentDirectory
We will now write two functions to change directories or return the current working directory respectively.
gwd() (get working directory) should return the current working directory.
cd() (change directory) should change the directory.
The
corresponding
Windows
SetCurrentDirectoryA().
functions
are
GetCurrentDirectoryA()
and
GetCurrentDirectoryA() has two parameters. The first parameter specifies the buffer size in which
the function will write the directory name.
The second parameter is a pointer to the buffer. The function will not write more characters into the buffer
than the first parameter specifies. The function returns the number of actually written characters. The
registration of this function looks like the following:
RegisterFunction("KERNEL32", "GetCurrentDirectoryA",..
"uint", "__GetCurDir", ["uint", "char*"]);
The registration for SetCurrentDirectory() is:
RegisterFunction("KERNEL32", "SetCurrentDirectoryA",..
"uint", "__SetCurDir", "char*");
We will now write the wrappers for these functions:
def gwd()
{
ss = "012345678901234567890123456789";
ssBuffer = "";
for (i in 1:10) ssBuffer = ssBuffer + ss;
GetCurDir(strlen(ssBuffer), ssBuffer)
return ssBuffer;
}
The first three lines of the function gwd() will create a buffer for 300 characters which will then be filled
by the GetCurrentDirectoryA() function. The function gwd() returns the buffer in the last line.
The function SetCurrentDirectoryA() receives a similar wrapper. The two if statements avoid the
problem of the function being called with a wrong number of arguments.
def cd(ssDir)
{
if (nargsin() != 1) {
error("usage: cd (ssDir)")
}
48
Chapter 7. Functions
UniScript Manual, Release R2016
if (type(ssDir) != "string") {
error("usage: cd (ssDir)")
}
return SetCurDir(ssDir);
}
Finally, we can test the new functions in the command window:
* cd ("c:/")
1.0000
* cd ()
>>> cd : usage: cd (ssDir)
* gwd()
c:\
* cd("d:/uniplot/script")
0.0000
* gwd()
c:\
* cd("d:/uniplot/script")
1.0000
* gwd()
d:\uniplot\script
7.7 COM-Interface
As of Version 3.0 UniScript can access objects that have a so called dispatch interface.
Below are some examples of how the new interface can be used.
7.7.1 Access Excel
In the first example we want data to be inserted into a Microsoft Excel spreadsheet.
First Excel must be started by calling the CreateObject function. CreateObject returns a pointer (a reference)
to the Excel instance. The function expects the server name of the program that should be started as the
argument. For Excel the server name is "Excel.Application".
xls = CreateObject("Excel.Application")
xls.Visible = 1
The second line (xls.Visible = 1) will make the application visible. To access the methods and
properties of an object use a period (.).
In the following example UniScript calls a method (function) to add a new workbook to the existing document:
wb = xls.Workbooks
wb.Add();
7.7. COM-Interface
49
UniScript Manual, Release R2016
You can call both methods in one statement:
xls.Workbooks.Add()
The following lines will fill the sheet:
xls.ActiveSheet.Range("a1").Value = "x"
xls.ActiveSheet.Range("b1").Value = "sin(x)"
x = linspace(0, 2*PI)
y = sin(x)
xls.ActiveSheet.Range("a2:a101").Value = x'
xls.ActiveSheet.Range("b2:b101").Value = y'
7.7.2 Data Base Access
In the following example, we will use Microsoft ADO (ActiveX Data Objects) to access the data of a
Microsoft Excel XLSX file like a database table with SQL.
// create an Excel 2007 file with the following content and
// name the sheet Sheet1:
/*
a
b
c
1
2
test1
4
5
test2
3
1
test3
/
*
def ado_Excel_Test()
{
// Must be an XLSX file, slash or double backslash
ssExcelFile = "c:\\excelfile.xlsx";
ssSheetName = "Sheet1";
// HDR=Yes : First row are the column names of the table
strCnn = "Provider=Microsoft.ACE.OLEDB.12.0;Data " + ...
"Source=%s;" + ..
"Extended Properties=\"Excel 12.0 Xml;HDR=Yes;IMEX=1\";"
strCnn = sprintf(strCnn, ssExcelFile);
db = db_create("ado");
if (db.connect(strCnn) == 0) {
MessageBoxError("Cannot connect: %s", strCnn);
return ""
}
// $-sign is neccessary for the table name
// return all data
ssSQL = sprintf("SELECT * FROM [%s$];", ssSheetName);
smData = db.exec(ssSQL);
// return all columns and all records where a > 1
ssSQL = sprintf("SELECT * FROM [%s$] Where a > 1;", ssSheetName);
smData = db.exec(ssSQL);
// return column b and c where column a > 1
50
Chapter 7. Functions
UniScript Manual, Release R2016
ssSQL = sprintf("SELECT b,c FROM [%s$] Where a > 1;", ssSheetName);
smData = db.exec(ssSQL);
return smData;
}
In the following example, we will use Microsoft Data Access Objects (DAO) to read data from a Microsoft
Excel table. DAO is not available in 64-bit Windows.
dao = CreateObject("Dao.DBEngine.36");
if (dao == 0) {
error("Cannot create Dao.DBEngine.3.6");
}
ws = dao.CreateWorkspace("", "Admin", "", 2);
ssFile = GetRootDirectory()+ "samples\ole\test.xls"
dbs = ws.OpenDatabase(ssFile, 0, 0, "Excel 8.0;HDR=No;");
m = dbs.OpenRecordset("test$").GetRows(1000);
print m
7.7.3 Variant Matrix
An Excel table can contain different data types. In the example above we wrote the string “x” into the cell
A1. We wrote floating point numbers into the cells A2 to A101.
In a data base each column can have a different data type, e.g. the first column is the date, the second column
an integer and the third column is a string with 80 characters.
To enable UniScript to deal with data matrices where elements can have different data types we added variant
matrices to UniScript.
A variant matrix can contain elements of the following 4 data types:
Type
real
complex
string
object
Meaning
Double precision values with 8 bytes.
Complex values. Two double precision values. A complex
value has 16 Bytes.
A string with up to 2 times 31 characters.
Reference to an ActiveX object.
The following example creates an column vector with 3 real values, one complex value, one string and one
object reference.
* xls = CreateObject("Excel.Application");
* v = [ConvertToVariant([1,2,3]), 4+5i, "Hello", xls]'
* v
1.0000
2.0000
3.0000
4.0000 + 5.0000i
Hello
7.7. COM-Interface
51
UniScript Manual, Release R2016
(0x001B6FC4)
The element access for variant matrices is identical to any other matrix element access in UniScript. Variant
matrices cannot be used in calculations. Comparison operators for variant matrices are not supported.
The following statement will therefore create a runtime error:
a = [1, "Hallo"]
b = a
if (a == b) MessageBox("a not equal to b")
To use data from variant matrices in computations, the matrices must be converted to real matrices. This can
be performed with the VariantConvert function.
a = [1, "Hallo"]
b = a
print VariantConvert(a[1]) + VariantConvert(b[1])
The inverse function to VariantConvert is ConvertToVariant.
VariantGetType returns a matrix with the type of each element.
The UniScript variant matrix is not identical to the data type Variant of Visual-Basic or the ActiveX interface.
The ActiveX variant data type knows the following data types:
Type No.
0
1
2
3
4
5
6
7
8
10
11
17
Name
VT_EMPTY
VT_NULL
VT_I2
VT_I4
VT_R4
VT_R8
VT_CY
VT_DATE
VT_BSTR
VT_ERROR
VT_BOOL
VT_UI1
Description
empty.
Null.
2-byte signed int.
4-byte signed int.
4-byte real.
8-byte real.
Currency.
Date/Time.
Binary string.
SCODE.
Boolean.
Unsigned char.
When UniScript uses a property or a method of the COM interface, UniScript must perform a data type
conversion from the UniScript data type to the COM data type.
Data types with the numbers 2, 3, 4, 5, 11, 17 will be converted to the UniScript-real data type (Double
precision value). Type number 8 will be converted into a UniScript-String. The types 0, 1, 6, 7 will be
converted to a complex number where the real part is the value and the imaginary part is the type number.
Example: An Excel table contains the following data in the first column:
x
1,23
01.01.2000
52
Chapter 7. Functions
UniScript Manual, Release R2016
#DIV/0!
FALSCH
UniScript will return the following vector:
* v = xls.ActiveSheet.Range("a1:a6").Value'
* print v
x
1.2300
0.0000 + 0.0000i
36526.0000 + 7.0000i
-2.147e+009 + 10i
0.0000
Cell A3 is empty. For this element UniScript returns the complex number 0+0i. Cell A4 contains a date.
For this element UniScript will return the complex number 36526+7i. To convert the date into an string
use DT_Format(real(v[4])). The cell A5 (-2.147e+009 + 10i) contains an error code. This is the
Excel error code for the Excel formula =1/0.
7.7.4 UniPlot as an COM Server
UniPlot can be used as an COM server (OLE Server or Automation Server). This means that you can use
UniPlot/UniScript functions in other applications. UniPlot uses a dual interface, i.e. UniPlot can be used by
script languages like VBScript, JavaScript, Visual Basic for Applications as well as languages like C, C++
or Visual Basic.
The following examples will show you how to use UniPlot with Excel. To try out the examples, you need
Excel 97 or Excel 2000.
7.7.5 Setup
To setup the examples, execute the following steps:
• If UniPlot is running, quit UniPlot.
• The examples are located in the directory UniPlot\Samples\ole. Copy the UniScript files that
begin with AX- into UniPlot Autoload directory.
• Open the DOS command window.
• Go to the \UniPlot\Program directory and start UniPlot with the following command:
uniplot /regserver
This will register UniPlot as an OLE-Server.
• After you are finished evaluating the examples it is recommended to remove the AX-*.ic files from
the UniPlot/AutoLoad directory.
7.7. COM-Interface
53
UniScript Manual, Release R2016
7.7.6 Example 1 (AX-Data)
The following example shows how a UniScript Function can be called by Excel and how data can be passed
to the function.
To execute the function, do the following:
• Start UniPlot. Open the UniScript Command window (viewcommand-window).
• Start Excel. Open the file UniPlot\Samples\Ole\AX-Data.xls. Excel may display a dialogbox with a message saying that the file contains macros. Select the button Activate Macros.
Arrange the two applications side by side on your monitor.
• Select some cells in the Excel sheet. You’ll see that the data will be displayed in the UniScript
Command window when you change the selection.
How does the data exchange between Excel and UniPlot/UniScript work?
Two scripts have been written. The Visual-Basic for Applications script, which is located in the Excel
file UniPlot\Samples\Ole\AX-Data.xls and a UniScript function that you can find in the file
UniPlot\AutoLoad\AX-Data.ic. Together these small script programs allow the data exchange
between Excel and UniPlot
Lets have a look at the Excel script.
To view the program open the Excel file and select
Tools=>Macro=>Visual Basic-Editor (Alt+F11).
Dim app As Object
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
On Error GoTo Error
Set app = CreateObject("UniPlot.Application")
app.Visible = 1
n = app.Call("AX_DataTest", Target)
Error:
End Sub
The code line Dim app As Object creates a global variable. It was not created inside the function to
avoid it being destroyed when the function exits.
The Worksheet_SelectionChange function will be called by Excel when the selection in the table
changes. A range object is passed as the first parameter by the name Target.
Set app = CreateObject("UniPlot.Application") creates a reference to a running UniPlot
instance. The function is equivalent to the CreateObject function in UniScript.
The app.Visible = 1 statement makes the UniPlot window visible if it was hidden.
The code line n = app.Call("AX_DataTest", Target) calls a UniScript function. The first parameter is a UniScript function name, (in this example AX_DataTest) followed by the function parameters. The number of parameters is limited to 16.
Now lets have a look at the UniScript function AX_DataTest.
The first parameter is the Excel range object. Here we use only the Row and Count property. You will find
a complete description of all properties and methods of the range object in the Excel Online help system.
54
Chapter 7. Functions
UniScript Manual, Release R2016
def AX_DataTest(t)
{
if (t.Rows.Count > 100) {
print "Rows > 100"
} else {
print t.Value
}
}
7.7.7 Example 2 (AX-Curv)
To run the second example, do the following:
• If UniPlot is running, quit UniPlot.
• Start Excel. Open the file :file:‘ UniPlot\Samples\Ole\AX-Curv.xls‘. Excel may display a dialog box
with a message saying that the file contains macros. Select the button Activate Macros.
• The second spreadsheet contains two UniPlot objects each showing one diagram. To send data to the
left diagram select the values 1, 4, 2, 2, etc. Data will be sent to the right diagram when the first value
is not equal to 1.
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
Dim arr(100) As Double
7.7. COM-Interface
55
UniScript Manual, Release R2016
On Error GoTo Error
Worksheets("Sheet
Worksheets("Sheet
Worksheets("Sheet
Worksheets("Sheet
1").OLEObjects(1).Enabled = True
1").OLEObjects(1).AutoLoad = True
1").OLEObjects(2).Enabled = True
1").OLEObjects(2).AutoLoad = True
hDocLeft = Worksheets(1).OLEObjects(1).Object.Handle
hDocRight = Worksheets(1).OLEObjects(2).Object.Handle
t1$
t2$
i =
For
= Cells(22, 2).Value
= Cells(23, 2).Value
0
Each Cell In Target.Cells
arr(i) = CDbl(Cell.Value)
i = i + 1
Next
Set app = Worksheets("Sheet 1").OLEObjects(1).Object.Application
n = app.Call("AX_CurveTest", hDocLeft, hDocRight, arr, i, t1$, t2$)
Error:
End Sub
def AX_CurveTest(hDoc1, hDoc2, y, n, t1, t2)
{
if (y[1] == 1.0) {
hPage = DocGetActivePage(hDoc1);
} else {
hPage = DocGetActivePage(hDoc2);
}
if (hPage == 0) {
return 0;
}
hLayer = PageGetAllDataLayers(hPage)
hData = LayerGetAllDatasets(hLayer);
if (hData == 0) {
hData = XYCreate("test", 1, 1);
LayerAddDataset(hLayer, hData);
}
if (n > 1) {
x = 1:n;
ret = XYSetData(hData, x, y[x]);
}
LayerAutoScale(hLayer)
LayerSetAxisTitle(hLayer, "x", t1)
LayerSetAxisTitle(hLayer, "y", t2)
__FF_FieldUpdate(0, hPage, 0, 0, 0);
PageReplot(hPage);
return n;
}
56
Chapter 7. Functions
UniScript Manual, Release R2016
7.8 The Debugger
Debugging is the process of correcting or modifying the code in a UniScript function.
• Open the file UniPlot\Script\do_new.ic.
• Set the cursor in line 62 (def _DoFileNew()). Press F9 (Toggle-Breakpoint) to set a breakpoint.
At the left side a break point simble will be set (red dot).
• Execute the command filenew. The execution will stop at the breakpoint and a yellow arrow will be
displayed.
• With F10 to single-step through instructions in the program. With F5 you can run to the next break
point.
The UniScript debugger supports the following functions:
Example of debbuging a UniScript function:
F5 Go: Executes code from the current statement until a breakpoint or the end of the program is reached,
or until the application pauses for user input.
F9 Set/remove a break point.
7.8. The Debugger
57
UniScript Manual, Release R2016
Ctrl+F9 Remove all break points.
F10 Step Over: Single-steps through instructions in the program.
F11 Step Into: Single-steps through instructions in the program, and enters each function call that is encountered.
Mostly it is more convenient to display variable contents using tool tips. To display the values place the
mouse cursor an a variable and wait until a small window with the value is displayed. If a variable contains
more than 20 elements, only the first 20 will be displayed.
7.9 Some Annotations about Functions
• UniScript allows recursive function calls. A recursive function is one which calls itself either directly
or indirectly.
• In contrast to C, UniScript passes function parameters by reference and not by value. This makes it
possible for a function to change the values of a parameter. So be careful and create copies of the
parameters:
// INCORRECT
def asin(x)
{
// WRONG !!!!!!
x = -1i .* log (1i .* x + sqrt(1 - x .* x));
if (all(all(real(x) == x))) {
return real(x);
} else {
return x;
}
}
// CORRECT
def asin(xx)
{
x = xx; // Use a copy
x = -1i .* log (1i .* x + sqrt(1 - x .* x));
if (all(all(real(x) == x))) {
58
Chapter 7. Functions
UniScript Manual, Release R2016
return real(x);
} else {
return x;
}
}
• The function what returns a list of all loaded functions.
• The UniScript source code file can be loaded with the load function. The function call can be included
into the file startup.ic.
• To reduce the loading time of the UniScript user function, a UniScript library is loaded during the
execution of the startup file. The name of the function which loads the library is loadiclib. To create
a UniScript library (default name: rs_sl.icl), use the following command:
saveiclib("c:/uniplot/program/rs_sl.icl")
7.9. Some Annotations about Functions
59
UniScript Manual, Release R2016
60
Chapter 7. Functions
CHAPTER 8
UniScript Objects
In chapter COM-Interface the application of the ActiveX interface in UniScript was shown.
xls = CreateObject("Excel.Application")
xls.Visible = 1
xls.Workbooks.Add()
xls.ActiveSheet.Range("b1").Value = "sin(x)"
y = sin(linspace(0, 2*PI))
xls.ActiveSheet.Range("b2:b101").Value = y'
The following chapters describe how UniScript objects can be created and used.
8.1 Introduction
UniScript-Objects are created using the obj_create function. The function creates an empty object. After
the object is created functions and variables can be added:
c = obj_create()
c.unit = "Nm"
c.val = [1,2,3,4]
The object c has two variables unit and val.
Alternatively the following, shorter object-constructor can be used to create the object and add variables.
c = [. unit = "Nm", val = [1,2,3,4] ]
The period behind the opening square bracket (“[”) tells the interpreter (and the programmer) that this is not
a normal array. Without the period a variant matrix with 5 elements would have been created:
c = [unit = "Nm", val = [1,2,3,4] ] // c is not an object
Objects can be assigned to variables. The assignment
b = c;
causes that b and c point to the same object. The assignment b = c; does not copy the object. The object
can be altered using the pointer b or c.
61
UniScript Manual, Release R2016
b.unit = "kg";
print c.unit
// => "kg"
For usual UniScript vectors and matrices the assignment operator will create a copy of the vector or matrix:
v1 = [1,3,7,123]
v2 = v1
v2[1] = 11
print v1[1] // => 1
If you assign a new value to c, c = 0, c does not point to the object any longer. The object can still be
accessed using the b pointer. b = 0 will destroy the last pointer to the object. It will be removed from the
memory by the garbage collector. The garbage collector can be invoked using the gc function. (see gc in the
online help).
Instead of following syntax
object_pointer "." Name = Value
a variable can be accessed and using the index syntax:
Instead of
c.unit = "Nm"
one can write
c["unit"] = "Nm"
If the variable name is not a valid UniScript name, e.g. the name contains blank characters, or special
characters like ‘+’ or ‘-‘ or the name is a key word only the index syntax can be used.
Internally, an object contains two tables. One table for string keys and one table for number keys. Each table
maps unique keys to values.
c = obj_create()
c[1] = 123
c["1"] = 456
c contains now two key-value pairs (elements), one in the number table and one in the string table.
In the object-constructor syntax one can write:
c = [. [1] = 123, ["1"] = 456]
The integer keys can also be negative values
c[-4] = "hello"
c[0] = 1+2i
c[16237623] = -11
UniScript objects contain a number of member functions (methods).
k = c.keys(-1e308, 1e308)
62
Chapter 8. UniScript Objects
UniScript Manual, Release R2016
returns all keys of the object c from the number table. k is a vector with the key values.
The online help contains help for all methods (obj_xxx, e.g. obj_keys).
It is not an error to access an index in the integer table for which no value is specified: a = c[111]
returns the value 0.0. The method has_key (obj_has_key) can be used to check if the key exists:
c.has_key(123) returns TRUE (1) if c[123] exists and FALSE (0) if c[123] does not exists.
Objects can contain as values numbers, complex numbers, strings, vectors and matrices of the three data
types as well as COM objects pointers and UniScript variant matrices.
Objects can contain pointers to objects. It is possible to build complex data structures like lists:
list = obj_create();
list.val = 123;
list.next = obj_create();
list.next.val = 456;
list.next.next = 0;
or in object-constructor syntax:
list = [. val = 123, next = [. val = 456, next = 0]]
8.2 Object-Constructor Syntax
Grammar
prop_val:
NUMBER
|STRING
| "(" exp ")"
| NUMBER "=" exp
| identifier "=" exp
| "[" exp "]" "=" exp
| STRING "=" exp
;
{
{
{
{
counter
counter
counter
counter
=
=
=
=
counter + 1; }
counter + 1; }
counter + 1; }
NUMBER + 1; }
prop_list:
/* empty */
| prop_val
| prop_list "," prop_val
;
constructor:
"[."
prop_list
"]"
;
{ counter = 1; }
/*
/*
/*
/*
/*
/*
/*
Rule1 */
R2 */
R3 */
R4 */
R5 */
R6 */
R7 */
/* R8 */
/* R9 */
/* R10 */
/* R11 */
Example:
[.]
[.123]
// Rule 11, R8
// R11, R9, R1
8.2. Object-Constructor Syntax
63
UniScript Manual, Release R2016
[.(1+2i)] // R11, R9, R3
[. "test 1" = 123] // R11, R9, R7
[. a = 1, b = 2] // R11, R9, R10, R5
Other Examples:
a = [. 1, 2, 3]
is identical to:
a = [.]; a[1] = 1; a[2] = 2; a[3] = 3;
a = [. 5 = 1, 2, 3]
is identical to:
a = [.]; a[5] = 1; a[6] = 2; a[7] = 3;
a = [. [5] = 1, 2, 3]
is identical to:
a = [.]; a[5] = 1; a[1] = 2; a[2] = 3;
8.3 Standard Methods
The following functions can always be written as:
obj_xxx(o, ...)
or shorter in the form:
o.xxx(...)
Instead of a = o.lookup() one can write a = obj_lookup(o).
If the function has only one parameter (obj) the braces can be omitted:
n = o.count;
oParent = o.parent;
obj_copy
obj_count
obj_count_num
obj_count_str
obj_create
obj_has_key
64
UniScript-Object-Functions
obj_copy creates a copy of an object.
obj_count returns the number of variables in an object.
obj_count_num returns the number of number keys in an
object.
obj_count_str returns the number of string keys in an object.
obj_create creates an UniScript object.
obj_has_key checks if a given key exists.
Chapter 8. UniScript Objects
UniScript Manual, Release R2016
obj_info
obj_keys
obj_load
obj_lookup
obj_methods
obj_parent
obj_remove
obj_save
obj_set_at
obj_set_methods
obj_set_parent
obj_set_str_return
set_method_table
obj_info returns a string of the form “obj-name,hexaddress”.
obj_keys returns all keys or a range of keys for the given
object.
obj_load loads an object saved with obj_save from the hard
drive.
obj_lookup returns the value of a given key.
obj_methods returns an object with methods (member
functions) for the given object.
obj_parent returns the parent object or 0 if the object does
not have a parent.
obj_remove removes a key-value pair from an object.
obj_save saves an object as an XML file or as an binary file
on the hard drive or as a string.
obj_set_at adds a key-value pair to the given object. If the
key already exists the value will be overwritten.
obj_set_methods sets the methods (member functions) for
the given object.
obj_set_parent sets the parent object.
obj_set_str_return specifies the return value of obj_lookup.
If a key does not exist, obj_lookup may return 0, an empty
string or throw an exception.
set_method_table sets the methods (member functions) for
the given object.
8.4 Methods for Objects
Beside the standard methods as copy, keys, set_at, etc. (see help for obj_copy, obj_keys, obj_set_at),
new methods can be added to objects.
To add a function to an object (also called member function or method) an object must be created that maps
the method name to a UniScript function.
Example:
def my_methods()
{
return [. test = "my_test"];
}
def my_create()
{
this = [.];
set_method_table(this, "my");
return this;
}
The function “my_test” could look like this:
8.4. Methods for Objects
65
UniScript Manual, Release R2016
def my_test(this, a, b)
{
return a+b;
}
If the expressions
obj = my_create();
obj.test(3,4);
are executed the UniScript interpreter will try to invoke the “my_test” function. The interpreter will pass the
object obj as the first parameter.
The my_create function is called the constructor function. my_create will first create the UniScript
object:
this = [.];
The function call
set_method_table(this, "my");
will invoke the my_methods functions. my_methods creates the object with the methods names.
set_method_table will than copy the object into a global table (g_method_table) and sets the object with
the methods for this with the help of the obj_set_methods function. All objects created by my_create will
contain the same object with the methods, i.e. my_methods will only invoked ones.
At the end the constructor will return the object:
return this;
8.5 Operator Overloading
Most of the operators can not be applied directly to objects.
The following code will create the run time error “+: Operand type incorrect”:
a = [. val = 123];
b = [. val = 456];
c = a + b;
The compare operator
a == b
will return the value 0, i.e a is not identical to b. If b.val = 123 is set a == b would return the value
FALSE. The == operator only returns TRUE if a and b point to the same object.
a = obj_create();
a.val = 123;
b = a;
or
66
Chapter 8. UniScript Objects
UniScript Manual, Release R2016
a = [.val = 123];
b = a;
a == b will return TRUE. The Not Equal operator a != b will also compare the pointers and not the
content. The Not operator (!a) can be used to check if the object has been created.
a = [.];
if (!a) {
error()
}
or
a = [.];
if (a == 0) {
error()
}
An object pointer can be compared with a number, but only the number 0 makes sense. You can redefine the
function of most built-in operators.
Example:
def my_add(this, b)
{
result = this.copy();
result.val = this.val + b.val;
return result;
}
def my_add2(this, b)
{
result = this.copy();
result.val = b.val + this.val;
return result;
}
def my_print(this)
{
print this.val;
}
def my_format(this)
{
return sprintf("%s=%f", this.type, this.val);
}
def my_tonumber(this)
{
return this.val;
}
def my_methods()
{
return [.
tonumber = "my_tonumber",
__print__ = "my_print",
__format__ = "my_format",
__add__ = "my_add",
8.5. Operator Overloading
67
UniScript Manual, Release R2016
__add2__ = "my_add2"
];
}
def my(num)
{
this = [. type = "my"];
set_method_table(this, "my");
if (nargsin() == 1) {
this.val = num;
} else {
this.val = 0;
}
return this;
}
a = my(2);
b = my(3);
d = my(3);
printf("\na + b = %f\n", (a+b).tonumber());
Operator
__destructor__
__print__
__format__
__getproperty__
__setproperty__
__getprop__
__setprop__
__veceval__
__vecassign__
__catcol__
__catcol2__
__catrow__
Description
Destructor. This function is invoked when the GarbageCollector destroys the object.
print a.
Create a string for the debugger.
eval v = a.b
eval a.b = v
eval v = a.b
eval a.b = v
eval a[idx]
eval a[idx] = v
concatenate ([a,b]).
concatenate ([a,b]). Is invoked if a does not have a
__catcol__ method.
concatenate ([a;b]). Is invoked if a does not have a
__catrow__ method.
__setprop__
With __setprop__ a UniScript function can be invoked to execute an expression of the form obj.prop
= value.
Example:
def my_setprop(obj, val)
{
obj["prop"] = val;
}
Inside the property-set function the assignment of the form obj.property = value can not be used.
Otherwise the function would be invoked recursively. One of the following forms should be use to set the
value:
68
Chapter 8. UniScript Objects
UniScript Manual, Release R2016
obj["prop_name"] = val;
obj.set_at("prop_name", val);
obj_set_at(obj, "prop_name", val);
__setproperty__
__setproperty__ has an extra parameter ssProp.
Example:
def my_setprop(obj, val, ssProp)
{
obj[ssProp] = val;
}
__getprop__
__getprop__ is called if an expression of the form obj.prop stand on the right side: val =
obj.prop.
def my_getprop(obj)
{
return obj["prop_name"];
}
__getproperty__
def my_getproperty(obj, ssProp)
{
return obj[ssProp];
}
__veceval__
Will be executed for expressions of the form v = obj[index].
def my_veceval(obj, index)
{
return obj.lookup(index);
}
__vecassign__
Will be executed for expressions of the form obj[index] = val.
def my_vecassign(this, index, val)
{
this.set_at(index, val);
}
Example:
def my_getprop(this)
{
print "in getprop"
return this.lookup("prop");
8.5. Operator Overloading
69
UniScript Manual, Release R2016
}
def my_getproperty(this, ssProp)
{
print "in getproperty"
return this.lookup(strupper(ssProp));
}
def my_setprop(this, val)
{
print "in setprop"
this.set_at("prop", val);
}
def my_setproperty(this, val, ssProp)
{
print "in setproperty"
return this.set_at(strupper(ssProp), val);
}
def my_veceval(this, idx)
{
print "in veceval"
return this.lookup(idx);
}
def my_vecassign(this, idx, val)
{
print "in vecassign"
this.set_at(idx, val);
}
def my_methods()
{
return [.
tonumber = "tonumber",
__setprop__ = [. prop = "my_setprop"],
__getprop__ = [. prop = "my_getprop"],
__getproperty__ = "my_getproperty",
__setproperty__ = "my_setproperty",
__veceval__ = "my_veceval",
__vecassign__ = "my_vecassign"]
}
def my(num)
{
this = [.type = "my"];
set_method_table(this, "my", 1);
if (nargsin() == 1) {
this[1] = num;
} else {
this[1] = 0;
}
return this;
}
a = my(11)
a.prop = 123
print a.prop
a.xyz = 456
print a.xyz
70
Chapter 8. UniScript Objects
UniScript Manual, Release R2016
a[11] = 12
print a[11]
Arithmetic Binary Operators
Operator
__add__
__sub__
__div__
__ediv__
__ldiv__
__mod__
__mul__
__emul__
__power__
__epower__
__shl__
__shr__
__and__
__or__
__xor__
__bitand__
__bitor__
Description
Addition (a + b).
Subtraction (a - b).
Division (a/b).
Elementwise Division (a ./ b).
Left-Division (a b).
Modulus (a % b).
Multiplication (a * b).
Elementwise Multiplication (a .* b).
Exponentiation (a ^ b).
Elementweise Exponentiation (a .^ b).
Left Shift (a << b).
Right Shift (a >> b).
Logical AND (a && b).
Logicol OR (a || b).
Exclusive OR (a @ b).
Bitwise AND (a & b).
Bitwise OR (a | b).
For all arithmetic binary operators a second form exists: __xxx2__, e.g. __add2__. This function is
invoked if the left operant does not have an __add__ function.
Arithmetische unary Operators
Operator
__uminus__
__trans__
__etrans__
__bitcmpl__
Description
Unary negation operator (-a).
Transpose (a’).
Elementwise Transpose (a.’).
Bitwise Complement (~a).
Compare Operators
The operators ==, != and ! have default operators which compare the pointer address of objects.
Operator
__lt__
__le__
__eq__
__ne__
__gt__
__ge__
__not__
Description
Less than (a < b).
Less than or equal to (a <= b).
Equal To (a == b).
Not equal to (a != b).
Greater than (a > b).
Greater than or equal to (a >= b).
Not (!a).
8.5. Operator Overloading
71
UniScript Manual, Release R2016
For all binary operators a second form exists: __xxx2__, e.g. __gt2__. This function is invoked if the
left operant does not have an __gt__ function.
8.6 Inheritance
Sometimes a group of objects have common properties such as Line, Circle and Rectangle. The common
properties are position and pen. The individual properties could be the width an height of the rectangle
the diameter of the circle and the end point of the line. It could make sense to create an base object for
the common properties. The child objects could inherit the properties of the base object (also called parent
object or Superclass object).
In the following example the base object is called shape and the objects which inherit shape are called
circle and rect.
def shape_set_name(this, s)
{
this.name = s;
}
def shape_methods()
{
return [. set_name = "shape_set_name"];
}
def shape(x, y)
{
this = [. x = x, y = y, name = ""];
set_method_table(this, "shape");
return this;
}
def circle_plot(this)
{
printf("<circle x='%d' y='%d' d='%d'/>\n", this.x, this.y, this.d);
}
def circle_methods()
{
return [. plot = "circle_plot"];
}
def circle(x, y, d)
{
this = [. __parent__ = shape(x, y), d = d];
return set_method_table(this, "circle");
}
def rect_plot(this)
{
printf("<rect x='%d' y='%d' a='%d' b='%d'/>\n", this.x, this.y, this.a, this.b);
}
def rect_set_name(this, s)
{
this.name = strupper(s);
}
def rect_methods()
{
72
Chapter 8. UniScript Objects
UniScript Manual, Release R2016
return [.
plot = "rect_plot",
set_name = "rect_set_name"];
}
def rect(x, y, a, b)
{
this = [. __parent__ = shape(x, y), a = a, b = b];
return set_method_table(this, "rect");
}
8.7 Functions calls with UniScript Objects
Some programming languages have the following options to pass function parameters:
• Named Arguments
• Arguments with default values
• Variable number of arguments
UniScript does not offer these technique, but they can be simulated using objects.
Named arguments:
def test_named(arg)
{
return arg.a + arg.b;
}
test_named([.b = 1, a = 2])
test_named([.a = 2, b = 1])
Arguments with default values:
def test_default(arg)
{
d = [.a = 11, b = 22];
for (i in arg.keys) d[i] = arg[i];
return d.a + d.b;
}
test_default([.a = 1000])
test_default([.b = 1000])
test_default([.a = 1, b = 2])
test_default([.])
Variable number of arguments:
def test_var(args)
{
print "test_var"
for (i in args.keys(1)) {
print args[i]
}
}
8.7. Functions calls with UniScript Objects
73
UniScript Manual, Release R2016
test_var([. 11111, "Hallo", ([1,2,3]), (2+3i)]);
test_var([. 1,2,3,4]);
8.8 Example
The following example is an object to read and write data to a file.
def file_methods()
{
return [.
read = "file_read",
write = "file_write",
name = "file_get_name",
close = "file_close",
__shl__ = "file_shl",
__destructor__ = "file_close",
__format__ = "file_format"];
}
def file_open(ssFileName, ssMode)
{
fp = fopen(ssFileName, ssMode);
if (!fp) {
return 0;
}
this = [. fp = fp, name = ssFileName];
set_method_table(this, "file");
return this;
}
def file_format(file)
{
return sprintf("fp = %d\nname = %s", file.fp, file.name);
}
def file_read(file, ssType, n)
{
if (nargsin() == 2) {
return fread(file.fp, ssType);
} else {
return fread(file.fp, ssType, n);
}
}
def file_write(file, ssType, dat)
{
return fwrite(file.fp, ssType, dat);
}
def file_get_name(file)
{
return file["name"];
}
def file_close(file)
{
fclose(file.fp);
74
Chapter 8. UniScript Objects
UniScript Manual, Release R2016
}
// file << val
def file_shl(this, other)
{
if (type(other) == "real") {
this.write("double", other);
} else if (type(other) == "string") {
this.write("char", other);
} else {
other.write(this);
}
return this;
}
def f_int32_write(this, file)
{
file.write("int", this.val);
}
def f_int32_methods()
{
return [. write = "f_int32_write"];
}
def f_int32(v)
{
return set_method_table([. type = "f_int32", val = v], "f_int32");
}
def test()
{
file = file_open("d:/test.txt", "wb");
file << [1, 3] << f_int32([4,5,6]) << "This is a test!";
file.close();
file = file_open("d:/test.txt", "rb");
print file.read("double", 2);
print file.read("int", 3);
print file.read("char");
file.close();
}
8.8. Example
75
UniScript Manual, Release R2016
76
Chapter 8. UniScript Objects
Index
Symbols
’, 26
*, 24
+, 23
.’, 26
.*, 24
/, 24
==, 28
#define, 15
%, 25
__add__, 71
__and__, 71
__bitand__, 71
__bitor__, 71
__catcol2__, 68
__catcol__, 68
__catrow__, 68
__destructor__, 68
__div__, 71
__ediv__, 71
__emul__, 71
__epower__, 71
__format__, 68
__getprop__, 68, 69
__ldiv__, 71
__mod__, 71
__mul__, 71
__or__, 71
__power__, 71
__print__, 68
__setprop__, 68
__setproperty__, 68
__shl__, 71
__shr__, 71
__sub__, 71
__vecassign__, 68, 69
__veceval__, 68, 69
__xor__, 71
^, 25
\, 24
>, 28
>=, 28
<, 28
<=, 28
0x, 15
A
ActiveX, 49
ADO, 50
Autoload, 53
B
break, 34
C
C, 13, 15, 45, 53
C++, 13, 53
call by reference, 58
call by value, 58
COM, 49
COM-Interface, 49
comments, 13
complex constants, 16
continuation lines, 14
continue, 34
CreateObject, 49, 59
D
DAO, 50
dB, 41
Debugger, 56
77
UniScript Manual, Release R2016
def, 41
DGEMM, 46
dispatch interface, 49
DLL’s, 45
E
eig, 44
else, 31
error, 35, 36
ESC-Key, 35
escape sequences, 16
Excel, 49, 59
Excel 2000, 53
except, 35
exception, 35
long strings, 17
loops, 34
M
MessageBox, 36, 52
multiple return values, 44
N
null-characters in strings, 17
O
hexadecimal constants, 15
obj_copy, 64
obj_count, 64
obj_count_num, 64
obj_count_str, 64
obj_create, 59, 64
obj_has_key, 64
obj_info, 64
obj_keys, 64
obj_load, 64
obj_lookup, 64
obj_parent, 64
obj_remove, 64
obj_save, 64
obj_set_at, 64
obj_set_methods, 64
obj_set_parent, 64
obj_set_str_return, 64
object constructor, 62
objects, 62
octal constants, 15
overloading, 66
I
P
i, 16
ICERR_INTERRUPT, 36
if, 31
in, 32
index expressions, 20
isreal, 36
PI, 15
pointer, 62
print, 31
printf, 32
F
fclose, 36
FindWindow, 45
fopen, 36
for, 32
FORTRAN, 45, 46
fread, 36
G
garbage collector, 62
gc, 62
GetCurrentDirectory, 48
global, 42
H
J
JavaScript, 53
L
load, 59
Local Variables, 42
log10, 41
78
R
real, 52
recursive function calls, 58
RegisterFunction, 46
return, 43
rs_sl.icl, 59
S
set_method_table, 64, 66
Index
UniScript Manual, Release R2016
SetCurrentDirectory, 48
sqrt(-1), 16
startup.ic, 45, 59
string constants, 16
SYM_BUILDIN, 41
symbols, 41
T
try, 35
V
variables, 17
variant matrix, 51
VariantConvert, 52
VBScript, 53
W
what, 59
while, 33
Index
79