<commit_before>=encoding utf8

=head1 TITLE

DRAFT: Synopsis 32: Setting Library - Exceptions

=head1 AUTHORS

    <NAME> <<EMAIL>>

Authors of previous versions of this document:

    <NAME> <<EMAIL>>
    <NAME> <<EMAIL>>

=head1 VERSION

    Created: 26 Feb 2009

    Last Modified: 17 August 2012
    Version: 20

The document is a draft.

If you read the HTML version, it is generated from the Pod in the specs
repository under
L<https://github.com/perl6/specs/blob/master/S32-setting-library/Exception.pod>
so edit it there in the git repository if you would like to make changes.

=head1 Roles and Classes

All built-in exceptions save for the base class C<Exception> live in the
C<X::> namespace.

Generally error classes are supposed to provide the objects involved with the
error, and only convert them to a string form when producing the error
message. This does not apply to compile errors that involve types which have
not been fully composed yet; in that case just the name of the incomplete
type is included in the exception object.

Names of error classes should describe the problem in some way, or at least
mention the operation that went wrong. If an error can only occur in relation
to a certain type, the error types should be under C<X::ThatType::>.

=head2 Exception

All built-in exceptions inherit from C<Exception>, which provides some basic
behavior: storing a backtrace and providing an interface for the backtrace
printer.

    class Exception {
        has $.backtrace;
        method message() { ... } # an actual stub
        method gist { "$.message\n$.backtrace" }
        method throw() { }
        method fail()  { }
        method resumable() { }
        method resume() { }
    }

All direct subclasses are supposed to override method C<message>.

=head2 X::OS

    role X::OS { has $.os-error }

for all errors that are triggered by some error reported by the operating
system (failed IO, system calls, fork, memory allocation).

=head2 X::IO

    role X::IO does X::OS { }

For IO related errors


=head3 X::IO::Rename

Thrown when a file rename fails. TODO: maybe unify with X::IO::Copy?

    my class X::IO::Rename does X::IO is Exception {
        has $.from;
        has $.to;
        method message() {
            "Failed to rename '$.from' to '$.to': $.os-error"
        }
    }

=head3 X::IO::Copy

Thrown when a file copy operation fails

    my class X::IO::Copy does X::IO is Exception {
        has $.from;
        has $.to;
        method message() {
            "Failed to copy '$.from' to '$.to': $.os-error"
        }
    }

=head3 X::IO::Mkdir

Thrown when an C<mkdir> operation fails.

    my class X::IO::Mkdir does X::IO is Exception {
        has $.path;
        has $.mode;
        method message() {
            "Failed to create directory '$.path' with mode '0o{$.mode.fmt("%03o")}': $.os-error"
        }
    }

=head3 X::IO::Chdir

Thrown when a C<chdir> fails

    my class X::IO::Chdir does X::IO is Exception {
        has $.path;
        method message() {
            "Failed to change the working directory to '$.path': $.os-error"
        }
    }

=head3 X::IO::Dir

Thrown when a C<dir()> fails

    my class X::IO::Dir does X::IO is Exception {
        has $.path;
        method message() {
            "Failed to get the directory contents of '$.path': $.os-error"
        }
    }

=head3 X::IO::Cwd

Thrown when unable to determine the current directory.

    my class X::IO::Cwd does X::IO is Exception {
        method message() {
            "Failed to get the working directory: $.os-error"
        }
    }

=head3 X::IO::Rmdir

Thrown when C<rmdir> fails.

    my class X::IO::Rmdir does X::IO is Exception {
        has $.path;
        method message() {
            "Failed to remove the directory '$.path': $.os-error"
        }
    }

=head3 X::IO::Unlink

Thrown when C<unlink> fails.

    my class X::IO::Unlink does X::IO is Exception {
        has $.path;
        method message() {
            "Failed to remove the file '$.path': $.os-error"
        }
    }

=head3 X::IO::Chmod

Thrown when C<chmod> fails.

    my class X::IO::Chmod does X::IO is Exception {
        has $.path;
        has $.mode;
        method message() {
            "Failed to set the mode of '$.path' to '0o{$.mode.fmt("%03o")}': $.os-error"
        }
    }

=head2 X::NYI

    class X::NYI is Exception {
        has $.feature;
        method message() { "$.feature is not yet implemented. Sorry. " }
    }

