David,
That sounds like a great solution now that I understand it better.
Please do check it in.
Thanks
Eric
>>> David PONCE <david.ponce@...> seems to think that:
>Hi Eric,
>
>[...]
>> This looks like a good idea. semantic-fw.el seems like a good place
>> for it as well. If the support for this sort of thing got much larger
>> with many other debugging forms, it would make sense to go in
>> cedet/common.
>
>A patch follows providing a first implementation. It mainly concerns
>Wisent for now, but the bovinator has source debugging ;-)
>
>> It would be nice if it could provide a clue for which rule and
>> expression was being run when the error was thrown in the message
>> statement. I've inserted such code into the parser directly before,
>> and still been lost not knowing which chunk of code was broken in my
>> parser. Doing so, however, would make it much more parser dependent,
>> probably going into semantic.el directly.
>[...]
>
>I artificially introduced this subtle nasty error in
>semantic-grammar.wy:
>
>rules:
> lifo_rules
> (apply 'nconc (nreverse $$1))
> ;
>
>where `$$1' is of course a "void variable".
>
>When `debug-on-error' is not set and I open a grammar file I now get
>this message, so I can suspect there is problem while parsing!
>
>"wisent-parse-stream: Symbol's value as variable is void: $$1"
>
>I retry with `debug-on-error' set to get the following nice back trace
>which clearly tells me that the "void variable" error occurred in
>"rules:0" semantic action, that is the first rule of nonterminal
>`rules'.
>
>Debugger entered--Lisp error: (void-variable $$1)
> (nreverse $$1)
> (apply (quote nconc) (nreverse $$1))
> (cons (apply (quote nconc) (nreverse $$1)) $region)
> (aset stack (1- sp) (cons (apply ... ...) $region))
> (let* (($region1 ...) ($region ...) ($nterm ...) ($action "rules:0")
> state) (setq sp (- sp 2) gotos (aref gotos ...) state (cdr ...) sp
> (+ sp 2)) (aset stack sp state) (aset stack (1- sp) (cons ...
> $region)) sp)
> rules:0([0 ("$$grammar") 9 ("input" 1513 . 1518) 37 ...
> [...]
>
>While in the debugger, looking at `semantic-debug-parser-source'
>value gives me what grammar file I have to fix. Very nice ;-)
>
>e semantic-debug-parser-source RET
>==> "semantic-grammar.wy"
>
>I can also use
>
>M-x wisent-debug-on-entry RET semantic-grammar-wy--parse-table RET
>rules:0 RET
>
>to debug the suspect semantic action :-)
>
>If you haven't objection, I will check the patch in.
>
>Thoughts?
>
>David
>
>2004-02-18 David Ponce <david@...>
>
> * cedet/semantic/semantic-fw.el
>
> (semantic-safe): New macro.
>
> * cedet/semantic/semantic-idle.el
>
> (semantic-idle-core-handler): New function.
> (semantic-idle-scheduler-function): Call it through
> `semantic-safe' to help debugging.
>
> * cedet/semantic/wisent/wisent-bovine.el
>
> (wisent-parse-stream): Use `semantic-safe' to help debugging.
> (wisent-parse-region): Likewise.
>
>Index: semantic/semantic-fw.el
>===================================================================
>RCS file: /cvsroot/cedet/cedet/semantic/semantic-fw.el,v
>retrieving revision 1.27
>diff -c -r1.27 semantic-fw.el
>*** semantic/semantic-fw.el 12 Feb 2004 02:03:25 -0000 1.27
>--- semantic/semantic-fw.el 18 Feb 2004 08:44:22 -0000
>***************
>*** 106,113 ****
> Mark OLDFNALIAS as obsolete, such that the byte compiler
> will throw a warning when it encounters this symbol."
> (defalias oldfnalias newfn)
>! (make-obsolete oldfnalias newfn)
>! )
>
> (defun semantic-varalias-obsolete (oldvaralias newvar)
> "Make OLDVARALIAS an alias for variable NEWVAR.
>--- 106,112 ----
> Mark OLDFNALIAS as obsolete, such that the byte compiler
> will throw a warning when it encounters this symbol."
> (defalias oldfnalias newfn)
>! (make-obsolete oldfnalias newfn))
>
> (defun semantic-varalias-obsolete (oldvaralias newvar)
> "Make OLDVARALIAS an alias for variable NEWVAR.
>***************
>*** 124,139 ****
> can't make obsolete variable `%s'\n\
> alias of `%s'." (error-message-string err) oldvaralias newvar)
> )))
>-
> (make-obsolete-variable oldvaralias newvar))
>
>-
> ;;; Semantic autoloads
> ;;
>! ;; Load semantic-al after compatibility code, to allow to use it in
>! ;; autoloads without infinite recursive load problems.
> (load "semantic-loaddefs" nil t)
>
> ;;; Misc utilities
> ;;
> (defun semantic-map-buffers (fun)
>--- 123,156 ----
> can't make obsolete variable `%s'\n\
> alias of `%s'." (error-message-string err) oldvaralias newvar)
> )))
> (make-obsolete-variable oldvaralias newvar))
>
> ;;; Semantic autoloads
> ;;
>! ;; Load semantic-loaddefs after compatibility code, to allow to use it
>! ;; in autoloads without infinite recursive load problems.
> (load "semantic-loaddefs" nil t)
>
>+ ;;; Help debugging
>+ ;;
>+ (defmacro semantic-safe (format &rest body)
>+ "Turn into a FORMAT message any error caught during eval of BODY.
>+ Return the value of last BODY form or nil if an error occurred.
>+ FORMAT can have a %s escape which will be replaced with the actual
>+ error message.
>+ If `debug-on-error' is set, errors are not caught, so that you can
>+ debug them.
>+ Avoid using a large BODY since it is duplicated."
>+ ;;(declare (debug t) (indent 1))
>+ `(if debug-on-error
>+ (progn ,@body)
>+ (condition-case err
>+ (progn ,@body)
>+ (error
>+ (message ,format (error-message-string err))
>+ nil))))
>+ (put 'semantic-safe 'lisp-indent-function 1)
>+
> ;;; Misc utilities
> ;;
> (defun semantic-map-buffers (fun)
>***************
>*** 165,171 ****
> (with-current-buffer b
> (if (memq major-mode modes)
> (funcall fun)))))))
>-
>
> ;;; Behavioral APIs
> ;;
>--- 182,187 ----
>***************
>*** 546,552 ****
> (semantic-augment-function-help (ad-get-arg 0)))))
>
>
>! ;;; User Interrupe handling
> ;;
> (defvar semantic-current-input-throw-symbol nil
> "The current throw symbol for `semantic-exit-on-input'.")
>--- 562,568 ----
> (semantic-augment-function-help (ad-get-arg 0)))))
>
>
>! ;;; User Interrupt handling
> ;;
> (defvar semantic-current-input-throw-symbol nil
> "The current throw symbol for `semantic-exit-on-input'.")
>Index: semantic/semantic-idle.el
>===================================================================
>RCS file: /cvsroot/cedet/cedet/semantic/semantic-idle.el,v
>retrieving revision 1.16
>diff -c -r1.16 semantic-idle.el
>*** semantic/semantic-idle.el 12 Feb 2004 02:04:33 -0000 1.16
>--- semantic/semantic-idle.el 18 Feb 2004 08:44:22 -0000
>***************
>*** 202,209 ****
>
> ;;; IDLE Function
> ;;
>! ;; This is the idle function which handles reparsing, and also
>! ;; manages services that depend on tag values.
> (defun semantic-idle-scheduler-function ()
> "Function run when after `semantc-idle-scheduler-idle-time'.
> This function will reparse the current buffer, and if successful,
>--- 202,236 ----
>
> ;;; IDLE Function
> ;;
>! (defun semantic-idle-core-handler ()
>! "Core idle function that handles reparsing.
>! And also manages services that depend on tag values."
>! (semantic-exit-on-input 'idle-timer
>! ;; First, reparse the current buffer.
>! (let ((inhibit-quit nil)
>! (lexok (semantic-idle-scheduler-refresh-tags))
>! (buffers (buffer-list))
>! (queue semantic-idle-scheduler-queue)
>! )
>!
>! ;; Now loop over other buffers, trying to update them as well.
>! (save-excursion
>! (while buffers
>! (semantic-throw-on-input 'parsing-all-buffers)
>! (set-buffer (car buffers))
>! (when semantic-idle-scheduler-mode
>! (semantic-idle-scheduler-refresh-tags)
>! )
>! (setq buffers (cdr buffers))))
>!
>! ;; Evaluate all other services. Stop on keypress.
>! (save-excursion
>! (while queue
>! (semantic-throw-on-input 'idle-queue)
>! (funcall (car queue))
>! (setq queue (cdr queue))))
>! )))
>!
> (defun semantic-idle-scheduler-function ()
> "Function run when after `semantc-idle-scheduler-idle-time'.
> This function will reparse the current buffer, and if successful,
>***************
>*** 213,246 ****
> ;; Disable the auto parse timer while re-parsing
> (semantic-idle-scheduler-kill-timer)
>
>! (condition-case err
>! (semantic-exit-on-input 'idle-timer
>! ;; First, reparse the current buffer.
>! (let ((inhibit-quit nil)
>! (lexok (semantic-idle-scheduler-refresh-tags))
>! (buffers (buffer-list))
>! (queue semantic-idle-scheduler-queue)
>! )
>!
>! ;; Now loop over other buffers, trying to update them as well.
>! (save-excursion
>! (while buffers
>! (semantic-throw-on-input 'parsing-all-buffers)
>! (set-buffer (car buffers))
>! (when semantic-idle-scheduler-mode
>! (semantic-idle-scheduler-refresh-tags)
>! )
>! (setq buffers (cdr buffers))))
>!
>! ;; Evaluate all other services. Stop on keypress.
>! (save-excursion
>! (while queue
>! (semantic-throw-on-input 'idle-queue)
>! (funcall (car queue))
>! (setq queue (cdr queue))))
>! ))
>! (error (message "idle error: %S" err)))
>!
> ;; Enable again the auto parse timer
> (semantic-idle-scheduler-setup-timer)))
>
>--- 240,249 ----
> ;; Disable the auto parse timer while re-parsing
> (semantic-idle-scheduler-kill-timer)
>
>! ;; Handle re-parsing and other scheduled services
>! (semantic-safe "idle error: %S"
>! (semantic-idle-core-handler))
>!
> ;; Enable again the auto parse timer
> (semantic-idle-scheduler-setup-timer)))
>
>Index: semantic/wisent/wisent-bovine.el
>===================================================================
>RCS file: /cvsroot/cedet/cedet/semantic/wisent/wisent-bovine.el,v
>retrieving revision 1.31
>diff -c -r1.31 wisent-bovine.el
>*** semantic/wisent/wisent-bovine.el 23 Jan 2004 08:34:57 -0000 1.31
>--- semantic/wisent/wisent-bovine.el 18 Feb 2004 08:44:23 -0000
>***************
>*** 218,229 ****
> (setq la-elt nil))
> ;; Parse
> (setq wisent-lex-istream stream
>! cache (condition-case nil
> (wisent-parse semantic-toplevel-bovine-table
> wisent-lexer-function
> wisent-error-function
>! goal)
>! (error nil)))
> ;; Manage returned lookahead token
> (if wisent-lookahead
> (if (eq (caar la-elt) wisent-lookahead)
>--- 218,228 ----
> (setq la-elt nil))
> ;; Parse
> (setq wisent-lex-istream stream
>! cache (semantic-safe "wisent-parse-stream: %s"
> (wisent-parse semantic-toplevel-bovine-table
> wisent-lexer-function
> wisent-error-function
>! goal)))
> ;; Manage returned lookahead token
> (if wisent-lookahead
> (if (eq (caar la-elt) wisent-lookahead)
>***************
>*** 272,283 ****
> (while wisent-lex-istream
> ;; Parse
> (setq wisent-lex-lookahead (car lstack)
>! tag (condition-case nil
> (wisent-parse semantic-toplevel-bovine-table
> wisent-lexer-function
> wisent-error-function
>! goal)
>! (error nil)))
> ;; Manage returned lookahead token
> (if wisent-lookahead
> (if (eq (car lstack) wisent-lookahead)
>--- 271,281 ----
> (while wisent-lex-istream
> ;; Parse
> (setq wisent-lex-lookahead (car lstack)
>! tag (semantic-safe "wisent-parse-region: %s"
> (wisent-parse semantic-toplevel-bovine-table
> wisent-lexer-function
> wisent-error-function
>! goal)))
> ;; Manage returned lookahead token
> (if wisent-lookahead
> (if (eq (car lstack) wisent-lookahead)
>
>
>
--
Eric Ludlam: zappo@..., eric@...
Home: http://www.ludlam.net Siege: http://www.siege-engine.com
Emacs: http://cedet.sourceforge.net GNU: http://www.gnu.org
|