summaryrefslogtreecommitdiffstats
path: root/share
Commit message (Collapse)AuthorAgeFilesLines
...
* stdlib: all code read under sys package.Kaz Kylheku2018-04-0614-51/+47
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Another part of the preparation for an upcoming change. All library code is now read in the sys package, so any symbols that are interned (local variables and whatnot) are in sys and will not be exposed to user code. We have to overcome some annoyances to achieve this: - We have to stay away from the symbols exp or var, because they are now sys:exp and sys:var with their special meaning. - Instances in which a symbol of the same name exists in both sys and usr present a problem; the plain symbol now is the usr one. For instance rplaca will refer to sys:rplaca, so a small amount of code has to explicitly use usr:rplaca. * Makefile (COMPILE_TL): Change to the sys package before compiling library code. * lisplib.c (lisplib_try_load): Bind *package* to the system package. * share/txr/stdlib/asm.tl, share/txr/stdlib/compiler.tl: Remove in-package macro invocation; we don't need this since all files are loaded or compiled in the sys package. * share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/ver.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl: Deal with the various usr versus sys symbol issues.
* structs: get rid of sys:slot and sys:static-slot.Kaz Kylheku2018-04-061-4/+4
| | | | | | | | | | | | | | | | * 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.
* trace: add missing copyright header.Kaz Kylheku2018-04-051-0/+26
| | | | * trace.tl: File was introduced in 2016, so 2016-2018.
* compile-file: handle gensyms and such.Kaz Kylheku2018-04-051-6/+13
| | | | | | | | | | | | | | | | | | | * 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-051-0/+1
| | | | | | | | | | * 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-041-1/+1
| | | | | | | | | | | 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.
* 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-042-7/+7
| | | | | | | | | | | | | | | | | | | | | | | 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.
* 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-041-5/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* compiler: first cut compile-file implementation.Kaz Kylheku2018-04-031-12/+88
| | | | | | | | | | | | | | | | | | | | | | * 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-031-1/+1
| | | | | | | | | | | | | | | | 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.
* compiler: change message for uhandled special op.Kaz Kylheku2018-03-291-1/+1
| | | | | | | * share/txr/stdlib/compiler.tl (compiler compile): All special forms are handled, so "not handled yet" wording is inappropriate. Going forward, no special form will be added without compiler support.
* compiler: improve register use when compiling calls.Kaz Kylheku2018-03-291-6/+11
| | | | | | | | | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-call-impl): Instead of allocating N temporary registers for N arguments, some (or even none) of which may actually be used, we do this one argument at a time: allocate just one register, compile the argument expression, and then free the register immediately if that fragment specifies its own output location instead of the register. Otherwise keep the register and push it on a stack. This strategy lowers maximum register use. Also, since we are pushing the used registers on a stack, when we call free-tregs, they get liberated in reverse order of allocation, which keeps things tidy.
* compiler: enforce register balance.Kaz Kylheku2018-03-291-0/+7
| | | | | | | * share/txr/stdlib/compiler.tl (compiler check-treg-leak): New method. (usr:compile-toplevel): Free the top-level output register, then call check-treg-leak to verify all were returned.
* compiler: incorrect null destructuring pattern.Kaz Kylheku2018-03-291-2/+2
| | | | | | | * share/txr/stdlib/compiler.tl (expand-bind-mac-params): The listp function identifies a recursive parameter, not consp, because nil is an empty pattern, and not a variable name, in macro-style parameter lists.
* compiler: special case if + eq combo.Kaz Kylheku2018-03-281-6/+58
| | | | | | | | | | | | | | | | | We use the ifq instruction for compiling (if (eq x y) ...) and (if (neq x y ...) rather than emitting a call to eq or neq. * share/txr/stdlib/compiler.tl (%test-funs-pos%, %test-funs-neg%, %test-funs%, %test-inv%): New global %variables. (comp-if): Recognize when test expression is one of the tests in %test-funs% and transform into (sys:ift ...) syntax. Also, minor unrelated change here: (if test) optimized away to nil if test is a constant expression. (compiler comp-ift): New method. (compiler comp-fun-form): Recognize sys:ift in operator position; hand off to comp-ift.
* compiler: pass whole form to comp-fun-form.Kaz Kylheku2018-03-281-19/+20
| | | | | | | | | * share/txr/stdlib/compiler.tl (compiler compile): Pass form to comp-fun-form rather than sym and (cdr form). (compile comp-fun-form): Take just a form argument. Internally destructure to sym and args with tree-bind. This will allow some special cases added in the future to have access to the original form.
* compiler: replace cond implementation.Kaz Kylheku2018-03-281-67/+10
| | | | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-cond): Replace pointlessly verbose cond implementation compact implementation that rewrites cond to combinations of if, progn and smaller cond. This generates pretty much the same code, and will automatically benefit from special case translations applied in if.
* compiler: move some lookup tables out of compiler struct.Kaz Kylheku2018-03-281-5/+7
| | | | | | | | * share/txr/stdlib/compiler.tl (compiler): Remove gcallop and callop static members. (%gcall-op%, %call-op%): New global variables. (compiler comp-fun-form): Use new globals instead of old static members.
* compiler: if: remove spurious instruction.Kaz Kylheku2018-03-281-2/+1
| | | | | | * share/txr/stdlib/compiler.tl (compiler comp-if): Remove a trailing maybe-mov from the instruction template that serves no purpose and can potentially generate an instruction.
* asm: use capital hex for dregs.Kaz Kylheku2018-03-281-1/+1
| | | | | | * share/txr/stdlib/asm.tl (disassemble-c-d): When printing the data table, use capital hexadecimal for the dregs, consistent with the instruction listing.
* compiler: bugfix in let.Kaz Kylheku2018-03-271-1/+2
| | | | | | | | | | | | | | | | | | | | | Very similar issue to the sys:fbind issue fixed some commits ago. When we are setting up parallel bindings, we don't want to compile initforms in the original env, because then they get the same frame level as the new env we are compiling. Thus (let ((x (let (...)))) ...) is mistranslated. Both lets, have environments which are siblings of the same parent env, which puts them on the same level. But their lifetimes at run-time are nested, so they cannot share the same level. The VM caught this since frame instructions declare their absolute level and it must be one higher than the current level. (I had the foresight to predict this might be a source of problems and put in the checks.) * share/txr/stdlib/compiler.tl (compiler comp-let): Same trick as in sys:fbind case: set up an empty environment above the initforms, so when an initform creates an environment, it is a granddaughter of env, and thus a niece rather than sister of of nenv, consequenty one frame level higher.
* compiler: don't wastefully enter into dreg table.Kaz Kylheku2018-03-271-0/+1
| | | | | | * share/txr/stdlib/compiler.tl (compiler get-dreg): If the input atom is nil, return the t0 register that always holds nil.
* compiler: diagnose exhaustion of dregs.Kaz Kylheku2018-03-271-4/+6
| | | | | * share/txr/stdlib/compiler.tl (compiler get-dreg): Restructure code. Don't increment dreg-cntr past 255.
* compiler: use counter instead of preallocating tregs.Kaz Kylheku2018-03-271-7/+7
| | | | | | | | | | * share/txr/stdlib/compiler.tl (compiler): new slot, treg-cntr; slot nregs removed; tregs stack initialized to empty list. (compiler alloc-treg): Take from stack if possible, otherwise create new treg using counter, up to 255. (usr:compile-toplevel): Referenceco.treg-cntr for register count, rather than removed co.nreg.
* compiler: bugfix: register double free.Kaz Kylheku2018-03-271-1/+2
| | | | | | * share/txr/stdlib/compiler.tl (compiler comp-progn): Since oreg-discard is conditionally allocated, it must be only be freed if it had been allocated.
* compiler: implement prof special op.Kaz Kylheku2018-03-271-0/+10
| | | | | | * share/txr/stdlib/compiler.tl (compiler compile): Handle prof via comp-prof method. (comp-prof): New method.
* vm/asm: new prof instruction.Kaz Kylheku2018-03-271-0/+2
| | | | | | | | | | * share/txr/stdlib/asm.tl (prof): New opcode. (op-prof): New opcode class. * vm.c (vm_prof_callback, vm_prof): New static functions. (vm_execute): Handle PROF opcode via vm_prof. * vmop.h: Regenerated.
* compiler: implement sys:switch special op.Kaz Kylheku2018-03-271-0/+32
| | | | | | * share/txr/stdlib/compiler.tl (compiler compile): Handle sys:switch via comp-switch method. (comp-switch): New method.
* compiler: bugfix in sys:fbind op.Kaz Kylheku2018-03-271-1/+2
| | | | | | | | | | | | When a (flet ...) form is compiled, the function arguments of the lambda are being bound in the same frame and clashing against the variables being bound by the construct. * share/txr/stdlib/compiler.tl (compiler comp-fbind): For the non-recursive case, insert the dummy empty environment eenv, and compile the forms in that environment. This raises them up to the appropriate display level without affecting what is visible in their scope.