ck-base.scm 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. ;;; It turns out, that for recursive expansion of macros it
  2. ;;; becomes very difficult to write the macro
  3. ;;; correctly. However, CK macros promise a solution, by
  4. ;;; implementing a way of expanding macros in the same order
  5. ;;; as function application works.
  6. ;;; Code for the CK macro taken from:
  7. ;;; https://okmij.org/ftp/Scheme/macros.html#ck-macros.
  8. ;;; Some comments added by me <zelphirkaltstahl@posteo.de>.
  9. ;;; Some renaming for readability by me <zelphirkaltstahl@posteo.de>.
  10. ;;; Some formatting by me <zelphirkaltstahl@posteo.de>.
  11. (library (ck-base)
  12. (export ck
  13. c-cons
  14. c-map
  15. c-apply
  16. c-quote
  17. c-unquote)
  18. (import (except (rnrs base) let-values)
  19. (only (guile)
  20. lambda* λ))
  21. ;; TODO: Explain this thing and why it works :D
  22. (define-syntax ck
  23. (syntax-rules (quote)
  24. ;; This is a base case, which unquotes quoted
  25. ;; expressions, so that they are evaluated at runtime,
  26. ;; instead of remaining quoted.
  27. [(ck () 'v) v] ; yield the value on empty stack
  28. [(ck (((op ...) ea ...) . s) 'v) ; re-focus on the other argument, ea
  29. (ck s "arg" (op ... 'v) ea ...)]
  30. [(ck s "arg" (op va ...)) ; all arguments are evaluated,
  31. (op s va ...)] ; do the redex
  32. [(ck s "arg" (op ...) 'v ea1 ...) ; optimization when the first ea
  33. (ck s "arg" (op ... 'v) ea1 ...)] ; was already a value
  34. [(ck s "arg" (op ...) ea ea1 ...) ; focus on ea, to evaluate it
  35. (ck (((op ...) ea1 ...) . s) ea)]
  36. [(ck s (op ea ...)) ; Focus: handle an application;
  37. (ck s "arg" (op) ea ...)] ; check if args are values
  38. ))
  39. (define-syntax c-cons
  40. (syntax-rules (quote)
  41. ;; As mentioned in the explanation on
  42. ;; https://okmij.org/ftp/Scheme/macros.html#ck-macros:
  43. ;; All things except the stack are quoted. c-cons
  44. ;; expects 2 values, head and tail.
  45. ;; In contrast to the normal pattern matching in
  46. ;; macros, the parts of a pattern need to be
  47. ;; quoted. This is probably due to CK macros building
  48. ;; yet another layer on top of normal macros, managing
  49. ;; things in a stack and having to avoid things
  50. ;; getting evaluated (or expanded in case of other,
  51. ;; possibly non-CK macros) too early.
  52. ;; For example, macro expansion would evaluate a
  53. ;; lambda too early, if it appeared without being
  54. ;; quoted.
  55. ;; This however, does not stop us from using pattern
  56. ;; matching on those quoted values! We can still write
  57. ;; something like the following:
  58. ;; (c-mymacro stack '(bla blub) 'other)
  59. ;; And then use the parts in the resulting expression
  60. ;; as we want, but again quote the resulting
  61. ;; expression.
  62. [(c-cons stack 'head 'tail)
  63. ;; Build up a pair. Always pass the stack along to
  64. ;; the CK macro.
  65. (ck stack '(head . tail))]))
  66. ;; c-map allows to map any kind of expression to a list of
  67. ;; expressions.
  68. (define-syntax c-map
  69. (syntax-rules (quote)
  70. ;; If the applied-thing is applied to the empty list,
  71. ;; then there is no need to even look at what the
  72. ;; applied-thing consists of or to destructure it via
  73. ;; pattern matching, because anything applied to the
  74. ;; empty list, will be the empty list.
  75. [(c-map stack
  76. 'applied-thing
  77. '())
  78. ;; Simply return the empty list.
  79. (ck stack
  80. ;; Base case gives the empty list, to build a
  81. ;; proper list.
  82. '())]
  83. ;; If however there are list elements, at least a head
  84. ;; and some arbitrary tail, then it becomes necessary
  85. ;; to take the applied thing apart, so that we can put
  86. ;; the first element of the list into the expression
  87. ;; of the applied-thing, thereby applying
  88. ;; applied-thing to the first element.
  89. [(c-map stack
  90. '(applied-thing ...)
  91. '(head . tail))
  92. (ck stack
  93. ;; Build up a list using cons.
  94. (c-cons
  95. ;; Apply the applied-thing to the first element.
  96. (applied-thing ... 'head)
  97. ;; Recursively expand c-map for the tail of the
  98. ;; list of expressions.
  99. (c-map '(applied-thing ...) 'tail)))]))
  100. ;; Example usage:
  101. ;; (ck ()
  102. ;; (c-map '(c-cons '10)
  103. ;; '((1) (2))))
  104. ;; (ck ()
  105. ;; (c-map '(c-cons '+)
  106. ;; '((1) (2))))
  107. (define-syntax c-apply
  108. (syntax-rules (quote)
  109. [(c-apply stack 'proc '(expr* ...))
  110. (ck stack '(proc expr* ...))]))
  111. ;; Example usage:
  112. ;; (ck ()
  113. ;; (c-apply '+
  114. ;; (c-map '(c-cons '+)
  115. ;; '((1) (2)))))
  116. ;; To quote things, we need to simply wrap with another
  117. ;; quote. This makes sense, because in the base case of
  118. ;; the CK-macro 1 quote wrapping is removed:
  119. ;; [(ck () 'v) v]
  120. ;; (see above).
  121. (define-syntax c-quote
  122. (syntax-rules (quote)
  123. [(c-quote s 'x)
  124. (ck s ''x)]))
  125. (define-syntax c-unquote
  126. (syntax-rules (quote)
  127. [(c-quote s (quote x))
  128. ;; Base case of the CK macro already removes one
  129. ;; layer of quoting, so we can use that.
  130. (ck s (quote x))])))
  131. ;;; When we use the CK macro above, there are a few rules to
  132. ;;; adhere to, to make it all work:
  133. ;;; 1. A macro CK style macro must always expand into a call
  134. ;;; of the `ck` macro.
  135. ;;; 2. When expanding into the `ck` macro, never forget to
  136. ;;; pass the stack.
  137. ;;; 3. All values after the stack must be quoted, except
  138. ;;; when they are CK style macros themselves.
  139. ;;; 4. When a CK style macro expands into other CK style
  140. ;;; macros, their arguments still need to be quoted.
  141. ;;; 5. To start the expansion process, call a macro with the
  142. ;;; form (ck () macro-call).
  143. ;;; 6. The `ck` macro will always add the stack as an
  144. ;;; "argument", when expanding into a CK style macro. This
  145. ;;; means one must always match the stack, even though the
  146. ;;; call to a macro does not contain the stack.