=head1 NAME

XS::Framework::Manual::SVAPI::Stash - XS::Framework Stash C++ class reference

=head1 Stash

=head2 Overview

The C<Stash> class extension of C<Hash> class, which provides convenient access
to perl symbol table as well as symbol resolution via C<call>, C<call_SUPER>
and C<call_next> methods.

Stash may be empty, i.e. contain C<NULL> C<SV*>.

=head2 Construction

    static Stash root ()

Returns Perl's default stash.

    Stash (std::nullptr_t = nullptr)

Creates an empty stash.

    static Stash from_name (SV* fqn, I32 flags = 0)
    Stash (const panda::string_view& package, I32 flags = 0)

Looks up for the specified fully-qualified package name and returns, may be empty,
C<Stash> object for the result. The C<flags> are additional parameters for lookup, e.g.
C<GV_ADD> will create new symbol table. See C<gv_stashpvn> in L<perlapi>.

    Stash (SV* sv, bool policy = INCREMENT)
    Stash (HV* sv, bool policy = INCREMENT)

Upgrades hash C<HV*>, which already refers to symbol table, or reference to it (C<SV*>)
into <Stash> object. If the supplied agrument is invalid, the exception will be
thrown. It is possible that the first agrument be C<NULL> or C<undef>, in that case
empty stash will be crated.

Copy and move-constructore are also available:

    Stash (const Stash& oth)
    Stash (const Hash&  oth)
    Stash (const Sv&    oth)
    Stash (Stash&&      oth)
    Stash (Hash&&       oth)
    Stash (Sv&&         oth)

=head2 assignment operators

    Stash& operator= (SV* val)
    Stash& operator= (HV* val)
    Stash& operator= (const Stash& oth)
    Stash& operator= (Stash&& oth)
    Stash& operator= (const Hash& oth)
    Stash& operator= (Hash&& oth)
    Stash& operator= (const Sv& oth)
    Stash& operator= (Sv&& oth)

The assignment operators are complementaty to the constructors above. They
inherit behaviour from C<Hash>, including NULL-safety. The previously held
C<SV*> will be C<dec>-remented.

    void set (HV* val)

The C<set> method directly assigns the value to the underlying C<SV*> in
the form of C<HV*>, I<bypassing all checks>. Use the method with caution.

=head2 element access

    Glob fetch (const panda::string_view& key)
    Glob at (const panda::string_view& key)
    Glob operator[] (const panda::string_view& key)
    op_proxy operator[] (const panda::string_view& key)

The first three methods return C<Glob> type via the C<key> string.
C<fetch> provides safe access to the elements, i.e. in case of absence of a key
empty C<Glob> will be returned. The C<at> method will throw error of the
specified C<key> is not found in the current symbol table. The
C<operator[] fetch> is the alias for C<fetch> method.

The non-const C<operator[]> allows in-place fast modification of underlying
element, i.e.

    Stash stash = Stash("my::package", GV_ADD);
    stash["PI"] = Simple(3.14);

All the methods above are NULL-safe; the assingment of empty stash leads
to thrown exception.

    void store (const panda::string_view& key, SV* v)
    void store (const panda::string_view& key, AV* v)
    void store (const panda::string_view& key, HV* v)
    void store (const panda::string_view& key, CV* v)
    void store (const panda::string_view& key, GV* v)
    void store (const panda::string_view& key, IO* v)
    void store (const panda::string_view& key, const Sv&     v)
    void store (const panda::string_view& key, const Scalar& v)
    void store (const panda::string_view& key, const Array&  v)
    void store (const panda::string_view& key, const Hash&   v)
    void store (const panda::string_view& key, const Sub&    v)
    void store (const panda::string_view& key, const Glob&   v)
    void store (const panda::string_view& key, const Io&     v)

The NULL-safe C<store> method allows to inject the new value into the stash.
The exception will be thrown if the stash object is empty.

The following methods provide convenient access C<Stash> symbol
values, when the type is known:

    Scalar scalar (const panda::string_view& name) const
    Array  array  (const panda::string_view& name) const
    Hash   hash   (const panda::string_view& name) const
    Sub    sub    (const panda::string_view& name) const
    Io     io     (const panda::string_view& name) const

    void scalar (const panda::string_view& name, const Scalar& v)
    void array  (const panda::string_view& name, const Array&  v)
    void hash   (const panda::string_view& name, const Hash&   v)
    void sub    (const panda::string_view& name, const Sub&    v)
    void io     (const panda::string_view& name, const Io&     v)

The read-access is NULL-safe; the write-access (i.e assignment) on empty C<Stash>
throws exception. Usage example:

    Stash stash = Stash("my::package");
    auto pi = stash.scalar("pi");
    stash.scalar("e", Simple(2.71));    // will throw if "my::package" is not known to Perl

=head2 method access

    Sub method (const Sv& name) const
    Sub method (const panda::string_view& name) const

    Sub method_strict (const Sv& name) const
    Sub method_strict (const panda::string_view& name) const

    Sub super_method        (const Sub& current) const
    Sub super_method_strict (const Sub& current) const

    Sub next_method        (const Sub& current) const
    Sub next_method_strict (const Sub& current) const

The method resolving can be performed either via C<panda::string_view> or C<Sv>
name. If a method name cannot be found, the empty C<Sub> is returned. To avoid
that the C<method_strict> should be invoked; if the method C<name> cannot be
found, then exception will be thrown.

