TkScript |
|
reference guide | Statements |
1. Statements
A
statement is a single element in a list of statements (
statement sequence).
Statements are usually executed in first to last order.
Flow control statements, like .e.g.
if
,
for
or
loop
can be used to conditionally execute a statement sequence respectively loop it.
A statement has no return value but is rather used to either store the result value from its contained expression(s) to a memory location or use it as a parameter for a control structure.
Statements can be categorized as following:
- Variable declarations
- Constant declarations (define, enum)
- Other datatype declarations (class, module, function, method, exception, ..)
- Variable/Member/Array/HashTable assignments
- Flow control (do..while, if, for, foreach, loop, break, while, switch..)
- Function/method calls
- Delegate assignments or calls
- Other (e.g. try/catch/finally/throw, prepare, clamp, wrap, global mutex declaration or signal callback bindings)
1.1. Declarations
TkScript supports the following
declarative statements:
- class
- Declare a script class datatype
- define
- Define a module or class constant
- Also used to define a new exception/error type
- enum
- Create a constant enumeration
- function
- Declare a module or class function (static method)
- module
- Set the current (unique) module name
- namespace
- Create or select a namespace
1.2. Flow control
TkScript supports the following
flow control statements:
1.3. Function/method calls
The following statements are used to handle function or method calls:
- Native and script function calls
- Native and script class method calls
- Special built-in functions and methods
- clamp
- prepare
- use
- wrap
- Array/hashtable assignments (yacArray*, yacHash*)
The
special functions and methods are usually called
indirectly by using certain kinds of expressions or statements.
2. Statement sequences
Statements are usually grouped in blocks (statement sequences) which are enclosed in
{}
brackets.
For every source file, a top level statement sequence is implicitely created. This makes it possible to write a TKS script which just consists of a single statement, for instance.
Statements outside of functions and methods are executed after successful compilation of all modules defined in the project file. The order of execution hereby equals the order of occurrence in the project file. This mechanism can be used to initialize objects, allocate arrays and/or initialize variables.
Example:
print "hello, world.";
...represents a complete, valid TKS program.
In contrary to C, a statement block may not directly contain another statement block:
Example:
if(i==42)
{
{
/* ..this does not work.. */
}
}
Example:
if(i==42)
{
if(j==1)
{
/* ..this is allowed.. */
}
}
The
{}
brackets can be omitted if a statement sequence only contains one single statement
but it is recommend to use them anyway to improve code readability and prevent some more obscure problems like e.g.
dangling else:
int i = 41, j = 1;
if(i == 42)
if(j == 1)
j = 2;
else
j = 3;
print j;
In order to make it work as expected, the code above should better be written as:
int i = 41, j = 1;
if(i == 42)
{
if(j == 1)
{
j = 2;
}
}
else
{
j = 3;
}
3. The if..else statement
This statement is used to branch conditionally depending on the result of a boolean expression.
If the expression evaluates to
true
(!=0) then the first statement block will be executed, otherwise the control flow will branch to the else statement, if available.
Example:
int i = 42;
int j;
if(i == 42)
{
j = 1;
}
Example:
int i = 41;
int j;
if(i == 42)
{
j = 1;
}
else
{
j = 2;
}
Note: The () brackets are not required; actually they are part of the expression:
Example:
int i = 42;
int j;
if i == 42
j = 1;
Example:
int i = 41;
int j;
if i == 42
j = 1;
else
j = 2;
4. The do..while statement
This statement is used to loop a given statement (-sequence) until the boolean expression after
while
evaluates to
false
(0).
The
break
statement may be used to immediately abort a
do
..
while
loop.
Example:
int i = 0;
do i++; while i < 10;
Example:
int i = 0 , j = 0;
do
{
i++;
j++;
}
while( (i + j) < 10 );
The boolean condition will be tested each time a loop iteration finishes, i.e. the
do
..
while
loop body is run at least once.
Similar to the
if
statement, the () brackets around the conditional expression are optional and actually part of the expression.
5. The while statement
This statement is used to repeat a statement sequence as long as the boolean expression after
while
evaluates to
true
(!=0).
The
break
statement may be used to immediately abort a
while
loop.
Example:
int i = 0;
while i < 10 i++;
Example:
int i = 0 , j = 0;
while( (i + j) < 10)
{
i++;
j++;
}
6. The switch statement
This statement is used to test the value of an expression for a number of conditions: If a condition is met, the associated statement sequence is executed. The condition
default
refers to all conditions not listed explicitely.
Each statement sequence should be closed using the
break
keyword. Otherwise, the statement sequence of the next condition will be executed as well - regardless whether that condition is met or not (
run into case label).
Example:
int i = rnd(10);
switch(i)
{
case 1:
trace "i is 1.";
break;
case 2:
trace "i is 2.";
break;
case 3: // run into case "4"
case 4:
trace "i is 3 or 4";
break;
default:
trace "i is neither 1,2,3 nor 4.";
break;
}
String
and
float
condition expressions are also allowed.
case
expressions do not need to be constant but may even contain function calls:
function MyFunction() {
return 10;
}
String
s = Arguments[0];
switch(s)
{
case "-h":
case "--help":
/* ... */
break;
case MyFunction(): // case 10
/* ... */
break;
}
7. The for statement
This statement is used to repeat the loop body as long as the loop condition, a boolean expression, evaluates to
true
.
The mode of operation of the
for
loop is similar to the
while
loop, although additional initialization and modification statements may be provided.
The empty statement (
;
) is used to omit the initialization; no semicolon is required to terminate the modification statement.
The initialization statement is called before the first loop iteration starts, the modification statement is called every time an interation finishes. Before each iteration, the loop condition is tested and if it evaluates to
true
, the loop body is executed and the next iteration starts.
The
break
statement may be used to immediately abort a
for
loop.
Example:
for(int i=0; i<10; i++) trace "i="+i;
* trace "i="+i; - is the loop body
* int i=0; - is the loop initialization
* i<10; - is the loop condition
* i++ -is the modification statement
* i -is the loop counter
Example:
int i = 0;
for(; i<10 ;) trace "i="+i++; // omit the init + modif. statements
Example:
int n = 16; // http://www.bagley.org/~doug/shootout/nestedloop
int x = 0;
for (int a=0; a<n; a++)
for (int b=0; b<n; b++)
for (int c=0; c<n; c++)
for (int d=0; d<n; d++)
for (int e=0; e<n; e++)
for (int f=0; f<n; f++)
x++;
The shortest way to write an infinite loop in TkScript:
for(;;)
{
stdout "*forever";
}
8. The loop statement
This statement resembles the
while
and
for
statements.
Actually, it represents a
frequently used special case of the
for
resp.
while
statement.
The expression given after the
loop
keyword determines the number of iterations.
This integer expression is evaluated just before the first iteration starts.
There is no way to access the internal loop counter, it will simply be decremented until it reaches 0.
The brackets around the integer expression are, similar to the
do
..
while
,
while
and
for
statements, technically part of the expression.
The
break
statement may be used to immediately abort a loop.
Example:
loop 10 trace "loop.";
Example:
int i = 0;
loop(10) trace "i=" + i++;
Example:
int n = 16; // http://www.bagley.org/~doug/shootout/nestedloop
int x = 0;
loop(n)
loop(n)
loop(n)
loop(n)
loop(n)
loop(n)
x++;
Example (uses the
tksdl
and
tkopengl
plugins):
use tksdl;
use tkopengl;
Texture tex; tex.alloc(256, 256, 4);
int k = 0;
loop(tex.sy)
{
loop(tex.sx)
{
tex[k++] = argb(rnd(255), rnd(255), rnd(255), rnd(255));
}
}
tex.saveImage("test.png");
9. The foreach statement
The
foreach
statement is used to iterate container objects like for instance String lists, Arrays, HashTables or Pools.
The loop body will be executed for each element in the given container object.
The
break
statement may be used to immediately abort a foreach-loop.
Example:
String
t , s = "one \"two and a half\" three";
foreach t in s.splitSpace(true) trace "t=" + t;
Example:
int i; foreach i in [1,2,4,7,9,11] trace "i=" + i;
The following example counts the number of occurences of unique words in a text file:
int i=0; // http://www.bagley.org/~doug/shootout/bench/wordfreq/
String
s,k;
HashTable
words; words.alloc(20000);
s.loadLocal("test.tks", true);
foreach k in s.splitSpace(false)
{
k.toLower();
words[k] = int(words[k]) + 1;
}
StringArray
sta; sta.alloc(words.numElements);
IntArray
ita; ita.alloc(words.numElements);
i = 0;
foreach k in words {
ita[i] = i;
Integer
io;
io.value = words[k];
sta[i] = io.printf("%7d") + " " + k;
i++;
}
sta.sortByValue(ita, false);
i = words.numElements;
loop(--i)
trace sta[ita[i--]];
trace "words.numElements=" + words.numElements;
10. The break statement
This statement is used to break out of
do
..
while
,
while
,
for
,
loop
, and
foreach
loops.
Example:
int i;
print "loop:";
i = 0;
loop(10)
{
if(i == 4)
break;
print i++;
}
print "while:";
i = 0;
while(i < 10)
{
if(i == 4)
break;
print i++;
}
print "dowhile:";
i = 0;
do
{
if(i == 4)
break;
print i++;
} while(i < 10);
print "foreach:";
foreach i in [0,1,2,3,5,7]
{
if(i == 5)
break;
print i;
}
11. The try..catch, finally statements
The
try
,
catch
and
finally
statements are used to handle exceptions or simply run clean-up code before passing an exception to the caller.
Also see
TkScript reference guide / Exceptions
,
Exceptions
.
Example:
try print "hello, world."; catch(Error e) trace "whoops.."; finally trace "cu!";
12. The prepare statement
This statement is used to run
one-time initializations in the context of a function.
In the following example, the statement sequence given after the
prepare
keyword will be executed only
once for all calls to function
FLookUp
:
function FLookUp(int _i) {
IntArray
lut;
prepare
{
lut.alloc(512);
int i = 0;
loop(256) lut.add(i++);
loop(256) lut.add(255);
}
return lut[_i];
}
trace FLookUp(184);
trace FLookUp(384);
Please notice that regular variable initializations are run everytime a function is called:
function FVarInit() {
int i = 42; // a "static" variable
local float f = PI; // a "local" variable
print "i=" + i;
print "f=" + f;
i = 23;
f = 2PI;
}
FVarInit();
FVarInit();
13. The clamp and wrap statements
Up: |
- TkScript Reference Guide » Statements » The clamp and wrap statements
|
These statements are used to limit the values of variable (int, float or
Object
reference) to a given range.
Example:
float f = 32; clamp f 0 20; // f => 20
Example:
int i = 32; wrap i 0 20; // i => 12
The
clamp
and
wrap
functionality is also available for C++/YAC objects although only few classes support it. See
tkmath
for an example.
The
clamp
statement is implemented using the following C-code:
if(var->pointer.float_val < min.value.float_val)
var->pointer.float_val = min.value.float_val;
else
if(var->pointer.float_val > max.value.float_val)
var->pointer.float_val = max.value.float_val;
The
wrap
statement is implemented using the following C-code:
if(var->pointer.float_val < min.value.float_val)
var->pointer.float_val =
(var->pointer.float_val - min.value.float_val) + max.value.float_val;
else if(var->pointer.float_val >= max.value.float_val)
var->pointer.float_val =
min.value.float_val + (var->pointer.float_val - max.value.float_val);
14. The use statement
This statement is used to dynamically load native program components (
plugins) at runtime.
Each plugin is associated with one shared object file (
.dll
or
.so
file extension).
Plugins will first be searched in the current directory, then in the directory determined by the environment variable
TKS_PLUGIN_PATH
and finally in the directory stored in the registry key
HKLM\Software\TKS\TKS_PLUGIN_PATH
(
Microsoft Windows only).
For more information about the plugin directories, see
TKS_PLUGIN_PATH
.
Example:
use tkopengl; // load the OpenGL/libPNG extension
use tksdl; // load the SDL/SDL_net extension
Viewport.openWindow(640,480);
SDL.eventLoop();
Another use of the statement is to bind script functions to events raised by C++ objects:
use tkopengl;
use tksdl;
function MyOnKeyboard(Key _k) {
trace "key \""+_k.name+"\" was pressed";
if(_k.pressed == VKEY_ESCAPE) SDL.exitEventLoop();
}
Viewport.openWindow(640,480);
use MyOnKeyboard for SDL.onKeyboard; // bind MyOnKeyboard callback
SDL.eventLoop();
The
use callbacks
syntax is used to automatically bind C++ event/signal handlers to script functions.
The name and signature of the script function must match the C++ signal definition.
Example:
use tkopengl;
use tksdl;
function onKeyboard(Key _k) {
trace "key \""+_k.name+"\" was pressed";
if(_k.pressed == VKEY_ESCAPE) SDL.exitEventLoop();
}
Viewport.openWindow(640,480);
use callbacks; // auto-bind all available callbacks
SDL.eventLoop();
15. The define and enum statements
These statements are used to define constant values.
Example:
#define MYCONSTANTINT 41
#define MYCONSTANTFLOAT 1.23
#define MYCONSTANTSTRING "hello, world"
print MYCONSTANTINT+1;
print MYCONSTANTFLOAT*2;
print MYCONSTANTSTRING;
enum { RED,GREEN,BLUE };
print "RED="+RED+" GREEN="+GREEN+" BLUE="+BLUE; // => RED=0 GREEN=1 BLUE=2
enum { FLAG0=0x01,
FLAG1=0x02,
FLAG2=0x04,
FLAG3=0x08,
FLAG4=0x10,
FLAG5=0x20,
FLAG6=0x40,
FLAG7=0x80
};
print 255&FLAG7;
print Object
(255&FLAG7).printf("0x%02x");
Please notice that only single string-replacements are being made. TkScript does not have a macro-preprocessor, i.e. the following code will raise an error:
// !!NOT ALLOWED!!
#define APLUSB (a+b)
int a=1,b=2;
print APLUSB;
The
class constant parser is a bit more sophisticated and allows complex expressions and strongly typed constants, also see
Class constants
.
16. The print statement
The
print
statement is used to print a
String
to the stdout stream.
There are a couple of variations of the
print
statement available:
String
s = "hello, world.";
print s; // print to stdout, automatically append linefeed character
stdout s; // print to stdout
stderr s; // print to stderr
17. The trace statement
The
trace
statement is used to print a debug
String
to the stdout stream.
In contrary to the
print
statement, the
trace
output can be statically excluded from execution at compile-time or dynamically at run-time:
trace s; // mainly used for debug output, can be disabled at compile or runtime
trace true; // enable compile-time "trace" statements (default)
trace false; // disable compile-time "trace" statements
dtrace true; // enable run-time "trace" statements (default)
dtrace false;// (temporarily) disable run-time "trace" statements
Example:
function TraceHello(String
arg) {
trace "hello" + arg;
}
TraceHello(", world.");
dtrace false;
TraceHello(", what ?");
dtrace true;
TraceHello(", world!");
18. The die statement
The
die
statement is used to raise the fatal/critical
Death
exception and quit the current application (after automatic clean up, of course).
Example:
String
s;
try
{
if!(s.loadLocal("somefile.txt", true))
{
die "could not load \"somefile.txt\"";
}
}
catch(Death e)
{
print "caught Death exception. darn :-)";
}
Note: The
die
statement is a reminiscence to the
Perl
language ;-)
19. The function statement
The
function
statement is used to define a function.
Please see
TkScript reference guide / Functions
for more information about functions.
Example:
function MyFunction(int i, float f, String
s) {
print "i="+i+" f="+f+" s=\""+s+"\".";
}
MyFunction(42, PI, "hello, world.");
20. The constraint statement
Up: |
- TkScript Reference Guide » Statements » The constraint statement
|
The
constraint
statement is used to define a function argument or return value constraint expression.
Please see
Constraints
for more information about function constraints.
Example:
constraint csisstring _ instanceof String
"is a string";
class C {
test(Object
o.csisstring) { trace typename(o); }
}
C c;
c.test("hello, world.");
21. The exception statement
The
exception
statement is used to define a new exception type.
Please see
TkScript reference guide / Exceptions
,
Exceptions
for more information about exceptions.
Example:
define exception MyError : UncriticalError;
try
{
throw MyError("cu!");
}
catch(MyError e)
{
trace "caught error "+e.name+" message="+e.message;
}
22. The return statement
The
return
statement is used to return from a function or method call. It can also be used to set the default return value.
Please see
The return statement
for more information about the
return
statement.
Example:
function Test() {
return "hello, world.";
}
function Test2() {
return = "world.";
stdout "hello, ";
}
print Test();
print Test2();
23. The class statement
The
class
statement is used to define a class.
Please see
TkScript reference guide / Classes
for more information about classes.
Example:
namespace test;
class C {
explain "A simple test class.";
define int CONSTANT = 42;
define exception MyException : UncriticalError;
static boolean b = false;
int i = 23;
float f = PI;
String
s = "n/a";
static MyStaticMethod() : boolean {
b = ! b;
return b;
}
public method myMethod() {
print "i="+i+" f="+f+" s=\""+s+"\".";
throw MyException("test");
}
}
C.b = true;
C.MyStaticMethod();
C c;
c.i = 42;
c.s <= "hello, world.";
c.myMethod();
24. The delegate statement
The
delegate
statement is used to declare or call a method delegate.
Also see
Delegates
.
25. The explain statement
The
explain
statement is used to embed inline documentation for a previous function, method, class or constant declaration.
When a script is run with the
-ee
,
--emitexplanations
command line option (see
Emitting inline documentation in DOG format
), the TkScript runtime will dump all inline documentation, encoded in a very simple ASCII format, to
stdout
.
The DOG (see
The DOG manual
) documentation tool can parse this output and generate a set of HTML pages. "DOG" uses a JavaDoc-like syntax.
Technically speaking, TkScript itself does not define a format for this
document string.
Example:
function Test(int i) {
explain 'Synopsis for function "Test".
Long description for function "Test".
@arg i Description of argument "i"
@returns Description for return value
@see MyClass
';
}
class MyClass {
explain 'Description for class "MyClass"..';
define int CONSTANT = 42;
explain 'Description for integer constant "CONSTANT"..';
public method test(int i) {
explain 'Description for method "test"..
@see Test
';
}
}
auto-generated by "DOG", the TkScript document generator. Wed, 31/Dec/2008 15:53:35