diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 19:39:39 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 19:39:39 (GMT) |
commit | ea28451286d3ea4a772fa174483f9a7a66bb1ab3 (patch) | |
tree | 6ee9d8a7848333a7ceeee3b13d492e40225f8b86 /tcllib/modules/interp | |
parent | b5ca09bae0d6a1edce939eea03594dd56383f2c8 (diff) | |
parent | 7c621da28f07e449ad90c387344f07a453927569 (diff) | |
download | blt-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/ChangeLog | 108 | ||||
-rw-r--r-- | tcllib/modules/interp/deleg_method.man | 49 | ||||
-rw-r--r-- | tcllib/modules/interp/deleg_method.tcl | 64 | ||||
-rw-r--r-- | tcllib/modules/interp/deleg_method.test | 192 | ||||
-rw-r--r-- | tcllib/modules/interp/deleg_proc.man | 47 | ||||
-rw-r--r-- | tcllib/modules/interp/deleg_proc.tcl | 68 | ||||
-rw-r--r-- | tcllib/modules/interp/deleg_proc.test | 153 | ||||
-rw-r--r-- | tcllib/modules/interp/interp.tcl | 87 | ||||
-rw-r--r-- | tcllib/modules/interp/interp.test | 127 | ||||
-rw-r--r-- | tcllib/modules/interp/pkgIndex.tcl | 4 | ||||
-rw-r--r-- | tcllib/modules/interp/tcllib_interp.man | 74 |
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] |