LanX has asked for the wisdom of the Perl Monks concerning the following question:

To those familiar with the Perl guts ...

The following code demonstrates two approaches to "simulate" a named infix operator in Perl

use strict; use warnings; package mypkg; use Carp; sub BETWEEN { carp "left = ", shift; carp "right = @_"; }; our $BETWEEN = \≬ 2->$BETWEEN(1,3) ; BETWEEN 2 => 1,3; #2 BETWEEN (1,3) ;

But commenting out the last line naturally leads to compile-time parser error:

Bareword found where operator expected at d:/Users/lanx/tmp/rewrite_bi +nary.pl line 20, near "2 BETWEEN" (Missing operator before BETWEEN?) syntax error at d:/Users/lanx/tmp/rewrite_binary.pl line 20, near "2 B +ETWEEN " Execution of d:/Users/lanx/tmp/rewrite_binary.pl aborted due to compil +ation errors.

Question:

Is there a clean approach to hook into the parse to catch this error event and to rewrite the code?

Such that

2 BETWEEN (1,3)

is translated to

2->$BETWEEN(1,3)

if ref $BETWEEN eq 'CODE' and parsing continues?

No source filters please... :)

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

update

I stumbled over perlguts#Custom-Operators but didn't understand the restrictions. (especially how do I create a "custom peephole optimizer"?)

update

that's it https://metacpan.org/pod/optimize, so if I understand correctly, I need to register BETWEEN as custom operator and use optimize to provide a callback?

Replies are listed 'Best First'.
Re: Implementing named infix operators with parser hook?
by haukex (Archbishop) on Aug 12, 2018 at 14:59 UTC

    Dunno if this meets your needs, but have a look at how tobyink's Sub::Infix does it.

    Edit: missing words.

      I think it doesn't, since I need most operators already. :/

      But thanks for reminding me.

      I new it from discussions here, but remembered it differently. (i.e. the operator needs to be blessed not the operands, which is cool)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        Only just noticed this line of your comment:

        I think it doesn't, since I need most operators already. :/

        Not sure what you mean by it. Did you assume that using Sub::Infix takes over existing operators, so you can no longer use (for example) the | or / operators normally? Because that's not what it does. You can continue to use the existing Perl operators normally, with no slow down, but Sub::Infix will allow you to define additional operators like:

        use Sub::Infix; BEGIN { *between = infix { my ($number, $range) = @_: $number >= $range->[0] and $number <= $range->[1]; }; } if ($value <<between>> [1,10]) { ...; }

        The only limitation is that your infix operator can't be spelled just between. It needs to be |between|, /between/, or <<between>> (and depending on which you choose, you'll get different precedence).

Re: Implementing named infix operators with parser hook?
by tobyink (Canon) on Aug 17, 2018 at 09:36 UTC

    Regarding your updates, the custom op stuff isn't what you want. It doesn't allow you to define your own infix operators. The custom op stuff is what Ref::Util::XS does to make its functions even faster.

    Subs written in XS run faster than subs written in Perl; that's obvious. But subs written in XS still don't run as fast as Perl built-ins like ref. The custom op code stuff allows XS code to be called as efficiently as built-ins. It doesn't have anything to do with parsing, so won't let you define an infix operator.

      Thanks :`(

      UPDATE

      I don't understand this wording though:

      This is primarily to allow the building of interpreters for other languages in the Perl core,

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        I don't know why it says that; I can't see how it's that useful for interpreting other languages. A couple of paragraphs further down it says:

        It's important to know what custom operators won't do for you. They won't let you add new syntax to Perl, directly. They won't even let you add new keywords, directly. In fact, they won't change the way Perl compiles a program at all.

        If you're building your own interpreter for another language into Perl, you'd first need to sort out the parsing. The custom op still would only be an optimization stage afterwards to enable the language's keywords to perform comparably to Perl's built-ins.

Re: Implementing named infix operators with parser hook?
by Eily (Monsignor) on Aug 17, 2018 at 08:52 UTC

    Just out of curiosity, did you consider something like: is 2 => between(1,3)? There's still the need for a comma* (or arrow) between the left operand and "infix" operator, but it's a little less scary looking than 2->$BETWEEN(1, 3). Also it's quite easy to implement, &is would just call the closure returned by &between. And closures are good.

    *Unless you want to write that as is { 2 } between 1, 3;, personally I don't like that version.

      > did you consider something like: is 2 => between(1,3)?

      Yes I did. :)

      > closures

      I'm using objects.

      I have a very good solution yet, using indirect method calls and constants as operands.

      col BETWEEN 1,2

      I just need an alternative for the cases where the LHS is not a constant, which is rare in most SQL statements.

      Maybe its time to show a proof of concept...

      Cheers Rolf
      , (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        Don't you mean it's rare for LHS to be a constant in SQL statements. Or is the problem that 'rare in most' as opposed to just saying 'rare' can be satisfied by a 51% hit rate (most can be 50.5%, with rare being say 1.5% inside that, but by saying nothing about the other 49.5% allows them all to be hits). One has to be rigorous with verbal expression of statistical propositions.

        One world, one people

Re: Implementing named infix operators with parser hook?
by anonymized user 468275 (Curate) on Aug 17, 2018 at 12:08 UTC
    Don't know if it helps but you can overload all keywords, functions and operators in Postgresql, and have them call a perl subroutine instead, e.g for something like BETWEEN (doc snippet:)
    CREATE OPERATOR name ( PROCEDURE = function_name [, LEFTARG = left_type ] [, RIGHTARG = right_type ] [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ] [, RESTRICT = res_proc ] [, JOIN = join_proc ] [, HASHES ] [, MERGES ] )

    One world, one people

      Thanks! :)

      It doesn't help here, because I'm DB agnostic and this goes the other way round.

      But it's good to know and shows a nice way to model such overloads.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Implementing named infix operators with parser hook?
by anonymized user 468275 (Curate) on Aug 17, 2018 at 08:33 UTC
    Ought to be possible using some kind of pathological c-preprocessor syntax and Filter::cpp

    One world, one people

      Thanks, but as I said, no source filters or worse. :)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        That's fine, it's your baby, but technically in this case the filtering occurs after Perl loads it unlike filtering it before Perl reads it. Otherwise Perl itself is a source filter falling on the wrong side of your line in the sand.

        One world, one people