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