Programming language Chora: Compiler directives

In the programming language Chora the compiler directives are special constructs intended to control how the Chora compiler should process the corresponding source code when translating a method, slot method, onget method, onset method or inline code member. In particular, the directives allow you to conditionally control the code compilation.

Syntax

Conditional directives:

$ifcondition

$elseifcondition

$else

$endif

Diagnostic directives:

$warningwarning‑message

$errorerror‑message

Equality operators:

$macro‑name==pattern

$macro‑name!=pattern

Test operators:

is_member(member‑name)

is_intrinsic(intrinsic‑name)

Logical AND, OR, NOT operators:

condition&&condition

condition||condition

!condition

Conditional directives $if, $elseif, $else and $endif

The conditional directives allow you to explicitly exclude chunks of code from the Chora compilation. For example, depending on the condition in the $if directive, the Chora compiler decides whether the following code should be taken in account or whether it should be ignored. The directive $endif marks the end of the affected code section. For example:

// Activate the engine. Application::Device.ActivatePowerSupply(); // If the macro '$UseHeater' is defined with the value // 'true', perform the following special initialization // steps. Otherwise ignore them. $if $UseHeater Application::Device.SetTemperature( 60 ); Application::Device.ActivateHeater(); $endif // Perform further common initialization steps ... Application::Device.SetCentrifugeSpeed( 1200 ); Application::Device.StartCentrifuge();

Generally, the condition in the $if directive is fulfilled if it results in the literal true. If it contains the literal false, the condition is not fulfilled. As demonstrated in the example above, eventual user defined macros involved within the condition are evaluated and replaced in advance by their actual content. Similarly, the built-in macros are treated (e.g. $prototyper):

$if true trace "This code is taken over"; $endif $if false trace "This code is ignored"; $endif $if $prototyper trace "This code is used during prototyping only"; $endif

The Chora compiler treats the condition very strictly. If the condition results in a value other than the literal true or false, the Chora compiler will report an error. For example, the built-in macro $line evaluates to a number literal (e.g. 14). Thus trying to use this macro as condition will raise a compilation error:

// Error: Expected 'true' or 'false' literal $if $line ... $endif

The directive $else allows you to specify an alternative code section to be taken in the case the condition is not fulfilled. Depending on the condition the directive selects then between the first or the second code section taking exact one of the both:

$if $prototyper trace "This code is used during prototyping only"; $else trace "This code is used during code generation only"; $endif

For more sophisticated application cases the $elseif directive is available. With it you can specify a further condition to be evaluated if the preceding condition is not fulfilled:

$if $composer trace "This code is used when working in Composer only"; $elseif $prototyper trace "This code is used during prototyping only"; $else trace "This code is used during code generation only"; $endif

Please note, Chora doesn't allow nested conditional directives. Thus the following code will raise a Chora compilation error. To formulate more complex conditions you can use e.g. the logical AND operator && and the logical NOT operator !:

// Error: nested directives are not supported $if $composer $if $prototyper trace "Both macros are 'true'"; $else trace "Only the 'composer' macro is 'true'"; $endif $else $if $prototyper trace "Only the 'prototyper' macro is 'true'"; $else trace "None of the both is 'true'"; $endif $endif // OK. Use complex conditions $if $composer && $prototyper trace "Both macros are 'true'"; $elseif $composer && !$prototyper trace "Only the 'composer' macro is 'true'"; $elseif !$composer && $prototyper trace "Only the 'prototyper' macro is 'true'"; $else trace "None of the both is 'true'"; $endif

Please note, a directive must be the only instruction on a line. Trying to use several directives within the same line will result again in a Chora compilation error:

// Error $if $prototyper trace "Prototyping"; $endif // OK $if $prototyper trace "Prototyping"; $endif

Equality operators == and !=

With the equality operator == you can compare in the condition whether the literal resulting from the operand on the left of the operator is identical to the from the operand on the right. If this is the case, the operator itself evaluates to the literal true. If the both operands are different, the operator == results in false. For example:

$if abc == abc trace "This code is taken over"; $endif $if abc == ABC trace "This code is ignored"; $endif

Similarly, with the equality operator != you can compare in the condition whether the literal resulting from the operand on the left of the operator is not identical to the from the operand on the right. If this is the case, the operator itself evaluates to the literal true. If the both operands are identical, the operator != results in false. For example:

$if abc != abc trace "This code is ignored"; $endif $if abc != ABC trace "This code is taken over"; $endif

The operands used in context of the == or != operator can be macros. For example, the built-in macro $profile evaluates to the name of the currently selected profile. Accordingly, the following condition is fulfilled if you compile the code for the profile with the name DeviceRev2:

$if $profile == DeviceRev2 trace "Compiling for profile 'DeviceRev2'"; $endif $if $profile != DeviceRev2 trace "Compiling for any profile except 'DeviceRev2'"; $endif

When using the == or != operator, one of the both operands may contain wildcard signs ? and *. Here, the sign ? is assumed as representing exactly one arbitrary character. In turn the sign * can represent any arbitrary number of characters including even an empty text. Thus with the wildcard signs you can formulate patterns to be used in the comparison operation. For example, the following condition is fulfilled if you are working with the eight generation of Embedded Wizard (means version 8.00, 8.10, 8.20 ...):

$if $version == 8.* trace "Using version 8.00, 8.10, 8.24, ..."; $endif $if $version == 8.?0 trace "Using version 8.00, 8.10, 8.20, ..."; $endif

