🔬65. The EVAL routine in Perl 6, part 2

🔬65. The EVAL routine in Raku, part 2

N. B. Perl 6 has been renamed to Raku. Click to read more.


Welcome back! As you might notice, there was a small gap in the daily post flow.

Before we are back to the Rakudo internals, a couple of words about some changes here. First of all, every post is now marked with either 🦋 or 🔬 (or with indistinguishable rectangles □ if your browser cannot display an emoji :-). These characters mean two categories of posts here: a butterfly stands for Perl 6 syntax, while a microscope is for Perl 6 internals. In the first category, only user-level aspects or Perl 6 are discussed. In the second, we dig into the source codes of Rakudo. All the past post are updated accordingly.

The second change is that I will occasionally post more articles in the Perl 6 syntax category because I found out that non-Russian speakers often like my Russian blog posts. Those posts are mostly short texts explaining interesting features of Perl 6, such as the =~= operator or promises.

* * *

OK, now we have to talk about the EVAL routine. It is defined in the src/core/ForeignCode.pm file as a multi-function. Let us see at their signatures:

proto sub EVAL($code is copy where Blob|Cool, 
               Str() :$lang = 'perl6',
               PseudoStash :$context, *%n)

multi sub EVAL($code, 
               Str :$lang where { ($lang // '') eq 'Perl5' },
               PseudoStash :$context)

Notice that one of the function is a proto, while another is the only multi-candidate. Unlike many other cases that you can see in the sources of Rakudo, this proto routine contains code. Refer to one of the recent blog posts to see how it works.

We start with an example from the first part of the article.

EVAL('say 123');

Here, the passed value is Str, and it is caught by the proto sub, as its first argument can be Cool.

The sub creates a compiler for the given language (which is Perl 6 by default).

my $compiler := nqp::getcomp($lang);

The next step in the sub is to make a string out of $code. In this first example, this task is trivial.

$code = nqp::istype($code,Blob) ?? $code.decode(
    $compiler.cli-options<encoding> // 'utf8'
) !! $code.Str;

Finally, the string is compiled:

my $compiled := $compiler.compile:
    $code,
    :outer_ctx($eval_ctx),
    :global(GLOBAL),
    :mast_frames(mast_frames),
    |(:optimize($_) with nqp::getcomp('perl6').cli-options<optimize>),
    |(%(:grammar($LANG<MAIN>), :actions($LANG<MAIN-actions>)) if $LANG);

After compilation, you get an object of the ForeignCode type. This class is a child class of Callable, so the object can be called and returned (actually, it’s not quite clear how it happens):

$compiled();

Now you can understand that single quotes in the second example with curly braces still create an executable code:

EVAL('say {456}');

Here, the whole string is compiled as it was a Perl 6 code, and the code block there is a code block, which Perl should execute, and thus say gets a code block, so it calls its gist method to prepare the output:

> {456}.gist
-> ;; $_? is raw { #`(Block|140388575216888) ... }

 

One thought on “🔬65. The EVAL routine in Perl 6, part 2”

Leave a Reply

Your email address will not be published. Required fields are marked *

Retype the CAPTCHA code from the image
Change the CAPTCHA codeSpeak the CAPTCHA code