PageRenderTime 57ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/ctco/expr/fn.clj

http://github.com/cjfrisz/clojure-tco
Clojure | 65 lines | 31 code | 5 blank | 29 comment | 0 complexity | ded1ed1565bcb2cec7ea60a43e816373 MD5 | raw file
  1. ;;----------------------------------------------------------------------
  2. ;; File fn.clj
  3. ;; Written by Chris Frisz
  4. ;;
  5. ;; Created 30 Mar 2012
  6. ;; Last modified 26 Apr 2012
  7. ;;
  8. ;; Defines the Fn record type for representing 'fn' expressions in the
  9. ;; Clojure TCO compiler.
  10. ;;
  11. ;; It implements the following protocols:
  12. ;;
  13. ;; PAbstractK:
  14. ;; Recursively applies abstract-k to the body expression,
  15. ;; returning a new Fn record.
  16. ;;
  17. ;; PEmit:
  18. ;; Emits (recursively) the syntax for the expression as
  19. ;; `(fn ~fml* body).
  20. ;;
  21. ;; PCpsTriv:
  22. ;; Applies the CPS transformation to the body expression
  23. ;; and extends the formal parameters list with an
  24. ;; additional 'k' argument for the continuation.
  25. ;;
  26. ;; PThunkify:
  27. ;; Simply calls thunkify on the body and returns a new Fn
  28. ;; record with that body value.
  29. ;;----------------------------------------------------------------------
  30. (ns ctco.expr.fn
  31. (:require [ctco.expr
  32. cont thunk]
  33. [ctco.protocol :as proto]
  34. [ctco.util :as util])
  35. (:import [ctco.expr.cont
  36. Cont AppCont]
  37. [ctco.expr.thunk
  38. Thunk]))
  39. (defrecord Fn [fml* body]
  40. proto/PAbstractK
  41. (abstract-k [this app-k]
  42. (let [BODY (proto/abstract-k (:body this) app-k)]
  43. (Fn. (:fml* this) BODY)))
  44. proto/PEmit
  45. (emit [this]
  46. (let [fml* (vec (map proto/emit (:fml* this)))
  47. body (proto/emit (:body this))]
  48. `(fn ~fml* ~body)))
  49. proto/PCpsTriv
  50. (cps-triv [this]
  51. (let [k (util/new-var 'k)]
  52. (let [FML* (conj (:fml* this) k)
  53. BODY (condp extends? (type (:body this))
  54. proto/PCpsTriv (AppCont. k (proto/cps-triv body))
  55. proto/PCpsSrs (proto/cps-srs body k))]
  56. (Fn. FML* BODY))))
  57. proto/PThunkify
  58. (thunkify [this]
  59. (let [BODY (proto/thunkify (:body this))]
  60. (Fn. (:fml* this) BODY))))