summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* autoload: add more missing symbols.Kaz Kylheku2018-04-061-1/+12
| | | | | | | | | | | | If user code interns these symbols before the autoload takes place, things will misbehave. For instance if user code interns a symbol called "rng" in its own package, not usr, and then awk is loaded, then using (rng ...) in that awk macro won't work. * lisplib.c (ifa_set_entries): Add the it symbol. (awk_set_entries): Add numerous symbols to the intern list: all of the awk special variables and awk functions/macros.
* structs: get rid of sys:slot and sys:static-slot.Kaz Kylheku2018-04-063-10/+8
| | | | | | | | | | | | | | | | * share/txr/stdlib/struct.tl (defstruct, sys:check-slot, defmeth): Use slot rather than sys:slot as indicator in tentative defs. * struct.c (static_slot_s): Variable removed. (struct_init): slot_s initialized with symbol in user package, rather than system package. Initialization of static_slot_s removed. Existing slot function now registered using slot_s. (static_slot_type_reg): Remove reference to static_slot_s. This was a dud all along; nothing publishes deferred warnings against this symbol. * protsym.c (protected_sym): Remove static_slot_s.
* autoload: smattering of missing/wrong entries.Kaz Kylheku2018-04-061-1/+4
| | | | | | | * lisplib.c (place_set_entries): add missing pinc and pdec. Fix misspelled define-accessor. (sock_set_entries): Add missing iinaddr-any, inaddr-loopback, in6addr-any and in6addr-loopback.
* autload: remove copy and pasted sock_load_init calls.Kaz Kylheku2018-04-061-3/+0
| | | | | | | * lisplib.c (termios_instantiate, awk_instantiate, build_instantiate): Remove sock_load_init calls which make no sense in these functions. This is the result of flurried copy and pasting.
* trace: add missing copyright header.Kaz Kylheku2018-04-051-0/+26
| | | | * trace.tl: File was introduced in 2016, so 2016-2018.
* lib: get rid of preprocessor macros for packages.Kaz Kylheku2018-04-054-20/+14
| | | | | | | | | | | | | | | | | | | | | | | The identifiers user_package, system_package and keyword_package are preprocessor symbols that expand to other preprocessor symbols for no good reason. Time to get rid of this. * lib.c (system_package_var, keyword_package_var, user_package_var): Variables renamed to system_package, keyword_package and user_package. (symbol_package, keywordp, obj_init): Fix variable references to follow rename. * lib.h (keyword_package, user_package, system_package): Macros removed. (system_package_var, keyword_package_var, user_package_var): Variables renamed. * eval.c (eval_init): Fix variable references to follow rename. * parser.y (sym_helper): Likewise.
* build: support compiling stdlib.Kaz Kylheku2018-04-051-5/+30
| | | | | | | | | | | | * Makefile (STDLIB_SRCS, STDLIB_TLOS, STDLIB_TLOS2): New variables. (COMPILE_TL): New recipe macro. (%.tlo, %.tlo2): New pattern rules. (all): Depend on new stage1 and stage2 targets. (stage1, stage2): New phony targets. (clean): Add clean-tlo dependency. (clean-tlo): New phony target. (install): Install .tlo files also.
* configure: link files rather than dirs.Kaz Kylheku2018-04-051-1/+36
| | | | | | | | | | | | * configure (lndir): New function; imitation of same-named utility from the X11 distribution. Using lndir, instead of creating, in the build directory, symlinks for the tests and shared directories pointing back to the source tree, we mirror the directory structure of these directories and populate it with individual file symlinks. Motivation: this will allow us to build .tlo object files in these directories side by side with .tl files, without touching the source tree.
* printer: improve object formatting.Kaz Kylheku2018-04-0510-17/+62
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There is an issue with the printer in that it produces output whereby objects continue on the same line after a multi-line object, e.g: (foo (foobly bar xyzzy quux) (oops same line)) rather than: (foo (foobly bar xyzzy quux) (oops same line)) There is a simple fix for this: set a flag to force a line break on the next width-check operation whenever an object has been broken into multiple lines. width-check can return a Boolean indication whether it generated a line break, and so aggregate object printing routines can tell whether their object has been broken into lines, and set the flag. * stream.h (struct strm_base): New member, force_break. (force_break): Declared. * stream.c (strm_base_init): Extent initializer to cover force_break flag. (put_string, put_char): Clear the force_break flag whenever we hit column zero. (width_check): If indent mode is on, and force_break is true, generate a break. Clear force_break. (force_break): New function. (stream_init): Register force-break intrinsic. * buf.c (buf_print): Set the force break flag if the buffer was broken into multiple lines. * hash.c (hash_print_op): Set the force break flag if the hash was broken into multiple lines. * lib.c (obj_print_impl): Same logic for lists. * struct.c (struct_inst_print): Same logic for structs. * tests/009/json.expected, tests/011/macros-2.expected, tests/012/struct.tl, tests/017/glob-zarray.expected: Update expected textual output to reflect new formatting.
* compile-file: handle gensyms and such.Kaz Kylheku2018-04-052-13/+23
| | | | | | | | | | | | | | | | | | | * parser.c (read_file_common): The entire compiled representation is now one big list. We must walk the list to visit the individual compiled top-level forms. * share/txr/stdlib/compiler.tl (compile-file): Collect all the compiled top-level forms into one list, and emit it as one object. This way, gensym references among the items will resolve; for instance tests/012/man-or-boy.tl now compiles. That file defines a function named by a gensym, and a macro which expands to calls to that function. These end up in separate top-level forms and have to resolve. Because we are emitting everything as one big object, we cannot rely on (in-package ...) forms influencing the reading of the symbols. So we create a dummy package and switch to that during the writing, which forces all symbols to be fully qualified.
* compile-file/load: add version to files.Kaz Kylheku2018-04-052-1/+10
| | | | | | | | | | * parser.c (read_file_common): Treat first form in file as a version number of the form (major minor), where major nad minor are non-negative integers. If the major number is greater than zero, reject the file as incompatible. * share/txr/stdlib/compiler.tl (usr:compile-file): Emit version number (0 0) as the first item in a compiled file.
* compiler: bugfix: quasilit cannot use append.Kaz Kylheku2018-04-042-1/+7
| | | | | | | | | | | append is too generic, and produces nil sometimes. Let's use a custom run-time support function sys:fmt-join. * eval.c (fmt_join): New function. (eval_init): Intern sys:fmt-join. * share/txr/stdlib/compiler.tl (expand-quasi): Generate a sys:fmt-join call to combine the pieces rather than append.
* load: remove hack for loading compiler.tlo.Kaz Kylheku2018-04-041-2/+1
| | | | | | | * parser.c (read_file_common): Remove the check whether the data vector is a list (due to have been converted to sys:vector-lit by the presence of unquotes). This doesn't happen any more, thanks to the previous parser commit.
* parser: don't generate special lits outside quasiquote.Kaz Kylheku2018-04-043-9/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The parser generates a sys:hash-lit, sys:struct-lit or sys:vector-lit whenever a hash, struct or vector literal contains unquotes. This allows the quasiquote expander to treat these objects as ordinary list structure when interpolating inside them, and then recognize these symbols and construct the implied real objects. The issue is that these literals are generated even if the unquotes occur outside of a backquote. For instance if a vector literal like #(,a) occurs out of the blue, not in any backquote, this is still a (sys:vector-lit (sys:unquote a)) and not an actual vector. The issue is compounded because this substitution takes place even if there is no actual comma or splice notation. Even the following is a sys:vector-lit: #((sys:unquote x)). In any case, it causes problems for compiled files, because such material can occur in the data vector of a compiled toplevel form. In this patch we modify the parser to keep track of the quasiquote/unquote level. The special literals are generated only when the object occurs inside a quasiquote. * parser.h (struct parser): New member, quasi_level. * parser.c (parser_common_init): Initialize the parser's new quasi_level member. * parser.y (vector, hash, struct): To decide whether to generate the special literal, don't just check whether unquotes occur in the list. Check that we are in a quasiquote, indicated by the quasiquoting level being positive. (i_expr, n_expr): Use a mid-rule actions on the quasiquote, unquote and splice rules to bump the quasiquoting level in one direction before recognizing the object, and then bump in the opposite direction when reducing the rule. (parse): Initialize quasi_level.
* hash: with-hash-iter bug found by new compiler.Kaz Kylheku2018-04-041-2/+2
| | | | | | | | The compiler barfed on hash.tl, reporting an if form with too many arguments in the with-hash-iter macro, indicating that it's basically broken. * share/txr/stdlib/hash.tl (with-hash-iter): Repair the macro.
* compiler: bugfix: broken Lisp forms in quasiquote.Kaz Kylheku2018-04-041-1/+1
| | | | | | | | * share/txr/stdlib/compiler.tl (expand-quasi-args): When the element of the quasiquote is a compound form, we can't just return it. Firstly, because we are appending, we must wrap each returned item in a list. Secondly, we must wrap the form in code which formats it into a string consistently.
* stdlib: remove macro-time.Kaz Kylheku2018-04-043-22/+19
| | | | | | | | | | | | | | These top-level macro-time forms are preventing code from being compiled. * share/txr/stdlib/ifa.tl: Remove macro-time around sys:if-to-cond function. * share/txr/stdlib/package.tl: Remove macro-time around sys:name-str. * share/txr/stdlib/struct.tl: Remove macro-time around sys:bad-slot-syntax and sys:prune-missing-inits.
* compiler: move sys:bind-mac-error to error.tl.Kaz Kylheku2018-04-043-8/+13
| | | | | | | | | | | | | | | | | | | | | | | The sys:bind-mac-error function is a run-time support function for the compiler-generated code for destructuring. But the compiler.tl source file is a bad place for it. It means that compiled modules which need sys:bind-mac-error auto-load the entire compiler. That easily creates an irresolveable cycle, because the compiler is on top of the foodchain. No, sys:bind-mac-error belongs in error.tl; the light-weight module of low-dependency run-time support routines for error reporting. * lisplib.c (error_set_entries): Add sys:bind-mac-error symbol here. (compiler_set_entries): Remove it from here. * share/txr/stdlib/compiler.tl (sys:bind-mac-error): Function removed. * share/txr/stdlib/error.tl (sys:bind-mac-error): Function moved here.
* struct: autoload sys:define-method.Kaz Kylheku2018-04-041-0/+4
| | | | | | | | | | Compiled code references sys:define-method directly without going through the struct macrology that would otherwise trigger the autoload of the struct stuff. The symbol needs to be added to the set of triggers. * lisplib.c (struct_set_entries): Add sys:define-method symbol.
* autoload: don't refer to .tl files specifically.Kaz Kylheku2018-04-043-32/+32
| | | | | | | | | | | | | | | | | | | | | | | We would like to load the compiled versions of the library files, if they exist, in preference to the source versions. So we want to issue loads without the .tl suffix; let the load function sort it out. * gencadr.c (cadr_register): Drop .tl suffix. * lisplib.c (place_instantiate, ver_instantiate, ifa_instantiate, txr_case_instantiate, with_resources_instantiate, path_test_instantiate, struct_instantiate, with_stream_instantiate, hash_instantiate, except_instantiate, type_instantiate, yield_instantiate, termios_instantiate, awk_instantiate, build_instantiate, trace_instantiate, getopts_instantiate, package_instantiate, getput_instantiate, tagbody_instantiate, pmac_instantiate, error_instantiate, keyparams_instantiate, ffi_instantiate, doloop_instantiate, stream_wrap_instantiate, asm_instantiate, compiler_instantiate, op_instantiate): Likewise. * cadr.c: Regenerated.
* eval: define sys:*load-recursive*Kaz Kylheku2018-04-041-0/+1
| | | | | | | | | * eval.c (eval_init): The existing variable sys:*load-recursive* is formally defined. This is necessary if a form is evaluated from the command line using -p or -e, which somewhere accesses this variable. txr_main sets up the variable dynamicaly, but later. It should have an entry for it in the global environment.
* regex: fix double free corruption bug.Kaz Kylheku2018-04-041-11/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Unfortunately, the nfa_state_free function doesn't check the static flag on a character set and just calls chr_set_destroy. So when one of the static character sets is planted into the NFA graph, when that graph is garbage-collected, it blows away the static character set. Then when that happens twice for the same set, boom! We make an alteration to make the destruction more defensive. Callers of char_set_destroy are no longer saddled with the responsibility of honoring the static flag buried in the object. Instead, that function itself check the static flag. An argument is provided to force the deletion in spite of the static flag; that is needed for the global cleanup of the static states. (Only occurs if txr is run with --free-all and cleanly exited.) * regex.c (char_set_destroy): Take extra argument, force. If the set is marked static, then do nothing, unless force is nonzero. (char_set_cobj_destroy): Don't check the static flag, just call char_set_destroy, force zero. (nfa_state_free): Add force zero argument to char_set_destroy call. The double free bug is thereby fixed here; static sets are protected. (regex_free_all): Force all the char_set_destroy calls here.
* regex: read/print bug: escaped double quote.Kaz Kylheku2018-04-043-6/+11
| | | | | | | | | | | | | | | | | | | Because the regex printer wrongly uses out_str_char (for the sake of borrowing its semicolon-notation processing) when a regex prints, all characters that require escaping in a string literal get escaped, which includes the " character. Unfortunately the \" sequence which results is rejected by the regex parser. * lib.c (out_str_char): Kludge: add extra argument to distinguish regex use versus string use, and treat the double quote accordingly. (out_str_readable): Give 0 arg to new param of out_str_char. * lib.h (out_str_char): Declaration updated. * regex.c (print_class_char, print_rec): Pass 1 to new param of out_str_char.
* Implement compiled file loading.Kaz Kylheku2018-04-045-11/+64
| | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (load): If open_txr_file indicates compiled file by setting txr_lisp_p to character #\o, use read_compiled_file. * match.c (v_load): Likewise. * parser.c (open_txr_file): Recognize the .tlo suffix, and also try to open a .tlo version of an unsuffixed file before trying it as .tl. Indicate a .tlo file by setting txr_lisp_p to the character #\o rather than t. (read_file_common): New static function, made from contents of read_eval_stream. Will either evaluate forms or load compiled code by instantiating virtual machine descriptions and performing their top-level execution. (read_eval_stream): Now a wrapper for read_file_common. (read_compiled_file): New function. * parser.h (read_compiled_file): Declared. * txr.c (help): List new --compiled option. (txr_main): If --compiled is specified, set txr_lisp_p to #\o to load as compiled code. Update error message that -c is not compatible with --lisp or --compiled. If txr_lisp_p is #\o, then use read_compiled_file.
* asm: changes for compiling.Kaz Kylheku2018-04-041-19/+20
| | | | | | | | | * share/txr/stdlib/asm.tl (assembler): Wrap with compile-only so we don't redefine this struct while we are compiling the assembler. (%oc-code%): Use defparml so this is reset to zero, so that the opcodes are numbered from zero instead of the most recent value left in the variable.
* compile-file: don't compile constants.Kaz Kylheku2018-04-041-1/+2
| | | | | | * share/txr/stdlib/compiler.tl: Skip top-level forms which are just constants. Their value is discarded and they have no effect.
* compiler: don't add compile-time gensym into env.Kaz Kylheku2018-04-041-3/+3
| | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-tree-case): The block name isn't a lexical variable; do not add it to nenv via extend-var. Just bind to gensym directly and insert where needed. This reduces the run-time frame size by one entry.
* macro param lists: remove colon hack.Kaz Kylheku2018-04-043-8/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Going forward, when : appears as the argument of an optional parameter in destructuring, it is treated as an ordinary object, and not as "this argument is missing". That is now a feature of function calls only. Rationale: interferes with macros. For instance, the pattern (test : then else) doesn't correctly express the arguments of if, because (if x y :) eats the semicolon. The defaulting behavior is not useful because usually there is no default value for optional structure, other than nil. * eval.c (bind_macro_params): Only implement the colon hack under compatibility with 190. * share/txr/stdlib/place.tl (defplace gethash, defplace fun, defplace symbol-function, defplace symbol-macro, defplace symbol-value): Remove uses of : for defaulting the ssetter argument. This illustrates how useless the feature is for macro destructuring; all these just replace with nil. * txr.1: Clarify that macro parameter lists don't implement the colon trick. It was never explicitly specified that this is the case, but could have been inferred from the statements which indicate that macro parameter lists copy the features of function parameter lists. Added compat notes.
* places: remove macro-time.Kaz Kylheku2018-04-031-129/+126
| | | | | | | | | | | | Uses of the macro-time form are not useful in this module, and will hinder compilation, since forms evaluated by macro-time are not seen by the compiler and thus cannot be emitted in compiled form into a compiled file. * share/txr/stdlib/place.tl: Remove all top-level occurrences of macro-time. (defplace): Remove macro-time emitted in expansion, replacing it by progn.
* compiler: rewrite incorrect defmacro expander.Kaz Kylheku2018-04-031-6/+8
| | | | | | | | | | * share/txr/stdlib/compiler.tl (expand-defmacro): We cannot simply generate a mac-param-bind form because that has no means to pass through the all-important macro environment parameter; its expansion is carried out by expand-bind-mac-params with an nil environment parameter. Instead, we retarget to use expand-bind-mac-params directly, and supply the parameter gensym.
* parser: avoid consing for buf literals.Kaz Kylheku2018-04-031-12/+7
| | | | | | | | | | | * parser.y (buflit, buflit_items): Don't cons up a list of bytes in buflit_items which are then assembled into a buffer. Rather, the buflit_items rules construct and fill a buffer object directly. The buflit rule then just has to signal the end of the buffer literal to the lexer, and trim the buffer to the actual size. We will need this for efficient loading of compiled files, in which the virtual machine code is represented as a buffer literal.
* packages: fix package prefix read/print issue.Kaz Kylheku2018-04-032-2/+45
| | | | | | | | | | | | | | | | | | | | | | | | Suppose that we have two symbols of the same name, in two packages: foo:sym and bar:sym. Suppose that the bar package has foo in its package fallback list, and suppose bar is the current package. Then bar:sym prints without a package prefix, as just sym. However, this is potentially ambiguous. Suppose that bar:sym is written to a file as just sym. Then later the file is read into a fresh image in a situation in which bar:sym has not yet been interned, but foo:sym already exists. In this situation, sym will just resolve to foo:sym. The printer must detect this ambiguous situation. If a symbol is present in a package, but a same-named symbol is in the fallback list; or if a symbol is visible in the fallback list, but a same-named symbol is present in the package, then a package prefix should be printed. * lib.c (symbol_needs_prefix): New function. (unquote_star_check, obj_print_impl): Use symbol_needs_prefix rather than symbol_visible. * lib.h (symbol_needs_prefix): Declared.
* compiler: first cut compile-file implementation.Kaz Kylheku2018-04-034-13/+106
| | | | | | | | | | | | | | | | | | | | | | * lisplib.c (compiler_set_entries): Autoload on compile-file. * parser.c (parse_init): Expose get-parser, parser-errors and parser-eof intrinsics in system package. * share/txr/stdlib/compiler.tl (compiler): Wrap defstruct form in compile-only. What this means is that when we invoke comile-file on compiler.tl, the compiler will only compile this defstruct and not evaluate it. I.e. it will not try to redefine the structure. Redefining the core structure of the compiler while it is compiling itself wreaks havoc on the compilation. (%fille-suff-rx%, *emit*, *eval*): New variables. (open-compile-streams, list-from-vm-desc, usr:compile-file): New functions. * vm.c (vm_desc_nlevels, vm_desc_nregs): New static functions. (vm_init): Register new intrinsics vm-desc-nlevels and vn-desc-nregs in system package.
* asm/compiler: use unadorned sym in in-package.Kaz Kylheku2018-04-032-2/+2
| | | | | * share/txr/stdlib/asm.tl, share/txr/stdlib/compiler.tl: Just use (in-package sys) rather than (in-package :sys).
* eval/compile: special ops compile-only & eval-only.Kaz Kylheku2018-04-032-1/+3
| | | | | | | | | | | | | | | | These forms will be specially recognized by the file compiler when they appear as top-level forms. eval-only will mean this: only execute this form (possibly after compiling it); do not emit any compiled code into the output file. compile-only will mean: only emit the compiled code into the output file; do not execute it. * eval.c (eval_init): Register special operators compile-only and eval-only. In the interpreter, these are equivalent to progn and so route to op_progn. * share/txr/stdlib/compiler.tl (compiler compile): Similarly to interpreter, handle compile-only and eval-only as progn.
* compiler: bugfix: missing case in cond.Kaz Kylheku2018-04-021-0/+1
| | | | | | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-cond): Add handling for the case when the cond clause contains only a test form, and no additional forms. In that case, if the value is true, then cond terminates with that value. We can nicely achieve this by using or. This was uncovered while compiling share/txr/stdlib/awk.tl, which contains such a case in (sys:awk-state loop) that handles opening the input source.
* compiler: bugfix: block: missing mov to oreg.Kaz Kylheku2018-04-021-1/+2
| | | | | | | | | | * share/txr/stdlib/compiler.tl (comp-block): Our output frag indicates that oreg is the output register, and in the case when the block is terminated by the dynamic return, that's where it stores the result value before branching to the skip address. In the ordinary termination case, we have neglected to move the output of the block's code from bfrag.oreg to the output register oreg.
* compiler: unwind-protect bug: wrong output reg.Kaz Kylheku2018-04-021-1/+1
| | | | | | | * share/txr/stdlib/compiler.tl (comp-unwind-protect): The output register of the compiled unwind-protect is that of the protected forms compiled in pfrag, not of the compiled code for the cleanup forms in cfrag.
* compiler: switch: bugfix: missing mov to oreg.Kaz Kylheku2018-04-021-0/+5
| | | | | | | * share/txr/stdlib/compiler.tl (comp-switch): When compiling the shared case of switch (generated by tagbody), we must identify the last fragment's output register and move that to oreg.
* compiler: switch bugfix: missing index code.Kaz Kylheku2018-04-021-1/+2
| | | | | | | | * share/txr/stdlib/compiler.tl (comp-switch): Emit the code for evaluating the switch index. This has been working by fluke, because when the index is a variable, the assembly code for ifrag is nil; the swtch instruction accesses the variable directly and all is cool.
* compiler: big oreg-related bugfixKaz Kylheku2018-04-011-40/+74
| | | | | | | | | | | | | | | | | | | | | | | | | | There is a smattering of incorrect logic affecting a number of the compiler's special form sub-compilers. Basically the issue is that a compiler routine cannot arbitrarily use the oreg that it is given. If it generates multiple instructions which clobber a destination, only the last clobber may target oreg. The reason is that oreg is not necessarily a fresh temporary that can be used arbitrarily. It can be a variable which is evaluated by the forms that are compiled by the sub-compiler. Prematurely storing a value into oreg can affect the behavior and result value of not-yet executed code. The recent "indirect function calls" fix addressed just one case of this; the problem is more wide-spread. * share/txr/stdlib/compiler.tl (compiler (maybe-alloc-treg, maybe-free-treg)): New methods. (compiler (comp-if, comp-switch, comp-unwind-protect, comp-block, comp-handler-bind, comp-catch, comp-let, comp-progn, comp-and-or, comp-prog1, comp-for, comp-call, comp-tree-case): Do not carelessly use oreg for intermediate computations; allocate one or more temporary registers for that purpose, and either only move the final value into oreg, or else indicate a temporary register as the returned frag's output register.
* compiler: bugfix: wrong lambda frame size.Kaz Kylheku2018-04-011-1/+1
| | | | | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-lambda): We must not deduce the frame size from the nenv v-counter, because in the case when no frame is needed (the function has no arguments), nenv is just env. Our need-frame variable indicates whether or not a frame is needed; if not, we must use size zero. This is crucial because the VM otherwise ends up throwing an exception due to the frame level mismatch.
* compiler: bugfix: return value optionalKaz Kylheku2018-04-011-2/+2
| | | | | | * share/txr/stdlib/compiler.tl (comp-return-from, comp-return): The value expression is optional in all the return operators.
* compiler: bug: indirect function calls.Kaz Kylheku2018-04-011-1/+3
| | | | | | | | * share/txr/stdlib/compiler.tl (comp-call): We must not use the output register oreg for compiling the expression which calculates the function because it could be one of the arguments. In that case, we clobber an argument before we have called the function.
* compiler: bugfix: bad len check for tree-case.Kaz Kylheku2018-04-011-3/+5
| | | | | | | | | * share/txr/stdlib/compiler.tl (expand-bind-mac-params): When the strict parameter is the keyword symbol : we are mis-translating the length check. We are ignoring the presence of the rest-par, and checking for an exact length. When rest-par is present, we must check only for a minimum number of fixed parameters.
* compiler: bugfix: incorrect jmp in catch.Kaz Kylheku2018-04-011-3/+1
| | | | | | | | | | * share/txr/stdlib/compiler.tl (comp-catch): The emitted code doesn't handle the normal non-exception path. It assumes that only the frame established with the earlier frame instruction needs to be terminated; but in fact the catch intruction's frame has to be ended also. Thus we don't need the frame-end label; all exit cases jump too the handler-end label in front of the two end instructions.
* compiler: bugfix: scope of init-forms in lambda.Kaz Kylheku2018-03-311-1/+1
| | | | | | * share/txr/stdlib/compiler.tl (comp-lambda): The init-forms for optional parameters in a lambda must be compiled in the environment in which prior arguments are visible.
* expander: bugfix: fixed params visible to optionals.Kaz Kylheku2018-03-311-0/+1
| | | | | | | | | | | * eval.c (expand_params_rec): Add the parameter to the macro-time environment before processing rest of parameter list. This is already done for all the symbols of a macro-style destructuring; just not for a simple parameter. This is necessary, because the init forms of optional parameters occur in a lexical environment in which prior parameters are visible. The test case for this is that (lambda (x : (y x))) must not produce a warning about unbound x.
* doc: codify infinite looping behavior of each.Kaz Kylheku2018-03-301-0/+6
| | | | | | | | | * txr.1: the each, append-each and all other variants of operators exhibit inifite looping if the list of bindings is empty. In that case, the terminating condition that at least one list is empty, is never true. The behavior is consistent under compilation and interpretation, so let's just document it.
* eval: add missing checks in fun operator.Kaz Kylheku2018-03-301-0/+13
| | | | | | * eval.c (do_expand): When traversing (fun ...) operator, warn if the function isn't defined or if it is being applied to a special operator.