debug.oak
← Standard library
See on GitHub ↗
{
println: stdPrintln
default: default
toHex: toHex
map: map
some: some
every: every
values: values
reduce: reduce
entries: entries
} := import('std')
{
letter?: letter?
digit?: digit?
join: join
padStart: padStart
} := import('str')
{
sort!: sort!
} := import('sort')
{
format: format
} := import('fmt')
fn _validIdent?(s) s |> every(fn(c, i) if i {
0 -> letter?(c) | c = '_' | c = '?' | c = '!'
_ -> letter?(c) | digit?(c) | c = '_' | c = '?' | c = '!'
})
fn _numeral?(s) s |> every(digit?)
fn _primitive?(x) if type(x) {
:null, :empty, :bool, :int, :float, :string, :atom
:function -> true
_ -> false
}
fn inspect(x, options) {
{
indent: indentUnit
depth: depth
maxLine: maxLine
maxList: maxList
maxObject: maxObject
} := options |> default({})
indentUnit := indentUnit |> default(' ')
depth := depth |> default(-1)
maxLine := maxLine |> default(80)
maxList := maxList |> default(16)
maxObject := maxObject |> default(3)
fn inspectObjectKey(key) if {
_validIdent?(key), _numeral?(key) -> key
_ -> inspectLine(key, -1)
}
fn inspectAbbreviated(x) if type(x) {
:list -> '[ {{0}} items... ]' |> format(len(x))
:object -> '{ {{0}} entries... }' |> format(len(x))
}
fn inspectLine(x, depth) if type(x) {
:null, :empty, :bool, :int, :float -> string(x)
:string -> '\'' + (x |> map(fn(c) if c {
'\\' -> '\\\\'
'\'' -> '\\\''
'\n' -> '\\n'
'\r' -> '\\r'
'\f' -> '\\f'
'\t' -> '\\t'
_ -> if {
codepoint(c) < 32
codepoint(c) > 126 -> '\\x' << toHex(codepoint(c)) |> padStart(2, '0')
_ -> c
}
})) + '\''
:atom -> if _validIdent?(payload := string(x)) {
true -> ':' + string(payload)
_ -> 'atom({{0}})' |> format(inspectLine(payload))
}
:function -> 'fn { ... }'
:list -> '[' + (x |> map(fn(y) inspectLine(y, depth)) |> join(', ')) + ']'
:object -> if len(x) {
0 -> '{}'
_ -> '{ ' + {
entries(x) |>
sort!(0) |>
map(fn(entry) inspectObjectKey(entry.0) + ': ' + inspectLine(entry.1, depth)) |>
join(', ')
} + ' }'
}
}
fn inspectMulti(x, indent, depth) {
innerIndent := indent + indentUnit
if type(x) {
:list -> x |> reduce('[', fn(lines, item) {
lines << '\n' + innerIndent + inspectAny(item, innerIndent, depth)
}) << '\n' + indent + ']'
:object -> entries(x) |> sort!(0) |> reduce('{', fn(lines, entry) {
lines << '\n' + innerIndent + inspectObjectKey(entry.0) + ': ' +
inspectAny(entry.1, innerIndent, depth)
}) << '\n' + indent + '}'
}
}
fn inspectAny(x, indent, depth) {
line := inspectLine(x, depth - 1)
overflows? := len(line) + len(indent) > maxLine
if {
_primitive?(x) -> line
depth = 0 -> inspectAbbreviated(x)
overflows? -> inspectMulti(x, indent, depth - 1)
type(x) = :list -> if {
len(x) > maxList
x |> some(fn(y) !_primitive?(y)) -> inspectMulti(x, indent, depth - 1)
_ -> line
}
type(x) = :object -> if {
len(x) > maxObject
x |> values() |> some(fn(y) !_primitive?(y)) -> inspectMulti(x, indent, depth - 1)
_ -> line
}
}
}
inspectAny(x, '', depth)
}
fn println(x, options) stdPrintln(inspect(x, options))