/lib/gaa_lambda.tcl

http://github.com/maxcom/tklor · TCL · 96 lines · 67 code · 12 blank · 17 comment · 11 complexity · db18e7f2dd4fefdd0831969666ac4974 MD5 · raw file

  1. ############################################################################
  2. # Copyright (C) 2008 Alexander Galanin <gaa.nnov@mail.ru> #
  3. # #
  4. # This program is free software: you can redistribute it and/or modify #
  5. # it under the terms of the GNU Lesser General Public License as #
  6. # published by the Free Software Foundation, either version 3 of the #
  7. # License, or (at your option) any later version. #
  8. # #
  9. # This program is distributed in the hope that it will be useful, #
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of #
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
  12. # GNU General Public License for more details. #
  13. # #
  14. # You should have received a copy of the GNU Lesser GNU General Public #
  15. # License along with this program. #
  16. # If not, see <http://www.gnu.org/licenses/>. #
  17. ############################################################################
  18. package provide gaa_lambda 1.2
  19. package require Tcl 8.4
  20. namespace eval lambda {
  21. namespace export \
  22. lambda \
  23. deflambda \
  24. closure \
  25. defclosure
  26. proc lambdaLowlevel {paramsVar scriptVar argsVar} {
  27. set params [ uplevel [ list set $paramsVar ] ]
  28. set script [ uplevel [ list set $scriptVar ] ]
  29. set args [ uplevel [ list set $argsVar ] ]
  30. uplevel [ list unset $paramsVar $scriptVar $argsVar ]
  31. for {set i 0} {$i < [ llength $params ]} {incr i} {
  32. if { [ lindex $params $i ] != "args" } {
  33. uplevel [ list set [ lindex $params $i ] [ lindex $args $i ] ]
  34. } else {
  35. uplevel [ list set [ lindex $params $i ] [ lrange $args $i end ] ]
  36. }
  37. }
  38. uplevel [ list eval $script ]
  39. }
  40. proc lambdaProc {params script args} {
  41. if {( [ lindex $params end ] == "args" && [ llength $params ] > [ llength $args ] ) || \
  42. ( [ lindex $params end ] != "args" && [ llength $params ] != [ llength $args ] )} {
  43. error "Arguments count mismatch: expected $params, but $args passed."
  44. }
  45. ::lambda::lambdaLowlevel params script args
  46. }
  47. proc lambda {params script args} {
  48. return [ concat [ list [ namespace current ]::lambdaProc $params $script ] $args ]
  49. }
  50. proc deflambda {id params script args} {
  51. uplevel [ list set $id [ concat [ list [ namespace current ]::lambdaProc $params $script ] $args ] ]
  52. }
  53. proc closure {locals params script} {
  54. set localParams ""
  55. set localArgs ""
  56. foreach p $locals {
  57. lappend localParams $p
  58. lappend localArgs [ uplevel [ list set $p ] ]
  59. }
  60. return [ concat \
  61. [ list [ namespace current ]::lambdaProc \
  62. [ concat $localParams $params ] \
  63. $script \
  64. ] \
  65. $localArgs \
  66. ]
  67. }
  68. proc defclosure {id locals params script args} {
  69. set localParams ""
  70. set localArgs ""
  71. foreach p $locals {
  72. lappend localParams $p
  73. lappend localArgs [ uplevel [ list set $p ] ]
  74. }
  75. uplevel [ concat \
  76. [ list [ namespace current ]::deflambda \
  77. $id \
  78. [ concat $localParams $params ] \
  79. $script \
  80. ] \
  81. $localArgs \
  82. ]
  83. }
  84. }