#ifndef INCLUDED_FUNCTION_H #define INCLUDED_FUNCTION_H #include "base.h" DECLARE_SYMBOL(and_optional); DECLARE_SYMBOL(and_rest); DECLARE_SYMBOL(and_key); DECLARE_SYMBOL(and_allow_other_keys); struct LambdaList { size_t n_req; size_t n_opt; bool allow_other_keys; LispVal *req; // list of symbols LispVal *opt; // list of lists of (name default has-p-name) LispVal *kw; // hash table mapping name (a keyword) to a list of (index name // default has-p-name). This is nil if we are not a keyword // function. LispVal *rest; // symbol (non-nil if we have a rest arg) }; #define MAX_NATIVE_FUNCTION_ARGS 5 union native_function { LispVal *(*zero)(void); LispVal *(*one)(LispVal *); LispVal *(*two)(LispVal *, LispVal *); LispVal *(*three)(LispVal *, LispVal *, LispVal *); LispVal *(*four)(LispVal *, LispVal *, LispVal *, LispVal *); LispVal *(*five)(LispVal *, LispVal *, LispVal *, LispVal *, LispVal *); }; struct interp_function { LispVal *body; // list of forms LispVal *lexenv; }; typedef enum { FUNCTION_NATIVE, FUNCTION_INTERP, } LispFunctionType; struct function_flags { LispFunctionType type : 2; unsigned int no_eval_args : 1; }; DEFOBJTYPE(Function, FUNCTION, FUNCTIONP, { LispVal *name; // symbol (or nil for a lambda) struct function_flags flags; struct LambdaList args; LispVal *docstr; union { union native_function native; struct interp_function interp; } impl; }); typedef enum { LLPS_OK, LLPS_DOTTED, LLPS_REPEAT_SECTION, LLPS_REPEAT_NAME, LLPS_ORDER, LLPS_BAD_NAME, LLPS_REPEAT_REST, LLPS_AFTER_ALLOW_OTHER_KEYS, LLPS_INVALID_OPT_SPEC, LLPS_N_ERROS, } LambdaListParseStatus; const char *llps_strerror(LambdaListParseStatus status); typedef struct { struct LambdaList lambda_list; LambdaListParseStatus status; LispVal *err_obj; // the object the caused the above status } LambdaListParseResult; void parse_lambda_list(LambdaListParseResult *out, LispVal *list); // This will cause the program to exit if an error occurs while parsing // LISP_ARGS! LispVal *make_builtin_function(LispVal *name, LispVal *(*func)(void), const char *lisp_args, size_t args_len, LispVal *docstr); #define BUILTIN_FUNCTION_OBJ(cname) \ make_builtin_function( \ Q##cname, (LispVal * (*) (void) ) F##cname, \ internal_F##cname##_argstr, internal_F##cname##_argstr_len, \ make_lisp_string(internal_F##cname##_docstr, \ internal_F##cname##_docstr_len, false, false)) DECLARE_FUNCTION(funcall, (LispVal * func, LispVal *args)); #define CALL(func, ...) (Ffuncall((func), LIST(__VA_ARGS__))) DECLARE_FUNCTION(lambda, (LispVal * args, LispVal *body)); DECLARE_SYMBOL(declare); DECLARE_SYMBOL(name); #endif