Labels, flet, and macrolet!
This commit is contained in:
91
src/lisp.c
91
src/lisp.c
@ -422,6 +422,23 @@ LispVal *make_user_pointer(void *data, void (*free_func)(void *)) {
|
||||
return LISPVAL(self);
|
||||
}
|
||||
|
||||
DEFUN(make_hashtable, "make-hashtable", (LispVal * hash_fn, LispVal *eq_fn)) {
|
||||
return make_lisp_hashtable(eq_fn, hash_fn);
|
||||
}
|
||||
|
||||
DEFUN(vector, "vector", (LispVal * elems)) {
|
||||
struct UnrefListData uld = {.vals = NULL, .len = 0};
|
||||
WITH_PUSH_FRAME(Qnil, Qnil, true, {
|
||||
void *cl_handler = register_cleanup(&unref_free_list_double_ptr, &uld);
|
||||
FOREACH(elt, elems) {
|
||||
uld.vals = lisp_realloc(uld.vals, sizeof(LispVal *) * (++uld.len));
|
||||
uld.vals[uld.len - 1] = elt;
|
||||
}
|
||||
cancel_cleanup(cl_handler);
|
||||
});
|
||||
return make_lisp_vector(uld.vals, uld.len);
|
||||
}
|
||||
|
||||
DEFUN(pair, "pair", (LispVal * head, LispVal *tail)) {
|
||||
return make_lisp_pair(head, tail);
|
||||
}
|
||||
@ -1068,6 +1085,11 @@ void lisp_init(void) {
|
||||
REGISTER_STATIC_FUNCTION(set_for_return, "(entry dest)", "");
|
||||
REGISTER_STATIC_FUNCTION(internal_real_return, "(name tag value)", "");
|
||||
|
||||
REGISTER_FUNCTION(make_hashtable, "(&opt hash-fn eq-fn)", "");
|
||||
REGISTER_FUNCTION(puthash, "(table key value)", "");
|
||||
REGISTER_FUNCTION(gethash, "(table key &opt def)", "");
|
||||
REGISTER_FUNCTION(remhash, "(table key)", "");
|
||||
REGISTER_FUNCTION(vector, "(&rest elements)", "");
|
||||
REGISTER_FUNCTION(breakpoint, "(&opt id)", "Do nothing...");
|
||||
REGISTER_FUNCTION(sethead, "(pair newval)",
|
||||
"Set the head of PAIR to NEWVAL.");
|
||||
@ -1100,6 +1122,7 @@ void lisp_init(void) {
|
||||
setq, "(&rest name-value-pairs)",
|
||||
"Set each of a number of variables to their respective values.");
|
||||
REGISTER_FUNCTION(progn, "(&rest forms)", "Evaluate each of FORMS.");
|
||||
REGISTER_FUNCTION(symbol_name, "(sym)", "");
|
||||
REGISTER_FUNCTION(symbol_function, "(sym &opt resolve)", "");
|
||||
REGISTER_FUNCTION(symbol_value, "(sym)", "Return the global value of SYM.");
|
||||
REGISTER_FUNCTION(symbol_plist, "(sym)", "Return the plist of SYM.");
|
||||
@ -1120,10 +1143,10 @@ void lisp_init(void) {
|
||||
"Return non-nil if OBJ1 and OBJ2 are equal");
|
||||
REGISTER_FUNCTION(make_symbol, "(name)",
|
||||
"Return a new un-interned symbol named NAME.");
|
||||
REGISTER_FUNCTION(macroexpand_1, "(form)",
|
||||
REGISTER_FUNCTION(macroexpand_1, "(form &opt lexical-macros)",
|
||||
"Return the form which FORM expands to.");
|
||||
REGISTER_FUNCTION(macroexpand_toplevel, "(form)", "");
|
||||
REGISTER_FUNCTION(macroexpand_all, "(form)", "");
|
||||
REGISTER_FUNCTION(macroexpand_toplevel, "(form &opt lexical-macros)", "");
|
||||
REGISTER_FUNCTION(macroexpand_all, "(form &opt lexical-macros)", "");
|
||||
REGISTER_FUNCTION(stringp, "(val)", "Return non-nil if VAL is a string.");
|
||||
REGISTER_FUNCTION(symbolp, "(val)", "Return non-nil if VAL is a symbol.");
|
||||
REGISTER_FUNCTION(pairp, "(val)", "Return non-nil if VAL is a pair.");
|
||||
@ -1133,7 +1156,7 @@ void lisp_init(void) {
|
||||
REGISTER_FUNCTION(
|
||||
functionp, "(val)",
|
||||
"Return non-nil if VAL is a non-macro function (includes buitlins).");
|
||||
REGISTER_FUNCTION(macrop, "(val)",
|
||||
REGISTER_FUNCTION(macrop, "(val &opt lexical-macros)",
|
||||
"Return non-nil if VAL is a non-builtin macro.");
|
||||
REGISTER_FUNCTION(builtinp, "(val)",
|
||||
"Return non-nil if VAL is a non-macro builtin.");
|
||||
@ -1210,6 +1233,11 @@ DEFUN(breakpoint, "breakpoint", (LispVal * id)) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
DEFUN(symbol_name, "symbol-name", (LispVal * symbol)) {
|
||||
CHECK_TYPE(TYPE_SYMBOL, symbol);
|
||||
return refcount_ref(((LispSymbol *) symbol)->name);
|
||||
}
|
||||
|
||||
DEFUN(symbol_function, "symbol-function",
|
||||
(LispVal * symbol, LispVal *resolve)) {
|
||||
CHECK_TYPE(TYPE_SYMBOL, symbol);
|
||||
@ -1707,10 +1735,32 @@ DEFUN(copy_tree, "copy-tree", (LispVal * tree)) {
|
||||
return copy;
|
||||
}
|
||||
|
||||
DEFUN(macroexpand_1, "macroexpand-1", (LispVal * form)) {
|
||||
static LispVal *lookup_lexical_macro(LispVal *name, LispVal *lexical_macros) {
|
||||
if (!SYMBOLP(name)) {
|
||||
return Qunbound;
|
||||
}
|
||||
LispVal *res = Fplist_get(lexical_macros, name, Qunbound, Qnil);
|
||||
if (FUNCTIONP(res)) {
|
||||
return res;
|
||||
}
|
||||
refcount_unref(res);
|
||||
return Qunbound;
|
||||
}
|
||||
|
||||
static inline LispVal *expand_function_as_macro(LispFunction *fobj,
|
||||
LispVal *args) {
|
||||
return Ffuncall((LispVal *) fobj, args);
|
||||
}
|
||||
|
||||
DEFUN(macroexpand_1, "macroexpand-1",
|
||||
(LispVal * form, LispVal *lexical_macros)) {
|
||||
if (PAIRP(form)) {
|
||||
LispFunction *fobj;
|
||||
if (FUNCTIONP(HEAD(form))) {
|
||||
LispVal *lex_res = lookup_lexical_macro(HEAD(form), lexical_macros);
|
||||
LispFunction *fobj = (LispFunction *) Qunbound;
|
||||
if (lex_res != Qunbound) {
|
||||
return expand_function_as_macro((LispFunction *) lex_res,
|
||||
TAIL(form));
|
||||
} else if (FUNCTIONP(HEAD(form))) {
|
||||
fobj = refcount_ref(HEAD(form));
|
||||
} else {
|
||||
fobj = (LispFunction *) Fsymbol_function(HEAD(form), Qt);
|
||||
@ -1748,12 +1798,13 @@ DEFUN(macroexpand_1, "macroexpand-1", (LispVal * form)) {
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN(macroexpand_toplevel, "macroexpand-toplevel", (LispVal * form)) {
|
||||
DEFUN(macroexpand_toplevel, "macroexpand-toplevel",
|
||||
(LispVal * form, LispVal *lexical_macros)) {
|
||||
if (PAIRP(form)) {
|
||||
LispVal *out = refcount_ref(form);
|
||||
void *cl_handler = register_cleanup(&unref_double_ptr, &out);
|
||||
while (PAIRP(out) && !NILP(Fmacrop(HEAD(out)))) {
|
||||
LispVal *new_out = Fmacroexpand_1(out);
|
||||
while (PAIRP(out) && !NILP(Fmacrop(HEAD(out), lexical_macros))) {
|
||||
LispVal *new_out = Fmacroexpand_1(out, lexical_macros);
|
||||
refcount_unref(out);
|
||||
out = new_out;
|
||||
}
|
||||
@ -1942,12 +1993,15 @@ static LispVal *filter_body_tree(LispVal *body,
|
||||
return start;
|
||||
}
|
||||
|
||||
static LispVal *macroexpand_toplevel_as_callback(LispVal *form, void *ignored) {
|
||||
return Fmacroexpand_toplevel(form);
|
||||
static LispVal *macroexpand_toplevel_as_callback(LispVal *form,
|
||||
void *lexical_macros) {
|
||||
return Fmacroexpand_toplevel(form, lexical_macros);
|
||||
}
|
||||
|
||||
DEFUN(macroexpand_all, "macroexpand-all", (LispVal * form)) {
|
||||
return filter_body_form(form, macroexpand_toplevel_as_callback, NULL);
|
||||
DEFUN(macroexpand_all, "macroexpand-all",
|
||||
(LispVal * form, LispVal *lexical_macros)) {
|
||||
return filter_body_form(form, macroexpand_toplevel_as_callback,
|
||||
lexical_macros);
|
||||
}
|
||||
|
||||
DEFUN(apply, "apply", (LispVal * function, LispVal *rest)) {
|
||||
@ -2257,7 +2311,7 @@ struct NameAndReturnTag {
|
||||
|
||||
static LispVal *expand_function_body_callback(LispVal *body, void *data) {
|
||||
struct NameAndReturnTag *name_and_return_tag = data;
|
||||
LispVal *expansion = Fmacroexpand_toplevel(body);
|
||||
LispVal *expansion = Fmacroexpand_toplevel(body, Qnil);
|
||||
// this mess checks that the call is exactly one of
|
||||
// - (return-from 'symbol)
|
||||
// - (return-from 'symbol val)
|
||||
@ -2292,7 +2346,7 @@ static inline LispVal *expand_function_body(LispVal *name, LispVal *return_tag,
|
||||
}
|
||||
|
||||
static LispVal *macroexpand_all_as_callback(LispVal *form, void *ignored) {
|
||||
return Fmacroexpand_all(form);
|
||||
return Fmacroexpand_all(form, Qnil);
|
||||
}
|
||||
|
||||
static inline void expand_lambda_list_for_toplevel(LispVal *list) {
|
||||
@ -2432,11 +2486,14 @@ DEFUN(functionp, "functionp", (LispVal * val)) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
DEFUN(macrop, "macrop", (LispVal * val)) {
|
||||
DEFUN(macrop, "macrop", (LispVal * val, LispVal *lexical_macros)) {
|
||||
if (FUNCTIONP(val) && !((LispFunction *) val)->is_builtin
|
||||
&& ((LispFunction *) val)->is_macro) {
|
||||
return Qt;
|
||||
} else if (SYMBOLP(val)) {
|
||||
if (lookup_lexical_macro(val, lexical_macros) != Qunbound) {
|
||||
return Qt;
|
||||
}
|
||||
LispVal *res = Fsymbol_function(val, Qt);
|
||||
LispVal *retval =
|
||||
LISP_BOOL(FUNCTIONP(res) && !((LispFunction *) res)->is_builtin
|
||||
|
Reference in New Issue
Block a user