Search code examples
rakunqp

What is the difference between `nqp::if` and `if` in an .nqp file?


From World.nqp, line 3602 :

nqp::if(                                    
   nqp::istype(nqp::atpos($task,3),$!Block),
   QAST::Op.new( :op<call>,
       QAST::WVal.new(:value(nqp::atpos($task,3))),
       $self,
       $getattr
   ),
   nqp::if(
       nqp::iseq_i($code,5),
       QAST::IVal.new(:value(nqp::atpos($task,3))),                        
       QAST::NVal.new(:value(nqp::atpos($task,3)))
   )
),

whereas from World.nqp, line 3314 :

if $invocant_type =:= $!acc_sig_cache_type {
     $sig := $!acc_sig_cache;
}
# First time, create new signature and mark it cached
else {
    $sig := $!w.create_signature_and_params(
    NQPMu, %sig_empty, $block, 'Any', :method, :$invocant_type);
    $!acc_sig_cache      := $sig;
    $!acc_sig_cache_type := $invocant_type;
}

I thought the last form of if (without nqp::) in front was not allowed unless if was a builtin? See NQP Built-in Subs List.

The first form, nqp::if, is described in the NQP Opcode List, however I could not find documentation for the second form, though it seems to be the most common form in the Rakudo source tree.

Why are there two forms of if statements in NQP?


Solution

  • The if statement in NQP is part of the language syntax rather than being any kind of built-in routine. It is parsed by the NQP compiler's grammar and compiled into an AST node. The AST node it produces is, so far as the conditional goes, the same one that an nqp::if would produce (the nqp::foo syntax is just a means to create Op AST nodes). The cond() ?? foo() !! bar() syntax also compiles into the same kind of node. This is also true for the full Perl 6.

    The notable differences are:

    • The if statement can only appear at statement level, while nqp::if(...) can appear anywhere
    • The if statement form introduces a new lexical scope inside of the curly braces, while the nqp::if form does not do that

    In the linked example, the expression form is desired, thus the use of the nqp::if construct. However, ??/!! could also have been used, and would arguably be more readable. Mostly, it's just up to the author of the code to decide what they think communicates best or matches the surrounding context.