This pattern notation with wildcard signs is very convenient to build conditions to be fulfilled when compiling code for a particular target system. The name of a target system is composed of identifiers separated by a . (dot) sign and it can be queried by evaluating the built-in macro $platform. For example, the following first condition is fulfilled when code for the Microsoft Windows system is compiled. In turn, the second condition is fulfilled when compiling code for a target of a particular color format:

$if $platform == Windows.*.* trace "Compiling for Microsoft Windows target."; trace "No matter what color format."; $endif $if $platform == *.RGB*888* trace "Compiling for a target with color format RGBA8888 or RGB888."; trace "No matter what target system."; $endif $if $platform != Windows.*.* trace "Compiling for any target system except Windows."; $endif

Test operator is_member()

The test operator is_member evaluates to the value true if the name specified in the operator does correspond to a member existing in the project. If the member is not existing in the project, the operator evaluates to the value false. The operator is thus useful to compile code conditionally depending on whether the project does contain a particular unit, class, method, property, etc. For example, the following condition is fullfilled only when the project does contain a member named Test (e.g. a unit Test):

$if is_member( Test ) trace "Running the application with additional 'test' environment."; $endif

The operator is_member expects the member to be specified by its full path. This means, to test for the existence of a class it is necessery to specify also the unit where the class is expected to exist. Similarly, to test whether the class Test::Logging does implement a method named Start, the fullpath Test::Logging.Start addressing the member in question has to be used:

$if is_member( Test::Logging.Start ) ( new Test::Logging ).Start(); $endif

Please note, the operator is_member does not evaluate the inheritance of class members. If there is a class U::A containing a method Foo and a class U::B descending from the class U::A, the test for the existence of the method Foo in context of the class U::B will result in value false. This is because, the class U::B does not contain any member Foo, it only inherits such member from the super class U::A:

$if is_member( U::B.Foo ) trace "This message will never appear ..."; $endif $if is_member( U::A.Foo ) trace "Yes, the member 'Foo' is implemented in class 'U::A'."; $endif

Test operator is_intrinsic()

The test operator is_intrinsic evaluates to the value true if the name specified in the operator does correspond to an intrinsic loaded actually in the prototyping environment. If the intrinsic is not available, the operator evaluates to the value false. The operator is thus useful to compile code conditionally depending on whether particular intrinsic module is available during the prototyping. For example, the following condition is fullfilled only when intrinsic with the name OpenDatabase is available, so it can be invoked:

$if is_intrinsic( OpenDatabase ) OpenDatabase(); $endif

Please note, during code generation for the target system, no intrinsic modules are loaded, what results in the test operator is_intrinsic resulting consequently in the value false. The operator is thus useful during prototyping only.

Logical AND operator

With the logical AND operator && you can combine two partial conditions. Precisely, if the operands on the left and on the right of the operator do both evaluate to the literal true, the operator && results itself in true. Otherwise the operator && results in the literal false. For example, the following condition is fulfilled only when compiling the code for prototyping and the macro UseHeater is defined with the value true:

$if $prototyper && $UseHeater trace "Compiling for prototyping and the macro 'UseHeater' is 'true'"; $endif

If necessary you can enclose the partial conditions between a pair of parentheses ( ... ):

$if $prototyper && ( $profile == DeviceRev2 ) trace "Compiling for prototyping and profile 'DeviceRev2'"; $endif

Logical OR operator

With the logical OR operator || you can combine two partial conditions. Precisely, if the operand on the left or on the right of the operator do evaluate to the literal true, the operator || results itself in true. If both operands evaluate to false the operator || results also in false. For example, the following condition is fulfilled when compiling the code for prototyping or with the macro UseHeater defined with the value true:

$if $prototyper || $UseHeater trace "Compiling for prototyping or the macro 'UseHeater' is 'true'"; $endif

If necessary you can enclose the partial conditions between a pair of parentheses ( ... ):

$if ( $profile == DeviceRev1 ) || ( $profile == DeviceRev2 ) trace "Compiling for profile 'DeviceRev1' or 'DeviceRev2'"; $endif

Logical NOT operator

The logical NOT operator ! results in the negation of the operand on its right. Precisely, if the operand on the right evaluates to the literal true, the operator ! results in false. If the operand evaluates to false, the operator results in true. For example, the following condition is fulfilled when compiling the code for code generation (not prototyping):

$if !$prototyper trace "Compiling code for code generation"; $endif

Diagnostic directive $warning

The directive $warning causes the Chora compiler to report a warning when the directive is evaluated. The directive can be combined with the conditional directives. The warning message is specified after the $warning directive separated by at least one blank:

$if $platform == Web.WebGL.* $warning No implementation available for the 'WebGL' target. $endif

At the compilation time, when the condition $platform == Web.WebGL.* is fulfilled, the following warning is reported:

Please note, a directive must be the only instruction on a line. Trying to use several directives within the same line will result in a Chora compilation error.

Diagnostic directive $error

The directive $error causes the Chora compiler to report an error when the directive is evaluated. The directive can be combined with the conditional directives. The error message is specified after the $error directive separated by at least one blank:

$if $platform == Web.WebGL.* $error No implementation available for the 'WebGL' target. $endif

At the compilation time, when the condition $platform == Web.WebGL.* is fulfilled, the following error is reported and the compilation is aborted:

Please note, a directive must be the only instruction on a line. Trying to use several directives within the same line will result in a Chora compilation error.