Index: TODO =================================================================== diff -u -r187fbd20a453ae9d73e9b48f88b8d6a8c79685c2 -rf41ae7e802868efee95b5d5682edfdbbe9ba2f64 --- TODO (.../TODO) (revision 187fbd20a453ae9d73e9b48f88b8d6a8c79685c2) +++ TODO (.../TODO) (revision f41ae7e802868efee95b5d5682edfdbbe9ba2f64) @@ -3606,20 +3606,17 @@ in objectParameterSlots - doc: - * integrate ::nx::doc::make with Makefile.in + * integrated ::nx::doc::make with Makefile.in (provide shell calls and, targets and dependencies) - - * provide a different flag for the generation of the documentation + * provided a different flag for the generation of the documentation (-develop, .... or -final) to show/hide it. - SS: By "it", you refer to the glossary? - - * separate entries for methods and hooks (can't be called if not defined)? + * separated entries for methods and hooks (can't be called if not defined)? hooks: * recreate should only be called internally, similarly "init" etc. * __unknown unknown is a hook for Object but a method for Class -- strange refcounting bug in 8.6b2 bug-is-86.tcl +- fixed strange refcounting bug in 8.6b2 bug-is-86.tcl where 2 refcounted items are not freed (value:class, issued from nx.tcl around line 120). Compile with DEBUG86B2 for more info @@ -3638,6 +3635,17 @@ } ================================================= +- nsf.c: cleanup on DEBUG86B2 + +- nx.tcl: + * do not namespace import my into ::nx + * replace usages of "my" by colon invocations + +- doc: + * extended method resolution section + * documented invocation flags for colon + + TODO: - warnings for "numeric" names for args and nonpos-args? - special handling of values looking like nonpos-flags, Index: doc/next-migration.html =================================================================== diff -u -r686684910e44fac172d7bcd8440aa23e44c7df5b -rf41ae7e802868efee95b5d5682edfdbbe9ba2f64 --- doc/next-migration.html (.../next-migration.html) (revision 686684910e44fac172d7bcd8440aa23e44c7df5b) +++ doc/next-migration.html (.../next-migration.html) (revision f41ae7e802868efee95b5d5682edfdbbe9ba2f64) @@ -1768,7 +1768,7 @@ the default protection for properties. The defaults can be overwritten also e.g. on a class level.</p></div> <div class="paragraph"><p>NX provides means for method hiding via the method modifier -<tt>private</tt>. Hidden methods can be invoked only via +my -local<br /> +<tt>private</tt>. Hidden methods can be invoked only via the <tt>-local</tt> flag, which means: "call the specified method defined in the same class/object as the currently executing method".</p></div> <div class="tableblock"> @@ -1812,13 +1812,13 @@ <pre class='nx'><span class='nx-comment'># Hiding of methods via "private" </span><span class='nx-comment'># </span><span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> Base { - :<span class='nx-keyword'>private</span> <span class='nx-keyword'>method</span> baz {a b} { <span class='nx-keyword'>expr</span> {<span class='nx-variable'>$a</span> + <span class='nx-variable'>$b</span>} } - :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> foo {a b} { <span class='nx-keyword'>my</span> -local baz <span class='nx-variable'>$a</span> <span class='nx-variable'>$b</span> } + :<span class='nx-keyword'>private</span> <span class='nx-keyword'>method</span> baz {a b} {<span class='nx-keyword'>expr</span> {<span class='nx-variable'>$a</span> + <span class='nx-variable'>$b</span>}} + :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> foo {a b} {: -local baz <span class='nx-variable'>$a</span> <span class='nx-variable'>$b</span>} } <span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> Sub -<span class='nx-keyword'>superclass</span> Base { - :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> bar {a b} { <span class='nx-keyword'>my</span> -local baz <span class='nx-variable'>$a</span> <span class='nx-variable'>$b</span> } - :<span class='nx-keyword'>private</span> <span class='nx-keyword'>method</span> baz {a b} { <span class='nx-keyword'>expr</span> {<span class='nx-variable'>$a</span> * <span class='nx-variable'>$b</span>} } + :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> bar {a b} {: -local baz <span class='nx-variable'>$a</span> <span class='nx-variable'>$b</span>} + :<span class='nx-keyword'>private</span> <span class='nx-keyword'>method</span> baz {a b} {<span class='nx-keyword'>expr</span> {<span class='nx-variable'>$a</span> * <span class='nx-variable'>$b</span>}} :<span class='nx-keyword'>create</span> s1 } @@ -6856,7 +6856,7 @@ <div id="footer"> <div id="footer-text"> Version 2.1<br /> -Last updated 2011-09-05 13:18:52 CEST +Last updated 2011-09-28 12:50:54 CEST </div> </div> </body> Index: doc/next-migration.txt =================================================================== diff -u -r686684910e44fac172d7bcd8440aa23e44c7df5b -rf41ae7e802868efee95b5d5682edfdbbe9ba2f64 --- doc/next-migration.txt (.../next-migration.txt) (revision 686684910e44fac172d7bcd8440aa23e44c7df5b) +++ doc/next-migration.txt (.../next-migration.txt) (revision f41ae7e802868efee95b5d5682edfdbbe9ba2f64) @@ -660,7 +660,7 @@ also e.g. on a class level. NX provides means for method hiding via the method modifier -+private+. Hidden methods can be invoked only via +my -local + ++private+. Hidden methods can be invoked only via the +-local+ flag, which means: "call the specified method defined in the same class/object as the currently executing method". @@ -677,13 +677,13 @@ # Hiding of methods via "private" # nx::Class create Base { - :private method baz {a b} { expr {$a + $b} } - :public method foo {a b} { my -local baz $a $b } + :private method baz {a b} {expr {$a + $b}} + :public method foo {a b} {: -local baz $a $b} } nx::Class create Sub -superclass Base { - :public method bar {a b} { my -local baz $a $b } - :private method baz {a b} { expr {$a * $b} } + :public method bar {a b} {: -local baz $a $b} + :private method baz {a b} {expr {$a * $b}} :create s1 } Index: doc/next-tutorial.html =================================================================== diff -u -r61a1c5c9e11a0277be442d98572bae6a3162cf1f -rf41ae7e802868efee95b5d5682edfdbbe9ba2f64 --- doc/next-tutorial.html (.../next-tutorial.html) (revision 61a1c5c9e11a0277be442d98572bae6a3162cf1f) +++ doc/next-tutorial.html (.../next-tutorial.html) (revision f41ae7e802868efee95b5d5682edfdbbe9ba2f64) @@ -1892,7 +1892,7 @@ <em>forwarders</em> and <em>aliases</em>.</p></div> <div class="exampleblock"> <div class="content"> -<div class="paragraph"><p>An <strong>accessor</strong> is a (in most cases) C-implemented method to access +<div class="paragraph"><p>An <strong>accessor method</strong> is a (in most cases) C-implemented method to access instance variables of an object. A call to an accessor with no arguments uses the accessor as a getter, obtaining the value of the associated variable. A call to an accessor with an argument uses it as a setter, @@ -2024,7 +2024,7 @@ <tt>fido::tail</tt>.</p></div> <div class="exampleblock"> <div class="content"> -<div class="paragraph"><p>A <strong>forwarder</strong> is a +<div class="paragraph"><p>A <strong>forwarder method</strong> is a C-implemented method to redirect an invocation for a certain method to either a method of other object or to some other method of the same object. Forwarding an invocation of a method to some other @@ -2042,8 +2042,9 @@ <h4 id="_method_aliases">3.2.3. Method-Aliases</h4> <div class="exampleblock"> <div class="content"> -<div class="paragraph"><p>A <strong>method alias</strong> is a means to register an existing method, a Tcl proc or -command under as a method with a certain name on a class or object.</p></div> +<div class="paragraph"><p>An <strong>alias method</strong> is a means to register an existing method, or a +Tcl proc or a Tcl command as a method with the provided +name on a class or object.</p></div> </div></div> <div class="paragraph"><p>In some way, the method alias is a restricted form of a forwarder, but it does not support delegation to different objects and argument @@ -2111,7 +2112,7 @@ called from every context. A <strong>protected</strong> method can only be invoked from the same object. A <strong>private</strong> method can be only invoked from methods defined on the same entity (e.g. defined on the same class) -via <tt>my -local</tt>.</p></div> +via the invocation with the local flag (i.e. "<tt>: -local</tt>").</p></div> </div></div> <div class="paragraph"><p>All kind of methods protection are applicable for all kind of methods, either scripted or C-implemented.</p></div> @@ -2213,13 +2214,13 @@ 13 14 </pre></td><td class='nx-body'><pre class='nx'><span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> Base { - :<span class='nx-keyword'>private</span> <span class='nx-keyword'>method</span> helper {a b} { <span class='nx-keyword'>expr</span> {<span class='nx-variable'>$a</span> + <span class='nx-variable'>$b</span>} } - :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> foo {a b} { <span class='nx-keyword'>my</span> -local helper <span class='nx-variable'>$a</span> <span class='nx-variable'>$b</span> } + :<span class='nx-keyword'>private</span> <span class='nx-keyword'>method</span> helper {a b} {<span class='nx-keyword'>expr</span> {<span class='nx-variable'>$a</span> + <span class='nx-variable'>$b</span>}} + :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> foo {a b} {: -local helper <span class='nx-variable'>$a</span> <span class='nx-variable'>$b</span>} } <span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> Sub -<span class='nx-keyword'>superclass</span> Base { - :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> bar {a b} { <span class='nx-keyword'>my</span> -local helper <span class='nx-variable'>$a</span> <span class='nx-variable'>$b</span> } - :<span class='nx-keyword'>private</span> <span class='nx-keyword'>method</span> helper {a b} { <span class='nx-keyword'>expr</span> {<span class='nx-variable'>$a</span> * <span class='nx-variable'>$b</span>} } + :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> bar {a b} {: -local helper <span class='nx-variable'>$a</span> <span class='nx-variable'>$b</span>} + :<span class='nx-keyword'>private</span> <span class='nx-keyword'>method</span> helper {a b} {<span class='nx-keyword'>expr</span> {<span class='nx-variable'>$a</span> * <span class='nx-variable'>$b</span>}} :<span class='nx-keyword'>create</span> s1 } @@ -2232,12 +2233,12 @@ we create an instance <tt>s1</tt> from the derived class, we can call the method <tt>foo</tt> which uses in turn the private method of the base class. Therefore, <tt>foo</tt> called with the arguments 3 and 4 returns its -sum. If we would not have used <tt>my -local</tt> for invoking the helper, +sum. If we would not have used the local flag for invoking the helper, <tt>s1</tt> would have tried to call the helper of <tt>Sub</tt>, which would be incorrect. For all other purposes, the private methods are "invisible" in all situations, e.g. when mixins are used, or within the <tt>next</tt>-path, etc.</p></div> -<div class="paragraph"><p>By using <tt>my -local</tt> for the invocation it is possible to call just the +<div class="paragraph"><p>By using the local flag for the invocation it is possible to call just the local definition of the method. If we would call the method as usual, the resolution order would be the same as usual, starting with filters, mixins, per-object methods and the full intrinsic class @@ -2506,7 +2507,7 @@ of the object. The method can be defined multiple times on the search path, so some of these method definitions might be <em>shadowed</em> by the more specific definitions.</p></div> -<div class="paragraph" id="xmp-method-resolution"><div class="title">Listing 31: Method Resolution</div><p></p></div> +<div class="paragraph" id="xmp-method-resolution"><div class="title">Listing 31: Method Resolution with Intrinsic Classes</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -2534,6 +2535,10 @@ 14 15 16 + 17 + 18 + 19 + 20 </pre></td><td class='nx-body'><pre class='nx'><span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> C { :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> foo {} { <span class='nx-keyword'>return</span> <span class='nx-string'>"C foo: [next]"</span>} } @@ -2549,7 +2554,11 @@ <span class='nx-comment'># Invoke the method foo </span>d1 foo -<span class='nx-comment'># result: "d1 foo: D foo: C foo: "</span></pre></td></tr></table></div></div> +<span class='nx-comment'># result: "d1 foo: D foo: C foo: " +</span> +<span class='nx-comment'># Query the precedence order from NX via introspection +</span>d1 <span class='nx-keyword'>info</span> precedence +<span class='nx-comment'># result: "::D ::C ::nx::Object"</span></pre></td></tr></table></div></div> <div class="paragraph"><p>Consider the example in <tt>foo</tt> is invoked on object <tt>d1</tt>, the per-object method has the highest precedence and is therefore invoked. The per-object methods shadows @@ -2562,6 +2571,149 @@ contains parts from <tt>d1</tt>, <tt>D</tt> and <tt>C</tt>. Note, that the topmost <tt>next</tt> in method <tt>foo</tt> of class <tt>C</tt> shadows no method <tt>foo</tt> and simply returns empty (and not an error message).</p></div> +<div class="paragraph"><p>The introspection method <tt>info precedence</tt> provides information about +the order, in which classes processed during method resolution.</p></div> +<div class="paragraph" id="xmp-method-resolution2"><div class="title">Listing 32: Method Resolution with Mixin Classes</div><p></p></div> +<div class="listingblock"> +<div class="content"><style type='text/css'> +.nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} +table.nx {border-collapse: collapse; border-spacing: 3px;} +.nx-linenr {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;} +.nx-string {color: #779977; font-weight: normal; font-style: italic;} +.nx-comment {color: #717ab3; font-weight: normal; font-style: italic;} +.nx-keyword {color: #7f0055; font-weight: normal; font-style: normal;} +.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;} +.nx-variable {color: #AF663F; font-weight: normal; font-style: normal;} +</style> +<table class='nx'><tr><td class='nx-linenr'><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 +</pre></td><td class='nx-body'><pre class='nx'><span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> M1 { + :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> foo {} { <span class='nx-keyword'>return</span> <span class='nx-string'>"M1 foo: [next]"</span>} +} +<span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> M2 { + :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> foo {} { <span class='nx-keyword'>return</span> <span class='nx-string'>"M2 foo: [next]"</span>} +} + +<span class='nx-comment'># +</span><span class='nx-comment'># "d1" is created based on the definitons of the last example +</span><span class='nx-comment'># +</span><span class='nx-comment'># Add the methods from "M1" as per-object mixin to "d1" +</span>d1 <span class='nx-keyword'>mixin</span> M1 + +<span class='nx-comment'># +</span><span class='nx-comment'># Add the methods from "M2" as per-class mixin to class "C" +</span>C <span class='nx-keyword'>mixin</span> M2 + +<span class='nx-comment'># Invoke the method foo +</span>d1 foo +<span class='nx-comment'># result: "M1 foo: M2 foo: d1 foo: D foo: C foo: " +</span> +<span class='nx-comment'># Query the precedence order from NX via introspection +</span>d1 <span class='nx-keyword'>info</span> precedence +<span class='nx-comment'># result: "::M1 ::M2 ::D ::C ::nx::Object"</span></pre></td></tr></table></div></div> +<div class="paragraph"><p>an extension of the previous example. We define here two additional +classes <tt>M1</tt> and <tt>M2</tt> which are used as per-object and per-class +mixins. Both classes define the method <tt>foo</tt>, these methods shadow +the definitins of the intrinsic class hierarchy. Therefore an +invocation of <tt>foo</tt> on object <tt>d1</tt> causes first an invocation of +method in the the per-object mixin.</p></div> +<div class="paragraph" id="xmp-method-resolution3"><div class="title">Listing 33: Method Invocation Flags</div><p></p></div> +<div class="listingblock"> +<div class="content"><style type='text/css'> +.nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} +table.nx {border-collapse: collapse; border-spacing: 3px;} +.nx-linenr {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;} +.nx-string {color: #779977; font-weight: normal; font-style: italic;} +.nx-comment {color: #717ab3; font-weight: normal; font-style: italic;} +.nx-keyword {color: #7f0055; font-weight: normal; font-style: normal;} +.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;} +.nx-variable {color: #AF663F; font-weight: normal; font-style: normal;} +</style> +<table class='nx'><tr><td class='nx-linenr'><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 +</pre></td><td class='nx-body'><pre class='nx'><span class='nx-comment'># +</span><span class='nx-comment'># "d1" is created based on the definitons of the last two examples, +</span><span class='nx-comment'># the mixins "M1" and "M2" are registered. +</span><span class='nx-comment'># +</span><span class='nx-comment'># Define a public per-object method "bar", which calls the method +</span><span class='nx-comment'># "foo" which variaous invocation options: +</span><span class='nx-comment'># +</span>d1 <span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> bar {} { + <span class='nx-keyword'>puts</span> [:foo] + <span class='nx-keyword'>puts</span> [: -local foo] + <span class='nx-keyword'>puts</span> [: -intrinsic foo] + <span class='nx-keyword'>puts</span> [: -system foo] +} + +<span class='nx-comment'># Invoke the method "bar" +</span>d1 bar</pre></td></tr></table></div></div> +<div class="paragraph"><p>In the first line of the body of method <tt>bar</tt>, the method <tt>foo</tt> is +called as usual with an implicit reciever, which defaults to the +current object (therefore, the call is equivalent to <tt>d1 foo</tt>). The +next three calls show how to provide flags that influence the method +resolution. The flags can be provided between the colon and the method +name. These flags are used rather seldomly but can be helpful in some +situations.</p></div> +<div class="paragraph"><p>The invocation flag <tt>-local</tt> means that the method has to be resolved +from the same place, where the current method is defined. Since the +current method is defined as a per-object method, <tt>foo</tt> is resolved as +a per-object method. The effect is that the mixin definitions are +ignored. The invocation flag <tt>-local</tt> was already introduced int the +setction about method protection, where it was used to call <em>private</em> +methods.</p></div> +<div class="paragraph"><p>The invocation flag <tt>-intrinsic</tt> means that the method has to be resolved +from the intrinsic definitions, meaning simply without mixins. The +effect is here the same as with the invocation flag <tt>-local</tt>.</p></div> +<div class="paragraph"><p>The invocation flag <tt>-system</tt> means that the method has to be resolved +from basic - typically predefined - classes of the object system. This +can be useful, when script overloads system methods, but still want to +call the shadowed methods from the base classes. In our case, we have +no definitions of <tt>foo</tt> on the base clases, therefore an error message +is returned.</p></div> +<div class="paragraph"><p></p></div> +<div class="listingblock"> +<div class="content"> +<pre><tt> M1 foo: M2 foo: d1 foo: D foo: C foo: + d1 foo: D foo: C foo: + d1 foo: D foo: C foo: + ::d1: unable to dispatch method 'foo'</tt></pre> +</div></div> </div> <div class="sect2"> <h3 id="_parameters">3.7. Parameters</h3> @@ -2611,7 +2763,7 @@ determined by its position. When we call a method with non-positional parameters, their meaning is determined via a name passed with the argument during invocation.</p></div> -<div class="paragraph" id="xmp-posnonpos"><div class="title">Listing 32: Positional and Non-Positional Method Parameters</div><p></p></div> +<div class="paragraph" id="xmp-posnonpos"><div class="title">Listing 34: Positional and Non-Positional Method Parameters</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -2695,7 +2847,7 @@ </span>o1 baz -x 1 100 o1 baz 200 o1 baz -- -y</pre></td></tr></table></div></div> -<div class="paragraph"><p>Consider the example in <a href="#xmp-posnonpos">Listing 32</a>. The method +<div class="paragraph"><p>Consider the example in <a href="#xmp-posnonpos">Listing 34</a>. The method <tt>foo</tt> has the argument list <tt>x y</tt>. This means that the first argument is passed in an invocation like <tt>o1 foo 1 2</tt> to <tt>x</tt> (here, the value <tt>1</tt>), and the second argument is passed to <tt>y</tt> (here the value <tt>2</tt>). @@ -2704,7 +2856,7 @@ invocation <tt>o1 bar -y 3 -x 1</tt> the names of the parameters are prefixed with a dash ("-"). No matter whether in which order we write the non-positional parameters in the invocation (see line 30 and 31 in -<a href="#xmp-posnonpos">Listing 32</a>) in both cases the variables <tt>x</tt> +<a href="#xmp-posnonpos">Listing 34</a>) in both cases the variables <tt>x</tt> and <tt>y</tt> in the body of the method <tt>bar</tt> get the same values assigned (<tt>x</tt> becomes <tt>1</tt>, <tt>y</tt> becomes <tt>3</tt>).</p></div> <div class="paragraph"><p>It is certainly possible to combine positional and non-positional @@ -2728,7 +2880,7 @@ parameters are optional (they can be left out). By using parameter options, we can as well define positional parameters, which are optional, and non-positional parameters, which are required.</p></div> -<div class="paragraph" id="xmp-optional-req"><div class="title">Listing 33: Optional and Required Method Parameters</div><p></p></div> +<div class="paragraph" id="xmp-optional-req"><div class="title">Listing 35: Optional and Required Method Parameters</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -2782,7 +2934,7 @@ <span class='nx-comment'># invoke foo (one optional positional parameter is missing) </span>o2 foo 1</pre></td></tr></table></div></div> -<div class="paragraph"><p>The example in <a href="#xmp-optional-req">Listing 33</a> defined method <tt>foo</tt> +<div class="paragraph"><p>The example in <a href="#xmp-optional-req">Listing 35</a> defined method <tt>foo</tt> with one required and one optional positional parameter. For this purpose we use the parameter options <tt>required</tt> and <tt>optional</tt>. The parameter options are separated from the parameter name by a colon. If @@ -2791,12 +2943,12 @@ <div class="paragraph"><p>The parameter definition <tt>x:required</tt> for method <tt>foo</tt> is equivalent to <tt>x</tt> without any parameter options (see e.g. previous example), since positional parameters are per default required. The invocation -in line 21 of <a href="#xmp-optional-req">Listing 33</a> will lead to an +in line 21 of <a href="#xmp-optional-req">Listing 35</a> will lead to an undefined variable <tt>y</tt> in method <tt>foo</tt>, because no value us passed to the optional parameter. Note that only trailing positional parameters might be -optional. If we would call method <tt>foo</tt> of <a href="#xmp-posnonpos">Listing 32</a> with only one argument, the system would raise an +optional. If we would call method <tt>foo</tt> of <a href="#xmp-posnonpos">Listing 34</a> with only one argument, the system would raise an exception.</p></div> -<div class="paragraph"><p>Similarly, we define method <tt>bar</tt> in <a href="#xmp-optional-req">Listing 33</a> with one required and one optional non-positional +<div class="paragraph"><p>Similarly, we define method <tt>bar</tt> in <a href="#xmp-optional-req">Listing 35</a> with one required and one optional non-positional parameter. The parameter definition <tt>-y:optional</tt> is equivalent to <tt>-y</tt>, since non-positional parameter are per default optional. However, the non-positional parameter <tt>-x:required</tt> is required. If we @@ -2807,7 +2959,7 @@ <div class="paragraph"><p>Optional parameters might have a default value, which will be used, when not value is provided for this parameter. Default values can be specified for positional and non-positional parameters.</p></div> -<div class="paragraph" id="xmp-default-value"><div class="title">Listing 34: Method Parameters with Default Values</div><p></p></div> +<div class="paragraph" id="xmp-default-value"><div class="title">Listing 36: Method Parameters with Default Values</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -2862,7 +3014,7 @@ <div class="paragraph"><p>In order to define a default value, the parameter specification must be of the form of a 2 element list, where the second argument is the default value. See for an example in -<a href="#xmp-default-value">Listing 34</a>.</p></div> +<a href="#xmp-default-value">Listing 36</a>.</p></div> </div> <div class="sect3"> <h4 id="_value_constraints">3.7.4. Value Constraints</h4> @@ -2888,16 +3040,16 @@ <div class="content"> <img src="value-checkers.png" alt="value-checkers.png" /> </div> -<div class="title">Figure 35. General Applicable Value Checkers in NX</div> +<div class="title">Figure 37. General Applicable Value Checkers in NX</div> </div> <div class="paragraph"><p></p></div> -<div class="paragraph"><p><a href="#img-value-checkers">Figure 35</a> shows the built-in +<div class="paragraph"><p><a href="#img-value-checkers">Figure 37</a> shows the built-in general applicable value checkers available in NX, which can be used for all method and object parameters. In the next step, we show how to use these value-checkers for checking permissible values for method parameters. Then we will show, how to provide more detailed value constraints.</p></div> -<div class="paragraph" id="xmp-value-check"><div class="title">Listing 36: Method Parameters with Value Constraints</div><p></p></div> +<div class="paragraph" id="xmp-value-check"><div class="title">Listing 38: Method Parameters with Value Constraints</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -2953,10 +3105,10 @@ integer. The parameter specification <tt>o:object,optional</tt> shows how to combine multiple parameter options. The parameter <tt>o</tt> is an optional positional parameter, its value must be an object (see -<a href="#xmp-value-check">Listing 36</a>). Value constraints are +<a href="#xmp-value-check">Listing 38</a>). Value constraints are specified exactly the same way for non-positional parameters (see -method <tt>bar</tt> in <a href="#xmp-value-check">Listing 36</a>).</p></div> -<div class="paragraph" id="xmp-check-parameterized"><div class="title">Listing 37: Parameterized Value Constraints</div><p></p></div> +method <tt>bar</tt> in <a href="#xmp-value-check">Listing 38</a>).</p></div> +<div class="paragraph" id="xmp-check-parameterized"><div class="title">Listing 39: Parameterized Value Constraints</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3029,10 +3181,10 @@ the permissible values to instances of certain classes. We can use for example the native value constraint <tt>object</tt> either for testing whether an argument is some object (without further constraints, as in -<a href="#xmp-default-value">Listing 34</a>, method <tt>foo</tt>), or we can +<a href="#xmp-default-value">Listing 36</a>, method <tt>foo</tt>), or we can constrain the value further to some type (direct or indirect instance of a class). This is shown by method <tt>work</tt> in -<a href="#xmp-check-parameterized">Listing 37</a> which requires +<a href="#xmp-check-parameterized">Listing 39</a> which requires the parameter <tt>-person</tt> to be an instance of class <tt>Person</tt> and the parameter <tt>-project</tt> to be an instance of class <tt>Project</tt>.</p></div> </div> @@ -3045,7 +3197,7 @@ in the next sections. In the following example we define two new value checkers on class <tt>nx::Slot</tt>. The first value checker is called <tt>groupsize</tt>, the second one is called <tt>choice</tt>.</p></div> -<div class="paragraph" id="xmp-user-types"><div class="title">Listing 38: Scripted Value Checker for Method Parameters</div><p></p></div> +<div class="paragraph" id="xmp-user-types"><div class="title">Listing 40: Scripted Value Checker for Method Parameters</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3143,14 +3295,14 @@ (mostly used for the error message) and the second parameter is provided value. The value checker simply tests whether the provided value is between 1 and 3 and raises an exception if this is not the -case (invocation in line 36 in <a href="#xmp-user-types">Listing 38</a>).</p></div> +case (invocation in line 36 in <a href="#xmp-user-types">Listing 40</a>).</p></div> <div class="paragraph"><p>The checker <tt>groupsize</tt> has the permissible values defined in its method’s body. It is as well possible to define more generic checkers that can be parameterized. For this parameterization, one can pass an argument to the checker method (last argument). The checker <tt>choice</tt> can be used for restricting the values to a set of predefined constants. This set is defined in the parameter specification. The -parameter <tt>a</tt> of method <tt>bar</tt> in <a href="#xmp-user-types">Listing 38</a> +parameter <tt>a</tt> of method <tt>bar</tt> in <a href="#xmp-user-types">Listing 40</a> is restricted to the values <tt>red</tt>, <tt>yellow</tt> or <tt>green</tt>, and the parameter <tt>b</tt> is restricted to <tt>good</tt> or <tt>bad</tt>. Note that the syntax of the permissible values is solely defined by the definition of the @@ -3182,7 +3334,7 @@ multiplicity is defined the default multiplicity is <tt>1..1</tt>, which means: provide exactly one (atomic) value (this was the case in the previous examples).</p></div> -<div class="paragraph" id="xmp-multiplicity"><div class="title">Listing 39: Method Parameters with Explicit Multiplicity</div><p></p></div> +<div class="paragraph" id="xmp-multiplicity"><div class="title">Listing 41: Method Parameters with Explicit Multiplicity</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3246,7 +3398,7 @@ <span class='nx-keyword'>puts</span> <span class='nx-string'>"x=$x"</span> } }</pre></td></tr></table></div></div> -<div class="paragraph"><p><a href="#xmp-multiplicity">Listing 39</a> contains three examples for +<div class="paragraph"><p><a href="#xmp-multiplicity">Listing 41</a> contains three examples for positional parameters with different multiplicities. Multiplicity is often combined with value constraints. A parameter specification of the form <tt>x:integer,0..n</tt> means that the parameter <tt>x</tt> receives a list @@ -3257,7 +3409,7 @@ no explicit value is passed for a certain parameter. Another style is to use required or optional parameters. NX does not enforce any particular style for handling unspecified values.</p></div> -<div class="paragraph"><p>All the examples in <a href="#xmp-multiplicity">Listing 39</a> are for +<div class="paragraph"><p>All the examples in <a href="#xmp-multiplicity">Listing 41</a> are for single positional parameters. Certainly, multiplicity is fully orthogonal with the other parameter features and can be used as well for multiple parameters, non-positional parameter, default values, @@ -3323,7 +3475,7 @@ parameters are often used in combination with special setter methods, etc.). Consider the following example, where we define the two application classes <tt>Person</tt> and <tt>Student</tt> with a few properties.</p></div> -<div class="paragraph" id="xmp-object-parameters"><div class="title">Listing 40: Object Parameters</div><p></p></div> +<div class="paragraph" id="xmp-object-parameters"><div class="title">Listing 42: Object Parameters</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3393,13 +3545,13 @@ property <tt>name</tt> is required, the property <tt>birthday</tt> is not. The class <tt>Student</tt> is a subclass of <tt>Person</tt> with the additional required property <tt>matnr</tt> and an optional property <tt>oncampus</tt> with the -default value <tt>true</tt> (see <a href="#xmp-object-parameters">Listing 40</a>). The class diagram below visualizes these +default value <tt>true</tt> (see <a href="#xmp-object-parameters">Listing 42</a>). The class diagram below visualizes these definitions.</p></div> <div class="imageblock" id="img-object-parameters" style="text-align:center;"> <div class="content"> <img src="object-parameter.png" alt="object-parameter.png" /> </div> -<div class="title">Figure 41. System and Application Classes</div> +<div class="title">Figure 43. System and Application Classes</div> </div> <div class="paragraph"><p></p></div> <div class="paragraph"><p>In NX, these definitions imply that instances of the class of <tt>Person</tt> @@ -3409,7 +3561,7 @@ parameters from <tt>Student</tt> (namely <tt>matnr</tt> and <tt>oncampus</tt>). Based on these object parameters, we can create a <tt>Person</tt> named <tt>Bob</tt> and a <tt>Student</tt> named <tt>Susan</tt> with the matriculation number <tt>4711</tt> (see line -23 and 24 in <a href="#xmp-object-parameters">Listing 40</a>). After the object <tt>s1</tt> is created it has the +23 and 24 in <a href="#xmp-object-parameters">Listing 42</a>). After the object <tt>s1</tt> is created it has the instance variables <tt>name</tt>, <tt>matnr</tt> and <tt>oncampus</tt> (the latter is initialized with the default value).</p></div> <div class="sect3"> @@ -3433,7 +3585,7 @@ object parameters. However, this object parameter is positional (last argument) and optional (it can be omitted). The following listing shows (simplified) the object parameters of <tt>Person p1</tt> and <tt>Student s1</tt>.</p></div> -<div class="paragraph" id="xmp-object-parameter-list"><div class="title">Listing 42: Computed Actual Object Parameter (simplified)</div><p></p></div> +<div class="paragraph" id="xmp-object-parameter-list"><div class="title">Listing 44: Computed Actual Object Parameter (simplified)</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3485,7 +3637,7 @@ the same way.</p></div> <div class="paragraph"><p>Since <tt>Student</tt> is an instance of the meta-class <tt>nx::Class</tt> it inherits the object parameters from <tt>nx::Class</tt> (see class diagram -<a href="#img-object-parameters">Figure 41</a>). Therefore, one can +<a href="#img-object-parameters">Figure 43</a>). Therefore, one can use e.g. <tt>-superclass</tt> in the definition of classes.</p></div> <div class="paragraph"><p>Since <tt>nx::Class</tt> is a subclass of <tt>nx::Object</tt>, the meta-class <tt>nx::Class</tt> inherits the parameter definitions from the most general @@ -3495,7 +3647,7 @@ most examples for defining the methods of the class. The following listing shows (simplified) the parameters applicable for <tt>Class Student</tt>.</p></div> -<div class="paragraph" id="xmp-class-parameter-list"><div class="title">Listing 43: Computed Parameters for a Class (simplified)</div><p></p></div> +<div class="paragraph" id="xmp-class-parameter-list"><div class="title">Listing 45: Computed Parameters for a Class (simplified)</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3531,7 +3683,7 @@ <div class="content"> <img src="slots.png" alt="slots.png" /> </div> -<div class="title">Figure 44. Slot Classes and Objects</div> +<div class="title">Figure 46. Slot Classes and Objects</div> </div> <div class="paragraph"><p></p></div> </div> @@ -3601,7 +3753,7 @@ with a method <tt>unknown</tt> which is called in cases, where an unknown method is called. The method unknown receives as first argument the called method followed by the provided arguments</p></div> -<div class="paragraph" id="xmp-unknown-method"><div class="title">Listing 45: Unknown Method Handler</div><p></p></div> +<div class="paragraph" id="xmp-unknown-method"><div class="title">Listing 47: Unknown Method Handler</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3645,7 +3797,7 @@ e.g. lazy loading of these classes. Nsf allows to register multiple unknown handlers, each identified by a key (a unique name, different from the keys of other unknown handlers).</p></div> -<div class="paragraph" id="xmp-unknown-class"><div class="title">Listing 46: Unknown Class Handler</div><p></p></div> +<div class="paragraph" id="xmp-unknown-class"><div class="title">Listing 48: Unknown Class Handler</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3702,7 +3854,7 @@ </span> <span class='nx-comment'># ::M </span>}</pre></td></tr></table></div></div> <div class="paragraph"><p>The Next Scripting Framework allows to add, query, delete and list unknown handlers.</p></div> -<div class="paragraph" id="xmp-unknown-registgration"><div class="title">Listing 47: Unknown Handler registration</div><p></p></div> +<div class="paragraph" id="xmp-unknown-registgration"><div class="title">Listing 49: Unknown Handler registration</div><p></p></div> <div class="listingblock"> <div class="content"><style type='text/css'> .nx {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px} @@ -3807,7 +3959,7 @@ <div id="footer"> <div id="footer-text"> Version 2.1<br /> -Last updated 2011-09-26 14:08:41 CEST +Last updated 2011-09-28 14:02:42 CEST </div> </div> </body> Index: doc/next-tutorial.txt =================================================================== diff -u -r61a1c5c9e11a0277be442d98572bae6a3162cf1f -rf41ae7e802868efee95b5d5682edfdbbe9ba2f64 --- doc/next-tutorial.txt (.../next-tutorial.txt) (revision 61a1c5c9e11a0277be442d98572bae6a3162cf1f) +++ doc/next-tutorial.txt (.../next-tutorial.txt) (revision f41ae7e802868efee95b5d5682edfdbbe9ba2f64) @@ -879,7 +879,7 @@ _forwarders_ and _aliases_. =========================================== -An *accessor* is a (in most cases) C-implemented method to access +An *accessor method* is a (in most cases) C-implemented method to access instance variables of an object. A call to an accessor with no arguments uses the accessor as a getter, obtaining the value of the associated variable. A call to an accessor with an argument uses it as a setter, @@ -960,7 +960,7 @@ +fido::tail+. =========================================== -A *forwarder* is a +A *forwarder method* is a C-implemented method to redirect an invocation for a certain method to either a method of other object or to some other method of the same object. Forwarding an invocation of a method to some other @@ -979,8 +979,9 @@ ==== Method-Aliases =========================================== -A *method alias* is a means to register an existing method, a Tcl proc or -command under as a method with a certain name on a class or object. +An *alias method* is a means to register an existing method, or a +Tcl proc or a Tcl command as a method with the provided +name on a class or object. =========================================== In some way, the method alias is a restricted form of a forwarder, but @@ -1032,7 +1033,7 @@ called from every context. A *protected* method can only be invoked from the same object. A *private* method can be only invoked from methods defined on the same entity (e.g. defined on the same class) -via +my -local+. +via the invocation with the local flag (i.e. "+: -local+"). =========================================== All kind of methods protection are applicable for all kind of methods, @@ -1091,13 +1092,13 @@ [source,tcl,numbers] -------------------------------------------------- nx::Class create Base { - :private method helper {a b} { expr {$a + $b} } - :public method foo {a b} { my -local helper $a $b } + :private method helper {a b} {expr {$a + $b}} + :public method foo {a b} {: -local helper $a $b} } nx::Class create Sub -superclass Base { - :public method bar {a b} { my -local helper $a $b } - :private method helper {a b} { expr {$a * $b} } + :public method bar {a b} {: -local helper $a $b} + :private method helper {a b} {expr {$a * $b}} :create s1 } @@ -1112,13 +1113,13 @@ we create an instance +s1+ from the derived class, we can call the method +foo+ which uses in turn the private method of the base class. Therefore, +foo+ called with the arguments 3 and 4 returns its -sum. If we would not have used +my -local+ for invoking the helper, +sum. If we would not have used the local flag for invoking the helper, +s1+ would have tried to call the helper of +Sub+, which would be incorrect. For all other purposes, the private methods are "invisible" in all situations, e.g. when mixins are used, or within the +next+-path, etc. -By using +my -local+ for the invocation it is possible to call just the +By using the local flag for the invocation it is possible to call just the local definition of the method. If we would call the method as usual, the resolution order would be the same as usual, starting with filters, mixins, per-object methods and the full intrinsic class @@ -1314,7 +1315,7 @@ more specific definitions. [[xmp-method-resolution]] -.Listing {counter:figure-number}: Method Resolution +.Listing {counter:figure-number}: Method Resolution with Intrinsic Classes {set:xmp-method-resolution:Listing {figure-number}} [source,tcl,numbers] -------------------------------------------------- @@ -1334,6 +1335,10 @@ # Invoke the method foo d1 foo # result: "d1 foo: D foo: C foo: " + +# Query the precedence order from NX via introspection +d1 info precedence +# result: "::D ::C ::nx::Object" -------------------------------------------------- Consider the example in @@ -1350,7 +1355,108 @@ in method +foo+ of class +C+ shadows no method +foo+ and simply returns empty (and not an error message). +The introspection method +info precedence+ provides information about +the order, in which classes processed during method resolution. +[[xmp-method-resolution2]] +.Listing {counter:figure-number}: Method Resolution with Mixin Classes +{set:xmp-method-resolution2:Listing {figure-number}} +[source,tcl,numbers] +-------------------------------------------------- +nx::Class create M1 { + :public method foo {} { return "M1 foo: [next]"} +} +nx::Class create M2 { + :public method foo {} { return "M2 foo: [next]"} +} + +# +# "d1" is created based on the definitons of the last example +# +# Add the methods from "M1" as per-object mixin to "d1" +d1 mixin M1 + +# +# Add the methods from "M2" as per-class mixin to class "C" +C mixin M2 + +# Invoke the method foo +d1 foo +# result: "M1 foo: M2 foo: d1 foo: D foo: C foo: " + +# Query the precedence order from NX via introspection +d1 info precedence +# result: "::M1 ::M2 ::D ::C ::nx::Object" +-------------------------------------------------- + +The example in <<xmp-method-resolution2,{xmpmethod-resolution2}>> is +an extension of the previous example. We define here two additional +classes +M1+ and +M2+ which are used as per-object and per-class +mixins. Both classes define the method +foo+, these methods shadow +the definitins of the intrinsic class hierarchy. Therefore an +invocation of +foo+ on object +d1+ causes first an invocation of +method in the the per-object mixin. + + +[[xmp-method-resolution3]] +.Listing {counter:figure-number}: Method Invocation Flags +{set:xmp-method-resolution3:Listing {figure-number}} +[source,tcl,numbers] +-------------------------------------------------- +# +# "d1" is created based on the definitons of the last two examples, +# the mixins "M1" and "M2" are registered. +# +# Define a public per-object method "bar", which calls the method +# "foo" which variaous invocation options: +# +d1 public method bar {} { + puts [:foo] + puts [: -local foo] + puts [: -intrinsic foo] + puts [: -system foo] +} + +# Invoke the method "bar" +d1 bar +-------------------------------------------------- + +In the first line of the body of method +bar+, the method +foo+ is +called as usual with an implicit reciever, which defaults to the +current object (therefore, the call is equivalent to +d1 foo+). The +next three calls show how to provide flags that influence the method +resolution. The flags can be provided between the colon and the method +name. These flags are used rather seldomly but can be helpful in some +situations. + +The invocation flag +-local+ means that the method has to be resolved +from the same place, where the current method is defined. Since the +current method is defined as a per-object method, +foo+ is resolved as +a per-object method. The effect is that the mixin definitions are +ignored. The invocation flag +-local+ was already introduced int the +setction about method protection, where it was used to call _private_ +methods. + +The invocation flag +-intrinsic+ means that the method has to be resolved +from the intrinsic definitions, meaning simply without mixins. The +effect is here the same as with the invocation flag +-local+. + +The invocation flag +-system+ means that the method has to be resolved +from basic - typically predefined - classes of the object system. This +can be useful, when script overloads system methods, but still want to +call the shadowed methods from the base classes. In our case, we have +no definitions of +foo+ on the base clases, therefore an error message +is returned. + +The output of <<xmp-method-resolution2,{xmpmethod-resolution2}>> is: +---- + M1 foo: M2 foo: d1 foo: D foo: C foo: + d1 foo: D foo: C foo: + d1 foo: D foo: C foo: + ::d1: unable to dispatch method 'foo' +---- + + === Parameters NX provides a generalized mechanism for passing values to either