unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Why isn't the string returned by symbol-name read-only?
@ 2010-01-23 20:55 Daniel Colascione
  2010-01-23 21:53 ` Chong Yidong
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Daniel Colascione @ 2010-01-23 20:55 UTC (permalink / raw)
  To: Emacs development discussions

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

Consider

(let ((name (symbol-name 'foo)))
  (aset name 0 ?x)
  (cons name (symbol-name 'foo)))

That yields ("xoo" . " xoo")

Now try


(let ((name (symbol-name 'car)))
  (aset name 0 ?x)
  (cons name (symbol-name 'car)))

That returns in an error when you try to evaluate it. The object
returned by (symbol-name 'car) must have some read-only bit set.

Why isn't that bit set for *all* symbol names?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (Darwin)

iEYEARECAAYFAktbYlAACgkQ17c2LVA10VsTLQCcCjDdAU9NSvOAVEMmVHfyhXxp
PRMAmgPmovQuhwTUwKGIFvd5giGQyXy4
=6FHg
-----END PGP SIGNATURE-----




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

* Re: Why isn't the string returned by symbol-name read-only?
  2010-01-23 20:55 Why isn't the string returned by symbol-name read-only? Daniel Colascione
@ 2010-01-23 21:53 ` Chong Yidong
  2010-01-24  0:33 ` alin.s
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Chong Yidong @ 2010-01-23 21:53 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Emacs development discussions

Daniel Colascione <daniel@censorshipresearch.org> writes:

> Consider
>
> (let ((name (symbol-name 'foo)))
>   (aset name 0 ?x)
>   (cons name (symbol-name 'foo)))
>
> That yields ("xoo" . " xoo")
>
> Now try
>
>
> (let ((name (symbol-name 'car)))
>   (aset name 0 ?x)
>   (cons name (symbol-name 'car)))
>
> That returns in an error when you try to evaluate it. The object
> returned by (symbol-name 'car) must have some read-only bit set.
>
> Why isn't that bit set for *all* symbol names?

Users will always have enough rope to hang themselves.  I don't think we
need to lose sleep over this, unless this is demonstrated to be a
problem in the real world.




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

* Re: Why isn't the string returned by symbol-name read-only?
  2010-01-23 20:55 Why isn't the string returned by symbol-name read-only? Daniel Colascione
  2010-01-23 21:53 ` Chong Yidong
@ 2010-01-24  0:33 ` alin.s
  2010-01-24  9:48   ` Thien-Thi Nguyen
  2010-01-24  1:12 ` Davis Herring
  2010-01-25  3:08 ` Stefan Monnier
  3 siblings, 1 reply; 7+ messages in thread
From: alin.s @ 2010-01-24  0:33 UTC (permalink / raw)
  To: Emacs-devel



This is an interesting question, and this is why I answer you.

In order to understand and use emacs at its real power you must learn
lisp. I recommend you to read and solve all the exercises from a book
like the original LISP Manual of McCarthy, or more recent course.

Emacs is a beautiful implementation of a Lisp system, and this is why
we love him.

To answer your question, first of all, try to compile thsese simple
programs:

main(){unix[(const char *)"emacs"]++;}
main(){unix[(const char[]){[0]="emacs"}]++;}

In the first case the constant "emacs" is put into .data, and in the
second into .rodata.

You will see that you get the same error.

Now let us see what happens when you declare a function CAR:
(extracted from data.c)


\f
/* Extract and set components of lists */

DEFUN ("car", Fcar, Scar, 1, 1, 0,
       doc: /* Return the car of LIST.  If arg is nil, return nil.
Error if arg is not nil and not a cons cell.  See also `car-safe'.

See Info node `(elisp)Cons Cells' for a discussion of related basic
Lisp concepts such as car, cdr, cons cell and list.  */)
     (list)
     register Lisp_Object list;
{
  return CAR (list);
}

To see in detail what that does, you can expand it using gcc -E: you
do (rm data.o && VERBOSE=1; make):


gcc -E -D_BSD_SOURCE   -Demacs -DHAVE_CONFIG_H  -I. -I/emacs/src .......... 
data.c

You will get:


Lisp_Object Fcar (Lisp_Object) ; struct Lisp_Subr __attribute__
((__aligned__ (1 << 3))) Scar = { PVEC_SUBR | (sizeof (struct Lisp_Subr) /
sizeof (int)), Fcar, 1, 1, "car", 0, 0}; Lisp_Object Fcar

     (list)
     register Lisp_Object list;
{
   <definition of CAR>
}

You see that before to define the function Fcar, it defines the structure
Scar:

Lisp_Object Fcar (Lisp_Object) ; struct Lisp_Subr __attribute__
((__aligned__ (1 << 3))) Scar = { PVEC_SUBR | (sizeof (struct Lisp_Subr) /
sizeof (int)), Fcar, 1, 1, "car", 0, 0}; 