The C<super_method> takes the existing C<Sub> and tries to find the corresponding
method in the B<parent> package of the current C<Stash>. It uses the resolution
order specified in the class (i.e. C<use mro 'c3'>). The C<next_method>
tries to find the next method using method resolution order, see L<mro>. The
C<_strict> version throw exception if nothing is found.

This are null-unsafe methods.

Usage example:

    Stash stash = Stash("my::derived");
    Sub m_child = stash.method("method");
    Sub m_parent = stash.super_method(m_child);
    m_parent.call();


=head2 method call

    *depends* call             (const Sv& name, Args&&...args)                 const
    *depends* call             (const panda::string_view& name, Args&&...args) const
    *depends* call_SUPER       (const Sub& context, Args&&...args)             const
    *depends* call_next        (const Sub& context, Args&&...args)             const
    *depends* call_next_maybe  (const Sub& context, Args&&...args)             const
    *depends* call_super       (const Sub& context, Args&&...args)             const
    *depends* call_super_maybe (const Sub& context, Args&&...args)             const

It is possible to invoke arbitrary method with arbitrary arguments if method
C<name> is known in a C<Stash>; if method is not found, then an exception will
be thrown. The C<call_SUPER> / C<call_super> / C<call_next> will lookup for
corresponding method in the parent or next class in the hierachy (see L<mro>).

The diffence between  C<call_SUPER> / C<call_super> is how the parent method
is looked-up: either via classical DFS MRO resolution or via class-defined
resolution (i.e. C3 if 'use mro c3' or DFS otherwise).

The same methods with C<_maybe> prefix do exist: if the corresponding metthod
is not found, then empty result will be returned, i.e. no exception will be
thrown.

This are null-unsafe methods.

=head2 package name

    panda::string_view name           () const
    HEK*             name_hek       () const
    const Simple&    name_sv        () const

To know the name of the package, to which the current C<Stash> object points, the
C<name>, C<name_sv> and C<name_hek> methods can be used. For example:

    Stash stash = Stash("my::package");
    auto name = stash.name();   // returns "my::package"

If it is planned to let the package name be used in Perl in future, then prefer
to use C<name_sv> method.

    panda::string_view effective_name () const

It is possible to have I<effective_name> of the current stash, if the stash
was aliased. See C<HvENAME> in L<perlapi>.

This are null-unsafe methods.

=head2 path()

    panda::string    path           () const

Returns the file path for the current stash, i.e.

    Stash s("A::B::C", GV_ADD);
    s.path();  // returns A/B/C.pm


=head2 mark_as_loaded()

    void mark_as_loaded (const Stash& source)            const
    void mark_as_loaded (const panda::string_view& source) const

Let the perl knows, where the current C<Stash> comes from, i.e. inserts into
the perl C<INC> variable the C<source> for the current C<Stash>. This is
useful, when writing multiple XS-bases packages in a single module.
L<XS::Framework> ships with a few useful macros, so, it is usually
used in the C<BOOT> section of the package like the following:

    Stash(__PACKAGE__, GV_ADD).mark_as_loaded(__MODULE__);

The typical sympthom to use C<mark_as_loaded> is the following error:

    Can't locate MyModule/MyClass.pm in @INC

=head2 inherit()

    void inherit        (const Stash& parent)
    void inherit        (const panda::string_view& parent)

Links the current symbol table as the descendant class for C<parent> C<Stash>.
In other words, it the following construct:

    Stash child("MyPackage::Child"); // or, better Stash(__PACKAGE__, GV_ADD)
    child.mark_as_loaded(__MODULE__);
    Stash base("MyPackage::Base");
    child.inherit(base);

is equivalent to perl code:

    package MyPackage::Child;
    use parent qw/MyPackage::Base/;

If the C<parent> package is defined as C<string_view>, it will be automatically
added to Perl via C<GV_ADD>.

The C<inherit> is NULL-safe method; the exception will be thrown if it is
invoked on empty C<Stash>.

=head2 isa()

    bool isa (const panda::string_view& parent, U32 hash = 0, int flags = 0) const
    bool isa (HEK* hek)            const
    bool isa (const Stash& parent) const

The C<isa> method returns C<true> if the current C<Stash> exactly matches C<parent>
C<Stash> or if the current C<Stash> is child class for the C<parent> C<Stash>.
The similar code in Perl is

    child_CLASS->isa(parent_CLASS);

Under the hood the method uses C<hv_common> function (see C<perlapi>).


=head2 bless()

    Object bless () const;

This method creates new C<Object>, which is blessed into to the current package
(C<Stash>).

    Object bless (const Sv& what) const;

This C<bless> method version works somewhat similiar to the following Perl
construction

    my $class = ...;
    my $obj = ...;
    return bless $obj => $class;

i.e. if C<what> is already an object, it is blessed into the C<Stash>,
otherwise new C<RV*> created from the C<what> argument, and the
blessed object returned.

=head2 add_const_sub()

    void add_const_sub (const panda::string_view& name, const Sv& val);
    
Creates subroutine C<name> that returns constant C<val> eligible for compile-time inlining (like newCONSTSUB). C<val> is retained and made readonly.

C<val> can be either any C<Scalar> or <Array>. In latter case, const sub will return list containing array's values.


=head1 SEE ALSO

L<XS::Framework>

L<XS::Framework::Manual::SVAPI>

L<XS::Framework::Manual::SVAPI::Sv>

L<XS::Framework::Manual::SVAPI::Hash>


=cut
