Skip to content

Commit

Permalink
Introduces 4 new classes that provide different behaviours for warnings
Browse files Browse the repository at this point in the history
 CX::Warn::Quietly - do not show warnings, similar to quietly
 CX::Warn::Fatal - immediately throw a warning as an exception
 CX::Warn::Verbose - immediately show warnings with complete backtrace
 CX::Warn::Collect - collect warnings until END, then show with frequencies
 CX::Warn::Debug - show warnings with complete backtrace and debugging info

The behaviour can be set by setting the new dynamic variable $*WARNINGS to
any of these classes (CX::Warn for normal behaviour), with the exception of
CX::Warn::Debug which *must* be instantiated.

The default behaviour of a process can be set with the RAKU_WARNINGS
environment variable, which should have any of "quietly", "fatal", "verbose",
or "collect" specified. No specification defaults to the current behaviour.

Custom behaviour can also be made by creating one's own CX::Warn::Foo class,
which should have a WARN method taking the warning message and a Backtrace
object. That method is then expected to do the right thing, and return Nil.
Such custom classes can also be activated with RAKU_WARNINGS=foo.

I also tried making this a v6.e feature only, but that ran into all sorts of
scoping issues. So until these are better understood, this is now implemented
as a 6.c feature.

The CX::Warn::Debug is special in that it must be instantiated, and as
such cannot be activated from an environment variable.  The .new method
takes any number of *variables* and will show the name of the variable and
its value every time a warning is issued.

    my $foo = 42;
    my $*WARNINGS = CX::Warn::Debug.new($foo);
    warn "bar";

will note:

    $foo = 42
    bar
      in ...
  • Loading branch information
lizmat committed Feb 22, 2023
1 parent a83376c commit a44140c
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 4 deletions.
71 changes: 67 additions & 4 deletions src/core.c/Exception.pm6
Expand Up @@ -435,6 +435,69 @@ my class CX::Warn does X::Control {
warn "Downgrading Rat $nu / $de to Num";
nqp::p6box_n(nqp::div_In($nu,$de))
}
method WARN(str $message, $bt --> Nil) is hidden-from-backtrace {
note "$message\n$bt.first-none-setting-line()";
}
}
my class CX::Warn::Quietly {
method WARN($, $ --> Nil) is hidden-from-backtrace { }
}
my class CX::Warn::Fatal {
method WARN(str $message, $bt --> Nil) is hidden-from-backtrace {
X::AdHoc.new(payload => $message).throw;
}
}
my class CX::Warn::Verbose {
method WARN( str $message, $bt --> Nil) is hidden-from-backtrace {
note "$message\n$bt";
}
}
my class CX::Warn::Collect {
my $lock := Lock.new;
my $messages := nqp::hash;

method WARN(str $message, $bt --> Nil) is hidden-from-backtrace {
my str $key = "$message\n$bt";
$lock.protect: {
nqp::bindkey($messages,$key,
nqp::add_i(nqp::ifnull(nqp::atkey($messages,$key),0),1)
);
}
}

END {
if nqp::elems($messages) {
my %messages := nqp::create(Map);
nqp::bindattr(%messages,Map,'$!storage',$messages);

note .value ~ 'x: ' ~ .key for %messages.sort(-*.value);
}
}
}
my class CX::Warn::Debug {
has @!debugs;

method new(|) {
my $args := nqp::clone(nqp::p6argvmarray);
nqp::shift($args); # lose the invocant

nqp::p6bindattrinvres(nqp::create(self),self,'@!debugs',
nqp::p6bindattrinvres(nqp::create(List),List,'$!reified',$args)
)
}

method WARN(str $message, $bt) {
my str @parts = @!debugs.map: {
my $VAR := .VAR;
$VAR.can("name")
?? $VAR.name ~ ' = ' ~ .raku
!! $_
}
@parts.push: $message;
@parts.push: $bt.Str;

note @parts.join("\n");
}
}
my class CX::Succeed does X::Control {
method message() { "<succeed control exception>" }
Expand Down Expand Up @@ -597,10 +660,10 @@ do {
nqp::if(
nqp::iseq_i($type,nqp::const::CONTROL_WARN),
nqp::stmts(
(my Mu $err := $*ERR),
(my str $msg = nqp::getmessage($ex)),
$err.say(nqp::if(nqp::chars($msg),$msg,"Warning")),
$err.print($backtrace.first-none-setting-line),
(nqp::istype((my $class := $*WARNINGS),Failure)
?? CX::Warn
!! $class
).WARN(nqp::getmessage($ex) || "Warning", $backtrace),
nqp::resume($ex)
)
);
Expand Down
1 change: 1 addition & 0 deletions src/core.c/Int.pm6
@@ -1,3 +1,4 @@

my class Rat { ... }
my class X::Cannot::Capture { ... }
my class X::Numeric::DivideByZero { ... }
Expand Down
8 changes: 8 additions & 0 deletions src/core.c/Process.pm6
Expand Up @@ -93,6 +93,14 @@ Rakudo::Internals.REGISTER-DYNAMIC: '$*HOME', {
PROCESS::<$HOME> := $HOME # bind container so Nil default is kept
}

Rakudo::Internals.REGISTER-DYNAMIC: '$*WARNINGS', {
PROCESS::<$WARNINGS> := (my $what := %*ENV<RAKU_WARNINGS>)
?? nqp::istype((my $lookup := ::("CX::Warn::$what.tc()")),Failure)
?? $lookup.throw
!! $lookup
!! CX::Warn;
}

{
sub fetch($what) {
once if !Rakudo::Internals.IS-WIN && try { qx/LC_MESSAGES=POSIX id/ } -> $id {
Expand Down

0 comments on commit a44140c

Please sign in to comment.