forked from franzinc/clim2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefpackage.lisp
162 lines (143 loc) · 6.3 KB
/
defpackage.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: (CLIM-LISP :USE LISP :COLON-MODE :EXTERNAL); Base: 10; Lowercase: Yes -*-
;; See the file LICENSE for the full license governing this code.
;;
;;;"Copyright (c) 1989, 1990, 1991 by International Lisp Associates. All Rights Reserved."
#-aclpc
(warn "utils/defpackage should not be used anymore")
#+aclpc
(progn
#+(or Allegro Lucid) (defpackage :clim-lisp)
#-(or Allegro Lucid)
(eval-when (compile load eval)
(unless (find-package :clim-lisp)
(make-package "CLIM-LISP" :use '("COMMON-LISP"))))
(in-package :clim-lisp)
#+Allegro
(import 'common-lisp::defpackage (find-package :clim-lisp))
#+Lucid
(import 'lucid-common-lisp::defpackage (find-package :clim-lisp))
#+Genera
(shadowing-import 'future-common-lisp:defpackage (find-package :clim-lisp))
#-(or Allegro Lucid Genera)
(progn
(defmacro defpackage (name &body options)
(flet ((get-option (option-name &optional default)
(dolist (option options default)
(if (atom option)
(when (eq option option-name)
(warn "Option ~S standing along ignored." option-name))
(when (eq (car option) option-name) (return (cdr option))))))
(stringify (option-arg) (mapcar #'string option-arg))
(map-options (option-name function)
(let ((result nil))
(dolist (option options (nreverse result))
(if (atom option)
(when (eq option option-name)
(warn "Option ~S standing alone ignored." option-name))
(when (eq (car option) option-name)
(push (funcall function (cdr option)) result)))))))
(let ((package-name (string name))
(use-list (get-option :use '(:common-lisp)))
(nicknames (get-option :nicknames))
#+Genera (prefix-name (car (get-option :prefix-name)))
(size (get-option :size))
(package-var '#:package))
(let ((bad-option
(find-if-not #'(lambda (opt)
(lisp:member opt '(:use :nicknames :size #+Genera :prefix-name
:shadow :shadowing-import-from
:import-from :internal :export)))
options
:key #'first)))
(when bad-option
(warn "Unknown ~S option: ~S" 'defpackage (first bad-option))))
`(eval-when (compile load eval)
(let ((,package-var (make-package-aux
',package-name :use nil
,@(when nicknames `(:nicknames ',(mapcar #'string nicknames)))
#+Genera
,@(when prefix-name `(:prefix-name ',prefix-name))
,@(when size `(:size ',(car size))))))
,@(map-options
:shadow
#'(lambda (option-arg) `(shadow ',option-arg ,package-var)))
,@(map-options
:shadowing-import-from
#'(lambda (option-arg)
`(shadowing-import-from ',(string (car option-arg))
',(stringify (cdr option-arg)) ,package-var)))
,@(map-options
:import-from
#'(lambda (option-arg)
`(import-from ',(string (car option-arg)) ',(stringify (cdr option-arg))
,package-var)))
,@(map-options
:internal
#'(lambda (option-arg)
`(progn ,@(mapcar #'(lambda (x) `(intern ',(string x) ,package-var))
option-arg))))
,@(when use-list `((use-package ',(stringify use-list) ,package-var)))
,@(map-options
:export
#'(lambda (option-arg)
`(export-1 ',option-arg ,package-var)
#+++ignore
`(progn ,@(mapcar #'(lambda (x)
`(export (list (intern ',x ,package-var))
,package-var))
(stringify option-arg)))))
,package-var)))))
(defun make-package-aux (package-name &rest args &key use nicknames #+Genera prefix-name size)
(let ((pkg (find-package package-name)))
(if pkg
(fix-up-package pkg use nicknames size #+Genera prefix-name)
(setf pkg (apply #'make-package package-name :use use args)))
pkg))
(defun fix-up-package (pkg use-list nicknames size #+Genera prefix-name)
(declare (ignore size)) ;Perhaps there is something non-standard we could do.
(unuse-package (package-use-list pkg) pkg)
(use-package use-list pkg)
(rename-package pkg (package-name pkg) nicknames) ;Remove old nicknames, if any.
#+Genera (when prefix-name (setf (si:pkg-prefix-name pkg) prefix-name))
pkg)
;;; Only Symbolics' find-package might return the package itself.
(defun find-package-1 (pkg)
(if (typep pkg 'package) pkg
(find-package pkg)))
;;; Keep proper semantics of package operations: Do it to a list, and it keeps the
;;; list-ness when passing it on to the underlying package operation. Thus, EXPORTing
;;; '(NIL), for example, will do what you expect.
(defun perform-package-operation (operation symbol-names from-package into-package)
(flet ((intern-symbol (name)
(if from-package
(intern (string name) from-package)
(string name))))
(setf symbol-names
(if (listp symbol-names)
(mapcar #'intern-symbol symbol-names)
(intern-symbol symbol-names))))
(funcall operation symbol-names into-package))
(defun shadowing-import-from (from-package symbol-names &optional (into-package *package*))
(let ((true-from-package (find-package-1 from-package))
(true-into-package (find-package-1 into-package)))
(when (and from-package (null true-from-package))
(error "Package ~A does not exist; cannot import symbols from it." from-package))
(when (and into-package (null true-into-package))
(error "Package ~A does not exist; cannot import symbols into it." into-package))
(perform-package-operation #'shadowing-import symbol-names
true-from-package true-into-package)))
(defun import-from (from-package symbol-names &optional (into-package *package*))
(let ((true-from-package (find-package-1 from-package))
(true-into-package (find-package-1 into-package)))
(when (and from-package (null true-from-package))
(error "Package ~A does not exist; cannot import symbols from it." from-package))
(when (and into-package (null true-into-package))
(error "Package ~A does not exist; cannot import symbols into it." into-package))
(perform-package-operation #'import symbol-names true-from-package true-into-package)))
(defun export-1 (symbol-names &optional (from-package *package*))
(let ((true-from-package (find-package-1 from-package)))
(when (and from-package (null true-from-package))
(error "Package ~A does not exist; cannot export symbols from it." from-package))
(perform-package-operation #'export symbol-names true-from-package true-from-package)))
) ;#-(or Allegro Lucid Genera)
)