Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[Language Design] How should references to localized special parameters behave?



What should the following script print?

typeset -n home=HOME
HOME=/bin; cd; pwd
function fn {
  typeset HOME=/usr; cd; pwd
  home=/var; cd; pwd
}
fn; cd; pwd

In particular, what should the effect of the assignment "home=/var" be? Currently, it triggers a segmentation fault.

The global "HOME" parameter is a special parameter that determines what Zsh considers as the home directory. The "cd" builtin, when invoked with no arguments, sets the current directory to the home directory. Thus, "cd" followed by "pwd" can be used to probe what Zsh considers as the home directory.

When a local parameter is defined with the same name as an enclosing special parameter (and no -h flag), then the local parameter inherits the specialness of the enclosing parameter. For that reason, "typeset HOME=/usr; cd; pwd" prints "/usr" (rather than "/bin"). When the local scope is exited, the specialness is returned to the enclosing parameter. Therefore, if "home=/var" is commented out, the last "pwd" prints "/bin".

The current implementation of "typeset HOME=/usr" moves the enclosing parameter into the current scope (i.e., assigns "locallocal" to "pm->level" where "pm" is the enclosing parameter's "Param" instance) and creates a pseudo parameter in the enclosing scope that stores the state of the enclosing parameter prior to the "typeset" (i.e., creates a "Param" instance that duplicates most of the fields of the enclosing parameter's "Param" instance). When the local scope is exited, the enclosing parameter is moved back to its original scope and its state is restored to its state prior to the "typeset" thanks to the values stored in the pseudo parameter, which is then discarded. The pseudo parameter isn't a real parameter because it lacks some internal attributes (in particular, the "gsu" field of its "Param" instance is not initialized). Nevertheless, the reference "home" currently refers to the pseudo parameter, which is why "home=/var" triggers a segmentation fault.

I see two ways of properly supporting references to localized special parameters.

One way is to consider that "typeset HOME=/usr" truly moves the special parameter to the local scope until that scope is exited, at which point the parameter is restored to its state prior to the "typeset". With that interpretation, there only ever exists a single HOME parameter. Therefore "home" should refer to the same variable as the global and local "HOME" and the script should produce the following output:

/bin
/usr
/var
/bin

Another way is to consider that "typeset HOME=/usr" creates a local parameter and truly moves the specialness of the enclosing parameter to the local parameter until the local scope is exited. With that interpretation, there are two distinct HOME parameters. The reference "home" refers to the enclosing one. The assignment "home=/var" occurs at a point in time when the enclosing parameter has lost its specialness. Therefore the script should produce the following output:

/bin
/usr
/usr
/var

Both ways are somewhat disturbing. The former because "typeset" moves rather than creates a parameter. The latter because it enables temporarily striping special parameters of their specialness.

The former has the advantage that it plays well with tied parameters (à la PATH/path). With it, there only ever exists one instance of each of the two tied parameters, which thus can remain tied at all times. With the latter, one has to consider what happens if one or the other of the two tied parameters is localized, or both, possibly in different scopes. How does tying work in all these cases? Which parameters are tied to which ones?

I'm leaning towards the former and therefore haven't yet tried to figure out how to handle tying with the latter. However, ksh implements the latter but ksh doesn't have support for tied parameters.

Wdyt? Which way should Zsh adopt? Or do you see an alternative way?

Philippe



Messages sorted by: Reverse Date, Date, Thread, Author