2005/5/10

     
 

CfgScript Pragma cast directions

artefaktur

| IncludeStatement | Pragma weak/strong | Pragma cast |

The pragma 'cast' directive controls how the interpreter does automatically casting types from one type to another.


Content of this chapter:

   Cast Pragmas
     Syntax
     Context of pragma cast
     Cast character types from and to integer types
     Cast integer types from and to float types
     Cast number types to boolean type
     Cast boolean type to number types
     Cast object types to boolean type
     Cast basic types to and from object types
     Check range overflow in number assignments
     Cast any type to string
     Cast string to number types
     Combination of cast
   Forced casts



 Cast Pragmas

Cast pragmas controls how the CfgScript interpreter should automatically cast from one type to another.

 Syntax

PragmaCastStatement
: '#' 'pragma' 'cast' CastOption ( 'true' | 'false' )
;

CastOption
:  'c2i2c'
|  'f2i2f'
|  'n2b'
|  'b2n'
|  'o2b'
|  'autobox'
|  'checkoverflow'
|  'a2s'
|  's2n'
;

 Context of pragma cast

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

 Cast character types from and to integer types

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'
}

 Cast integer types from and to float types


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'.



 Cast number types to boolean type


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.

 Cast boolean type to number types

The #pragma cast n2b false is by default false.

#pragma cast n2b true
int i = true; // 1
float f = false; // 0

 Cast object types to boolean type

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)
{
}

 Cast basic types to and from object types

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());

 Check range overflow in number assignments

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);
	}
}

 Cast any type to string

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);
}

 Cast string to number types

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) {
	}
}

 Combination of cast

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());
	}
}

 Forced casts


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());
}