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