From: David Vázquez Date: Thu, 17 Oct 2013 20:13:01 +0000 (-0700) Subject: Merge pull request #147 from Ferada/defpackage X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=08f50f40ca51ee15efe8c2a4be1445b5ba6d4a86;hp=5b6da2fb81d3a9e059b6d92f091558536745cda7;p=jscl.git Merge pull request #147 from Ferada/defpackage DEFPACKAGE including USE and some more functions. --- diff --git a/src/list.lisp b/src/list.lisp index b974cd0..9cb8e45 100644 --- a/src/list.lisp +++ b/src/list.lisp @@ -39,6 +39,12 @@ (defun cdr (x) (cdr x)) +(defun rplaca (cons x) + (rplaca cons x)) + +(defun rplacd (cons x) + (rplacd cons x)) + (defun first (x) (car x)) (defun second (x) (cadr x)) (defun third (x) (caddr x)) @@ -354,3 +360,51 @@ (when (member (funcall key x) list2 :test test :key key) (push x new-list))) new-list)) + +(defun get-properties (plist indicator-list) + (do* ((plist plist (cddr plist)) + (cdr (cdr plist) (cdr plist)) + (car (car plist) (car plist))) + ((null plist) (values nil nil nil)) + (when (null cdr) + (error "malformed property list ~S" plist)) + (let ((found (member car indicator-list :test #'eq))) + (when found + (return (values car (cadr plist) plist)))))) + +(defun getf (plist indicator &optional default) + (do* ((plist plist (cddr plist)) + (cdr (cdr plist) (cdr plist)) + (car (car plist) (car plist))) + ((null plist) default) + (when (null cdr) + (error "malformed property list ~S" plist)) + (when (eq indicator car) + (return (cadr plist))))) + +(defun %putf (plist indicator new-value) + (do* ((tail plist (cddr tail)) + (cdr (cdr tail) (cdr tail)) + (car (car tail) (car tail))) + ((null tail) (list* indicator new-value plist)) + (when (null cdr) + (error "malformed property list ~S" tail)) + (when (eq indicator car) + ;; TODO: should be cadr, needs a defsetf for that + (setf (car (cdr tail)) new-value) + (return tail)))) + +(define-setf-expander getf (plist indicator &optional default) + (multiple-value-bind (dummies vals newval setter getter) + (get-setf-expansion plist) + (let ((store (gensym)) + (indicator-sym (gensym)) + (default-sym (and default (gensym)))) + (values `(,indicator-sym ,@(and default `(,default-sym)) ,@dummies) + `(,indicator ,@(and default `(,default)) ,@vals) + `(,store) + `(let ((,(car newval) (%putf ,getter ,indicator-sym ,store)) + ,@(cdr newval)) + ,setter + ,store) + `(getf ,getter ,indicator-sym ,@(and default `(,default-sym))))))) diff --git a/src/package.lisp b/src/package.lisp index 3ee5105..7449f84 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -20,9 +20,8 @@ (defun list-all-packages () (copy-list *package-list*)) -(defun make-package (name &key use) - (let ((package (new)) - (use (mapcar #'find-package-or-fail use))) +(defun %make-package (name use) + (let ((package (new))) (setf (oget package "packageName") name) (setf (oget package "symbols") (new)) (setf (oget package "exports") (new)) @@ -30,6 +29,17 @@ (push package *package-list*) package)) +(defun resolve-package-list (packages) + (let (result) + (dolist (package (mapcar #'find-package-or-fail packages)) + (pushnew package result :test #'eq)) + (reverse result))) + +(defun make-package (name &key use) + (%make-package + (string name) + (resolve-package-list use))) + (defun packagep (x) (and (objectp x) (in "symbols" x))) @@ -79,6 +89,26 @@ `(eval-when (:compile-toplevel :load-toplevel :execute) (setq *package* (find-package-or-fail ',string-designator)))) +(defmacro defpackage (package &rest options) + (let (use) + (dolist (option options) + (ecase (car option) + (:use + (setf use (append use (cdr option)))))) + `(eval-when (:compile-toplevel :load-toplevel :execute) + (%defpackage ',(string package) ',use)))) + +(defun redefine-package (package use) + (setf (oget package "use") use) + package) + +(defun %defpackage (name use) + (let ((package (find-package name)) + (use (resolve-package-list use))) + (if package + (redefine-package package use) + (%make-package name use)))) + ;; This function is used internally to initialize the CL package ;; with the symbols built during bootstrap. (defun %intern-symbol (symbol) diff --git a/tests/list.lisp b/tests/list.lisp index ffc672d..b59f662 100644 --- a/tests/list.lisp +++ b/tests/list.lisp @@ -217,3 +217,14 @@ (test (let (foo) (mapc (lambda (x y z) (push (+ x y z) foo)) '(1 2) '(3) '(4 5 6)) (equal foo '(8)))) + +;; GETF +(test (eq (getf '(a b c d) 'a) 'b)) +(test (null (getf '(a b c d) 'e))) +(test (equal (let ((x (list 'a 1))) (setf (getf x 'a) 3) x) '(a 3))) +(test (equal (let ((x (list 'a 1))) (incf (getf x 'a)) x) '(a 2))) + +;; GET-PROPERTIES +(test (equal (multiple-value-list (get-properties '(a b c d) '(b d e))) '(NIL NIL NIL))) +(test (equal (multiple-value-list (get-properties '(a b c d) '(b a c))) '(a b (a b c d)))) +(test (equal (multiple-value-list (get-properties '(a b c d) '(b c a))) '(a b (a b c d))))