| Name | Volker Oth |
| Born | 1971 |
| Country | Germany |
| Occupation | Embedded
C software development
(automobile) |
| Contact | You might contact me by mail if you have questions/bug reports/suggestions regarding Calcutta: VolkerOth (at) GMX.de |
| Repository URL | http://javaforge.com/svn/calcutta |
| login | anonymous |
| password | anon |
| Expression |
Comment |
| prime(2**31-1) out = true |
This
number is indeed prime and we can
find out in the tenth of a second |
| a=1;b=a++
out = 1 b out = 1 a out = 2 |
Note
that the postincrement ++ works as
it should: a is increased after b is assigned the value of a (still 1)
and after the whole expression is evaluated (also out=1). |
| fraction(1.34p456) out = 22387/16650 |
Rational
number with endless periods
can be expressed as rational fraction. Indeed there is no loss of
precision as long as no irrational function as sin,sqrt etc. is used. |
| hex(65536) out = 0x010000 |
Get
hexadecimal output |
| bin(0x7e) out = 0b01111110 |
get
binary output |
| (1+2*3-4/(2*3)) out = 6.3333333333333333 fraction(out) out = 19/3 out*6 out = 38 |
Note
that the variable out is always
overwritten with the last result. Also note that even if a decimal is
printed out, the internal representation is always a rational fraction.
That's why multiplication with 6 ends with an integer number though the
operand had an endless period |
| fac(2000) out = 0.3316275092450633e+5736 |
factorial
of 2000. This is way beyond
the scope of normal calculators or even double precision. Try to print
out the whole number with full(out) |
| hex(0x80) out = 0x0080 hex(-128) out = 0x80 ~0x80; out = -129 hex(out) out = 0xff7f |
Note
that while 0x80 seems to fit into
a byte, it is automatically evaluated as 0x0080 to express that it's
unsigned, while hex(-128) is evaluated as 0x80: here the most
significant bit is set, so it's a negative number. As 0x80 is internally represented as 0x0080, the binary complement evaluated to 0xff7f, which can only be evaluated as negative number, as the most significant bit is set. |
| bin(0b111
^ 0b101) out = 0b00000010 |
This
goes to show that "^" is not a "to
the power of" operator, but the binary XOR. Also note that binary
numbers are always extended to the next byte,word,dword etc. boundary |
| true
^ true out = false |
And
yer, as in Java, the XOR is also
defined on boolean values |
| full(2**150) out = 1427247692705959881058285969449495136382746624 |
Already
quite a large number. But not
nearly as large as it can get ;) |
| 5<<3
== 5*8 out = true |
Was
to be expected |
| false
&& ((z=1)==1) out = false z z ^ Empty or invalid expression |
Note
that "&&" and "||" are
boolean shortcut operators. If the left side is sufficient to evaluate
the expression (false && exp is always false), the
right side
is not evaluated. In this case, 'z' is not set to 1. Therefore it's
still
undefined! |
| false &
((w=1)==1) out = false w out = 1 |
Same
example with
non-shortcut operator &. This time the right side is evaluated
and
'w' is defined. |
| sqrt(2**2000) out = 10.7150860718626732e+300 |
Note
that functions like sqrt are not
simply passed to the double sqrt. Most simple calculators will fail
here. |
| 2 out = 2 2; out = <UNDEF VALUE> |
A separator consumes an exisiting value |
| a
= {1,
"lurch", {2,true}} out = {1,"lurch",{2,true}} a[1] out = "lurch" a[2] out = {2,true} a[2][1] out = true a[2][0] = "new" out = {1,"lurch",{"new",true}} |
Define
a list by putting value
separated by commas into curved braces Access list elements by using index in brackets (reading or writing is allowed) Lists are allowed as list elements -> multidimensional lists |
| Integer
numbers: |
1, 2e3,1971e+3 |
| Decimal
numbers (p marks beginning of
periodic part) |
1.345,
2e-3, 1.2p3 |
| Hex
numbers: |
0xdeadbeef, 0xe |
| Binary
Numbers: |
0b010101 |
| Octal
Numbers: |
070,
066 |
| a=1;b=2 | No need to define them, just assign a value |
| a=1; a="oink"; a=true | 1st a is a number, then a string, then a boolean |
| a=c | Now c is not defined yet -> this will result in an error |
| my_1st_string = "Hello World" | Now we have a string |
| my_1st_boolean = true | And now a boolean |
| Operator |
Use |
Precedence |
Valid
on |
Description |
| + |
+op1 |
1 |
Number |
Marks numeric value as positive |
| ++ |
++op1 op1++ |
1 |
Number |
Preincrement,
postincrement |
| - |
-op1 |
1 |
Number | Negative
value of operand |
| -- |
--op1 op1-- |
1 |
Number |
Predecrement, postdecrement, |
| ~ |
~op1 |
1 |
Integer
Number |
Binary
complement |
| ! |
!op1 |
1 |
Integer
Number, Boolean |
Logical
complement (true - false, 0 -
>0) |
| ** |
op1**op2 |
1 |
Number |
op1
to the power of op2 |
| * |
op1*op2 |
2 |
Number |
Multiplication |
| / |
op1/op2 |
2 |
Number |
Division |
| % |
op1%op2 |
2 |
Integer
Number |
Integer
Division Remainder |
| + |
op1+op2 |
3 |
Number,
String, List |
Addition,
String-Concatenation,
List-Concatenation |
| - |
op1-op2 |
3 |
Number |
Subtraction |
| << |
op1<<op2 |
4 |
Integer
Number |
Shift
left |
| >> |
op1>>op2 |
4 |
Integer
Number |
Shift
right |
| < |
op1<op2 |
5 |
Number,String |
Smaller
than (result: boolean) |
| <= |
op1<=op2 |
5 |
Number,String | Smaller
than or equal (result: boolean) |
| > |
op1>op2 |
5 |
Number,String | Larger than (result: boolean) |
| >= |
op1>=op2 |
5 |
Number,String | Larger than or equal (result: boolean) |
| == |
op1==op2 |
6 |
Number,
Boolean, String, List |
Equals
(result: boolean) |
| != |
op1!=op2 |
6 |
Number,
Boolean, String, List |
Not
equal (result: boolean) |
| & |
op1&op2 |
7 |
Integer
Number, Boolean |
Integer
Number: binary AND, boolean:
logical AND (no shortcut!) |
| ^ |
op1^op2 |
8 |
Integer
Number, Boolean |
Integer
Number: binary XOR, boolean:
logical XOR (no shortcut!) |
| | |
op1|op2 |
9 |
Integer
Number, Boolean |
Integer Number: binary OR, boolean: logical OR (no shortcut!) |
| && |
op1&&op2 |
10 |
Integer
Number, Boolean |
logical
AND (shortcut!) |
| || |
op1||op2 |
11 |
Integer
Number, Boolean |
Logical OR (shortcut!) |
| = |
var=exp |
13 |
Left
Side: variable, Right side: any expression |
Defines
variable var if
it doesn't
exist yet
and
assigns it to the value of the expression on the right side |
| *= | var*=op | 14 | Left:
variable Right: numeric expression |
same as var = var * (op) (multiplication) |
| /= | var/=op | 14 | Left:
variable Right: numeric expression |
same
as var = var / op
(division) |
| += | var+=op | 14 | Left:
variable Right: Number, String, List |
same
as var = var + op
(addition/ Concatenation) |
| -= | var-=op | 14 | Left:
variable Right: Number |
same
as var = var - op
(subtraction) |
| <<= | var<<=op | 14 | Left:
variable Right: Number |
same
as var = var <<
op
(shift left) |
| >>= | var>>=op | 14 | Left:
variable Right: Number |
same
as var = var >>
op
(shift right) |
| |= | var|=op | 14 | Left:
variable Right:Number.Boolean |
same as var = var | op (or) |
| &= | var&=op | 14 | Left:
variable Right:Number, Boolean |
same as var = var & op (and) |
| ^= | var^=op | 14 | Left:
variable Right:Number, Boolean |
same as var = var ^ op (xor) |
| Cast
Operator |
Valid
on |
Description |
| (u8),(u08),(byte) |
Number |
Casts
expression to unsigned 8bit value
(0..255) |
| (s8),(s08) |
Number |
Casts
expression to signed 8bit value
(-128..128) |
| (u16),(word),(char) |
Number |
Casts
expression to unsigned 16bit
value (0..65535) |
| (s16),(short) |
Number |
Casts
expression to signed 16bit value
(-32768..32767) |
| (u32),(dword) |
Number |
Casts
expression to unsigned 32bit
value (0..4294967295) |
| (s32),(int) |
Number |
Casts
expression to signed 32bit value
(-2147483647..2147483646) |
| (u64),(qword) |
Number |
Casts
expression to unsigned 64bit
value (0..18446744073709551616) |
| (s64),(long) |
Number |
Casts expression to signed 64bit value (-9223372036854775807..9223372036854775806) |
| (double) |
Number |
Cast
to double |
| (integer) |
Number |
Cast
to integer number (same as
trunc(operand)) |
| (string) | any value | Converts a value to a string. The resulting string will look exactly as the default output on the console. |
| Function |
Description |
| abs(x) |
Absolute
value of number x |
| trunc(x) |
Integer part of number x (cutting of decimal part) |
| floor(x) |
Integer i closest to number x with i <= x |
| ceil(x) |
Integer
i closest to number x with i
>= x (same as -floor(-x) ) |
| round(x) |
Integer
closest to number x + 0.5 (same
as floor(x+0.5) ) |
| pow(x,N) |
Calculates
number x to the power of
number N (same as x**N) |
| root(x,N) |
Calculates
the Nth root of number x
(same as x**(1/N) ) |
| sqrt(x) |
Calculates
the square root of number x
(same as root(x,2) ) |
| fac(x) |
Calculates
factorial of number x (
normally written as x!, but "!" is logical complement) |
| prim(x) |
Returns
boolean if integer number x is
(probably) a prime number |
| exp(x) |
Returns
Euler's number e
raised
to the power of number x |
| log(x) |
Returns
the natural logarithm (base e)
of number x |
| log10(x) |
Returns
the logarithm (base 10) of
number x |
| ld(x) |
Returns
the logarithm digitalis (base 2)
of number x |
| bits(x) |
Returns
the number of bits needed to
represent the integer number x |
| sin(x) |
Returns the trigonometric sine of a radian angle x (number) |
| sinh(x) |
Returns the trigonometric hyperbolic sine of a radian angle x (number) |
| asin(x) |
Returns the trigonometric arc sine of a radian angle x (number) |
| cos(x) |
Returns the trigonometric cosine of a radian angle x (number) |
| cosh(x) |
Returns the trigonometric hyperbolic cosine of a radian angle x (number) |
| acos(x) |
Returns the trigonometric arc cosine of a radian angle x (number) |
| tan(x) |
Returns
the trigonometric tangent of a
radian angle (number) |
| tanh(x) |
Returns the trigonometric hyperbolic tangent of a radian angle (number) |
| atan(x) |
Returns the trigonometric arc tangent of a radian angle (number) |
| Function |
Description |
| print(x) println(x) |
Print
value x on the console (x can be
a number, boolean or string) println works as print, but adds a linefeed |
| hex(x) |
Show integer number x in hexadecimal representation* |
| bin(x) |
Show integer number x in binary representation* |
| oct(x) | Show integer number x in octal representation* |
| full(x) |
Show
number x as accurate as possible BEWARE! For rational numbers with more digits after the decimal point than the internal scale provides, the result will be less precise. E.g. full(1/3)==(1/3) results in false, since 1/3 is precise, but full(1/3) is not!!! |
| fraction(x) |
Show
number x as a rational fraction |
| defined(x) |
Returns
true, if the variable x is
defined, else false. Will
not work on values! |
| load(x) |
Load
file with name x (must be a
string!). Files can contain
all the operators, literals and functions described here. E.g. load("test.clc") |
| die(x) |
Immediately
exits the current
expression evaluation and
creates a user defined parse exception x, where x must be a string.
E.g. a==1 || die("a is not 1"); |
| rnd() | Returns random number N where 0 <= N <= 1 |
| time() | Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT |
| clear() | Undefines all user variables and user functions |
| listv() | Returns a sorted list with all defined variables (as strings) |
| listf() | Returns a sorted list with all defined user functions (as strings) |
| eval(x) | Evaluates
the expression inside string
<x>. E.g.
eval("1+3*2") will evaluate as 7. Every operator, function and literal is allowed within the expression, only quotes (") are forbidden. |
| Function |
Description |
| lfill(value,size) |
Returns
a list
filled with value
until size
is reached 'a= fill(true,3)' results in {true,true,true} |
| sfill(string,size) | Returns
a string filles with
string
until size
is reached 'a= sfill("ab",5)' results in "ababa" |
| sub(string,pos,len) | Returns
a substring of string
starting at position pos
and
containing len
characters 'sub("12345",2,3)' results in "345" |
| sub(list,pos,len) | Returns
a sublist of list
starting at position pos
and
containing len
list elements 'sub({1,2,3,4,5},2,3)' results in {3,4,5} |
| insert(string,insert,pos) | Returns a string with the string insert inserted into string string at position pos 'insert("12345","AB",2)' results in "12AB345" |
| insert(list,insert,pos) | Returns a list with the list insert inserted into list list at position pos 'insert({1,2,3,4,5},{"A","B"},3)' results in {1,2,3,"A","B",4,5} |
| replace(string,replace,pos) | Returns a string with the string replace replaced in string string beginning with position pos 'replace("12345","AB",2)' results in "12AB5" |
| replace(list,replace,pos) | Returns a list with the list replace replaced in list string beginning with position pos 'replace({1,2,3,4,5},{"A","B"},2)' results in {1,2,"A","B",5} |
| index(string1,string2) | Returns (0 based) index of string2 inside string1, if found, else -1 (searching from beginning) |
| index(list,value) | Returns (0 based) index of value inside string1, if found, else -1 (searching from beginning) |
| lastindex(string1,string2) | Returns (0 based) index of string2 inside string1, if found, else -1 (searching from end) |
| lastindex(list,value) | Returns (0 based) index of value inside string1, if found, else -1 (searching from end) |
| size(variable) | returns
the size of a variable. For a list, this is the number of elements: 'a={1,2,3,{1,2,3}}; size(a)' results in 4 For a String, this is the number of characters 'a="0123456789"; size(a)' results in 10 For any other value (number, boolean), this is 1 |
| {} | empty list |
| {1,2,3} out = {1,2,3} |
simple list |
| {true,
2,
"sheep" } out = {true, 2, "sheep" } |
mixed list |
| {
1,
{1,2,3}, 3} out = { 1, {1,2,3}, 3} |
list inside list |
| a=1;
b
=2; { a,
b, 3} out = {1,2,3} |
Note that the variables are evaluated when creating the list |
| {
sin(0),
cos(0), tan(0) } out = {0,1,0} |
Same with functions |
| a
=
{1,2,3};
a[0] out = 1 |
Just like in C or Java |
| a
=
{1,2,3};
a[0] = a[2] = 0; a out = {0,2,0} |
Indexed variables behave just like ordinary variables. You can write to them and also right association is working. |
| b={
{1,2}, {3,4}, {4,5} };
b[0][0] = b[2][0] = 0;b out = {{0,2},{3,4},{0,5}} |
Same with two dimensions |
| a
= {
1, 2, 3
}; a[3] Index 3 out of bounds. |
Neither reading nor writing to an undefined index is allowed. |
| {1,"a",true,
{1,2}} == {1,"a",true, {1,2}} out = true |
equality operator works on lists as well |
| a
= {};
a = a +
{1}; a = a + {2}; a out = {1,2} |
plus operator allows list concatenation |
| function
square(a) { a*a } square(4); out = 16 square(true) Number expected on the left side of operator |
The
return value is just the value of
the expression "a*a" Works with numbers Doesn't work with boolean |
| function
square(a) { a*a; } square(4); out = <UNDEF VALUE> |
Beware! The semicolon after the last statement of the function consumes the value |
| function
test(a,b) { c=a*b; println(c); d=a+b; println(d); } |
Two
parameters here. Use as many as you
want. |
| lurch
= 2; function lurchtest() { println(lurch); lurch = 3; println(lurch) } lurchtest() 2 3 out = 3 lurch out = 2 |
Note
that first the global variable is
read (which contains
2). Then a local variable is written to. With the next read access, the local variable is read, which now hides the global variable!!! |
| function
ctest(a,b) { c } |
This
is allowed, since the syntax is
correct. However when you call this function, it will fail if no global variable c exists. It will work however if the variable exists! |
| a
= 1; if ( a == 1) { b = 0 } else { b = 1 } out = 0 |
b is assigned 0, note that the result of the statement equals the if branch |
|
a = 1; |
This does the same as the example above by directing assigning the statement to b. Note that this is perfectly allowed in contrary to C etc. where you would need to use the "?:" operator |
|
a = 1; |
Note that the semicolon consumes the value. Thus the return value is undefined!!! |
| a
= 1; sin ( if (a==1) {PI} else {1}) out = 0 |
Note how the result of the statement can be passed as parameter |
| if
(false) {1} out = <UNDEF VALUE> |
There is no else branch and no statement after this that would define a result. Thus the value of this statement is undefined! |
Furthermore the ternary operator "?" is defined as in C and Java.
(<condition>) ? <true_statement> : <false_statement>
Remarks:
|
a = 1; |
b is assigned 0, note that the result of the statement equals the true branch |
|
a
= 1; |
This does the same as the example above by directing assigning the statement to b. Note that this is perfectly allowed in contrary to C etc. where you would need to use the "?:" operator |
|
a = 1; |
Note that the semicolon consumes the value. Thus the return value is undefined!!! |
|
a = 1; |
Note that the semicolon after the false statement consumes the return value of the whole expression. Still a is defined correctly. Using parenthesises around "1" would create an evaluator stack underflow as well. |
| a
= 1; sin ( (a==1) ? PI : 1) out = 0 |
Note how the result of the statement can be passed as parameter |
| for
(i=0;
i<10;i++) { print(i) } 0123456789 |
Nothing spectacular. Just note that since "i++" evaluates 9, while "i" is already 10! |
| for
(i=0;
i<10;i=i+1) { print(i) } 0123456789 out = 10 |
"i=i+1" works exactly the same as "++i" would |
| for
(i=sin(0);
i<3**2+1;i=i+1) {
print(i) } 0123456789 |
You can use expressions and functions inside the statements of course |
| for
(;;) {
print("#") } Invalid condition |
The loop condition shall not be omitted! |
| a={1,2,3};
foreach(i;a){ print(i) } 123 |
Simple example |
| foreach(i;{1,2,3})
{ print(i) } 123 |
Same with a list literal |
| foreach(i;{1,2,3})
{ print(i); foreach(j;{"a","b","c"}){print(j)} } 1abc2abc3abc |
Nested foreach loops |
| a={1,2,3};
foreach(i;a){ a={"a","b"}; print(i) } 123 a out = {"a","b"} |
Note that changing the variable 'a' works, but doesn't influence the loop behaviour. |
| i=0;do
{ print(i) }while(++i<10) 0123456789 |
No
init statement, so you have to put
it in a separate statement. |
| i=0;while (i<10)
{ print(i++) } 0123456789 |
No init statement, so you have to put it in a separate statement. |
| function
factorial(n) { if (n<=1) { 1 } else { n*factorial_recursive(n-1) } } |
load("factorial.clc") factorial(200) out = 0.7886578673647905e+375 fac(200) out = 0.7886578673647905e+375 |
| function
galton(rows, trials)
{
// init slot = lfill(0,rows+1); // run trials for (trial = 0; trial < trials; trial++) { position = 0; for (pos = 0; pos < rows; pos++) { if (rnd() >= 0.5) { position++; } } slot[position]++; } // output for (pos = 0; pos <= rows; pos++) { println("Slot " + (string)(pos+1) + " contains " + (string)slot[pos] + " balls."); } } |
load("galton.clc") galton(4,1000) Slot 1 contains 49 balls. Slot 2 contains 240 balls. Slot 3 contains 374 balls. Slot 4 contains 273 balls. Slot 5 contains 64 balls. |
| //
Calcutta
version of 99 Bottles of
beer b1 = " bottle of beer"; bn = " bottles of beer"; otw = " on the wall"; for (i=100; i>0; i--) { b = if (i>1) {bn} else {b1}; println ((string)i+b+otw+", "+(string)i+b+"."); println("Take one down and pass it around,"); b = if (i-1>1) {bn} else {b1}; println((string)(i-1)+b+otw+"."); println(""); } |
load("99bottles.clc") 100 bottles of beer on the wall, 100 bottles of beer. Take one down and pass it around, 99 bottles of beer on the wall. ... ... ... 1 bottle of beer on the wall, 1 bottle of beer. Take one down and pass it around, 0 bottle of beer on the wall. |