| IncludeStatement | Pragma weak/strong | Pragma cast |
The pragma 'cast' directive controls how the interpreter
does automatically casting types from one type to another.
Cast pragmas controls how the CfgScript interpreter should automatically
cast from one type to another.
PragmaCastStatement
: '#' 'pragma' 'cast' CastOption ( 'true' | 'false' )
;
CastOption
: 'c2i2c'
| 'f2i2f'
| 'n2b'
| 'b2n'
| 'o2b'
| 'autobox'
| 'checkoverflow'
| 'a2s'
| 's2n'
;
The declaration of a
pragma cast
is scoped and valid in the scope it is defined:
// default for pragma cast s2n is by default false
{ // enter a new scope
#pragma cast s2n true
// from here auto casting from string to a number is on
} // leaving scope
// the previous setting for s2n (false) is active again
|
With the
c2i2c
cast pragma automatic cast from a character type
(
char, ucchar
) to an integer will be allowed or not.
The default setting for the
#pragma cast c2i2c
in CfgScript is 'false'.
Sample:
ucchar c = 'A';
try {
int i = c; // this will throw an exception, because casting a character from/to integer is not allowed
__script.testAssertComment(false, "expected throwing DmiTypeConversionException");
} catch (DmiTypeConversionException ex) {
__script.testAssertComment(true, "expected exception: " + ex.getMessage());
}
{
#pragma cast c2i2c true // allow casting
int i = c; // ok, no exception. i contains the unicode character number for the letter 'A'
}
|
With the
#pragma cast f2i2f false
automatic cast
an integer type (byte, short, int, long) from / to a float type (float, double)
can be disallowed.
The default setting for the
#pragma cast f2i2f
in CfgScript is 'true'.
The
#pragma cast n2b false
is by default true.
This enables for example
int i = 10;
while (i) // while expect expression which evaluates to bool
--i;
|
Otherwise same has to be written:
int i = 10;
while (i != 0) // while expect expression which evaluates to bool
--i;
|
Any number expression, which evalutes to zero is false, all other are
true.
The
#pragma cast n2b false
is by default false.
#pragma cast n2b true
int i = true; // 1
float f = false; // 0
|
The
#pragma cast o2b
is by default true.
If a boolean expression is needed, but the expression
will be evaluated to a object reference, the object
reference will be translated to:
Object o = giveSomeObjectOrNil();
if (o)
{
}
// is equal to
#pragma cast o2b false
if (o != Nil)
{
}
|
The
#pragma cast autobox
is by default true.
Autoboxing is the ability of the interpreter to convert
a basic type (for example
int
) to the corresponding object
type (
acdk.lang.Integer
) and vice versa.
Example:
// default is autobox true
int i = 2;
Number o = i; // thats ok, translates the int to acdk.lang.Integer
short s = o; // unboxing is also ok
// now the same with autobox false
#pragma cast autobox false
int i = 2;
Number o = new Integer(i);
short s = o.shortValue();
|
Independed to the pragma cast autobox is the ability to invoke
methods on basic types:
#pragma cast autobox false
int i = 2;
String s = i.toString(); // still possible
i = i + 1;
// will basically call
i = (new acdk.lang.dmi.DmiObject(i)).operator+(1).castTo(int.GetClass());
|
The
#pragma cast checkoverflow
is by default false.
With the pragma cast checkoverflow in assignment from one number type
to a another the interpreter will check if the value of the right value
will fit into the type of the left:
#pragma cast checkoverflow true
try {
short sval = 0xf234567; // this value doesn't fit into a short
__script.testAssertComment(false, "never reach here, exception should be thrown");
} catch (ArithmeticOverflowException ex) {
__script.testAssertComment(true, "expected exception: " + ex.getMessage());
}
|
This also handles situations in arithmic operations:
{
#pragma cast checkoverflow true
short sval = Short.MAX_VALUE - 1;
try {
for (int i = 0; i < 10; ++i)
sval = sval + 1;
} catch (ArithmeticOverflowException ex) {
out.println("last sval was: " + sval);
}
}
|
The
#pragma cast a2s
is by default false.
The pragma cast a2s converts automatically any types to a string.
If the type is a basic type it returned the stringified string using
the corresponding Object wrapper method. If the type is an object
it will call the to
toString()
of this method.
{
#pragma cast a2s true
String s;
s = true;
out.println("stringified bool true is: " + s);
}
|
The
#pragma cast s2n
is by default false.
The pragma cast s2n converts automatically a string type to a number type.
This 'duck type cast' (it looks like a duck, it walks like a duck, etc., so it is a duck)
is also known for example by the Perl language.
{
try {
int i = "32"; // this does not work by default
__script.testAssertComment(false, "exception should be thrown");
} catch (DmiTypeConversionException ex) {
}
}
{
#pragma cast s2n true
// enable parsing numbers
int i = "32";
}
{
#pragma cast s2n true
try {
int i = "ba32"; // oops not a number
}
catch (NumberFormatException ex) {
}
}
|
The pragma casts can have also combination effects.
{
#pragma cast checkoverflow true
#pragma cast s2n true
try {
// s2n will parse to a number
// the result number has the int type
// casting this to short (which is to small)
// will throw ArithmeticOverflowException
short sval = "0xf234567";
__script.testAssertComment(false, "exception should be thrown");
} catch (ArithmeticOverflowException ex) {
__script.testAssertComment(true, "expected exception: " + ex.getMessage());
}
}
|
The class
acdk::cfgscript::ScriptGlobals contains some pseudo
operators. To make use of these operators just
using
the class:
// uses static methods ScriptGlobals
using acdk.cfgscript.ScriptGlobals;
{
ucchar c = 'A';
// cast from character type to number type:
int i = castTo(c, int.GetClass());
}
|