diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-11-11 08:18:35 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-11-11 08:18:35 -0800 |
commit | e3314a5609df7bc920a99766770c66bac690a873 (patch) | |
tree | c27bebfcea2398d86e67ae2724a2d4128636bcb5 | |
parent | 7843bdd7550a1cf3213a184c350b3175d8e8e562 (diff) | |
download | txr-e3314a5609df7bc920a99766770c66bac690a873.tar.gz txr-e3314a5609df7bc920a99766770c66bac690a873.tar.bz2 txr-e3314a5609df7bc920a99766770c66bac690a873.zip |
Add defpackage macro.
* lisplib.c (package_set_entries, package_instantiate): New
static functions.
(lisplib_init): Register auto-loading for new package.tl
file using new functions.
* share/txr/stdlib/package.tl: New file.
* txr.1: Documented.
-rw-r--r-- | lisplib.c | 19 | ||||
-rw-r--r-- | share/txr/stdlib/package.tl | 61 | ||||
-rw-r--r-- | txr.1 | 72 |
3 files changed, 152 insertions, 0 deletions
@@ -407,6 +407,24 @@ static val getopts_instantiate(val set_fun) return nil; } +static val package_set_entries(val dlt, val fun) +{ + val name[] = { + lit("defpackage"), + nil + }; + set_dlt_entries(dlt, name, fun); + return nil; +} + +static val package_instantiate(val set_fun) +{ + funcall1(set_fun, nil); + load(format(nil, lit("~apackage.tl"), stdlib_path, nao)); + return nil; +} + + val dlt_register(val dlt, val (*instantiate)(val), val (*set_entries)(val, val)) @@ -440,6 +458,7 @@ void lisplib_init(void) dlt_register(dl_table, build_instantiate, build_set_entries); dlt_register(dl_table, trace_instantiate, trace_set_entries); dlt_register(dl_table, getopts_instantiate, getopts_set_entries); + dlt_register(dl_table, package_instantiate, package_set_entries); } val lisplib_try_load(val sym) diff --git a/share/txr/stdlib/package.tl b/share/txr/stdlib/package.tl new file mode 100644 index 00000000..4c423145 --- /dev/null +++ b/share/txr/stdlib/package.tl @@ -0,0 +1,61 @@ +;; Copyright 2016 +;; Kaz Kylheku <kaz@kylheku.com> +;; Vancouver, Canada +;; All rights reserved. +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions are met: +;; +;; 1. Redistributions of source code must retain the above copyright notice, this +;; list of conditions and the following disclaimer. +;; +;; 2. Redistributions in binary form must reproduce the above copyright notice, +;; this list of conditions and the following disclaimer in the documentation +;; and/or other materials provided with the distribution. +;; +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +;; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +;; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(macro-time + (defun sys:name-str (kind sym-or-string) + (cond + ((symbolp sym-or-string) (symbol-name sym-or-string)) + ((stringp sym-or-string) sym-or-string) + (t (throw 'eval-error "~s: ~s isn't a valid ~a name" + 'defpackage sym-or-string kind))))) + +(defmacro defpackage (name . clauses) + (let* ((pkg (gensym "pkg-")) + (name-str (sys:name-str 'package name)) + (exp-clauses (append-each ((c clauses)) + (tree-case c + ((keyword . rest) + (caseql keyword + (:use + (if rest ^((use-package ',rest ,pkg)))) + (:use-syms + ^((each ((s ',rest)) + (use-sym s ,pkg)))) + (:local + ^((each ((n ',(mapcar (op sys:name-str 'symbol) + rest))) + (let ((s (intern n ,pkg))) + (unless (eq (symbol-package s) ,pkg) + (unuse-sym s ,pkg) + (intern n ,pkg)))))))) + (atom + (throwf 'eval-error "~s: invalid clause: ~s" + 'defpackage atom)))))) + ^(let ((,pkg (or (find-package ,name-str) + (make-package ,name-str)))) + ,*(unless (assoc :use clauses) ^((use-package "usr" ,pkg))) + ,*exp-clauses + ,pkg))) @@ -38955,6 +38955,11 @@ function creates and returns a package named where .meta name is a string. It is an error if a package by that name exists already. +Note: ordinary creation of packages for everyday program modularization +should be performed with the +.code defpackage +macro rather than by direct use of +.codn make-package . .coNP Function @ delete-package .synb @@ -39429,6 +39434,73 @@ of the .cble expression. +.coNP Macro @ defpackage +.synb +.mets (defpackage < name << clause *) +.syne +.desc +The +.code defpackage +macro provides a convenient means to create a package and establish its +properties in a single construct. It is intended for the ordinary situations +in which packages support the organization of programs into modules. + +The +.code name +argument, giving the package name, may be a symbol or a character string. +If it is a symbol, then the symbol's name is taken to be name for the +package. + +If a package called +.code name +already exists, then +.code defpackage +selects that package for further operations. Otherwise, a new, +empty package is created. + +The +.code name +may be optionally followed by one or more clauses, which are processed +in the order that they appear. Each clause is a compound form headed +by a keyword. If no +.code :use +clauses are present, then an implicit +.code "(:use \(dqusr\(dq)" +clause is inserted ahead of all other clauses. + +The supported clauses are as follows: +.RS +.meIP (:use << package-name *) +The +.code :use +clause specifies packages whose local symbols are to be interned +into the package as foreign symbols. Each +.meta package-name +may be a string or symbol naming an existing package. +The list of package names is processed as if by a call to +.codn use-package . +.meIP (:use-syms << symbol *) +The +.code :use-syms +clause specifies individual symbols to be interned in the new package. +The arguments are symbols. +.meIP (:local << symbol-name *) +The +.code :local +clause specifies the names of symbols to be interned in the new package +as local symbols. Each +.meta symbol-name +argument must be either a character string or a symbol. If it is a symbol, its +name is taken, thereby reducing the argument to a character string. +The arguments are processed in the order in which they appear. Each name is +first interned in the newly created package using the +.code intern +function. Then, if the resulting symbol is foreign to the package, it is +removed with +.code unuse-sym +and the name is interned again. +.RE + .SS* Pseudo-random Numbers .coNP Special variable @ *random-state* .desc |