From 0c05e24143f2823802aeec05a97178911efdef9a Mon Sep 17 00:00:00 2001 From: uri Date: Sun, 24 Sep 2023 15:13:52 +0300 Subject: [PATCH] improve trace utils --- src/composition.ts | 29 ++++------------------------- src/debug.ts | 22 +++++++++++++--------- src/trace.ts | 22 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 src/trace.ts diff --git a/src/composition.ts b/src/composition.ts index 3acf822..56de61f 100644 --- a/src/composition.ts +++ b/src/composition.ts @@ -1,8 +1,9 @@ -import { last, reverse } from "./array.ts"; +import { reverse } from "./array.ts"; import { AnyAsync, Func, Last, ReturnTypeUnwrapped } from "./typing.ts"; import { not } from "./operator.ts"; import { reduce } from "./reduce.ts"; +import { currentLocation } from "./trace.ts"; type UnaryFn = (a: A) => R; type Arg = Parameters[0]; @@ -34,35 +35,13 @@ const pipeWithoutStack = ( Fs >; -interface StackFrame { - file: string; - line: number; - column: number; -} - -const frameToString = ({ line, file, column }: StackFrame) => - `${file}:${line}:${column}`; - -const parseStackLine = (stackLine: string): null | StackFrame => { - const matches = RegExp(/\s+at\s+(.+\s)?\(?(.+):(\d+):(\d+)\)?/).exec( - stackLine, - ); - if (!matches) return null; - const [, , file, line, column] = matches; - return { file, line: parseInt(line), column: parseInt(column) }; -}; - -const parseStackTrace = (trace: string) => - parseStackLine(last(trace.split("\n"))); - const errorBoundry = (f: F) => { - const err = new Error().stack as string; + const codeLocation = currentLocation(); return ((...x) => { try { return f(...x); } catch (e) { - const lastStackCall = parseStackTrace(err); - if (lastStackCall) console.error(frameToString(lastStackCall)); + console.error(codeLocation); throw e; } }) as F; diff --git a/src/debug.ts b/src/debug.ts index 8622152..1614be3 100644 --- a/src/debug.ts +++ b/src/debug.ts @@ -1,37 +1,41 @@ import { Func, ReturnTypeUnwrapped } from "./typing.ts"; +import { currentLocation } from "./trace.ts"; import { sideEffect } from "./composition.ts"; export const sideLog = (x: T) => { - console.log(x); + console.log(currentLocation(), x); return x; }; -export const sideLogAfter = (f: F): F => - ((...xs) => { +export const sideLogAfter = (f: F): F => { + const codeLocation = currentLocation(); + return ((...xs) => { const output = f(...xs); if (output instanceof Promise) { return output.then((x) => { - console.log(x); + console.log(codeLocation, x); return x; }) as ReturnType; } - console.log(output); + console.log(codeLocation, output); return output; }) as F; +}; -export const sideLogBefore = (f: F): F => - ((...xs) => { - console.log(xs.length === 1 ? xs[0] : xs); +export const sideLogBefore = (f: F): F => { + const codeLocation = currentLocation(); + return ((...xs) => { + console.log(codeLocation, xs.length === 1 ? xs[0] : xs); const output = f(...xs); if (output instanceof Promise) { return output.then((x) => { return x; }) as ReturnType; } - console.log(output); return output; }) as F; +}; export const sideLogTable = sideEffect(console.table); // deno-lint-ignore no-explicit-any diff --git a/src/trace.ts b/src/trace.ts new file mode 100644 index 0000000..23c4028 --- /dev/null +++ b/src/trace.ts @@ -0,0 +1,22 @@ +interface StackFrame { + file: string; + line: number; + column: number; +} +const frameToString = ({ line, file, column }: StackFrame) => + `${file}:${line}:${column}`; + +const parseStackLine = (stackLine: string): StackFrame => { + const matches = RegExp(/\s+at\s+(.+\s)?\(?(.+):(\d+):(\d+)\)?/).exec( + stackLine, + ); + if (!matches) throw new Error("could not figure out stack line"); + const [, , file, line, column] = matches; + return { file, line: parseInt(line), column: parseInt(column) }; +}; + +const parseStackTrace = (trace: string, picker: (lines: string[]) => string) => + parseStackLine(picker(trace.split("\n"))); + +export const currentLocation = () => + frameToString(parseStackTrace(new Error().stack as string, (x) => x[3]));