summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
...
* 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) ...)).
* compiler: bump object file version.Kaz Kylheku2018-04-182-3/+3
| | | | | | | | | | | The instruction set architecture has changed due to the redimensioning of the frame display, so we must bump up the major number. * share/txr/stdlib/compiler.tl (%tlo-ver%): Change to (1 0). * parser.c (read_file_common): Refuse to load if major number isn't 1.
* asm: deal with too large d regs in getv/setv.Kaz Kylheku2018-04-172-4/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Only registers d00 through d3f can now fit into a small operand, but the setv, getv and derived instructions only take a small operand as the name. If a function accesses more than 64 dynamic variables, it can't be compiled and assembled. (Fewer, if it uses symbols for anything else.) The approach we take here is to relax the name operand in getv and setv: it can be a large or small operand. When assembling these instructions, we check the size: if the operand is large, we emit an extra mov instruction to move the operand to a register that is itself a small operand. Then we use that register as the operand. To do this, we need a dedicated assembler temporary register, like the "at" register on MIPS. We reserve t1 as the assembler temporary; the compiler must be adjusted not to use it. Future task: the following optimization is possible: the machine code can be scanned for uses of d registers. The d registers can be globally renumbered/reassigned (along with a rearrangement of the order of the datavec) such that the getv and setv instructions can use the lowest-numbered d registers, minimizing or eliminating these extra mov instructions. * share/txr/stdlib/asm.tl (operand-to-exp): New function. (op-getv, op-setv): Change name operand from rs to r, allowing a large operand. If the operand is large, emit the extra mov instruction into the temp register, and designate that register as the name for the getv/setv. * share/txr/stdlib/compiler.tl (compiler): Initialize t register counter to 2 rather than 1 so we don't allocate the assembler temporary t001. (compiler check-treg-leak): The balance check must cover a deficit of two registers now: t000 and t001.
* vm/asm: reconfiguration of display dimensions.Kaz Kylheku2018-04-173-25/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | Increasing the maximum frame width from 256 to 1024 words; and reducing the max display depth from 256 to 64 frames. Small operands use a 4:6 split: the first 64 words of the first 16 levels can be accessed with a 10 bit operand. * share/txr/stdlib/asm.tl (parse-operand): Adjust to wider syntax for registers due to more digits. The v registers are 5 hex digits now: 2 digit level, and a 3 digit offset. (with-lev-idx): New macro. (operand-to-sym): Use with-lev-idx and rename variables to lv and ix. (small-op-p, enc-op-p, small-op-to-sym): Rewrite for 4:6 small operand. * share/txr/stdlib/vm-param.tl (%lev-size%, %lev-bits%, %max-lev%): Adjust values. (%sm-lev-size%, %max-sm-lev-idx%, sm-lev-bits%): New symbol macros. * vm.c (VM_LEV_BITS, VM_LEV_MASK, VM_SM_LEV_BITS, VM_SM_LEV_MASK): Values adjusted.
* vm: clear stack memory moved to heap.Kaz Kylheku2018-04-171-1/+3
| | | | | | | * vm.c (vm_make_closure): When a display frame is captured by a closure and moves into the heap object, the original should be cleared to all nil values, otherwise it can cause spurious retention of garbage.
* lib: error message cleanup.Kaz Kylheku2018-04-179-58/+66
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Eliminate function names from message string literals; they are interpolated via ~s from the symbol. Consistently use compile-error in macros. * share/txr/stdlib/asm.tl (asm-error): New function. (oc-base backpatch, assembler (define-label, parse-args, asm-one), bits-to-obj): Use asm-error. * share/txr/stdlib/awk.tl (awk-error): New function. (awk-state rec-to-f, awk-expander): Use awk-error. * share/txr/stdlib/conv.tl (conv): Function name out of string literal. * share/txr/stdlib/getopts.tl (getopts-error): New function. (opt-desc): Use getopts-error. * share/txr/stdlib/ifa.tl (ifa): Use compile-error; use symbol for name. (if-to-cond): Use compile-error. * share/txr/stdlib/place.tl (shift, defplace, get-mb): Use compile-error. (lset, placelet*, placelet): Use compile-error; use symbol for name. * share/txr/stdlib/socket.tl (str-inaddr, str-in6addr, str-inaddr-net-impl, str-inaddr-net, str-in6addr-net): Use symbols for function names. * share/txr/stdlib/txr-case.tl (txr-case-impl): Use compile-error and symbol for function name. * share/txr/stdlib/with-resources.tl (with-resources): Use compile-error and symbol for function name.
* vm/asm/compiler: parametrize display parameters.Kaz Kylheku2018-04-164-58/+142
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this patch we replace some hard-coded constants related to the dimensions of the frame display, which will make it easier to experiment with changes to the configuration: to set up wider frames at the cost of max display depth. The encoding of small operands needs to be abstracted because games can be played here. A 10 bit small operand can be configured in various ways: for instance a 5:5 split would mean that the first 32 entries in the first 32 levels can be small operands. That's independent of the display configuration. * share/txr/stdlib/asm.tl: Load vm-param to get some fundamental constants. (small-op-p): New macro. (assembler parse-args, parse-compound-operand, parse-operand, operand-to-sym): Use constants. (enc-small-oip, small-op-to-sym): New macros. (op-frame asm): Use constants. Small range check problem fixed here: a frame level of 1 mustn't be allowed. (op-movrs, op-movsr, op-mov-pseudo, op-movsmi, op-movrbi, op-movi-pseudo, op-retsr, op-retrs, op-retrr, op-ret-pseudo, op-getv, op-setv): Deal with small operand via functions. (op-close): Use constants. Off-by-one problem: frame size of 256 must be allowed. * share/txr/stdlib/compiler.tl: Load vm-param to get constants. (compiler get-dreg, compiler get-funvec): Use constant for max frame size. (compiler new-env): Check for maximum levels being exceeded. (compiler comp-atom): Use constant for maximum immediate integer operand width. * share/txr/stdlib/vm-param.tl: New file. * vm.c (vm_insn_extra_dec_small): New macro. (VM_LEV_BITS, VM_LEV_MASK, VM_SM_LEV_BITS, VM_SM_LEV_MASK): New preprocessor constants. (vm_lev, vm_idx, vm_sm_lev, vm_sm_idx): New macros. (vm_get, vm_set): Use macros instead of literals. (vm_sm_get, vm_sm_set): New inline functions. (vm_movrs, vm_movsr, vm_movsmi, vm_retsr, vm_retrs, vm_abscsr, vm_get_binding, vm_bindv): Use vm_sm_get or vm_sm_set to access the display using the small operand. (vm_close): Use preprocessor symbols instead of hard-coded literals.
* vm: remove unused, bogus definitions.Kaz Kylheku2018-04-161-8/+0
| | | | * vm.c (vm_opcode, vm_oparg): Unused macros removed.
* build: remove dubious license header from y.tab.c.Kaz Kylheku2018-04-161-0/+10
| | | | | | | | | | | | | | | | | | | | | | | The GNU Bison parser has a GPL header in the parser skeleton which gets copied to the generated parser. The GPL asserts that the entire file falls under the GPL (but as a special exception, it may be used in any manner whatsoever in a program, as long as it isn't used as the skeleton of a parser generator). The GPL assertion is false; the file is not entirely derived from the skeleton but contains code directly copied from parser.y, as well as tables generated from parser.y's original grammar. Since we are definitely not using this as a parser skeleton for a parser generator and are thus allowed to do whatever we want such as compiling this into proprietary object files, I'm removing the copyright header as a build step. You never know; someone could package up a built directory of TXR containing a Bison-generated y.tab.c, and then it looks like there is a GPL-ed file in the project. * Makefile (CM): New variable, needed for interpolating literal commas into macro calls. (BS_LIC_FROM, BS_LIC_TO): New variables. (y.tab.c): Filter y.tab.c to remove GPL comment.
* parser: propagate copyright to generated parser.Kaz Kylheku2018-04-161-2/+2
| | | | | | | | | | * parser.y: Move the copyright comment header into the %{ ... %} section so that it is copied to the generated parser, rathe than stripped away by the generator. The problem is that Bison adds a GPL header to the file wrongly implying that the whole thing is under the GPL (with a special exception). Without our copyright header there, it looks as if the whole file is from Bison.
* Makefile: bugfix: shell quoting issue in macro.Kaz Kylheku2018-04-161-1/+1
| | | | | | | | | | * Makefile (SH): The $(1) macro argument is substituted into a shell '...' quote. It may contain single quotes itself, so these have to be mapped to the famous '\'' sequence. Currently, only one SH call has '...' syntax in it: one in the y.tab.c rule which calls sed -e '/yyparse/d'. That works anyway, and the quotes could be removed from it; but let's fix the SH macro.
* parser: show starting line of unterminated form.Kaz Kylheku2018-04-151-0/+5
| | | | | | * parser.y (parse): Note the line number before parsing. If the error seems to be bad termination, issue an extra message indicating the starting line number of the form.
* compiler: lambda call to let optimization.Kaz Kylheku2018-04-153-7/+81
| | | | | | | | | | | | | | | | | | | Normalize ((lambda ...) args) to (call (lambda ...) args). Reduce (apply (lambda ...) args) and (call (lambda ...) args) to let (let (vars-inited-from-args ...) ...). * lisplib.c (error_set_entries): Autoload for new error functions lambda-too-many-args, lambda-too-few-args, lambda-short-apply-list. * share/txr/stdlib/compiler.tl (comp-fun-form): Restructure to recognize lambda and handle via comp-inline-lambda. (compiler comp-inline-lambda): New method. (lambda-apply-transform): New function. * share/txr/stdlib/error.tl (lambda-too-many-args, lambda-too-few-args, lambda-short-apply-list): New functions.
* compiler: use new parser for macro params.Kaz Kylheku2018-04-151-100/+80
| | | | | | * share/txr/stdlib/compiler.tl (expand-bind-mac-parse-params): Function removed. (expand-bind-mac-params): Use mac-param-parser struct.
* compiler: move lambda param parsing into struct.Kaz Kylheku2018-04-141-85/+116
| | | | | | | | * share/txr/stdlib/compiler.tl (param-parser-base, fun-param-parser, mac-param-parser): New structs. (compiler comp-lambda): Construct a fun-param-parser object using parameter syntax. Then just extract the parsed pieces for further processing.
* compiler: lambda: accurate determination of need-frame.Kaz Kylheku2018-04-141-3/+3
| | | | | | | | | | | | | * share/txr/stdlib/compiler.tl (comp-lambda): The local variable need-frame is supposed to indicate whether the lambda needs a frame for its arguments: i.e. whether it has any parameters. However the way it is calculated is poor: the fixed-pars list potentially includes the semicolon symbol : which separates the required parameters from optionals. Hence the parameter list syntax (:) will be treated as "needs frame", even though it denotes an empty parameter list, just like the syntax (). This slight flaw is now tightened up.
* compiler: bugfix: handle lambda call form.Kaz Kylheku2018-04-131-0/+2
| | | | | | | | | Looks like the compiler neglects to handle the syntax ((lambda (params ...) body ...) args ...). * share/txr/stdlib/compiler.tl (compiler compile): Check for a lambda expression in the car position of a form; if it's present then ((lambda ...) ...) -> (call (lambda ...) ...).
* case macros: switch for integer and char ranges.Kaz Kylheku2018-04-131-0/+77
| | | | | | | | * eval.c (hash_min_max): New static function. (me_case): Check for keys being all integers or all characters in a dense range (> 75% full). Generate code for switching directly on the displacement of the tested value into the key range.
* build: compiling Lisp requires ./txr to exist.Kaz Kylheku2018-04-121-2/+2
| | | | | | | | * Makfile (%.tlo, %.tlo2): We take advantage of Gmake's order-only prerequisites to express this dependency. This means that .tlo and .tlo2 files are not considered outdated when $(PROG) is newer; it only ensures that $(PROG) cannot be missing when a .tlo or .tlo2 must be updated.
* build: prevent make parallelization.Kaz Kylheku2018-04-121-0/+2
| | | | | | * Makefile: add .NOTPARALLEL: special target. This Makfile doesn't support parallel builds; it relies on left-to-right execution of prerequisites in some places.
* compile-file: need endian mark in .tlo files.Kaz Kylheku2018-04-125-3/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | VM machine code is endian-specific: it consists of 32 bit instruction words which are 32 bit in the local byte order. Thus code assembled on a little-endian machine won't run on a big endian-machine, or vice versa: unless we identify the situation and byte-swap the code when we load it. * buf.c (buf_swap32): New function. * buf.h (buf_swap32): Declared. * parser.c (read_file_common): Decode the third element from the version: a Boolean indicating big endian, if true. If the object file's endian is opposite from our endian, then byte swap the code. * itypes.c (itypes_init): Oops, calculation of itypes_little_endian was broken due to classic C =/== typo. Luckily, nothing has used this flag so far; it's been waiting for this first use. I caught this due to testing on a PPC64 box. * share/txr/stdlib/compiler.tl (%big-endian%, %tlo-ver%): New variables. (usr:compile-file): The file version comes from %tlo-ver% now, which includes the big-endian flag.
* Version 191.txr-191Kaz Kylheku2018-04-107-632/+733
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim, protsym.c: Regenerated.
* load: fix vm gc issue.Kaz Kylheku2018-04-101-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This issue manifested itself as a segfault on Mac OS while compiling a library file using the compiled implementation (hash.tl -> hash.tlo2). The problem is premature reclamation of a virtual machine description. While the asm.tlo module is loaded, suddenly a function table goes corrupt. When we execute machine using vm_execute_toplevel, the vm's stack doesn't actually contain a reference to the description object anywhere. It's passed in as a parameter, and right away converted to the (struct vm_desc *) handle which is planted in the struct vm representing the running instance, which lives on the stack. That pointer isn't a reference traversed by the garbage collector. If the original Lisp object is optimized away and overwritten both in vm_execute_toplevel and in that function's caller, then it can be reclaimed even as it executes. * parser.c (read_file_common): Add a gc_hint(desc) after the vm_execute_toplevel so that the compiler thinks the value of the variable is still needed after the call. That keeps it around on the stack or in a register so that the garbage collector can see it as a root pointer.
* Windows: package .tlo files.Kaz Kylheku2018-04-101-0/+1
| | | | | * inst.nsi (section "TXR"): Add File command to package up the compiled .tlo files.
* vm: don't eagerly resolve functions.Kaz Kylheku2018-04-101-7/+0
| | | | | | | | | | | | | | | * vm.c (vm_make_desc): Do not walk ftab to resolve the function bindings at VM instantiation time. Just let it be done late in vm_ftab when a gcall or gapply instruction is executing. We don't gain anything by doing it early; there is no error checking or anything. This early resolution causes the autoload semantics of the standard library modules to change between interpreted and compiled. When a compiled module is loaded, it immediately triggers autloads of everything that it potentially references. This suddenly broke the build under a newer GNU Make which doesn't sort the files expanded by $(wildcard ...), causing the library to be compiled in a different order.
* defpackage: bugfix: symbol clash.Kaz Kylheku2018-04-101-3/+3
| | | | | | | | * share/txr/stdlib/package.tl (defpackage): Now that library file are read in the sys package, this macro's name-str local variable is the same symbol as sys:name-str, the function it uses. They clash in the (op sys:name-str ...) syntax. Let's rename the local.
* parser: @(if) hack in output must use usr package.Kaz Kylheku2018-04-103-6/+7
| | | | | | | | | | | * match.c (else_s, elif_s): New symbol variables. (syms_init): Initialize new variable with interned symbols. * match.h (else_s, elif_s): Declared. * parser.y (not_a_clause): Refer to if_s, else_s and elif_s, which are symbols in the usr package, instead of intering symbols in whatever package is current.
* parser: duplicate package prefix in diagnostic.Kaz Kylheku2018-04-101-2/+2
| | | | | * parser.l (directive_tok): Fix printing of duplicate package prefix on symbol.
* doc: new package fallback use by printer.Kaz Kylheku2018-04-101-1/+3
| | | | | * txr.1: Update the description of how the printer avoids ambiguity when making use of the packag fallback list.
* doc: document new pub package.Kaz Kylheku2018-04-091-11/+32
| | | | | | * txr.1: Fix places which say that *package* is initialized to the user package. Under *package*, describe the pub package. Compat notes added.
* doc: vm-fun-p described.Kaz Kylheku2018-04-091-0/+22
| | | | * txr.1: Document vm-fun-p.
* compiler: implement with-compilation-unit macro.Kaz Kylheku2018-04-093-36/+82
| | | | | | | | | | | | * lisp.c (compiler_set_entries): Add with-compilation-unit to autoload symbols for compile module. * share/txr/stdlib/compiler.tl (usr:with-compilation-unit): New macro. (usr:compile-file): Use with-compilation-unit macro to dump warnings if a file is processed alone. * txr.1: Documented.
* compiler: record source loc when reading.Kaz Kylheku2018-04-091-0/+1
| | | | | | | * share/txr/stdlib/compiler.tl (usr:compile-file): Bind *rec-source-loc* to t, otherwise the read function doesn't record source loc info and we don't get warnings reported against line numbers in the processed source files.
* doc: document force-flag.Kaz Kylheku2018-04-091-5/+92
| | | | | | * txr.1: Documented force-break and the altered return value of width-check. The existence of a stream's force flag is mentioned under width check.