Thu Mar 8 05:15:58 UTC 2012 pix@kepibu.org * Rename notes.org to README.org Mon Jul 20 18:34:17 UTC 2009 pix@kepibu.org * see other links, and add reference to cl-syntax-sugar Mon Jul 20 07:07:16 UTC 2009 pix@kepibu.org * Some org-mode syntaxisms Mon Jul 20 06:58:45 UTC 2009 pix@kepibu.org * Update bug list to include reader bug Mon Jul 20 01:31:17 UTC 2009 pix@kepibu.org tagged VERSION 0.1.3 Mon Jul 20 01:31:10 UTC 2009 pix@kepibu.org * Bump version Mon Jul 20 01:14:10 UTC 2009 pix@kepibu.org * Improved feature readers It turns out #+/#- also need to do their thing under *read-suppress*, rather than simply skipping two forms. E.g., '(#+(or) #+(not a b) a b c) => '(c) '(#+(or) #+(and) a b c) => '(b c) (Not that such constructions are practically portable anyway, but meh.) Regardless, this fixes that as best I can. Unfortunately, it also forces the normal package problems within feature expressions: #+(or) #+(notapackage:foo) 'a => PACKAGE-ERROR #+(or) #+(cl:notexported) 'a => PACKAGE-ERROR This is, so far as I can tell, portably unavoidable. However, some (all?) implementations /already/ have this problem, so at least it's nothing new. Mon Jul 20 01:09:25 UTC 2009 pix@kepibu.org * Better reporting of undefined-feature-tests. Sun Jul 19 13:58:44 UTC 2009 pix@kepibu.org tagged VERSION 0.1.2 Sun Jul 19 13:58:33 UTC 2009 pix@kepibu.org * Bump version Sun Jul 19 13:58:20 UTC 2009 pix@kepibu.org * Use consp to avoid treating nil as a list Sun Jul 19 12:31:43 UTC 2009 pix@kepibu.org tagged VERSION 0.1.1 Sun Jul 19 12:28:28 UTC 2009 pix@kepibu.org * Take *read-suppress* into account Sun Jul 19 12:27:37 UTC 2009 pix@kepibu.org * Minor changes to the notes file Fri Jul 17 05:24:52 UTC 2009 pix@kepibu.org * Initial checkin --- old-portaCL/control-flow.lisp 1970-01-01 00:00:00.000000000 +0000 +++ new-portaCL/control-flow.lisp 2013-08-05 22:27:56.000000000 +0000 @@ -0,0 +1,89 @@ +(in-package #:portaCL) + +(defmacro feature-cond (&body clauses) + "Some things are best shown by example. Suppose you have: + #+clisp (do-clisp-thing-1) + #+clisp (do-clisp-thing-2) + #+sbcl (do-sbcl-thing) + #-(or clisp sbcl) (error \"not implemented\") +Using feature-cond, that would be: + (feature-cond + (:clisp (do-clisp-thing-1) + (do-clisp-thing-2)) + (:sbcl (do-sbcl-thing)) + (t (error \"not implemented\"))) + +Accordingly, putting cl:t into *features* is not recommended. + +In general, this probably won't be very useful: read-time conditionals are +often used to read symbols from packages which may not exist across +implementations. And, of course, because this is a macro, it cannot appear +in places where it won't be macroexpanded (e.g., the conditions of case). + +By the time you're in a position where this is actually useful, + #-(or a b c) (otherwise-clause) +doesn't seem so bad. At least it'll look the same as your other feature +conditionals! + +Note also that this does NOT provide a run-time check of *features*, but is +instead a macroexpansion-time check." + (let* ((last-clause (car (last clauses))) + (otherwise-clause (when (member (car last-clause) '(t otherwise) :test #'eq) + last-clause))) + (when otherwise-clause (setf clauses (butlast clauses))) + `(progn + ,@(or (loop :for (cond . body) :in clauses + :when (featurep cond) + :return body) + (cdr otherwise-clause))))) + +(defmacro feature-econd (&body clauses) + "Like feature-cond, but automatically adds a final clause issuing a +not-implemented error." + `(feature-cond ,@clauses (t (error 'not-implemented)))) + +(defmacro feature-if (feature-expression true-form &optional else-form) + `(if (featurep ,feature-expression) + ,true-form + ,else-form)) + +(defmacro feature-when (feature-expression &body body) + `(when (featurep ,feature-expression) ,@body)) + +(defmacro feature-unless (feature-expression &body body) + `(unless (featurep ,feature-expression) ,@body)) + +#+nil +(feature-cond + (:clisp (do-clisp-thing-1) + (do-clisp-thing-2)) + (:sbcl (do-sbcl-thing)) + (t (error "not implemented"))) + +#+nil +(feature-cond + ((not :clisp) (do-clisp-thing-1) + (do-clisp-thing-2)) + (:sbcl (do-sbcl-thing)) + (t (error "not implemented"))) + +#+nil +(feature-cond + ((or :sbcl :clisp) (do-clisp-thing-1) + (do-clisp-thing-2)) + (:clisp (do-sbcl-thing)) + (t (error "not implemented"))) + +#+nil +(feature-cond + ((and (not :windows) :sbcl) + (do-sbcl-thing)) + ((and (or :windows :win32) :clisp) + (do-clisp-thing-1) + (do-clisp-thing-2)) + (t (error "not implemented"))) + +#+nil +(feature-econd + (:sbcl (do-sbcl-thing)) + (:posix (do-posix-thing))) \ No newline at end of file