summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* Version 195.txr-195Kaz Kylheku2018-05-046-122/+139
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* More reasonable fallback for self path.Kaz Kylheku2018-05-042-11/+5
| | | | | | | | | | | | | | | | * Makefile (opt/txr.o, dbg/txr.o): Set up TXR_REL_PATH preprocessor symbol on command line which specifies the hard installation path derived from the configure prefix. * txr.c (get_self_path): The fallback implementation simply returns TXR_REL_PATH. This will work if in fact the executable is installed at that path. What it means is that the build of TXR which uses this fallback get_self_path will not support relocation: the installation cannot be moved to another directory, yet still find its supporting files. This is better than what we are replacing: not working even in the original installation directory, if not invoked by an absolute path.
* bugfix: correcly obtain self path on Solaris.Kaz Kylheku2018-05-044-1/+30
| | | | | | | | | | | | * configure: Add detection for getexecname. * sysif.c (getcwd_wrap): Change static function to external. * sysif.h (getcwd_wrap): Declared. * txr.c (get_self_path): New implementation for Solaris using getexecname, which requires us to prepend the current directory name if the result is a relative path.
* Mac-OS: replace nonworking method of getting self-path.Kaz Kylheku2018-05-041-0/+13
| | | | | | | | | TXR's fall-back method of getting the executable's own path is broken in the Mac-OS port, which means that TXR doesn't work when invoked via PATH search. Mac-OS-specific code is required. * txr.c (get_self_path): New variant for Darwin, using the platform-specific function _NSGetExecutablePath.
* bugfix: interpreted destructuring doesn't do specials.Kaz Kylheku2018-05-031-8/+18
| | | | | | | | | | | | | | | It looks like I neglected to treat dynamically scoped variables in destructuring; all parameters are treated as lexical. This is only true in interpreted code; compiled destructuring treats dynamics properly because it generates a let to bind all the variables which occur, and then uses assignment to populate them. * eval.c (bind_macro_params): Instead of env_vbind, use the newly introduced lex_or_dyn_bind helper function. (op_tree_bind, op_mac_param_bind): Save and restore dyn_env around bind_macro_params and the evaluation of the associated body. In op_defmacro, this is already done.
* bind_args refactoring.Kaz Kylheku2018-05-031-77/+45
| | | | | | | | * eval.c (lex_or_dyn_bind_seq, lex_or_dyn_bind): New static functions. (bind_args): Eliminate repeated code using new helper functions. One wrong repetitions is thereby fixed also: a a neglected check of dyn_env_made.
* doc: break up long syntax.Kaz Kylheku2018-05-021-9/+14
| | | | | | | | * txr.1: The syntax synopses for the following functions and macros are too long and are awkwardly wrapped by man under 80 columns: make-time, make-time-utc, make-env, call-update-expander, call-clobber-expander and txr-if. Breaking up and shortening some identifiers.
* doc: fix recurring syntax formatting error.Kaz Kylheku2018-05-021-12/+12
| | | | | | * txr.1: I spotted a problem in the syntax synopsis of remq, remql and remqual. The same mistake was made in a few other places. remq* also had an error, though different.
* expander: remove pspecials from param expansionKaz Kylheku2018-05-011-29/+11
| | | | | | | | | * eval.c (expand_opt_params_rec, expand_params_rec): Remove pspecials argument, and accumulation of the special variables. The caller doesn't use this list any more. (expand_params): Remove unused specials local variable whose address was passed as the pspecials argument to expand_params_rec.
* compiler: correct semantics of special var args.Kaz Kylheku2018-05-011-7/+15
| | | | | | | | | | | | | | | | | | | The same, correct semantics for special variables in function arguments get implemented in the compiler. * share/txr/stdlib/compiler.tl (compiler comp-lambda): We stick with the strategy that each parameter which is a special variable is aliased by an anonymous lexical variable. The difference is that we bind the underlying special variable from the hidden lexical's value as early as possible. The overall processing is rearranged. On entry into the function, if any of the required arguments are specials, their values are immediately bound to the special variables in a new environment. Then the optional arguments are processed, and they bind specials in the dynamic environment also. Previously, the specials were bound in one fell swoop after processing the optionals, leading to the same incorrect semantics that the interpreter code had.
* interpreter: correct semantics of special var args.Kaz Kylheku2018-05-013-60/+92
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this patch we eliminate the special operator sys:with-dyn-rebinds, and implement correct semantics for dynamically scoped variables that occur in argument lists. * eval.c (with_dyn_rebinds_s): Symbol variable removed. (bind_args): Handle special variables dynamically: for each symbol that appears, check whether it is a special and treat accordingly by allocating a new dynamic environment if necessary, and binding in that environment. This adds overhead, which is why I moved away from this approach in the past. But now that there is a compiler, overhead in the interpreter matters less. Correct semantics is more important. (expand_params): Greatly simplified for not having to wrap the sys:with-dyn-rebinds operator around the body. (funcall_interp): Since bind_args can now extend the dynamic environment, it is necessary to save and restore dyn_env around it. Another call to bind_args occurs in op_catch; that already saves and restores dyn_env. (op_with_dyn_rebinds): Static function removed. (do_expand): with-dyn-rebinds-s case removed. (eval_init): Removed interning of sys:with-dyn-rebinds symbol and registration of special op. * protsym.c: Regenerated. * compiler.tl (compiler compile): Remove case which handles sys:with-dyn-rebinds.
* expander: regression in param list treatment.Kaz Kylheku2018-04-301-8/+5
| | | | | | | | | | | | | | | | | | | | | | | | | Change ca6199a that went into TXR 191 was over-zealous in suppressing expand_param_rec calls for non-macro argument processing. The recursive calls are needed in order to detect parameters that are special variables and add them to pspecials. The upshot is that usage such as the following broke: (lambda (*stdout*) ...) because expand_param_rec isn't called on the *stdout* symbol and *stdout* is thus not noted as a special variable, and thus the expander then neglects to produce (sys:with-dyn-rebinds (*stdout*) ...) around the body of the lambda. The new compiler introduced at the same time made this harder to find. Why? Because the compiler ignores the sys:with-dyn-rebinds special form; it implements its own handling for specials in lambda and let! So compiled code is unaffected by this regression. * eval.c (expand_opt_params_rec): Call expand_params_rec on the car of the optional var-init pair, whether or not expanding a macro style parameter. (expand_params_rec): Call expand_params_rec recursively on any parameter that is bindable whether or not in macro mode. The two cases fold together again, and so here we see that the recent fix d934a3e was also a regression caused by ca6199a.
* Version 194.txr-194Kaz Kylheku2018-04-304-3/+22
| | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise.
* Makefile: use order-only between early and late tlo-s.Kaz Kylheku2018-04-291-1/+1
| | | | | | | | | * Makefile: make STDLIB_EARLY_TLOS order-only prerequisites of STDLIB_LATE_TLOS, rather than conventional prerequisites. This means that the early tlo-s are built or rebuilt before the late ones, but there is no other dependency expressed: an update of early tlo-s doesn't force late tlo-s to be out-of-date and updated also.
* compiler: improve wording of destructuring errors.Kaz Kylheku2018-04-291-10/+16
| | | | | | | * share/txr/stdlib/error.tl (sys:bind-mac-error, sys:bind-mac-check): Improve error messages with better wording. Use ~a for rendering parameter syntax so sys: package prefixes don't appear.
* bugfix: include most negative two's in cnum range.Kaz Kylheku2018-04-292-3/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The INT_PTR_MIN value isn't the smallest value actually representable in cnum, because it is just the additive inverse of INT_PTR_MAX. In two's complement, the INT_PTR_MIN-1 value is still representable. But we are excluding it. If a Lisp integer has the value INT_PTR_MIN-1, the c_num function will fail to convert it to a cnum. This situation occurs in FFI, where code may expect that the Lisp value #x-80000000 can convert to an external 32 bit integer type. This will be done by way of a conversion to cnum first via c_num (see ffi_i32_put for instance, which calls c_i32 which relies on c_num). * arith.c (INT_PTR_MAX_SUCC_MP): New static variable. This holds a bignum equivalent to INT_PTR_MAX + 1. (in_int_ptr_range): We now check whether the value against the range [-(INT_PTR_MAX + 1), (INT_PTR_MAX + 1)] and then check all possible return values. The MP_LT case is clearly in range, and MP_GT is out of the range. The interesting situation is MP_EQ: in that case we just test the sign to see whether we are looking at -(INT_PTR_MAX + 1). (int_flo): INT_PTR_MIN is referenced in this function, so we use INT_PTR_MIN - 1 instead. This allows that value to be handled via the simple bignum(n) case. (arith_init): Initialize INT_PTR_MAX_SUCC_MP. We cannot initialize it to INT_PTR_MAX + 1 directly because that expression overflows: insted we use INT_PTR_MIN - 1 and then flip the resulting bignum's sign. (arith_free_all): Call mp_clear on the new variable to release its digit buffer. * ffi.c (make_ffi_type_enum): Use INT_PTR_MIN - 1 as the initial value of the highest variable, to accurately calculate the range of the enum values if they contain INT_PTR_MIN - 1.
* compiler/assembler: bugfix: bignums can't be immediate ops.Kaz Kylheku2018-04-292-2/+2
| | | | | | | | | | | | | | | | | * share/txr/stdlib/asm.tl (assembler immediate-fits-type): Do not include bignum types as candidates for immediate operand. We take the sys:bits representation of the object, and that of course is a pointer. This case actually happens on 32 bit platforms because the value that is one less than the most negative fixnum still fits into the fixnum representational range, due to the way two's complement works, but is actually a bignum. Concretely, the value #x-20000000 is a bignum, but its width is 29, which falsely suggests that its representation can fit into 32 bits as a literal. * share/txr/stdlib/compiler.tl (compiler comp-atom): Test for fixnum here rather than integerp, so in the above discussed case, we don't generate a movi instruction.
* asm: improve bad immediate diagnostic.Kaz Kylheku2018-04-281-1/+1
| | | | | * share/txr/stdlib/asm.tl (bits-to-obj): Show the bad immediate operand in hex.
* compiler: bugfix: wrong immediate op width calculation.Kaz Kylheku2018-04-281-1/+1
| | | | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-atom): The calculation which determines whether an integer operand fits into an immediate move instruction is incorrect. The width function doesn't include a sign bit, so that must be counted. Also, the immediate operand includes a two bit type tag: thus we are off by three.
* Version 193.txr-193Kaz Kylheku2018-04-267-594/+635
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim, protsym.c: Regenerated.
* build: fix failure due to .tlo compilation order.Kaz Kylheku2018-04-261-0/+6
| | | | | | | | | | | | | On newer GNU Make versions, $(wildcard ...) doesn't sort its results, and so we compile .tlo files in an arbitrary order. For the most part, this is fine. However, there is a complicated circular dependency involving the error.tl file requiring it to be compiled first. * Makefile (STLIB_EARLY_PATS, STDLIB_EARLY_TLOS, STDLIB_LATE_TLOS): New variables. Use these to express a dependency which causes error.tlo to be built first.
* vm: heap corruption bug.Kaz Kylheku2018-04-251-1/+1
| | | | | | | | | | | | * vm.c (vm_execute_toplevel): Fix data vector being assigned to the wrong display frame, leaving vm.dspl[1].vec uninitialized. Why is that a problem? Because the VM depends on these vectors when performing the vm_set operation: if a frame register is stored, and the frame has an associated vector, mut_obj is invoked on that vector. Now that there exists the load-time operator, the d regs (which live in dspl[1]) can be mutated. That causes mut_obj to be called with garbage. This was all discovered during testing on PPC64.
* compiler: replace "$" package hack.Kaz Kylheku2018-04-254-12/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | When compile-file writes emits the file, it does so with *package* bound to a temporary package named "$" so that all the symbols get fully qualified. Problem is, this is a valid package name and is added to the package list. While the package exists, symbols such as $:a could be interned. If such symbols occur in code being compiled, they get emitted using unqualified names. Let's introduce an internal interface for making an anonymous package which isn't on the list of package, and which has a name that results in bad syntax if it occurs in print. * eval.c (eval_init): Register sys:make-anon-package intrinsic. * lib.c (make_package_common): New static function. (make_package): Package construction and initialization code moved into make_package_common. (make_anon_package): New function. * lib.h (make_anon_package): Declared. * share/txr/stdlib/compiler.tl (usr:compile-file): When writing out translation, bind *package* to anonymous package from sys:make-anon-package.
* vm: de-inline opcode dispatch.Kaz Kylheku2018-04-252-41/+43
| | | | | | | | | | | | | | | | | | | The vm_execute function is heavily inlined by gcc, and requires almost 500 bytes of stack space. The stack space really adds up when the vm re-enters itself recursively. Also, pointers to garbage can hide in areas of that bloated stack frame that are not being used by execution paths, adding to the spurious retention problem. * lib.h (NOINLINE): New preprocessor symbol. * vm.c (vm_prof, vm_frame, vm_sframe, vm_dframe, vm_end, vm_fin, vm_call, vm_apply, vm_gcall, vm_gapply, vm_movrs, vm_movsr, vm_movrr, vm_movrsi, vm_movsmi, vm_movrbi, vm_if, vm_ifq, vm_ifql, vm_swtch, vm_uwprot, vm_block, vm_no_block_err, vm_retsr, vm_retrs, vm_retrr, vm_abscsr, vm_catch, vm_handle, vm_getsym, vm_getbind, vm_setsym, vm_bindv, vm_close, vm_execute): Apply INLINE to functions.
* vm: null out variable arg list.Kaz Kylheku2018-04-251-1/+1
| | | | | * vm.c (vm_execute_closure): Null out the vargs local to prevent spurious retention.
* vm: destroy t-reg values used as call args.Kaz Kylheku2018-04-241-17/+25
| | | | | | | | | | Whe the compiler uses t-regs as function call arguments, they are t-regs that have no next use and can be nulled out. We do this to prevent false retention. * vm.c (vm_getz): New function. (vm_call, vm_apply, vm_gcall, vm_gapply): Use vm_getz for fetching arguments.
* compiler: implement eliding of blocks.Kaz Kylheku2018-04-242-13/+139
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It is time-wasting to have a block in every function. In this patch we have the compiler eliminate blocks if it is obvious that they will not be the targets of any exits or continuation captures through any direct function calls. If a block contains only calls to library functions, and doesn't call certain functions, then it is removed. It is possible for this removal to be strictly wrong and different from interpreted code. This is true if the code enclosed in a block invokes a function indirectly or via a quoted symbol, and that function tries to return from the block or capture a continuation using that block as a prompt. Such a call doesn't prevent the block from being removed. For instance, this won't work in compiled code any more: (defun tricky (fun) (call fun)) (tricky (lambda () (return-from tricky 42))) The call function is considered safe; the (call fun) form doesn't prevent the block inside the tricky function from being removed. * share/txr/stdlib/compiler.tl (blockinfo): New struct. (env): New slot, bb. (env lookup-block, env extend-block): New methods. (%block-using-funs%): New global variable. (compiler comp-block): Implement the elision of the block based on what free functions are referenced in the body, and whether the block is referenced lexically. Also, bind the block in the environment using the bb member in the env structure. (comp-return-from): Lookup the block lexically and mark it as used. (system-symbol-p): New function. * txr.1: Document the rules for elision of blocks.
* compiler: compile-file/load-time integration fix.Kaz Kylheku2018-04-241-1/+1
| | | | | | | | | | | | | | | The issue is that when load-time forms are present in top-level forms, the execution of those forms destructively manipulates the data table. This is bad when we intend to write out the compiled forms into a file; we need to write them out in their freshly compiled state before these side effects took place. * share/txr/stdlib/compiler.tl (list-from-vm-desc): When serializing the compiled VM pieces to a list, make a freshly allocated shallow copy of the data vector. This could be optimized away if we know that the VM doesn't contain load-time effects.
* compiler: called function must be listed as free.Kaz Kylheku2018-04-241-4/+6
| | | | | | | | | When compiling a plain (f x) function call, the resulting frag must list f as a free function. * share/txr/stdlib/compiler.tl (comp-fun-form): Compile the call with comp-call-impl; then pushnew the symbol into the frag's ffuns set list.
* compiler: bug: return miscompiled as abscond.Kaz Kylheku2018-04-241-1/+1
| | | | | | | | | | Oops; (return x), equivalent to (return-from nil x), is being miscompiled as if it were (sys:abscond-from nil x). * share/txr/stdlib/compiler.tl (comp-return): When short-circuit-recursing into comp-return-from, put return-from into the operator position, because that function checks for that symbol.
* autoload: few autoload entries needed.Kaz Kylheku2018-04-241-1/+22
| | | | | | | | | | | | | | | | | | With the advent of compiled code, problems are exposed in the autoloader. We can no longer rely on the reference to a macro to load a dependent module. Macros go away during compiling, leaving behind functions. References to those functions have to trigger autoloading. * lisplib.c (place_set_entries): Add new table of sys: functions, containing sys:get-fun-getter-setter, sys:get-mb, sys:get-vb and sys:register-simple-accessor. These seem to be all the macro run-time-support functions in place.tl. (struct_set_entries): Add sys:rslotset. (yield_set_entries): Add sys:obtain-impl. (trace_set_entries): Add sys:trace and sys:untrace. (keyparams_set_entries): Add sys:extract-keys.
* compiler: streamline destructuring error checks.Kaz Kylheku2018-04-233-93/+92
| | | | | | | | | | | | | * lisplib.c (error_set_entries): Add sys:bind-mac-check to autoload list for error.tl * compiler.tl (expand-bind-mac-params): For strict mode, use the new sys:bind-mac-check function to do the check and report the error. For non-strict checks, consolidate the error check by taking advantage of n-ary nature of <= function. * error.tl (sys:bind-mac-check): New function.
* New macro: load-time.Kaz Kylheku2018-04-235-10/+367
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is similar to the ANSI CL load-time-value. * eval.c (load_time_s, load_time_lit_s): New symbol variables. (op_load_time_lit, me_load_time): New static functions. (eval_init): Intern load-time symbol and sys:load-time-lit. Register the sys:load-time-lit special operator and load-time macro. * share/txr/stdlib/asm.tl (assembler parse-args): We must now allow the d registers to be the targets of a mov instruction, because load-time depends on being able to mutate the data vector, in order to turn the result of a calculation into a de facto literal. * share/txr/stdlib/compiler.tl (compiler): New member, lt-frags. (compile-in-toplevel): New macro. (compiler alloc-dreg): New method. (compiler compile): Handle sys:load-time-lit special form via comp-load-time-lit method. (compiler comp-load-time-lit): New method. (usr:compile-toplevel): Prepend the load-time assembly code fragments to the compiled assembly code. * vm.c (vm_set, vm_sm_set): Do not reject an attempt to modify the static data, since load-time now generates mov instructions targetting the d registers. * txr.1: Document load-time.
* compiler: remove unused slot.Kaz Kylheku2018-04-231-1/+0
| | | | | * share/txr/stdlib/compiler.tl (compiler): Remove the nreg slot. It is not referenced anywhere.
* compiler: better diagnostic about d-reg exhaustion.Kaz Kylheku2018-04-231-1/+1
| | | | | | | * share/txr/stdlib/compiler.t (compiler get-dreg): Replace "out of registers" message with something more pertinent. The problem is that the code has too many literals for the maximum table size.
* compiler: unnecessary let*.Kaz Kylheku2018-04-231-1/+1
| | | | | * share/txr/stdlib/compiler.tl (compiler get-dreg): A let* with just one variable in it is changed to let.
* compiler: tighter code for quasiliterals.Kaz Kylheku2018-04-213-11/+19
| | | | | | | | | | | | | | | | | | | | | | | | Give the sys:fmt-simple function argument defaulting so the generated code doesn't have to call it with all five arguments present, four of them nil being much of the time. * eval.c (fmt_simple): Default all but the first four arguments. (eval_init): Re-register sys:fmt-simple as having only one required argument. * parser.c (read_file_common): Load version 1 or 2 files. We are bumping the object file version to 2 because now when we compile files, they won't work with older TXR in which all five arguments to sys:fmt-simple are required. * share/txr/stdlib/compiler.tl (expand-quasi-mods): Generate the sys:fmt-simple call with just enough arguments to express the modifiers that were decoded. (sexpand-quasi-args): Reduce the trivial modifier-less sys:fmt-simple calls to just one argument. (%tlo-ver%): Bump major version to 2.
* awk: bug: multiple expansion in redirection macros.Kaz Kylheku2018-04-211-2/+3
| | | | | | share/txr/stdlib/awk.tl (sys:awk-redir): Put the unused gensym to use: evaluate the path expressio nonce into the gensym variable. Also move strangely place comma.
* Version 192.txr-192Kaz Kylheku2018-04-197-712/+764
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim, protsym.c: Regenerated.
* doc: continuations: compiled vs interpreted.Kaz Kylheku2018-04-191-1/+38
| | | | | | | | * txr.1: Turn the comparison with lexical closures into a named subsection instead of Notes. Add subsection about mutated lexical variables and continuations: how the behavior can differ between interpreted and compiled code. Point user to the hlet and hlet* macros.
* new macros: hlet, hlet*.Kaz Kylheku2018-04-193-1/+51
| | | | | | | | | | * lisplib.c (yield_set_entries): Add hlet and hlet* to autoload list. * share/txr/stdlib/yield.tl (hlet-expand): New function (hlet, hlet*): New macros. * txr.1: Documented.
* asm: disassemble: three digits in t and d regs.Kaz Kylheku2018-04-191-3/+3
| | | | | | | | share/txr/stdlib/asm.tl (operand-to-sym): Print t and d registers with three digits, like is done with the index portion of v regs already. (disassemble-cdf): Print three-digit d regs in data table dump.
* compiler: don't expand top-level forms twice.Kaz Kylheku2018-04-182-5/+15
| | | | | | | | | | * share/txr/stdlib/compiler.tl (usr:compile-toplevel): Support optional parameter indicating that no expansion is required. (usr:compile-file): Call compile-toplevel with a t argument for the new expanded-p parameter, so no further expansion takes place. * txr.1: Document new optional parameter of compile-toplevel.
* compiler: bugfix: miscompiled unwind-protect.Kaz Kylheku2018-04-181-5/+3
| | | | | | | | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-unwind-protect): The protected code must terminate with an end instruction. It cannot just branch to the skip label because then we keep executing the following unprotected code still under the unwind protect. How it works is that the protected code ends with end. Then the cleanup fragment at the cleanup offset is executed, also terminating with an end (that one we have in place). We don't need the skip label because the instruction pointer advances after executing the end instruction after the cleanup fragment.
* asm: disassembler v-reg regression.Kaz Kylheku2018-04-181-2/+2
| | | | | | | * share/txr/stdlib/asm.tl (operand-to-sym): To form v registers, we must subtract 2 from the level, not add. (operand-to-exp): Bug was propagated to this new function, too.
* dot-to-apply: optimize out call function.Kaz Kylheku2018-04-181-4/+11
| | | | | | | | | | | | | | | | | When a dotted form like (call x ... . z) is subject to the dot-to-apply transformation, this results in (apply (fun call) x ... . z). The (fun call) is useless and can be removed. Therefore, what we do is remove occurrences of call from the original form. * eval.c (dot_to_apply): Remove leading occurrences of call. Since this promotes the second or subsequent form into the operator position, we must be careful; if we are doing a Lisp-2 form, only the first element requires wrapping in (fun ...) when turned into an apply argument. The second and subsequent arguments are subject to ordinary evaluation and so if any of those becomes the operator, it doesn't need (fun ...) wrapping.
* apply: remove remaining apply_intrinsic uses.Kaz Kylheku2018-04-183-8/+2
| | | | | | | | | * eval.c (apply_intrinsic): Function removed. (to_apf): Use applyv instead of apply_intrinsic. * eval.h (apply_intrinsic): Declaration removed. * vm.c (vm_gapply): Use applyv instead of apply_intrinsic.
* apply: eliminate wasteful consing.Kaz Kylheku2018-04-183-3/+14
| | | | | | | | | | | | | | | | | | | | Now (pprof (apply '+ 1 2 3 4 5 '(6 7))) shows zero bytes consed. Previously 176 (on 32 bit). This is the same whether the expression is compiled or interpreted. * eval.c (applyv): Rewritten to efficiently manipulate the args and call generic_funcall directly. The consing funcction apply_intrinsic_frob_args is only used when args contains a trailing list (args->list) and is only used on that trailing list, not the entire arg list. Also, changing the static function to external. * eval.h (applyv): Declared. * vm.c (vm_apply): Use applyv instead of wastefully converting the arguments to a consed list and going through apply_intrinsic.
* apply: diagnose missing argument.Kaz Kylheku2018-04-181-1/+3
| | | | | | | | The <trailing-args> argument is required in apply and iapply; and that is documented. * eval.c (apply_intrinsic_frob_args): Check for args being empty and throw.
* compiler: de-duplicate switch.Kaz Kylheku2018-04-181-11/+18
| | | | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-switch): Identify duplicate cases and don't generate code for these; patch their table entries to point to one case. The case macros generate such code when the keys are integers, and multiple integer keys are associated with the same case: (caseq x ((1 2 3 4 5) ...) ((6 7) ...)).