summaryrefslogtreecommitdiffstats
path: root/eval.c
Commit message (Collapse)AuthorAgeFilesLines
...
* Rename interp_fun function.Kaz Kylheku2015-11-301-1/+1
| | | | | | | | | * eval.c (interp_fun): Function renamed to funcall_interp. * eval.h (interp_fun): Declaration updated. * lib.c (generic_funcall, funcall, funcall1, funcall2, funcall3, funcall4): Calls to interp_fun updated.
* func-get-name calculates a name for methods.Kaz Kylheku2015-11-301-1/+4
| | | | | | | | | | | | | | * eval.c (func_get_name): Use try to use new method_name function, if unable to get name from the lexical or global environment for functions. * struct.c (meth_s): New symbol variable. (struct_init): Initialize meth_s variable. (method_name): New function. * struct.h (method_name): Declared. * txr.1: Re-documented func-get-name.
* Improve destructuring error messages.Kaz Kylheku2015-11-291-4/+4
| | | | | | | * eval.c (bind_macro_params): On mismatch between atom and param list, or insufficient parameters for list, report which params are mismatched. In a nested destructuring syntax, it is difficult to know.
* Error reports trace through layers of macroexpansion.Kaz Kylheku2015-11-281-9/+56
| | | | | | | | | | | | | | | | | | | | * eval.c (error_trace): New function. Consolidates error reporting between unhandled exception handling in uw_throw, and the catcher in the repl. (op_defmacro, expand_macrolet): Propagate location info from body to wrapping block, and to the macro binding. In the latter function, also to the body that is wrapped by local macros. (do_expand, macroexpand_1): Propagate location info from macro expander to expansion, only taking it from the form if the macro doesn't supply it. * eval.h (error_trace): Declared. * parser.c (repl): Replace error reporting code with call to error_trace. * unwind.c (uw_throw): uw_throw: likewise.
* Propagate location info in progn optimization.Kaz Kylheku2015-11-281-1/+1
| | | | * eval.c (maybe_progn): rlcp info to generated progn cons.
* Improve source loc copying in expand_qquote.Kaz Kylheku2015-11-281-5/+5
| | | | | | * eval.c (expand_qquote): Use rlcp_tree to propagate source location more completely. Also, it was missing in the quote case.
* Report chain of macro-expansions in errors.Kaz Kylheku2015-11-251-2/+14
| | | | | | | | | | | | | | | * eval.c (origin_hash): New global variable. (lookup_origin): New function. (expand_macro): Enter original form into origin hash, keyed by new form. (eval_init): gc-protect and initialize origin_hash. * eval.h (lookup_origin): Declared. * parser.c (repl): Report chain of expansions from last_form_evaled. * unwind.c (uw_throw): Likewise.
* New functions window-map and window-mappend.Kaz Kylheku2015-11-251-0/+2
| | | | | | | | | | | | | | | | | * args.h (args_set_fill): New inline function. * eval.c (eval_init): Register window-map and window-mappend intrinics. * lib.c (wrap_k, reflect_k): New keyword variables. (calc_win_size): New static function. (window_map_list, window_map_vec): New static functions. (window_map, window_mappend): New functions. (obj_init): Initialize wrap_k and reflect_k. * lib.h (window_map, window_mappend): Declared. * txr.1: Documented window-map and window-mappend
* Provide butlast function.Kaz Kylheku2015-11-201-0/+1
| | | | | | | | | | * eval.c (eval_init): Registered butlast intrinsic. * lib.c (butlast): New function. * lib.h (butlast): Declared. * txr.1: Documented butlast.
* Adding revappend and nreconc.Kaz Kylheku2015-11-111-0/+2
| | | | | | | | | | | | | | | * eval.c (eval_init): Register revappend and nreconc intrinsics. * lib.c (list_collect_nreconc): New function. (revlist): New static function. (list_collect_revappend): New function. (revappend, nreconc): New functions. * lib.h (revappend, nreconc): Declared. (list_collect_nreconc, list_collect_revappend): Declared. * txr.1: Documented revappend and nreconc.
* New function: group-reduce.Kaz Kylheku2015-11-101-0/+2
| | | | | | | | | | * eval.c (eval_init): Register group-reduce intrinsic. * hash.c (group_reduce): New function. * hash.h (group_reduce): Declared. * txr.1: Documented group-reduce.
* New block* op; functions return* and sys:abscond*.Kaz Kylheku2015-11-091-2/+34
| | | | | | | | | | | | * eval.c (block_star_s): New symbol variable. (op_block_star): New static function. (do_expand): Handle block* symbol. (return_star, abscond_star): New static functions. (eval_init): Initialize block_star_s variable. Register block* operator and return* and sys:abscond* functions. * txr.1: Documented new operator and functions.
* Variable init forms of for go inside nil block.Kaz Kylheku2015-11-081-3/+7
| | | | | | | | * eval.c (op_for): Establish the block before doing any evaluation, subject to the compatibility option. * txr.1: Updated documentation for for, exchanging steps 1 and 2. Added compatibility notes.
* New iread function.Kaz Kylheku2015-11-071-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The read function no longer works like it used to on an interactive terminal because of the support for .. and . syntax on a top-level expression. The iread function is provided which uses a modified syntax that doesn't support these operators on a top-level expression. The parser thus doesn't look one token ahead, and so iread can return immediately. * eval.c (eval_init): Register iread intrinsic function. * parser.c (prime_parser): Only push back the recently seen token when priming for a regular Lisp read. Handle the prime_interactive method by preparing a SECRET_ESCAPE_I token. (lisp_parse_impl): New static function, formed from previous lisp_parse. Takes a boolean argument indicating interactive mode. (prime_parser_post): New function. (lisp_parse): Now a wrapper for lisp_parse_impl which passes a nil to indicate noninteractive read. (iread): New function. * parser.h (enum prime_parser): New member, prime_interactive. (scrub_scanner, iread, prime_parser_post): Declared. * parser.l (prime_scanner): Handle the prime_interactive case the same way as prime_lisp. (scrub_scanner): New function. * parser.y (SECRET_ESCAPE_I): New token type. (i_expr): New nonterminal symbol. Like n_expr, but doesn't support dot or dotdot operators, except in nested subexpressions. (spec): Handle SECRET_ESCAPE_I by way of i_expr. (sym_helper): Before freeing the token lexeme, call scrub_scanner. If the token is registered as the scanner's most recently seen token, the scanner must forget that registration, because it is no longer valid. (parse): Call prime_parser_post. * txr.1: Documented iread.
* Copy envs for middle-of-binding continuations.Kaz Kylheku2015-11-051-14/+68
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When continuations are captured/restored in the middle of variable binding constructs, a hidden problem occurs. Binding constructs work by allocating an empty environment and then destructively extending it. Since the environment is not on the stack, but a referenced object, it doesn't get deep copied into a continuation. As the continuation is revived repeatedly, parts of the variable binding code are repeatedly re-executed, and keep pushing fresh bindings into the same environment object. Though the new bindings correctly shadow the old, the old bindings are there and potentially hang on to garbage. The solution taken here is to introduce a new kind of frame for handling the situation: a continuation copy handling frame. This frame allows functions to register objects to be copied more deeply if a continuation is captured/revived across them. * eval.c (copy_env): New static function. (copy_env_handler): New static function. (bind_args, bind_macro_params): Install continuation copy handling frame for cloning new_env. (struct bindings_helper_vars): New struct type. (copy_bh_env_handler): New static function. (bindings_helper): Install continuation copy handling frame for de and ne variables which hold environments. The variables are moved to a struct to facilitate access from the handler. * eval.h (copy_env): Declared. * unwind.c (uw_push_cont_copy): New function. (call_copy_handler): New static function. (revive_cont): When a continuation is being revived invoke the copying actions in its continuation copy handling frames, but not if it is only being temporarily revived for immediate unwinding. (capture_cont): After copying the continuation, invoke any continuation copying frames in the "parent": the original frames that were captured. * unwind.h (enum uw_frtype): New type, UW_CONT_COPY. (struct uw_cont_copy): New struct type. (union uw_frame): New member cp. (uw_push_cont_copy): Declared.
* Pattern vars accessed from Lisp now dynamic.Kaz Kylheku2015-11-041-1/+1
| | | | | | | | | | | | | | | * eval.c (set_dyn_env): Static function becomes external. * eval.h (set_dyn_env): Declared. * match.c (eval_with_bindings, eval_progn_with_bindings): Evaluate Lisp code in null lexical environment. Instead install the pattern variables as dynamic, so they shadow global variables. A compatibility check for 121 or earlier provides the old behavior. * txr.1: Document scoping rules, and added compatibility notes.
* New range type, distinct from cons cell.Kaz Kylheku2015-11-011-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): Register intrinsic functions rcons, rangep from and to. (eval_init): Register rangep intrinsic. * gc.c (mark_obj): Traverse RNG objects. (finalize): Handle RNG in switch. * hash.c (equal_hash, eql_hash): Hashing for for RNG objects. * lib.c (range_s, rcons_s): New symbol variables. (code2type): Handle RNG type. (eql, equal): Equality for ranges. (less_tab_init): Table extended to cover RNG. (less): Semantics defined for ranges. (rcons, rangep, from, to): New functions. (obj_init): range_s and rcons_s variables initialized. (obj_print_impl): Produce #R notation for ranges. (generic_funcall, dwim_set): Recognize range objects for indexing * lib.h (enum type): New enum member, RNG. MAXTYPE redefined to RNG value. (TYPE_SHIFT): Increased to 5 since there are now 16 type codes. (struct range): New struct type. (union obj): New member rn, of type struct range. (range_s, rcons_s, rcons, rangep, from, to): Declared. (range_bind): New macro. * parser.l (grammar): New rule for recognizing the #R sequence as HASH_R token. * parser.y (HASH_R): New terminal symbol. (range): New nonterminal symbol. (n_expr): Derives the new range symbol. The n_expr DOTDOT n_expr rule produces rcons expression rather than const. * match.c (format_field): Recognize rcons syntax in fields which is now what ranges translate to. Also recognize range object. * tests/013/maze.tl (neigh): Fix code which destructures range as a cons. That can't be done any more. * txr.1: Document ranges.
* Implementing sys:abscond-from operator.Kaz Kylheku2015-10-281-2/+16
| | | | | | | | | | | | | | | | | | | | | * eval.c (sys_abscond_from_s): New symbol variable. (op_abscond_from): New static function. (do_expand): Handle abscond-from like return-from. (eval_init): Initialize sys_abscond_from_s and register sys:abscond-from operator. * share/txr/stdlib/yield.tl (yield-from): Use sys:abscond-from instead of return-from, to avoid tearing down the continuation's resources that it may need when restarted. * txr.1: Documented sys:abscond-from and added a mention to the Delimited Continuations introduction. * unwind.c (uw_abscond_to_exit_point): New static function. (uw_block_abscond): New function. * unwind.h (uw_block_abscond): Declared.
* Expose eval_error out of eval module.Kaz Kylheku2015-10-281-1/+1
| | | | | | * eval.c (eval_error): Static function made external. * eval.h (eval_error): Declared.
* New special macro parameter list parameter :form.Kaz Kylheku2015-10-281-3/+8
| | | | | | | | * eval.c (form_k): New keyword symbol variable. (bind_macro_params): Implement form_k. (eval_init): Initialize form_k. * txr.1: Documented :form parameter.
* Stop using C library setjmp/longjmp.Kaz Kylheku2015-10-251-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | TXR is moving to custom assembly-language routines. This is mainly motivated by a very dubious thing done in the GNU C Library setjmp and longjmp in the name of security. Evidently, glibc's setjmp "mangles" certain pointer values which are stored into the jmp_buf buffer. It's been that way since 2005, evidently. This means that, firstly, all along, the use of setjmp in gc.c to get registers into a buffer so they can be scanned has not actually worked properly. More importantly, this pointer mangling in setjmp and longjmp is very hostile to a stack copying implementation of delimited continuations. The reason is that continuations contain jmp_buf buffers, which get relocated in the process of capturing and reviving a continuation. Any pointers in a jmp_buf which point into the captured stack segment have to be fixed up to point into the relocated location. Mangled pointers make this difficult, requiring hacks which are specific to glibc and the machine architecture. We might as well implement a clean, well-behaved setjmp and longjmp. * Makefile (jmp.o): New object file. (dbg/%.o, opt/%.o): New rules for .S prerequisites. * args.c, arith.c, cadr.c, combi.c, cadr.c, combi.c, debug.c, eval.c, filter.c, glob.c, hash.c, lib.c, match.c, parser.c, rand.c, regex.c, signal.c, stream.c, struct.c, sysif.c, syslog.c, txr.c, unwind.c, utf8.c: Removed <setjmp.h> include. * gc.c: Switch to struct jmp and jmp_save, instead of jmp_buf and setjmp. * jmp.S: New source file. * signal.h (struct jmp): New struct type. (jmp_save, jmp_restore): New function declarations denoting assembly language routines in jmp.S. (extended_jmp_buf): Uses struct jmp instead of setjmp. (extended_setjmp): Use jmp_save instead of setjmp. (extended_longjmp): Use jmp_restore instead of longjmp.
* Reduce stack usage for args in a few places.Kaz Kylheku2015-10-241-3/+2
| | | | | | * eval.c (apply, do_eval): Use ARGS_MIN instead of ARGS_MAX. * unwind.c (uw_throw): Ditto, when invoking handler.
* Renaming some functions for consistency.Kaz Kylheku2015-10-161-7/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * combi.c (perm_list, perm_str, rperm_list, reperm_gen_fun, rperm_vec, comb_vec, rcomb_list, rcomb_vec, rcomb_str): Follow rename of list_vector to list_vec. * eval.c (vector_list_s): Global variable renamed to vec_list_s. (expand_qquote): Follow vector_list_s to vec_list_s. (eval_init): Follow renames of all identifiers. Functions num-chr, chr-num, vector-list and list-vector are registered under new names, while remaining registered under old names. * eval.h (vector_list_s): Declaration renamed. * filter.c (url_encode): Follow chr_num to chr_int rename. * lib.c (make_like, interpose, shuffle): Follow vector_list to vec_list rename. (tolist, replace, replace_list): Follow list_vector to list_vec rename. (num_chr): Renamed to int_chr. (chr_num): Renamed to chr_int. (vector_list): Renamed to vec_list. (list_vector): Renamed to list_vec. * lib.h (num_chr, chr_num, list_vector, vector_list): * Declarations renamed. * parser.y (vector): Follow vector_list to vec_list rename. * txr.1: Updated documentation for num-chr, chr-num, list-vector and vector-list with new names, and notes about the old names being supported, but obsolescent.
* New way of handling exceptions without unwinding.Kaz Kylheku2015-10-141-1/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (handler_bind_s): New symbol variable. (op_handler_bind): New static function. (do_expand): Traverse handler-bind forms. (eval_init): Initialize handler_bind_s variable and register handler-bind operator. * lisplib.c (except_set_entries, except_instantiate): New functions. (lisplib_init): Register new functions in dl_table. * parser.c (intr_s): New symbol variable. (repl_intr): Throw exception of type intr, rather than error. This way we can interrupt accidental exception handling loops involving exceptions derived from error. (parse_init): Initialize intr_s. * share/txr/stdlib/except.tl: New file, defines handle macro. * unwind.c (uw_push_handler): New function. (invoke_handler): New static function. (uw_throw): Search loop looks for and processes handlers in addition to catches. * unwind.h (uw_frtype_t): New enum member, UW_HANDLE. (struct uw_catch): Move member visible so it is in the same position as in struct uw_handler. (struct uw_handler): New struct type. (union uw_frame): New member ha of type struct uw_handler. (uw_push_handler): Function declared. * txr.1: Added introductory paragraphs to Exception Handling section. Documented handler-bind and handle. Some minor errors corrected.
* Hash table iterators exposed, with new macro.Kaz Kylheku2015-10-111-0/+2
| | | | | | | | | | | * eval.c (eval_init): Register hash-begin and hash-next intrinsics. * lisplib.c (hash_set_entries, hash_instantiate): New static functions. (lisplib_init): Register new tables in dl_table. * share/txr/stdlib/hash.tl: New file. * txr.1: Document with-hash-iter macro.
* Improve progn expansion.Kaz Kylheku2015-10-091-4/+13
| | | | | * eval.c (do_expand): Reduce (progn) to nil, and (progn single) to single.
* Tweaking expansions of when and until.Kaz Kylheku2015-10-091-2/+10
| | | | | | | * eval.c (me_when): Expand to if if there aren't multiple body forms. (me_unless): Simplify progn. * tests/012/struct.tl: Update string representation in struct test case.
* Adding defex macro and related functions.Kaz Kylheku2015-10-081-0/+23
| | | | | | | | | | * eval.c (me_defex, register_exception_subtypes): New static functions. (eval_init): Registered new defex macro, and register-exception-subtype and exception-subtype-p intrinsic functions. * txr.1: Documented new macro and functions.
* Adding promisep function.Kaz Kylheku2015-10-071-0/+12
| | | | | | | * eval.c (promisep): New static function. (eval_init): Registered promisep intrinsic. * txr.1: Documented promisep.
* New function, expand-right.Kaz Kylheku2015-10-061-0/+29
| | | | | | | | * eval.c (expand_right_fun, expand_right): New static functions. (eval_init): Register expand-right intrinsic. * txr.1: Documented expand-right.
* New function: ginterate.Kaz Kylheku2015-10-061-0/+31
| | | | | | | | * eval.c (ginterate_func): New static function. (ginterate): New function. (eval_init): Registered ginterate as intrinsic. * txr.1: Documented.
* New functions take, drop, {take,drop}-{while,until}.Kaz Kylheku2015-10-051-0/+6
| | | | | | | | | | | | * lib.c (take_list_fun, take_while_list_fun, take_until_list_fun): New static functions. (take, take_while, take_until, drop, drop_while, drop_until): New functions. * eval.c (eval_init): Register intrinsics take, take-while, take-until, drop, drop-while, drop-until. * txr.1: Documented.
* Allow empty loops to be interrupted by signals.Kaz Kylheku2015-10-021-0/+5
| | | | | * eval.c (eval_progn): If there are no forms to evaluate, then check for signals.
* bugfix: macro-time not bound as special operator.Kaz Kylheku2015-10-021-0/+1
| | | | | | | * eval.c (eval_init): Bind macro-time to op_error. * genvim.txr: No longer manually add macro-time to txl-orig-sym.
* bugfix: symbol-function throws on builtin macro.Kaz Kylheku2015-10-011-2/+2
| | | | | * eval.c (symbol_value): lookup_mac doesn't return a cons cell binding; don't do cdr on it.
* Fix incorrect "during expansion of ..." error reporting.Kaz Kylheku2015-09-301-1/+4
| | | | | | | | * eval.c (eval_intrinsic): Treat last_form_expanded just like last_form_evaled: save it, set to nil, and restore it. If it is not set to nil, then an evaluation error will be falsely reported as being during the expansion of that form.
* return and return-from must throw, not abort.Kaz Kylheku2015-09-251-0/+3
| | | | | | * eval.c (op_return, op_return_from): If uw_block_return doesn't find a block, and just returns, then throw an exception rather than aborting.
* Adding flatcar* function.Kaz Kylheku2015-09-191-0/+1
| | | | | | | | | | | | * eval.c (eval_init): Registered flatcar* intrinsic. * lib.c (lazy_flatcar_scan, lazy_flatcar_func): New static functions. (lazy_flatcar): New function. * lib.h (lazy_flatcar): Declared. * txr.1: Documented, also touching flatten documentation.
* New function: flatcar.Kaz Kylheku2015-09-181-0/+1
| | | | | | | | | | * eval.c (eval_init): Register flatcar intrinsic. * lib.c (flatcar): New function. * lib.h (flatcar): Declared. * txr.1: Documented.
* Remove duplicate variable initialization.Kaz Kylheku2015-09-101-1/+0
| | | | | * eval.c (eval_init): Remove duplicate initialization of with_saved_vars_s.
* Don't scan C source code for Lisp symbols.Kaz Kylheku2015-09-101-0/+3
| | | | | | | | | | | | | | * eval.c (eval_init): Register package-alist, package-name and package-symbols intrinsics. * genvim.txr: Rather than scanning C sources for TXR Lisp symbols, iterate over the packages and their symbols, collecting anything which has a binding or is self-evaluating. To get the stdlib symbols, we trigger the autoloads by doing boundp queries on a few symbols. * txr.1: Document package-alist, package-name and package-symbols.
* New functions, subtypep and typep.Kaz Kylheku2015-09-081-0/+2
| | | | | | | | | | | | | | | | * eval.c (eval_init): Register subtypep and typep. * eval.h (list_s): Existing variable declared. * lib.c (atom_s, integer_s, number_s, sequence_s, string_s): new symbol variables. (subtypep, typep): New functions. (obj_init): Initialize new symbol variables. * lib.c (atom_s, integer_s, number_s, sequence_s, string_s): Declared. * txr.1: Documented type hierarchy and the new functions.
* Don't report unbound var errors against wrong form.Kaz Kylheku2015-09-081-2/+5
| | | | | | | | | | | The issue is that eval_intrinsic doesn't clear the last_form_evaled global around the evaluation of its forms. If a symbol is evaluated, and it is an unbound variable, the error is reported against some wrong form. * eval.c (eval_intrinsic): Set the value of last_form_evaled to nil before expanding and evaluating the form, then restore the value.
* Don't show whole function definition in args mismatch.Kaz Kylheku2015-09-071-4/+11
| | | | | | * eval.c (abbrev_ctx): New static function. (bind_args): In too many/few args case, use abbrev_ctx to only show function only when it is a lambda.
* Allow evaluation from repl to be interrupted.Kaz Kylheku2015-09-061-0/+1
| | | | | | | | | | | * eval.c (do_eval): Check for pending signals. * parser.c (repl_intr): New static function. (repl): Set up signal handler for SIGINT around REPL. * signal.h (sig_deferred): declared. (sig_check_fast): New inline function/macro. A bit of a rearrangement here.
* Parenthesis sensitivity for completion.Kaz Kylheku2015-09-061-1/+1
| | | | | | | | | | | | | * eval.c (boundp): Static function becomes extern. * eval.h (boundp): Declared. * parser.c (find_matching_syms): New par parameter lets function determine whether previous character is a an open parenthesis or brace, based on which the set of possible completions is restricted. (provide_completions): Calculate the par parameter and pass to find_matching_syms.
* Syntax errors refer to REPL line number.Kaz Kylheku2015-09-051-2/+2
| | | | | | | | | | | | | | | | | | * eval.c (eval_init): Registrations of lisp-parse and read must account for new optional argument. * lib.c (func_n5o): New function. * lib.h (func_n5o): Declared. * parser.c (lisp_parse): New argument for passing in line number. This is punched into the parser object. (read_eval_stream): Call to lisp_parse defaults new argument. (repl): Pass repl line number to lisp_parse. * parser.h (lisp_parse): Declaration updated. * txr.c (txr_main): Call to lisp_parse defaults new argument.
* Fix wrongly named hash_lit_s symbol.Kaz Kylheku2015-09-011-1/+1
| | | | | * eval.c (eval_init): Fix wrong name of hash_lit_s symbol; it should be sys:hash-lit and not sys:hash-construct.
* Time structure.Kaz Kylheku2015-08-311-0/+2
| | | | | | | | | | | | | * eval.c (eval_init): Register time-struct-local and time-struct-utc intrinsic funtions. * lib.c (time_s, year_s, month_s, day_s, hour_s, min_s, sec_s): New global symbol variables. (broken_time_struct, time_init): New static functions. (time_struct_local, time_struct_utc): New functions. (init): Call time_init. * lib.h (time_struct_local, time_struct_utc): Declared.
* Introducing structs.Kaz Kylheku2015-09-021-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * args.c (args_cat_zap): New function. * args.h: (args_cat_zap): Declared. * eval.c (struct_lit_s): New symbol variable. (eval_init): Initialize struct_lit_s. * eval.h (struct_lit_s): Declared. * gc.c (finalize): If a symbol has a struct slot hash attached to it, we must free it when the symbol is reclaimed. * lib.c (make_sym): Initialize symbol's slot_cache pointer to null. (copy): Copy structure objects. (init): Call struct_init to initialize struct module. * lib.h (SLOT_CACHE_SIZE): New preprocessor symbol (slot_cache_line_t, slot_cache_t): New typedefs. (struct sym): New member, slot_cache. * lisplib.c (struct_set_entries, struct_instantiate): New static functions. (liplib_init): Register new functions in dl_table. parser.y (HASH_S): New terminal symbol. (struct): New grammar rule. (n_expr): Derive struct. (yybadtoken): Map HASH_S to #S string. parser.l (grammar): Recognize #S and return HASH_S token. share/txr/stdlib/place.tl (slot): New defplace. share/txr/stdlib/struct.tl: New file. struct.c: New file. struct.h: New file. * Makefile (OBJS): Adding struct.o.