diff --git a/packages/components/src/components/SquiggleErrorAlert.tsx b/packages/components/src/components/SquiggleErrorAlert.tsx index c4b14f17..fee0fca5 100644 --- a/packages/components/src/components/SquiggleErrorAlert.tsx +++ b/packages/components/src/components/SquiggleErrorAlert.tsx @@ -22,7 +22,7 @@ const StackTrace: React.FC = ({ error }) => { const frames = error.getFrameArray(); return frames.length ? (
-
Traceback:
+
Stack trace:
{frames.map((frame, i) => ( diff --git a/packages/squiggle-lang/scripts/lib.mjs b/packages/squiggle-lang/scripts/lib.mjs index 5fc91873..b51bcc7c 100644 --- a/packages/squiggle-lang/scripts/lib.mjs +++ b/packages/squiggle-lang/scripts/lib.mjs @@ -36,6 +36,6 @@ export const run = (src, { output, sampleCount } = {}) => { "Time:", String(time), result.tag === "Error" ? red(result.tag) : green(result.tag), - result.tag === "Error" ? result.value.toStringWithStackTrace() : "" + result.tag === "Error" ? result.value.toStringWithFrameStack() : "" ); }; diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Exception.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Exception.res deleted file mode 100644 index 14db0843..00000000 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Exception.res +++ /dev/null @@ -1,3 +0,0 @@ -// There are switch statement cases in the code which are impossible to reach by design. -// ImpossibleException is a sign of programming error. -exception ImpossibleException(string) diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_FrameStack.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_FrameStack.res index 46640439..02bb1cad 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_FrameStack.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_FrameStack.res @@ -1,3 +1,6 @@ +// This is called "frameStack" and not "callStack", because the last frame in errors is often not a function call. +// A "frame" is a pair of a scope (function or top-level scope, currently stored as a string) and a location inside it. +// See this comment to deconfuse about what a frame is: https://github.com/quantified-uncertainty/squiggle/pull/1172#issuecomment-1264115038 type t = Reducer_T.frameStack module Frame = { @@ -18,9 +21,6 @@ module Frame = { let make = (): t => list{} -@genType -let getTopFrame = (t: t): option => Belt.List.head(t) - let extend = (t: t, name: string, location: option) => t->Belt.List.add({ name: name, diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Lambda.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Lambda.res index 98a272db..b814ea45 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Lambda.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Lambda.res @@ -82,7 +82,7 @@ let doLambdaCallFrom = ( inFunction: Some(t), } - SqError.rethrowWithStacktrace(() => { + SqError.rethrowWithFrameStack(() => { switch t { | FnLambda({body}) => body(args, newContext, reducer) | FnBuiltin({body}) => body(args, newContext, reducer) diff --git a/packages/squiggle-lang/src/rescript/SqError.res b/packages/squiggle-lang/src/rescript/SqError.res index a9950020..dd28fa4b 100644 --- a/packages/squiggle-lang/src/rescript/SqError.res +++ b/packages/squiggle-lang/src/rescript/SqError.res @@ -1,7 +1,8 @@ type location = Reducer_Peggy_Parse.location // Messages don't contain any stack trace information. -// FunctionRegistry functions are allowed to throw MessageExceptions, though, because they will be caught and rewrapped by Reducer_Lambda code +// FunctionRegistry functions are allowed to throw MessageExceptions, though, +// because they will be caught and rewrapped by Reducer_Lambda code. module Message = { @genType.opaque type t = @@ -125,16 +126,16 @@ let getFrameArray = (t: t): array => t.frameStack->Reducer_Fram @genType let toStringWithStackTrace = (t: t) => t->toString ++ if t.frameStack->Reducer_FrameStack.isEmpty { - "\nTraceback:\n" ++ t.frameStack->Reducer_FrameStack.toString + "\nStack trace:\n" ++ t.frameStack->Reducer_FrameStack.toString } else { "" } let throw = (t: t) => t->SqException->raise let throwMessageWithFrameStack = (message: Message.t, frameStack: Reducer_FrameStack.t) => - fromMessageWithFrameStack(message, frameStack)->throw + message->fromMessageWithFrameStack(frameStack)->throw -// this shouldn't be used for most runtime errors - the resulting error would have an empty stacktrace +// this shouldn't be used for most runtime errors - the resulting error would have an empty framestack let fromException = exn => switch exn { | SqException(e) => e @@ -143,14 +144,14 @@ let fromException = exn => | _ => REOther("Unknown exception")->fromMessage } -// converts raw exceptions into exceptions with stacktrace attached +// converts raw exceptions into exceptions with framestack attached // already converted exceptions won't be affected -let rethrowWithStacktrace = (fn: unit => 'a, frameStack: Reducer_FrameStack.t) => { +let rethrowWithFrameStack = (fn: unit => 'a, frameStack: Reducer_FrameStack.t) => { try { fn() } catch { - | SqException(e) => e->throw // exception already has a stacktrace - | Message.MessageException(e) => e->throwMessageWithFrameStack(frameStack) // probably comes from FunctionRegistry, adding stacktrace + | SqException(e) => e->throw // exception already has a framestack + | Message.MessageException(e) => e->throwMessageWithFrameStack(frameStack) // probably comes from FunctionRegistry, adding framestack | Js.Exn.Error(obj) => REJavaScriptExn(obj->Js.Exn.message, obj->Js.Exn.name)->throwMessageWithFrameStack(frameStack) | _ => REOther("Unknown exception")->throwMessageWithFrameStack(frameStack)