TkScript |
|
reference guide | Expressions |
1. Expressions
Expressions are used to combine one, two, three or many values (subexpressions) to a result value, possibly by using operators.
The most simple example for an expression is a constant value:
int i = 42; // Assign result of constant expression "42" to variable "i"
float f = PI;
String
s = "hello, world.";
TkScript supports quite a number of expression types. This section only lists a couple of the more distinct expressions.
You can read more about general unary, binary and ternary expressions in the
TkScript reference guide / Operators
chapter.
1.1. Nested expressions
It is sometimes necessary to override operator priorities by nesting an expression in a sub-expression:
print 1 + 2 * 3; // => 7
print (1 + 2) * 3; // => 9
Nested expressions can improve the readability of a source code. Notice how the brackets around the
if
expression are actually part of the expression:
int i = 42;
int j = 41;
String
s = "hello, world.";
if (i <= 42) && (++j < 43) && (s == "hello, world.")
{
print "ok";
}
Also see
The while statement
,
The for statement
,
The do..while statement
,
The loop statement
,
The foreach statement
,
The switch statement
.
2. Constant expressions
The result value of a constant expression is, as the name implies, constant and can be determined while a script is being compiled.
Example:
// "2 + 3 * 4" is optimized to constant value "14"
// at compile time:
int i = 2 + 3 * 4;
This
constant folding will also be done for objects:
IntArray
ia <= [1, 1+1, 3, 4, 5, 6, 7, 8];
3. Variable expressions
A variable expression simply returns the value of a variable:
int i;
int j = i + 1; // read "i", add "1" and assign result to "j"
3.1. Pre/Post In/Decrement
Integer and even float variables can be incremented (+1) or decremented (-1) before / after their value is returned in an expression.
int i = 41;
int j = ++i; // increment "i" and assign to "j"
int k = j++; // assign "j" to "k" and increment "j" afterwards
int l = --i; // decrement "i" and assign to "j"
int m = j--; // assign "j" to "k" and decrement "j" afterwards
Double
d = 0;
Double
e = d++;
Double
f = --d; // pre/post inc/dec may not work for all object types..
Since the
++
and
--
operators modify a variable, this feature should not be used when the variable is used more than once in an expression. The order of evaluation (left-to-right or right-to-left) is not strictly defined.
int i = 41;
int j = --i + i++;
3.1.1. In statements
The pre/post inc/dec operators can also be used in statements:
int i = 41;
i++;
int j = i;
int k = j;
j++;
i--;
int l = i;
int m = j;
j--;
Example:
for(int i=0; i<10; i++) {
print i;
}
loop(20-i) {
print i++;
}
4. The range expression
The range expression tests whether an int or float value lies between the given boundaries.
Example:
boolean b;
int i = 5;
b = (1 < i < 10);
float f = 5.23;
b = (1.1 < f < 10.10);
5. The "mini-if" ternary expression
This expression returns the value of two alternative result expressions depending on the boolean result value of a conditional expression.
Example:
int i = rnd(10) , j = rnd(10) , k = i > 5 ? (i + j) : (j - i);
The above example equals the following program in terms of functionality:
int i = rnd(10), j = rnd(10), k;
if(i > 5)
{
k = i + j;
}
else
{
k = j - i;
}
6. Object expressions
Up: |
- TkScript Reference Guide » Expressions » The new and deref expressions
|
6.1. The new expression
The
new
expression is used to spawn a new instance of the right-handside class type.
This works for native C++ API classes as well as user defined script classes.
function NewString {
String
s <= new String
; // allocate new String
return deref s; // grab ownership for String from "s" and
// return temporary value
}
String
mynewstring <= NewString();
6.1.1. Arguments to new
TkScript does not support parameter lists in
new
expressions.
It is recommended to use init/exit, alloc/free or similarly named methods instead:
Buffer
b; // Create "blank" instance of Buffer
b.size = 256; // Call setSize() and allocate 256 elements
Parametrizable constructors can also be emulated by using static class methods:
class MyClass {
int i;
float f;
String
s;
public static New(int i, float f, String
s) returns MyClass {
local MyClass c;
c.init(i, f, deref s);
return deref c;
}
protected method init(int _i, float _f, String
_s) {
i = _i;
f = _f;
s = _s;
}
}
MyClass mc <= MyClass.New(42, PI, "hello, world.");
6.2. The deref expression
This expression is used to unlink an object reference, including the
ownership for it, from a variable or class member.
The object can then be bound to another container or it will be deleted when the statement which includes the
deref
expression terminates.
Example:
HashTable
ht;
Double
d;
ht["mydouble"] = deref d; // unlink object from variable "d"
// Variable "d" now stores a simple reference to the Double object.
// The hashtable element "mydouble" will also store a reference to the
// object but it will also have the ownership for it.
// The Double object is deleted when the HashTable object is deleted
Example:
class C {
String
s;
public method unlinkS() {
return deref s;
}
}
C c;
trace #(c.unlinkS());
7. The [] array expression
The
[]
expression is used to create arrays on-the-fly.
The return type of the expression, i.e. the array
Object
type, actually depends on the array elements:
- if all elements are integers, an
IntArray
is returned
- if all elements are floats, a
FloatArray
is returned
- if all elements are objects, a
PointerArray
is returned
- if all elements are strings, a
StringArray
is returned
- if the element types are mixed, a
ValueArray
is returned
Example:
IntArray
ia <= [1, 2, 3];
FloatArray
fa <= [1.1, 2.2, 3.3];
PointerArray
pa <= [null, Double
, Float
];
StringArray
sa <= ["hello", ", ", "world."];
ValueArray
va <= [1, 2.2, "hello, world."];
If uncertain about the array type, you can still assign/copy the returned array to an existing
Object
(instead of copying the
reference to it) :
IntArray
ia = [1, 2, 3];
FloatArray
fa = [1.1, 2.2, 3.3];
PointerArray
pa = [null, Double
, Float
];
StringArray
sa = ["hello", ", ", "world."];
ValueArray
va = [1, 2.2, "hello, world."];
Similar to the list and hashtable expressions, prepending the array with the keyword
new
will make the expression return a
new Object
each time it is evaluated:
function ReturnNewIntArray() {
return new [1, 2, 3];
}
IntArray
ia <= ReturnNewIntArray();
The array element expressions are usually evaluated each time the array expression is evaluated, regardless whether a new array is returned or simply a
non-deletable reference to a static
Object
.
However, if all array element expressions can be
folded to a constant value, and the
new
keyword was not used, the array object becomes a constant
Object
.
Also see
Via array variables
.
8. The #[] hash table expression
Up: |
- TkScript Reference Guide » Expressions » The #[] hash table expression
|
The
#[]
expression is used to create associative arrays (
hashtables) on-the-fly.
The expression returns a
HashTable
object whose elements are updated each time the expression is evaluated.
Example:
HashTable
ht <= #[a=1, b=2, c=3];
print ht["c"];
Please notice that the
#[]
expression usually returns always the same
HashTable
object (for each occurence of the expression).
In order to allocate a new
HashTable
object before the hashtable elements are initialized, prepend the expression with the
new
keyword:
HashTable
ht <= new #[a=1, b=2, c=3];
print #(deref ht);
The
#[]
expression can be used recursively. For example, in order to create a
hash of hashes, try the following:
HashTable
ht <= #[hash1=#[a=1, b=2, c=3],
hash2=#[a=#[x=1], b=#[x=1 y=2], c=#[x=1 y=2 z=3]]
];
Also see
The HashTable class
.
9. The #() value expression
This expression is used to catch the return
value,
type and
Object
ownership of an expression and wrap it in a
Value
Object
.
Also see
Value wrapper objects
,
Native functions
.
Example:
function ReturnSomething(int _what) {
switch(_what)
{
case 0:
return 0;
case 1:
return 42;
case 2:
return PI;
case 3:
return new Time
;
case 4:
return "hello, world.";
}
}
Value
vi <= #(ReturnSomething(1)); // -return an integer
Value
vf <= #(ReturnSomething(2)); // -return a floating point number
Value
vo <= #(ReturnSomething(3)); // -return an object
Value
vs <= #(ReturnSomething(4)); // -return a String
trace "vi.value=" + vi.value;
trace "vf.value=" + vf.value;
trace "vo.value=" + vo.value;
trace "vs.value=" + vs.value;
A new
Value
object is returned everytime the expression is called:
int i = 42;
loop(3)
{
trace #(#(i));
}
There is an exception: If the
Value
object is optimized to a constant value, the #() value expression will always return the same object:
loop(3)
{
trace #(#(42));
}
10. The {} list expression
The
ListNode
expression is used to create arbitrary-length double linked lists on-the-fly.
Example:
ListNode
l <= {1, 2.2, "hallo"};
trace #(deref l);
The
ListNode
expression usually returns the same object (per occurence). If you want a new
ListNode
object to be returned everytime the expression is called, prepend the list with the
new
keyword:
ListNode
l <= new {1, 2.2, "was"};
trace #(deref l);
Here is a simple list example that uses the {} list initializer expression (from 2004):
ListNode
l <= {1, 2.2, "hallo"};
ListNode
c;
c <= l.tail; c.appendValue(#("welt"));
c <= l.tail; c.appendValue(#(Object
(42)));
c <= l.tail; c.appendValue(#(new String
()));
Value
v;
foreach v in {1, 2.2, "hi", Object
(42), #(5), 6}
trace "v.type=" + TKS.constantToString(v.type, "YAC_TYPE_") +
" v.string=" + v.stringValue;
trace l;
ListNode
l2,l3;
function evalListExpr() {
trace "---------------------------------";
l2 <= {rnd(1), rnd(2), rnd(3), #(rnd(42))};
l3 <= l2.copy;
c <= l3.tail; c.appendValue(#("EOL."));
trace l3;
}
loop(1)
evalListExpr();
Also see
Permissions
.
11. The instanceof expression
The
instanceof
expression is used to determine whether the class type of the left-handside value of the expression is compatible to the class type of the right-handside value.
Example:
Object
o <= StdOutStream
;
if(o instanceof Stream
)
{
print "ok";
}
This works for native C++ API classes as well as user defined script classes:
class BaseClass { }
class MyClass : BaseClass { }
MyClass mc;
if(mc instanceof BaseClass)
{
print "ok";
}
Also see
Polymorphy
.
12. Expressions as statements
Up: |
- TkScript Reference Guide » Expressions » Expressions as statements
|
Expressions may not be used as
statements, in general.
There is a work-around, though: By assigning the result of an expression to a dummy value ("
_
"), thus discarding it, expressions can be used as statements, too:
_= 1 + 2;
13. Built-in functions
The following is a list of function-like expressions, intrinsics, which are built into the scriptengine.
These intrinsics do not involve any real functions calls: For example, when generating code in the JIT compiler, some of these functions can be inlined into the generated code.
13.1. The @() address expression
The
@
() expression is used to return the address of an object.
On 32bit platforms, this will simply copy the 32bit object address and change the value type to
int
.
On 64bit platforms, this will wrap the 64bit object address into a new
Long
object and return it.
Example:
String
s;
trace #(@(s));
This can sometimes be useful when comparing object references:
String
s = "hello, world.";
String
t = "hello, world.";
if(@(s) != @(t))
{
print "ok";
// note: the objects "look" the same but are stored at different
// memory locations !
}
13.2. The 2n() expression
The
2n
() expression returns the next bigger power of two integer value:
int i = 2n(63);
13.3. The abs() expression
The
abs
() expression returns the absolute value of an int or float value:
int i = abs(-42);
float f = abs(-PI);
13.4. The acos() expression
The
acos
() expression returns the arc cosine of a float value:
float f = acos(1.0);
13.5. The argb() expression
The
argb
() expression packs four 8bit values
a
,
r
,
g
,
b
into a 32bit value:
int a=$11, r=$22, g=$33, b=$44;
int argb32 = argb(a, r, g, b); // argb32 => 0x11223344
Integer
io = argb32;
print io.printf("0x%08x");
13.6. The asin() expression
The
asin
() expression returns the arc sine of a float value:
float f = asin(1.0);
13.7. The ceil() expression
The
ceil
() expression rounds a float value to the next bigger value:
float f = ceil(-0.2);
13.8. The cos() expression
The
cos
() expression returns the cosine of a float value (radian measure):
float f = cos(PI);
13.9. The deg() expression
The
deg
() expression converts an angle (in radian measure) to degrees:
float f = deg(PI);
13.10. The exp() expression
The
exp
() expression returns
e
raised to the power of a float value:
float x = 2;
float y = 6;
float f = exp(y * ln(x)); // f => 2^6 => 64
13.11. The float() expression
The
float
() expression typecasts a value to a float value:
float f = float("3.1415") + 1;
13.12. The floor() expression
The
floor
() expression rounds a float value to the next smaller value:
float f = floor(1.7);
;
13.13. The frac() expression
The
frac
() expression returns the fractional part of a float value:
float f = frac(1.23456);
13.14. The int() expression
The
int
() expression typecasts a value to an integer value:
int i = int("41") + 1;
13.15. The ln() expression
The
ln
() expression returns the logarithm naturalis for a float value:
float f = ln(E);
13.16. The Object() expression
The
Object
() expression typecasts a value to a
Object
value:
Integer
io <= Object
(42);
Float
fo <= Object
(3.1415);
Double
d = 10;
Double
e <= Object
(d); // Create copy of "d"
If the value is already an
Object
and it is not
deletable, the
Object
() expression creates a copy of the
Object
:
Double
d = PI;
trace #(d);
d <= Object
(d);
trace #(deref d);
13.17. The rad() expression
The
rad
() expression converts an angle (degrees) to radian measure:
float f = sin(rad(90));
13.18. The rgb() expression
The
rgb
() expression packs three 8bit values into a 32bit integer value:
int r=$11, g=$22, b=$33;
int argb32 = rgb(r, g, b); // argb32 => 0xFF112233;
Integer
io = argb32;
print io.printf("0x%08x");
13.19. The rand() expression
The
rand
() expression returns a random int or float value that ranges between 0 and the given value:
int i = rand(10) - 5; // random int value between -5 and 5
float f = rand(10.0); // random float value between -5.0 and 5.0
print i;
print f;
13.20. The round() expression
The
round
() expression rounds a float value to the next smaller or bigger value:
float f = round(-0.5);
13.21. The sin() expression
The
sin
() expression returns the sine for an angle in radian measure:
float f = sin(PI);
13.22. The sqrt() expression
The
sqrt
() expression returns the square root of an int or float value:
int i = sqrt(64);
float f = sqrt(1.52399025);
13.23. The String() expression
The
String
() expression typecasts a value to a
String
value:
String
s = String
(42);
If the value is already a
String
and not
deletable, the
String
() expression will create a copy of the
String
:
String
s;
trace #(s);
s <= String
("hello, world.");
trace #(deref s);
13.24. The tan() expression
The
tan
() expression returns the tangens of a float value:
float f = tan(rad(20));
float g = sin(rad(20)) / cos(rad(20));
13.25. The tcchar() expression
The
tcchar
() expression converts an ASCII character to a
String
that only consists of that character:
String
s = tcchar(65); // s => "A"
13.26. The typeid() expression
The
typeid
() expression returns the type identifier for a value:
int t0 = typeid(void);
int t1 = typeid(42);
int t2 = typeid(PI);
int t3 = typeid(null);
int t4 = typeid("hello, world.");
13.27. The typename() expression
The
typename
() expression returns the atomic or C++ class type name for a value:
String
t0 = typename(void);
String
t1 = typename(42);
String
t2 = typename(PI);
String
t3 = typename(null);
String
t4 = typename("hello, world.");
The C++ class type name for a script class is
Class
. Use the
yacMetaClassName
() method to obtain the actual script class name.
Example:
class MyClass { }
trace (new MyClass()).yacMetaClassName();
auto-generated by "DOG", the TkScript document generator. Wed, 31/Dec/2008 15:53:35