summaryrefslogtreecommitdiffstats
path: root/eval.c
Commit message (Collapse)AuthorAgeFilesLines
* load: tolerate hash bang files.Kaz Kylheku2018-11-051-0/+3
| | | | | * eval.c (load): Consume the first line of the input file if it starts with hash bang.
* The code expander becomes a public API.Kaz Kylheku2018-11-021-3/+3
| | | | | | | | | | | | | | | | | | | | | | | The functions sys:expand, sys:expand* and sys:expand-with-free-refs are now in the usr package and documented for public use. * eval.c (eval_init): Move registrations of the symbools expand, expand* and expand-with-free-refs from the system package to the user package. * share/txr/stdlib/awk.tl (sys:awk-mac-let, awk): Uses of sys:expand drop the sys: prefix. * share/txr/stdlib/op.tl (sys:op-alpha-rename): Likewise. * share/txr/stdlib/place.tl (call-upudate-expander, call-clobber-expander, call-delete-expander, sys:placelet-1): Likewise. * tests/011/macros-2.txr, tests/012/struct.tl: Likewise. * txr.1: Documented expand, expand* and expand-with-free-refs.
* defvar: warn about prior lexical uses.Kaz Kylheku2018-10-261-1/+5
| | | | | | | | | | | | | | | | | | | Now that the compiler has a more efficient treatment of global lexical variables, code which accesses global variables that have not yet been defined will misbehave if the intent is to for those variables to be dynamically scoped. There is such a bug in the op expander, in fact. * eval.c (me_def_variable): When defvar/defparm are expanding, they now check whether there is an outstanding unbound warning against the variable. If so, then a warning is issued that the variable was previously used lexically and is now being marked special. * unwind.c (uw_warning_exists): New function. * unwind.h (uw_warning_exists): Declared.
* eval: handle top-level incrementally.Kaz Kylheku2018-07-171-3/+30
| | | | | | | | | | | | | | | | | | | | | | | | Like in some other Lisp dialects, evaluation of top-level forms should deal with forms like: (progn (defmacro a () 42) (a)) where the (a) will correctly reference the macro earlier in the progn. * eval.c (eval_only_s, compile_only_s): New symbol variables. (expand_eval): New static function, based on previous code of eval_intrinsic. (eval_intrinsic): Rewritten to perform incremental macroexpand, similarly to compile-file, and recurse. If a form, after macro-expansion, is a progn, eval-only or compile-only, then its constituents are individually evaluated through expand_eval as separate forms: each one is fully expanded and evaluated before the next one is processed. If the form isn't a progn, eval-only or compile-only, then it is treated as a single expansion and evaluation. (eval_init): Initialize new symbol variables and use their values in registering their respective operators.
* opip, oand: rewrite in Lisp.Kaz Kylheku2018-07-161-39/+2
| | | | | | | | | | | | | | | | | * eval.c (opip_s, oand_s, chain_s, chand_s): Variables removed. (me_opip): Function removed. (eval_init): Initializations of removed variables removed. chain and chand symbols interned at point of function registration. * lisplib.c (op_set_entries): Add autoload entries for opip and oand. * share/txr/stdlib/op.tl (sys:opip-expand): New function. (opip, oand): New macros. * protsym.c: Regenerated.
* op: convert to Lisp trivial macros related to op.Kaz Kylheku2018-07-161-43/+3
| | | | | | | | | | | | | | | | | | | | | | | The op macro is no longer written in C, but the trivial macros ap, ip, ado, ido, ret and aret are still C. It's silly to have macros written in C, baked into the TXR executable, which just produce syntax for a complicated macro written in Lisp that must be autoloaded when that code is used. * eval.c (ap_s, apf_s, ipf_s, ret_s, aret_s): Variables removed. (me_ap, me_ip, me_ado, me_ido, me_ret_aret): Functions removed. (eval_init): Do not initialize removed variables. Remove registration for macros ap, ip, ado, ido, ret and aret. Intern the apf and ipf symbols in the same expression which registers these functions. * lisplib.c (op_set_entries): Add autoload entries for ap, ip, ado, ido, ret and aret. * share/txr/stdlib/op.tl (ap, ip, ado, ido, ret, aret): New macros. * protsym.c: Regenerated.
* vm: release cached bindings that become unbound.Kaz Kylheku2018-06-211-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | When a function binding is removed using fmakunbound, virtual machine descriptions hang on to the previously cached binding in the ftab. When the symbol is newly bound, virtual machine descriptions keep pointing to the old function. To solve this, we put the vm_desc structures into a global list and provide a function that fmakunbound calls to scrub all the VM descriptors of that binding. * eval.c (makunbound, fmakunbound): Call new vm_invalidate_binding function. * vm.c (struct vm_desc_links): New structure. (struct vm_desc): New member lnk, with links. (vmd_list): New static variable: circular list of all VM descriptors. (vm_make_desc): Insert new VM descriptor into list. (vm_desc_destroy): Remove VM descriptor from list. (vm_invalidate_binding): New function. * vm.h (vm_invalidate_binding): Declared.
* logcount: new function.Kaz Kylheku2018-05-181-0/+1
| | | | | | | | | | | | | | | | | | This is in ANSI CL; potentially useful and hard to implement efficiently in user code. * arith.c (logcount): New function. * eval.c (eval_init): Register logcount intrinsic. * lib.h (logcount): Declared. * mpi/mi.c (s_mp_count_ones): New static function. (mp_count_ones): New function. * mpi/mpi.h (mp_count_ones): Declared. * txr.1: Documented.
* 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.
* 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.
* interpreter: correct semantics of special var args.Kaz Kylheku2018-05-011-53/+86
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* compiler: replace "$" package hack.Kaz Kylheku2018-04-251-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* New macro: load-time.Kaz Kylheku2018-04-231-0/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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: tighter code for quasiliterals.Kaz Kylheku2018-04-211-5/+8
| | | | | | | | | | | | | | | | | | | | | | | | 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.
* 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-181-6/+1
| | | | | | | | | * 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-181-2/+12
| | | | | | | | | | | | | | | | | | | | 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.
* 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.
* expander: no dot-to-apply transform on special forms.Kaz Kylheku2018-04-081-1/+3
| | | | | | | | * eval.c (do_expand): Do not convert (op arg ... . dot) to (sys:apply (fun op) (sys:l1-value arg) ... dot) if op is a special operator; this is only valid for functions. This issue has been uncovered by new diagnosis of undefined functions in the fun operator.
* expander: consolidate dotted argument error.Kaz Kylheku2018-04-081-6/+9
| | | | | | | * eval.c (dotted_form_error): New static function. (expand_forms, expand_forms_ss, expand_forms_lisp1): Call dotted_form_error instead of repeated open coded uw_throwf calls.
* case macros: bugfix: use hash for caseql and casequal too.Kaz Kylheku2018-04-071-2/+1
| | | | | | | | | | * eval.c (me_case): Correct the condition. We want to generate for all the case comparison types. The only situation we want to avoid is when the keys do not use eq equality, but caseq is used. The reason is that the underlying hash table is eql-based, not eq-based: it's not the right kind of hash table for caseql/caseql*. We can only use it if two keys might be eql that are not eq.
* case macros: reduce consing.Kaz Kylheku2018-04-071-6/+8
| | | | | | | * eval.c (compares_with_eq): New static function. (me_case): Instead of check_fun, call compares_with_eq directly. For the case when we map over check fun, allocate the function just once, outside the loop.
* lib: new function vm-fun-p.Kaz Kylheku2018-04-071-0/+1
| | | | | | | | * eval.c (eval_init): vm-fun-p intrinsic registered. * lib.c (vm_fun_p): New function. * lib.h (vm_fun_p): Declared.
* Application code is now in a package called pub.Kaz Kylheku2018-04-091-1/+2
| | | | | | | | | | | | | | | * lib.c (public_package): New variable. (obj_init): Protect public_package from gc. Initialize it with a package called "pub" which has the user package in its fallback list. * lib.h (public_package): Declared. * eval.c (eval_init): Initialize package_s to public_package rather than user_package, except in compat <= 190 mode. * txr.c (txr_main): Bind *package* to public_package rather than user_package, except in compat <= 190 mode.
* lib: get rid of preprocessor macros for packages.Kaz Kylheku2018-04-051-10/+7
| | | | | | | | | | | | | | | | | | | | | | | 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.
* compiler: bugfix: quasilit cannot use append.Kaz Kylheku2018-04-041-0/+6
| | | | | | | | | | | 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.
* 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.
* Implement compiled file loading.Kaz Kylheku2018-04-041-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | * 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.
* macro param lists: remove colon hack.Kaz Kylheku2018-04-041-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* eval/compile: special ops compile-only & eval-only.Kaz Kylheku2018-04-031-0/+2
| | | | | | | | | | | | | | | | 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.
* 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.
* 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.
* case macros: translate big case forms to hash+switch.Kaz Kylheku2018-03-291-1/+50
| | | | | | | | | | | | | | | | | | | | | | | | | | | Currently, the case macros (caseq, caseql, casequal, caseq*, caseql* and casequal*) all translate to a cond statement which tries the cases one by one. With this change, larger cases are translated to a lookup through a hash table, which produces an integer value. The integer value is then used as the index in an op:switch form for table lookup dispatch. If the hash lookup fails, then the else-clause is evaluated. op:switch is handled efficiently in the interpreter, and turned into an efficient swtch VM instruction by the new compiler. * eval.c (me_case): Add variables and logic to the function such that while it gathers the materials for the cond-based translation, it also builds materials for a hash-switch-based translation. Then, at the end, a decision is made by looking at how many keys there are and other factors. Because we don't have hash tables based on the eq function, but only eql, we must be careful not to turn caseq into hash lookup, unless we verify that the keys which occur are fixnum integers, characters or symbols.
* eval: bugs/regressions in handling nil in param expansion.Kaz Kylheku2018-03-291-8/+12
| | | | | | | | | | | | | | | | | | | | Due to a number of changes since December 2016, we have two problems in the evaluator: (lambda (nil)) is accepted rather than complaining that nil is not bindable; and (tree-bind (()) '(3)) silently proceeds rather than diagnosing that the atom 3 doesn't match the empty pattern (). * eval.c (expand_opt_params_rec, expand_params_rec): When not expandin macro-style params, check for a parameter not being bindable, and also avoid recursion entirely when not doing macro style. (bind_macro_params): Don't assume that an atom parameter is a variable, but rather tha a non-list parameter is a variable. Otherwise we bind nil rather than treating it as an empty sub-pattern. Before the December 2016 change (744340ab), we were checking bindablep here; the idea was to hoist the detailed checking to expansion time. But then the pattern versus variable distinction was bungled here.
* eval: refactor op_prof to support reuse.Kaz Kylheku2018-03-271-2/+18
| | | | | | | | | | | * eval.c (prof_call): New function, contents based on op_prof. (struct prof_ctx): New struct type. (op_prof_callback): New static function. (op_prof): Reduced to call to prof_call, passing context through to callback which performs the evaluation that is timed. * eval.h (prof_call): Declared.
* compiler: implement defsymacro special op.Kaz Kylheku2018-03-251-0/+9
| | | | | | | | | * share/txr/stdlib/compiler.tl (compiler compile): Handle defsymacro via expand-defsymacro expander. (expand-defsymacro): New function. * eval.c (rt_defsymacro): New static function. (eval_init): register sys:rt-defsymacro intrinsic.
* eval: remove hack of macro deffers evaled on expansion.Kaz Kylheku2018-03-251-2/+3
| | | | | | | | | | | | | | | | | | * eval.c (do_expand): When a defmacro or defsymacro form is traversed, do not evaluate it, except in backward compatibility mode. Unfortunately, this breaks some code. * tests/011/macros-1.txr: A defmacro form has to be wrapped in macro-time. * tests/011/macros-2.txr: Likewise. * tests/011/mandel.txr: Likewise. * tests/012/man-or-boy.tl (defun-cbn): This macro generates a progn which which expects that a defmacro form will come into effect for the subsequent lambda in the same form. We must wrap it in macro-time to make this happen now.
* eval/compiler: run-time support for compiled defun.Kaz Kylheku2018-03-251-8/+18
| | | | | | | * eval.c (rt_defun, rt_defmacro): New static functions. (op_defun): Use static functions. (eval_init): Register sys:rt-defun and sys:rt-defmacro intrinsics.
* eval/compiler: run-time support for compact defvarl.Kaz Kylheku2018-03-251-5/+20
| | | | | | * eval.c (rt_defvarl): New static function. (op_defvarl): Simplified using rt_defvarl. (eval_init): Register sys:rt-defvarl.
* new special op sys:upenvKaz Kylheku2018-03-211-0/+9
| | | | | | | | | | | | | | | | | | | | | | | This is something that will be useful in compiling some forms. At first I added it to the compiler only, but it seems wise to have it in the interpreter also. (sys:upenv form) causes form to be treated as if it were not in the immediately surrounding lexical environment but its parent. Thus (let ((a 1)) (let ((a 2)) (list a (sys:upenv a)))) yields (2 1). This operator needs no special treatment in the expander; it is expanded as a function call. This is not 100% correct in the face of all conceivable use. For instance given (symacrolet ((a 1)) (let ((a 2)) (sys:upenv a))), we probably want sys:upenv to skip the inner environment at expansion time too so that a is replaced by 1. However, it is not documented for application use, and will never be used in such a situation in the compiler. * eval.c (op_upenv): New static function. (eval_init): Register sys:upenv special operator. * compiler.tl (compiler compile): Implement compiled version of sys:upenv.
* expander: bugfix: sys:for-op init forms.Kaz Kylheku2018-03-201-5/+8
| | | | | | | * eval.c (do_expand): The first argument of the sys:for-op special operator isn't "vars" but a sequence of initialization forms. Name the variable appropriately. The neglected expansion of these forms is now performed.
* lib: new ldiff function.Kaz Kylheku2018-03-201-1/+2
| | | | | | | | | | * eval.c (eval_init): Use the old ldiff function under compatibility with 190 or lower. * lib.c (ldiff): Rewritten. (ldiff_old): New function, copy of previous version of ldiff. * lib.h (ldiff_old): Declared.
* compile-toplevel: expand with warnings.Kaz Kylheku2018-03-171-0/+1
| | | | | | | | * eval.c (eval_init): Expose raw expand function as sys:expand*, since sys:expand squelches warnings. * share/txr/stdlib/compiler.tl (usr:compile-toplevel): Use expand* instead of expand.
* quasi: factor out repeated code.Kaz Kylheku2018-03-161-19/+24
| | | | | | | | * eval.c (fmt_tostring, fmt_cat): New static functions. (do_format_field): Replace code block with call to fmt_cat. (fmt_simple, fmt_flex): Insert needed call to fmt_tostring. (subst_vars): Replace blocks of code with calls to fmt_tostring and fmt_cat.
* quasilit: expose access to field formatting.Kaz Kylheku2018-03-161-0/+35
| | | | | | | | | | | | | | | | | | | | | | | | | This is the second round of changes in perparation for compiling the string quasiliterals special form. Having split format_fields into a lower level do_format_field and format_field, we now provide two functions which allow Lisp code to call do_format_field. The sys:fmt-simple function has fixed arguments for the field width/alignment, indexing/slicing, separator and plist. Any of them can be defaulted with nil. This function will be useful when the quasiliteral specifies modifiers that are simple literals or constant expressions. The sys:fmt-flex function takes a variable number of arguments, after the object and the plist. This function has to scan through the arguments and classify them by type: a string is a separator, an integer is a width and left/right alignment and so on. The compiler will use sys:flex when format field modifiers are present whose arguments contain expressions that get evaluated. * eval.c (fmt_simple, fmt_flex): New static functions. (eval_init): sys:fmt-simple and sys:fmt-flex registered.
* quasilit: split format_field into two functions.Kaz Kylheku2018-03-161-46/+55
| | | | | | | | | | | | | | | | | | | | | | | | The objective of this work is to isolate the field-formatting logic so we can target it in the compiler. Currently, the sys:quasi special operator relies on calling subst_vars, which calls format_field. Both subst_vars and format_field perform dynamic evaluation, requiring an environment. In the compiler, this will be replaced by macro-generated logic; but we would like to obtain the use of the lower-level field formatting as a pure function. * eval.c (do_format_field): New static function. Does the field formatting previously done in format_field. Also performs the indexing on the object implied by the numeric or range modifier; but the range or index is already computed and comes in as a parameter. (format_field): Perform the modifier parsing only, requiring the dynamic evaluations via eval_fun, and then call do_format_field on the extracted data. The range indexing on the input sequence is no longer done during the parsing of the modifiers. That unfortunately changes some behaviors that are possible but are fortunately obscure and undocumented.
* structs: spurious hiding of defmeth: fix needed.Kaz Kylheku2018-03-141-1/+1
| | | | | | | | | | * eval.c (op_defun): There is a hidden reference to the sys:defmeth function here, which should have been updated in commit 0ae617f463290ff4463db2e479604808f940cc76 that renamed the function to define-method! Caught this by incidental code inspection, browsing through special forms in the context of working on the compiler.