For errors that stem from incomplete implementations of the Perl 6 language.
A full Perl 6.0 implementation should not throw such errors.

=head2 X::AdHoc

    class X::AdHoc is Exception {
        has $.payload handles <Str Numeric>;
        method message() { $.payload.Str }
    }

If you call C<&die> with non-C<Exception> arguments, what the user finds
in his C<$!> variables is an object of type C<X::AdHoc>.

So C<&die> could be written as

    multi sub die(Exception $e) is hidden_from_backtrace {
        $e.throw
    }
    multi sub die($payload) is hidden_from_backtrace {
        X::AdHoc.new(:$payload).throw;
    }


=head2 Compile-time errors

=head3 X::Comp

    role X::Comp {
        has $.filename;
        has $.line;
        has $.column;
    }

For errors that arise from compiling code. Note that in this case the
backtrace shows how the
compilation was triggered (through C<use SomeModule;>, C<eval>s etc.).
The actual location of the error does not appear in the backtrace, but
rather in the attributes defined in this role.

For exceptions that can occur both at run time and at compile time, the base
exception type should not do C<X::Comp>, but it should be mixed in into
the exception object when thrown at compile time.

=head3 X::Placeholder::Block

Thrown when a placeholder variable is used in a block that does not allow a
signature (for example C<class A { $^foo }>.

    my class X::Placeholder::Block does X::Comp {
        has $.placeholder;
        method message() {
            "Placeholder variable $.placeholder may not be used here because the surrounding block takes no signature";
        }
    }

=head3 X::Placeholder::Mainline

Thrown when a placeholder variable is used in the mainline, ie outside of any
explicit block.

    my class X::Placeholder::Mainline is X::Placeholder::Block {
        method message() {
            "Cannot use placeholder parameter $.placeholder in the mainline"
        }
    }

=head3 X::Redeclaration

Thrown when a symbol is redeclared

    my class X::Redeclaration does X::Comp {
        has $.symbol;
        has $.postfix = '';
        has $.what    = 'symbol';
        method message() {
            "Redeclaration of $.what $.symbol$.postfix";
        }
    }

=head3 X::Undeclared

Occurs when a symbol is being referenced that needs to be declared, but isn't.

    my class X::Undeclared does X::Comp {
        has $.what = 'Variable';
        has $.symbol;
        method message() {
            "$.what $.symbol is not declared";
        }
    }

=head3 X::Attribute::Undeclared

Thrown when an undeclared attribute is being referenced.

    my class X::Attribute::Undeclared is X::Undeclared {
        has $.package-kind;
        has $.package-name;
        method message() {
            "Attribute $.name not declared in $.package-kind $.package-name";
        }
    }

=head3 X::Phaser::Multiple

Thrown when multiple phasers of the same type occur in a block, but only one
is allowed (for example C<CATCH> or C<CONTROL>).

    my class X::Phaser::Multiple does X::Comp {
        has $.block;
        method message() { "Only one $.block block is allowed" }
    }

=head3 X::Parameter::Default

Thrown when a paramter has a default, but isn't allowed to have one, for
example on mandatory parameters.

    my class X::Parameter::Default does X::Comp {
        has $.how;
        has $.parameter;
        method message() {
            $.parameter
                ?? "Cannot put default on $.how parameter $.parameter"
                !! "Cannot put default on anonymous $.how parameter";
        }
    }


=head3 X::Parameter::Placeholder

Thrown when the user tries to use a placeholder as a formal parameter.
(Usually C<:$foo> misspelled as C<$:foo>).

    my class X::Parameter::Placeholder does X::Comp {
        has $.parameter;
        has $.right;
        method message() {
            "In signature parameter, placeholder variables like $.parameter are illegal\n"
            ~ "you probably meant a named parameter: '$.right'";
        }
    }

=head3 X::Parameter::Twigil

Thrown when an illegal twigil is used in a formal parameter.

    my class X::Parameter::Twigil does X::Comp {
        has $.parameter;
        has $.twigil;
        method message() {
            "In signature parameter $.parameter, it is illegal to use the $.twigil twigil";
        }
    }

=head3 X::Parameter::MultipleTypeConstraints

Thrown for multiple prefix type constraints like C<Int Str $x>.

    my class X::Parameter::MultipleTypeConstraints does X::Comp {
        has $.parameter;
        method message() {
            qq[{"Parameter $.parameter" || 'A parameter'} may only have one prefix type constraint];
        }
    }

=head3 X::Parameter::WrongOrder

Thrown when parameters are listed in a signature in the wrong order (for
example optional before mandatory parameters).

    my class X::Parameter::WrongOrder does X::Comp {
        has $.misplaced;
        has $.parameter;
        has $.after;
        method message() {
            "Cannot put $.misplaced parameter $.parameter after $.after parameters";
        }
    }

=head3 X::Signature::NameClash

Thrown when multiple named paramters have the same name.

    my class X::Signature::NameClash does X::Comp {
        has $.name;
        method message() {
            "Name $.name used for more than one named parameter";
        }
    }

=head3 X::Method::Private::Permission

Thrown when attempting to call a private method outside the current class or
role without a fitting trust relation.

    my class X::Method::Private::Permission does X::Comp {
        has $.method;
        has $.source-package;
        has $.calling-package;
        method message() {
            "Cannot call private method '$.method' on package $.source-package because it does not trust $.calling-package";
        }
    }

=head3 X::Method::Private::Unqualified

Thrown when attempting to call a method on something else than C<self> without
fully qualifying the class.

    my class X::Method::Private::Unqualified does X::Comp {
        has $.method;
        method message() {
            "Private method call to $.method must be fully qualified with the package containing the method";
        }
    }


=head3 X::Bind::NativeType

Thrown when trying to bind to a natively typed variable
TODO: inherit from X::Bind?

    my class X::Bind::NativeType does X::Comp {
        method message() {
            'Cannot bind to a natively typed variable; use assignment instead'
        }
    }

=head3 X::Attribute::Package

Thrown when trying to declare an attribute inside a package which doesn't
support attributes.

    my class X::Attribute::Package does X::Comp {
        has $.package-kind;<commit_msg>[S32::Exception] X::Bind::NativeType now reports name of the variable<commit_after>=encoding utf8

=head1 TITLE

DRAFT: Synopsis 32: Setting Library - Exceptions

=head1 AUTHORS

    <NAME> <<EMAIL>>

Authors of previous versions of this document:

    <NAME> <<EMAIL>>
    <NAME> <<EMAIL>>

=head1 VERSION

    Created: 26 Feb 2009

    Last Modified: 21 August 2012
    Version: 21

The document is a draft.

If you read the HTML version, it is generated from the Pod in the specs
repository under
L<https://github.com/perl6/specs/blob/master/S32-setting-library/Exception.pod>
so edit it there in the git repository if you would like to make changes.

=head1 Roles and Classes

All built-in exceptions save for the base class C<Exception> live in the
C<X::> namespace.

Generally error classes are supposed to provide the objects involved with the
error, and only convert them to a string form when producing the error
message. This does not apply to compile errors that involve types which have
not been fully composed yet; in that case just the name of the incomplete
type is included in the exception object.

Names of error classes should describe the problem in some way, or at least
mention the operation that went wrong. If an error can only occur in relation
to a certain type, the error types should be under C<X::ThatType::>.

=head2 Exception

All built-in exceptions inherit from C<Exception>, which provides some basic
behavior: storing a backtrace and providing an interface for the backtrace
printer.

    class Exception {
        has $.backtrace;
        method message() { ... } # an actual stub
        method gist { "$.message\n$.backtrace" }
        method throw() { }
        method fail()  { }
        method resumable() { }
        method resume() { }
    }

All direct subclasses are supposed to override method C<message>.

=head2 X::OS

    role X::OS { has $.os-error }

for all errors that are triggered by some error reported by the operating
system (failed IO, system calls, fork, memory allocation).

=head2 X::IO

    role X::IO does X::OS { }

For IO related errors


=head3 X::IO::Rename

Thrown when a file rename fails. TODO: maybe unify with X::IO::Copy?

    my class X::IO::Rename does X::IO is Exception {
        has $.from;
        has $.to;
        method message() {
            "Failed to rename '$.from' to '$.to': $.os-error"
        }
    }

=head3 X::IO::Copy

Thrown when a file copy operation fails

    my class X::IO::Copy does X::IO is Exception {
        has $.from;
        has $.to;
        method message() {
            "Failed to copy '$.from' to '$.to': $.os-error"
        }
    }

=head3 X::IO::Mkdir

Thrown when an C<mkdir> operation fails.

    my class X::IO::Mkdir does X::IO is Exception {
        has $.path;
        has $.mode;
        method message() {
            "Failed to create directory '$.path' with mode '0o{$.mode.fmt("%03o")}': $.os-error"
        }
    }

=head3 X::IO::Chdir

Thrown when a C<chdir> fails

    my class X::IO::Chdir does X::IO is Exception {
        has $.path;
        method message() {
            "Failed to change the working directory to '$.path': $.os-error"
        }
    }

=head3 X::IO::Dir

Thrown when a C<dir()> fails

    my class X::IO::Dir does X::IO is Exception {
        has $.path;
        method message() {
            "Failed to get the directory contents of '$.path': $.os-error"
        }
    }

=head3 X::IO::Cwd

Thrown when unable to determine the current directory.

    my class X::IO::Cwd does X::IO is Exception {
        method message() {
            "Failed to get the working directory: $.os-error"
        }
    }

=head3 X::IO::Rmdir

Thrown when C<rmdir> fails.

    my class X::IO::Rmdir does X::IO is Exception {
        has $.path;
        method message() {
            "Failed to remove the directory '$.path': $.os-error"
        }
    }

=head3 X::IO::Unlink

Thrown when C<unlink> fails.

    my class X::IO::Unlink does X::IO is Exception {
        has $.path;
        method message() {
            "Failed to remove the file '$.path': $.os-error"
        }
    }

=head3 X::IO::Chmod

Thrown when C<chmod> fails.

    my class X::IO::Chmod does X::IO is Exception {
        has $.path;
        has $.mode;
        method message() {
            "Failed to set the mode of '$.path' to '0o{$.mode.fmt("%03o")}': $.os-error"
        }
    }

=head2 X::NYI

    class X::NYI is Exception {
        has $.feature;
        method message() { "$.feature is not yet implemented. Sorry. " }
    }

For errors that stem from incomplete implementations of the Perl 6 language.
A full Perl 6.0 implementation should not throw such errors.

=head2 X::AdHoc

    class X::AdHoc is Exception {
        has $.payload handles <Str Numeric>;
        method message() { $.payload.Str }
    }

If you call C<&die> with non-C<Exception> arguments, what the user finds
in his C<$!> variables is an object of type C<X::AdHoc>.

So C<&die> could be written as

    multi sub die(Exception $e) is hidden_from_backtrace {
        $e.throw
    }
    multi sub die($payload) is hidden_from_backtrace {
        X::AdHoc.new(:$payload).throw;
    }


=head2 Compile-time errors

=head3 X::Comp

    role X::Comp {
        has $.filename;
        has $.line;
        has $.column;
    }

For errors that arise from compiling code. Note that in this case the
backtrace shows how the
compilation was triggered (through C<use SomeModule;>, C<eval>s etc.).
The actual location of the error does not appear in the backtrace, but
rather in the attributes defined in this role.

For exceptions that can occur both at run time and at compile time, the base
exception type should not do C<X::Comp>, but it should be mixed in into
the exception object when thrown at compile time.

=head3 X::Placeholder::Block

Thrown when a placeholder variable is used in a block that does not allow a
signature (for example C<class A { $^foo }>.

    my class X::Placeholder::Block does X::Comp {
        has $.placeholder;
        method message() {
            "Placeholder variable $.placeholder may not be used here because the surrounding block takes no signature";
        }
    }

=head3 X::Placeholder::Mainline

Thrown when a placeholder variable is used in the mainline, ie outside of any
explicit block.

    my class X::Placeholder::Mainline is X::Placeholder::Block {
        method message() {
            "Cannot use placeholder parameter $.placeholder in the mainline"
        }
    }

=head3 X::Redeclaration

Thrown when a symbol is redeclared

    my class X::Redeclaration does X::Comp {
        has $.symbol;
        has $.postfix = '';
        has $.what    = 'symbol';
        method message() {
            "Redeclaration of $.what $.symbol$.postfix";
        }
    }

=head3 X::Undeclared

Occurs when a symbol is being referenced that needs to be declared, but isn't.

    my class X::Undeclared does X::Comp {
        has $.what = 'Variable';
        has $.symbol;
        method message() {
            "$.what $.symbol is not declared";
        }
    }

=head3 X::Attribute::Undeclared

Thrown when an undeclared attribute is being referenced.

    my class X::Attribute::Undeclared is X::Undeclared {
        has $.package-kind;
        has $.package-name;
        method message() {
            "Attribute $.name not declared in $.package-kind $.package-name";
        }
    }

=head3 X::Phaser::Multiple

Thrown when multiple phasers of the same type occur in a block, but only one
is allowed (for example C<CATCH> or C<CONTROL>).

    my class X::Phaser::Multiple does X::Comp {
        has $.block;
        method message() { "Only one $.block block is allowed" }
    }

=head3 X::Parameter::Default

Thrown when a paramter has a default, but isn't allowed to have one, for
example on mandatory parameters.

    my class X::Parameter::Default does X::Comp {
        has $.how;
        has $.parameter;
        method message() {
            $.parameter
                ?? "Cannot put default on $.how parameter $.parameter"
                !! "Cannot put default on anonymous $.how parameter";
        }
    }


=head3 X::Parameter::Placeholder

Thrown when the user tries to use a placeholder as a formal parameter.
(Usually C<:$foo> misspelled as C<$:foo>).

    my class X::Parameter::Placeholder does X::Comp {
        has $.parameter;
        has $.right;
        method message() {
            "In signature parameter, placeholder variables like $.parameter are illegal\n"
            ~ "you probably meant a named parameter: '$.right'";
        }
    }

=head3 X::Parameter::Twigil

Thrown when an illegal twigil is used in a formal parameter.

    my class X::Parameter::Twigil does X::Comp {
        has $.parameter;
        has $.twigil;
        method message() {
            "In signature parameter $.parameter, it is illegal to use the $.twigil twigil";
        }
    }

=head3 X::Parameter::MultipleTypeConstraints

Thrown for multiple prefix type constraints like C<Int Str $x>.

    my class X::Parameter::MultipleTypeConstraints does X::Comp {
        has $.parameter;
        method message() {
            qq[{"Parameter $.parameter" || 'A parameter'} may only have one prefix type constraint];
        }
    }

=head3 X::Parameter::WrongOrder

Thrown when parameters are listed in a signature in the wrong order (for
example optional before mandatory parameters).

    my class X::Parameter::WrongOrder does X::Comp {
        has $.misplaced;
        has $.parameter;
        has $.after;
        method message() {
            "Cannot put $.misplaced parameter $.parameter after $.after parameters";
        }
    }

=head3 X::Signature::NameClash

Thrown when multiple named paramters have the same name.

    my class X::Signature::NameClash does X::Comp {
        has $.name;
        method message() {
            "Name $.name used for more than one named parameter";
        }
    }

=head3 X::Method::Private::Permission

Thrown when attempting to call a private method outside the current class or
role without a fitting trust relation.

    my class X::Method::Private::Permission does X::Comp {
        has $.method;
        has $.source-package;
        has $.calling-package;
        method message() {
            "Cannot call private method '$.method' on package $.source-package because it does not trust $.calling-package";
        }
    }

=head3 X::Method::Private::Unqualified

Thrown when attempting to call a method on something else than C<self> without
fully qualifying the class.

    my class X::Method::Private::Unqualified does X::Comp {
        has $.method;
        method message() {
            "Private method call to $.method must be fully qualified with the package containing the method";
        }
    }


=head3 X::Bind::NativeType

Thrown when trying to bind to a natively typed variable
TODO: inherit from X::Bind?

    my class X::Bind::NativeType does X::Comp {
        has $.name;
        method message() {
            "Cannot bind to natively typed variable '$.name'; use assignment instead'
        }
    }

=head3 X::Attribute::Package

Thrown when trying to declare an attribute inside a package which doesn't
support attributes.

    my class X::Attribute::Package does X::Comp {
        has $.package-kind;
{'fraction_non_alphanumeric': 0.10201002795403115, 'fraction_numerical': 0.005857035097839109, 'mean_word_length': 2.5695280329426673, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 77, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4130657', 'n_tokens_mistral': 6495, 'n_tokens_neox': 6273, 'n_words': 2624}