Expressions are used to combine one, two or three values (subexpressions) to a result value by using operators. The most simple example for an expression is a constant value.
Example:
int i=42; // constant expression ("42") int j=i; // variable expression ("i")
From a technical point of view, the result of every expression is exactly one value. Since this value may represent a reference to an array or other complex datastructure, an expression may also evaluate to an array of values effectively.
Example:// the result of the expression is a pointer to an IntArray which // again is made up by an arbitrary number of values function ReturnN { return [1,2,3,4,5,6,7,8]; } trace "element[7]="+ReturnN()[7];
A variable expression may also contain a pre/post increment/decrement operator (++v, v++, --v, v--) which is used to alter the value of a variable without explicite assignments. The variable is incremented resp. decremented, depending on the position of the operator, before or after it is saved for later evaluation. This works with int as well as float variables (+1.0, -1.0).
Example:
int i=42, j=i++; // j is 42, i becomes 43.
Example:
int i=42, j=--i; // j is 41, i becomes 41.
This may also be applied to members of modules and classes:
Example:
int j = MMyModule.myvariable++;
Example:
int j = --myobj.mymember;
These operators may also be used in statements:
Example:
int i=42; i++; i--;
A boolean expression evaluates to either true (!=0) or false (==0). Boolean expressions are typically used to test break conditions of loops or to signalize conditions using flags (or shifted bitmasks). The integer literals true and false can be used to substitute the values 1 and 0.
Example:
if(true) trace "it's true";
The range expression tests whether an int or float value ranges between the given boundaries.
Example:
int i=5; i= (1 < i < 10); float f=5.23; i= (1.1 < f < 10.10);
This expression tests a condition within an expression and selects between two alternative result expressions depending on the test result, which may be true or false.
Example:
// the value of the ternary expression is determined by // the seizure of the variable i 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(j>5) k=i+j; else k=j-i;
The new expression is used to explicitely create new objects.
The argument passed to this expression must be the name of a user-defined script- or a C++ API class. This expression is rarely needed in TKS but it is surely important for object factories.
Example:
function NewString { String s<=new String; // allocate new String return deref s; // release binding to variable s } String mynewstring<=NewString();
Example:
class AbstractFactory { newObject() {/*trace "Abstract::newObject, never called";*/} } class ConcreteStringFactory : AbstractFactory { newObject() { return new String; } } class ConcreteFloatFactory : AbstractFactory { newObject() { return new Float; } }
This expression is used to unlink an "read-write" object from a variable. The object can then be bound to another container otherwise 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 "read-only" reference to the object, it becomes
// invalid when the HashTable object is deleted
This expression is used to create hashtables on-the-fly. The expression returns a constant HashTable object whose elements are updated each time the expression is evaluated.
Please also see here.
Example:
HashTable ht<=#[a=1, b=2, c=3];
print ht["c"];
This expression is used to catch the return value and type of an expression and wrap it in a Value object. Please also see the Value API documentation.
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;
The List expression is used to create arbitrary-length double linked list on-the-fly. Please also see the ListNode API documentation.
Example:
// // ---- file: list.tks // ---- author: bastian spiegel // ---- created: 14-Jan-2004 // ListNode l<={1,2.2,"hallo"}; ListNode c; c<=l.tail; c.appendValue(#("welt")); c<=l.tail; c.appendValue(#(tcobject(42))); c<=l.tail; c.appendValue(#(new String())); Value v; foreach v in {1,2.2,"hi",tcobject(42),#(5),6} trace "v.type="+v.type+" v.string="+v.stringValue; trace l; l.print(); 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; l3.print(); } loop(1) evalListExpr();
Also see Runtime class type checks.