Work on packages

This commit is contained in:
2025-09-22 04:08:24 -07:00
parent 96c4d9eecb
commit 5dbc0276d4
6 changed files with 773 additions and 186 deletions

View File

@ -31,6 +31,7 @@ typedef enum {
TYPE_FUNCTION,
TYPE_HASHTABLE,
TYPE_USER_POINTER,
TYPE_PACKAGE,
N_LISP_TYPES,
} LispType;
@ -60,6 +61,7 @@ typedef struct {
LISP_OBJECT_HEADER;
LispString *name;
LispVal *package;
LispVal *plist;
LispVal *function;
LispVal *value;
@ -122,7 +124,10 @@ typedef struct {
bool allow_other_keys;
LispVal *rest_arg;
union {
lisp_function_ptr_t builtin;
struct {
lisp_function_ptr_t builtin;
bool distinguish_unpassed;
};
LispVal *body;
};
@ -159,6 +164,14 @@ typedef struct {
} LispUserPointer;
#define USERPTR(type, obj) ((type *) ((LispUserPointer *) (obj))->data)
typedef struct {
LISP_OBJECT_HEADER;
LispString *name;
LispVal *obarray; // str -> sym
LispVal *exported_sym_table; // sym -> bool
LispVal *imported; // list of (package . (str -> bool))
} LispPackage;
// #######################
// # nil, unbound, and t #
// #######################
@ -193,12 +206,17 @@ extern LispSymbol _Qt;
#define FUNCTIONP(v) (TYPEOF(v) == TYPE_FUNCTION)
#define HASHTABLEP(v) (TYPEOF(v) == TYPE_HASHTABLE)
#define USER_POINTER_P(v) (TYPEOF(v) == TYPE_USER_POINTER)
#define PACKAGEP(v) (TYPEOF(v) == TYPE_PACKAGE)
#define ATOM(v) (TYPEOF(v) != TYPE_PAIR)
extern LispVal *package_table;
extern LispVal *system_package;
extern LispVal *keyword_package;
extern LispVal *current_package;
inline static bool KEYWORDP(LispVal *v) {
return SYMBOLP(v) && ((LispSymbol *) v)->name->length
&& ((LispSymbol *) v)->name->data[0] == ':';
return SYMBOLP(v) && ((LispSymbol *) v)->package == keyword_package;
}
inline static bool LISTP(LispVal *v) {
@ -224,8 +242,9 @@ inline static bool NUMBERP(LispVal *v) {
static LispSymbol _Q##c_name = { \
.type = TYPE_SYMBOL, \
.name = &_Q##c_name##_symnamestr, \
.package = Qnil, \
.plist = Qnil, \
.function = Qunbound, \
.function = Qnil, \
.value = Qunbound, \
.is_constant = false, \
}; \
@ -234,62 +253,67 @@ inline static bool NUMBERP(LispVal *v) {
LispVal *F##c_name args; \
extern LispVal *Q##c_name
// The args and doc fields are filled when the function is registered
#define _INTERNAL_DEFUN_EXTENDED(macrop, c_name, lisp_name, c_args, static_kw) \
static_kw LispVal *F##c_name c_args; \
DEF_STATIC_STRING(_Q##c_name##_fnnamestr, lisp_name); \
static LispSymbol _Q##c_name; \
static LispFunction _Q##c_name##_function = { \
.type = TYPE_FUNCTION, \
.is_builtin = true, \
.is_macro = macrop, \
.builtin = (void (*)(void)) & F##c_name, \
.name = LISPVAL(&_Q##c_name), \
.doc = Qnil, \
.args = Qnil, \
.rargs = Qnil, \
.oargs = Qnil, \
.rest_arg = Qnil, \
.kwargs = Qnil, \
.lexenv = Qnil, \
}; \
static LispSymbol _Q##c_name = { \
.type = TYPE_SYMBOL, \
.name = &_Q##c_name##_fnnamestr, \
.plist = Qnil, \
.value = Qunbound, \
.function = LISPVAL(&_Q##c_name##_function), \
.is_constant = false, \
}; \
LispVal *Q##c_name = (LispVal *) &_Q##c_name; \
#define _INTERNAL_DEFUN_EXTENDED(macrop, du, c_name, lisp_name, c_args, \
static_kw) \
static_kw LispVal *F##c_name c_args; \
DEF_STATIC_STRING(_Q##c_name##_fnnamestr, lisp_name); \
static LispSymbol _Q##c_name; \
static LispFunction _Q##c_name##_function = { \
.type = TYPE_FUNCTION, \
.is_builtin = true, \
.is_macro = macrop, \
.builtin = (void (*)(void)) & F##c_name, \
.distinguish_unpassed = du, \
.name = LISPVAL(&_Q##c_name), \
.doc = Qnil, \
.args = Qnil, \
.rargs = Qnil, \
.oargs = Qnil, \
.rest_arg = Qnil, \
.kwargs = Qnil, \
.lexenv = Qnil, \
}; \
static LispSymbol _Q##c_name = { \
.type = TYPE_SYMBOL, \
.name = &_Q##c_name##_fnnamestr, \
.package = Qnil, \
.plist = Qnil, \
.value = Qunbound, \
.function = LISPVAL(&_Q##c_name##_function), \
.is_constant = false, \
}; \
LispVal *Q##c_name = (LispVal *) &_Q##c_name; \
static_kw LispVal *F##c_name c_args
#define DEFUN(c_name, lisp_name, c_args) \
_INTERNAL_DEFUN_EXTENDED(false, c_name, lisp_name, c_args, )
_INTERNAL_DEFUN_EXTENDED(false, false, c_name, lisp_name, c_args, )
#define DEFUN_DISTINGUISHED(c_name, lisp_name, c_args) \
_INTERNAL_DEFUN_EXTENDED(false, true, c_name, lisp_name, c_args, )
#define DEFMACRO(c_name, lisp_name, c_args) \
_INTERNAL_DEFUN_EXTENDED(true, c_name, lisp_name, c_args, )
_INTERNAL_DEFUN_EXTENDED(true, false, c_name, lisp_name, c_args, )
#define STATIC_DEFUN(c_name, lisp_name, c_args) \
_INTERNAL_DEFUN_EXTENDED(false, c_name, lisp_name, c_args, static)
_INTERNAL_DEFUN_EXTENDED(false, false, c_name, lisp_name, c_args, static)
#define STATIC_DEFMACRO(c_name, lisp_name, c_args) \
_INTERNAL_DEFUN_EXTENDED(true, c_name, lisp_name, c_args, static)
_INTERNAL_DEFUN_EXTENDED(true, false, c_name, lisp_name, c_args, static)
// ###############
// # Loop macros #
// ###############
#define HASHTABLE_FOREACH(key_var, val_var, table, body) \
{ \
LispHashtable *__hashtable_foreach_table = (LispHashtable *) table; \
for (size_t __hashtable_foreach_i = 0; \
__hashtable_foreach_i < __hashtable_foreach_table->table_size; \
++__hashtable_foreach_i) { \
struct HashtableBucket *__hashtable_foreach_cur = \
__hashtable_foreach_table->data[__hashtable_foreach_i]; \
while (__hashtable_foreach_cur) { \
LispVal *key_var = __hashtable_foreach_cur->key; \
LispVal *val_var = __hashtable_foreach_cur->value; \
{body}; \
__hashtable_foreach_cur = __hashtable_foreach_cur->next; \
} \
} \
}
#define HASHTABLE_FOREACH(key_var, val_var, table) \
for (struct { \
LispHashtable *ht; \
size_t i; \
} __l = {.ht = (void *) table, .i = 0}; \
__l.i < __l.ht->table_size; ++__l.i) \
for (LispVal *__b = (void *) __l.ht->data[__l.i], \
*key_var = __b ? ((struct HashtableBucket *) __b)->key \
: NULL, \
*val_var = __b ? ((struct HashtableBucket *) __b)->value \
: NULL; \
__b; __b = (void *) ((struct HashtableBucket *) __b)->next, \
key_var = __b ? ((struct HashtableBucket *) __b)->key \
: NULL, \
val_var = __b ? ((struct HashtableBucket *) __b)->value \
: NULL)
#define FOREACH(var, list) \
for (LispVal *__foreach_cur = list, *var = HEAD(list); \
!NILP(__foreach_cur); \
@ -327,6 +351,7 @@ LispVal *make_lisp_hashtable(LispVal *eq_fn, LispVal *hash_fn);
LispVal *make_user_pointer(void *data, void (*free_func)(void *));
#define ALLOC_USERPTR(type, free_func) \
(make_user_pointer(lisp_malloc(sizeof(type)), &free_func))
LispVal *make_lisp_package(LispVal *name);
// ########################
// # Utility and internal #
@ -343,15 +368,35 @@ DECLARE_FUNCTION(puthash, (LispVal * table, LispVal *key, LispVal *value));
DECLARE_FUNCTION(gethash, (LispVal * table, LispVal *key, LispVal *def));
DECLARE_FUNCTION(remhash, (LispVal * table, LispVal *key));
DECLARE_FUNCTION(hash_table_count, (LispVal * table));
LispVal *intern(const char *name, size_t length, bool take);
DECLARE_FUNCTION(intern, (LispVal * name));
static inline LispVal *_internal_INTERN_STATIC(const char *name, size_t len) {
DECLARE_FUNCTION(in_package, (LispVal * package));
DECLARE_FUNCTION(package_name, (LispVal * package));
DECLARE_FUNCTION(mapsymbols, (LispVal * func, LispVal *package));
DECLARE_FUNCTION(set_current_package, (LispVal * package));
DECLARE_FUNCTION(current_package, (void) );
DECLARE_FUNCTION(export_symbol, (LispVal * symbol));
DECLARE_FUNCTION(import_package,
(LispVal * source, LispVal *names, LispVal *target));
DECLARE_FUNCTION(make_package, (LispVal * name));
DECLARE_FUNCTION(register_package, (LispVal * package));
DECLARE_FUNCTION(find_package, (LispVal * name));
DECLARE_FUNCTION(exported_symbol_p, (LispVal * symbol));
DECLARE_FUNCTION(intern_soft, (LispVal * name, LispVal *def, LispVal *package,
LispVal *included_too));
LispVal *find_package(const char *name, size_t length);
#define FIND_PACKAGE_STATIC(name) (find_package(name, sizeof(name)))
LispVal *intern(const char *name, size_t length, bool take, LispVal *package,
bool included_too);
DECLARE_FUNCTION(intern,
(LispVal * name, LispVal *package, LispVal *included_too));
static inline LispVal *_internal_INTERN_STATIC(const char *name, size_t len,
LispVal *package) {
LispVal *kn = make_lisp_string(name, len, true, true);
LispVal *retval = Fintern(kn);
LispVal *retval = Fintern(kn, package, Qnil);
refcount_unref(kn);
return retval;
}
#define INTERN_STATIC(name) (_internal_INTERN_STATIC((name), sizeof(name) - 1))
#define INTERN_STATIC(name, package) \
(_internal_INTERN_STATIC((name), sizeof(name) - 1, package))
DECLARE_FUNCTION(sethead, (LispVal * pair, LispVal *head));
DECLARE_FUNCTION(settail, (LispVal * pair, LispVal *tail));
@ -504,8 +549,8 @@ DECLARE_FUNCTION(backtrace, (void) );
noreturn DECLARE_FUNCTION(return_from, (LispVal * name, LispVal *value));
noreturn DECLARE_FUNCTION(throw, (LispVal * signal, LispVal *rest));
extern LispVal *Qsuccess;
extern LispVal *Qfinally;
extern LispVal *Qkw_success;
extern LispVal *Qkw_finally;
extern LispVal *Qshutdown_signal;
extern LispVal *Qtype_error;
extern LispVal *Qread_error;
@ -519,6 +564,9 @@ extern LispVal *Qargument_error;
extern LispVal *Qinvalid_function_error;
extern LispVal *Qno_applicable_method_error;
extern LispVal *Qreturn_frame_error;
extern LispVal *Qpackage_exists_error;
extern LispVal *Qunknown_package_error;
extern LispVal *Qimport_error;
LispVal *predicate_for_type(LispType type);
#define CHECK_TYPE(type, val) \
@ -530,16 +578,17 @@ LispVal *predicate_for_type(LispType type);
Fthrow(Qtype_error, args); \
}
extern LispVal *Vobarray;
#define REGISTER_SYMBOL_NOINTERN(sym) \
{ \
refcount_init_static(Q##sym); \
refcount_init_static(((LispSymbol *) Q##sym)->name); \
}
#define REGISTER_SYMBOL(sym) \
REGISTER_SYMBOL_NOINTERN(sym) \
puthash(Vobarray, LISPVAL(((LispSymbol *) Q##sym)->name), Q##sym);
#define REGISTER_SYMBOL_INTO(sym, pkg) \
REGISTER_SYMBOL_NOINTERN(sym) \
((LispSymbol *) Q##sym)->package = refcount_ref(pkg); \
puthash(((LispPackage *) pkg)->obarray, \
LISPVAL(((LispSymbol *) Q##sym)->name), Q##sym);
#define REGISTER_SYMBOL(sym) REGISTER_SYMBOL_INTO(sym, system_package)
#define REGISTER_STATIC_FUNCTION(name, args, docstr) \
REGISTER_SYMBOL_NOINTERN(name); \
{ \
@ -547,14 +596,16 @@ extern LispVal *Vobarray;
refcount_init_static(obj); \
((LispFunction *) (obj))->doc = STATIC_STRING(docstr); \
LispVal *src = STATIC_STRING(args); \
LispVal *a = Fread(src); \
LispVal *a = Fread(src, system_package); \
set_function_args((LispFunction *) (obj), a); \
refcount_unref(src); \
refcount_unref(a); \
}
#define REGISTER_FUNCTION(fn, args, docstr) \
REGISTER_STATIC_FUNCTION(fn, args, docstr); \
puthash(Vobarray, LISPVAL(((LispSymbol *) Q##fn)->name), Q##fn);
#define REGISTER_FUNCTION(fn, args, docstr) \
REGISTER_STATIC_FUNCTION(fn, args, docstr); \
((LispSymbol *) Q##fn)->package = refcount_ref(system_package); \
puthash(((LispPackage *) system_package)->obarray, \
LISPVAL(((LispSymbol *) Q##fn)->name), Q##fn);
void lisp_init(void);
void lisp_shutdown(void);
@ -566,6 +617,7 @@ extern LispVal *Qcomma_at;
DECLARE_FUNCTION(quote, (LispVal * form));
DECLARE_FUNCTION(breakpoint, (LispVal * id));
DECLARE_FUNCTION(symbol_package, (LispVal * symbol));
DECLARE_FUNCTION(symbol_name, (LispVal * symbol));
DECLARE_FUNCTION(symbol_function, (LispVal * symbol, LispVal *resolve));
DECLARE_FUNCTION(symbol_value, (LispVal * symbol));
@ -605,6 +657,7 @@ DECLARE_FUNCTION(pairp, (LispVal * val));
DECLARE_FUNCTION(integerp, (LispVal * val));
DECLARE_FUNCTION(floatp, (LispVal * val));
DECLARE_FUNCTION(vectorp, (LispVal * val));
DECLARE_FUNCTION(packagep, (LispVal * val));
DECLARE_FUNCTION(functionp, (LispVal * val));
DECLARE_FUNCTION(macrop, (LispVal * val, LispVal *lexical_macros));
DECLARE_FUNCTION(builtinp, (LispVal * val));