On 11/10/2010 09:50 AM, Bart Schaefer wrote: > On Nov 9, 3:08pm, Eric Blake wrote: > } > } 1. Implementation aspect: > } How hard would it be to add static scoping to zsh? > > Just to elaborate on this, as I've been fooling with parameter scopes a > bit lately (http://www.zsh.org/mla/workers//2010/msg00719.html) ... > > Zsh currently maintains scopes as [what amounts to] a parallel stack > alongside the function call stack, with scope depth indexed by the > call stack depth. A variable expansions finds its object at the > uppermost frame of the scope stack in which that variable's name has > been "mentioned" with either typeset/local/declare or undef; if it is > not found at all, assignment creates it in the global frame. Note, > though, that the global frame is simply the bottom of the stack, not > handled separately except for some special cases for stack depth 0. > > Therefore it's at least moderately difficult to add static scoping. > > } Is it something that can be added in addition to dynamic scoping, via > } the use of an option to select the non-default mode (for example, 'local > } -d' to force dynamic, 'local -s' to force static, and 'local' to go with > } default scoping)? > > It might be possible to flag a variable in a given frame as static and > thereby cause it to be skipped when the current call depth does not > match the stack depth where the variable was "mentioned", but due to > the details of the implementation [*] I can't think of any reasonable > way to mark entire frames static or dynamic as implied by having two > different function styles. Maybe that doesn't matter as long as all > undeclared variables in either kind of scope are global, because then > the state of the frame matters only when "local" is used in that frame. > > [*] Cf. "what amounts to" -- in reality, every variable has its own > independent stack which comes into being only when the variable is > "mentioned", so that it's not necessary to walk the stack to find > the uppermost frame for a given variable. You are correct that ksh93 currently has two flavors of functions: POSIX functions 'f () {...}', currently no scoping support ksh functions 'function f {...}', supports static scoping But I see no need to standardize on this. My current thoughts for POSIX standardization are: keep a single function syntax (ksh can continue to use 'function' as a reserved word, and with alternate function syntax, but that would be an extension and not mandatory; bash can continue to use function as an alternate spelling for POSIX functions without the split in functionality used by ksh) provide the 'typeset' special built-in, which is required to obey XBD 12.2 (that is, it must honor --), so as to allow implementations to support extensions such as 'typeset -a' for declaring array variables require that 'typedef' used without options and within a function body provide a statically scoped local variable. Possible require a few other commonly implemented 'typedef -X' options, such as 'typedef -p' for printing the current set of locally scoped variables (much like 'export -p). only require static scoping (for ksh93), but additionally allow dynamic scoping as an extension (this would be the course used by bash and zsh, to preserve their current user base of tab-completion that expects dynamic scoping) continue to allow the ksh extension of reference variables (since ksh uses this in in lieu of dynamic scoping for exposing local variables to secondary functions), although I don't see this implemented in bash or zsh For implementations that want to provide static and dynamic scoping simultaneously (bash, zsh), I think the following implementation would do just fine: + Create two variants of 'local': 'local -d' for dynamic scoping, and 'local -s' for static scoping (which version was used determines whether a variable is marked as static on the variable stack). For backwards compatibility, 'local' becomes 'local -d'. + Make 'typedef' become a synonym for 'local -s' (or keep 'typedef' as a synonym for 'local', and add a a shell option that determines whether 'local' defaults to 'local -d' or 'local -s', where that option is auto-set according to posix mode) + Within a function, when referencing a variable: + if the variable was declared within that function, use it (doesn't matter whether it was declared with 'local -s' or 'local -d') + if the variable was not declared within that function, then travel up the variable declaration stack to the first instance of the variable that was not marked static (if the script only uses static scoping, then this requires traversing the entire stack of variables, but will settle on the global scope; if the script only uses dynamic scoping, then this will find the very first variable on the stack) -- Eric Blake eblake@xxxxxxxxxx +1-801-349-2682 Libvirt virtualization library http://libvirt.org
Attachment:
signature.asc
Description: OpenPGP digital signature