ck-extra.scm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. ;; This library makes use of the CK macro base library, to
  2. ;; define more CK style macros.
  3. (library (ck-extra)
  4. (export c-and-raise
  5. c-replace-placeholder
  6. c-list->vector
  7. c-vector->list
  8. <?>)
  9. (import (except (rnrs base) let-values)
  10. (only (guile)
  11. lambda* lambda λ
  12. raise-exception)
  13. (ck-base)
  14. (exceptions))
  15. (define <?> '<?>)
  16. ;; ==========================
  17. ;; additional CK style macros
  18. ;; ==========================
  19. ;; `c-and-raise` needs to be a macro, because its
  20. ;; arguments must not be evaluated, before we can look at
  21. ;; them and build up an expression, which contains the
  22. ;; argument in its unevaluated form. We need the not yet
  23. ;; evaluated form, to have a readable and understandable
  24. ;; error message, when raising an exception. The exception
  25. ;; will contain the literal expression, which failed to
  26. ;; evaluate to a truthy value.
  27. (define-syntax c-and-raise
  28. (syntax-rules (quote)
  29. ;; `and-raise` takes a list of expressions to check as
  30. ;; an argument.
  31. [(c-and-raise stack
  32. 'function-name
  33. '(list
  34. (op args* ...)
  35. expr* ...))
  36. (ck stack
  37. '(cond
  38. ;; Check the first condition.
  39. [(op args* ...)
  40. (ck stack
  41. ;; Check the rest of the conditions.
  42. (c-and-raise (quote function-name)
  43. (quote (list expr* ...))))]
  44. [else
  45. (raise-exception
  46. (make-exception-contract-violated-compound
  47. "contract violated"
  48. (quote function-name)
  49. (quote (op args* ...))
  50. (list (quote op) args* ...)))]))]
  51. [(c-and-raise stack
  52. (quote function-name)
  53. (quote (list #|nothing|#)))
  54. (ck stack (quote #t))]))
  55. ;; Usage example:
  56. #;(ck ()
  57. (c-and-raise
  58. 'unknown-origin
  59. '(list (= 1 1) (= 2 3))))
  60. ;; (define result 3)
  61. ;; (ck ()
  62. ;; (c-and-raise
  63. ;; 'unknown-origin
  64. ;; (c-map '(c-replace-placeholder 'result)
  65. ;; '(list (= 1 <?>) (= 2 3)))))
  66. ;; (define result 3)
  67. ;; (ck ()
  68. ;; (c-and-raise
  69. ;; 'my-function-name
  70. ;; (c-map '(c-replace-placeholder 'result)
  71. ;; '(list (= 1 <?>) (= 2 3)))))
  72. (define-syntax c-replace-placeholder
  73. (syntax-rules (quote <?>)
  74. ;; Replace the placeholder, if it is the expression.
  75. [(c-replace-placeholder stack 'result (quote <?>))
  76. (ck stack (quote result))]
  77. ;; Only one expression remaining.
  78. [(c-replace-placeholder stack 'result '(expr))
  79. (ck stack
  80. (c-cons
  81. (c-replace-placeholder 'result 'expr)
  82. '()))]
  83. ;; There are multiple expressions left. (Case of single
  84. ;; expression is matched earlier.)
  85. [(c-replace-placeholder stack 'result '(expr expr* ...))
  86. (ck stack
  87. (c-cons
  88. (c-replace-placeholder 'result 'expr)
  89. (c-replace-placeholder 'result '(expr* ...))))]
  90. ;; Take care of vectors.
  91. [(c-replace-placeholder stack 'result (quote #(expr* ...)))
  92. (ck stack
  93. (c-list->vector
  94. (c-replace-placeholder 'result
  95. (c-vector->list
  96. '#(expr* ...)))))]
  97. ;; Or a non-compound expression, which is not the
  98. ;; placeholder.
  99. [(c-replace-placeholder stack 'result 'expr)
  100. (ck stack 'expr)]
  101. ))
  102. ;; Example usage:
  103. ;; (ck () (c-replace-placeholder 'result ''(1 2 <>)))
  104. ;; (ck ()
  105. ;; (c-replace-placeholder 'result
  106. ;; '(apply + (list 1 2 <?>))))
  107. ;; (ck ()
  108. ;; (c-map '(c-replace-placeholder 'result)
  109. ;; '((= 1 <?>))))
  110. (define-syntax c-list->vector
  111. (syntax-rules (quote list)
  112. [(_ stack (quote '(expr* ...)))
  113. ;; Replace with call to (vector ...), because #()
  114. ;; syntax does not evaluate the things inside
  115. ;; parentheses. If there was a reference to a
  116. ;; variable in there, it would be seen as a symbol
  117. ;; only. The actual value would not be in there.
  118. (ck stack (quote (vector expr* ...)))]
  119. [(_ stack (quote (list expr* ...)))
  120. (ck stack (quote (vector expr* ...)))]
  121. ;; Fallback for better error message.
  122. [(_ stack (quote other* ...))
  123. (syntax-error
  124. "could not recognize list in expression"
  125. other* ...)]))
  126. ;; Example usage:
  127. ;; (ck ()
  128. ;; (c-list->vector ''(a b c)))
  129. ;; (ck ()
  130. ;; (c-list->vector '(list 1 2 3)))
  131. (define-syntax c-vector->list
  132. (syntax-rules (quote list)
  133. [(_ stack (quote #(expr* ...)))
  134. (ck stack (quote '(expr* ...)))]
  135. [(_ stack (quote (vector expr* ...)))
  136. (ck stack (quote (list expr* ...)))]
  137. ;; Fallback for better error message.
  138. [(_ stack (quote other* ...))
  139. (syntax-error
  140. "could not recognize vector in expression"
  141. other* ...)])))