silo:std.error-report

Source src/silo:std.error-report

1##! ErrorReport — a pretty-printable error-chain formatter.
2##!
3##! The record carries a `Str` message, an optional cause
4##! (`Option ErrorReport`), and a `(Vec Str)` backtrace placeholder.
5##! `.pretty` renders the chain into a multi-line `Str`. A `Display`
6##! impl lands once the `FmtSpec`-aware format pipeline widens.
7##!
8##! Construction goes through the free fns `error-report` and
9##! `error-report-with-cause`, both of which take a pre-formatted
10##! message `Str`; the existential `Error`-trait constructor arrives
11##! later. Backtrace frames will tighten from `Str` to a structured
12##! `Frame` type alongside the panic-payload rework.
13
14:use
15  :open core Bool AnyInt Option None Some Str Vec
16  :open traits Default Add Eq
17:end
18
19# si[impl stdlib.error-report.type]
20##(
21`ErrorReport` wraps a message string, an optional wrapped cause (the next
22layer of the error chain), and an optional backtrace represented as a
23`(Vec Str)` of pre-rendered frame descriptions. The record is value-typed;
24every modifier returns a fresh copy.
25
26Spec shape uses `Error` (existential) + `(Option (Seq Frame _))`; this
27partial uses `Str` + `(Vec Str)` pending the `Error` trait and `Frame`
28types.
29)#
30:record(pub) ErrorReport
31  .message   Str
32  .cause     (Option ErrorReport)
33  .backtrace (Vec Str)
34:end
35
36# si[impl stdlib.error-report.new]
37## Free-fn constructor: build an `ErrorReport` carrying just a message. The
38## cause is `None` and the backtrace is an empty `(Vec Str)`.
39:fn(pub) error-report ( Str -> ErrorReport )
40  None (Vec .default) ErrorReport
41:end
42
43## Free-fn constructor: build an `ErrorReport` with the given message and
44## wrap an existing report as its cause. The backtrace starts empty.
45:fn(pub) error-report-with-cause ( Str ErrorReport -> ErrorReport )
46  Some (Vec .default) ErrorReport
47:end
48
49# Internal helper: walk the `(Option ErrorReport)` cause chain and append
50# each layer on its own indented line.
51:fn pretty-chain ( Str (Option ErrorReport) -> Str )
52  :match
53    | None     =>
54    | Some nxt =>
55        "\ncaused by: " + nxt .message +
56        nxt .cause pretty-chain
57  :end
58:end
59
60# Internal helper: walk a backtrace `(Vec Str)` and append each frame on
61# its own indented line. Empty backtraces are passed through unchanged.
62# Open-codes the loop rather than using `.fold` so we don't depend on the
63# Foldable trait plumbing being visible across the stdlib boundary.
64:fn pretty-backtrace ( Str (Vec Str) -> Str )
65  pop-> frames
66  frames .len 0 = :if :ret :end
67  "\nbacktrace:" +
68  0 pop-> i
69  :loop
70    i frames .len = :if :break :end
71    "\n  at " + i frames .get +
72    i 1 + pop-> i
73  :end
74:end
75
76# si[impl stdlib.error-report.with-backtrace]
77# si[impl stdlib.error-report.pretty]
78:impl ErrorReport
79  ## Accessor: return the top-level message. Equivalent to the `.message`
80  ## record-field accessor, provided as an explicit method so callers can
81  ## treat the type as opaque.
82  .message ( ErrorReport -> Str )
83    .message ;
84
85  ## Accessor: return the wrapped cause, if any.
86  .cause ( ErrorReport -> (Option ErrorReport) )
87    .cause ;
88
89  ## Attach a backtrace (sequence of pre-rendered frame strings). Replaces
90  ## any previously attached backtrace.
91  .with-backtrace ( ErrorReport (Vec Str) -> ErrorReport )
92    swap .backtrace<- ;
93
94  ## Render a multi-line pretty-printed representation of the error chain.
95  ## The top-level message appears on its own line; each wrapped cause is
96  ## emitted on a subsequent line prefixed with `"caused by: "`. When a
97  ## non-empty backtrace is attached, it is appended after the chain, one
98  ## frame per line, prefixed with `"  at "`.
99  .pretty ( ErrorReport -> Str )
100    pop-> rpt
101    # Start with the top-level message.
102    rpt .message
103    # Walk the cause chain, appending each layer on its own line.
104    rpt .cause pretty-chain
105    # Append the backtrace, if any.
106    rpt .backtrace pretty-backtrace ;
107:end