It seems some functions are not traced
xumingming opened this issue · comments
e.g. when invoke (read-string "\\a")
the function read-char*
is not traced.
(read-string "\"a\"")
also have the same issue:
user> (read-string "\"a\"")
|- (blind.reader/read-string "\"a\"")
| |- (blind.reader/string-push-back-reader "\"a\"")
| | |- (blind.reader/string-push-back-reader "\"a\"" 1)
| | | |- (blind.reader/string-reader "\"a\"")
| | | \=> #<StringReader blind.reader.StringReader@3ec44cfb>
| | \=> #<PushbackReader blind.reader.PushbackReader@499a12ee>
| \=> #<PushbackReader blind.reader.PushbackReader@499a12ee>
| |- (blind.reader/read #<PushbackReader blind.reader.PushbackReader@499a12ee> true nil false)
| | |- (blind.reader/char \")
| | \=> \"
| | |- (blind.reader/whitespace? \")
| | \=> false
| | |- (blind.reader/number-literal? #<PushbackReader blind.reader.PushbackReader@499a12ee> \")
| | | |- (blind.reader/numeric? \")
| | | \=> false
| | \=> false
| | |- (blind.reader/comment-prefix? \")
| | \=> false
| | |- (blind.reader/macros \")
| | \=> #<reader$read_string_STAR_ blind.reader$read_string_STAR_@2f590164>
| | |- (blind.reader/char \a)
| | \=> \a
| | |- (blind.reader/char \")
| | \=> \"
| \=> "a"
\=> "a"
"a"
that's because those functions are called from a constant lookup https://github.com/Bronsa/blind/blob/master/src/blind/reader.clj#L819-L851
So even though tracer is altering the vars, it's not altering the value of the functions used by macros
and dispatch-macros
, eg. this problem wouldn't happen if macros would return #'read-string* instead of read-string
I'm not sure if there is a method to solve this problem
@Bronsa Yeah, it seems it is not that easy to trace this kind of functions statically, here is a potential solution:
We already wrapped all the functions in the target namespace, and we stored the mapping from orignal function to wrapped function in an atom(https://github.com/xumingming/tracer/blob/master/src/tracer/core.clj#L15), we have access to functions' return value, we can do one more thing: if the return value is a function, we check whether it is in the mapping, if it is, we replace it with the wrapped function, then it can be traced.
How do you think?
Smallest reproduce case:
user=> (defn a [] "a") (defn b [] "b") (defn c [num] (case num 1 a 2 b)) (use 'tracer.core) (trace 'user) ((c 1))
#'user/a
#'user/b
#'user/c
nil
Add user/cdoc to trace list.
Add user/sourcery to trace list.
Add user/help to trace list.
Add user/a to trace list.
Add user/defn to trace list.
Add user/c to trace list.
Add user/b to trace list.
Add user/set-signal-handler! to trace list.
Add user/clojuredocs to trace list.
nil
|- (user/c 1)
\=> #<user$a user$a@1c6250d2>
"a"
Here function a
is missing in the call stack.