Skip to content
utilities.lisp 2.64 KiB
Newer Older
;;; -*- Mode: Lisp ; Base: 10 ; Syntax: ANSI-Common-Lisp -*-
;;;; Various utilities (to move to some other package...)

(in-package :philip-jose)

(exporting-definitions

;; depends on closer-mop
(defun collect-slots (object &optional (slot-list t))
  (loop with class = (class-of object)
        with slots = (if (eq slot-list t) (compute-slots class) slot-list)
        for slot in slots
        for name = (slot-definition-name slot)
        for iarg = (or (first (slot-definition-initargs slot)) name)
        nconc (when (slot-boundp object name) `(,iarg ,(slot-value object name)))))

(defun simple-print-object (object stream &key identity (slots t))
  (with-output (stream)
    (print-unreadable-object (object stream :type t :identity identity)
      (write (collect-slots object slots) :stream stream))))

(defgeneric slots-to-print (object)
  (:method ((object t))
    t))

(defclass simple-print-object-mixin (standard-object)
  ())

(defmethod print-object ((object simple-print-object-mixin) stream)
  (simple-print-object object stream :slots (slots-to-print object)))

;; depends on arnesi
(defun funkall (f &rest args)
  (etypecase f
    (function
     (apply f args)) ; fast path for functions
    (boolean
     f) ; booleans evaluate as constant functions returning self -- must be before symbols
    ((and symbol (satisfies arnesi::fdefinition/cc))
     (with-call/cc (apply (arnesi::fdefinition/cc f) args)))
    (symbol
     (apply f args))
    (arnesi::closure/cc
     (with-call/cc (apply f args)))
    (cons
     (apply #'kall f args)))) ; arnesi represents continuations as lists

;; This code should be moved to iolib-posix and exported.
;; gettime should be renamed get-monotonic-time and exported, too.
(defun get-real-time ()
  (multiple-value-bind (sec nsec)
      (et:clock-get-time et:clock-realtime)
    (+ sec (* nsec 1d-9))))

(defconstant +unix-epoch+ (encode-universal-time 0 0 0 1 1 1970 0))

(defun fsleep (delay)
  (when (plusp delay)
    (multiple-value-bind (i d) (floor delay)
      (unless (zerop i)
        ;; TODO: here insert check for overflow...
        (et::sleep i))
      (unless (zerop d)
        (et::usleep (floor (* d 1000000))))))
  nil)

(defmacro with-error-message-handler ((&rest handler) &body body)
  (with-gensyms (err)
    `(handler-bind
         ((simple-condition (lambda (,err)
                             (,@handler
                              (apply #'format nil
                                     (simple-condition-format-control ,err)
                                     (simple-condition-format-arguments ,err)))))
          (t (lambda (,err) (,@handler (format nil "~A" ,err)))))
       ,@body)))


);exporting-definitions