Posted to tcl by aspect at Wed Oct 08 09:49:08 GMT 2014view pretty
** Macros in Tcl ** The invocation [proc $name $arglist $body] creates a command procedure named $name, whose invocation (according to DDL#2) results in the following 1.1) a local scope will be created for the local vars 1.2) some local vars (the formal arguments) will be initialized with values coming from the actual arguments; 1.3) the body will be run as a script in that local scope, returning it's last result; 1.4) the local scope will be destroyed The invocation [defmacro $name $arglist $body] creates a command procedure named $name, whose expansion and invocation are according to the following: 2.1) a local scope will be created for the local vars 2.2) some local vars (the formal arguments) will be initialized with values coming from the actual arguments; 2.3) the body will be run as a script in that local scope, returning it's last result; 2.4) the local scope will be destroyed 2.5) the result of step #3 will be evaluated in the calling context as though it were passwd to [eval]; A macro differs from a proc in that steps 1-4 may occur *at any time*. The interpreter is free to pre-evaluate macros, or to cache the results of a macro call to be re-used next time a compatible call-site is evaluated. This places limits on the sort of things that can be done in a macro body with defined results. Those limits can be summarised as: 3.1) evaluation of a macro body can have no observable side effects 3.2) evaluation of a macro body cannot depend on time-varying elements of the execution environment Breaching either of these may make demons fly out your nose. *** Proof-of concept implementation in pure Tcl **** ====== namespace eval ::macros {} proc defmacro {name arglist body} { proc ::macros::$name $arglist $body uplevel 1 [ list interp alias {} $name {} expand-macro $name ] } proc expand-macro {name args} { tailcall eval [::macros::$name {*}$args] } # not-very-motivating example usage: defmacro let {varName args} { return "set [list $varName] \[expr $args\]" } let x 23*42 ====== *** Proof-of-concept implementation inside the interpreter *** See http://sourceforge.net/p/tcl/patches/535/ - spjuth, 2008; via http://wiki.tcl.tk/11159