all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Compilation warnings of ELisp seem wrong and misleading
@ 2015-03-30 13:47 Ludwig, Mark
  0 siblings, 0 replies; 11+ messages in thread
From: Ludwig, Mark @ 2015-03-30 13:47 UTC (permalink / raw)
  To: help-gnu-emacs@gnu.org

Greetings,

I've been using an ancient Emacs (19.29) on Solaris and finally
got around to installing a current one (24.4).

I don't normally compile my ".emacs" code, but stumbled
across a change in the compile code (compile-internal is no
longer present), and that prompted me to explicitly
byte-compile my custom Elisp code to see what other problems
that would expose, so I could take care of all of them at
the same time.

I find my custom Elisp generates warnings that seem pretty stupid.
For example:

emacs.el:255:10:Warning: reference to free variable `if'
emacs.el:219:8:Warning: reference to free variable `save-excursion'
emacs.el:331:41:Warning: reference to free variable `forward-char'
emacs.el:261:17:Warning: reference to free variable `insert'
emacs.el:261:17:Warning: reference to free variable `forward-sexp'

Those are all valid functions.  For example, here are lines 255-258:

	(if (not (= ans ?q))
	    (progn
	      (goto-char found-start)
	      (delete-region found-start found-end)))

This is inside a large-ish "let*" form (111 lines).

Most of this code is duplicated on Windows, where I'm using
Emacs 24.2 (just to give some context that my Elisp
knowledge isn't all completely ancient).

I can't see how these warnings can be correct, but there are
so many that they obscure the "meaningful" ones.  Are these
sorts of warnings known flaws in the byte compiler, do I
need to compile differently, am I doing something stupid, or
what?

BTW, I /very/ /much/ /like/ this warning:

emacs.el:1326:76:Warning: Use `with-current-buffer' rather than
    save-excursion+set-buffer

Thanks for that!

Cheers,

Mark Ludwig
Lifecycle Coll
Product Lifecycle Management

Siemens Industry Sector
Siemens Product Lifecycle Management Software Inc.
5939 Rice Creek Parkway
Shoreview, MN  55126 United States 
Tel.      :+1 (651) 855-6140
Fax      :+1 (651) 855-6280
ludwig.mark@siemens.com 
www.siemens.com/plm 





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Compilation warnings of ELisp seem wrong and misleading
       [not found] <mailman.3018.1427724507.31049.help-gnu-emacs@gnu.org>
@ 2015-03-30 14:39 ` Pascal J. Bourguignon
  2015-03-30 15:40   ` Ludwig, Mark
       [not found]   ` <mailman.3032.1427730039.31049.help-gnu-emacs@gnu.org>
  2015-03-31  0:53 ` Emanuel Berg
  1 sibling, 2 replies; 11+ messages in thread
From: Pascal J. Bourguignon @ 2015-03-30 14:39 UTC (permalink / raw)
  To: help-gnu-emacs

"Ludwig, Mark" <ludwig.mark@siemens.com> writes:

> Greetings,
>
> I've been using an ancient Emacs (19.29) on Solaris and finally
> got around to installing a current one (24.4).
>
> I don't normally compile my ".emacs" code, but stumbled
> across a change in the compile code (compile-internal is no
> longer present), and that prompted me to explicitly
> byte-compile my custom Elisp code to see what other problems
> that would expose, so I could take care of all of them at
> the same time.
>
> I find my custom Elisp generates warnings that seem pretty stupid.
> For example:
>
> emacs.el:255:10:Warning: reference to free variable `if'
> emacs.el:219:8:Warning: reference to free variable `save-excursion'
> emacs.el:331:41:Warning: reference to free variable `forward-char'
> emacs.el:261:17:Warning: reference to free variable `insert'
> emacs.el:261:17:Warning: reference to free variable `forward-sexp'
>
> Those are all valid functions.  For example, here are lines 255-258:
>
> 	(if (not (= ans ?q))
> 	    (progn
> 	      (goto-char found-start)
> 	      (delete-region found-start found-end)))
>
> This is inside a large-ish "let*" form (111 lines).
>
> Most of this code is duplicated on Windows, where I'm using
> Emacs 24.2 (just to give some context that my Elisp
> knowledge isn't all completely ancient).
>
> I can't see how these warnings can be correct, but there are
> so many that they obscure the "meaningful" ones.  Are these
> sorts of warnings known flaws in the byte compiler, do I
> need to compile differently, am I doing something stupid, or
> what?

We cannot see either, because the meaning of a sexp is determined by its
surrounding form, which you didn't provide.

You probably have a parenthesis problem in your let* form which makes
lisp interpret some parts as being variable names instead of operators.

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: Compilation warnings of ELisp seem wrong and misleading
  2015-03-30 14:39 ` Compilation warnings of ELisp seem wrong and misleading Pascal J. Bourguignon
