NAME
Stefo - Compile Perl subs to optimized bytecode via optree walking
SYNOPSIS
use Stefo;
# Compile a simple predicate - returns optimized checker
my $check = Stefo::compile(sub { $_ > 0 });
# Execute in C (~5 cycles instead of ~100)
my $ok = Stefo::check($check, 42); # true
my $ok = Stefo::check($check, -1); # false
# Check if a sub was successfully optimized
if (Stefo::is_optimized($check)) {
print "Running at C speed!\n";
}
DESCRIPTION
Stefo walks Perl optrees at compile-time and extracts simple patterns that can be executed in pure C without Perl callback overhead.
When you pass a sub to compile(), it:
- 1. Gets the CV's optree via CvROOT
- 2. Walks the ops looking for recognizable patterns
- 3. Compiles matching patterns to a simple bytecode IR
- 4. Executes that bytecode in C (~5 cycles vs ~100 for call_sv)
Subs that can't be optimized fall back to normal Perl execution.
SUPPORTED PATTERNS
Numeric Comparisons
$_ > N $_ >= N $_ < N $_ <= N
$_ == N $_ != N
String Comparisons
$_ eq 'str' $_ ne 'str'
Arithmetic Operations
$_ + N $_ - N $_ * N $_ / N
$_ % N abs($_) int($_)
Definedness and Boolean
defined $_ !defined $_
$_ !$_
!!$_ (double negation for bool coercion)
Length Checks
length($_) length($_) > N
length($_) == N length($_) < N
Reference Type Checks
ref($_) ref($_) eq 'ARRAY'
ref($_) eq 'HASH' ref($_) eq 'CODE'
ref($_) eq 'SCALAR' ref($_) eq 'Regexp'
ref($_) eq 'GLOB' ref($_) ne 'TYPE'
Regex Matching
$_ =~ /pattern/ $_ !~ /pattern/
Boolean Logic
EXPR && EXPR short-circuit AND
EXPR || EXPR short-circuit OR
EXPR // EXPR defined-or
!EXPR logical NOT
Complex Expressions
$_ > 0 && $_ < 100 range check
($_ > 0 && $_ < 10) || $_ == 100
$_ % 2 == 0 even check
int($_) == $_ integer check
abs($_) > 5 absolute value comparison
Performance Estimates
Pattern Cycles (approx)
----------------------------------------------------------------
Simple comparison ~5-10
defined/ref check ~3-5
String comparison ~10-15
Regex match ~20-100 (varies by pattern)
Boolean logic +1-2 per operator
call_sv (fallback) ~100
Unsupported patterns (method calls, external functions, complex logic) fall back to Perl call_sv.
FUNCTIONS
compile($sub)
Compile a sub to an optimized checker. Returns an opaque blessed reference.
my $checker = Stefo::compile(sub { $_ > 0 && $_ < 100 });
The returned object can be passed to check().
check($checker, $value)
Execute a compiled checker against a value. Returns true/false.
my $ok = Stefo::check($checker, 42);
If the sub wasn't optimizable, this falls back to calling the original sub.
is_optimized($checker)
Returns true if the sub was successfully compiled to bytecode.
if (Stefo::is_optimized($checker)) {
# Running at C speed
}
instruction_count($checker)
Returns the number of bytecode instructions (for debugging/profiling).
DIRECT HELPER FUNCTIONS
Stefo also provides direct XS helper functions that don't require compilation. These are fast C implementations for common type checks.
Type Checks
Stefo::is_array($val) # true if ARRAY ref
Stefo::is_hash($val) # true if HASH ref
Stefo::is_code($val) # true if CODE ref
Stefo::is_ref($val) # true if any reference
Stefo::is_scalar($val) # true if SCALAR ref
Stefo::is_regexp($val) # true if Regexp ref
Stefo::is_glob($val) # true if GLOB ref
Stefo::is_blessed($val) # true if blessed object
Value Checks
Stefo::is_defined($val) # true if defined
Stefo::is_undef($val) # true if undef
Stefo::is_true($val) # true if Perl-true
Stefo::is_false($val) # true if Perl-false
Stefo::looks_like_number($val) # true if numeric
Numeric Checks
Stefo::is_integer($val) # true if integer value
Stefo::is_positive($val) # true if > 0
Stefo::is_negative($val) # true if < 0
Stefo::is_zero($val) # true if == 0
Stefo::is_even($val) # true if even integer
Stefo::is_odd($val) # true if odd integer
String Checks
Stefo::is_empty_string($val) # true if ""
Stefo::is_nonempty_string($val) # true if length > 0
Stefo::is_alpha($val) # all alphabetic
Stefo::is_alnum($val) # all alphanumeric
Stefo::is_digit($val) # all digits
Stefo::is_space($val) # all whitespace
Stefo::is_word_char($val) # all word characters (\w)
Stefo::is_upper($val) # all uppercase
Stefo::is_lower($val) # all lowercase
Stefo::is_ascii($val) # all ASCII (0-127)
Stefo::is_printable($val) # all printable
String Operations
Stefo::string_contains($str, $needle) # substring search
Stefo::string_starts_with($str, $prefix) # prefix check
Stefo::string_ends_with($str, $suffix) # suffix check
Collection Checks
Stefo::array_length($val) # number of elements (-1 if not array)
Stefo::hash_size($val) # number of keys (-1 if not hash)
Stefo::is_array_empty($val) # true if empty array
Stefo::is_hash_empty($val) # true if empty hash
Type Inspection
Stefo::typeof($val) # returns: UNDEF, INTEGER, NUMBER, STRING,
# ARRAY, HASH, CODE, REGEXP, GLOB,
# SCALAR, OBJECT, UNKNOWN
Stefo::reftype($val) # returns ref type or undef
USE CASES
Type Constraints
# Before: ~100 cycles per check
object::register_type('PositiveInt', sub { $_ > 0 });
# After: ~5 cycles per check
my $check = Stefo::compile(sub { $_ > 0 });
object::register_type_compiled('PositiveInt', $check);
Hot Loop Predicates
# Before: call_sv overhead per element
my @valid = grep { $_ > 0 && $_ < 100 } @huge_list;
# After: bytecode execution
my $pred = Stefo::compile(sub { $_ > 0 && $_ < 100 });
my @valid = grep { Stefo::check($pred, $_) } @huge_list;
HOW IT WORKS
The module walks Perl's internal optree representation. For example:
sub { $_ > 0 }
Produces this optree:
leavesub
nextstate
gt
gvsv[*_]
const[IV 0]
Which gets compiled to bytecode:
PUSH_VAL ; push $_
PUSH_IV 0 ; push 0
GT ; compare, push result
RETURN ; return top of stack
The bytecode is executed by a simple stack-based VM written in C.
REQUIREMENTS
Perl 5.10.0 or later. Works with threaded and non-threaded Perl.
AUTHOR
LNATION <email@lnation.org>
LICENSE
Same as Perl itself.