* module/language/elisp/boot.el (%catch): New variable.
(catch): Bind `%catch' to `t' during the evaluation of `body'. Call
`throw' instead of signalling an exception directly.
(throw): Signal a `no-catch' error if there is no `catch' to throw to.
* module/language/elisp/boot.el (throw): Define an `error-conditions'
property for this symbol.
(catch): Define in terms of `condition-case' instead of using Guile
exceptions directly.
(throw): Signal a `throw' condition instead of throwing a Guile
exception directly.
* module/language/elisp/boot.el (error, wrong-type-argument, no-catch,
invalid-function): Define `error-conditions' properties for these
standard error symbols.
* module/language/elisp/boot.el (signal): Accept only two arguments, and
throw an `elisp-condition' exception instead of an `elisp-error'
exception.
(condition-case): New macro.
* module/language/elisp/boot.el (lexical-let, lexical-let*): New macros.
* module/language/elisp/compile-tree-il.scm (bind-lexically?): Remove
the check for a `lexical' flag, since `lexical-let' and `lexical-let*'
are no longer special operators.
(compile-lexical-let, compile-lexical-let*): Remove.
* module/language/elisp/runtime/function-slot.scm: Update module
definition.
* module/language/elisp/boot.el (prog1, cond, or, catch): Use `let' with
`lexical' declarations instead of `lexical-let'.
(%plist-put): Use `let' instead of `lexical-let', since "boot.el" now
uses lexical binding by default.
* module/language/elisp/compile-tree-il.scm (process-let-bindings):
Remove.
(parse-let-binding, parse-flet-binding): New procedures.
(generate-let, generate-let*): Now takes an association list mapping
symbols to values for the `bindings' argument.
(compile-let, compile-let*, compile-lexical-let)
(compile-lexical-let*): Parse the bindings list with
`parse-let-binding'.
(compile-flet): Parse the bindings list with `parse-flet-binding'.
* module/language/elisp/compile-tree-il.scm (bind-lexically?): Accept a
new `decls' argument and check it for `lexical' declarations.
Establish the same kind of binding whether or not a lexical binding
for `sym' exists, whereas previously the presence of a lexical binding
would cause newly-established bindings to be lexical bindings as well.
(split-let-bindings): Remove. All callers changed.
(generate-let, generate-let*, compile-lambda): Pass the declarations
list to `bind-lexically?'.
* test-suite/tests/elisp-compiler.test: Explicitly disable the
lexical-binding mode. Add `lexical' declarations where necessary.
* module/language/elisp/compile-tree-il.scm (parse-body-1, parse-body)
(parse-lambda-body, parse-declaration): New procedures.
(generate-let, generate-let*): Use `parse-body'.
(compile-lambda): Use `parse-lambda-body'.
* module/language/elisp/compile-tree-il.scm (split-lambda-arguments):
Remove.
(parse-lambda-list, make-simple-lambda): New procedures.
(compile-lambda): Use `parse-lambda-list' and `make-simple-lambda'.
Set empty rest arguments to the empty list instead of `#nil'.
* test-suite/tests/elisp-compiler.test ("Lambda Expressions")["rest
argument"]: Use Elisp `null' instead of a Scheme equality check.
* module/language/elisp/boot.el (null, consp, listp, car, cdr)
(make-symbol, signal): Use `%funcall' instead of `funcall' or `fset'.
(symbolp, symbol-function, eval): Use `%funcall', since `funcall' now
calls these functions.
(functionp, %indirect-function): New functions.
(funcall): Define in terms of `%funcall' and `%indirect-function'.
(apply): New function. Previously defined in
"module/language/elisp/runtime/subrs.scm".
(fset): If `definition' is not a function, set the function cell of
`symbol' to an falias for `definition'.
* module/language/elisp/falias.scm: New file.
* module/language/elisp/subrs.scm: Remove file.
(apply): Remove. Now defined in "boot.el".
* module/language/elisp/runtime/function-slot.scm: Update module
definition.
* module/Makefile.am: Update.
* module/language/elisp/compile-tree-il.scm (find-operator): Assume that
`name' is lexically bound.
* module/language/elisp/runtime.scm (symbol-fbound?, fmakunbound!):
Assume that `symbol' is lexically bound.
(defspecial): Bind special operators lexically.
* module/language/elisp/compile-tree-il (compile-pair): Use `function'
to perform functional evaluation. Previously, if the operator of a
compound form was not a symbol, the operator would be evaluated as a
normal expression. This happened to work only because there is a
`lambda' macro. The compiler will now signal an error if the operator
is neither a function name nor a lambda expression.
* test-suite/tests/elisp-compiler.test ("Lambda Expressions")["optional
argument"]: Remove an erroneous use of `function' in the function
position.
* language/elisp/compile-tree-il.scm (compile-lambda): Add a `meta'
argument for the procedure's properties.
(compile-function, compile-defmacro, compile-defun): Update
accordingly, passing a `name' property to `compile-lambda' where
possible.
* module/language/elisp/compile-tree-il.scm: (always-lexical): Remove.
All uses changed.
(with-added-symbols): Remove.
(compile-with-always-lexical): Remove.
(process-options!): Remove support for the `#:always-lexical' option.
* module/language/elisp/runtime/function-slot.scm: Update import and
re-export lists.
* test-suite/tests/elisp-compiler.test: Remove or update tests using
`with-always-lexical'.
* module/language/elisp/bindings.scm (global?): New function.
* module/language/elisp/compile-tree-il.scm (lexical-binding): New
variable.
(bind-lexically?): If lexical binding is enabled, bind lexically
unless a special binding exists.
(compile-%set-lexical-binding-mode): New function.
* module/language/elisp/lexer.scm (lexical-binding-regexp): New
variable.
(lex): Return a `set-lexical-binding-mode!' token if a comment is
found while reading the first line.
* module/language/elisp/parser.scm (get-expression): Add support for
`set-lexical-binding-mode!' tokens.
* module/language/elisp/runtime/function-slot.scm: Import and re-export
the `%set-lexical-binding-mode' special form.
* test-suite/tests/elisp-compiler.test
("Let and Let*")["lambda args inside lexical-let"]: Update.
* module/language/elisp/bindings.scm: Use `(srfi srfi-9)'.
(bindings-type): Remove low-level record type definition and replace
with...
(bindings): ...this, an SRFI-9 record type. All uses changed.
(mark-global-needed!): Rename to...
(mark-global!): ...this. All callers changed.
(map-globals-needed): Rename to...
(map-globals): ...this. All callers changed.
* module/language/elisp/compile-tree-il.scm (generate-let)
(generate-let*, compile-lambda, compile-with-added-symbols)
(compile-progn, compile-if): Return nil if the form's body is empty.
* test-suite/tests/elisp-compiler.test ("Sequencing")["empty progn"]:
New test.
("Conditionals")["if with no else"]: New test.
("Let and Let*")["empty let, empty let*"]: New test.
("Lambda Expressions")["empty lambda"]: New test.
* module/language/elisp/runtime/macros.scm: Remove.
(macro-lambda, macro-prog1, macro-prog2, macro-cond, macro-and,
macro-or, macro-catch, macro-unwind-protect): Rewrite in Elisp and
move to...
* module/language/elisp/boot.el (lambda, prog1, prog2, cond, and, or,
catch, unwind-protect): ...here.
(eval-and-compile): New macro.
(funcall, fset, null, consp, listp, car, cdr, make-symbol-signal):
Wrap definitions in an `eval-and-compile' form so that they can be
used by the rewritten macros.
* module/language/elisp/runtime.scm: Remove `built-in-macro'.
* module/language/elisp/Makefile.am: Remove
module/language/elisp/runtime/macros.scm from `ELISP_LANG_SOURCES'.
* test-suite/tests/elisp-compiler.test ("Exceptions")["catch and
throw"]: Use a freshly-consed object instead of a literal object. This
test previously assumed that similar literal objects are never
identical, which no longer true.
("Equivalence Predifcates")["eq"]: Likewise.
* libguile/boolean.c (scm_nil_p): New function.
* libguile/vm-i-scheme.c (nilp, not_nilp):
* libguile/vm-i-system.c (br_if_nil, br_if_not_nil): New instructions.
Renumber other ops.
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Increment.
* module/language/assembly/compile-bytecode.scm (compile-bytecode): Add
support for writing `br-if-nil' and `br-if-not-nil' instructions.
* module/language/assembly/disassemble.scm (code-annotation): Add
`br-if-nil' and `br-if-not-nil' to the list of branch instructions.
* module/language/tree-il/compile-glil.scm: Add `nil?' to
`*primcall-ops*'.
(flatten): Use the new branch instructions for `nil?' conditionals.
* module/language/tree-il/primitives.scm: Add `nil?' to
`*interesting-primitive-names*', `*effect-free-primitives', and
`*effect+exception-free-primitives*'.