Cedric, you're right in both your assessment of the potential solution (this could definitely be done) and also the problems. You'd need an additional line number mapping of original source line to expanded-lines source line to be able to make any sense of stack traces, thread dumps etc, and of course your debugger would need to use it to correctly highlight the current line. It's a nice idea but I fear it's not very practical. I'll think about it a bit, though, and see if I can take advantage of it in some way. I thought there was an additional line limit per class that might have been problematic but I was wrong, it's a bytecode size limit per method.
On 8 November 2013 19:24, Cedric Greevey <cgree...@gmail.com> wrote: > This JVMTI doesn't know Clojure source code from parsnip soup, I expect, > so can't it be fooled into "thinking" that the bytecode it's interpreting > came from a source with many more, shorter lines? So > > (defn x [y z] > (a (b (c)) > ((d) e (f g)))) > > could be passed off to it as if it were > > (defn x [y z] (a (b > (c)) > ((d) > e (f g)))) > > with breakpoints on (defn ...), (a ...), a, (b (c)), or b being passed to > JVMTI as breakpoints on the first line of the latter formatting of the > code; breakpoints on (c) or c the second line; breakpoints on (d) or d the > third line; and breakpoints on e, (f g), f, or g the fourth line. Execution > would halt at the breakpoint with the correct amount of evaluation done. > (The bare letters are presumed to be self-evaluating literals or var > lookups here, and the operators, other than defn, to be functions.) > > Breakpoints on a macro sexp would need to halt on the first evaluation of > any of the expansion, and breakpoints on a macro argument would need to be > carried through into the expansion. The special forms are mostly fairly > obvious -- break on an if or its condition, for example, breaks before > evaluating the condition; break on the then clause breaks after evaluating > the condition, before evaluating the then clause, only if the condition was > true; etc. Combined, those rules mean a breakpoint on a particular (cond > ...) condition X would only trip if all the previous conditions were false, > before evaluating condition X, and a breakpoint on the corresponding then > clause only if all the preceding conditions were false but condition X was > true, after evaluating X but before evaluating X's then clause, because it > would end up attached to X's corresponding conditional or then clause > (respectively) in the macro-expanded if-tree (>(sexp)< indicates breakpoint > target): > > (cond > (thing1) (dothis) > (thing2) (dothat) > >(thing3)< (dosomethingelse) > :else (default)) > > should macroexpand to > > (if (thing1) > (dothis) > (if (thing2) > (dothat) > (if >(thing3)< > (dosomethingelse) > (if :else > (default) > (throw ( ... no matching clause blah blah ... [never actually > executes in this case])))))) > > so the "(if >(thing3)<" line would be what JVMTI "thinks" is the > breakpointed line in this case. > > The real issue I can foresee here would be if there's no way to make the > "lines" seen by the breakpoint/debugging stuff be different from the > "lines" used for error reporting (e.g. in stacktraces), as then *either* > the "line" granularity for breakpoints is whole lines of your actual source > code *or* stacktrace line numbers won't always correspond to what your > editor shows for the problem line in your source code, for example if > (default) threw a ClassCastException because "default" did not implement > IFn in the above the stacktrace might point to line 8 when it was really > line 5 of your (cond ...) expression (but line 8 of the (if ...) it > macroexpanded to, and which was vertically spread out to put each distinct > (as to what nontrivial evaluation has happened yet) sexp-based breakpoint > position on its own line to please JVMTI). > > > > > On Fri, Nov 8, 2013 at 12:53 AM, Colin Fleming < > colin.mailingl...@gmail.com> wrote: > >> Right, sadly I believe this is impossible using JVMTI, although I'm far >> from an expert. >> >> >> On 8 November 2013 18:51, Cedric Greevey <cgree...@gmail.com> wrote: >> >>> Ideally, in a Lisp I'd think the unit of breakpoints would not be a line >>> but instead an s-expression, tripping before evaluating the body of the >>> expression. >>> >>> >>> On Fri, Nov 8, 2013 at 12:24 AM, Colin Fleming < >>> colin.mailingl...@gmail.com> wrote: >>> >>>> I'm slightly late to the discussion, sorry - currently moving cities. >>>> Cursive does indeed have a stepping debugger which works well with Clojure, >>>> although it's quite slow (I haven't been able to figure out why, yet - I >>>> suspect Clojure adds a lot of line information to the bytecode). There have >>>> also been some fairly annoying bugs with it which will be fixed in the next >>>> drop. Here's more or less what it can do: >>>> >>>> 1. Standard stepping - step into, step over. Step out is flaky for >>>> non-Java languages for some reason, I believe this is fixed in the new >>>> version of IntelliJ (13, currently in beta, due to be released soon). >>>> 2. Place breakpoints on any line. This generally works well but is >>>> occasionally frustrating with Clojure since you can pack a lot on a >>>> line. >>>> I've found chained sequence operations to be particularly difficult to >>>> debug. This is really a JVM limitation since JVMTI is line-oriented. >>>> 3. Breakpoints can be configured in various ways. Instead of >>>> stopping you can configure them to print the value of an expression, or >>>> to >>>> stop only the current thread, or to stop all threads. >>>> 4. Drop frame to go back in time, as long as you're not mutating >>>> any global state. You're not, right? >>>> 5. Look at locals up and down the stack, as long as you have locals >>>> clearing disabled. >>>> 6. For the next drop I'm going to add the ability to toggle locals >>>> clearing in debug REPLs with a button in the REPL tool window. >>>> 7. You can evaluate arbitrary Clojure expressions at any point in >>>> the call stack. >>>> 8. You can set a breakpoint on an arbitrary exception, and it will >>>> pause *at the time the exception is thrown* and you can inspect locals >>>> etc. >>>> >>>> I'm pretty sure all of this works, and I use most of it regularly. >>>> Expression evaluation has been broken until the current dev build so I need >>>> to test that things that depend on it work before promising them, but I'm >>>> pretty sure they will. They include: >>>> >>>> 1. Watches. >>>> 2. Being able to configure breakpoints to only stop when a >>>> particular expression is true. >>>> >>>> For the next drop I'm planning to work a lot on the debugger and >>>> document it all properly including some pretty animations, so I'll post to >>>> the list when that is done. >>>> >>>> >>>> On 8 November 2013 13:14, intronic <m...@pheasant.co.nz> wrote: >>>> >>>>> Why would a break function in clojure the language not be >>>>> considered, a-la common-lisp? >>>>> >>>>> >>>>> >>>>> On Friday, 8 November 2013 09:31:55 UTC+10, Lee wrote: >>>>>> >>>>>> >>>>>> On Nov 7, 2013, at 5:48 PM, Alex Miller wrote: >>>>>> >>>>>> > When you say "hit an error", I'm assuming you mean "clojure throws >>>>>> an exception" and not "hit a breakpoint in a debugger" or something else. >>>>>> >>>>>> Yes -- I mean "clojure throws an exception." >>>>>> >>>>>> > >>>>>> > I don't think there is one place where we could generically attach >>>>>> locals info to a thrown exception. The JVM debugging interface (JVMTI - >>>>>> http://docs.oracle.com/javase/7/docs/technotes/guides/jvmti/ >>>>>> index.html) can do an awful lot of things (including arbitrary class >>>>>> bytecode transformation) so I would guess it's possible to build a java >>>>>> agent that could do this (or to modify the Compiler to inject the right >>>>>> code at compile time). Sounds like a fun project, but probably >>>>>> non-trivial. >>>>>> >>>>>> Too bad... unless someone wants to have that fun and then share it >>>>>> with the rest of us :-). It still strikes me as really odd that such >>>>>> basic >>>>>> and clearly desirable functionality, available forever in other >>>>>> environments, should be so hard to come by. >>>>>> >>>>>> -Lee >>>>> >>>>> -- >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Clojure" group. >>>>> To post to this group, send email to clojure@googlegroups.com >>>>> Note that posts from new members are moderated - please be patient >>>>> with your first post. >>>>> To unsubscribe from this group, send email to >>>>> clojure+unsubscr...@googlegroups.com >>>>> For more options, visit this group at >>>>> http://groups.google.com/group/clojure?hl=en >>>>> --- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Clojure" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to clojure+unsubscr...@googlegroups.com. >>>>> For more options, visit https://groups.google.com/groups/opt_out. >>>>> >>>> >>>> -- >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Clojure" group. >>>> To post to this group, send email to clojure@googlegroups.com >>>> Note that posts from new members are moderated - please be patient with >>>> your first post. >>>> To unsubscribe from this group, send email to >>>> clojure+unsubscr...@googlegroups.com >>>> For more options, visit this group at >>>> http://groups.google.com/group/clojure?hl=en >>>> --- >>>> You received this message because you are subscribed to the Google >>>> Groups "Clojure" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to clojure+unsubscr...@googlegroups.com. >>>> For more options, visit https://groups.google.com/groups/opt_out. >>>> >>> >>> -- >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To post to this group, send email to clojure@googlegroups.com >>> Note that posts from new members are moderated - please be patient with >>> your first post. >>> To unsubscribe from this group, send email to >>> clojure+unsubscr...@googlegroups.com >>> For more options, visit this group at >>> http://groups.google.com/group/clojure?hl=en >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to clojure+unsubscr...@googlegroups.com. >>> For more options, visit https://groups.google.com/groups/opt_out. >>> >> >> -- >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clojure@googlegroups.com >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+unsubscr...@googlegroups.com >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/groups/opt_out. >> > > -- > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > -- -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.