-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add debug
built-in
#1267
Add debug
built-in
#1267
Conversation
The `debug` function is a utility designed to aid in debugging specifications by allowing the spec developer to print out a contextual message while executing a specification, whether in a run or in a test, along with a formatted representation of a value. This can be useful when trying to understand the state of variables at specific points during the spec execution or while tracking down issues. The `debug` function has the following signature: ``` def debug(header: str, value: a) -> a ``` The `debug` function prints both header and the value on the same line, preceded by a `>` character, and then returns the given value, which makes it easy to debug nested expressions without having the extract them into a variable first. Example usage in the REPL: ``` >>> debug("a number:", 42) > a number: 42 42 >>> debug("a record:", { foo: 32, bar: true }) > a record: { bar: true, foo: 32 } { bar: true, foo: 32 } >>> debug("large record:", largeRecord) > large record: { hello: { world: { foo: { bar: { baz: 42 }, toto: { tata: { tutu: "Hello, World" } } } } } } { hello: { world: { foo: { bar: { baz: 42 }, toto: { tata: { tutu: "Hello, World" } } } } } } >>> if (a * debug("nested", a + b) == 10) true else false > nested 5 true ```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love it! Thanks for getting this done, I'm sure it will be super useful.
I'd do three things before merging:
- Adding an entry to
CHANGELOG.md
- Adding an integration test to
io-cli-tests.md
(i.e. evaluating a quint REPL shell invocation and checking that the debug line is sent to STDOUT) - Add an entry to
builtin.qnt
fordebug
with a docstring (and runningnpm run api-docs
to generate a Markdown). This is used for showing overlay documentation in the IDEs.
If you are interested in doing any of those, please go ahead! Otherwise, I can pick it up 😄
Thanks a lot for the pointers! I've done all three things, let me know if you want me to add more tests or expand on the documentation. |
I wonder if it would make sense to switch the arguments around, to allow for writing the following in method-call style: >>> 42.debug("value is")
> value is 42 The downside with this order is that when used as a function it now reads less well imho: >>> debug(42, "value is")
> value is 42 I don't feel strongly either way, so will defer to you on that if you don't mind :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this feature! But I have my doubts about the operator name debug
:
- It only works for REPL. We add the prefix
q::
to all internal or repl-specific operators. - The name
misleading
is a bit misleading. It's not really debugging anything. Quick alternatives fromgdb
:print
,inspect
,trace
. Of course, I would prefer them to have the prefixq::
.
this.applyFun(app.id, 2, (msg, value) => { | ||
let columns = terminalWidth() | ||
let valuePretty = format(columns, 0, prettyQuintEx(value.toQuintEx(zerog))) | ||
console.log('>', msg.toStr(), valuePretty.toString()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though it works this way. Would not it be better to print the message via CompilerErrorTracker? We could probably introduce a debug/info level for this purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest leaving this as is for now, and replacing it with the proper logging lib along with all our other console prints when we get around to that. This is not a compilation error, so I wouldn't want to put it in the tracker for that.
Oh I wasn't aware of that. I'll see if I can figure out how to do that.
Good point! If you ask me I would go with a) to avoid overloading the "trace" term too much which could be confusing/misleading |
I also like |
Yeah I meant |
Thanks for the useful addition! We'll need to make sure we strip this out of the IR before sending to alache I think, but we can do that in a followup. |
I personally like |
How should we proceed here? Should we go with |
I would vote for proceeding like that. |
I'd also prefer |
@romac do you need help in getting this one merged? |
I was just waiting for the Quint team to decide on the final name, but if/once that's done I am happy to do the renaming if needed and prefix it with the |
I merged Shall we keep the name or do I rename it to something else? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I talked to the team and we are going with q::debug
! Thanks for the patience and for all the updates.
Thanks for helping me see this PR through! |
Closes: #1266
The
debug
built-in is a utility for aiding in debugging specifications by allowing the spec developer to print out a contextual message while executing a specification, whether in a run or in a test, along with a formatted representation of a value.This can be useful when trying to understand the state of variables at specific points during the spec execution or while tracking down issues.
The
debug
function has the following signature:The
debug
function prints both header and the value on the same line, preceded by a>
character, and then returns the given value, which makes it easy to debug nested expressions without having the extract them into a variable first.Example usage in the REPL:
CHANGELOG.md
for any new functionalityREADME.md
updated for any listed functionality