Fisheye: Tag 24cb8f4bffd49c9375c1c64aa0610933b62511bb refers to a dead (removed) revision in file `apps/utils/nxdoc'. Fisheye: No comparison available. Pass `N' to diff? Index: apps/utils/source-doc-beautifier.tcl =================================================================== diff -u -r09360883738f214c19404032888a48c4f937a16c -r24cb8f4bffd49c9375c1c64aa0610933b62511bb --- apps/utils/source-doc-beautifier.tcl (.../source-doc-beautifier.tcl) (revision 09360883738f214c19404032888a48c4f937a16c) +++ apps/utils/source-doc-beautifier.tcl (.../source-doc-beautifier.tcl) (revision 24cb8f4bffd49c9375c1c64aa0610933b62511bb) @@ -1,4 +1,4 @@ -#!/usr/bin/env tclsh +#!/usr/bin/env tclsh8.5 # # Script to beautify scripted documentations. # @@ -87,4 +87,4 @@ } } output flush -} \ No newline at end of file +} Index: apps/utils/source-highlight-with-pp =================================================================== diff -u -r1914a014643964e54046fca2960f8c7b2a9d224d -r24cb8f4bffd49c9375c1c64aa0610933b62511bb --- apps/utils/source-highlight-with-pp (.../source-highlight-with-pp) (revision 1914a014643964e54046fca2960f8c7b2a9d224d) +++ apps/utils/source-highlight-with-pp (.../source-highlight-with-pp) (revision 24cb8f4bffd49c9375c1c64aa0610933b62511bb) @@ -1,5 +1,5 @@ -#!/usr/bin/env tclsh +#!/usr/bin/env tclsh8.5 package req nx::pp lappend argv [read stdin] -puts stdout [nx::pp render {*}$argv] \ No newline at end of file +puts stdout [nx::pp render {*}$argv] Index: doc/example-scripts/bagel.html =================================================================== diff -u -r93bb0947d582f274afb1cdbc885909d55e100b36 -r24cb8f4bffd49c9375c1c64aa0610933b62511bb --- doc/example-scripts/bagel.html (.../bagel.html) (revision 93bb0947d582f274afb1cdbc885909d55e100b36) +++ doc/example-scripts/bagel.html (.../bagel.html) (revision 24cb8f4bffd49c9375c1c64aa0610933b62511bb) @@ -3,7 +3,7 @@ - + Listing of doc/example-scripts/bagel.tcl +
package req nx
+nx::test configure -count 1

Suppose we need to work with many bagels in our application. We might start by creating a Bagel class.

-
+
+
% nx::Class create Bagel
+::Bagel

We can now create bagels and keep track of them using the info method.

-
+
+
% Bagel create abagel
+::abagel
+
+% abagel info class
+::Bagel
+
+% Bagel info instances
+::abagel

Of course, bagels don’t do much yet. They should remember whether they’ve been toasted. We can create and access an instance variable by defining an property for the class. All instance variables are per default public in the sense of C++.

-
+
+
% Bagel property {toasted 0}

Since abagel was created before the definition of the property we have to set the default value for it using the setter method. Again, the info method helps us keep track of things.

-
+
+
% abagel info vars
+
+% abagel configure -toasted 0
+
+% abagel info vars
+toasted
+
+% abagel cget -toasted
+0

But we really want them to begin in an untoasted state to start with.

-
+
+
% Bagel create bagel2
+::bagel2
+
+% bagel2 info vars
+toasted
+
+% bagel2 cget -toasted
+0

Our bagels now remember whether they’ve been toasted. Let is recreate the first one.

-
+
+
% lsort [Bagel info instances]
+::abagel ::bagel2
+
+% ::abagel destroy
+
+% Bagel info instances
+::bagel2
+
+% Bagel create abagel
+::abagel

Now we’re ready to add a method to bagels so that we can toast them. Methods have an argument list and body like regular Tcl procs. Here’s the toast method.

-
+
+
% Bagel public method toast {} {
+      if {[incr :toasted] > 1} then {
+        error "something's burning!"
+      }
+}
+::nsf::classes::Bagel::toast

The defined methods can be queried with info. We see as well the setter method for the variable toasted.

-
+
+
% Bagel info methods
+toast

Aside from setting the toasted variable, the body of the toast method demonstrates how to access instance variables by using a leading colon in the name.

We invoke the toast method on bagels in the same way we use the info and destroy methods that were provided by the system. That is, there is no distinction between user and system methods.

-
+
+
% abagel toast
+% abagel toast
+something's burning!

Now we can add spreads to the bagels and start tasting them. If we have bagels that aren’t topped, as well as bagels that are, we may want to make toppable bagels a separate class. Let explore @@ -794,11 +937,72 @@ property toppings which might have multiple values. Initially, toppings are empty.

-
+
+
% nx::Class create SpreadableBagel -superclass Bagel {
+    :property -incremental {toppings:0..n ""}
+}
+::SpreadableBagel
+
+% SpreadableBagel cget -superclass
+::Bagel
+% SpreadableBagel info superclasses
+::Bagel
+
+% SpreadableBagel info heritage
+::Bagel ::nx::Object

Let’s add a taste method to bagels, splitting its functionality between the two classes and combining it with next.

-
+
+
% Bagel public method taste {} {
+    if {${:toasted} == 0} then {
+    return raw!
+  } elseif {${:toasted} == 1} then {
+    return toasty
+  } else {
+    return burnt!
+  }
+}
+::nsf::classes::Bagel::taste
+
+% SpreadableBagel public method taste {} {
+    set t [next]
+    foreach i ${:toppings} {
+       lappend t $i
+    }
+    return $t
+}
+::nsf::classes::SpreadableBagel::taste
+
+% SpreadableBagel create abagel
+::abagel
+
+% abagel toast
+% abagel toppings add jam
+jam
+% abagel toppings add m&m
+m&m jam
+
+% abagel taste
+toasty m&m jam

