Debug

The Debug module provides utilities for debugging Kit programs. These functions help you trace values through pipelines, mark unimplemented code, and get source location information.

Development Only

Debug functions are intended for development and debugging purposes. Functions like Debug.todo and Debug.unreachable will panic at runtime if executed.

Tracing

Debug.trace
String -> a -> a
Prints a message along with the given value to stderr, then returns the value unchanged. Useful for debugging pipelines without breaking the data flow.
# Simple tracing
result = Debug.trace "value is" 42
# Prints: [TRACE] value is: 42
# result = 42

# Tracing in a pipeline
numbers = [1, 2, 3, 4, 5]
result = numbers
    |> filter (fn(x) => x > 2)
    |> Debug.trace "after filter"
    |> map (fn(x) => x * 2)
    |> Debug.trace "after map"
# Prints:
# [TRACE] after filter: [3, 4, 5]
# [TRACE] after map: [6, 8, 10]

Side Effects

Debug.tap
(a -> ()) -> a -> a
Applies a function to the value for its side effects, then returns the value unchanged. Useful for logging, assertions, or any side-effect in the middle of a pipeline.
# Custom logging in a pipeline
log-length = fn(xs) => println "Length: ${length xs}"

result = [1, 2, 3]
    |> map (fn(x) => x * 2)
    |> Debug.tap log-length
    |> filter (fn(x) => x > 2)
# Prints: Length: 3
# result = [4, 6]

# Using with an inline function
data = {name: "Alice", age: 30}
    |> Debug.tap (fn(r) => println "Processing: ${r.name}")
# Prints: Processing: Alice

Placeholders

Debug.todo
String -> a
Marks code as unimplemented. When executed, it will panic with the given message. Useful as a placeholder during development to indicate incomplete code paths.
# Placeholder for unimplemented functionality
process-data = fn(data) =>
    match data.format
        | "json" -> parse-json data.content
        | "xml" -> Debug.todo "XML parsing not yet implemented"
        | "csv" -> Debug.todo "CSV parsing coming soon"
        | _ -> Debug.todo "Unknown format"

# If xml format is passed:
# PANIC: TODO: XML parsing not yet implemented
Debug.unreachable
String -> a
Marks code that should never be reached. When executed, it will panic with the given message. Useful for exhaustive pattern matching where you know certain cases are impossible.
# Marking impossible cases
get-sign = fn(n) =>
    match compare n 0
        | Lt -> "negative"
        | Eq -> "zero"
        | Gt -> "positive"

# Validating invariants
safe-head = fn(xs) =>
    if is-empty? xs
        then Debug.unreachable "safe-head called on empty list"
        else head xs

# If unreachable code is executed:
# PANIC: UNREACHABLE: safe-head called on empty list

Source Info

Debug.source-location
a
Returns source location information including the file path, line number, and column number where it is called. Returns a record with file, line, and column fields.
# Get current source location
loc = Debug.source-location
println "File: ${loc.file}"
println "Line: ${loc.line}"
println "Column: ${loc.column}"
# Output:
# File: /path/to/script.kit
# Line: 5
# Column: 7

# Useful for custom error messages
my-assert = fn(condition, message) =>
    if not condition
        loc = Debug.source-location
        panic "Assertion failed at ${loc.file}:${loc.line} - ${message}"