Index: doc/example-scripts/tk-horse-race.html =================================================================== diff -u -r6ad7855cd7aba089f7a160293802e1639d0d6198 -rd31c271afb2488abafa0642b07538a3e62106130 --- doc/example-scripts/tk-horse-race.html (.../tk-horse-race.html) (revision 6ad7855cd7aba089f7a160293802e1639d0d6198) +++ doc/example-scripts/tk-horse-race.html (.../tk-horse-race.html) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -737,15 +737,15 @@ .nx-variable {color: #AF663F; font-weight: normal; font-style: normal;}
package require Tk
-package require nx::callback
+package require nx::trait
 
  ##############################################################################
  # Trait ListUtils
  #
  # Some list utilities, not part of a package we can require here.
  ##############################################################################
 
- nx::Trait create TListUtils {
+ nx::Trait create ::nx::traits::listUtils {
 
    :protected method lpick {list} {
      # return a random entry from a given list
@@ -773,8 +773,8 @@
    :property canvas:required    ;# the canvas, on which the horse is drawn
    :property n:integer,required ;# the position on the canvas
 
-   :require trait nx::TCallback
-   :require trait TListUtils
+   :require trait nx::traits::callback
+   :require trait nx::traits::listUtils
 
    :method draw {x y} {
      set hide [:lpick {black brown white gray brown3 brown4}]
@@ -812,8 +812,8 @@
    :property {height 330}   ;# height of the canvas
    :property {horses}       ;# a list of horse names participating in the game
 
-   :require trait nx::TCallback
-   :require trait TListUtils
+   :require trait nx::traits::callback
+   :require trait nx::traits::listUtils
 
    :method init {} {
      #
@@ -889,7 +889,7 @@
 

Index: doc/example-scripts/tk-horse-race.tcl =================================================================== diff -u -r6ad7855cd7aba089f7a160293802e1639d0d6198 -rd31c271afb2488abafa0642b07538a3e62106130 --- doc/example-scripts/tk-horse-race.tcl (.../tk-horse-race.tcl) (revision 6ad7855cd7aba089f7a160293802e1639d0d6198) +++ doc/example-scripts/tk-horse-race.tcl (.../tk-horse-race.tcl) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -5,15 +5,15 @@ # image::tk-horse-race.png[] # package require Tk -package require nx::callback +package require nx::trait ############################################################################## # Trait ListUtils # # Some list utilities, not part of a package we can require here. ############################################################################## - nx::Trait create TListUtils { + nx::Trait create ::nx::traits::listUtils { :protected method lpick {list} { # return a random entry from a given list @@ -41,8 +41,8 @@ :property canvas:required ;# the canvas, on which the horse is drawn :property n:integer,required ;# the position on the canvas - :require trait nx::TCallback - :require trait TListUtils + :require trait nx::traits::callback + :require trait nx::traits::listUtils :method draw {x y} { set hide [:lpick {black brown white gray brown3 brown4}] @@ -80,8 +80,8 @@ :property {height 330} ;# height of the canvas :property {horses} ;# a list of horse names participating in the game - :require trait nx::TCallback - :require trait TListUtils + :require trait nx::traits::callback + :require trait nx::traits::listUtils :method init {} { # Index: doc/example-scripts/tk-mini.html =================================================================== diff -u -r6ad7855cd7aba089f7a160293802e1639d0d6198 -rd31c271afb2488abafa0642b07538a3e62106130 --- doc/example-scripts/tk-mini.html (.../tk-mini.html) (revision 6ad7855cd7aba089f7a160293802e1639d0d6198) +++ doc/example-scripts/tk-mini.html (.../tk-mini.html) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -735,7 +735,7 @@ .nx-variable {color: #AF663F; font-weight: normal; font-style: normal;}
package require Tk
-package require nx::callback
+package require nx::trait
 
 nx::Class create MyClass {
   #
@@ -744,9 +744,9 @@
   # content of the variable is placed into an additional output label.
 
   #
-  # The trait TCallback imports methods "callback" and "bindvar"
+  # The callback trait imports methods "callback" and "bindvar":
   #
-  :require trait nx::TCallback
+  :require trait nx::traits::callback
 
   :public method button-pressed {} {
     # When this method is invoked, the content of the ".label" widget
@@ -771,7 +771,7 @@
 

Index: doc/example-scripts/tk-mini.tcl =================================================================== diff -u -r6ad7855cd7aba089f7a160293802e1639d0d6198 -rd31c271afb2488abafa0642b07538a3e62106130 --- doc/example-scripts/tk-mini.tcl (.../tk-mini.tcl) (revision 6ad7855cd7aba089f7a160293802e1639d0d6198) +++ doc/example-scripts/tk-mini.tcl (.../tk-mini.tcl) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -5,7 +5,7 @@ # package require Tk -package require nx::callback +package require nx::trait nx::Class create MyClass { # @@ -14,9 +14,9 @@ # content of the variable is placed into an additional output label. # - # The trait TCallback imports methods "callback" and "bindvar" + # The callback trait imports methods "callback" and "bindvar": # - :require trait nx::TCallback + :require trait nx::traits::callback :public method button-pressed {} { # When this method is invoked, the content of the ".label" widget Index: doc/example-scripts/tk-spread.html =================================================================== diff -u -r9ab6a86b4aee196f04363d13e5eadbdfdb814a06 -rd31c271afb2488abafa0642b07538a3e62106130 --- doc/example-scripts/tk-spread.html (.../tk-spread.html) (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) +++ doc/example-scripts/tk-spread.html (.../tk-spread.html) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -738,7 +738,7 @@ .nx-variable {color: #AF663F; font-weight: normal; font-style: normal;}
package require Tk
-package require nx::callback
+package require nx::trait
 
  ##############################################################################
  # Class SpreadSheet
@@ -763,7 +763,7 @@
    #
    # Use the nx callback trait
    #
-   :require trait nx::TCallback
+   :require trait nx::traits::callback
 
    #
    # The method "cell" hides the internal respresentation and sets a
@@ -880,7 +880,7 @@
 

Index: doc/example-scripts/tk-spread.tcl =================================================================== diff -u -r9ab6a86b4aee196f04363d13e5eadbdfdb814a06 -rd31c271afb2488abafa0642b07538a3e62106130 --- doc/example-scripts/tk-spread.tcl (.../tk-spread.tcl) (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) +++ doc/example-scripts/tk-spread.tcl (.../tk-spread.tcl) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -6,7 +6,7 @@ # image::tk-spread.png[] # package require Tk -package require nx::callback +package require nx::trait ############################################################################## # Class SpreadSheet @@ -31,7 +31,7 @@ # # Use the nx callback trait # - :require trait nx::TCallback + :require trait nx::traits::callback # # The method "cell" hides the internal respresentation and sets a Index: doc/example-scripts/traits-composite.html =================================================================== diff -u -r6ad7855cd7aba089f7a160293802e1639d0d6198 -rd31c271afb2488abafa0642b07538a3e62106130 --- doc/example-scripts/traits-composite.html (.../traits-composite.html) (revision 6ad7855cd7aba089f7a160293802e1639d0d6198) +++ doc/example-scripts/traits-composite.html (.../traits-composite.html) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -727,7 +727,7 @@

-

Fig 13: TReadStream and TWriteStream as composite traits

+

Fig 13: tReadStream and tWriteStream as composite traits

In this example, traits are used to extend classes and other traits (called then composite traits).

@@ -742,7 +742,7 @@ .nx-variable {color: #AF663F; font-weight: normal; font-style: normal;}
package req nx::trait
-

Create a Trait called TPositionableStream

+

Create a Trait called tPositionableStream

-
nx::Trait create TPositionableStream {
+
nx::Trait create tPositionableStream {
   #
   # Define the methods provided by this trait:
   #
@@ -773,8 +773,8 @@
   :requiredMethods position
   :requiredVariables collection
 }
-

Create a composite trait called TReadStream based on the trait -TPositionableStream:

+

Create a composite trait called tReadStream based on the trait +tPositionableStream:

-
nx::Trait create TReadStream {
+
nx::Trait create tReadStream {
   #
   # Methods provided by this trait:
   #
@@ -802,11 +802,11 @@
   # This trait requires these methods:
   :requiredMethods {setToStart atEnd nextPosition}
 
-  # Require the trait "TPositionableStream"
-  :require trait TPositionableStream
+  # Require the trait "tPositionableStream"
+  :require trait tPositionableStream
 }
-

Create a composite trait called TWriteStream based on the trait -TPositionableStream:

+

Create a composite trait called tWriteStream based on the trait +tPositionableStream:

-
nx::Trait create TWriteStream {
+
nx::Trait create tWriteStream {
   #
   # Methods provided by this trait:
   #
@@ -832,11 +832,11 @@
   # This trait requires these methods:
   :requiredMethods {setToEnd nextPosition}
 
-  # Require the trait "TPositionableStream"
-  :require trait TPositionableStream
+  # Require the trait "tPositionableStream"
+  :require trait tPositionableStream
 }

Define a class ReadStream with properties position and -collection that uses the composite trait TReadStream:

+collection that uses the composite trait tReadStream:

package require nx::trait
-

Create a simple trait called TReadStream which provides the +

Create a simple trait called tReadStream which provides the interface to a stream. In contrary to a composite trait, a simple trait does not inherit from another trait.

@@ -755,7 +755,7 @@ .nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;} .nx-variable {color: #AF663F; font-weight: normal; font-style: normal;} -
nx::Trait create TReadStream {
+
nx::Trait create tReadStream {
   #
   # Define the methods provided by this trait:
   #
@@ -799,7 +799,7 @@
 
nx::Class create ReadStream {
   :property {collection ""}
   :property {position 0}
-  :require trait TReadStream
+  :require trait tReadStream
 }

Create an instance of the class ReadStream:

@@ -840,7 +840,7 @@

Index: doc/example-scripts/traits-simple.tcl =================================================================== diff -u -r6ad7855cd7aba089f7a160293802e1639d0d6198 -rd31c271afb2488abafa0642b07538a3e62106130 --- doc/example-scripts/traits-simple.tcl (.../traits-simple.tcl) (revision 6ad7855cd7aba089f7a160293802e1639d0d6198) +++ doc/example-scripts/traits-simple.tcl (.../traits-simple.tcl) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -4,19 +4,19 @@ # Traits: A Mechanism for Fine-grained Reuse, # ACM transactions on Programming Language Systems, Vol 28, No 2, March 2006 # -# Example in Fig 12: ReadStream and Trait TReadStream +# Example in Fig 12: ReadStream and Trait tReadStream # # In this example, traits are used to extend classes and other traits. package require nx::test package require nx::trait # -# Create a simple trait called +TReadStream+ which provides the +# Create a simple trait called +tReadStream+ which provides the # interface to a stream. In contrary to a composite trait, a simple # trait does not inherit from another trait. # -nx::Trait create TReadStream { +nx::Trait create tReadStream { # # Define the methods provided by this trait: # @@ -51,7 +51,7 @@ nx::Class create ReadStream { :property {collection ""} :property {position 0} - :require trait TReadStream + :require trait tReadStream } # Create an instance of the class +ReadStream+: Index: generic/nsf.c =================================================================== diff -u -rf32527e58ada02a9089fa17e2d1a99bac89f9be9 -rd31c271afb2488abafa0642b07538a3e62106130 --- generic/nsf.c (.../nsf.c) (revision f32527e58ada02a9089fa17e2d1a99bac89f9be9) +++ generic/nsf.c (.../nsf.c) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -17860,17 +17860,23 @@ ObjectSystemsCleanup(interp, withKeepvars); #ifdef DO_CLEANUP + { + NsfRuntimeState *rst = RUNTIME_STATE(interp); # if defined(CHECK_ACTIVATION_COUNTS) - assert(RUNTIME_STATE(interp)->cscList == NULL); + assert(rst->cscList == NULL); # endif - /*fprintf(stderr, "CLEANUP TOP NS\n");*/ - Tcl_Export(interp, RUNTIME_STATE(interp)->NsfNS, "", 1); - MEM_COUNT_FREE("TclNamespace",RUNTIME_STATE(interp)->NsfClassesNS); - MEM_COUNT_FREE("TclNamespace",RUNTIME_STATE(interp)->NsfNS); - Tcl_DeleteNamespace(RUNTIME_STATE(interp)->NsfClassesNS); - Tcl_DeleteNamespace(RUNTIME_STATE(interp)->NsfNS); + /*fprintf(stderr, "CLEANUP TOP NS\n");*/ + Tcl_Export(interp, rst->NsfNS, "", 1); + if (rst->NsfClassesNS) { + MEM_COUNT_FREE("TclNamespace",rst->NsfClassesNS); + Tcl_DeleteNamespace(rst->NsfClassesNS); + } + if (rst->NsfNS) { + MEM_COUNT_FREE("TclNamespace",rst->NsfNS); + Tcl_DeleteNamespace(rst->NsfNS); + } + } #endif - return TCL_OK; } Index: library/lib/nx-callback.tcl =================================================================== diff -u -r2076ef459f42cdf6426522aab56be490b66c2436 -rd31c271afb2488abafa0642b07538a3e62106130 --- library/lib/nx-callback.tcl (.../nx-callback.tcl) (revision 2076ef459f42cdf6426522aab56be490b66c2436) +++ library/lib/nx-callback.tcl (.../nx-callback.tcl) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -1,8 +1,8 @@ package require nx package require nx::trait -package provide nx::callback 1.0 +package provide nx::traits::callback 1.0 -nx::Trait create nx::TCallback { +nx::Trait create nx::traits::callback { # # A small support trait to ease syntactically the reference to # instance variables and the registration of callbacks. @@ -14,4 +14,4 @@ :method callback {name args} { return [list [nx::self] $name {*}$args] } -} \ No newline at end of file +} Index: library/lib/nx-traits.tcl =================================================================== diff -u -r8c8980c36802cc5e71f8a1713945e7655a5a480a -rd31c271afb2488abafa0642b07538a3e62106130 --- library/lib/nx-traits.tcl (.../nx-traits.tcl) (revision 8c8980c36802cc5e71f8a1713945e7655a5a480a) +++ library/lib/nx-traits.tcl (.../nx-traits.tcl) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -1,5 +1,5 @@ package require nx -package provide nx::trait 0.2 +package provide nx::trait 0.3 # @package nx::trait # @@ -39,6 +39,32 @@ # namespace eval ::nx::trait {} +# +# nx::trait::provide and nx::trait::require implement the basic +# loading mechanism for traits +# +nsf::proc nx::trait::provide {traitName script} { + set ::nsf::traitIndex($traitName) [list script $script] +} + +nsf::proc nx::trait::require {traitName} { + if {[::nsf::object::exists $traitName]} {return} + set key ::nsf::traitIndex($traitName) + if {[info exists $key]} { + array set "" [set $key] + if {$(script) ne ""} { + eval $(script) + + } + } + if {[::nsf::object::exists $traitName]} {return} + error "cannot require trait $traitName, trait unknown" +} + +# +# The function nx::trait::add adds the methods defined in the +# specified trait to the obj/class provided as first argument. +# nsf::proc nx::trait::add {obj -per-object:switch traitName {nameMap ""}} { array set map $nameMap foreach m [$traitName info methods -callprotection all] { @@ -54,6 +80,10 @@ } } +# +# The function nx::trait::checkObject checks, whether the target +# object has the method defined that the trait requires. +# nsf::proc nx::trait::checkObject {obj traitName} { foreach m [$traitName requiredMethods] { #puts "$m ok? [$obj info methods -closure $m]" @@ -62,6 +92,11 @@ } } } + +# +# The function nx::trait::checkClass checks, whether the target +# class has the method defined that the trait requires. +# nsf::proc nx::trait::checkClass {obj traitName} { foreach m [$traitName requiredMethods] { #puts "$m ok? [$obj info methods -closure $m]" @@ -71,31 +106,43 @@ } } +# +# The require methods for traits extend the predefined ensemble with +# trait-specific subcommands. +# nx::Class public method "require trait" {traitName {nameMap ""}} { # adding a trait to a class + nx::trait::require $traitName nx::trait::checkClass [self] $traitName nx::trait::add [self] $traitName $nameMap } nx::Class public method "require class trait" {traitName {nameMap ""}} { # adding a trait to the class object + nx::trait::require $traitName nx::trait::checkObject [self] $traitName nx::trait::add [self] -per-object $traitName $nameMap } nx::Object public method "require trait" {traitName {nameMap ""}} { # adding a trait to an object + nx::trait::require $traitName nx::traitCheckObject [self] $traitName nx::traitAdd [self] -per-object $traitName $nameMap } +# +# The class "nx::Trait" provides the basic properties and methods needed for +# the trait management. +# nx::Class create nx::Trait { - + :property {package} :property {requiredMethods:0..n,incremental ""} :property {requiredVariables:0..n,incremental ""} :public method "require trait" {traitName {nameMap ""}} { # adding a trait to a trait + nx::trait::require $traitName nx::trait::add [self] -per-object $traitName $nameMap set finalReqMethods {} foreach m [lsort -unique [concat ${:requiredMethods} [$traitName requiredMethods]]] { Index: library/lib/pkgIndex.tcl =================================================================== diff -u -r9ab6a86b4aee196f04363d13e5eadbdfdb814a06 -rd31c271afb2488abafa0642b07538a3e62106130 --- library/lib/pkgIndex.tcl (.../pkgIndex.tcl) (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) +++ library/lib/pkgIndex.tcl (.../pkgIndex.tcl) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -8,13 +8,17 @@ # script is sourced, the variable $dir must contain the # full path name of this file's directory. -package ifneeded nx::callback 1.0 [list source [file join $dir nx-callback.tcl]] package ifneeded nx::doc 1.0 [list source [file join $dir nxdoc-core.tcl]] package ifneeded nx::doc::dc 1.0 [list source [file join $dir nxdoc-dc.tcl]] package ifneeded nx::doc::html 1.0 [list source [file join $dir nxdoc-html.tcl]] package ifneeded nx::doc::xodoc 1.0 [list source [file join $dir nxdoc-xodoc.tcl]] package ifneeded nx::doc::xowiki 1.0 [list source [file join $dir nxdoc-xowiki.tcl]] package ifneeded nx::pp 1.0 [list source [file join $dir pp.tcl]] package ifneeded nx::test 1.0 [list source [file join $dir test.tcl]] -package ifneeded nx::trait 0.2 [list source [file join $dir nx-traits.tcl]] +package ifneeded nx::trait 0.3 [list source [file join $dir nx-traits.tcl]] +package ifneeded nx::traits::callback 1.0 [list source [file join $dir nx-callback.tcl]] package ifneeded nx::zip 1.1 [list source [file join $dir nx-zip.tcl]] +# -*- Tcl -*- +namespace eval ::nsf { + set traitIndex(nx::traits::callback) {script {package require nx::traits::callback}} +} Index: library/nx/nx.tcl =================================================================== diff -u -r8b8e75e010beae46adb99f4902ca80c50b1a6825 -rd31c271afb2488abafa0642b07538a3e62106130 --- library/nx/nx.tcl (.../nx.tcl) (revision 8b8e75e010beae46adb99f4902ca80c50b1a6825) +++ library/nx/nx.tcl (.../nx.tcl) (revision d31c271afb2488abafa0642b07538a3e62106130) @@ -5,6 +5,7 @@ namespace eval ::nsf {}; # make pkg indexer happy namespace eval ::nsf::object {}; # make pkg indexer happy namespace eval ::nx::internal {}; # make pkg indexer happy + namespace eval ::nx::traits {}; # make pkg indexer happy # # By setting the variable bootstrap, we can check later, whether we