Of course, along come sesame, onion, poppy, and a host of other bagels, requiring us to expand our scheme. We could keep track of flavor with an instance variable, but this may not be @@ -809,28 +1013,104 @@ their taste independent trait to bagels or whatever other food they are mixed with.

-
+
+
% nx::Class create Sesame {
+    :public method taste {} {concat [next] "sesame"}
+}
+::Sesame
+
+% nx::Class create Onion {
+    :public method taste {} {concat [next] "onion"}
+}
+::Onion
+
+% nx::Class create Poppy {
+    :public method taste {} {concat [next] "poppy"}
+}
+::Poppy

Well, they don’t appear to do much, but the use of next allows them to be freely mixed.

-
+
+
% nx::Class create SesameOnionBagel -superclass SpreadableBagel -mixin {Sesame Onion}
+::SesameOnionBagel
+
+% SesameOnionBagel create abagel -toppings butter
+::abagel
+
+% abagel taste
+raw! butter onion sesame

For multiple inheritance, the system determines a linear inheritance ordering that respects all of the local superclass orderings. You can examine this ordering with an info option. next follows this ordering when it combines behavior.

-
+
+
% SesameOnionBagel info heritage
+::Sesame ::Onion ::SpreadableBagel ::Bagel ::nx::Object
+
+% abagel info precedence
+::Sesame ::Onion ::SesameOnionBagel ::SpreadableBagel ::Bagel ::nx::Object

We can also combine our mixins with other classes, classes that need have nothing to do with bagels, leading to a family of chips.

-
+
+
% nx::Class create Chips {
+    :public method taste {} {return "crunchy"}
+}
+::Chips
+
+% nx::Class create OnionChips -superclass Chips -mixin Onion
+::OnionChips
+
+% OnionChips create abag
+::abag
+
+% abag taste
+crunchy onion

Index: doc/example-scripts/rosetta-abstract-type.html =================================================================== diff -u -r93bb0947d582f274afb1cdbc885909d55e100b36 -r24cb8f4bffd49c9375c1c64aa0610933b62511bb --- doc/example-scripts/rosetta-abstract-type.html (.../rosetta-abstract-type.html) (revision 93bb0947d582f274afb1cdbc885909d55e100b36) +++ doc/example-scripts/rosetta-abstract-type.html (.../rosetta-abstract-type.html) (revision 24cb8f4bffd49c9375c1c64aa0610933b62511bb) @@ -3,7 +3,7 @@ - + Listing of doc/example-scripts/rosetta-abstract-type.tcl +
package req nx

Define a class AbstractQueue

-
+
+
nx::Class create AbstractQueue {
+
+  :public method enqueue {item} {error "not implemented"}
+  :public method dequeue {} {error "not implemented"}
+
+  :public object method create {args} {
+    error "Cannot instantiate abstract class [self]"
+  }
+}

Define a concrete queue (named ListQueue) based on the Abstract Queue

-
+
+
nx::Class create ListQueue -superclass AbstractQueue {
+
+  :variable list {}
+
+  :public method enqueue {item} {
+    lappend :list $item
+  }
+
+  :public method dequeue {} {
+    set item [lindex ${:list} 0]
+    set :list [lrange ${:list} 1 end]
+    return $item
+  }
+}

Demonstrating the behavior in a shell:

Trying to create an instance of the AbstraceQueue returns an error message:

-
+
+
% AbstractQueue new
+Cannot instantiate abstract class ::AbstractQueue

Create an instance of the concrete queue:

-
+
+
% set q [ListQueue new]

Enqueue and dequeue items

-
+
+
% $q enqueue 100
+100
+% $q enqueue 101
+100 101
+% $q dequeue
+100

Index: doc/example-scripts/rosetta-abstract-type.tcl =================================================================== diff -u -rf858f142f5fab4f88996b3eb709c3afa55114be9 -r24cb8f4bffd49c9375c1c64aa0610933b62511bb --- doc/example-scripts/rosetta-abstract-type.tcl (.../rosetta-abstract-type.tcl) (revision f858f142f5fab4f88996b3eb709c3afa55114be9) +++ doc/example-scripts/rosetta-abstract-type.tcl (.../rosetta-abstract-type.tcl) (revision 24cb8f4bffd49c9375c1c64aa0610933b62511bb) @@ -24,10 +24,13 @@ # Define a concrete queue (named ListQueue) based # on the Abstract Queue nx::Class create ListQueue -superclass AbstractQueue { + :variable list {} + :public method enqueue {item} { lappend :list $item } + :public method dequeue {} { set item [lindex ${:list} 0] set :list [lrange ${:list} 1 end] @@ -46,4 +49,4 @@ # Enqueue and dequeue items ? {$q enqueue 100} 100 ? {$q enqueue 101} "100 101" -? {$q dequeue} 100 \ No newline at end of file +? {$q dequeue} 100 Index: doc/example-scripts/rosetta-classes.html =================================================================== diff -u -r5693145107c55b5f64bf0fb487aa43e0f2238f1a -r24cb8f4bffd49c9375c1c64aa0610933b62511bb --- doc/example-scripts/rosetta-classes.html (.../rosetta-classes.html) (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) +++ doc/example-scripts/rosetta-classes.html (.../rosetta-classes.html) (revision 24cb8f4bffd49c9375c1c64aa0610933b62511bb) @@ -3,7 +3,7 @@ - + Listing of doc/example-scripts/rosetta-classes.tcl