Now let us see how this structure looks like:


struct Lisp_Subr
  {
    EMACS_UINT size;
    Lisp_Object (*function) ();
    short min_args, max_args;
    const char *symbol_name;
    char *intspec;
    char *doc;
  };

You see that the 4th parameter is const char *symbol_name  = "car".

So emacs tries to define the names of the symbols defined with DEFUN
into a zone of memory that the compiler marks as read-only. That means
that the lisp evaluator must know that it is not allowed to change
that zone.

Let us see further what happens:

By definition of emacs lisp system , the lisp symbols have to be
interned into the function syms_of_<file>. In this case, inside
syms_of_data (), defsubr (&Scar); Inside this function,


void
defsubr (sname)
     struct Lisp_Subr *sname;
{
  Lisp_Object sym;
  sym = intern_c_string (sname->symbol_name);
  XSETPVECTYPE (sname, PVEC_SUBR);
  XSETSUBR (XSYMBOL (sym)->function, sname);
}

Inside intern_c_string (const char *str), it is checked whether the
symbol with the name STR is already interned inside the main obarray,
and if not, it is internet using the final call. The first call of
intern_c_string happens exactly from defsubr statement, and this call
forces the symbol to be interned using make_pure_c_string. Next calls
of intern_c_string(the same string) happens from READ lisp function
(see read1()), and they already find the symbol interned.


Lisp_Object
intern_c_string (const char *str)
{
............
  return Fintern (make_pure_c_string (str), obarray);
}

return Fintern (make_pure_c_string (str), obarray);

Here it is the point:

make_pure_c_string (str)


Lisp_Object
make_pure_c_string (const char *data)
{
  Lisp_Object string;
  struct Lisp_String *s;
  int nchars = strlen (data);

  s = (struct Lisp_String *) pure_alloc (sizeof *s, Lisp_String);
  s->size = nchars;
  s->size_byte = -1;
  s->data = (unsigned char *) data;
  s->intervals = NULL_INTERVAL;
  XSETSTRING (string, s);
  return string;
}

Now the function pure_alloc:


/* Allocate room for SIZE bytes from pure Lisp storage and return a
   pointer to it.  TYPE is the Lisp type for which the memory is
   allocated.  TYPE < 0 means it's not used for a Lisp object.  */


Now we see the second function that you use : aset. We look at its
definition, and see:




DEFUN ("aset", Faset, Saset, 3, 3, 0,
       doc: /* Store into the element of ARRAY at index IDX the value
NEWELT.
Return NEWELT.  ARRAY may be a vector, a string, a char-table or a
bool-vector.  IDX starts at 0.  */)
     (array, idx, newelt)
     register Lisp_Object array;
     Lisp_Object idx, newelt;
{
....

CHECK_IMPURE (array);

}

The definition of CHECK_IMPURE is :

/* Signal an error if OBJ is pure.  */
#define CHECK_IMPURE(obj) \
  { if (PURE_P (obj))	  \
      pure_write_error (); }

and finally we get the result of the problem:


void
pure_write_error ()
{
  error ("Attempt to modify read-only object");
}


Here it is why the error is generated in the second case and not in
the first case.

In the first case, the symbol 'FOO is interned inside obarray during
the reading operation, while in the second case the symbol is interned
during the initialization of emacs, and this is different.

Note hoever in , that inside read1(), a symbol is interned inside pure
space if you set the variable Vpurify_flag accordingly. You can set
this variable using the evaluator (its name is pure, but its value is
not in pure storage, so the value can be changed ;) ).

I do not know why the idea of pure storage was introduced in emacs;
maybe in order to connect it to the idea of constant of C code, but I
am not absolutely sure. I have not met the idea of pure storage into a
standard course of Lisp. I do not know why Richard did want to insert
this concept.

I hope that my long message be useful. Sorry for any king of error
that mingled around.



