NAME

Infix::Custom - custom infix operators

VERSION

Version 0.01

SYNOPSIS

use utf8;

# call mode: lower to a sub call
use Infix::Custom op => '⊕', call => \&add, prec => 'add';
my $sum = 2 ⊕ 3;             # add(2, 3)  ==  5

# op mode: lower to a native binary op (no call overhead)
use Infix::Custom op => '×', binop => '*', prec => 'mul';
my $area = $w × $h;          # native multiply

sub add { $_[0] + $_[1] }

DESCRIPTION

Infix::Custom owns core's single PL_infix_plugin hook and exposes a small declarative API for adding your own binary infix operators. A declared operator is parsed at compile time and lowered to an ordinary optree, so there is no residual runtime cost beyond the work the operator names.

import options

use Infix::Custom op => GLYPH, <one lowering mode>, prec => NAME;
use Infix::Custom GLYPH => \&code, prec => NAME;     # shorthand for call mode
op => string

The operator glyph (the shorthand passes it as the first argument). Any byte/UTF-8 sequence core will route to the plugin; it may not contain whitespace.

call => CODE ref or sub name

Call mode. LHS op RHS lowers to call(LHS, RHS).

method => bool (with call)

Method mode. The right-hand side is read as a bareword (an identifier, captured by a parse stage before strict subs sees it) and passed to call as a string, so LHS op name lowers to call(LHS, "name"). This is what makes a safe-navigation operator read naturally:

sub nav { my ($o, $m) = @_; defined $o ? $o->$m : undef }
use Infix::Custom op => '?->', call => \&nav, method => 1, prec => 'mul';

my $n = $obj ?-> child ?-> name // 'default';   # under strict, no quotes

The bareword must be a plain method name with no argument list; for arguments, fall back to call mode with a CODE ref ($obj ?-> sub { $_[0]->m(@a) }).

binop => symbol

Op mode. LHS op RHS lowers to a native binary op, with no sub-call overhead. One of + - * / % ** . x | & ^ << >>.

build_op => integer

Escape hatch for XS authors (see "C-LEVEL build_op").

prec => name

One of low, logical_or_low, logical_and_low, assign, logical_or, logical_and, rel, add, mul, pow, high (mirroring core's INFIX_PREC_* ladder). Defaults to low.

Associativity follows the precedence tier — core's infix-plugin API ties the two together, so there is no separate assoc option. add, mul, logical_or, logical_and (and the *_low pair) are left-associative; assign and pow are right-associative; low, rel and high are non-associative.

Lexical scope

A declared operator is active only in the lexical scope that imported it (it is recorded in %^H) and is restored on scope exit. The same glyph can be rebound to a different meaning in a nested scope. Used outside any declaring scope, the glyph is an ordinary unknown-operator parse error. no Infix::Custom GLYPH; removes an operator earlier; no Infix::Custom; removes all of them.

C-LEVEL build_op

For operators that should lower to a custom optree rather than a sub call or a native binop, an XS author can supply their own build_op with the core signature

OP *build_op(pTHX_ SV **opdata, OP *lhs, OP *rhs, struct Perl_custom_infix *);

and pass its address (as an integer, e.g. via PTR2IV) as build_op:

use Infix::Custom op => '×', build_op => $addr, prec => 'mul';

The pointer is called at compile time with the parsed operands and must return the combined optree. This is a deliberately low-level hatch; the call and binop modes cover everything reachable from pure Perl.

Perl version requirement

Requires perl 5.38 or newer. The PL_infix_plugin hook that makes ambient infix operators possible was added to core in 5.38; there is no way to parse a custom operator mid-expression before then, so the distribution does not install on older perls.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under The Artistic License 2.0 (GPL Compatible).

1 POD Error

The following errors were encountered while parsing the POD:

Around line 29:

Non-ASCII character seen before =encoding in ''⊕','. Assuming UTF-8