@ 2015-03-30 15:40   ` Ludwig, Mark
  2015-03-30 16:59     ` tomas
       [not found]   ` <mailman.3032.1427730039.31049.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 11+ messages in thread
From: Ludwig, Mark @ 2015-03-30 15:40 UTC (permalink / raw)
  To: Pascal J. Bourguignon, help-gnu-emacs@gnu.org

"Pascal J. Bourguignon" wrote:

> "Ludwig, Mark" <ludwig.mark@siemens.com> writes:
> 
> > Greetings,
> >
> > I've been using an ancient Emacs (19.29) on Solaris and finally
> > got around to installing a current one (24.4).
> >
> > I find my custom Elisp generates warnings that seem pretty stupid.
> > For example:
> >
> > emacs.el:255:10:Warning: reference to free variable `if'
> > emacs.el:219:8:Warning: reference to free variable `save-excursion'
> > emacs.el:331:41:Warning: reference to free variable `forward-char'
> > emacs.el:261:17:Warning: reference to free variable `insert'
> > emacs.el:261:17:Warning: reference to free variable `forward-sexp'
> >
> > Those are all valid functions.  For example, here are lines 255-258:
> >
> > 	(if (not (= ans ?q))
> > 	    (progn
> > 	      (goto-char found-start)
> > 	      (delete-region found-start found-end)))
> >
> > This is inside a large-ish "let*" form (111 lines).

> We cannot see either, because the meaning of a sexp is determined by its
> surrounding form, which you didn't provide.
> 
> You probably have a parenthesis problem in your let* form which makes
> lisp interpret some parts as being variable names instead of operators.

No, I know how to balance parentheses.  I've been
programming Emacs Lisp for almost 30 years.  I rely on Emacs
for its outstanding job of showing structural problems
through its automatic indentation (in all programming
languages, but certainly within its own).  By all means, if
there's anything wrong with that (if ...) form, please
explain.