Daniel Colascione-3 wrote:
> 
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Consider
> 
> (let ((name (symbol-name 'foo)))
>   (aset name 0 ?x)
>   (cons name (symbol-name 'foo)))
> 
> That yields ("xoo" . " xoo")
> 
> Now try
> 
> 
> (let ((name (symbol-name 'car)))
>   (aset name 0 ?x)
>   (cons name (symbol-name 'car)))
> 
> That returns in an error when you try to evaluate it. The object
> returned by (symbol-name 'car) must have some read-only bit set.
> 
> Why isn't that bit set for *all* symbol names?
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (Darwin)
> 
> iEYEARECAAYFAktbYlAACgkQ17c2LVA10VsTLQCcCjDdAU9NSvOAVEMmVHfyhXxp
> PRMAmgPmovQuhwTUwKGIFvd5giGQyXy4
> =6FHg
> -----END PGP SIGNATURE-----
> 
> 
> 
> 

-- 
View this message in context: http://old.nabble.com/Why-isn%27t-the-string-returned-by-symbol-name-read-only--tp27289855p27291323.html
Sent from the Emacs - Dev mailing list archive at Nabble.com.





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

* Re: Why isn't the string returned by symbol-name read-only?
  2010-01-23 20:55 Why isn't the string returned by symbol-name read-only? Daniel Colascione
  2010-01-23 21:53 ` Chong Yidong
  2010-01-24  0:33 ` alin.s
@ 2010-01-24  1:12 ` Davis Herring
  2010-01-24 11:19   ` alin.s
  2010-01-25  3:08 ` Stefan Monnier
  3 siblings, 1 reply; 7+ messages in thread
From: Davis Herring @ 2010-01-24  1:12 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Emacs development discussions

> That returns in an error when you try to evaluate it. The object
> returned by (symbol-name 'car) must have some read-only bit set.
>
> Why isn't that bit set for *all* symbol names?

It's set for that string not because `car' is too important to be changed,
but because it was created before Emacs was dumped.  (Of course, it is
created that early because it is important.)  Making such strings
read-only saves the time in checking whether they might need
garbage-collection later.  So it's purely an optimization; it's not meant
to protect anything.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.




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

* Re: Why isn't the string returned by symbol-name read-only?
  2010-01-24  0:33 ` alin.s
@ 2010-01-24  9:48   ` Thien-Thi Nguyen
  0 siblings, 0 replies; 7+ messages in thread
From: Thien-Thi Nguyen @ 2010-01-24  9:48 UTC (permalink / raw)
  To: Emacs-devel

() "alin.s" <alinsoar@voila.fr>
() Sat, 23 Jan 2010 16:33:18 -0800 (PST)

   the 4th parameter is [...]

Probably you mean "struct element".
A "parameter" is something that functions require.

   I do not know why the idea of pure storage was introduced in
   emacs; maybe in order to connect it to the idea of constant of
   C code, but I am not absolutely sure. I have not met the idea
   of pure storage into a standard course of Lisp. I do not know
   why Richard did want to insert this concept.

Pure storage is a (set of, in the case of VMS) memory range(s)
that can be written to (and subsequently read, quickly, from)
disk.  In other Lisp systems you might see the term "fasl".

   Sorry for any king of error that mingled around.

o king of error, precocious winnowing,
 why deny'd my runtime simmering,
where mingled are my symbols latent,
 where singled are my asets potent?

thi




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

* Re: Why isn't the string returned by symbol-name read-only?
  2010-01-24  1:12 ` Davis Herring
@ 2010-01-24 11:19   ` alin.s
  0 siblings, 0 replies; 7+ messages in thread
From: alin.s @ 2010-01-24 11:19 UTC (permalink / raw)
  To: Emacs-devel


Thanks.



Davis Herring wrote:
> 
>  So it's purely an optimization; it's not meant
> to protect anything.
> 
> Davis
> 
> -- 
> This product is sold by volume, not by mass.  If it appears too dense or
> too sparse, it is because mass-energy conversion has occurred during
> shipping.
> 
> 
> 
> 

-- 
View this message in context: http://old.nabble.com/Why-isn%27t-the-string-returned-by-symbol-name-read-only--tp27289855p27293923.html
Sent from the Emacs - Dev mailing list archive at Nabble.com.





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

* Re: Why isn't the string returned by symbol-name read-only?
  2010-01-23 20:55 Why isn't the string returned by symbol-name read-only? Daniel Colascione
                   ` (2 preceding siblings ...)
  2010-01-24  1:12 ` Davis Herring
@ 2010-01-25  3:08 ` Stefan Monnier
  3 siblings, 0 replies; 7+ messages in thread
From: Stefan Monnier @ 2010-01-25  3:08 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Emacs development discussions

> That returns in an error when you try to evaluate it. The object
> returned by (symbol-name 'car) must have some read-only bit set.

I don't know about "must" but I'd agree with "should".
It's not terribly important, tho, so any patch for it should better not
have any significant/noticeable impact.


        Stefan "who's known for thinking that *all* strings should be
                immutable"




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

end of thread, other threads:[~2010-01-25  3:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-23 20:55 Why isn't the string returned by symbol-name read-only? Daniel Colascione
2010-01-23 21:53 ` Chong Yidong
2010-01-24  0:33 ` alin.s
2010-01-24  9:48   ` Thien-Thi Nguyen
2010-01-24  1:12 ` Davis Herring
2010-01-24 11:19   ` alin.s
2010-01-25  3:08 ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).