package Meow;

use 5.006;
use strict;
use warnings;
our $VERSION = '0.21';

# Store specs for use after JIT compilation (for inheritance)
# This is accessed from XS via get_hv("Meow::SPECS", ...)
our %SPECS;

require XSLoader;
XSLoader::load('Meow', $VERSION);

1;

__END__

=encoding UTF-8

=head1 NAME

Meow - Object ฅ^•ﻌ•^ฅ Orientation

=head1 VERSION

Version 0.21

=cut

=head1 SYNOPSIS

This module is experimental. Many basic features do not yet exist.

	package Cat;

	use Meow;
	use Basic::Types::XS qw/Str Num/;

	ro name => Str;

	rw age => Default(Num, 0);

	make_immutable;

	1;

...

	package Siberian;

	use Meow;

	extends qw/Cat/;

	make_immutable;

	1;

...

	my $cat = Siberian->new(
		name => 'Simba',
		age => 10
	);

	$cat->name; # Simba;
	$cat->age; # 10;

	$cat->age(11);

=head1 DESCRIPTION

Meow provides a fast, minimalist object system in XS, supporting:

=over 4

=item * Read-write (C<rw>) and read-only (C<ro>) attributes

=item * Attribute specification with a Type, C<Default>, C<Coerce>, C<Trigger>, and C<Builder>

=item * Multiple inheritance via C<extends>

=item * Perl-style constructor (C<new>)

=back

=head1 EXPORTS

=head2 rw $name, $spec

Defines a read-write attribute.

=head2 ro $name, $spec

Defines a read-only attribute.

=head2 Default $spec, $value

Sets a default value for an attribute.

=head2 Coerce $spec, $coderef

Sets a coercion coderef for an attribute.

=head2 Trigger $spec, $coderef

Sets a trigger coderef to be called when the attribute is set.

=head2 Builder $spec, $coderef

Sets a builder coderef for lazy attribute construction.

=head2 extends @parents

Adds one or more parent classes to C<@ISA> and copies their attribute specs.

=head2 new %args

Constructs a new object, applying defaults, coercions, triggers, and builders as specified.

=head2 slot $package, $attr_name

Returns the numeric slot index for an attribute in a package. Returns -1 if the
attribute is not found.

    my $NAME_IDX = slot('Cat', 'name');
    my $name = $cat->[$NAME_IDX];

=head2 Slot Variables

When C<make_immutable> is called, uppercase read-only package variables are 
automatically created for each attribute's slot index:

    package Cat {
        use Meow;
        ro name => Str;
        ro age => Int;
        make_immutable;  # Creates $Cat::NAME, $Cat::AGE
    }
    
    # Direct slot access - 43M ops/sec (vs 25M for ->name)
    my $n = $cat->[$Cat::NAME];

=head1 PERFORMANCE

Meow uses JIT-compiled XS accessors for maximum performance:

    Access Method                    ops/sec     Notes
    ─────────────────────────────────────────────────────
    $cat->name (JIT accessor)        25M         Recommended - clean API
    $cat->[$Cat::NAME]               43M         Direct slot access

For typical use, the standard C<< $obj->attr >> syntax is recommended. For
performance-critical hot paths, use the slot variables for direct access.

=head2 Direct Slot Access Example

    use strict;
    use warnings;
    no warnings 'once';  # Meow creates variables at runtime
    
    package Point {
        use Meow;
        ro x => ();
        ro y => ();
        make_immutable;  # Creates $Point::X, $Point::Y
    }
    
    # Standard access - clean API
    my $p = Point->new(x => 10, y => 20);
    print $p->x;  # 25M ops/sec
    
    # Direct slot access - maximum speed
    print $p->[$Point::X];  # 43M ops/sec

=head1 BENCHMARK

	{
		package Foo::Mouse;

		use Mouse;
		use Types::Standard qw/Str Num/;

		has one => (
			is => 'ro',
			isa => Str,
			default => sub { 100 },
		);

		has two => (
			is => 'ro',
			isa => Num,
			default => sub { 200 },
		);

		1;
	}

	{
		package Foo::Extends::Mouse;

		use Mouse;
		extends qw/Foo::Mouse/;

		1;
	}


	{
		package Foo::Moo;

		use Moo;
		use Types::Standard qw/Str Num/;

		has one => (
			is => 'ro',
			isa => Str,
			default => sub { 100 },
		);

		has two => (
			is => 'ro',
			isa => Num,
			default => sub { 200 },
		);

		1;
	}

	{
		package Foo::Extends::Moo;

		use Moo;
		extends qw/Foo::Moo/;

		1;
	}

	{
		package Foo::Meow;
		use Meow;
		use Basic::Types::XS qw/Str Num/;

		ro one => Default(Str, 100);

		ro two => Default(Num, 200);

		make_immutable;

		1;
	}


	{
		package Foo::Extends::Meow;

		use Meow;
		extends qw/Foo::Meow/;

		make_immutable;

		1;
	}

	{
		package Foo::Marlin;
		use Types::Common -lexical, qw/Int/;
		use Marlin
			'one' => { isa => Int, default => 100 },
			'two' => { isa => Int, default => 200 };

		1;
	}


	{
		package Foo::Extends::Marlin;

		use Marlin
			-extends => [qw/Foo::Marlin/];

		1;
	}

	my $ONE = $Foo::Extends::Meow::ONE;
	my $TWO = $Foo::Extends::Meow::TWO;

	my $r = timethese(5000000, {
		'Moo' => sub {
			my $foo = Foo::Extends::Moo->new();
			$foo->one;
			$foo->two;
		},
		'Meow' => sub {
			my $foo = Foo::Extends::Meow->new();
			$foo->one;
			$foo->two;
		},
		'Meow (direct)' => sub {
			my $foo = Foo::Extends::Meow->new();
			my $one = $foo->[$ONE];
			my $two = $foo->[$TWO];
		 },
		'Mouse' => sub {
			my $foo = Foo::Extends::Mouse->new();
			$foo->one;
			$foo->two;
		},
		'Marlin' => sub {
			my $foo = Foo::Extends::Marlin->new();
			$foo->one;
			$foo->two;
		},
		
	});

	cmpthese $r;

