359 lines
12 KiB
Nix
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 "Unreachable…or at least should not have been o.O!";
|
|
}
|
|
)
|