How do Perl if-statements work under the hood?
Asked Answered
U

1

6

How does Perl's interpreter do if-statements? I wanted to try to implement a simple Lazy-Basic-Block-Versioning for if-statements that use ref as a predicate, and maybe subsequently for sub-routines as well.

After studying the source code I see OP codes for everything but control flow. My interpreter experience is quite limited, but I would assume to see a OP_IF that would pop the stack for it's predicates OP codes or something along those lines. I found KEY_if which comes from the Yacc grammar, which then subsequently is used in toke.c and translated to a KW_IF, but I can't find where KW_IF is actually used.

I originally intended to just add some basic optimization with global state to peep.c, but since there is no OP_IF I'm struggling to see the big-picture of how control flow is handled.

Unclose answered 6/3 at 18:28 Comment(9)
If you're doing this for practical reasons, more power to you. But if you're trying to cut your teeth on language design, hacking at Perl is probably one of the worst choices for a learning tool. A nice, consistent Lisp dialect or something homoiconic like Io would probably serve that purpose better.Pigweed
@SilvioMayolo It's mostly to get more comfortable with the Perl internals. So I would call it practical, thanks for the insights though.Unclose
Re "It's mostly to get more comfortable with the Perl internals.", -MO=Concise,-exec and Devel::Peek's Dump are your friends.Rocray
There was some documentation named "illguts". The source of it is still obtainable, but I don't know if the generated documents are? Goes into the details of variables.Rocray
Honestly, knowledge of the parser (as opposed to its output, viewable with Concise) isn't really useful. I've never even looked at it.Rocray
@Rocray At least there is a web page PerlGuts Illustrated (there used to be a pdf as well?). And then there's perldoc's perlgutsUnguiculate
... and here's a pdf for it, on cpan: illguts. This is labeled as version 0.09, while the web page (linked above in my previous comment) is 0.06Unguiculate
@zdim, Those are both ancient. Version 0.49 is the latest. repoRocray
The repo comes with a Makefile which I used to package it all, with a pdf and an index.html. A link on Google Drive: perl-illguts-0.49Unguiculate
R
6

if gets compiled into an and or or op.

perl -MO=Concise,-exec -e'if ( f() ) { ... }'
1  <0> enter v
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark s
4  <#> gv[*f] s/EARLYCV
5  <1> entersub[t2] sKS/TARG
6  <|> and(other->7) vK/1
7      <0> pushmark s
8      <$> const[PV "Unimplemented"] s
9      <@> die vK/1
a  <@> leave[1 ref] vKP/REFC
-e syntax OK
perl -MO=Concise,-exec -e'if ( !f() ) { ... }'
1  <0> enter v
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark s
4  <#> gv[*f] s/EARLYCV
5  <1> entersub[t2] sKS/TARG
6  <|> or(other->7) vK/1
7      <0> pushmark s
8      <$> const[PV "Unimplemented"] s
9      <@> die vK/1
a  <@> leave[1 ref] vKP/REFC
-e syntax OK

if can also be compiled into a cond_expr op like the conditional operator (?:).

perl -MO=Concise,-exec -e'if ( f() ) { ... } else { ... }'
1  <0> enter v
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark s
4  <#> gv[*f] s/EARLYCV
5  <1> entersub[t2] sKS/TARG
6  <|> cond_expr(other->7) vK/1
7      <0> pushmark s
8      <$> const[PV "Unimplemented"] s
9      <@> die vK/1
           goto a
b  <0> enter v
c  <;> nextstate(main 5 -e:1) v
d  <0> pushmark s
e  <$> const[PV "Unimplemented"] s
f  <@> die vK/1
g  <@> leave vKP
a  <@> leave[1 ref] vKP/REFC
-e syntax OK

The opcode name from Concise maps to a function named pp_name in pp*.c (with a few exceptions).

Rocray answered 6/3 at 18:32 Comment(2)
Remove the ,-exec to see the unflattened representation.Rocray
Further, for an if with an else clause, then it compiles to an OP_COND_EXPR, which is the same op that implements $cond ? $val1 : $val2.Unhouse

© 2022 - 2024 — McMap. All rights reserved.