develooper Front page | perl.perl5.porters | Postings from January 2012

[perl #108286] Wishlist: Overridable keywords

Thread Next
From:
Father Chrysostomos
Date:
January 15, 2012 12:51
Subject:
[perl #108286] Wishlist: Overridable keywords
Message ID:
rt-3.6.HEAD-14510-1326660668-1023.108286-75-0@perl.org
# New Ticket Created by  Father Chrysostomos 
# Please include the string:  [perl #108286]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=108286 >


This touches on issues in tickets #84690, #94480, #96116, #105924, #105926 and #105928.

I have been thinking about this from time to time, and I think I finally have all the edge cases worked out:

Proposal
--------

I propose that we make ‘use feature "overrides"’ allow all keywords to be overridden.

Infix operators like ‘and’ will continue to be overridable only in non-infix positions.  I.e., ‘use subs "and"; sub and () {} and and and’ will continue to parse as ‘&and && &and’, as it currently does.  Allowing overridable infix operators would be nice, but is not part of this proposal.  Maybe that can come later.

The keywords do, require and glob are currently not overridable as keywords.  Overrides cannot change their syntax, but only their behaviour.  In other words, overrides of these keywords are actually callbacks, rather than overrides.

I propose that whether overrides of those three keywords are actual keyword overrides depend on whether the ‘overrides’ feature is enabled in the scope where the subroutine is defined, not where it is used.  For XS functions, I don’t know which way we should do it.  We probably need a new XS keyword, similar to PROTOTYPE.

I also propose that we add an :iter attribute, that will allow custom subs to get the special defined() treatment that glob and readline get inside a while() condition.  (while(glob "foo") is equivalent to while(defined(glob "foo")).)

All special-casing for parsing require VERSION should be removed from the tokenizer.  ck_require can flag the op if it has a single unfolded numeric or vstring constant for its kidop.  require VERSION should not delegate to a callback (‘override’) any more.

glob overrides should no longer be passed a second argument.  The only code using the undocumented second argument anywhere on CPAN is in the core and can be changed.

<> should continue to call glob and readline overrides automatically.

Reasoning
---------

This should be in a feature feature, because otherwise the existence of a length method will cause every subsequent use of length() in the same file to produce a warning.

do, glob, and require should be overridable based on the hints where the sub is defined, not where the sub is used, because otherwise this would violate existing subs’ expectations. Existing require subs expect to receive "Foo/Bar.pm" rather than "Foo::Bar".  A true override (with a * prototype) would leave it as "Foo::Bar".  Similarly for glob overrides: an existing custom glob function might expect the automatic defined() in while(glob()).

The purpose of the :iter attribute is to avoid adding too many more hacks to fix bug #84690.  It also allows true glob overrides to retain that feature.

Parsing of require VERSION is currently very screwy.  It is not even consistent with itself.  require also has the num/str bug, in that it tries to decide based on the type of its operand whether it will be a version number or a file name.  We cannot fix that bug unless we make require VERSION a *syntactic* special case.  In that case require $version would no longer work (thank goodness!).  That means that require overrides would no longer be able to do CORE::require($_[0]), unless we stop calling the override in the case of a version number.  That would apply only to ‘callback-style’ overrides; i.e., the old kind.  require overrides defined under ‘use feature "overrides"’ would be true overrides which would not go through the special parsing at all, but would be required (i.e., allowed) to implement it themselves, if at all.

My reason for putting require parsing in this ticket is that it is inextricably linked to the overrides feature.  It’s hard to change one without the other.

The reason for eliminating the second argument to glob() (did you even know about it?) is that <> will continue to call glob overrides, and glob implementations that want to accept lists will still be expected to handle <>’s calling convention.

---
Flags:
    category=wishlist
    severity=low
---
Site configuration information for perl 5.15.6:

Configured by sprout at Sat Dec 31 10:12:16 PST 2011.

Summary of my perl5 (revision 5 version 15 subversion 6) configuration:
  Local Commit: b2635083831c8935c437465bbeb03aec8b599c01
  Ancestor: 407287f90891c4292ac8268e6566164f3992e28e
  Platform:
    osname=darwin, osvers=10.5.0, archname=darwin-thread-multi-2level
    uname='darwin pint.local 10.5.0 darwin kernel version 10.5.0: fri nov 5 23:20:39 pdt 2010; root:xnu-1504.9.17~1release_i386 i386 '
    config_args='-de -Dusedevel -Duseithreads -DDEBUGGING -Dmad'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-common -DPERL_DARWIN -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
    optimize='-O3 -g',
    cppflags='-fno-common -DPERL_DARWIN -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.2.1 (Apple Inc. build 5664)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib
    libs=-ldbm -ldl -lm -lutil -lc
    perllibs=-ldl -lm -lutil -lc
    libc=, so=dylib, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector'

Locally applied patches:
    

---
@INC for perl 5.15.6:
    /usr/local/lib/perl5/site_perl/5.15.6/darwin-thread-multi-2level
    /usr/local/lib/perl5/site_perl/5.15.6
    /usr/local/lib/perl5/5.15.6/darwin-thread-multi-2level
    /usr/local/lib/perl5/5.15.6
    /usr/local/lib/perl5/site_perl
    .

---
Environment for perl 5.15.6:
    DYLD_LIBRARY_PATH (unset)
    HOME=/Users/sprout
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About