Posted to tcl by aspect at Wed Oct 08 09:49:08 GMT 2014view raw

  1. ** Macros in Tcl **
  2.  
  3. The invocation [proc $name $arglist $body] creates a command procedure named $name, whose invocation (according to DDL#2) results in the following
  4.  
  5. 1.1) a local scope will be created for the local vars
  6. 1.2) some local vars (the formal arguments) will be initialized with values coming from the actual arguments;
  7. 1.3) the body will be run as a script in that local scope, returning it's last result;
  8. 1.4) the local scope will be destroyed
  9.  
  10.  
  11. The invocation [defmacro $name $arglist $body] creates a command procedure named $name, whose expansion and invocation are according to the following:
  12.  
  13. 2.1) a local scope will be created for the local vars
  14. 2.2) some local vars (the formal arguments) will be initialized with values coming from the actual arguments;
  15. 2.3) the body will be run as a script in that local scope, returning it's last result;
  16. 2.4) the local scope will be destroyed
  17. 2.5) the result of step #3 will be evaluated in the calling context as though it were passwd to [eval];
  18.  
  19. 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
  20. macro call to be re-used next time a compatible call-site is evaluated.
  21.  
  22. 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:
  23.  
  24. 3.1) evaluation of a macro body can have no observable side effects
  25. 3.2) evaluation of a macro body cannot depend on time-varying elements of the execution environment
  26.  
  27. Breaching either of these may make demons fly out your nose.
  28.  
  29.  
  30. *** Proof-of concept implementation in pure Tcl ****
  31.  
  32. ======
  33. namespace eval ::macros {}
  34.  
  35. proc defmacro {name arglist body} {
  36. proc ::macros::$name $arglist $body
  37. uplevel 1 [
  38. list interp alias {} $name {} expand-macro $name
  39. ]
  40. }
  41.  
  42. proc expand-macro {name args} {
  43. tailcall eval [::macros::$name {*}$args]
  44. }
  45.  
  46. # not-very-motivating example usage:
  47. defmacro let {varName args} {
  48. return "set [list $varName] \[expr $args\]"
  49. }
  50. let x 23*42
  51. ======
  52.  
  53.  
  54. *** Proof-of-concept implementation inside the interpreter ***
  55.  
  56. See http://sourceforge.net/p/tcl/patches/535/ - spjuth, 2008; via http://wiki.tcl.tk/11159
  57.