1
0
mirror of https://github.com/janet-lang/janet synced 2025-02-23 11:40:01 +00:00

More work on improving stacktraces slightly.

Add extra information about when we change fibers. The janet
stack is really a spaghetti stack, where each fiber represents
a group of stack frames as well as a place where we can longjmp to. It
is therefor useful information for the programmer to know where each
stack frame is.

However, an argument could be made that this clutters the stackframe
and is more of a hindrance than a help.
This commit is contained in:
Calvin Rose 2024-05-26 08:45:38 -05:00
parent cb529bbd63
commit 1844beecc3
4 changed files with 48 additions and 40 deletions

View File

@ -2405,6 +2405,33 @@
(defdyn *err-color*
"Whether or not to turn on error coloring in stacktraces and other error messages.")
(defdyn *err-line-col*
"Whether or not to print the line of source code that caused an error.")
(defn- print-line-col
``Print the source code at a line, column in a source file. If unable to open
the file, prints nothing.``
[where line col]
(if-not line (break))
(unless (string? where) (break))
(unless (dyn *err-line-col*) (break))
(def ec (dyn *err-color*))
(when-with [f (file/open where :r)]
(def source-code (file/read f :all))
(var index 0)
(repeat (dec line)
(if-not index (break))
(set index (string/find "\n" source-code index))
(if index (++ index)))
(when index
(def line-end (string/find "\n" source-code index))
(def s (if ec "\e[31m"))
(def e (if ec "\e[0m"))
(eprint s " " (string/slice source-code index line-end) e)
(when col
(+= index col)
(eprint s (string/repeat " " (inc col)) "^" e)))))
(defn bad-parse
"Default handler for a parse error."
[p where]
@ -2419,29 +2446,10 @@
col
": parse error: "
(:error p)
(if ec "\e[0m" ""))
(if ec "\e[0m"))
(print-line-col where line col)
(eflush))
(defn- print-line-col
``Print the source code at a line, column in a source file. If unable to open
the file, prints nothing.``
[where line col]
(if-not line (break))
(unless (string? where) (break))
(when-with [f (file/open where :r)]
(def source-code (file/read f :all))
(var index 0)
(repeat (dec line)
(if-not index (break))
(set index (string/find "\n" source-code index))
(if index (++ index)))
(when index
(def line-end (string/find "\n" source-code index))
(eprint " " (string/slice source-code index line-end))
(when col
(+= index col)
(eprint (string/repeat " " (inc col)) "^")))))
(defn warn-compile
"Default handler for a compile warning."
[msg level where &opt line col]
@ -2454,10 +2462,8 @@
":"
col
": compile warning (" level "): ")
(eprint msg)
(when ec
(print-line-col where line col)
(eprin "\e[0m"))
(eprint msg (if ec "\e[0m"))
(print-line-col where line col)
(eflush))
(defn bad-compile
@ -2474,10 +2480,8 @@
": compile error: ")
(if macrof
(debug/stacktrace macrof msg "")
(eprint msg))
(when ec
(print-line-col where line col)
(eprin "\e[0m"))
(eprint msg (if ec "\e[0m")))
(print-line-col where line col)
(eflush))
(defn curenv
@ -3049,7 +3053,7 @@
``A table of loading method names to loading functions.
This table lets `require` and `import` load many different kinds
of files as modules.``
@{:native (fn native-loader [path &] (native path (make-env)))
@{:native (fn native-loader [path &] (native path ((dyn *module-make-env* make-env))))
:source (fn source-loader [path args]
(def ml (dyn *module-loading* module/loading))
(put ml path true)
@ -3996,18 +4000,19 @@
(compwhen (dyn 'os/stat)
(defn- bundle-dir
[&opt bundle-name]
(string (dyn *syspath*) "/bundle/" bundle-name))
(defn- bundle-file
[bundle-name filename]
(string (dyn *syspath*) "/bundle/" bundle-name "/" filename))
(defn- bundle-rpath
[path]
(string/replace-all "\\" "/" (os/realpath path)))
(defn- bundle-dir
[&opt bundle-name]
(string (bundle-rpath (dyn *syspath*)) "/bundle/" bundle-name))
(defn- bundle-file
[bundle-name filename]
(string (bundle-rpath (dyn *syspath*)) "/bundle/" bundle-name "/" filename))
(defn- get-manifest-filename
[bundle-name]
(bundle-file bundle-name "manifest.jdn"))

View File

@ -1056,7 +1056,7 @@ JanetCompileResult janet_compile_lint(Janet source,
if (c.result.status == JANET_COMPILE_OK) {
JanetFuncDef *def = janetc_pop_funcdef(&c);
def->name = janet_cstring("_thunk");
def->name = janet_cstring("thunk");
janet_def_addflags(def);
c.result.funcdef = def;
} else {

View File

@ -164,7 +164,7 @@ void janet_stacktrace_ext(JanetFiber *fiber, Janet err, const char *prefix) {
}
}
if (frame->flags & JANET_STACKFRAME_TAILCALL)
janet_eprintf(" (tailcall)");
janet_eprintf(" (tail call)");
if (frame->func && frame->pc) {
int32_t off = (int32_t)(frame->pc - def->bytecode);
if (def->sourcemap) {
@ -180,6 +180,9 @@ void janet_stacktrace_ext(JanetFiber *fiber, Janet err, const char *prefix) {
}
}
janet_eprintf("\n");
if (i <= 0 && fi > 0) { /* no next frame, first stack frame in fiber. First fiber is trivial. */
janet_eprintf(" in parent fiber\n");
}
}
}

View File

@ -318,7 +318,7 @@ static Janet janet_binop_call(const char *lmethod, const char *rmethod, Janet lh
Janet lr = janet_method_lookup(rhs, rmethod);
Janet argv[2] = { rhs, lhs };
if (janet_checktype(lr, JANET_NIL)) {
janet_panicf("could not find method :%s for %v, or :%s for %v",
janet_panicf("could not find method :%s for %v or :%s for %v",
lmethod, lhs,
rmethod, rhs);
}