...

	============================================================
	Meow Benchmark
	============================================================

	Benchmark: 5,000,000 iterations
	------------------------------------------------------------

	Benchmark: running Marlin, Meow, Meow (direct), Moo, Mouse for at least 5 CPU seconds...
	    Marlin:  5 wallclock secs ( 5.16 usr +  0.14 sys =  5.30 CPU) @ 4766685.66/s (n=25263434)
	      Meow:  5 wallclock secs ( 5.38 usr +  0.03 sys =  5.41 CPU) @ 6183117.56/s (n=33450666)
	Meow (direct):  5 wallclock secs ( 5.00 usr +  0.02 sys =  5.02 CPU) @ 7230451.20/s (n=36296865)
	       Moo:  5 wallclock secs ( 5.20 usr +  0.02 sys =  5.22 CPU) @ 831828.16/s (n=4342143)
	     Mouse:  6 wallclock secs ( 5.21 usr +  0.00 sys =  5.21 CPU) @ 1631554.89/s (n=8500401)

			   Rate        Moo      Mouse    Marlin       Meow Meow (direct)
	Moo            831828/s         --       -49%      -83%       -87%          -88%
	Mouse         1631555/s        96%         --      -66%       -74%          -77%
	Marlin        4766686/s       473%       192%        --       -23%          -34%
	Meow          6183118/s       643%       279%       30%         --          -14%
	Meow (direct) 7230451/s       769%       343%       52%        17%            --

... so without types and against python

	# Python slots class - fastest Python OO pattern
	class Foo:
	    __slots__ = ('_one', '_two')

	    def __init__(self):
		self._one = 100
		self._two = 200

	    @property
	    def one(self):
		return self._one

	    @property
	    def two(self):
		return self._two


	class FooExtends(Foo):
	    __slots__ = ()


	def benchmark():
	    """Run benchmark and return elapsed time."""
	    start = time.perf_counter()
	    for _ in range(ITERATIONS):
		foo = FooExtends()
		_ = foo.one
		_ = foo.two
	    return time.perf_counter() - start


... Meow

	{
	    package Foo::Meow;
	    use Meow;

	    ro one => Default(100);
	    ro two => Default(200);

	    make_immutable;
	    1;
	}

	{
	    package Foo::Extends::Meow;
	    use Meow;
	    extends 'Foo::Meow';

	    make_immutable;
	    1;
	}

	sub benchmark {
	    my $start = time();
	    my $ONE = $Foo::Extends::Meow::ONE;
	    my $TWO = $Foo::Extends::Meow::TWO;
	    for (1 .. $ITERATIONS) {
		my $foo = Foo::Meow->new();
		my $one = $foo->[$ONE];
		my $two = $foo->[$TWO];
	    }
	    return time() - $start;
	}

...

	============================================================
	Python Direct Benchmark (slots + property accessors)
	============================================================
	Python version: 3.9.6 (default, Dec  2 2025, 07:27:58)
	[Clang 17.0.0 (clang-1700.6.3.2)]
	Iterations: 5,000,000
	Runs: 5
	------------------------------------------------------------
	Run 1: 0.649s (7,704,306/s)
	Run 2: 0.647s (7,733,902/s)
	Run 3: 0.646s (7,736,307/s)
	Run 4: 0.648s (7,720,909/s)
	Run 5: 0.649s (7,702,520/s)
	------------------------------------------------------------
	Median rate: 7,720,909/s
	============================================================
	Results saved to bench-direct-python.json
	
	============================================================
	Perl/Meow Direct Benchmark (slots mode)
	============================================================
	Perl version: 5.042000
	Iterations: 5000000
	Runs: 5
	------------------------------------------------------------
	Run 1: 0.674s (7,421,151/s)
	Run 2: 0.640s (7,810,950/s)
	Run 3: 0.640s (7,808,876/s)
	Run 4: 0.639s (7,819,011/s)
	Run 5: 0.639s (7,825,363/s)
	------------------------------------------------------------
	Median rate: 7,810,950/s
	============================================================

=head1 AUTHOR

LNATION, C<< <email at lnation.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-meow at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Meow>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Meow

You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Meow>

=item * Search CPAN

L<https://metacpan.org/release/Meow>

=back

=head1 ACKNOWLEDGEMENTS

=head1 LICENSE AND COPYRIGHT

This software is Copyright (c) 2025 by LNATION.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)

=cut

1; # End of Meow