For context, the "let*" is on line 239; the warning
(mentioned above as being on line 255 column 10) is
referring to the form after the comment "Make the
substitution."  If you read the warnings carefully, you'll
note that it warns about two different things on line 261,
column 17.  That line is the one with the comment, 'Now it's
"strlcpy" or whatever.'  Clearly, the byte-compiler is
pretty confused....

      (let* ((c1 (string-to-char to1))
	     (c2 (string-to-char to2))
	     (ans 0))

	;; Get one of the first characters from the two substitutions

	(while (and (not (= ans c1))
		    (not (= ans c2))
		    (not (= ans ?q)))	; Quit, don't substitute anything
	  (setq ans (read-char-exclusive
		     (concat "Replace " from " with "
			     to1 " (will truncate silently) or "
			     to2 " (dstat)? (" (char-to-string c1) "/" (char-to-string c2) "/q) "))))

	;; Make the substitution

	(if (not (= ans ?q))
	    (progn
	      (goto-char found-start)
	      (delete-region found-start found-end)))

	(cond ((= ans c1)
	       (insert to1)		; Now it's "strlcpy" or whatever
	       )

	      ((= ans c2)
	       (insert "dstat = " to2)	; Now it's "dstat = nlsStrLCpy" or whatever
	       (back-to-indentation)
	       (setq ans 0)
	       (while (and (not (= ans ?d))
			   (not (= ans ?e))
			   (not (= ans ?n)))
		 (setq ans (read-char-exclusive "Use DSOK/EXIT/no form? ")))

	       (let ((if-pos (point)))

		 (cond ((= ans ?d)
			(insert "if (DSOK) ")
			(forward-sexp 3) ; After the closing parenthesis for the function call
			)

		       ((= ans ?e)
			(insert "if (")
			(forward-sexp 3) ; After the closing parenthesis for the function call
			(insert ")")
			(newline-and-indent)
			(insert "goto EXIT") ; The semi-colon should end up after "EXIT"
			(c-indent-command) ; Make the "goto" be correctly indented under the "if"
			)

		       ((= ans ?n)
			;; no form
			)
		       )

		 ;; Try to look ahead, in case the function call we just
		 ;; modified was a one-statement "block" in an "if," so
		 ;; we've just unintentionally modified the meaning of
		 ;; that "if" statement
			
		 (if (not (= ans ?n))
		     (condition-case nil
			 (progn
			   (forward-sexp 1) ; Skip over "else" if it's there
			   (forward-sexp -1) ; Back in front of "else" if it's there
			   (if (looking-at "else")
			       (progn
				 (goto-char if-pos) ; Go back to where we inserted "if"

				 (cond ((= ans ?d)
					;; Skip over: "if" "(DSOK)" "dstat" "= ..." "()"
					(forward-sexp 5)
					)

				       ((= ans ?e)
					;; Skip over:
					;; "if" "(dstat = ...)" "goto" "EXIT"
					(forward-sexp 4)
					)

				       (if (not (looking-at ";"))
					   (error "First expected ';' not: \"%s\"" (buffer-substring (point)
												     (progn (end-of-line 1)
													    (point)))))
				       (save-excursion
					 (goto-char if-pos) ; Go back to where we inserted "if"
					 (insert "{
"))
				       (if (not (looking-at ";"))
					   (error "Second expected ';' not: \"%s\"" (buffer-substring (point)
												      (progn (end-of-line 1)
													     (point)))))
				       (forward-char 1)

				       ;; We should be looking at the end of line
				       (if (not (looking-at "\\s-*$"))
					   (error "Second expected end of line, not: \"%s\"" (buffer-substring (point)
													       (progn (end-of-line 1)
														      (point)))))
				       (insert "
}")
				       (forward-sexp -1)
				       (c-indent-exp)
				       ))))
		       (error nil)	;hand-rolled (ignore-errors ...)
		       )
		   )
		 )
	       )
	      )
	)

> 
> --
> __Pascal Bourguignon__                 http://www.informatimago.com/
> “The factory of the future will have only two employees, a man and a
> dog. The man will be there to feed the dog. The dog will be there to
> keep the man from touching the equipment.” -- Carl Bass CEO Autodesk

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Compilation warnings of ELisp seem wrong and misleading
  2015-03-30 15:40   ` Ludwig, Mark
@ 2015-03-30 16:59     ` tomas
  2015-03-30 19:09       ` Ludwig, Mark
  0 siblings, 1 reply; 11+ messages in thread
From: tomas @ 2015-03-30 16:59 UTC (permalink / raw)
  To: Ludwig, Mark; +Cc: Pascal J. Bourguignon, help-gnu-emacs@gnu.org

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Mon, Mar 30, 2015 at 03:40:21PM +0000, Ludwig, Mark wrote:
> "Pascal J. Bourguignon" wrote:
> 
> > "Ludwig, Mark" <ludwig.mark@siemens.com> writes:
> > 
> > > Greetings,
> > >
> > > I've been using an ancient Emacs (19.29) on Solaris and finally
> > > got around to installing a current one (24.4).
> > >
> > > I find my custom Elisp generates warnings that seem pretty stupid.
> > > For example:
> > >
> > > emacs.el:255:10:Warning: reference to free variable `if'

Bizarre.

> For context, the "let*" is on line 239; the warning
> (mentioned above as being on line 255 column 10) is
> referring to the form after the comment "Make the
> substitution."  If you read the warnings carefully, you'll
> note that it warns about two different things on line 261,
> column 17.  That line is the one with the comment, 'Now it's
> "strlcpy" or whatever.'  Clearly, the byte-compiler is
> pretty confused....

At first blush, to me the following looks fishy:

>       (let* ((c1 (string-to-char to1))
> 	     (c2 (string-to-char to2))
> 	     (ans 0))

[...]

> 				 (cond ((= ans ?d)
> 					;; Skip over: "if" "(DSOK)" "dstat" "= ..." "()"
> 					(forward-sexp 5)
> 					)
> 
> 				       ((= ans ?e)
> 					;; Skip over:
> 					;; "if" "(dstat = ...)" "goto" "EXIT"
> 					(forward-sexp 4)
> 					)
> 
> 				       (if (not (looking-at ";"))
> 					   (error "First expected ';' not: \"%s\"" (buffer-substring (point)

Here: you're in the middle of a `cond' and the clause reads "(if ...)". I'd
expect `cond' to try to interpret "if" as a naked variable (granted, the error
message points at another place).

> 												     (progn (end-of-line 1)
> 													    (point)))))
> 				       (save-excursion
> 					 (goto-char if-pos) ; Go back to where we inserted "if"
> 					 (insert "{

...likewise the `save-excursion' here.

And so on.

HTH
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlUZgPcACgkQBcgs9XrR2kYznQCfa2FWYAipjWHgTbfS0lR4BV2L
TKAAniQtR5ddvmg1extvIKl5ZnkOeF1C
=KuKr
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Compilation warnings of ELisp seem wrong and misleading
       [not found]   ` <mailman.3032.1427730039.31049.help-gnu-emacs@gnu.org>
@ 2015-03-30 17:08     ` Pascal J. Bourguignon
  0 siblings, 0 replies; 11+ messages in thread
From: Pascal J. Bourguignon @ 2015-03-30 17:08 UTC (permalink / raw)
  To: help-gnu-emacs

"Ludwig, Mark" <ludwig.mark@siemens.com> writes:

> "Pascal J. Bourguignon" wrote:
>
>> "Ludwig, Mark" <ludwig.mark@siemens.com> writes:
>> 
>> > Greetings,
>> >
>> > I've been using an ancient Emacs (19.29) on Solaris and finally
>> > got around to installing a current one (24.4).
>> >
>> > I find my custom Elisp generates warnings that seem pretty stupid.
>> > For example:
>> >
>> > emacs.el:255:10:Warning: reference to free variable `if'
>> > emacs.el:219:8:Warning: reference to free variable `save-excursion'
>> > emacs.el:331:41:Warning: reference to free variable `forward-char'
>> > emacs.el:261:17:Warning: reference to free variable `insert'
>> > emacs.el:261:17:Warning: reference to free variable `forward-sexp'
>> >
>> > Those are all valid functions.  For example, here are lines 255-258:
>> >
>> > 	(if (not (= ans ?q))
>> > 	    (progn
>> > 	      (goto-char found-start)
>> > 	      (delete-region found-start found-end)))
>> >
>> > This is inside a large-ish "let*" form (111 lines).
>
>> We cannot see either, because the meaning of a sexp is determined by its
>> surrounding form, which you didn't provide.
>> 
>> You probably have a parenthesis problem in your let* form which makes
>> lisp interpret some parts as being variable names instead of operators.
>
> No, I know how to balance parentheses.  I've been
> programming Emacs Lisp for almost 30 years.  I rely on Emacs
> for its outstanding job of showing structural problems
> through its automatic indentation (in all programming
> languages, but certainly within its own).  By all means, if
> there's anything wrong with that (if ...) form, please
> explain.
>
> For context, the "let*" is on line 239; the warning
> (mentioned above as being on line 255 column 10) is
> referring to the form after the comment "Make the
> substitution."  If you read the warnings carefully, you'll
> note that it warns about two different things on line 261,
> column 17.  That line is the one with the comment, 'Now it's
> "strlcpy" or whatever.'  Clearly, the byte-compiler is
> pretty confused....


No it is not confused.  
The warning are correct.  
However, it reports them at seemingly wrong places.

First, the code you gave has indeed 5 free variables.  It should not
compile and it should not run!  I had to add them to be able to compile
it, in a surrounding let.

Second, the code you gave is ill-formatted.  How hard is it to put the
closing parentheses on the same line (try to avoid ;-comments on the
last expression before a closing parenthesis), and how hard is it to
type M-q to have emacs indent your code correctly?!?

Next, the warning reported:

Compiling file /tmp/e.el at Mon Mar 30 18:38:30 2015
e.el:65:14:Warning: reference to free variable `if'
e.el:90:33:Warning: reference to free variable `save-excursion'
e.el:99:33:Warning: reference to free variable `forward-char'
e.el:32:12:Warning: reference to free variable `insert'
e.el:32:12:Warning: reference to free variable `forward-sexp'
e.el:110:33:Warning: reference to free variable `c-indent-exp'

correspond indeed to those symbols used in variable position, as cond
expressions!  Which can be clearly seen, when you have your code
indented properly, starting from line 85 below:


     1	(let ((from  "from")
     2	      (to1   "T")
     3	      (to2   "t")
     4	      (found-start 0)
     5	      (found-end   2))
     6	 (let* ((c1 (string-to-char to1))
     7	        (c2 (string-to-char to2))
     8	        (ans 0))
     9	
    10	   ;; Get one of the first characters from the two substitutions
    11	
    12	   (while (and (not (= ans c1))
    13	               (not (= ans c2))
    14	               (not (= ans ?q)))     ; Quit, don't substitute anything
    15	     (setq ans (read-char-exclusive
    16	                (concat "Replace " from " with "
    17	                        to1 " (will truncate silently) or "
    18	                        to2 " (dstat)? (" (char-to-string c1) "/" (char-to-string c2) "/q) "))))
    19	
    20	   ;; Make the substitution
    21	
    22	   (if (not (= ans ?q))
    23	       (progn
    24	         (goto-char found-start)
    25	         (delete-region found-start found-end)))
    26	
    27	   (cond ((= ans c1)
    28	          (insert to1)                ; Now it's "strlcpy" or whatever
    29	          )
    30	
    31	         ((= ans c2)
    32	          (insert "dstat = " to2) ; Now it's "dstat = nlsStrLCpy" or whatever
    33	          (back-to-indentation)
    34	          (setq ans 0)
    35	          (while (and (not (= ans ?d))
    36	                      (not (= ans ?e))
    37	                      (not (= ans ?n)))
    38	            (setq ans (read-char-exclusive "Use DSOK/EXIT/no form? ")))
    39	
    40	          (let ((if-pos (point)))
    41	
    42	            (cond ((= ans ?d)
    43	                   (insert "if (DSOK) ")
    44	                   (forward-sexp 3) ; After the closing parenthesis for the function call
    45	                   )
    46	
    47	                  ((= ans ?e)
    48	                   (insert "if (")
    49	                   (forward-sexp 3) ; After the closing parenthesis for the function call
    50	                   (insert ")")
    51	                   (newline-and-indent)
    52	                   (insert "goto EXIT") ; The semi-colon should end up after "EXIT"
    53	                   (c-indent-command) ; Make the "goto" be correctly indented under the "if"
    54	                   )
    55	
    56	                  ((= ans ?n)
    57	                   ;; no form
    58	                   ))
    59	
    60	            ;; Try to look ahead, in case the function call we just
    61	            ;; modified was a one-statement "block" in an "if," so
    62	            ;; we've just unintentionally modified the meaning of
    63	            ;; that "if" statement
    64	           
    65	            (if (not (= ans ?n))
    66	                (condition-case
    67	                 nil
    68	                 (progn
    69	                   (forward-sexp 1)   ; Skip over "else" if it's there
    70	                   (forward-sexp -1) ; Back in front of "else" if it's there
    71	                   (if (looking-at "else")
    72	                       (progn
    73	                         (goto-char if-pos) ; Go back to where we inserted "if"
    74	
    75	                         (cond ((= ans ?d)
    76	                                ;; Skip over: "if" "(DSOK)" "dstat" "= ..." "()"
    77	                                (forward-sexp 5)
    78	                                )
    79	
    80	                               ((= ans ?e)
    81	                                ;; Skip over:
    82	                                ;; "if" "(dstat = ...)" "goto" "EXIT"
    83	                                (forward-sexp 4))
    84	
    85	                               (if (not (looking-at ";"))
    86	                                   (error "First expected ';' not: \"%s\""
    87	                                          (buffer-substring (point)
    88	                                                            (progn (end-of-line 1)
    89	                                                                   (point)))))
    90	                               (save-excursion
    91	                                (goto-char if-pos) ; Go back to where we inserted "if"
    92	                                (insert "{
    93	"))
    94	                               (if (not (looking-at ";"))
    95	                                   (error "Second expected ';' not: \"%s\""
    96	                                          (buffer-substring (point)
    97	                                                            (progn (end-of-line 1)
    98	                                                                   (point)))))
    99	                               (forward-char 1)
   100	
   101	                               ;; We should be looking at the end of line
   102	                               (if (not (looking-at "\\s-*$"))
   103	                                   (error "Second expected end of line, not: \"%s\""
   104	                                          (buffer-substring (point)
   105	                                                            (progn (end-of-line 1)
   106	                                                                   (point)))))
   107	                               (insert "
   108	}")
   109	                               (forward-sexp -1)
   110	                               (c-indent-exp)
   111	                               ))))
   112	                 (error nil)          ;hand-rolled (ignore-errors ...)
   113	                 )))))))


You may indeed report an emacs bug, that the warnings refer the first
occurences of the symbol, instead of the erroneous occurences.


Finally, you should have expressions so long. You should write short
functions, and use them in shorter forms.


Your code should be replaced with a single simple function:

(defun do-something (from to1 to2 found-start found-end)
  (let* ((c1 (string-to-char to1))
         (c2 (string-to-char to2))
         (ans (get-one-of-the-first-characters-from-the-two-substitutions from to1 to2 c1 c2)))
    (unless (= ans ?q)
      (make-the-substitution ans from to1 to2 c1 c2 found-start found-end))))


;; which uses the two simple and clear functions:

(defun get-one-of-the-first-characters-from-the-two-substitutions (from to1 to2 c1 c2)
  (let ((ans 0))
    (while (and (/= ans c1)
                (/= ans c2)
                (/= ans ?q))          ; Quit, don't substitute anything
      (setq ans (read-char-exclusive
                 (concat "Replace " from " with "
                         to1 " (will truncate silently) or "
                         to2 " (dstat)? (" (char-to-string c1) "/" (char-to-string c2) "/q) "))))
    ans))


(defun make-the-substitution (ans from to1 to2 c1 c2 found-start found-end)
  (assert (/= ans ?q))
  (goto-char found-start)
  (delete-region found-start found-end)
  (cond ((= ans c1) (insert to1))
        ((= ans c2) (insert-dstat ans from to2 c2 found-start found-end))))


;; Also notice how they can very easily be tested alone:

;; (get-one-of-the-first-characters-from-the-two-substitutions "from" "T" "t" ?T ?t)
;; (make-the-substitution ?T "from" "T" "t" ?T ?t (point) (point))


;; With make-the-substitution itself using the following functions:

(defun get-dstat-choice ()
  (let ((ans 0))
    (while (and (/= ans ?d)
                (/= ans ?e)
                (/= ans ?n))
      (setq ans (read-char-exclusive "Use DSOK/EXIT/no form? ")))
    ans))

;; again, very easily testable: (get-dstat-choice)


(defun insert-dstat (ans from to2 c2 found-start found-end)
  (insert "dstat = " to2) ; Now it's "dstat = nlsStrLCpy" or whatever
  (back-to-indentation)
  (let ((ans    (get-dstat-choice))
        (if-pos (point)))
    (unless (= ans ?n)

      (case ans
        (?d
         (insert "if (DSOK) ")
         (forward-sexp 3))
        (?e
         (insert "if (")
         (forward-sexp 3) ; After the closing parenthesis for the function call
         (insert ")")
         (newline-and-indent)
         (insert "goto EXIT") ; The semi-colon should end up after "EXIT"
         (c-indent-command)))

      ;; Try to look ahead, in case the function call we just
      ;; modified was a one-statement "block" in an "if," so
      ;; we've just unintentionally modified the meaning of
      ;; that "if" statement
      
      (forward-sexp 1)  ; Skip over "else" if it's there
      (forward-sexp -1) ; Back in front of "else" if it's there
      (when (looking-at "else")
        (goto-char if-pos) ; Go back to where we inserted "if"
        (case ans
          (?d ;; Skip over: "if" "(DSOK)" "dstat" "= ..." "()"
           (forward-sexp 5))
          (?e
           ;; Skip over:
           ;; "if" "(dstat = ...)" "goto" "EXIT"
           (forward-sexp 4))
          (otherwise ;; perhaps you didn't mean otherwise, but end of
                     ;; the case?  You'll have to debug it here.
           (unless (looking-at ";")
             (error "First expected ';' not: \"%s\""
                    (buffer-substring (point)
                                      (progn (end-of-line 1)
                                             (point)))))
           (save-excursion
            (goto-char if-pos) ; Go back to where we inserted "if"
            (insert "{\n"))
           (unless (looking-at ";")
             (error "Second expected ';' not: \"%s\""
                    (buffer-substring (point)
                                      (progn (end-of-line 1)
                                             (point)))))
           (forward-char 1)
           ;; We should be looking at the end of line
           (unless  (looking-at "\\s-*$")
             (error "Second expected end of line, not: \"%s\""
                    (buffer-substring (point)
                                      (progn (end-of-line 1)
                                             (point)))))
           (insert "\n}")
           (forward-sexp -1)
           (c-indent-exp)))))))


;; you an then call your functions from the toplevel:

(let ((from  "from")
      (to1   "T")
      (to2   "t")
      (found-start 0)
      (found-end   2))
  (do-something from to1 to2 found-start found-end))



-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: Compilation warnings of ELisp seem wrong and misleading
  2015-03-30 16:59     ` tomas
@ 2015-03-30 19:09       ` Ludwig, Mark
  0 siblings, 0 replies; 11+ messages in thread
From: Ludwig, Mark @ 2015-03-30 19:09 UTC (permalink / raw)
  To: tomas@tuxteam.de; +Cc: Pascal J. Bourguignon, help-gnu-emacs@gnu.org

"tomas@tuxteam.de" wrote on Monday, March 30, 2015 12:00 PM
> 
> On Mon, Mar 30, 2015 at 03:40:21PM +0000, Ludwig, Mark wrote:
> > "Pascal J. Bourguignon" wrote:
> >
> > > "Ludwig, Mark" <ludwig.mark@siemens.com> writes:
> > >
> > > > I find my custom Elisp generates warnings that seem pretty stupid.
> > > > For example:
> > > >
> > > > emacs.el:255:10:Warning: reference to free variable `if'
> 
> Bizarre.
> 
[...]
> Here: you're in the middle of a `cond' and the clause reads "(if ...)". I'd
> expect `cond' to try to interpret "if" as a naked variable (granted, the error
> message points at another place).

Doh!  At a minimum, I guess there is a small bug in how
the warnings are reported.  Oh, well.

Thanks!

Mark


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Compilation warnings of ELisp seem wrong and misleading
       [not found] <mailman.3018.1427724507.31049.help-gnu-emacs@gnu.org>
  2015-03-30 14:39 ` Compilation warnings of ELisp seem wrong and misleading Pascal J. Bourguignon
@ 2015-03-31  0:53 ` Emanuel Berg
  2015-04-01 11:45   ` Ludwig, Mark
       [not found]   ` <mailman.3123.1427888711.31049.help-gnu-emacs@gnu.org>
  1 sibling, 2 replies; 11+ messages in thread
From: Emanuel Berg @ 2015-03-31  0:53 UTC (permalink / raw)
  To: help-gnu-emacs

"Ludwig, Mark" <ludwig.mark@siemens.com> writes:

> emacs.el:255:10:Warning: reference to free variable
> `if' emacs.el:219:8:Warning: reference to free
> variable `save-excursion' emacs.el:331:41:Warning:
> reference to free variable `forward-char'
> emacs.el:261:17:Warning: reference to free variable
> `insert' emacs.el:261:17:Warning: reference to free
> variable `forward-sexp'
>
> Those are all valid functions. For example, here are
> lines 255-258:
>
> (if (not (= ans ?q)) (progn (goto-char found-start)
> (delete-region found-start found-end)))
>
> This is inside a large-ish "let*" form (111 lines).

It shouldn't say that of functions. Are you sure the
syntax is correct?

Nonetheless, I agree that the messages from the
compiler are sometimes cryptic and sometimes annoying.
But I've never experienced such crazy messages as
you report!

As for "should you compile your code?": one of the
reasons to do that apart from the supposed but seldom
noticed gains is that you can improve the quality of
your code and become a better lisper. It is
automatized feedback. And, because of that, it is even
more important that the error/warning messages
are understandable.

If you get the free variable warning when it is indeed
a variable that is mentioned, use the help -
`describe-variable' - to find out where it is defined,
then put (require 'library) above. If you don't want
to do that - for example for infrequently used modes -
use `defvar' yourself, e.g.

    (defvar ada-mode-hook)
    (setq ada-mode-hook
              (lambda ()
                (enable-line-mode)
                (setq ada-auto-case nil)
                (disable-super-global-keys) ))

> emacs.el:1326:76:Warning: Use `with-current-buffer'
> rather than save-excursion+set-buffer

Apart from them not adding even a single line
explanation why you should "rather" do that, this
warning is clear: instead of first `save-excursion'
(which has to do with point movement) and then
`set-buffer', you do `with-current-buffer'.
Those stuff do not seem to relate (to me), which is
why I'd be happy to see an explanation, but apparently
it is an intuitive (bad) thing to do, which they have
seen often, hence the warning.

> Mark Ludwig Lifecycle Coll Product Lifecycle
> Management
>
> Siemens Industry Sector Siemens Product Lifecycle
> Management Software Inc. 5939 Rice Creek Parkway
> Shoreview, MN 55126 United States Tel. :+1 (651)
> 855-6140 Fax :+1 (651) 855-6280
> ludwig.mark@siemens.com www.siemens.com/plm

Hint: Put your signature on a new line immediately
under two dashes and a whitespace, i.e. "-- ".
Go to this page [1] and make a search for
"Signature Convention" if you like details.

[1] http://www.ietf.org/rfc/rfc3676.txt

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: Compilation warnings of ELisp seem wrong and misleading
  2015-03-31  0:53 ` Emanuel Berg
@ 2015-04-01 11:45   ` Ludwig, Mark
  2015-04-01 12:02     ` tomas
  2015-04-02 10:20     ` Philipp Stephani
       [not found]   ` <mailman.3123.1427888711.31049.help-gnu-emacs@gnu.org>
  1 sibling, 2 replies; 11+ messages in thread
From: Ludwig, Mark @ 2015-04-01 11:45 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs@gnu.org

"Emanuel Berg" writes:

> As for "should you compile your code?": one of the
> reasons to do that apart from the supposed but seldom
> noticed gains is that you can improve the quality of
> your code and become a better lisper. It is
> automatized feedback. And, because of that, it is even
> more important that the error/warning messages
> are understandable.

In spite of pointing to the wrong source lines, the warnings
were basically correct.

Is there a way to get the warnings without writing a .elc
file?  I ask, because some time in the last few years, this
list convinced me that compiling my init file was a bad
idea.  I've lost track of /why/.  (*Sigh*)  I /think/ it has
to do with the error reporting, or maybe it predates my
addition of the little customization that automatically
byte-compiles a .el file if there's already a corresponding
.elc file, so there's little risk that the .elc gets picked
up when it's older than the source.  /That/ behavior (with
its little /completely/ /useless/ warning that the .el is
newer) drives me crazy!

Thanks,
Mark



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Compilation warnings of ELisp seem wrong and misleading
  2015-04-01 11:45   ` Ludwig, Mark
@ 2015-04-01 12:02     ` tomas
  2015-04-02 10:20     ` Philipp Stephani
  1 sibling, 0 replies; 11+ messages in thread
From: tomas @ 2015-04-01 12:02 UTC (permalink / raw)
  To: Ludwig, Mark; +Cc: help-gnu-emacs@gnu.org, Emanuel Berg

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Wed, Apr 01, 2015 at 11:45:00AM +0000, Ludwig, Mark wrote:

>                                     [...] it predates my
> addition of the little customization that automatically
> byte-compiles a .el file if there's already a corresponding
> .elc file, so there's little risk that the .elc gets picked
> up when it's older than the source.

Perhaps `byte-recompile-directory' is helpful to you?

- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlUb3kQACgkQBcgs9XrR2kZm6ACfQOOuqMIDLkF+BLc38tz4EmAy
y+4An2UWECEh1T3dljqhesI8y//eqwQs
=SyJB
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Compilation warnings of ELisp seem wrong and misleading
       [not found]   ` <mailman.3123.1427888711.31049.help-gnu-emacs@gnu.org>
@ 2015-04-01 23:08     ` Emanuel Berg
  0 siblings, 0 replies; 11+ messages in thread
From: Emanuel Berg @ 2015-04-01 23:08 UTC (permalink / raw)
  To: help-gnu-emacs

"Ludwig, Mark" <ludwig.mark@siemens.com> writes:

>> As for "should you compile your code?": one of the
>> reasons to do that apart from the supposed but
>> seldom noticed gains is that you can improve the
>> quality of your code and become a better lisper.
>> It is automatized feedback. And, because of that,
>> it is even more important that the error/warning
>> messages are understandable.
>
> In spite of pointing to the wrong source lines, the
> warnings were basically correct.
>
> Is there a way to get the warnings without writing
> a .elc file?

Interesting idea, if you are only concerned with
having the compiler tell you how to improve your code
it can be an alternative.

I don't know if there is a built-in way to do such
dry-runs, but if there is not, you can do a Makefile
which simply removes the .elc files immediately when
compilation is done.

However, there might be a better idea if the problem
is just the warning that the .emacs is newer than the
.elc, and that is to make a shell function that starts
Emacs and instead of just starting it, it will first
compile, only then start it. If there has been no
changes, with a Makefile, there will be no
recompilation, and if there have been changes, those
will be compiled first which is what you want.

So the shell function can look like this, if the
Makefile is in ~/.emacs.d/emacs-init:

    make -C ~/.emacs.d/emacs-init
    emacs

Here is the Makefile I use [1]. It has grown a bit
complicated by now, which is mostly a consequence of
me using separate files in a directory structure, not
just the ~/.emacs file. If you only have that file, it
should be ten times the more simple a Makefile, but it
should solve this issue nonetheless.

[1] http://user.it.uu.se/~embe8573/emacs-init/Makefile

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Compilation warnings of ELisp seem wrong and misleading
  2015-04-01 11:45   ` Ludwig, Mark
  2015-04-01 12:02     ` tomas
@ 2015-04-02 10:20     ` Philipp Stephani
  1 sibling, 0 replies; 11+ messages in thread
From: Philipp Stephani @ 2015-04-02 10:20 UTC (permalink / raw)
  To: Ludwig, Mark, Emanuel Berg, help-gnu-emacs@gnu.org

Ludwig, Mark <ludwig.mark@siemens.com> schrieb am Mi., 1. Apr. 2015 um
13:45 Uhr:

> Is there a way to get the warnings without writing a .elc
> file?


Flycheck.


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-04-02 10:20 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.3018.1427724507.31049.help-gnu-emacs@gnu.org>
2015-03-30 14:39 ` Compilation warnings of ELisp seem wrong and misleading Pascal J. Bourguignon
2015-03-30 15:40   ` Ludwig, Mark
2015-03-30 16:59     ` tomas
2015-03-30 19:09       ` Ludwig, Mark
     [not found]   ` <mailman.3032.1427730039.31049.help-gnu-emacs@gnu.org>
2015-03-30 17:08     ` Pascal J. Bourguignon
2015-03-31  0:53 ` Emanuel Berg
2015-04-01 11:45   ` Ludwig, Mark
2015-04-01 12:02     ` tomas
2015-04-02 10:20     ` Philipp Stephani
     [not found]   ` <mailman.3123.1427888711.31049.help-gnu-emacs@gnu.org>
2015-04-01 23:08     ` Emanuel Berg
2015-03-30 13:47 Ludwig, Mark

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.