"Sputnik" help  
Sputnik Help
Language Reference - Preprocessor - Block Macros - Directies with a . (dot)

Directies with a . (dot)

Block macros support a unique use of directives with the . (dot) syntax instead of the traditional #. This syntax is designed to enhance readability and distinguish preprocessor directives from runtime code within the block macros.

#macro macro_name(parameters)
    .directive_name directive_parameters
    // Rest of the macro code

.directive_name: Preprocessor directives within block macros now use the . (dot) syntax for clarity and differentiation from runtime code.

The introduction of the . (dot) syntax for directives enhances the readability of block macros, making it clear which parts of the code are processed at compile time.

#macro Testy($cat)
    .if $cat == 10
        say "Cat is 10";
    .elif $cat == 15
        say "Cat is 15";
        say "Cat is unknown";

Testy(10); // Prints "Cat is 10"
Testy(15); // Prints "Cat is 15"
Testy(20); // Prints "Cat is unknown"

In this example, the macro Testy uses the .if, .elif, and .else directives within the block to conditionally print messages based on the input.

Any line starting with a . (dot) triggers the preprocessor. For example, in block macros, using a dot after a statement may lead to an unterminated macro directive error. To address this, proper syntax involves placing the dot before the statement continuation, ensuring correct preprocessor interpretation.

#macro Cat()
    my $a = 10
            . 20;
    say $a;


// Main.spk:1: 20
//             ^ unterminated macro directive
// --- Exit ---

Here we got a crash due to the . leading into the 20 making the preprocessor think thats a preprocessor statement which it isnt.

#macro Cat()
    my $a = 10 .
    say $a;


// 1020

By having the dot at the end (or anywhere but the beginning) of a line we can avoid this issue.

Here is a fairly complex example:

#define VAR_DATA ("cat", "dog", "fox", "kitten")

#macro Test(data)
    .eq PAX, data
    .countt PBX, PAX
    .while PDX < PBX
        .gettm PCX, PAX, PDX
        say "[" . PDX . "] Value " . PCX;
        .inc PDX


// [0] Value cat
// [1] Value dog
// [2] Value fox
// [3] Value kitten

It is using registers instead of local variables and loops through a macro tuple printing its values.

Here is an example where the data is printed then modified then printed again:

#eq PAX, ("a", "b", "c", "d")
#macro TestGet(n)
    .gettm PCX, PAX, n
#macro TestSet(n, k)
    .eq PCX, k
    .settm PAX, PCX, n
say TestGet(0);
say TestGet(1);
say TestGet(2);
say TestGet(3);
TestSet(0, "at");
TestSet(1, "bt");
TestSet(2, "ct");
TestSet(3, "dt");
say TestGet(0);
say TestGet(1);
say TestGet(2);
say TestGet(3);
// a
// b
// c
// d
// at
// bt
// ct
// dt

As we can see . (dot) directives allow for complex macro creation.

The purpose of using . (dot) is to clearly indicate preprocessor directives and differentiate them from runtime code. This syntax choice improves code understanding and maintainability.

Block macros in Sputnik use the . (dot) syntax for preprocessor directives, providing clarity and separation between compile-time directives and runtime code within the block. This choice enhances code readability and maintains a clean distinction between different parts of the code.

Cheryl (uberfox@hotmail.com)