Index: TODO =================================================================== diff -u -rfd39317a31fcc1aae5985fb0236901b910b4bae3 -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- TODO (.../TODO) (revision fd39317a31fcc1aae5985fb0236901b910b4bae3) +++ TODO (.../TODO) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -2904,15 +2904,13 @@ - improve bignum conversion handling further - found memleak in tcl -TODO: -- in method-require.test - # TODO: make me more pretty - set ::nsf::unknown(nx) {::nx::Class __unknown} -- nicer registration of unknown handlers needed? -- remove - #Class protected class method __unknown {name} {} +- provided nicer registration and inspection interface for unknown handlers +- added documentation for unknown handlers in tutorial +- cleanup of __unknown +TODO: + - add explicit regression tests for disposition + types - check refcounting for dispo+types - maybe: add a dispoition=pipe Index: doc/next-migration.txt =================================================================== diff -u -r1beeb594c1cd9e222b6e1f419e9a6f5ec0713249 -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- doc/next-migration.txt (.../next-migration.txt) (revision 1beeb594c1cd9e222b6e1f419e9a6f5ec0713249) +++ doc/next-migration.txt (.../next-migration.txt) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -325,11 +325,11 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When creating objects or classes, one should use the method +create+ -explicitly. In XOTcl, a default +unknown+ handler was provided for +explicitly. In XOTcl, a default +unknown+ method handler was provided for classes, which create for every unknown method invocation an object/class with the name of the invoked method. This technique was convenient, but as well dangerous, since typos in method names lead -easily to unexpected behavior. This default unknown handler is not +easily to unexpected behavior. This default unknown method handler is not provided in NX (but can certainly be provided as a one-liner in NX by the application). Index: doc/next-tutorial.html =================================================================== diff -u -rb3018d3be0f1524a3f1709edc0e2ddb5d8bc4c0b -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- doc/next-tutorial.html (.../next-tutorial.html) (revision b3018d3be0f1524a3f1709edc0e2ddb5d8bc4c0b) +++ doc/next-tutorial.html (.../next-tutorial.html) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -2323,6 +2323,157 @@

+ + + + +
+

4. Miscellaneous

+
+
+

4.1. Unknown Handlers

+

NX provides two kinds of unknown handlers:

+
    +
  • +

    +Unknown handlers for methods +

    +
  • +
  • +

    +Unknown handlers for objects and classes +

    +
  • +
+
+

4.1.1. Unknown Handlers for Methods

+

Object and classes might be equipped +with a method unknown 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

+
Listing 29: Unknown Method Handler

+
+
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+
::nx::Object create o {
+  :method unknown {called_method args} {
+    puts "Unknown method '$called_method' called"
+  }
+}
+
+# Invoke an unknown method for object o:
+o foo 1 2 3
+
+# Output will be: "Unknown method 'foo' called"
+

Without any provision of an unknown method handler, an error will be +raised, when an unknown method is called.

+
+
+

4.1.2. Unknown Handlers for Objects and Classes

+

The next scripting framework provides in addition to unknown method +handlers also a means to dynamically create objects and classes, when +these are referenced. This happens e.g. when superclasses, mixins, or +parent objects are referenced. This mechanism can be used to implement +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).

+
Listing 30: Unknown Class Handler

+
+
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+
::nx::Class public class method __unknown {name} {
+  # A very simple unknown handler, showing just how
+  # the mechanism works.
+  puts "***** __unknown called with <$name>"
+  ::nx::Class create $name
+}
+
+# Register an unknown handler as a method of ::nx::Class
+::nsf::unknown::add nx {::nx::Class __unknown}
+
+::nx::Object create o {
+  # The class M is unknown at this point
+
+  :mixin add M
+  # The line above has triggered the unknown class handler,
+  # class M is now defined
+
+  puts [:info mixin classes]
+  # The output will be:
+  #     ***** __unknown called with <::M>
+  #     ::M
+}
+

The Next Scripting Framework allows to add, query, delete abd list unknown handlers.

+
Listing 31: Unknown Handler registration

+
+
+
  1
