ck-extra.scm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. [(c-and-raise stack
  51. (quote function-name)
  52. (quote (list #|nothing|#)))
  53. (ck stack (quote #t))]))
  54. ;; Usage example:
  55. #;(ck ()
  56. (c-and-raise
  57. 'unknown-origin
  58. '(list (= 1 1) (= 2 3))))
  59. ;; (define result 3)
  60. ;; (ck ()
  61. ;; (c-and-raise
  62. ;; 'unknown-origin
  63. ;; (c-map '(c-replace-placeholder 'result)
  64. ;; '(list (= 1 <?>) (= 2 3)))))
  65. ;; (define result 3)
  66. ;; (ck ()
  67. ;; (c-and-raise
  68. ;; 'my-function-name
  69. ;; (c-map '(c-replace-placeholder 'result)
  70. ;; '(list (= 1 <?>) (= 2 3)))))
  71. (define-syntax c-replace-placeholder
  72. (syntax-rules (quote <?>)
  73. ;; Replace the placeholder, if it is the expression.
  74. [(c-replace-placeholder stack 'result (quote <?>))
  75. (ck stack (quote result))]
  76. ;; Only one expression remaining.
  77. [(c-replace-placeholder stack 'result '(expr))
  78. (ck stack
  79. (c-cons
  80. (c-replace-placeholder 'result 'expr)
  81. '()))]
  82. ;; There are multiple expressions left. (Case of single
  83. ;; expression is matched earlier.)
  84. [(c-replace-placeholder stack 'result '(expr expr* ...))
  85. (ck stack
  86. (c-cons
  87. (c-replace-placeholder 'result 'expr)
  88. (c-replace-placeholder 'result '(expr* ...))))]
  89. ;; Take care of vectors.
  90. [(c-replace-placeholder stack 'result (quote #(expr* ...)))
  91. (ck stack
  92. (c-list->vector
  93. (c-replace-placeholder 'result
  94. (c-vector->list
  95. '#(expr* ...)))))]
  96. ;; Or a non-compound expression, which is not the
  97. ;; placeholder.
  98. [(c-replace-placeholder stack 'result 'expr)
  99. (ck stack 'expr)]
  100. ))
  101. ;; Example usage:
  102. ;; (ck () (c-replace-placeholder 'result ''(1 2 <>)))
  103. ;; (ck ()
  104. ;; (c-replace-placeholder 'result
  105. ;; '(apply + (list 1 2 <?>))))
  106. ;; (ck ()
  107. ;; (c-map '(c-replace-placeholder 'result)
  108. ;; '((= 1 <?>))))
  109. (define-syntax c-list->vector
  110. (syntax-rules (quote list)
  111. [(_ stack (quote '(expr* ...)))
  112. ;; Replace with call to (vector ...), because #()
  113. ;; syntax does not evaluate the things inside
  114. ;; parentheses. If there was a reference to a
  115. ;; variable in there, it would be seen as a symbol
  116. ;; only. The actual value would not be in there.
  117. (ck stack (quote (vector expr* ...)))]
  118. [(_ stack (quote (list expr* ...)))
  119. (ck stack (quote (vector expr* ...)))]
  120. ;; Fallback for better error message.
  121. [(_ stack (quote other* ...))
  122. (syntax-error
  123. "could not recognize list in expression"
  124. other* ...)]))
  125. ;; Example usage:
  126. ;; (ck ()
  127. ;; (c-list->vector ''(a b c)))
  128. ;; (ck ()
  129. ;; (c-list->vector '(list 1 2 3)))
  130. (define-syntax c-vector->list
  131. (syntax-rules (quote list)
  132. [(_ stack (quote #(expr* ...)))
  133. (ck stack (quote '(expr* ...)))]
  134. [(_ stack (quote (vector expr* ...)))
  135. (ck stack (quote (list expr* ...)))]
  136. ;; Fallback for better error message.
  137. [(_ stack (quote other* ...))
  138. (syntax-error
  139. "could not recognize vector in expression"
  140. other* ...)])))