Check-in [7ff5dde719]

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Updated TIP 500 in light of implementation experience.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7ff5dde719885f7394c8adce89ad344aa5ae5f3bc63c7f304407e5ae8830ade3
User & Date: dkf 2018-05-19 08:37:09
Context
2018-05-19
10:48
Added an example check-in: e6ade010a0 user: dkf tags: trunk
08:37
Updated TIP 500 in light of implementation experience. check-in: 7ff5dde719 user: dkf tags: trunk
2018-05-17
12:58
TIP #491 Done check-in: a23088053b user: jan.nijtmans tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to tip/500.md.

    32     32   mechanism does not need to be totally proof against prying (and introspection
    33     33   mechanisms are desirable) as TclOO deliberately does not provide security
    34     34   mechanisms; such mechanisms are the purpose of Tcl's interpreters. All that is
    35     35   desired is a way of ensuring that code does not inadvertently trample other
    36     36   code, allowing a superclass to evolve its implementation without needing to
    37     37   take into account every detail of its subclasses.
    38     38   
           39  +# Private Declarations: Syntax and Immediate Semantics
           40  +
           41  +This TIP introduces a new definition command, **private**, that is present
           42  +when doing both **oo::define** and **oo::objdefine**. Much as with the
           43  +**self** definition command (or the **oo::define** and **oo::objdefine**
           44  +commands themselves), it takes either single arguments or a list of arguments
           45  +(that it then builds a script of by turning them into a list) and evaluates
           46  +the result in a special context. The special context is the same as the outer
           47  +definition context, except that some definition commands instead create
           48  +_private definitions_ in that context.
           49  +
           50  +The following commands are private-definition aware:
           51  +
           52  +  * **forward** — the forwarded method it creates is a _private method_.
           53  +  * **method** — the procedure-like method it creates is a _private method_.
           54  +  * **self** (in **oo::class**) — the definitions on the class instance inside
           55  +    will be _private definitions_ (if the concept applies).
           56  +  * **variable** — the variable resolution rules created or manipulated (as
           57  +    this is a slot) will be for _private variables_.
           58  +
           59  +If provided with no arguments, the **private** definition command will return
           60  +whether it was invoked from a context that should create private definitions.
           61  +Otherwise it returns the result of evaluating its script.
           62  +
           63  +The meaning of a private method and a private variable is defined below.
           64  +
    39     65   # Detailed Proposal: Methods
    40     66   
    41     67   For methods, as they actually exist in storage that is totally controlled by
    42     68   TclOO (and which is not addressable other than via TclOO-created commands or
    43     69   introspectors) the main complexity is working out what lookups are possible in
    44     70   a particular case while ensuring that method lookups are fast. Determining
    45     71   what the context class (or instance) is easy enough, as that's present pretty
................................................................................
    52     78   inside a method that is part of the class *but a different instance* or
    53     79   possibly even a *different subclass* of that class, then that method will be
    54     80   found. That makes this a useful mechanism that is not provided by the TclOO
    55     81   system in Tcl 8.6.
    56     82   
    57     83   ## Method Invoke Semantics
    58     84   
    59         -When a method is invoked, a public (or unexported, if via the **self**
    60         -command) method is always preferred. However, if the resolution of the method
    61         -would result in no resolution of the method, private methods are also
    62         -searched. The private methods that are searched are those of the declaration
    63         -context (class or method) of the currently executing method only; subclasses
    64         -and superclasses are _not_ examined. Filters are still applied to the outside
    65         -of the method call, but the actual private method has no need to ever call
    66         -**next** or **nextto**; it is always the terminal method implementation in its
    67         -method call chain.
           85  +When a method is invoked, a public (or unexported, if via the **my** command)
           86  +method is usually preferred. However, if the class of the object on which the
           87  +method is called is also the class that defined the currently executing method
           88  +(specifically, is the creator of the method that defines the current stack
           89  +frame at the point of the call), bearing in mind that the determination of
           90  +this also respects the inheritance and mixin hierarchies, then private methods
           91  +on that context class will also be found. Similarly, if the currently
           92  +executing method was defined by an object and that object is the object to
           93  +which the method invoke is directed, private methods on that object are also
           94  +found (the author expects these to be a rarely used feature). Searches for
           95  +private methods precede the equivalent public and unexported methods in the
           96  +method resolution order, but share a common naming space (i.e., they're stored
           97  +in the same hash tables) so that there are no ambiguities.
           98  +
           99  +Since every method has at most one declaring class or object (and not both
          100  +simultaneously) there is at most one private method that can be on any call
          101  +chain. External calls (e.g., from the top level of Tcl, from a **namespace
          102  +eval**, from a procedure) will never have a private method on thir call
          103  +chains.
          104  +
          105  +Once the call chain is created, the execution is handled as prior to this TIP;
          106  +the implementation of the first element on the call chain is executed,
          107  +whatever that is, and that can dispatch to later items on the call chain using
          108  +**next** and **nextto**.
    68    109   
    69    110   A private method on a class (or object) may not have the same name as another
    70    111   method on that class; all methods of a class (or object) are part of a single
    71    112   space of names. When resolving a method call of a subclass of the class that
    72    113   has the private method, even if the method names match, the private method
    73    114   does not participate in the call chain; only an exact match from exactly the
    74    115   right context counts.
