nixfiles/libs/core/lib/debug/default.nix
Sebastian Walz 860d31cee1
Tohu vaBohu
2023-04-21 00:22:52 +02:00

359 lines
12 KiB
Nix

{
ansi, context, debug, error, intrinsics, library, list, set, string, type,
logLevel ? debug.levels.info,
fatalLevel ? debug.levels.error,
...
}:
let
Body
= string
|| [ string ]
|| {
# depth: integer? = null,
# fatal: bool = false,
# text: ([ string ] | string)? = [],
# when: bool = true,
# show: bool = false,
# data: any = null,
}
|| null;
Debug
= type "Debug"
{
from#:
# { colour: string, level: integer }
# -> { body: [ string ]; fatal: bool; nice: bool; show: bool; showType: bool; when: bool; }
# -> Debug
= { active, colour, fatal, level, source, ... } @ self:
{
body,
hex ? false,
maxDepth ? null,
nice ? false,
show ? false,
showType ? true,
trace ? false,
when ? true
}:
let
body' = list.map string.expect body;
fail
= if level == 0
then
error.abort
else
error.panic;
message
= let
format = context.formatAbsolute';
in
[ "[${self.getVariant}] {${format source} @ ${context.formatFileName source}}" ] ++ body';
toDebug
= isFatal:
from:
Debug.instanciateAs (self.getVariant)
{
inherit from isFatal;
body = body';
__functor = _: from;
__toString
= { body, ... }:
intrinsics.trace (string.concatLines body)
error.abort "???";
};
in
if when
&& ( active || fatal )
then
if fatal
then
toDebug true
(
intrinsics.trace
(ansiFormat colour message)
(fail "See Error Message Above")
)
else if show
then
toDebug false
(
value:
let
additionalLines
= string.splitLines
(
string.toTrace
{ inherit hex maxDepth nice showType trace; }
value
);
in
intrinsics.trace
(ansiFormat colour (message ++ additionalLines))
value
)
else
toDebug false
(
intrinsics.trace
(ansiFormat colour message)
)
else
toDebug false (x: x);
};
DebugLevel
= let
print
= let
toLines
= text:
string.splitLines (string.trim text);
toLines'
= text:
type.matchPrimitiveOrPanic text
{
null = [ ];
list = text;
string = toLines text;
};
fromList
= lines:
{
body = list.map string.expect lines;
};
fromSet
= {
data ? null,
hex ? false,
maxDepth ? null,
nice ? false,
show ? false,
showType ? true,
text ? [ ],
trace ? false,
when ? true,
} @ this:
{
inherit hex maxDepth nice show showType trace when;
body
= ( toLines' text )
++ (
if this ? data
then
string.splitLines
(
string.toTrace
{ inherit hex maxDepth nice showType trace; }
data
)
else
[ ]
);
};
in
self:
source:
body:
Debug
(
self
// {
source = self.source source;
}
)
(
type.matchPrimitiveOrPanic body
{
null = { body = [ ]; };
list = fromList body;
set = fromSet body;
string = { body = toLines body; };
}
);
in
type "DebugLevel"
{
from
= variant:
{ colour, level }:
DebugLevel.instanciateAs variant
{
inherit colour level print;
__functor = print;
active = level <= logLevel.level;
fatal = level <= fatalLevel.level;
message = null;
};
};
Source
= string
|| [ string ]
|| null;
ansiFormat
= let
backspaces = "${string.repeat string.char.backspace 7}";
in
color:
lines:
let
concatLines = string.concatMapped (line: "\n${color}| ${line}");
head = list.head lines;
tail = concatLines (list.tail lines);
in
"${backspaces}${color}${ansi.bold}${head}${ansi.reset}${tail}${ansi.reset}";
minimal
= set.mapValues
(
logger:
source:
body:
if body.when or true
then
(
if body ? data
then
intrinsics.trace body.data
else
(x: x)
)
logger (body.text or body)
else
(x: x)
)
{
dafuq = message: error.abort "[dafuq] ${string.toString message}";
panic = message: error.throw "[panic] ${string.toString message}";
error = message: intrinsics.trace "[error] ${string.toString message}";
warn = message: intrinsics.trace "[warn] ${string.toString message}";
info = message: intrinsics.trace "[info] ${string.toString message}";
debug = message: intrinsics.trace "[debug] ${string.toString message}";
trace = message: intrinsics.trace "[trace] ${string.toString message}";
silent = message: x: x;
};
levels
= let
inherit(ansi) foreground;
in
{
dafuq = { colour = foreground.brightMagenta; level = 0; }; # This should not even happen.
panic = { colour = foreground.red; level = 1; }; # You will not get a result.
error = { colour = foreground.brightRed; level = 2; }; # You will not get, what you expect.
warn = { colour = foreground.brightYellow; level = 3; }; # You might not get, what you expect.
info = { colour = foreground.brightGreen; level = 4; }; # Usefull information, which are fine.
debug = { colour = foreground.brightCyan; level = 5; }; # Specific Information.
trace = { colour = foreground.lightGrey; level = 6; }; # Single code paths.
silent = { colour = foreground.white; level = 7; }; # Silent.
};
printers = set.map DebugLevel levels;
updatePrinters
= self:
{
debug ? null,
source,
...
}:
(
set.map
(
name:
method:
if DebugLevel.isInstanceOf method
then
method
// {
inherit source;
}
// (
if debug != null
then
{
active = method.level <= (debug.logLevel or levels.info).level or levels.${debug.logLevel}.level;
fatal = method.level <= (debug.fatalLevel or levels.error).level or levels.${debug.fatalLevel}.level;
}
else
{}
)
else
method
)
self
)
// { inherit source; };
withFunction
= debugLevel:
call:
debugLevel
// {
inherit call;
__functor
= { call, print, ... } @ self:
source:
call
(
self
// {
__functor = _: print self source;
}
);
};
withMessage
= debugLevel:
message:
debugLevel
// {
inherit message;
__functor
= { message, print, ... } @ self:
source:
print self source message;
};
in
library.NeedInitialisation
(
{ ... } @ self:
{ ... } @ args:
updatePrinters self args
)
(
printers
// {
__functor
= { ... } @ self:
source:
updatePrinters self { source = self.source source; };
inherit Debug DebugLevel levels;
deprecated
= withFunction
printers.warn
(
{ ... } @ print:
other:
print
(
if other ? source
then
let
format = context.formatAbsolute';
in
"Deprecated: Use ${format other.source} instead!"
else
"Deprecated!"
)
other
);
unimplemented = withMessage printers.panic "Not implemented yet, please be patient!";
unreachable = withMessage printers.dafuq "Unreachableor at least should not have been o.O!";
}
)