macros.lisp 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. (define-condition-type &port-invalid &assertion make-port-invalid
  2. port-invalid?
  3. (expression port-invalid-expression)
  4. (return port-invalid-return))
  5. ;; (:documentation "Signals an error if the returned port is invalid.")
  6. (define-report ((condition &port-invalid) stream)
  7. (format stream "Port returned by the expression ~s (~s) is not valid."
  8. (port-invalid-expression condition)
  9. (port-invalid-return condition)))
  10. (define (%get-nil-task task)
  11. "Returns (task-self) if 'task' is nil, 'task' otherwise."
  12. (if (null? task)
  13. #'(task-self)
  14. task))
  15. (define (with-port-generic destroy port-name creation task body)
  16. "Generates code for port using and releasing."
  17. #`(let ((#,port-name #,creation))
  18. (cond
  19. ((port-valid-p #,port-name)
  20. (with-cleanup #,(destroy port-name (%get-nil-task task))
  21. #,@body))
  22. (#t (raise (make-port-invalid '#,creation #,port-name))))))
  23. (define-syntax with-port-deallocate
  24. (lambda (s)
  25. "Uses a port and then port-deallocate's"
  26. (syntax-case s ()
  27. ((_ port-name creation #:body body task)
  28. (with-port-generic (lambda (port task)
  29. #`(port-deallocate! #,port #,task))
  30. #'port-name #'creation #'task #'body))
  31. ((_ port-name creation #:body body)
  32. #'(with-port-deallocate port-name creation #nil #:body body)))))
  33. (define-syntax with-port-destroy
  34. (lambda (s)
  35. "Uses a port and then port-destroy's"
  36. (syntax-case s ()
  37. ((_ port-name creation task #:body body)
  38. (with-port-generic (lambda (port task)
  39. #`(port-destroy #,port #,task))
  40. #'port-name #'creation #'task #'body))
  41. ((_ port-name creation #:body body)
  42. #'(with-port-destroy port-name creation body #nil)))))
  43. (define (%generate-release-list port task ls)
  44. "Generate code for port and port rights releasing based on the 'ls'
  45. list syntax."
  46. (define (generate-release right)
  47. (syntax-case right ()
  48. ((#:deallocate) #`(port-deallocate! #,port #,task))
  49. (_ #`(port-mod-refs #,port #,right -1 #,task))))
  50. (syntax-map generate-release (syntax-cadr ls)))
  51. (define* (with-port port-name creation #:optional (task #nil)
  52. (release-list #nil) #:key body)
  53. "Generic with-port, uses a port initialized with 'creation'
  54. and then releases rights.
  55. release-list can have #:deallocate or any port right specified to port-mod-rights."
  56. (with-port-generic (lambda (port task)
  57. #`(progn #,@(%generate-release-list port task release-list)))
  58. port-name creation task body))