Raku Books / Creating a Compiler in Raku / Arrays and Hashes

Accessing array elements

The next goal is to start using individual array items, for example, as shown in the next fragment:

say data[0];
say data[1];

my n = data[0] * data[1];
say n;

Our current actions class already supports indexing strings, and that’s the exact place which we have to extend:

multi method expr($/ where $<variable-name> && $<integer>) {
    if %!var{$<variable-name>} ~~ Array {
        $/.make(%!var{$<variable-name>}[+$<integer>]);
    }
    else {
        $/.make(%!var{$<variable-name>}.substr(
            +$<integer>, 1));
    }
}

The method checks the type of the variable stored in the %!var hash, and if it is an array, returns the requested element. The other branch works with strings as it did before.

The grammar can be simplified once again by extracting the sequence representing an array (and string) index to a separate rule:

rule index {
    '[' <integer> ']'
}

Use the new rule in assignment and when you take the value:

rule assignment {
    <variable-name> <index>? '=' <value>
}

. . .

multi rule expr(4) {
    | <number>
    | <variable-name> <index>?
    | '(' <expression> ')'
}

If you ever will want to change the syntax of indexes, there’s a single place to do that, the index rule.

The actions must be adapted too. An index’s attribute is an integer value:

method index($/) {
    $/.make(+$<integer>);
}

And thus you should use $<index>.made to get it in other methods:

multi method assignment($/ where $<index>) {
    %!var{~$<variable-name>}[$<index>.made] = $<value>.made;
}

multi method assignment($/ where !$<index>) {
    %!var{~$<variable-name>} = $<value>.made;
}

. . .

multi method expr($/ where $<variable-name> && $<index>) {
    if %!var{$<variable-name>} ~~ Array {
        $/.make(%!var{$<variable-name>}[$<index>.made]);
    }
    else {
        $/.make(%!var{$<variable-name>}.substr(
            $<index>.made, 1));
    }
}

multi method expr($/ where $<variable-name> && !$<index>) {
    $/.make(%!var{$<variable-name>});
}

Once again, the !$<index> is used in the where clause to make the code more readable, while the multi-method can be correctly dispatched without it.

Course navigation

Off-topic: The joy of syntax   |   List assignments