summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-07-12 11:29:33 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-07-12 11:29:33 -0700
commit15740ae6b6c8476cd1a9323ffd50f85a3c8ea245 (patch)
treef5eac0226a4e57e1383771c862a23efc0eddfb93
parenta6f6072761d124c60793325bc512048b0f31f5a3 (diff)
downloadtxr-15740ae6b6c8476cd1a9323ffd50f85a3c8ea245.tar.gz
txr-15740ae6b6c8476cd1a9323ffd50f85a3c8ea245.tar.bz2
txr-15740ae6b6c8476cd1a9323ffd50f85a3c8ea245.zip
Support weak semantics in symbol packages.
A package is weak if it holds weak references to symbols, meaning that if there are no references to a symbol other than its entry in a weak package, it can be removed from the package and reclaimed by the garbage collector. * eval.c (eval_init): Update registrations for make-package and sys:make-anon-package to reflect new optional argument. * lib.c (make_package_common): New argument weak. If it is true then both the hashes will have weak values. (make_package, make_anon_package): New optional argument weak. (obj_init): Add nil argument to calls to make_package. All the standard packages are regular, not weak. * lib.h (make_package, make_anon_package): Declarations updated. * txr.1: Documented.
-rw-r--r--eval.c4
-rw-r--r--lib.c23
-rw-r--r--lib.h4
-rw-r--r--txr.120
4 files changed, 35 insertions, 16 deletions
diff --git a/eval.c b/eval.c
index 6f4cc7c1..fe11c763 100644
--- a/eval.c
+++ b/eval.c
@@ -6761,8 +6761,8 @@ void eval_init(void)
reg_var(package_alist_s = intern(lit("*package-alist*"), user_package), packages);
reg_var(package_s = intern(lit("*package*"), user_package),
(opt_compat && opt_compat <= 190) ? user_package : public_package);
- reg_fun(intern(lit("make-package"), user_package), func_n1(make_package));
- reg_fun(intern(lit("make-anon-package"), system_package), func_n0(make_anon_package));
+ reg_fun(intern(lit("make-package"), user_package), func_n2o(make_package, 1));
+ reg_fun(intern(lit("make-anon-package"), system_package), func_n1o(make_anon_package, 0));
reg_fun(intern(lit("find-package"), user_package), func_n1(find_package));
reg_fun(intern(lit("delete-package"), user_package), func_n1(delete_package));
reg_fun(intern(lit("merge-delete-package"), user_package), func_n2o(merge_delete_package, 1));
diff --git a/lib.c b/lib.c
index c1be0e29..4fcd12cc 100644
--- a/lib.c
+++ b/lib.c
@@ -5910,10 +5910,11 @@ val gensym(val prefix)
return make_sym(name);
}
-static val make_package_common(val name)
+static val make_package_common(val name, val weak)
{
- val sh = make_hash(nil, nil, lit("t")); /* don't have t yet! */
- val hh = make_hash(nil, nil, lit("t"));
+ val weak_vals = default_null_arg(weak);
+ val sh = make_hash(nil, weak_vals, lit("t")); /* don't have t yet! */
+ val hh = make_hash(nil, weak_vals, lit("t"));
val obj = make_obj();
obj->pk.type = PKG;
obj->pk.name = name;
@@ -5922,7 +5923,7 @@ static val make_package_common(val name)
return obj;
}
-val make_package(val name)
+val make_package(val name, val weak)
{
if (find_package(name)) {
uw_throwf(error_s, lit("make-package: ~s exists already"), name, nao);
@@ -5932,15 +5933,15 @@ val make_package(val name)
uw_throwf(error_s, lit("make-package: package name can't be empty string"),
nao);
} else {
- val obj = make_package_common(name);
+ val obj = make_package_common(name, weak);
mpush(cons(name, obj), cur_package_alist_loc);
return obj;
}
}
-val make_anon_package(void)
+val make_anon_package(val weak)
{
- return make_package_common(lit("#<anon-package>"));
+ return make_package_common(lit("#<anon-package>"), weak);
}
val packagep(val obj)
@@ -11878,10 +11879,10 @@ static void obj_init(void)
null_list = cons(nil, nil);
hash_s = make_sym(lit("hash"));
- system_package = make_package(lit("sys"));
- keyword_package = make_package(lit("keyword"));
- user_package = make_package(lit("usr"));
- public_package = make_package(lit("pub"));
+ system_package = make_package(lit("sys"), nil);
+ keyword_package = make_package(lit("keyword"), nil);
+ user_package = make_package(lit("usr"), nil);
+ public_package = make_package(lit("pub"), nil);
rehome_sym(hash_s, user_package);
diff --git a/lib.h b/lib.h
index 330ae34f..fc4dfebd 100644
--- a/lib.h
+++ b/lib.h
@@ -928,8 +928,8 @@ val compl_span_str(val str, val set);
val break_str(val str, val set);
val make_sym(val name);
val gensym(val prefix);
-val make_package(val name);
-val make_anon_package(void);
+val make_package(val name, val weak);
+val make_anon_package(val weak);
val packagep(val obj);
val find_package(val name);
val delete_package(val package);
diff --git a/txr.1 b/txr.1
index 0f3561e8..ad04d24c 100644
--- a/txr.1
+++ b/txr.1
@@ -54483,7 +54483,7 @@ uses to form the name of the new symbol.
.coNP Function @ make-package
.synb
-.mets (make-package << name )
+.mets (make-package < name <> [ weak ])
.syne
.desc
The
@@ -54499,6 +54499,24 @@ should be performed with the
macro rather than by direct use of
.codn make-package .
+If the
+.meta weak
+parameter is given an argument which is a Boolean true, then the resulting
+package holds symbols weakly, from a garbage collection point of view. If the
+only reference to a symbol is that which occurs inside the weak package, then
+that symbol may be removed from the package and reclaimed by the garbage
+collector.
+
+Note: weak packages address the following problem. The application creates a
+package for the purpose of reading Lisp data. Symbols occurring in that data
+therefore are interned into the package. Subsequently, the application retains
+references to some of the symbols, discarding the others. If the package isn't
+weak, then because the application is retaining some of the symbols, and those
+symbols hold a reference to the package, and the package holds a reference to
+all symbols that were interned in it, all of the symbols are retained. If a
+weak package is used, then the uninterested symbols are eligible for garbage
+collection.
+
.coNP Function @ delete-package
.synb
.mets (delete-package << package )