In Perl 6, you can use superscript indices to calculate powers of numbers, for example:

> 2⁵ 32 > 7³ 343

It also works with more than one digit in the superscript:

> 10¹² 1000000000000

You can guess that the above cases are equivalent to the following:

> 2**5 32 > 7**3 343 > 10**12 1000000000000

But the question is: How on Earth does it work? Let us find it out.

For the `Numeric` role, the following operation is defined:

proto sub postfix:<ⁿ>(Mu $, Mu $) is pure {*} multi sub postfix:<ⁿ>(\a, \b) { a ** b }

Aha, that is what we need, and the superscript notation is converted to the simple `**` operator here.

You can visualise what exactly is passed to the operation by printing the operands:

multi sub postfix:<ⁿ>(\a, \b) {nqp::say('# a = ' ~ a);nqp::say('# b = ' ~ b);a ** b }

In this case, you’ll see the following output for the test examples above:

> 2⁵ # a = 2 # b = 5 > 10¹² # a = 10 # b = 12

Now, it is time to understand how the postfix that extracts superscripts works. Its name, `ⁿ`, written in superscript, should not mislead you. This is not a magic trick of the parser, this is just a name of the symbol, and it can be found in the Grammar:

token postfix:sym<ⁿ> { <sign=[⁻⁺¯]>? <dig=[⁰¹²³⁴⁵⁶⁷⁸⁹]>+ <O(|%autoincrement)> }

You see, this symbol is a sequence of superscripted digits with an optional sign before them. (Did you think of a sign before we reached this moment in the Grammar?)

Let us try negative powers, by the way:

> say 4⁻³ # a = 4 # b = -3 0.015625

Also notice that the whole construct is treated as a postfix operator. It can also be applied to variables, for example:

> my $x = 9 9 > say $x² # a = 9 # b = 2 81

So, a digit in superscript is not a part of the variable’s name.

OK, the final part of the trilogy, the code in Actions, which parses the index:

method postfix:sym<ⁿ>($/) { my $Int := $*W.find_symbol(['Int']); my $power := nqp::box_i(0, $Int);for $<dig> {$power := nqp::add_I(nqp::mul_I($power, nqp::box_i(10, $Int), $Int),nqp::box_i(nqp::index("⁰¹²³⁴⁵⁶⁷⁸⁹", $_), $Int),$Int);}$power := nqp::neg_I($power, $Int) if $<sign> eq '⁻' || $<sign> eq '¯'; make QAST::Op.new(:op<call>, :name('&postfix:<ⁿ>'), $*W.add_numeric_constant($/, 'Int', $power)); }

As you can see here, it scans the digits and updates the `$power` variable by adding the value at the next decimal position (it is selected in the code above).

The available characters are listed in a string, and to get its value, the offset in the string is used. The `$<dig>` match contains a digit, you can see it in the Grammar:

<dig=[⁰¹²³⁴⁵⁶⁷⁸⁹]>+

## One thought on “🔬72. Superscripts in Perl 6”