................................................................................
    77    118   
    78    119       oo::class create Top {
    79    120           method Foo {} {
    80    121               puts "This is Top::Foo for [self]"
    81    122           }
    82    123       }
    83    124       oo::class create Super {
          125  +        superclass Top
    84    126           private method Foo {} {
    85    127               puts "This is Super::Foo for [self]"
    86    128           }
    87    129           method bar {other} {
    88    130               puts "This is Super::bar for [self]"
    89    131               my Foo
    90    132               [self] Foo
................................................................................
    96    138           method Foo {} {
    97    139               puts "This is Sub::Foo for [self]"
    98    140               next
    99    141           }
   100    142           private method bar {other} {
   101    143               error "This should be unreachable"
   102    144           }
          145  +        method grill {} {
          146  +            puts "This is Sub::grill for [self]"
          147  +            my Foo
          148  +        }
   103    149       }
   104    150       Sub create obj1
   105    151       Sub create obj2
   106    152       obj1 bar obj2
          153  +    obj1 grill
   107    154   
   108    155   is expected to print out:
   109    156   
   110    157       This is Super::bar for ::obj1
   111         -    This is Sub::Foo for ::obj1
   112         -    This is Top::Foo for ::obj1
          158  +    This is Super::Foo for ::obj1
   113    159       This is Super::Foo for ::obj1
   114    160       This is Super::Foo for ::obj2
          161  +    This is Sub::grill for ::obj1
          162  +    This is Sub::Foo for ::obj1
          163  +    This is Top::Foo for ::obj1
   115    164   
   116         -Note that the call via **my** picks up the unexported method from the
   117         -subclass, and that the call from outside does not find the method on _Sub_,
   118         -and the call to **next** does not pick up the method on _Super_.
   119         -
   120         -Private methods on object instances are similar, and are only visible from
   121         -other instance methods on the same object. The author expects them to be
   122         -rarely used.
          165  +Note that the calls via **my**, **self** and through the public handle of
          166  +another object all pick up the private method from _Super_,
          167  +and the call to **next** from _Sub_ does not pick up the method on _Super_ but
          168  +instead goes straight to _Top_.
   123    169   
   124    170   ## Creation and Introspection
   125    171   
   126    172   Private methods are created calling **oo::define** (and **oo::objdefine**, and
   127    173   via the constructor of **oo::class**) like this:
   128    174   
   129    175       oo::define TheClass {
   130    176           private method foo {...} {
   131    177               ...
   132    178           }
   133    179           private forward bar  SomeOtherCommand
   134    180       }
   135    181   
   136         -More formally, the **private** definition command sets a flag for the duration
   137         -of its execution that causes any methods (of any standard type) defined in the
   138         -current definition context to be marked as being private rather than using the
   139         -usual public/unexported semantics.  All remaining arguments are then
   140         -concatenated as a proper Tcl list and the result evaluated in the current
   141         -context. It has no effect on recursive calls, or on the **export** or
   142         -**unexport** definition commands, or on any custom declaration types.
   143         -
   144    182   At the C API level, private methods can be directly created by setting the
   145         -*flags* parameter (called *isPublic* in older versions of the API) to the
   146         -constant `TCL_OO_METHOD_PRIVATE`. This lets custom types of methods be
   147         -declared by their C code directly.
          183  +*flags* parameter (called *isPublic* in older versions of the API) of
          184  +`Tcl_NewMethod` and `Tcl_NewInstanceMethod` to the constant
          185  +`TCL_OO_METHOD_PRIVATE`. This lets custom types of methods be declared private
          186  +by their C code directly.
   148    187   
   149    188   Introspection is done via appropriate options to **info class methods** and
   150    189   **info object methods**. In particular, they are never returned when the
   151    190   **-all** option is given, are found when **-private** option is given (unless
   152    191   the **-all** option is _also_ given), and can be found when the new option
   153    192   **-scope** is given, depending on what scope is chosen from the options below:
   154    193   
................................................................................
   235    274   returns the creation ID of any existing object. It also applies to classes.
   236    275   Again, note that creation IDs are _always_ system-allocated and are _never_
   237    276   guaranteed to be unique between interpreters, either in multiple processes or
   238    277   in the same thread or process; they are only ever locally unique.
   239    278   
   240    279   # Implementation
   241    280   
   242         -Not yet done.
          281  +See the [`tip-500` branch](https://core.tcl.tk/tcl/timeline?r=tip-500).
   243    282   
   244    283   # Copyright
   245    284   
   246    285   This document has been placed in the public domain.