-
Notifications
You must be signed in to change notification settings - Fork 447
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 a builtin trace function. #487
Conversation
Prints the first argument to std err with line number Returns the second argument which is expected to be an object.
@sparkprime
I have not added documentation or error tests yet. As it stands the trace function expects an obj Maybe we should implement a trace function that can return whatever its second argument is ? |
By the way, are the appveyor tests operational ?
|
Thank you very much for contributing! Don't worry about appveyor tests. There were some problems going on for a while. |
Yes, I think it should allow any value to be passed there. It's a bit confusing otherwise. Especially since it's intended for debugging, so the user may not know about the type of the value passed to it. |
core/desugarer.cpp
Outdated
@@ -63,6 +63,7 @@ BuiltinDecl jsonnet_builtin_decl(unsigned long builtin) | |||
case 24: return {U"primitiveEquals", {U"a", U"b"}}; | |||
case 25: return {U"native", {U"name"}}; | |||
case 26: return {U"md5", {U"str"}}; | |||
case 27: return {U"trace", {U"str", U"obj"}}; |
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.
Once the trace call can accept any type as the second parameter, what to call this here ? Right now it is obj.
Does it actually matter except what is printed in an error message ?
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.
It doesn't really matter. rest
might work.
Another option here is to return true
, in which case this can be used as in if std.trace("foo") then ...
or just assert std.trace("foo"); ...
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 do not understand what you suggest.
First do you want to use "rest" like
case 27: return {U"trace", {U"str", U"rest"}};
?
Secondly, how would the return true look like ?
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.
These are just giving the parameter names on the Jsonnet side, which matter because of being able to do std.md5(str="foo"), and otherwise aren't specified anywhere. There is no equivalent for the return value, I just mentioned it because I was thinking of ways to avoid the 2nd param, which might get a bit annoying because of the need to put a ) some distance away, when you insert the std.trace. However my suggestions are also a bit obtuse, since this really has nothing to do with assert or conditionals :)
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.
case 27: return {U"trace", {U"str", U"rest"}};
would be fine
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.
👍 for case 27: return {U"trace", {U"str", U"rest"}};
. Functions that provide alternative semantics can be later implemented as regular jsonnet functions (non-builtin).
core/state.h
Outdated
STRING = 0x13 | ||
STRING = 0x13, | ||
|
||
ANY = 0xFF00 |
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 am not sure whether it is acceptable to add this ENUM. I am open to suggestions though.
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.
It is not necessary.
As @sparkprime mentioned in #130 the trace reveals implementation details. For example
Prints
The trace messages are interleaved. |
If all this looks reasonable I will also add documentation and then this can be merged. |
core/vm.cpp
Outdated
@@ -1290,6 +1293,33 @@ class Interpreter { | |||
return nullptr; | |||
} | |||
|
|||
const AST *builtinTrace(const LocationRange &loc, const std::vector<Value> &args) | |||
{ | |||
validateBuiltinArgs(loc, "trace", args, {Value::STRING, Value::ANY}); |
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.
Just don't call this and you don't need to define ANY.
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.
Inline the bits of it that you do need, though. There must be some examples of this.
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.
builtinLength is an example
core/vm.cpp
Outdated
std::cerr << "TRACE: " << loc.file << ":" << loc.begin.line << " " << str | ||
<< std::endl; | ||
|
||
auto t = args[1].t; |
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.
you should be able to do scratch = args[1];
After we resolve the last questions about how to write |
As far as I can tell, this is ready to merge FYI @sparkprime @sbarzowski |
I have just seen the go port |
doc/docs/stdlib.html
Outdated
|
||
<h4 id="trace">std.trace(str, rest)</h4> | ||
|
||
<p> <code>trace</code> outputs the string to std::cerr in its first argument, before |
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.
s/std:cerr/stderr/, std::cerr is a C++ concept.
I would phrase it this way:
<code>trace</code> outputs the given string <code>str</code> to stderr and returns <code>rest</code> as the result.
doc/docs/stdlib.html
Outdated
else | ||
std.trace('cond is false returning ' + std.toString(in2), in2); | ||
}</code></p> | ||
|
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 would extend the example with a call to conditionalReturn and then we could include example output as well.
<h3 id="Debugging">Debugging</h3> | ||
|
||
<h4 id="trace">std.trace(str, rest)</h4> | ||
|
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.
Maybe we can add a note about versions of jsonnet in which it is available. In the past, users were confused when they tried to call new functions in older versions of jsonnet.
<em>Available since version UNRELEASED.</em>
would work I think.
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 was hoping you could cut a release after this merges. Can I call it 0.10.1 ?
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.
@sparkprime decides about these things.
It would probably be 0.11 since new features were added. We would also need to add documentation for #481 before. I'm all for frequent releases, but the current procedure for new releases is a bit tedious AFAIK.
It should be quite easy. Just a few lines need to be added to this file: https://github.com/google/go-jsonnet/blob/master/builtins.go. The only non-obvious part is extracting the location - and for that |
About the go port, Is there a document describing the reasoning behind it ? I would be very interested to know what drove you to re-implement jsonnet in go. Also I recommend to redirect new features to go-jsonnet and stop accepting PRs to C++ except bugfixes from now on. Double committing can be really strenuous. |
A few reasons:
@sparkprime could probably come up with more things.
It depends. There are things that are order of magnitude faster in go-jsonnet. Mostly because of more builtins and better desugaring of some code structures. But there are also some things that are slower.
@sparkprime announced a plan to eventually deprecate C++ version, but some things need to happen first (fully shared tests, some remaining issues in go-jsonnet). Actually double committing is not that much of an issue - tests and stdlib are shared, and implementation details can differ. Only new language features need to be implemented in both places and adding such things is a pretty big deal anyway. |
The security concerns about people running Jsonnet on untrusted code on the server side was probably the biggest motivator for go-jsonnet. It was started by jbeda of heptio but most of the work was done by sbarzowski. I find go-jsonnet generally about 2x slower in my usage. You could certainly experiment with it though, the commandline binary is a drop-in replacement. It really needs someone to go over it with a profiler and tweak some of the code at a microscopic level, I suspect that would get a chunk of performance back. The next thing would be to implement optimizations at the Jsonnet language level, and only implement them in go-jsonnet. I would indeed like to cut over to add features to go-jsonnet only, but it's not quite ready yet. In particular, the ASTs do not record comments and whitespace, which is bad for tooling. I think we can merge this now, right sbarzowski? |
Yes, LGTM. |
Thanks @ahakanbaba I think a lot of people will find this useful! |
@sparkprime awesome. |
@sparkprime Do you plan to generate a release anytime soon ? It would be great for and and make it easier for us to use std.trace(). |
Any way to get timings of what's inside the |
@abourget No, but it's an interesting idea and probably quite easy to implement. (Though it may be tricky to interpret the results sometimes due to caching and laziness, at least this Also if you are having performance issues feel free to report performance issues (especially if the problem is also happening with go-jsonnet). |
Prints the first argument to std err with line number
Returns the second argument which is expected to be an object.
ISSUE: #130