summaryrefslogtreecommitdiffstats
path: root/tcllib/modules/interp
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 19:39:39 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 19:39:39 (GMT)
commitea28451286d3ea4a772fa174483f9a7a66bb1ab3 (patch)
tree6ee9d8a7848333a7ceeee3b13d492e40225f8b86 /tcllib/modules/interp
parentb5ca09bae0d6a1edce939eea03594dd56383f2c8 (diff)
parent7c621da28f07e449ad90c387344f07a453927569 (diff)
downloadblt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.zip
blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.gz
blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.bz2
Merge commit '7c621da28f07e449ad90c387344f07a453927569' as 'tcllib'
Diffstat (limited to 'tcllib/modules/interp')
-rw-r--r--tcllib/modules/interp/ChangeLog108
-rw-r--r--tcllib/modules/interp/deleg_method.man49
-rw-r--r--tcllib/modules/interp/deleg_method.tcl64
-rw-r--r--tcllib/modules/interp/deleg_method.test192
-rw-r--r--tcllib/modules/interp/deleg_proc.man47
-rw-r--r--tcllib/modules/interp/deleg_proc.tcl68
-rw-r--r--tcllib/modules/interp/deleg_proc.test153
-rw-r--r--tcllib/modules/interp/interp.tcl87
-rw-r--r--tcllib/modules/interp/interp.test127
-rw-r--r--tcllib/modules/interp/pkgIndex.tcl4
-rw-r--r--tcllib/modules/interp/tcllib_interp.man74
11 files changed, 973 insertions, 0 deletions
diff --git a/tcllib/modules/interp/ChangeLog b/tcllib/modules/interp/ChangeLog
new file mode 100644
index 0000000..0fb2cb9
--- /dev/null
+++ b/tcllib/modules/interp/ChangeLog
@@ -0,0 +1,108 @@
+2013-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.15 ========================
+ *
+
+2011-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.14 ========================
+ *
+
+2011-11-07 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * interp.tcl (::interp::createEmpty): Fixed problem with 8.6,
+ * interp.man: where the removal of the ::tcl namespace also kills
+ * pkgIndex.tcl: the 'namespace' command, as it is ensemblified.
+ Version bumped to 0.1.2.
+
+2011-01-24 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.13 ========================
+ *
+
+2009-12-07 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.12 ========================
+ *
+
+2008-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.11.1 ========================
+ *
+
+2008-10-16 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.11 ========================
+ *
+
+2007-09-12 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.10 ========================
+ *
+
+2007-08-20 Andreas Kupries <andreask@activestate.com>
+
+ * tcllib_interp.tcl: Bumped package version to 0.1.1.
+ * interp.man:
+ * pkgIndex.tcl:
+
+2007-08-02 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * interp.tcl (::interp::createEmpty): Modified the sequence
+ clearing an interpreter of commands to properly handle the ::tcl
+ system namespace of Tcl 8.5.
+
+2007-08-01 Andreas Kupries <andreask@activestate.com>
+
+ * deleg_method.test: Updated tests for changes in snit internal,
+ now using the new method introspection methods. Requires snit
+ 1.3.1
+
+2007-03-21 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * tcllib_interp.man: Fixed all warnings due to use of now
+ * deleg_method.man: deprecated commands. Added a section about how
+ * deleg_proc.man: to give feedback.
+
+2006-10-03 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.9 ========================
+ *
+
+2006-09-01 Andreas Kupries <andreask@activestate.com>
+
+ * deleg_proc.man: Added manpages for the packages creating
+ * deleg_merthod.man: delegation procedures and methods.
+
+ * deleg_proc.tcl: Fixed bug, forgot that not only a comm
+ * deleg_method.tcl: channel is needed, but also the id of
+ * deleg_proc.test: the remote location. Added argument,
+ * deleg_method.test: shuffled arguments, updated testsuites.
+ * pkgIndex.tcl: ** INCOMPATIBILITY ** Version bumped to 0.2
+
+2006-08-30 Andreas Kupries <andreask@activestate.com>
+
+ * interp.man: Renamed the manpage, avoid clash with
+ * tcllib_interp.man: core documentation.
+
+2006-08-29 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * deleg_proc.tcl: Creation of delegation procedures.
+ * deleg_proc.test:
+
+ * deleg_method.tcl: Creation of delegation methods.
+ * deleg_method.test:
+
+2006-08-16 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * interp.tcl: New module. Interpreter creation and alias
+ * interp.man: utility commands. Basic testsuite.
+ * interp.test:
diff --git a/tcllib/modules/interp/deleg_method.man b/tcllib/modules/interp/deleg_method.man
new file mode 100644
index 0000000..89c0824
--- /dev/null
+++ b/tcllib/modules/interp/deleg_method.man
@@ -0,0 +1,49 @@
+[comment {-*- tcl -*- doctools manpage}]
+[manpage_begin deleg_method n 0.2]
+[keywords comm]
+[keywords delegation]
+[keywords interpreter]
+[keywords method]
+[keywords snit]
+[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}]
+[moddesc {Interpreter utilities}]
+[titledesc {Creation of comm delegates (snit methods)}]
+[category {Programming tools}]
+[require Tcl 8.3]
+[require snit [opt 1.1]]
+[require interp::delegate::method [opt 0.2]]
+[description]
+[para]
+
+This package provides a single command for use within [package snit]
+type definition (i.e. actually a [cmd snit::macro]) for the convenient
+creation of methods which delegate the actual work to a remote
+location via a "channel" created by the package [package comm].
+
+[section API]
+[list_begin definitions]
+
+[call [cmd ::interp::delegate::method] [opt [option -async]] [arg name] [arg arguments] [arg comm] [arg id]]
+
+This commands creates a method which is named by [arg name]. All
+invokations of this method will delegate the actual work to the remote
+location identified by the comm channel [arg comm] and the endpoint
+[arg id].
+
+[para]
+
+The name of the remote method invoked by the delegator is identical to
+the name of the method itself.
+
+[para]
+
+Normally the generated method marshalls the [arg arguments], and
+returns the result from the remote method as its own result. If
+however the option [option -async] was specified then the generated
+method will not wait for a result and return immediately.
+
+[list_end]
+
+[vset CATEGORY interp]
+[include ../doctools2base/include/feedback.inc]
+[manpage_end]
diff --git a/tcllib/modules/interp/deleg_method.tcl b/tcllib/modules/interp/deleg_method.tcl
new file mode 100644
index 0000000..c25f9a6
--- /dev/null
+++ b/tcllib/modules/interp/deleg_method.tcl
@@ -0,0 +1,64 @@
+# interp.tcl
+# Some utility commands for creation of delegation methods.
+# (Delegation of methods to a remote interpreter via a comm
+# handle).
+#
+# Copyright (c) 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: deleg_method.tcl,v 1.2 2006/09/01 19:58:21 andreas_kupries Exp $
+
+package require Tcl 8.3
+package require snit
+
+# ### ### ### ######### ######### #########
+## Requisites
+
+namespace eval ::interp::delegate {}
+
+# ### ### ### ######### ######### #########
+## Public API
+
+snit::macro ::interp::delegate::method {args} {
+ # syntax: ?-async? name arguments comm id
+
+ set async 0
+ while {[string match -* [set opt [lindex $args 0]]]} {
+ switch -exact -- $opt {
+ -async {set async 1 ; set args [lrange $args 1 end]}
+ default {
+ return -code error "unknown option \"$opt\", expected -async"
+ }
+ }
+ }
+ if {[llength $args] != 4} {
+ return -code error "wrong # args"
+ }
+ foreach {name arguments comm rid} $args break
+
+ if {![llength $arguments]} {
+ set delegate "[list $name]"
+ } elseif {[string equal args [lindex $arguments end]]} {
+ if {[llength $arguments] == 1} {
+ set delegate "\[linsert \$args 0 [list $name]\]"
+ } else {
+ set delegate "\[linsert \$args 0 [list $name] \$[join [lrange $arguments 0 end-1] " \$"]\]"
+ }
+ } else {
+ set delegate "\[list [list $name] \$[join $arguments " \$"]\]"
+ }
+
+ set body ""
+ append body [list $comm] " " "send "
+ if {$async} {append body "-async "}
+ append body [list $rid] " " $delegate
+
+ ::method $name $arguments $body
+}
+
+# ### ### ### ######### ######### #########
+## Ready to go
+
+package provide interp::delegate::method 0.2
diff --git a/tcllib/modules/interp/deleg_method.test b/tcllib/modules/interp/deleg_method.test
new file mode 100644
index 0000000..5625b28
--- /dev/null
+++ b/tcllib/modules/interp/deleg_method.test
@@ -0,0 +1,192 @@
+# -*- tcl -*-
+# interp.test: tests for the interp alias and creation utilities
+#
+# Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+
+# -------------------------------------------------------------------------
+
+source [file join \
+ [file dirname [file dirname [file join [pwd] [info script]]]] \
+ devtools testutilities.tcl]
+
+testsNeedTcl 8.3
+testsNeedTcltest 1.0
+
+support {
+ use snit/snit.tcl snit
+ testsNeed snit 1.3.1 ; # method introspection arguments/body
+}
+testing {
+ useLocal deleg_method.tcl interp::delegate::method
+}
+
+# -------------------------------------------------------------------------
+
+test dmethod-1.0 {wrong#args} {
+ catch {snit::type foo {interp::delegate::method}} msg
+ set msg
+} {wrong # args}
+
+test dmethod-1.1 {wrong#args} {
+ catch {snit::type foo {interp::delegate::method a}} msg
+ set msg
+} {wrong # args}
+
+test dmethod-1.2 {wrong#args} {
+ catch {snit::type foo {interp::delegate::method a b}} msg
+ set msg
+} {wrong # args}
+
+test dmethod-1.3 {wrong#args} {
+ catch {snit::type foo {interp::delegate::method a b c}} msg
+ set msg
+} {wrong # args}
+
+test dmethod-1.4 {wrong#args} {
+ catch {snit::type foo {interp::delegate::method a b c d e}} msg
+ set msg
+} {wrong # args}
+
+# -------------------------------------------------------------------------
+
+test dmethod-2.0 {bad switch} {
+ catch {snit::type foo {interp::delegate::method -bogus}} msg
+ set msg
+} {unknown option "-bogus", expected -async}
+
+# -------------------------------------------------------------------------
+
+test dmethod-3.0 {delegation result} {
+ snit::type foo {
+ interp::delegate::method request {} COMM ID
+ }
+ res!
+ foo bar
+ res+ [info commands foo::Snit_methodrequest]
+ res+ [lsort [bar info methods]]
+ bar destroy
+ foo destroy
+ res?
+} {::foo::Snit_methodrequest {{destroy info request}}}
+
+# -------------------------------------------------------------------------
+
+test dmethod-4.0 {signature} {
+ snit::type foo {
+ interp::delegate::method request {} COMM ID
+ }
+ foo X
+ res!
+ res+ \
+ [X info args request] \
+ [string trimleft [X info body request]]
+ X destroy
+ foo destroy
+ res?
+} {{{} {COMM send ID request}}}
+
+test dmethod-4.1 {signature} {
+ snit::type foo {
+ interp::delegate::method request {a b} COMM ID
+ }
+ foo X
+ res!
+ res+ \
+ [X info args request] \
+ [string trimleft [X info body request]]
+ X destroy
+ foo destroy
+ res?
+} {{{a b} {COMM send ID [list request $a $b]}}}
+
+test dmethod-4.2 {signature} {
+ snit::type foo {
+ interp::delegate::method request {a b args} COMM ID
+ }
+ foo X
+ res!
+ res+ \
+ [X info args request] \
+ [string trimleft [X info body request]]
+ X destroy
+ foo destroy
+ res?
+} {{{a b args} {COMM send ID [linsert $args 0 request $a $b]}}}
+
+test dmethod-4.3 {signature} {
+ snit::type foo {
+ interp::delegate::method request {args} COMM ID
+ }
+ foo X
+ res!
+ res+ \
+ [X info args request] \
+ [string trimleft [X info body request]]
+ X destroy
+ foo destroy
+ res?
+} {{args {COMM send ID [linsert $args 0 request]}}}
+
+# -------------------------------------------------------------------------
+
+test dmethod-5.0 {signature} {
+ snit::type foo {
+ interp::delegate::method -async request {} COMM ID
+ }
+ foo X
+ res!
+ res+ \
+ [X info args request] \
+ [string trimleft [X info body request]]
+ X destroy
+ foo destroy
+ res?
+} {{{} {COMM send -async ID request}}}
+
+test dmethod-5.1 {signature} {
+ snit::type foo {
+ interp::delegate::method -async request {a b} COMM ID
+ }
+ foo X
+ res!
+ res+ \
+ [X info args request] \
+ [string trimleft [X info body request]]
+ X destroy
+ foo destroy
+ res?
+} {{{a b} {COMM send -async ID [list request $a $b]}}}
+
+test dmethod-5.2 {signature} {
+ snit::type foo {
+ interp::delegate::method -async request {a b args} COMM ID
+ }
+ foo X
+ res!
+ res+ \
+ [X info args request] \
+ [string trimleft [X info body request]]
+ X destroy
+ foo destroy
+ res?
+} {{{a b args} {COMM send -async ID [linsert $args 0 request $a $b]}}}
+
+test dmethod-5.3 {signature} {
+ snit::type foo {
+ interp::delegate::method -async request {args} COMM ID
+ }
+ foo X
+ res!
+ res+ \
+ [X info args request] \
+ [string trimleft [X info body request]]
+ X destroy
+ foo destroy
+ res?
+} {{args {COMM send -async ID [linsert $args 0 request]}}}
+
+# -------------------------------------------------------------------------
+
+testsuiteCleanup
+return
diff --git a/tcllib/modules/interp/deleg_proc.man b/tcllib/modules/interp/deleg_proc.man
new file mode 100644
index 0000000..6060bd2
--- /dev/null
+++ b/tcllib/modules/interp/deleg_proc.man
@@ -0,0 +1,47 @@
+[comment {-*- tcl -*- doctools manpage}]
+[manpage_begin deleg_proc n 0.2]
+[keywords comm]
+[keywords delegation]
+[keywords interpreter]
+[keywords procedure]
+[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}]
+[moddesc {Interpreter utilities}]
+[titledesc {Creation of comm delegates (procedures)}]
+[category {Programming tools}]
+[require Tcl 8.3]
+[require interp::delegate::proc [opt 0.2]]
+[description]
+[para]
+
+This package provides a single command for the convenient creation of
+procedures which delegate the actual work to a remote location via a
+"channel" created by the package [package comm].
+
+[section API]
+[list_begin definitions]
+
+[call [cmd ::interp::delegate::proc] [opt [option -async]] [arg name] [arg arguments] [arg comm] [arg id]]
+
+This commands creates a procedure which is named by [arg name] and
+returns its fully-qualified name. All invokations of this procedure
+will delegate the actual work to the remote location identified by the
+comm channel [arg comm] and the endpoint [arg id].
+
+[para]
+
+The name of the remote procedure invoked by the delegator is
+[lb]namespace tail [arg name][rb]. I.e., namespace information is
+stripped from the call.
+
+[para]
+
+Normally the generated procedure marshalls the [arg arguments], and
+returns the result from the remote procedure as its own result. If
+however the option [option -async] was specified then the generated
+procedure will not wait for a result and return immediately.
+
+[list_end]
+
+[vset CATEGORY interp]
+[include ../doctools2base/include/feedback.inc]
+[manpage_end]
diff --git a/tcllib/modules/interp/deleg_proc.tcl b/tcllib/modules/interp/deleg_proc.tcl
new file mode 100644
index 0000000..8aee165
--- /dev/null
+++ b/tcllib/modules/interp/deleg_proc.tcl
@@ -0,0 +1,68 @@
+# interp.tcl
+# Some utility commands for creation of delegation procedures
+# (Delegation of commands to a remote interpreter via a comm
+# handle).
+#
+# Copyright (c) 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: deleg_proc.tcl,v 1.2 2006/09/01 19:58:21 andreas_kupries Exp $
+
+package require Tcl 8.3
+
+# ### ### ### ######### ######### #########
+## Requisites
+
+namespace eval ::interp::delegate {}
+
+# ### ### ### ######### ######### #########
+## Public API
+
+proc ::interp::delegate::proc {args} {
+ # syntax: ?-async? name arguments comm id
+
+ set async 0
+ while {[string match -* [set opt [lindex $args 0]]]} {
+ switch -exact -- $opt {
+ -async {
+ set async 1
+ set args [lrange $args 1 end]
+ }
+ default {
+ return -code error "unknown option \"$opt\", expected -async"
+ }
+ }
+ }
+ if {[llength $args] != 4} {
+ return -code error "wrong # args"
+ }
+ foreach {name arguments comm rid} $args break
+ set base [namespace tail $name]
+
+ if {![llength $arguments]} {
+ set delegate "[list $base]"
+ } elseif {[string equal args [lindex $arguments end]]} {
+ if {[llength $arguments] == 1} {
+ set delegate "\[linsert \$args 0 [list $base]\]"
+ } else {
+ set delegate "\[linsert \$args 0 [list $base] \$[join [lrange $arguments 0 end-1] " \$"]\]"
+ }
+ } else {
+ set delegate "\[list [list $base] \$[join $arguments " \$"]\]"
+ }
+
+ set body ""
+ append body [list $comm] " " "send "
+ if {$async} {append body "-async "}
+ append body [list $rid] " " $delegate
+
+ uplevel 1 [list ::proc $name $arguments $body]
+ return $name
+}
+
+# ### ### ### ######### ######### #########
+## Ready to go
+
+package provide interp::delegate::proc 0.2
diff --git a/tcllib/modules/interp/deleg_proc.test b/tcllib/modules/interp/deleg_proc.test
new file mode 100644
index 0000000..02ecf3e
--- /dev/null
+++ b/tcllib/modules/interp/deleg_proc.test
@@ -0,0 +1,153 @@
+# -*- tcl -*-
+# interp.test: tests for the interp alias and creation utilities
+#
+# Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+
+# -------------------------------------------------------------------------
+
+source [file join \
+ [file dirname [file dirname [file join [pwd] [info script]]]] \
+ devtools testutilities.tcl]
+
+testsNeedTcl 8.3
+testsNeedTcltest 1.0
+
+testing {
+ useLocal deleg_proc.tcl interp::delegate::proc
+}
+
+# -------------------------------------------------------------------------
+
+test dproc-1.0 {wrong#args} {
+ catch {interp::delegate::proc} msg
+ set msg
+} {wrong # args}
+
+test dproc-1.1 {wrong#args} {
+ catch {interp::delegate::proc a} msg
+ set msg
+} {wrong # args}
+
+test dproc-1.2 {wrong#args} {
+ catch {interp::delegate::proc a b} msg
+ set msg
+} {wrong # args}
+
+test dproc-1.3 {wrong#args} {
+ catch {interp::delegate::proc a b c} msg
+ set msg
+} {wrong # args}
+
+test dproc-1.4 {wrong#args} {
+ catch {interp::delegate::proc a b c d e} msg
+ set msg
+} {wrong # args}
+
+# -------------------------------------------------------------------------
+
+test dproc-2.0 {bad switch} {
+ catch {interp::delegate::proc -bogus} msg
+ set msg
+} {unknown option "-bogus", expected -async}
+
+# -------------------------------------------------------------------------
+
+test dproc-3.0 {delegation result} {
+ res!
+ res+ \
+ [info commands request] \
+ [interp::delegate::proc request {} FOO ID] \
+ [info commands request]
+ rename request {}
+ res?
+} {{{} request request}}
+
+# -------------------------------------------------------------------------
+
+test dproc-4.0 {signature} {
+ res!
+ res+ \
+ [interp::delegate::proc {re quest} {} COMM ID] \
+ [info args {re quest}] \
+ [info body {re quest}]
+ rename {re quest} {}
+ res?
+} {{{re quest} {} {COMM send ID {re quest}}}}
+
+test dproc-4.1 {signature} {
+ res!
+ res+ \
+ [interp::delegate::proc {re quest} {a b} COMM ID] \
+ [info args {re quest}] \
+ [info body {re quest}]
+ rename {re quest} {}
+ res?
+} {{{re quest} {a b} {COMM send ID [list {re quest} $a $b]}}}
+
+test dproc-4.2 {signature} {
+ res!
+ res+ \
+ [interp::delegate::proc {re quest} {a b args} COMM ID] \
+ [info args {re quest}] \
+ [info body {re quest}]
+ rename {re quest} {}
+ res?
+} {{{re quest} {a b args} {COMM send ID [linsert $args 0 {re quest} $a $b]}}}
+
+test dproc-4.3 {signature} {
+ res!
+ res+ \
+ [interp::delegate::proc {re quest} {args} COMM ID] \
+ [info args {re quest}] \
+ [info body {re quest}]
+ rename {re quest} {}
+ res?
+} {{{re quest} args {COMM send ID [linsert $args 0 {re quest}]}}}
+
+# -------------------------------------------------------------------------
+
+test dproc-5.0 {signature} {
+ res!
+ res+ \
+ [interp::delegate::proc -async {re quest} {} COMM ID] \
+ [info args {re quest}] \
+ [info body {re quest}]
+ rename {re quest} {}
+ res?
+} {{{re quest} {} {COMM send -async ID {re quest}}}}
+
+test dproc-5.1 {signature} {
+ res!
+ res+ \
+ [interp::delegate::proc -async {re quest} {a b} COMM ID] \
+ [info args {re quest}] \
+ [info body {re quest}]
+ rename {re quest} {}
+ res?
+} {{{re quest} {a b} {COMM send -async ID [list {re quest} $a $b]}}}
+
+test dproc-5.2 {signature} {
+ res!
+ res+ \
+ [interp::delegate::proc -async {re quest} {a b args} COMM ID] \
+ [info args {re quest}] \
+ [info body {re quest}]
+ rename {re quest} {}
+ res?
+} {{{re quest} {a b args} {COMM send -async ID [linsert $args 0 {re quest} $a $b]}}}
+
+test dproc-5.3 {signature} {
+ res!
+ res+ \
+ [interp::delegate::proc -async {re quest} {args} COMM ID] \
+ [info args {re quest}] \
+ [info body {re quest}]
+ rename {re quest} {}
+ res?
+} {{{re quest} args {COMM send -async ID [linsert $args 0 {re quest}]}}}
+
+# -------------------------------------------------------------------------
+
+testsuiteCleanup
+return
diff --git a/tcllib/modules/interp/interp.tcl b/tcllib/modules/interp/interp.tcl
new file mode 100644
index 0000000..7fefa5f
--- /dev/null
+++ b/tcllib/modules/interp/interp.tcl
@@ -0,0 +1,87 @@
+# interp.tcl
+# Some utility commands for interpreter creation
+#
+# Copyright (c) 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: interp.tcl,v 1.5 2011/11/08 02:40:31 andreas_kupries Exp $
+
+package require Tcl 8.3
+
+# ### ### ### ######### ######### #########
+## Requisites
+
+namespace eval ::interp {}
+
+# ### ### ### ######### ######### #########
+## Public API
+
+proc ::interp::createEmpty {args} {
+ # Create interpreter, predefined path or
+ # automatic naming.
+
+ if {[llength $args] > 1} {
+ return -code error "wrong#args: Expected ?path?"
+ } elseif {[llength $args] == 1} {
+ set i [interp create [lindex $args 0]]
+ } else {
+ set i [interp create]
+ }
+
+ # Clear out namespaces and commands, leaving an empty interpreter
+ # behind. Take care to delete the rename command last, as it is
+ # needed to perform the deletions. We have to keep the 'rename'
+ # command until last to allow us to delete all ocmmands. We also
+ # have to defer deletion of the ::tcl namespace (if present), as
+ # it may contain state for the auto-loader, which may be
+ # invoked. This also forces us to defer the deletion of the
+ # builtin command 'namespace' so that we can delete ::tcl at last.
+
+ foreach n [interp eval $i [list ::namespace children ::]] {
+ if {[string equal $n ::tcl]} continue
+ interp eval $i [list namespace delete $n]
+ }
+ foreach c [interp eval $i [list ::info commands]] {
+ if {[string equal $c rename]} continue
+ if {[string equal $c namespace]} continue
+ interp eval $i [list ::rename $c {}]
+ }
+
+ interp eval $i [list ::namespace delete ::tcl]
+ catch {
+ # In 8.6 the removal of the ::tcl namespace killed the
+ # ensemblified namespace command already, so a deletion will
+ # fail. Easier to catch than being conditional.
+ interp eval $i [list ::rename namespace {}]
+ }
+ interp eval $i [list ::rename rename {}]
+
+ # Done. Result is ready.
+
+ return $i
+}
+
+proc ::interp::snitLink {path methods} {
+ foreach m $methods {
+ set dst [uplevel 1 [linsert $m 0 mymethod]]
+ set alias [linsert $dst 0 interp alias $path [lindex $m 0] {}]
+ eval $alias
+ }
+ return
+}
+
+proc ::interp::snitDictLink {path methoddict} {
+ foreach {c m} $methoddict {
+ set dst [uplevel 1 [linsert $m 0 mymethod]]
+ set alias [linsert $dst 0 interp alias $path $c {}]
+ eval $alias
+ }
+ return
+}
+
+# ### ### ### ######### ######### #########
+## Ready to go
+
+package provide interp 0.1.2
diff --git a/tcllib/modules/interp/interp.test b/tcllib/modules/interp/interp.test
new file mode 100644
index 0000000..bcbc65a
--- /dev/null
+++ b/tcllib/modules/interp/interp.test
@@ -0,0 +1,127 @@
+# -*- tcl -*-
+# interp.test: tests for the interp alias and creation utilities
+#
+# Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+
+# -------------------------------------------------------------------------
+
+source [file join \
+ [file dirname [file dirname [file join [pwd] [info script]]]] \
+ devtools testutilities.tcl]
+
+testsNeedTcl 8.3
+testsNeedTcltest 1.0
+
+support {
+ use snit/snit.tcl snit
+}
+testing {
+ useLocal interp.tcl interp
+}
+
+# -------------------------------------------------------------------------
+
+test interp-1.0 {wrong#args} {
+ catch {interp::createEmpty a b} msg
+ set msg
+} {wrong#args: Expected ?path?}
+
+# -------------------------------------------------------------------------
+
+test interp-2.0 {auto naming, empty} {
+ set i [interp::createEmpty]
+ catch {$i eval {set x}} msg
+ interp delete $i
+ set msg
+} {invalid command name "set"}
+
+test interp-2.1 {explicit naming, empty} {
+ set i [interp::createEmpty A]
+ catch {$i eval {set x}} msg
+ interp delete $i
+ list $i $msg
+} {A {invalid command name "set"}}
+
+# -------------------------------------------------------------------------
+
+test interp-3.0 {wrong#args} {
+ catch {interp::snitLink} msg
+ set msg
+} [tcltest::wrongNumArgs interp::snitLink {path methods} 0]
+
+test interp-3.1 {wrong#args} {
+ catch {interp::snitLink a} msg
+ set msg
+} [tcltest::wrongNumArgs interp::snitLink {path methods} 1]
+
+test interp-3.2 {wrong#args} {
+ catch {interp::snitLink a b c} msg
+ set msg
+} [tcltest::tooManyArgs interp::snitLink {path methods}]
+
+test interp-3.3 {create, test redirection} {
+ res!
+ snit::type foo {
+ variable i
+ constructor {} {
+ set i [interp::createEmpty]
+ interp::snitLink $i Duck
+ }
+ method Duck {} {
+ res+ Ducking
+ }
+ method ho {} {$i eval Duck}
+ }
+ set i [foo %AUTO%]
+ $i ho
+ $i destroy
+ foo destroy
+ res?
+} Ducking
+
+# -------------------------------------------------------------------------
+
+test interp-4.0 {wrong#args} {
+ catch {interp::snitDictLink} msg
+ set msg
+} [tcltest::wrongNumArgs interp::snitDictLink {path methoddict} 0]
+
+test interp-4.1 {wrong#args} {
+ catch {interp::snitDictLink a} msg
+ set msg
+} [tcltest::wrongNumArgs interp::snitDictLink {path methoddict} 1]
+
+test interp-4.2 {wrong#args} {
+ catch {interp::snitDictLink a b c} msg
+ set msg
+} [tcltest::tooManyArgs interp::snitDictLink {path methoddict}]
+
+test interp-4.3 {create, test redirection} {
+ res!
+ snit::type foo {
+ variable i
+ constructor {} {
+ set i [interp::createEmpty]
+ interp::snitDictLink $i {
+ Wail {The wailer}
+ Quack {The duck}
+ }
+ }
+ method The {what} {
+ res+ $what
+ }
+ method ho {sound} {$i eval $sound}
+ }
+ set i [foo %AUTO%]
+ $i ho Quack
+ $i ho Wail
+ $i destroy
+ foo destroy
+ res?
+} {duck wailer}
+
+# -------------------------------------------------------------------------
+
+testsuiteCleanup
+return
diff --git a/tcllib/modules/interp/pkgIndex.tcl b/tcllib/modules/interp/pkgIndex.tcl
new file mode 100644
index 0000000..072c3b1
--- /dev/null
+++ b/tcllib/modules/interp/pkgIndex.tcl
@@ -0,0 +1,4 @@
+if {![package vsatisfies [package provide Tcl] 8.3]} return
+package ifneeded interp 0.1.2 [list source [file join $dir interp.tcl]]
+package ifneeded interp::delegate::proc 0.2 [list source [file join $dir deleg_proc.tcl]]
+package ifneeded interp::delegate::method 0.2 [list source [file join $dir deleg_method.tcl]]
diff --git a/tcllib/modules/interp/tcllib_interp.man b/tcllib/modules/interp/tcllib_interp.man
new file mode 100644
index 0000000..87978f2
--- /dev/null
+++ b/tcllib/modules/interp/tcllib_interp.man
@@ -0,0 +1,74 @@
+[comment {-*- tcl -*- doctools manpage}]
+[manpage_begin interp n 0.1.2]
+[keywords alias]
+[keywords {empty interpreter}]
+[keywords interpreter]
+[keywords method]
+[keywords snit]
+[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}]
+[moddesc {Interpreter utilities}]
+[titledesc {Interp creation and aliasing}]
+[category {Programming tools}]
+[require Tcl 8.3]
+[require interp [opt 0.1.2]]
+[description]
+[para]
+
+This package provides a number of commands for the convenient creation
+of Tcl interpreters for highly restricted execution.
+
+[section API]
+[list_begin definitions]
+
+[call [cmd ::interp::createEmpty] [opt [arg path]]]
+
+This commands creates an empty Tcl interpreter and returns it
+name. Empty means that the new interpreter has neither namespaces, nor
+any commands. It is useful only for the creation of aliases.
+
+[para]
+
+If a [arg path] is specified then it is taken as the name of the new
+interpreter.
+
+[call [cmd ::interp::snitLink] [arg path] [arg methodlist]]
+
+This command assumes that it was called from within a method of a snit
+object, and that the command [cmd mymethod] is available.
+
+[para]
+
+It extends the interpreter specified by [arg path] with aliases for
+all methods found in the [arg methodlist], with the alias directing
+execution to the same-named method of the snit object invoking this
+command.
+
+Each element of [arg methodlist] is actually interpreted as a command
+prefix, with the first word of each prefix the name of the method to
+link to.
+
+[para]
+
+The result of the command is the empty string.
+
+[call [cmd ::interp::snitDictLink] [arg path] [arg methoddict]]
+
+This command behaves like [cmd ::interp::snitLink], except that it
+takes a dictionary mapping from commands to methods as its input, and
+not a list of methods.
+
+Like for [cmd ::interp::snitLink] the method references are actually
+command prefixes.
+
+This command allows the creation of more complex command-method
+mappings than [cmd ::interp::snitLink].
+
+[para]
+
+The result of the command is the empty string.
+
+[list_end]
+
+[vset CATEGORY interp]
+[include ../doctools2base/include/feedback.inc]
+[manpage_end]