This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: tie variable


Jim Blandy <jimb@red-bean.com> writes:

> [It] seems inevitable to me that an Emacs lisp 'let' must change the
> binding of a global variable to a thread-local value.

Yes, this seems to be precisely what we want.

> > I thought we were going to translate the code, and then it should be
> > possible to translate a variable reference into an arbitrary
> > expression, e.g. into a byte-code object (similar to a gloc) which
> > references a fluid.
> 
> No, this isn't correct.  Any global variable in Emacs Lisp can be
> re-bound by a let, so unless you want to represent every Emacs Lisp
> global with a fluid, this won't work.

Well, I think it could be just a simple global until it gets rebound.
Below I include a piece of code which demonstrates what kind of
expression (a `@fluid-ref' form) the translator could produce for an
Elisp variable, and, also, how this expression could be interpreted in
the current evaluator.

This is probably very similar to what you actually were thinking.

The let-form itself could be translated into a `@bind' construct.  The
current `@bind' does not use fluids, but could easily be modified to
do so.  The modified `#@bind'-construct (the memoized form) would
contain a sequence of fluid keys and vcells so that binding is
efficient.

> > > To reduce the overhead, we could make the `unbound' value, which the
> > > interpreter already checks for, one of these objects, whose reference
> > > and assignment functions signal an `unbound variable' error.
> > > 
> > > Does the interpreter check for unbound values in local variables?
> > 
> > No, it does this only the first time the variable is referenced.
> 
> Actually, it's not necessary to change the way local variables work,
> only global variables.  There are no "local" variables in Emacs Lisp
> --- just global variables which have are temporarily rebound.

Yes.  Since I got the general impression that you wanted support
without translation, I thought you had the idea to use the lexical
mechanism for scoping, and that this "special" value "passed on" to
the dynamic mechanism.

With translation, however, there's no need for such complexity.

OK, here's some code:

SCM_SYNTAX (s_atfluid_ref, "@fluid-ref", scm_makmmacro, scm_m_atfluid_ref);

/*
 * Macro: (@fluid-ref VARNAME) => (#@fluid-ref . () . FLUID-KEY . GLOC-CDRPTR)
 *
 * The (W0 . W1 . W2 . W3) syntax represents a single 4-word cell.
 *
 * #@fluid-ref  byte-code (ISYM) for primitive fluid ref
 * ()		the empty list
 * FLUID-KEY    getspecific key for a fluid associated with this variable.
 * GLOC-PTR     pointer to the CDR (the value) of the gloc of this variable.
 *
 */

SCM
scm_m_atfluid_ref (SCM xorig, SCM env)
{
  SCM varname, vcell, z;
  scm_key_t fluid_key;
  
  SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1
	      && SCM_SYMBOLP (SCM_CADR (xorig)),
	      xorig, scm_s_expression, s_atfluid_ref);
  varname = SCM_CADR (xorig);
  /*
   * Compute fluid_key using the mapping
   *
   *  ENV x VARNAME --> FLUID
   *
   * Compute vcell using the environment API
   *
   *  ENV x VARNAME --> VCELL
   */
  SCM_NEWCELL2 (z);
  SCM_SET_CELL_WORD_0 (z, SCM_IM_ATFLUID_REF);
  SCM_SET_CELL_WORD_1 (z, SCM_EOL);
  SCM_SET_CELL_WORD_2 (z, fluid_key);
  SCM_SET_CELL_WORD_3 (z, SCM_CDRLOC (vcell));

  return z;
}

/* And here's code to put into the evaluator:
 */

{
  	case (SCM_ISYMNUM (SCM_IM_ATFLUID_REF)):
	  t.arg1 = scm_thread.getspecific ((scm_key_t) SCM_CELL_WORD_2 (x));
	  if (SCM_UNPACK (t.arg1))
	    RETURN (t.arg1);
	  else
	    RETURN (* (SCM *) SCM_CELL_WORD_3 (x));
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]