+  2
+  3
+  4
+  5
+
# Interface for unknown handlers:
+# nsf::unknown::add /key/ /handler/
+# nsf::unknown::get /key/
+# nsf::unknown::delete /key/
+# nsf::unknown::keys
References
  • @@ -2406,7 +2557,7 @@

    Index: doc/next-tutorial.txt =================================================================== diff -u -rb3018d3be0f1524a3f1709edc0e2ddb5d8bc4c0b -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- doc/next-tutorial.txt (.../next-tutorial.txt) (revision b3018d3be0f1524a3f1709edc0e2ddb5d8bc4c0b) +++ doc/next-tutorial.txt (.../next-tutorial.txt) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -1287,6 +1287,96 @@ - incremental slots +== Miscellaneous + +=== Unknown Handlers + +NX provides two kinds of unknown handlers: + +- Unknown handlers for methods +- Unknown handlers for objects and classes + +==== Unknown Handlers for Methods + +Object and classes might be equipped +with a method +unknown+ 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 + +[[xmp-unknown-method]] +.Listing {counter:figure-number}: Unknown Method Handler +{set:xmp-unknown-method:Listing {figure-number}} +[source,tcl,numbers] +-------------------------------------------------- +::nx::Object create o { + :method unknown {called_method args} { + puts "Unknown method '$called_method' called" + } +} + +# Invoke an unknown method for object o: +o foo 1 2 3 + +# Output will be: "Unknown method 'foo' called" +-------------------------------------------------- + +Without any provision of an unknown method handler, an error will be +raised, when an unknown method is called. + +==== Unknown Handlers for Objects and Classes + +The next scripting framework provides in addition to unknown method +handlers also a means to dynamically create objects and classes, when +these are referenced. This happens e.g. when superclasses, mixins, or +parent objects are referenced. This mechanism can be used to implement +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). + +[[xmp-unknown-class]] +.Listing {counter:figure-number}: Unknown Class Handler +{set:xmp-unknown-class:Listing {figure-number}} +[source,tcl,numbers] +-------------------------------------------------- +::nx::Class public class method __unknown {name} { + # A very simple unknown handler, showing just how + # the mechanism works. + puts "***** __unknown called with <$name>" + ::nx::Class create $name +} + +# Register an unknown handler as a method of ::nx::Class +::nsf::unknown::add nx {::nx::Class __unknown} + +::nx::Object create o { + # The class M is unknown at this point + + :mixin add M + # The line above has triggered the unknown class handler, + # class M is now defined + + puts [:info mixin classes] + # The output will be: + # ***** __unknown called with <::M> + # ::M +} +-------------------------------------------------- + +The Next Scripting Framework allows to add, query, delete and list unknown handlers. + +[[xmp-unknown-registgration]] +.Listing {counter:figure-number}: Unknown Handler registration +{set:xmp-unknown-registgration:Listing {figure-number}} +[source,tcl,numbers] +-------------------------------------------------- +# Interface for unknown handlers: +# nsf::unknown::add /key/ /handler/ +# nsf::unknown::get /key/ +# nsf::unknown::delete /key/ +# nsf::unknown::keys +-------------------------------------------------- + + [bibliography] .References Index: generic/nsf.tcl =================================================================== diff -u -r756a5ed4e51921ada898fdf69cc7bd2c5c616828 -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- generic/nsf.tcl (.../nsf.tcl) (revision 756a5ed4e51921ada898fdf69cc7bd2c5c616828) +++ generic/nsf.tcl (.../nsf.tcl) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -91,8 +91,15 @@ } return "" } + namespace eval ::nsf::unknown { + proc add {key handler} {set ::nsf::unknown($key) $handler} + proc get {key} {return $::nsf::unknown($key)} + proc delete {key} {array unset ::nsf::unknown($key)} + proc keys {} {array names ::nsf::unknown} + } + # Example unknown handler: - # set ::nsf::unknown(xotcl) {::xotcl::Class __unknown} + # ::nsf::unknown::add xotcl {::xotcl::Class __unknown} ###################################################################### Index: generic/predefined.h =================================================================== diff -u -r756a5ed4e51921ada898fdf69cc7bd2c5c616828 -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- generic/predefined.h (.../predefined.h) (revision 756a5ed4e51921ada898fdf69cc7bd2c5c616828) +++ generic/predefined.h (.../predefined.h) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -36,6 +36,11 @@ "if {$result ne \"\"} {\n" "return $result}}\n" "return \"\"}\n" +"namespace eval ::nsf::unknown {\n" +"proc add {key handler} {set ::nsf::unknown($key) $handler}\n" +"proc get {key} {return $::nsf::unknown($key)}\n" +"proc delete {key} {array unset ::nsf::unknown($key)}\n" +"proc keys {} {array names ::nsf::unknown}}\n" "proc ::nsf::exithandler {args} {\n" "lassign $args op value\n" "switch $op {\n" Index: library/nx/nx.tcl =================================================================== diff -u -r67591822465e64d9051583c9aa71f8d3a4ef5c96 -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- library/nx/nx.tcl (.../nx.tcl) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) +++ library/nx/nx.tcl (.../nx.tcl) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -355,15 +355,6 @@ } ###################################################################### - # The method __unknown is called in cases, where we try to resolve - # an unkown class. One could define a custom resolver with this name - # to load the class on the fly. After the call to __unknown, nsf - # tries to resolve the class again. This meachnism is used e.g. by - # the ::ttrace mechanism for partial loading by Zoran. - ###################################################################### - #Class protected class method __unknown {name} {} - - ###################################################################### # Provde method "alias" # # -frame object|method make only sense for c-defined cmds, Index: library/xotcl/library/xotcl2.tcl =================================================================== diff -u -r756a5ed4e51921ada898fdf69cc7bd2c5c616828 -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- library/xotcl/library/xotcl2.tcl (.../xotcl2.tcl) (revision 756a5ed4e51921ada898fdf69cc7bd2c5c616828) +++ library/xotcl/library/xotcl2.tcl (.../xotcl2.tcl) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -867,7 +867,7 @@ #::nsf::method::alias ::xotcl::Class -per-object __unknown ::nx::Class::__unknown ::nsf::method::create ::xotcl::Class -per-object __unknown {name} {} - set ::nsf::unknown(xotcl) {::xotcl::Class __unknown} + ::nsf::unknown::add xotcl {::xotcl::Class __unknown} proc myproc {args} {linsert $args 0 [::xotcl::self]} proc myvar {var} {:requireNamespace; return [::xotcl::self]::$var} Index: tests/method-require.test =================================================================== diff -u -r756a5ed4e51921ada898fdf69cc7bd2c5c616828 -r542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043 --- tests/method-require.test (.../method-require.test) (revision 756a5ed4e51921ada898fdf69cc7bd2c5c616828) +++ tests/method-require.test (.../method-require.test) (revision 542e84bd66ce4c3cd28e4ba1fd41f2151d8cb043) @@ -62,8 +62,7 @@ #puts stderr "***** __unknown called with <$name>" ::nx::Object create $name } - # TODO: make me more pretty - set ::nsf::unknown(nx) {::nx::Class __unknown} + ::nsf::unknown::add nx {::nx::Class __unknown} nx::Class create C