demand.lisp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. (import core/base (defun defmacro error get-idx if unless setmetatable =))
  2. (import core/method (pretty defmethod))
  3. (import core/type (type list? symbol?))
  4. (import compiler (flag?))
  5. (import lua/debug debug)
  6. (import lua/string string)
  7. (defun demand-failure->string (failure)
  8. :hidden
  9. (if (get-idx failure :message)
  10. (string/format "demand not met: %s (%s).\n%s"
  11. (get-idx failure :condition)
  12. (get-idx failure :message)
  13. (get-idx failure :traceback))
  14. (string/format "demand not met: %s.\n%s"
  15. (get-idx failure :condition)
  16. (get-idx failure :traceback))))
  17. (define *demand-failure-mt* :hidden
  18. { :__tostring demand-failure->string })
  19. (defun demand-failure (message condition)
  20. "Construct a new demand-failure with the given MESSAGE and CONDITION
  21. string."
  22. :hidden
  23. ;; Whilst it may be tidier to error in this function, in order to preserve
  24. ;; the stack we error in the parent function instead.
  25. (setmetatable
  26. { :tag "demand-failure"
  27. :message message
  28. :traceback (if debug/traceback (debug/traceback "" 2) "")
  29. :condition condition }
  30. *demand-failure-mt*))
  31. (defmethod (pretty demand-failure) (failure)
  32. (demand-failure->string failure))
  33. (defun maybe-demand (condition message) :hidden
  34. (if (flag? :lax :lax-checks)
  35. `nil
  36. `(unless ,condition
  37. (error (demand-failure ,(if (= message nil) `nil message)
  38. ,(pretty condition))))))
  39. (defmacro demand (condition message)
  40. "Demand that particular CONDITION is upheld. If provided, MESSAGE will
  41. be included in the thrown error.
  42. Note that MESSAGE is only evaluated if CONDITION is not met."
  43. (maybe-demand condition message))
  44. (defmacro desire (condition message)
  45. "Demand that particular CONDITION is upheld if debug assertions are
  46. on (`-fstrict-checks`). If provided, MESSAGE will be included in the
  47. thrown error.
  48. Note that MESSAGE is only evaluated if CONDITION is not met. Neither
  49. will be evaluated if debug assertions are disabled."
  50. (if (flag? :strict :strict-checks)
  51. (maybe-demand condition message)
  52. `nil))
  53. (defmacro assert-type! (arg ty)
  54. "Assert that the argument ARG has type TY, as reported by the function
  55. [[type]]."
  56. :deprecated "Use [[desire]] or [[demand]] instead."
  57. `(demand (= (type ,arg) ,(get-idx ty :contents))))