1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-03 02:31:03 -08:00

Get rid of funvec.

* lisp/emacs-lisp/bytecomp.el (byte-compile-lapcode): Handle new form of
`byte-constant'.
(byte-compile-close-variables, displaying-byte-compile-warnings):
Add edebug spec.
(byte-compile-toplevel-file-form): New fun, split out of
byte-compile-file-form.
(byte-compile-from-buffer): Use it to avoid applying cconv
multiple times.
(byte-compile): Only strip `function' if it's present.
(byte-compile-lambda): Add `reserved-csts' argument.
Use new lexenv arg of byte-compile-top-level.
(byte-compile-reserved-constants): New var.
(byte-compile-constants-vector): Obey it.
(byte-compile-constants-vector): Handle new `byte-constant' form.
(byte-compile-top-level): Add args `lexenv' and `reserved-csts'.
(byte-compile-form): Don't check callargs here.
(byte-compile-normal-call): Do it here instead.
(byte-compile-push-unknown-constant)
(byte-compile-resolve-unknown-constant): Remove, unused.
(byte-compile-make-closure): Use `make-byte-code' rather than `curry',
putting the environment into the "constant" pool.
(byte-compile-get-closed-var): Use special byte-constant.
* lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): Handle new
intermediate special form `internal-make-vector'.
(byte-optimize-lapcode): Handle new form of `byte-constant'.
* lisp/help-fns.el (describe-function-1): Don't handle funvecs.
* lisp/emacs-lisp/macroexp.el (macroexpand-all-1): Only convert quote to
function if the content is a lambda expression, not if it's a closure.
* emacs-lisp/eieio-come.el: Remove.
* lisp/emacs-lisp/eieio.el: Don't require eieio-comp.
(defmethod): Do a bit more work to find the body and wrap it into
a function before passing it to eieio-defmethod.
(eieio-defmethod): New arg `code' for it.
* lisp/emacs-lisp/debug.el (debugger-setup-buffer): Don't hide things in
debugger backtrace.
* lisp/emacs-lisp/cl-extra.el (cl-macroexpand-all): Use backquotes, and be
more careful when quoting a function value.
* lisp/emacs-lisp/cconv.el (cconv-freevars): Accept defvar/defconst.
(cconv-closure-convert-rec): Catch stray `internal-make-closure'.
* lisp/Makefile.in (COMPILE_FIRST): Compile pcase and cconv early.

* src/eval.c (Qcurry): Remove.
(funcall_funvec): Remove.
(funcall_lambda): Move new byte-code handling to reduce impact.
Treat all args as lexical in the case of lexbind.
(Fcurry): Remove.
* src/data.c (Qfunction_vector): Remove.
(Ffunvecp): Remove.
* src/lread.c (read1): Revert to calling make_byte_code here.
(read_vector): Don't call make_byte_code any more.
* src/lisp.h (enum pvec_type): Rename back to PVEC_COMPILED.
(XSETCOMPILED): Rename back from XSETFUNVEC.
(FUNVEC_SIZE): Remove.
(FUNVEC_COMPILED_TAG_P, FUNVEC_COMPILED_P): Remove.
(COMPILEDP): Rename back from FUNVECP.
* src/fns.c (Felt): Remove unexplained FUNVEC check.
* src/doc.c (Fdocumentation): Don't handle funvec.
* src/alloc.c (make_funvec, Ffunvec): Remove.
* doc/lispref/vol2.texi (Top):
* doc/lispref/vol1.texi (Top):
* doc/lispref/objects.texi (Programming Types, Funvec Type, Type Predicates):
* doc/lispref/functions.texi (Functions, What Is a Function, FunctionCurrying):
* doc/lispref/elisp.texi (Top): Remove mentions of funvec and curry.
This commit is contained in:
Stefan Monnier 2011-02-24 22:27:45 -05:00
parent cb9336bd97
commit 876c194cba
33 changed files with 379 additions and 752 deletions

View file

@ -1,6 +1,6 @@
((nil . ((tab-width . 8)
(sentence-end-double-space . t)
(fill-column . 70)))
(fill-column . 79)))
(c-mode . ((c-file-style . "GNU")))
;; You must set bugtracker_debbugs_url in your bazaar.conf for this to work.
;; See admin/notes/bugtracker.

View file

@ -1,3 +1,11 @@
2011-02-25 Stefan Monnier <monnier@iro.umontreal.ca>
* vol2.texi (Top):
* vol1.texi (Top):
* objects.texi (Programming Types, Funvec Type, Type Predicates):
* functions.texi (Functions, What Is a Function, Function Currying):
* elisp.texi (Top): Remove mentions of funvec and curry.
2011-02-19 Eli Zaretskii <eliz@gnu.org>
* elisp.texi: Sync @dircategory with ../../info/dir.

View file

@ -249,7 +249,7 @@ Programming Types
* Macro Type:: A method of expanding an expression into another
expression, more fundamental but less pretty.
* Primitive Function Type:: A function written in C, callable from Lisp.
* Funvec Type:: A vector type callable as a function.
* Byte-Code Type:: A function written in Lisp, then compiled.
* Autoload Type:: A type used for automatically loading seldom-used
functions.
@ -464,8 +464,6 @@ Functions
* Inline Functions:: Defining functions that the compiler
will open code.
* Declaring Functions:: Telling the compiler that a function is defined.
* Function Currying:: Making wrapper functions that pre-specify
some arguments.
* Function Safety:: Determining whether a function is safe to call.
* Related Topics:: Cross-references to specific Lisp primitives
that have a special bearing on how functions work.

View file

@ -23,8 +23,6 @@ define them.
of a symbol.
* Obsolete Functions:: Declaring functions obsolete.
* Inline Functions:: Defining functions that the compiler will open code.
* Function Currying:: Making wrapper functions that pre-specify
some arguments.
* Declaring Functions:: Telling the compiler that a function is defined.
* Function Safety:: Determining whether a function is safe to call.
* Related Topics:: Cross-references to specific Lisp primitives
@ -113,25 +111,7 @@ editors; for Lisp programs, the distinction is normally unimportant.
@item byte-code function
A @dfn{byte-code function} is a function that has been compiled by the
byte compiler. A byte-code function is actually a special case of a
@dfn{funvec} object (see below).
@item function vector
A @dfn{function vector}, or @dfn{funvec} is a vector-like object whose
purpose is to define special kinds of functions. @xref{Funvec Type}.
The exact meaning of the vector elements is determined by the type of
funvec: the most common use is byte-code functions, which have a
list---the argument list---as the first element. Further types of
funvec object are:
@table @code
@item curry
A curried function. Remaining arguments in the funvec are function to
call, and arguments to prepend to user arguments at the time of the
call; @xref{Function Currying}.
@end table
byte compiler. @xref{Byte-Code Type}.
@end table
@defun functionp object
@ -172,11 +152,6 @@ function. For example:
@end example
@end defun
@defun funvecp object
@code{funvecp} returns @code{t} if @var{object} is a function vector
object (including byte-code objects), and @code{nil} otherwise.
@end defun
@defun subr-arity subr
This function provides information about the argument list of a
primitive, @var{subr}. The returned value is a pair
@ -1302,49 +1277,6 @@ do for macros. (@xref{Argument Evaluation}.)
Inline functions can be used and open-coded later on in the same file,
following the definition, just like macros.
@node Function Currying
@section Function Currying
@cindex function currying
@cindex currying
@cindex partial-application
Function currying is a way to make a new function that calls an
existing function with a partially pre-determined argument list.
@defun curry function &rest args
Return a function-like object that will append any arguments it is
called with to @var{args}, and call @var{function} with the resulting
list of arguments.
For example, @code{(curry 'concat "The ")} returns a function that
concatenates @code{"The "} and its arguments. Calling this function
on @code{"end"} returns @code{"The end"}:
@example
(funcall (curry 'concat "The ") "end")
@result{} "The end"
@end example
The @dfn{curried function} is useful as an argument to @code{mapcar}:
@example
(mapcar (curry 'concat "The ") '("big" "red" "balloon"))
@result{} ("The big" "The red" "The balloon")
@end example
@end defun
Function currying may be implemented in any Lisp by constructing a
@code{lambda} expression, for instance:
@example
(defun curry (function &rest args)
`(lambda (&rest call-args)
(apply #',function ,@@args call-args)))
@end example
However in Emacs Lisp, a special curried function object is used for
efficiency. @xref{Funvec Type}.
@node Declaring Functions
@section Telling the Compiler that a Function is Defined
@cindex function declaration

View file

@ -156,7 +156,7 @@ latter are unique to Emacs Lisp.
* Macro Type:: A method of expanding an expression into another
expression, more fundamental but less pretty.
* Primitive Function Type:: A function written in C, callable from Lisp.
* Funvec Type:: A vector type callable as a function.
* Byte-Code Type:: A function written in Lisp, then compiled.
* Autoload Type:: A type used for automatically loading seldom-used
functions.
@end menu
@ -1313,55 +1313,18 @@ with the name of the subroutine.
@end group
@end example
@node Funvec Type
@subsection ``Function Vector' Type
@cindex function vector
@cindex funvec
@node Byte-Code Type
@subsection Byte-Code Function Type
A @dfn{function vector}, or @dfn{funvec} is a vector-like object whose
purpose is to define special kinds of functions. You can examine or
modify the contents of a funvec like a normal vector, using the
@code{aref} and @code{aset} functions.
The byte compiler produces @dfn{byte-code function objects}.
Internally, a byte-code function object is much like a vector; however,
the evaluator handles this data type specially when it appears as a
function to be called. @xref{Byte Compilation}, for information about
the byte compiler.
The behavior of a funvec when called is dependent on the kind of
funvec it is, and that is determined by its first element (a
zero-length funvec will signal an error if called):
@table @asis
@item A list
A funvec with a list as its first element is a byte-compiled function,
produced by the byte compiler; such funvecs are known as
@dfn{byte-code function objects}. @xref{Byte Compilation}, for
information about the byte compiler.
@item The symbol @code{curry}
A funvec with @code{curry} as its first element is a ``curried function''.
The second element in such a funvec is the function which is
being curried, and the remaining elements are a list of arguments.
Calling such a funvec operates by calling the embedded function with
an argument list composed of the arguments in the funvec followed by
the arguments the funvec was called with. @xref{Function Currying}.
@end table
The printed representation and read syntax for a funvec object is like
that for a vector, with an additional @samp{#} before the opening
@samp{[}.
@defun funvecp object
@code{funvecp} returns @code{t} if @var{object} is a function vector
object (including byte-code objects), and @code{nil} otherwise.
@end defun
@defun funvec kind &rest params
@code{funvec} returns a new function vector containing @var{kind} and
@var{params}. @var{kind} determines the type of funvec; it should be
one of the choices listed in the table above.
Typically you should use the @code{make-byte-code} function to create
byte-code objects, though they are a type of funvec.
@end defun
The printed representation and read syntax for a byte-code function
object is like that for a vector, with an additional @samp{#} before the
opening @samp{[}.
@node Autoload Type
@subsection Autoload Type
@ -1808,7 +1771,7 @@ with references to further information.
@xref{Buffer Basics, bufferp}.
@item byte-code-function-p
@xref{Funvec Type, byte-code-function-p}.
@xref{Byte-Code Type, byte-code-function-p}.
@item case-table-p
@xref{Case Tables, case-table-p}.

View file

@ -269,7 +269,7 @@ Programming Types
* Macro Type:: A method of expanding an expression into another
expression, more fundamental but less pretty.
* Primitive Function Type:: A function written in C, callable from Lisp.
* Funvec Type:: A vector type callable as a function.
* Byte-Code Type:: A function written in Lisp, then compiled.
* Autoload Type:: A type used for automatically loading seldom-used
functions.

View file

@ -268,7 +268,7 @@ Programming Types
* Macro Type:: A method of expanding an expression into another
expression, more fundamental but less pretty.
* Primitive Function Type:: A function written in C, callable from Lisp.
* Funvec Type:: A vector type callable as a function.
* Byte-Code Type:: A function written in Lisp, then compiled.
* Autoload Type:: A type used for automatically loading seldom-used
functions.

View file

@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2011
Free Software Foundation, Inc.
See the end of the file for license conditions.
@ -12,21 +12,12 @@ This file is about changes in the Emacs "lexbind" branch.
* Lisp changes in Emacs 23.1
** New `function vector' type, including function currying
The `function vector', or `funvec' type extends the old
byte-compiled-function vector type to have other uses as well, and
includes existing byte-compiled functions as a special case. The kind
of funvec is determined by the first element: a list is a byte-compiled
function, and a non-nil atom is one of the new extended uses, currently
`curry' for curried functions. See the node `Funvec Type' in the Emacs
Lisp Reference Manual for more information.
*** New function curry allows constructing `curried functions'
(see the node `Function Currying' in the Emacs Lisp Reference Manual).
*** New functions funvec and funvecp allow primitive access to funvecs
** The `lexical-binding' lets code use lexical scoping for local variables.
It is typically set via file-local variables, in which case it applies to
all the code in that file.
** Lexically scoped interpreted functions are represented with a new form
of function value which looks like (closure ENV lambda ARGS &rest BODY).
----------------------------------------------------------------------
This file is part of GNU Emacs.

View file

@ -1,3 +1,46 @@
2011-02-25 Stefan Monnier <monnier@iro.umontreal.ca>
* emacs-lisp/bytecomp.el (byte-compile-lapcode): Handle new form of
`byte-constant'.
(byte-compile-close-variables, displaying-byte-compile-warnings):
Add edebug spec.
(byte-compile-toplevel-file-form): New fun, split out of
byte-compile-file-form.
(byte-compile-from-buffer): Use it to avoid applying cconv
multiple times.
(byte-compile): Only strip `function' if it's present.
(byte-compile-lambda): Add `reserved-csts' argument.
Use new lexenv arg of byte-compile-top-level.
(byte-compile-reserved-constants): New var.
(byte-compile-constants-vector): Obey it.
(byte-compile-constants-vector): Handle new `byte-constant' form.
(byte-compile-top-level): Add args `lexenv' and `reserved-csts'.
(byte-compile-form): Don't check callargs here.
(byte-compile-normal-call): Do it here instead.
(byte-compile-push-unknown-constant)
(byte-compile-resolve-unknown-constant): Remove, unused.
(byte-compile-make-closure): Use `make-byte-code' rather than `curry',
putting the environment into the "constant" pool.
(byte-compile-get-closed-var): Use special byte-constant.
* emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): Handle new
intermediate special form `internal-make-vector'.
(byte-optimize-lapcode): Handle new form of `byte-constant'.
* help-fns.el (describe-function-1): Don't handle funvecs.
* emacs-lisp/macroexp.el (macroexpand-all-1): Only convert quote to
function if the content is a lambda expression, not if it's a closure.
* emacs-lisp/eieio-come.el: Remove.
* emacs-lisp/eieio.el: Don't require eieio-comp.
(defmethod): Do a bit more work to find the body and wrap it into
a function before passing it to eieio-defmethod.
(eieio-defmethod): New arg `code' for it.
* emacs-lisp/debug.el (debugger-setup-buffer): Don't hide things in
debugger backtrace.
* emacs-lisp/cl-extra.el (cl-macroexpand-all): Use backquotes, and be
more careful when quoting a function value.
* emacs-lisp/cconv.el (cconv-freevars): Accept defvar/defconst.
(cconv-closure-convert-rec): Catch stray `internal-make-closure'.
* Makefile.in (COMPILE_FIRST): Compile pcase and cconv early.
2011-02-21 Stefan Monnier <monnier@iro.umontreal.ca>
* emacs-lisp/cconv.el (cconv-closure-convert-rec): Let the byte

View file

@ -83,7 +83,9 @@ BIG_STACK_OPTS = --eval "(setq max-lisp-eval-depth $(BIG_STACK_DEPTH))"
COMPILE_FIRST = \
$(lisp)/emacs-lisp/bytecomp.elc \
$(lisp)/emacs-lisp/byte-opt.elc \
$(lisp)/emacs-lisp/pcase.elc \
$(lisp)/emacs-lisp/macroexp.elc \
$(lisp)/emacs-lisp/cconv.elc \
$(lisp)/emacs-lisp/autoload.elc
# The actual Emacs command run in the targets below.
@ -203,7 +205,7 @@ compile-onefile:
@echo Compiling $(THEFILE)
@# Use byte-compile-refresh-preloaded to try and work around some of
@# the most common bootstrapping problems.
@$(emacs) -l bytecomp.el -f byte-compile-refresh-preloaded \
$(emacs) -l bytecomp.el -f byte-compile-refresh-preloaded \
$(BIG_STACK_OPTS) $(BYTE_COMPILE_EXTRA_FLAGS) \
-f batch-byte-compile $(THEFILE)
@ -220,7 +222,7 @@ compile-onefile:
# cannot have prerequisites.
.el.elc:
@echo Compiling $<
@$(emacs) $(BIG_STACK_OPTS) $(BYTE_COMPILE_EXTRA_FLAGS) \
$(emacs) $(BIG_STACK_OPTS) $(BYTE_COMPILE_EXTRA_FLAGS) \
-f batch-byte-compile $<
.PHONY: compile-first compile-main compile compile-always

View file

@ -531,7 +531,11 @@
;; However, don't actually bother calling `ignore'.
`(prog1 nil . ,(mapcar 'byte-optimize-form (cdr form))))
((eq fn 'internal-make-closure)
form)
((not (symbolp fn))
(debug)
(byte-compile-warn "`%s' is a malformed function"
(prin1-to-string fn))
form)
@ -1472,7 +1476,8 @@
byte-cdr-safe byte-cons byte-list1 byte-list2 byte-point byte-point-max
byte-point-min byte-following-char byte-preceding-char
byte-current-column byte-eolp byte-eobp byte-bolp byte-bobp
byte-current-buffer byte-stack-ref))
byte-current-buffer byte-stack-ref ;; byte-closed-var
))
(defconst byte-compile-side-effect-free-ops
(nconc
@ -1680,11 +1685,18 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
;; const goto-if-* --> whatever
;;
((and (eq 'byte-constant (car lap0))
(memq (car lap1) byte-conditional-ops))
(memq (car lap1) byte-conditional-ops)
;; If the `byte-constant's cdr is not a cons cell, it has
;; to be an index into the constant pool); even though
;; it'll be a constant, that constant is not known yet
;; (it's typically a free variable of a closure, so will
;; only be known when the closure will be built at
;; run-time).
(consp (cdr lap0)))
(cond ((if (or (eq (car lap1) 'byte-goto-if-nil)
(eq (car lap1) 'byte-goto-if-nil-else-pop))
(car (cdr lap0))
(not (car (cdr lap0))))
(eq (car lap1) 'byte-goto-if-nil-else-pop))
(car (cdr lap0))
(not (car (cdr lap0))))
(byte-compile-log-lap " %s %s\t-->\t<deleted>"
lap0 lap1)
(setq rest (cdr rest)
@ -1696,11 +1708,11 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
(when (memq (car lap1) byte-goto-always-pop-ops)
(setq lap (delq lap0 lap)))
(setcar lap1 'byte-goto)))
(setq keep-going t))
(setq keep-going t))
;;
;; varref-X varref-X --> varref-X dup
;; varref-X [dup ...] varref-X --> varref-X [dup ...] dup
;; stackref-X [dup ...] stackref-X+N --> stackref-X [dup ...] dup
;; stackref-X [dup ...] stackref-X+N --> stackref-X [dup ...] dup
;; We don't optimize the const-X variations on this here,
;; because that would inhibit some goto optimizations; we
;; optimize the const-X case after all other optimizations.
@ -1877,18 +1889,21 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
(cons 'byte-discard byte-conditional-ops)))
(not (eq lap1 (car tmp))))
(setq tmp2 (car tmp))
(cond ((memq (car tmp2)
(if (null (car (cdr lap0)))
'(byte-goto-if-nil byte-goto-if-nil-else-pop)
'(byte-goto-if-not-nil
byte-goto-if-not-nil-else-pop)))
(cond ((when (consp (cdr lap0))
(memq (car tmp2)
(if (null (car (cdr lap0)))
'(byte-goto-if-nil byte-goto-if-nil-else-pop)
'(byte-goto-if-not-nil
byte-goto-if-not-nil-else-pop))))
(byte-compile-log-lap " %s goto [%s]\t-->\t%s %s"
lap0 tmp2 lap0 tmp2)
(setcar lap1 (car tmp2))
(setcdr lap1 (cdr tmp2))
;; Let next step fix the (const,goto-if*) sequence.
(setq rest (cons nil rest)))
(t
(setq rest (cons nil rest))
(setq keep-going t))
((or (consp (cdr lap0))
(eq (car tmp2) 'byte-discard))
;; Jump one step further
(byte-compile-log-lap
" %s goto [%s]\t-->\t<deleted> goto <skip>"
@ -1897,8 +1912,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
(setcdr tmp (cons (byte-compile-make-tag)
(cdr tmp))))
(setcdr lap1 (car (cdr tmp)))
(setq lap (delq lap0 lap))))
(setq keep-going t))
(setq lap (delq lap0 lap))
(setq keep-going t))))
;;
;; X: varref-Y ... varset-Y goto-X -->
;; X: varref-Y Z: ... dup varset-Y goto-Z

View file

@ -794,10 +794,13 @@ CONST2 may be evaulated multiple times."
;; goto
(byte-compile-push-bytecodes opcode nil (cdr off) bytes pc)
(push bytes patchlist))
((and (consp off)
;; Variable or constant reference
(progn (setq off (cdr off))
(eq op 'byte-constant)))
((or (and (consp off)
;; Variable or constant reference
(progn
(setq off (cdr off))
(eq op 'byte-constant)))
(and (eq op 'byte-constant) ;; 'byte-closed-var
(integerp off)))
;; constant ref
(if (< off byte-constant-limit)
(byte-compile-push-bytecodes (+ byte-constant off)
@ -1480,6 +1483,7 @@ symbol itself."
((byte-compile-const-symbol-p ,form))))
(defmacro byte-compile-close-variables (&rest body)
(declare (debug t))
(cons 'let
(cons '(;;
;; Close over these variables to encapsulate the
@ -1510,6 +1514,7 @@ symbol itself."
body)))
(defmacro displaying-byte-compile-warnings (&rest body)
(declare (debug t))
`(let* ((--displaying-byte-compile-warnings-fn (lambda () ,@body))
(warning-series-started
(and (markerp warning-series)
@ -1930,7 +1935,7 @@ With argument ARG, insert value in current buffer after the form."
(byte-compile-warn "!! The file uses old-style backquotes !!
This functionality has been obsolete for more than 10 years already
and will be removed soon. See (elisp)Backquote in the manual."))
(byte-compile-file-form form)))
(byte-compile-toplevel-file-form form)))
;; Compile pending forms at end of file.
(byte-compile-flush-pending)
;; Make warnings about unresolved functions
@ -2041,8 +2046,8 @@ Call from the source buffer."
;; defalias calls are output directly by byte-compile-file-form-defmumble;
;; it does not pay to first build the defalias in defmumble and then parse
;; it here.
(if (and (memq (car-safe form) '(defun defmacro defvar defvaralias defconst autoload
custom-declare-variable))
(if (and (memq (car-safe form) '(defun defmacro defvar defvaralias defconst
autoload custom-declare-variable))
(stringp (nth 3 form)))
(byte-compile-output-docform nil nil '("\n(" 3 ")") form nil
(memq (car form)
@ -2182,12 +2187,17 @@ list that represents a doc string reference.
byte-compile-maxdepth 0
byte-compile-output nil))))
(defun byte-compile-file-form (form)
(let ((byte-compile-current-form nil) ; close over this for warnings.
bytecomp-handler)
;; byte-hunk-handlers cannot call this!
(defun byte-compile-toplevel-file-form (form)
(let ((byte-compile-current-form nil)) ; close over this for warnings.
(setq form (macroexpand-all form byte-compile-macro-environment))
(if lexical-binding
(setq form (cconv-closure-convert form)))
(byte-compile-file-form form)))
;; byte-hunk-handlers can call this.
(defun byte-compile-file-form (form)
(let (bytecomp-handler)
(cond ((not (consp form))
(byte-compile-keep-pending form))
((and (symbolp (car form))
@ -2541,7 +2551,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(if lexical-binding
(setq fun (cconv-closure-convert fun)))
;; Get rid of the `function' quote added by the `lambda' macro.
(setq fun (cadr fun))
(if (eq (car-safe fun) 'function) (setq fun (cadr fun)))
(setq fun (if macro
(cons 'macro (byte-compile-lambda fun))
(byte-compile-lambda fun)))
@ -2654,7 +2664,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
;; of the list FUN and `byte-compile-set-symbol-position' is not called.
;; Use this feature to avoid calling `byte-compile-set-symbol-position'
;; for symbols generated by the byte compiler itself.
(defun byte-compile-lambda (bytecomp-fun &optional add-lambda)
(defun byte-compile-lambda (bytecomp-fun &optional add-lambda reserved-csts)
(if add-lambda
(setq bytecomp-fun (cons 'lambda bytecomp-fun))
(unless (eq 'lambda (car-safe bytecomp-fun))
@ -2702,14 +2712,16 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(byte-compile-warn "malformed interactive spec: %s"
(prin1-to-string bytecomp-int)))))
;; Process the body.
(let* ((byte-compile-lexical-environment
;; If doing lexical binding, push a new lexical environment
;; containing just the args (since lambda expressions
;; should be closed by now).
(and lexical-binding
(byte-compile-make-lambda-lexenv bytecomp-fun)))
(compiled
(byte-compile-top-level (cons 'progn bytecomp-body) nil 'lambda)))
(let* ((compiled
(byte-compile-top-level (cons 'progn bytecomp-body) nil 'lambda
;; If doing lexical binding, push a new
;; lexical environment containing just the
;; args (since lambda expressions should be
;; closed by now).
(and lexical-binding
(byte-compile-make-lambda-lexenv
bytecomp-fun))
reserved-csts)))
;; Build the actual byte-coded function.
(if (eq 'byte-code (car-safe compiled))
(apply 'make-byte-code
@ -2740,6 +2752,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
;; A simple lambda is just a constant.
(byte-compile-constant code)))
(defvar byte-compile-reserved-constants 0)
(defun byte-compile-constants-vector ()
;; Builds the constants-vector from the current variables and constants.
;; This modifies the constants from (const . nil) to (const . offset).
@ -2748,7 +2762,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
;; Next up to byte-constant-limit are constants, still with one-byte codes.
;; Next variables again, to get 2-byte codes for variable lookup.
;; The rest of the constants and variables need 3-byte byte-codes.
(let* ((i -1)
(let* ((i (1- byte-compile-reserved-constants))
(rest (nreverse byte-compile-variables)) ; nreverse because the first
(other (nreverse byte-compile-constants)) ; vars often are used most.
ret tmp
@ -2759,11 +2773,15 @@ If FORM is a lambda or a macro, byte-compile it as a function."
limit)
(while (or rest other)
(setq limit (car limits))
(while (and rest (not (eq i limit)))
(if (setq tmp (assq (car (car rest)) ret))
(setcdr (car rest) (cdr tmp))
(while (and rest (< i limit))
(cond
((numberp (car rest))
(assert (< (car rest) byte-compile-reserved-constants)))
((setq tmp (assq (car (car rest)) ret))
(setcdr (car rest) (cdr tmp)))
(t
(setcdr (car rest) (setq i (1+ i)))
(setq ret (cons (car rest) ret)))
(setq ret (cons (car rest) ret))))
(setq rest (cdr rest)))
(setq limits (cdr limits)
rest (prog1 other
@ -2772,7 +2790,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
;; Given an expression FORM, compile it and return an equivalent byte-code
;; expression (a call to the function byte-code).
(defun byte-compile-top-level (form &optional for-effect output-type)
(defun byte-compile-top-level (form &optional for-effect output-type
lexenv reserved-csts)
;; OUTPUT-TYPE advises about how form is expected to be used:
;; 'eval or nil -> a single form,
;; 'progn or t -> a list of forms,
@ -2783,9 +2802,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(byte-compile-tag-number 0)
(byte-compile-depth 0)
(byte-compile-maxdepth 0)
(byte-compile-lexical-environment
(when (eq output-type 'lambda)
byte-compile-lexical-environment))
(byte-compile-lexical-environment lexenv)
(byte-compile-reserved-constants (or reserved-csts 0))
(byte-compile-output nil))
(if (memq byte-optimize '(t source))
(setq form (byte-optimize-form form for-effect)))
@ -2904,6 +2922,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(bytecomp-body
(list bytecomp-body))))
;; FIXME: Like defsubst's, this hunk-handler won't be called any more
;; because the macro is expanded away before we see it.
(put 'declare-function 'byte-hunk-handler 'byte-compile-declare-function)
(defun byte-compile-declare-function (form)
(push (cons (nth 1 form)
@ -2950,12 +2970,6 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(memq bytecomp-fn byte-compile-interactive-only-functions)
(byte-compile-warn "`%s' used from Lisp code\n\
That command is designed for interactive use only" bytecomp-fn))
(when (byte-compile-warning-enabled-p 'callargs)
(if (memq bytecomp-fn
'(custom-declare-group custom-declare-variable
custom-declare-face))
(byte-compile-nogroup-warn form))
(byte-compile-callargs-warn form))
(if (and (fboundp (car form))
(eq (car-safe (symbol-function (car form))) 'macro))
(byte-compile-report-error
@ -2985,6 +2999,13 @@ That command is designed for interactive use only" bytecomp-fn))
(byte-compile-discard)))
(defun byte-compile-normal-call (form)
(when (and (byte-compile-warning-enabled-p 'callargs)
(symbolp (car form)))
(if (memq (car form)
'(custom-declare-group custom-declare-variable
custom-declare-face))
(byte-compile-nogroup-warn form))
(byte-compile-callargs-warn form))
(if byte-compile-generate-call-tree
(byte-compile-annotate-call-tree form))
(when (and for-effect (eq (car form) 'mapcar)
@ -3037,7 +3058,7 @@ If BINDING is non-nil, VAR is being bound."
(boundp var)
(memq var byte-compile-bound-variables)
(memq var byte-compile-free-references))
(byte-compile-warn "reference to free variable `%s'" var)
(byte-compile-warn "reference to free variable `%S'" var)
(push var byte-compile-free-references))
(byte-compile-dynamic-variable-op 'byte-varref var))))
@ -3082,26 +3103,6 @@ If BINDING is non-nil, VAR is being bound."
(defun byte-compile-push-constant (const)
(let ((for-effect nil))
(inline (byte-compile-constant const))))
(defun byte-compile-push-unknown-constant (&optional id)
"Generate code to push a `constant' who's value isn't known yet.
A tag is returned which may then later be passed to
`byte-compile-resolve-unknown-constant' to finalize the value.
The optional argument ID is a tag returned by an earlier call to
`byte-compile-push-unknown-constant', in which case the same constant is
pushed again."
(unless id
(setq id (list (make-symbol "unknown")))
(push id byte-compile-constants))
(byte-compile-out 'byte-constant id)
id)
(defun byte-compile-resolve-unknown-constant (id value)
"Give an `unknown constant' a value.
ID is the tag returned by `byte-compile-push-unknown-constant'. and VALUE
is the value it should have."
(setcar id value))
;; Compile those primitive ordinary functions
;; which have special byte codes just for speed.
@ -3345,18 +3346,23 @@ discarding."
(defconst byte-compile--env-var (make-symbol "env"))
(defun byte-compile-make-closure (form)
;; FIXME: don't use `curry'!
(byte-compile-form
(unless for-effect
`(curry (function (lambda (,byte-compile--env-var . ,(nth 1 form))
. ,(nthcdr 3 form)))
(vector . ,(nth 2 form))))
for-effect))
(if for-effect (setq for-effect nil)
(let* ((vars (nth 1 form))
(env (nth 2 form))
(body (nthcdr 3 form))
(fun
(byte-compile-lambda `(lambda ,vars . ,body) nil (length env))))
(assert (byte-code-function-p fun))
(byte-compile-form `(make-byte-code
',(aref fun 0) ',(aref fun 1)
(vconcat (vector . ,env) ',(aref fun 2))
,@(nthcdr 3 (mapcar (lambda (x) `',x) fun)))))))
(defun byte-compile-get-closed-var (form)
(byte-compile-form (unless for-effect
`(aref ,byte-compile--env-var ,(nth 1 form)))
for-effect))
(if for-effect (setq for-effect nil)
(byte-compile-out 'byte-constant ;; byte-closed-var
(nth 1 form))))
;; Compile a function that accepts one or more args and is right-associative.
;; We do it by left-associativity so that the operations

View file

@ -47,19 +47,14 @@
;; (lambda (v1 ...) ... fv1 fv2 ...) => (lambda (v1 ... fv1 fv2 ) ... fv1 fv2 .)
;; if the function is suitable for lambda lifting (if all calls are known)
;;
;; (lambda (v1 ...) ... fv ...) =>
;; (curry (lambda (env v1 ...) ... env ...) env)
;; if the function has only 1 free variable
;;
;; and finally
;; (lambda (v1 ...) ... fv1 fv2 ...) =>
;; (curry (lambda (env v1 ..) .. (aref env 0) (aref env 1) ..) (vector fv1 fv2))
;; if the function has 2 or more free variables.
;; (lambda (v0 ...) ... fv0 .. fv1 ...) =>
;; (internal-make-closure (v0 ...) (fv1 ...)
;; ... (internal-get-closed-var 0) ... (internal-get-closed-var 1) ...)
;;
;; If the function has no free variables, we don't do anything.
;;
;; If a variable is mutated (updated by setq), and it is used in a closure
;; we wrap it's definition with list: (list val) and we also replace
;; we wrap its definition with list: (list val) and we also replace
;; var => (car var) wherever this variable is used, and also
;; (setq var value) => (setcar var value) where it is updated.
;;
@ -71,15 +66,12 @@
;;; Code:
;;; TODO:
;; - pay attention to `interactive': its arg is run in an empty env.
;; - canonize code in macro-expand so we don't have to handle (let (var) body)
;; and other oddities.
;; - Change new byte-code representation, so it directly gives the
;; number of mandatory and optional arguments as well as whether or
;; not there's a &rest arg.
;; - Use abstract `make-closure' and `closure-ref' expressions, which bytecomp
;; should turn into building corresponding byte-code function.
;; - don't use `curry', instead build a new compiled-byte-code object
;; (merge the closure env into the static constants pool).
;; - warn about unused lexical vars.
;; - clean up cconv-closure-convert-rec, especially the `let' binding part.
;; - new byte codes for unwind-protect, catch, and condition-case so that
@ -184,8 +176,8 @@ Returns a list of free variables."
;; We call cconv-freevars only for functions(lambdas)
;; defun, defconst, defvar are not allowed to be inside
;; a function (lambda).
;; FIXME: should be a byte-compile-report-error!
(error "Invalid form: %s inside a function" sym))
;; (error "Invalid form: %s inside a function" sym)
(cconv-freevars `(progn ,@(cddr form)) fvrs))
(`(,_ . ,body-forms) ; First element is (like) a function.
(dolist (exp body-forms)
@ -537,6 +529,9 @@ Returns a form where all lambdas don't have any free variables."
`(internal-make-closure
,vars ,envector . ,body-forms-new)))))
(`(internal-make-closure . ,_)
(error "Internal byte-compiler error: cconv called twice"))
(`(function . ,_) form) ; Same as quote.
;defconst, defvar
@ -599,20 +594,18 @@ Returns a form where all lambdas don't have any free variables."
;condition-case
(`(condition-case ,var ,protected-form . ,handlers)
(let ((handlers-new '())
(newform (cconv-closure-convert-rec
(let ((newform (cconv-closure-convert-rec
`(function (lambda () ,protected-form))
emvrs fvrs envs lmenvs)))
(setq fvrs (remq var fvrs))
(dolist (handler handlers)
(push (list (car handler)
(cconv-closure-convert-rec
`(function (lambda (,(or var cconv--dummy-var))
,@(cdr handler)))
emvrs fvrs envs lmenvs))
handlers-new))
`(condition-case :fun-body ,newform
,@(nreverse handlers-new))))
,@(mapcar (lambda (handler)
(list (car handler)
(cconv-closure-convert-rec
(let ((arg (or var cconv--dummy-var)))
`(function (lambda (,arg) ,@(cdr handler))))
emvrs fvrs envs lmenvs)))
handlers))))
(`(,(and head (or `catch `unwind-protect)) ,form . ,body)
`(,head ,(cconv-closure-convert-rec form emvrs fvrs envs lmenvs)

View file

@ -766,21 +766,15 @@ This also does some trivial optimizations to make the form prettier."
(eq (car-safe (car body)) 'interactive))
(push (list 'quote (pop body)) decls))
(put (car (last cl-closure-vars)) 'used t)
(append
(list 'list '(quote lambda) '(quote (&rest --cl-rest--)))
(sublis sub (nreverse decls))
(list
(list* 'list '(quote apply)
(list 'quote
(list 'function
(list* 'lambda
(append new (cadadr form))
(sublis sub body))))
(nconc (mapcar (function
(lambda (x)
(list 'list '(quote quote) x)))
cl-closure-vars)
'((quote --cl-rest--)))))))
`(list 'lambda '(&rest --cl-rest--)
,@(sublis sub (nreverse decls))
(list 'apply
(list 'quote
#'(lambda ,(append new (cadadr form))
,@(sublis sub body)))
,@(nconc (mapcar (lambda (x) `(list 'quote ,x))
cl-closure-vars)
'((quote --cl-rest--))))))
(list (car form) (list* 'lambda (cadadr form) body))))
(let ((found (assq (cadr form) env)))
(if (and found (ignore-errors

View file

@ -10,7 +10,7 @@
;;;;;; ceiling* floor* isqrt lcm gcd cl-progv-before cl-set-frame-visible-p
;;;;;; cl-map-overlays cl-map-intervals cl-map-keymap-recursively
;;;;;; notevery notany every some mapcon mapcan mapl maplist map
;;;;;; cl-mapcar-many equalp coerce) "cl-extra" "cl-extra.el" "2bfbae6523c842d511b8c8d88658825a")
;;;;;; cl-mapcar-many equalp coerce) "cl-extra" "cl-extra.el" "26339d9571f9485bf34fa6d2ae38fc84")
;;; Generated autoloads from cl-extra.el
(autoload 'coerce "cl-extra" "\

View file

@ -269,8 +269,9 @@ That buffer should be current already."
(setq buffer-undo-list t)
(let ((standard-output (current-buffer))
(print-escape-newlines t)
(print-level 8)
(print-length 50))
(print-level 1000) ;8
;; (print-length 50)
)
(backtrace))
(goto-char (point-min))
(delete-region (point)

View file

@ -1,145 +0,0 @@
;;; eieio-comp.el -- eieio routines to help with byte compilation
;; Copyright (C) 1995-1996, 1998-2002, 2005, 2008-2011
;; Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Version: 0.2
;; Keywords: lisp, tools
;; Package: eieio
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Byte compiler functions for defmethod. This will affect the new GNU
;; byte compiler for Emacs 19 and better. This function will be called by
;; the byte compiler whenever a `defmethod' is encountered in a file.
;; It will output a function call to `eieio-defmethod' with the byte
;; compiled function as a parameter.
;;; Code:
(declare-function eieio-defgeneric-form "eieio" (method doc-string))
;; Some compatibility stuff
(eval-and-compile
(if (not (fboundp 'byte-compile-compiled-obj-to-list))
(defun byte-compile-compiled-obj-to-list (moose) nil))
(if (not (boundp 'byte-compile-outbuffer))
(defvar byte-compile-outbuffer nil))
)
;; This teaches the byte compiler how to do this sort of thing.
(put 'defmethod 'byte-hunk-handler 'eieio-byte-compile-file-form-defmethod)
(defun eieio-byte-compile-file-form-defmethod (form)
"Mumble about the method we are compiling.
This function is mostly ripped from `byte-compile-file-form-defun',
but it's been modified to handle the special syntax of the `defmethod'
command. There should probably be one for `defgeneric' as well, but
that is called but rarely. Argument FORM is the body of the method."
(setq form (cdr form))
(let* ((meth (car form))
(key (progn (setq form (cdr form))
(cond ((or (eq ':BEFORE (car form))
(eq ':before (car form)))
(setq form (cdr form))
":before ")
((or (eq ':AFTER (car form))
(eq ':after (car form)))
(setq form (cdr form))
":after ")
((or (eq ':PRIMARY (car form))
(eq ':primary (car form)))
(setq form (cdr form))
":primary ")
((or (eq ':STATIC (car form))
(eq ':static (car form)))
(setq form (cdr form))
":static ")
(t ""))))
(params (car form))
(lamparams (eieio-byte-compile-defmethod-param-convert params))
(arg1 (car params))
(class (if (listp arg1) (nth 1 arg1) nil))
(my-outbuffer (if (eval-when-compile (featurep 'xemacs))
byte-compile-outbuffer
(cond ((boundp 'bytecomp-outbuffer)
bytecomp-outbuffer) ; Emacs >= 23.2
((boundp 'outbuffer) outbuffer)
(t (error "Unable to set outbuffer"))))))
(let ((name (format "%s::%s" (or class "#<generic>") meth)))
(if byte-compile-verbose
;; #### filename used free
(message "Compiling %s... (%s)"
(cond ((boundp 'bytecomp-filename) bytecomp-filename)
((boundp 'filename) filename)
(t ""))
name))
(setq byte-compile-current-form name) ; for warnings
)
;; Flush any pending output
(byte-compile-flush-pending)
;; Byte compile the body. For the byte compiled forms, add the
;; rest arguments, which will get ignored by the engine which will
;; add them later (I hope)
;; FIXME: This relies on compiler's internal. Make sure it still
;; works with lexical-binding code. Maybe calling `byte-compile'
;; would be preferable.
(let* ((new-one (byte-compile-lambda
(append (list 'lambda lamparams)
(cdr form))))
(code (byte-compile-byte-code-maker new-one)))
(princ "\n(eieio-defmethod '" my-outbuffer)
(princ meth my-outbuffer)
(princ " '(" my-outbuffer)
(princ key my-outbuffer)
(prin1 params my-outbuffer)
(princ " " my-outbuffer)
(prin1 code my-outbuffer)
(princ "))" my-outbuffer)
)
;; Now add this function to the list of known functions.
;; Don't bother with a doc string. Not relevant here.
(add-to-list 'byte-compile-function-environment
(cons meth
(eieio-defgeneric-form meth "")))
;; Remove it from the undefined list if it is there.
(let ((elt (assq meth byte-compile-unresolved-functions)))
(if elt (setq byte-compile-unresolved-functions
(delq elt byte-compile-unresolved-functions))))
;; nil prevents cruft from appearing in the output buffer.
nil))
(defun eieio-byte-compile-defmethod-param-convert (paramlist)
"Convert method params into the params used by the `defmethod' thingy.
Argument PARAMLIST is the parameter list to convert."
(let ((argfix nil))
(while paramlist
(setq argfix (cons (if (listp (car paramlist))
(car (car paramlist))
(car paramlist))
argfix))
(setq paramlist (cdr paramlist)))
(nreverse argfix)))
(provide 'eieio-comp)
;;; eieio-comp.el ends here

View file

@ -45,8 +45,7 @@
;;; Code:
(eval-when-compile
(require 'cl)
(require 'eieio-comp))
(require 'cl))
(defvar eieio-version "1.3"
"Current version of EIEIO.")
@ -123,6 +122,7 @@ execute a `call-next-method'. DO NOT SET THIS YOURSELF!")
;; while it is being built itself.
(defvar eieio-default-superclass nil)
;; FIXME: The constants below should have a `eieio-' prefix added!!
(defconst class-symbol 1 "Class's symbol (self-referencing.).")
(defconst class-parent 2 "Class parent slot.")
(defconst class-children 3 "Class children class slot.")
@ -181,10 +181,6 @@ Stored outright without modifications or stripping.")
(t key) ;; already generic.. maybe.
))
;; How to specialty compile stuff.
(autoload 'eieio-byte-compile-file-form-defmethod "eieio-comp"
"This function is used to byte compile methods in a nice way.")
(put 'defmethod 'byte-hunk-handler 'eieio-byte-compile-file-form-defmethod)
;;; Important macros used in eieio.
;;
@ -1293,9 +1289,35 @@ Summary:
((typearg class-name) arg2 &optional opt &rest rest)
\"doc-string\"
body)"
`(eieio-defmethod (quote ,method) (quote ,args)))
(let* ((key (cond ((or (eq ':BEFORE (car args))
(eq ':before (car args)))
(setq args (cdr args))
:before)
((or (eq ':AFTER (car args))
(eq ':after (car args)))
(setq args (cdr args))
:after)
((or (eq ':PRIMARY (car args))
(eq ':primary (car args)))
(setq args (cdr args))
:primary)
((or (eq ':STATIC (car args))
(eq ':static (car args)))
(setq args (cdr args))
:static)
(t nil)))
(params (car args))
(lamparams
(mapcar (lambda (param) (if (listp param) (car param) param))
params))
(arg1 (car params))
(class (if (listp arg1) (nth 1 arg1) nil)))
`(eieio-defmethod ',method
'(,@(if key (list key))
,params)
(lambda ,lamparams ,@(cdr args)))))
(defun eieio-defmethod (method args)
(defun eieio-defmethod (method args &optional code)
"Work part of the `defmethod' macro defining METHOD with ARGS."
(let ((key nil) (body nil) (firstarg nil) (argfix nil) (argclass nil) loopa)
;; find optional keys
@ -1349,10 +1371,7 @@ Summary:
;; generics are higher
(setq key (eieio-specialized-key-to-generic-key key)))
;; Put this lambda into the symbol so we can find it
(if (byte-code-function-p (car-safe body))
(eieiomt-add method (car-safe body) key argclass)
(eieiomt-add method (append (list 'lambda (reverse argfix)) body)
key argclass))
(eieiomt-add method code key argclass)
)
(when eieio-optimize-primary-methods-flag

View file

@ -153,13 +153,14 @@ Assumes the caller has bound `macroexpand-all-environment'."
;; here, so that any code that cares about the difference will
;; see the same transformation.
;; First arg is a function:
(`(,(and fun (or `apply `mapcar `mapatoms `mapconcat `mapc)) ',f . ,args)
(`(,(and fun (or `apply `mapcar `mapatoms `mapconcat `mapc))
',(and f `(lambda . ,_)) . ,args)
;; We don't use `maybe-cons' since there's clearly a change.
(cons fun
(cons (macroexpand-all-1 (list 'function f))
(macroexpand-all-forms args))))
;; Second arg is a function:
(`(,(and fun (or `sort)) ,arg1 ',f . ,args)
(`(,(and fun (or `sort)) ,arg1 ',(and f `(lambda . ,_)) . ,args)
;; We don't use `maybe-cons' since there's clearly a change.
(cons fun
(cons (macroexpand-all-1 arg1)

View file

@ -363,13 +363,6 @@ suitable file is found, return nil."
(concat beg "built-in function")))
((byte-code-function-p def)
(concat beg "compiled Lisp function"))
((and (funvecp def) (eq (aref def 0) 'curry))
(if (symbolp (aref def 1))
(format "a curried function calling `%s'" (aref def 1))
"a curried function"))
((funvecp def)
(format "a function-vector (funvec) of type `%s'"
(aref def 0)))
((symbolp def)
(while (and (fboundp def)
(symbolp (symbol-function def)))
@ -510,21 +503,6 @@ suitable file is found, return nil."
((or (stringp def)
(vectorp def))
(format "\nMacro: %s" (format-kbd-macro def)))
((and (funvecp def) (eq (aref def 0) 'curry))
;; Describe a curried-function's function and args
(let ((slot 0))
(mapconcat (lambda (arg)
(setq slot (1+ slot))
(cond
((= slot 1) "")
((= slot 2)
(format " Function: %S" arg))
(t
(format "Argument %d: %S"
(- slot 3) arg))))
def
"\n")))
((funvecp def) nil)
(t "[Missing arglist. Please make a bug report.]")))
(high (help-highlight-arguments use doc)))
(let ((fill-begin (point)))

View file

@ -1,3 +1,23 @@
2011-02-25 Stefan Monnier <monnier@iro.umontreal.ca>
* eval.c (Qcurry): Remove.
(funcall_funvec): Remove.
(funcall_lambda): Move new byte-code handling to reduce impact.
Treat all args as lexical in the case of lexbind.
(Fcurry): Remove.
* data.c (Qfunction_vector): Remove.
(Ffunvecp): Remove.
* lread.c (read1): Revert to calling make_byte_code here.
(read_vector): Don't call make_byte_code any more.
* lisp.h (enum pvec_type): Rename back to PVEC_COMPILED.
(XSETCOMPILED): Rename back from XSETFUNVEC.
(FUNVEC_SIZE): Remove.
(FUNVEC_COMPILED_TAG_P, FUNVEC_COMPILED_P): Remove.
(COMPILEDP): Rename back from FUNVECP.
* fns.c (Felt): Remove unexplained FUNVEC check.
* doc.c (Fdocumentation): Don't handle funvec.
* alloc.c (make_funvec, Ffunvec): Remove.
2011-02-21 Stefan Monnier <monnier@iro.umontreal.ca>
* bytecode.c (exec_byte_code): Change stack_ref and stack_set to use
@ -113,6 +133,42 @@
Merge funvec patch.
2004-05-20 Miles Bader <miles@gnu.org>
* lisp.h: Declare make_funvec and Ffunvec.
(enum pvec_type): Rename `PVEC_COMPILED' to `PVEC_FUNVEC'.
(XSETFUNVEC): Rename from `XSETCOMPILED'.
(FUNVEC_SIZE, FUNVEC_COMPILED_TAG_P, FUNVEC_COMPILED_P): New macros.
(COMPILEDP): Define in terms of funvec macros.
(FUNVECP, GC_FUNVECP): Rename from `COMPILEDP' & `GC_COMPILEDP'.
(FUNCTIONP): Use FUNVECP instead of COMPILEDP.
* alloc.c (make_funvec, funvec): New functions.
(Fmake_byte_code): Make sure the first element is a list.
* eval.c (Qcurry): New variable.
(funcall_funvec, Fcurry): New functions.
(syms_of_eval): Initialize them.
(funcall_lambda): Handle non-bytecode funvec objects by calling
funcall_funvec.
(Ffuncall, Feval): Use FUNVECP insetad of COMPILEDP.
* lread.c (read1): Return result of read_vector for `#[' syntax
directly; read_vector now does any extra work required.
(read_vector): Handle both funvec and byte-code objects, converting the
type as necessary. `bytecodeflag' argument is now called
`read_funvec'.
* data.c (Ffunvecp): New function.
* doc.c (Fdocumentation): Return nil for unknown funvecs.
* fns.c (mapcar1, Felt, concat): Allow funvecs.
* eval.c (Ffunctionp): Use `funvec' operators instead of `compiled'
operators.
* alloc.c (Fmake_byte_code, Fpurecopy, mark_object): Likewise.
* keyboard.c (Fcommand_execute): Likewise.
* image.c (parse_image_spec): Likewise.
* fns.c (Flength, concat, internal_equal): Likewise.
* data.c (Faref, Ftype_of): Likewise.
* print.c (print_preprocess, print_object): Likewise.
2004-04-10 Miles Bader <miles@gnu.org>
* eval.c (Fspecialp): New function.

View file

@ -1,37 +0,0 @@
2004-05-20 Miles Bader <miles@gnu.org>
* lisp.h: Declare make_funvec and Ffunvec.
(enum pvec_type): Rename `PVEC_COMPILED' to `PVEC_FUNVEC'.
(XSETFUNVEC): Renamed from `XSETCOMPILED'.
(FUNVEC_SIZE, FUNVEC_COMPILED_TAG_P, FUNVEC_COMPILED_P): New macros.
(COMPILEDP): Define in terms of funvec macros.
(FUNVECP, GC_FUNVECP): Renamed from `COMPILEDP' & `GC_COMPILEDP'.
(FUNCTIONP): Use FUNVECP instead of COMPILEDP.
* alloc.c (make_funvec, funvec): New functions.
(Fmake_byte_code): Make sure the first element is a list.
* eval.c (Qcurry): New variable.
(funcall_funvec, Fcurry): New functions.
(syms_of_eval): Initialize them.
(funcall_lambda): Handle non-bytecode funvec objects by calling
funcall_funvec.
(Ffuncall, Feval): Use FUNVECP insetad of COMPILEDP.
* lread.c (read1): Return result of read_vector for `#[' syntax
directly; read_vector now does any extra work required.
(read_vector): Handle both funvec and byte-code objects, converting the
type as necessary. `bytecodeflag' argument is now called
`read_funvec'.
* data.c (Ffunvecp): New function.
* doc.c (Fdocumentation): Return nil for unknown funvecs.
* fns.c (mapcar1, Felt, concat): Allow funvecs.
* eval.c (Ffunctionp): Use `funvec' operators instead of `compiled'
operators.
* alloc.c (Fmake_byte_code, Fpurecopy, mark_object): Likewise.
* keyboard.c (Fcommand_execute): Likewise.
* image.c (parse_image_spec): Likewise.
* fns.c (Flength, concat, internal_equal): Likewise.
* data.c (Faref, Ftype_of): Likewise.
* print.c (print_preprocess, print_object): Likewise.
;; arch-tag: f35a6a00-4a11-4739-a4b6-9cf98296f315

View file

@ -2924,37 +2924,6 @@ See also the function `vector'. */)
}
/* Return a new `function vector' containing KIND as the first element,
followed by NUM_NIL_SLOTS nil elements, and further elements copied from
the vector PARAMS of length NUM_PARAMS (so the total length of the
resulting vector is 1 + NUM_NIL_SLOTS + NUM_PARAMS).
If NUM_PARAMS is zero, then PARAMS may be NULL.
A `function vector', a.k.a. `funvec', is a funcallable vector in Emacs Lisp.
See the function `funvec' for more detail. */
Lisp_Object
make_funvec (Lisp_Object kind, int num_nil_slots, int num_params,
Lisp_Object *params)
{
int param_index;
Lisp_Object funvec;
funvec = Fmake_vector (make_number (1 + num_nil_slots + num_params), Qnil);
ASET (funvec, 0, kind);
for (param_index = 0; param_index < num_params; param_index++)
ASET (funvec, 1 + num_nil_slots + param_index, params[param_index]);
XSETPVECTYPE (XVECTOR (funvec), PVEC_FUNVEC);
XSETFUNVEC (funvec, XVECTOR (funvec));
return funvec;
}
DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
doc: /* Return a newly created vector with specified arguments as elements.
Any number of arguments, even zero arguments, are allowed.
@ -2974,27 +2943,6 @@ usage: (vector &rest OBJECTS) */)
}
DEFUN ("funvec", Ffunvec, Sfunvec, 1, MANY, 0,
doc: /* Return a newly created `function vector' of type KIND.
A `function vector', a.k.a. `funvec', is a funcallable vector in Emacs Lisp.
KIND indicates the kind of funvec, and determines its behavior when called.
The meaning of the remaining arguments depends on KIND. Currently
implemented values of KIND, and their meaning, are:
A list -- A byte-compiled function. See `make-byte-code' for the usual
way to create byte-compiled functions.
`curry' -- A curried function. Remaining arguments are a function to
call, and arguments to prepend to user arguments at the
time of the call; see the `curry' function.
usage: (funvec KIND &rest PARAMS) */)
(int nargs, Lisp_Object *args)
{
return make_funvec (args[0], 0, nargs - 1, args + 1);
}
DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0,
doc: /* Create a byte-code object with specified arguments as elements.
The arguments should be the arglist, bytecode-string, constant vector,
@ -3008,10 +2956,6 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
register int index;
register struct Lisp_Vector *p;
/* Make sure the arg-list is really a list, as that's what's used to
distinguish a byte-compiled object from other funvecs. */
CHECK_LIST (args[0]);
XSETFASTINT (len, nargs);
if (!NILP (Vpurify_flag))
val = make_pure_vector ((EMACS_INT) nargs);
@ -3033,8 +2977,8 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
args[index] = Fpurecopy (args[index]);
p->contents[index] = args[index];
}
XSETPVECTYPE (p, PVEC_FUNVEC);
XSETFUNVEC (val, p);
XSETPVECTYPE (p, PVEC_COMPILED);
XSETCOMPILED (val, p);
return val;
}
@ -4817,7 +4761,7 @@ Does not copy symbols. Copies strings without text properties. */)
obj = make_pure_string (SSDATA (obj), SCHARS (obj),
SBYTES (obj),
STRING_MULTIBYTE (obj));
else if (FUNVECP (obj) || VECTORP (obj))
else if (COMPILEDP (obj) || VECTORP (obj))
{
register struct Lisp_Vector *vec;
register EMACS_INT i;
@ -4829,10 +4773,10 @@ Does not copy symbols. Copies strings without text properties. */)
vec = XVECTOR (make_pure_vector (size));
for (i = 0; i < size; i++)
vec->contents[i] = Fpurecopy (XVECTOR (obj)->contents[i]);
if (FUNVECP (obj))
if (COMPILEDP (obj))
{
XSETPVECTYPE (vec, PVEC_FUNVEC);
XSETFUNVEC (obj, vec);
XSETPVECTYPE (vec, PVEC_COMPILED);
XSETCOMPILED (obj, vec);
}
else
XSETVECTOR (obj, vec);
@ -5418,7 +5362,7 @@ mark_object (Lisp_Object arg)
}
else if (SUBRP (obj))
break;
else if (FUNVECP (obj) && FUNVEC_COMPILED_P (obj))
else if (COMPILEDP (obj))
/* We could treat this just like a vector, but it is better to
save the COMPILED_CONSTANTS element for last and avoid
recursion there. */
@ -6320,7 +6264,6 @@ The time is in seconds as a floating point value. */);
defsubr (&Scons);
defsubr (&Slist);
defsubr (&Svector);
defsubr (&Sfunvec);
defsubr (&Smake_byte_code);
defsubr (&Smake_list);
defsubr (&Smake_vector);

View file

@ -51,7 +51,7 @@ by Hallvard:
*
* define BYTE_CODE_METER to enable generation of a byte-op usage histogram.
*/
/* #define BYTE_CODE_SAFE 1 */
/* #define BYTE_CODE_SAFE */
/* #define BYTE_CODE_METER */
@ -1720,8 +1720,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
break;
#endif
case 0:
/* Actually this is Bstack_ref with offset 0, but we use Bdup
for that instead. */
/* case Bstack_ref: */
abort ();
/* Handy byte-codes for lexical binding. */
/* case Bstack_ref: */ /* Use `dup' instead. */
case Bstack_ref+1:
case Bstack_ref+2:
case Bstack_ref+3:

View file

@ -84,7 +84,7 @@ static Lisp_Object Qsymbol, Qstring, Qcons, Qmarker, Qoverlay;
Lisp_Object Qwindow;
static Lisp_Object Qfloat, Qwindow_configuration;
Lisp_Object Qprocess;
static Lisp_Object Qcompiled_function, Qfunction_vector, Qbuffer, Qframe, Qvector;
static Lisp_Object Qcompiled_function, Qbuffer, Qframe, Qvector;
static Lisp_Object Qchar_table, Qbool_vector, Qhash_table;
static Lisp_Object Qsubrp, Qmany, Qunevalled;
Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
@ -194,11 +194,8 @@ for example, (type-of 1) returns `integer'. */)
return Qwindow;
if (SUBRP (object))
return Qsubr;
if (FUNVECP (object))
if (FUNVEC_COMPILED_P (object))
return Qcompiled_function;
else
return Qfunction_vector;
if (COMPILEDP (object))
return Qcompiled_function;
if (BUFFERP (object))
return Qbuffer;
if (CHAR_TABLE_P (object))
@ -397,13 +394,6 @@ DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p,
return Qnil;
}
DEFUN ("funvecp", Ffunvecp, Sfunvecp, 1, 1, 0,
doc: /* Return t if OBJECT is a `function vector' object. */)
(Lisp_Object object)
{
return FUNVECP (object) ? Qt : Qnil;
}
DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0,
doc: /* Return t if OBJECT is a character or a string. */)
(register Lisp_Object object)
@ -2113,9 +2103,9 @@ or a byte-code object. IDX starts at 0. */)
{
int size = 0;
if (VECTORP (array))
size = ASIZE (array);
else if (FUNVECP (array))
size = FUNVEC_SIZE (array);
size = XVECTOR (array)->size;
else if (COMPILEDP (array))
size = XVECTOR (array)->size & PSEUDOVECTOR_SIZE_MASK;
else
wrong_type_argument (Qarrayp, array);
@ -3180,7 +3170,6 @@ syms_of_data (void)
Qwindow = intern_c_string ("window");
/* Qsubr = intern_c_string ("subr"); */
Qcompiled_function = intern_c_string ("compiled-function");
Qfunction_vector = intern_c_string ("function-vector");
Qbuffer = intern_c_string ("buffer");
Qframe = intern_c_string ("frame");
Qvector = intern_c_string ("vector");
@ -3206,7 +3195,6 @@ syms_of_data (void)
staticpro (&Qwindow);
/* staticpro (&Qsubr); */
staticpro (&Qcompiled_function);
staticpro (&Qfunction_vector);
staticpro (&Qbuffer);
staticpro (&Qframe);
staticpro (&Qvector);
@ -3243,7 +3231,6 @@ syms_of_data (void)
defsubr (&Smarkerp);
defsubr (&Ssubrp);
defsubr (&Sbyte_code_function_p);
defsubr (&Sfunvecp);
defsubr (&Schar_or_string_p);
defsubr (&Scar);
defsubr (&Scdr);

View file

@ -357,11 +357,6 @@ string is passed through `substitute-command-keys'. */)
else
return Qnil;
}
else if (FUNVECP (fun))
{
/* Unless otherwise handled, funvecs have no documentation. */
return Qnil;
}
else if (STRINGP (fun) || VECTORP (fun))
{
return build_string ("Keyboard macro.");

View file

@ -60,7 +60,6 @@ Lisp_Object Qinhibit_quit;
Lisp_Object Qand_rest, Qand_optional;
Lisp_Object Qdebug_on_error;
Lisp_Object Qdeclare;
Lisp_Object Qcurry;
Lisp_Object Qinternal_interpreter_environment, Qclosure;
Lisp_Object Qdebug;
@ -2405,7 +2404,7 @@ eval_sub (Lisp_Object form)
}
}
}
else if (FUNVECP (fun))
else if (COMPILEDP (fun))
val = apply_lambda (fun, original_args);
else
{
@ -2890,7 +2889,7 @@ DEFUN ("functionp", Ffunctionp, Sfunctionp, 1, 1, 0,
if (SUBRP (object))
return (XSUBR (object)->max_args != UNEVALLED) ? Qt : Qnil;
else if (FUNVECP (object))
else if (COMPILEDP (object))
return Qt;
else if (CONSP (object))
{
@ -3034,7 +3033,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
}
}
}
else if (FUNVECP (fun))
else if (COMPILEDP (fun))
val = funcall_lambda (fun, numargs, args + 1);
else
{
@ -3107,54 +3106,6 @@ apply_lambda (Lisp_Object fun, Lisp_Object args)
return tem;
}
/* Call a non-bytecode funvec object FUN, on the argments in ARGS (of
length NARGS). */
static Lisp_Object
funcall_funvec (Lisp_Object fun, int nargs, Lisp_Object *args)
{
int size = FUNVEC_SIZE (fun);
Lisp_Object tag = (size > 0 ? AREF (fun, 0) : Qnil);
if (EQ (tag, Qcurry))
{
/* A curried function is a way to attach arguments to a another
function. The first element of the vector is the identifier
`curry', the second is the wrapped function, and remaining
elements are the attached arguments. */
int num_curried_args = size - 2;
/* Offset of the curried and user args in the final arglist. Curried
args are first in the new arg vector, after the function. User
args follow. */
int curried_args_offs = 1;
int user_args_offs = curried_args_offs + num_curried_args;
/* The curried function and arguments. */
Lisp_Object *curry_params = XVECTOR (fun)->contents + 1;
/* The arguments in the curry vector. */
Lisp_Object *curried_args = curry_params + 1;
/* The number of arguments with which we'll call funcall, and the
arguments themselves. */
int num_funcall_args = 1 + num_curried_args + nargs;
Lisp_Object *funcall_args
= (Lisp_Object *) alloca (num_funcall_args * sizeof (Lisp_Object));
/* First comes the real function. */
funcall_args[0] = curry_params[0];
/* Then the arguments in the appropriate order. */
memcpy (funcall_args + curried_args_offs, curried_args,
num_curried_args * sizeof (Lisp_Object));
memcpy (funcall_args + user_args_offs, args,
nargs * sizeof (Lisp_Object));
return Ffuncall (num_funcall_args, funcall_args);
}
else
xsignal1 (Qinvalid_function, fun);
}
/* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR
and return the result of evaluation.
FUN must be either a lambda-expression or a compiled-code object. */
@ -3167,34 +3118,6 @@ funcall_lambda (Lisp_Object fun, int nargs,
int count = SPECPDL_INDEX ();
int i, optional, rest;
if (COMPILEDP (fun)
&& FUNVEC_SIZE (fun) > COMPILED_PUSH_ARGS
&& ! NILP (XVECTOR (fun)->contents[COMPILED_PUSH_ARGS]))
/* A byte-code object with a non-nil `push args' slot means we
shouldn't bind any arguments, instead just call the byte-code
interpreter directly; it will push arguments as necessary.
Byte-code objects with either a non-existant, or a nil value for
the `push args' slot (the default), have dynamically-bound
arguments, and use the argument-binding code below instead (as do
all interpreted functions, even lexically bound ones). */
{
/* If we have not actually read the bytecode string
and constants vector yet, fetch them from the file. */
if (CONSP (AREF (fun, COMPILED_BYTECODE)))
Ffetch_bytecode (fun);
return exec_byte_code (AREF (fun, COMPILED_BYTECODE),
AREF (fun, COMPILED_CONSTANTS),
AREF (fun, COMPILED_STACK_DEPTH),
AREF (fun, COMPILED_ARGLIST),
nargs, arg_vector);
}
if (FUNVECP (fun) && !FUNVEC_COMPILED_P (fun))
/* Byte-compiled functions are handled directly below, but we
call other funvec types via funcall_funvec. */
return funcall_funvec (fun, nargs, arg_vector);
if (CONSP (fun))
{
if (EQ (XCAR (fun), Qclosure))
@ -3213,6 +3136,27 @@ funcall_lambda (Lisp_Object fun, int nargs,
}
else if (COMPILEDP (fun))
{
if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_PUSH_ARGS
&& ! NILP (XVECTOR (fun)->contents[COMPILED_PUSH_ARGS]))
/* A byte-code object with a non-nil `push args' slot means we
shouldn't bind any arguments, instead just call the byte-code
interpreter directly; it will push arguments as necessary.
Byte-code objects with either a non-existant, or a nil value for
the `push args' slot (the default), have dynamically-bound
arguments, and use the argument-binding code below instead (as do
all interpreted functions, even lexically bound ones). */
{
/* If we have not actually read the bytecode string
and constants vector yet, fetch them from the file. */
if (CONSP (AREF (fun, COMPILED_BYTECODE)))
Ffetch_bytecode (fun);
return exec_byte_code (AREF (fun, COMPILED_BYTECODE),
AREF (fun, COMPILED_CONSTANTS),
AREF (fun, COMPILED_STACK_DEPTH),
AREF (fun, COMPILED_ARGLIST),
nargs, arg_vector);
}
syms_left = AREF (fun, COMPILED_ARGLIST);
lexenv = Qnil;
}
@ -3248,11 +3192,7 @@ funcall_lambda (Lisp_Object fun, int nargs,
val = Qnil;
/* Bind the argument. */
if (!NILP (lexenv) && SYMBOLP (next)
/* FIXME: there's no good reason to allow dynamic-scoping
on function arguments, other than consistency with let. */
&& !XSYMBOL (next)->declared_special
&& NILP (Fmemq (next, Vinternal_interpreter_environment)))
if (!NILP (lexenv) && SYMBOLP (next))
/* Lexically bind NEXT by adding it to the lexenv alist. */
lexenv = Fcons (Fcons (next, val), lexenv);
else
@ -3532,24 +3472,6 @@ context where binding is lexical by default. */)
DEFUN ("curry", Fcurry, Scurry, 1, MANY, 0,
doc: /* Return FUN curried with ARGS.
The result is a function-like object that will append any arguments it
is called with to ARGS, and call FUN with the resulting list of arguments.
For instance:
(funcall (curry '+ 3 4 5) 2) is the same as (funcall '+ 3 4 5 2)
and:
(mapcar (curry 'concat "The ") '("a" "b" "c"))
=> ("The a" "The b" "The c")
usage: (curry FUN &rest ARGS) */)
(int nargs, Lisp_Object *args)
{
return make_funvec (Qcurry, 0, nargs, args);
}
DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0,
doc: /* Set the debug-on-exit flag of eval frame LEVEL levels down to FLAG.
The debugger is entered when that frame exits, if the flag is non-nil. */)
@ -3764,9 +3686,6 @@ before making `inhibit-quit' nil. */);
Qclosure = intern_c_string ("closure");
staticpro (&Qclosure);
Qcurry = intern_c_string ("curry");
staticpro (&Qcurry);
Qdebug = intern_c_string ("debug");
staticpro (&Qdebug);
@ -3901,11 +3820,9 @@ alist of active lexical bindings. */);
defsubr (&Srun_hook_with_args_until_success);
defsubr (&Srun_hook_with_args_until_failure);
defsubr (&Sfetch_bytecode);
defsubr (&Scurry);
defsubr (&Sbacktrace_debug);
defsubr (&Sbacktrace);
defsubr (&Sbacktrace_frame);
defsubr (&Scurry);
defsubr (&Sspecial_variable_p);
defsubr (&Sfunctionp);
}

View file

@ -127,8 +127,8 @@ To get the number of bytes, use `string-bytes'. */)
XSETFASTINT (val, MAX_CHAR);
else if (BOOL_VECTOR_P (sequence))
XSETFASTINT (val, XBOOL_VECTOR (sequence)->size);
else if (FUNVECP (sequence))
XSETFASTINT (val, FUNVEC_SIZE (sequence));
else if (COMPILEDP (sequence))
XSETFASTINT (val, ASIZE (sequence) & PSEUDOVECTOR_SIZE_MASK);
else if (CONSP (sequence))
{
i = 0;
@ -488,7 +488,7 @@ concat (int nargs, Lisp_Object *args, enum Lisp_Type target_type, int last_speci
{
this = args[argnum];
if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
|| FUNVECP (this) || BOOL_VECTOR_P (this)))
|| COMPILEDP (this) || BOOL_VECTOR_P (this)))
wrong_type_argument (Qsequencep, this);
}
@ -512,7 +512,7 @@ concat (int nargs, Lisp_Object *args, enum Lisp_Type target_type, int last_speci
Lisp_Object ch;
EMACS_INT this_len_byte;
if (VECTORP (this) || FUNVECP (this))
if (VECTORP (this) || COMPILEDP (this))
for (i = 0; i < len; i++)
{
ch = AREF (this, i);
@ -1311,9 +1311,7 @@ DEFUN ("elt", Felt, Selt, 2, 2, 0,
return Fcar (Fnthcdr (n, sequence));
/* Faref signals a "not array" error, so check here. */
if (! FUNVECP (sequence))
CHECK_ARRAY (sequence, Qsequencep);
CHECK_ARRAY (sequence, Qsequencep);
return Faref (sequence, n);
}
@ -2092,14 +2090,13 @@ internal_equal (register Lisp_Object o1, register Lisp_Object o2, int depth, int
if (WINDOW_CONFIGURATIONP (o1))
return compare_window_configurations (o1, o2, 0);
/* Aside from them, only true vectors, char-tables, function vectors,
and fonts (font-spec, font-entity, font-ojbect) are sensible to
compare, so eliminate the others now. */
/* Aside from them, only true vectors, char-tables, compiled
functions, and fonts (font-spec, font-entity, font-ojbect)
are sensible to compare, so eliminate the others now. */
if (size & PSEUDOVECTOR_FLAG)
{
if (!(size & (PVEC_FUNVEC
| PVEC_CHAR_TABLE | PVEC_SUB_CHAR_TABLE
| PVEC_FONT)))
if (!(size & (PVEC_COMPILED
| PVEC_CHAR_TABLE | PVEC_SUB_CHAR_TABLE | PVEC_FONT)))
return 0;
size &= PSEUDOVECTOR_SIZE_MASK;
}
@ -2302,7 +2299,7 @@ mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
1) lists are not relocated and 2) the list is marked via `seq' so will not
be freed */
if (VECTORP (seq) || FUNVECP (seq))
if (VECTORP (seq) || COMPILEDP (seq))
{
for (i = 0; i < leni; i++)
{

View file

@ -835,8 +835,9 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
case IMAGE_FUNCTION_VALUE:
value = indirect_function (value);
/* FIXME: Shouldn't we use Ffunctionp here? */
if (SUBRP (value)
|| FUNVECP (value)
|| COMPILEDP (value)
|| (CONSP (value) && EQ (XCAR (value), Qlambda)))
break;
return 0;

View file

@ -10179,7 +10179,7 @@ a special event, so ignore the prefix argument and don't clear it. */)
return Fexecute_kbd_macro (final, prefixarg, Qnil);
}
if (CONSP (final) || SUBRP (final) || FUNVECP (final))
if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
/* Don't call Fcall_interactively directly because we want to make
sure the backtrace has an entry for `call-interactively'.
For the same reason, pass `cmd' rather than `final'. */

View file

@ -349,7 +349,7 @@ enum pvec_type
PVEC_NORMAL_VECTOR = 0,
PVEC_PROCESS = 0x200,
PVEC_FRAME = 0x400,
PVEC_FUNVEC = 0x800,
PVEC_COMPILED = 0x800,
PVEC_WINDOW = 0x1000,
PVEC_WINDOW_CONFIGURATION = 0x2000,
PVEC_SUBR = 0x4000,
@ -607,7 +607,7 @@ extern Lisp_Object make_number (EMACS_INT);
#define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
#define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL))
#define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR))
#define XSETFUNVEC(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_FUNVEC))
#define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED))
#define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
#define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
#define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
@ -623,9 +623,6 @@ extern Lisp_Object make_number (EMACS_INT);
eassert ((IDX) >= 0 && (IDX) < ASIZE (ARRAY)), \
AREF ((ARRAY), (IDX)) = (VAL))
/* Return the size of the psuedo-vector object FUNVEC. */
#define FUNVEC_SIZE(funvec) (ASIZE (funvec) & PSEUDOVECTOR_SIZE_MASK)
/* Convenience macros for dealing with Lisp strings. */
#define SDATA(string) (XSTRING (string)->data + 0)
@ -1474,7 +1471,7 @@ struct Lisp_Float
typedef unsigned char UCHAR;
#endif
/* Meanings of slots in a byte-compiled function vector: */
/* Meanings of slots in a Lisp_Compiled: */
#define COMPILED_ARGLIST 0
#define COMPILED_BYTECODE 1
@ -1484,24 +1481,6 @@ typedef unsigned char UCHAR;
#define COMPILED_INTERACTIVE 5
#define COMPILED_PUSH_ARGS 6
/* Return non-zero if TAG, the first element from a funvec object, refers
to a byte-code object. Byte-code objects are distinguished from other
`funvec' objects by having a (possibly empty) list as their first
element -- other funvec types use a non-nil symbol there. */
#define FUNVEC_COMPILED_TAG_P(tag) \
(NILP (tag) || CONSP (tag))
/* Return non-zero if FUNVEC, which should be a `funvec' object, is a
byte-compiled function. Byte-compiled function are funvecs with the
arglist as the first element (other funvec types will have a symbol
identifying the type as the first object). */
#define FUNVEC_COMPILED_P(funvec) \
(FUNVEC_SIZE (funvec) > 0 && FUNVEC_COMPILED_TAG_P (AREF (funvec, 0)))
/* Return non-zero if OBJ is byte-compile function. */
#define COMPILEDP(obj) \
(FUNVECP (obj) && FUNVEC_COMPILED_P (obj))
/* Flag bits in a character. These also get used in termhooks.h.
Richard Stallman <rms@gnu.ai.mit.edu> thinks that MULE
(MUlti-Lingual Emacs) might need 22 bits for the character value
@ -1657,7 +1636,7 @@ typedef struct {
#define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
#define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
#define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR)
#define FUNVECP(x) PSEUDOVECTORP (x, PVEC_FUNVEC)
#define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
#define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
#define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
#define SUB_CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_SUB_CHAR_TABLE)
@ -1851,7 +1830,7 @@ typedef struct {
#define FUNCTIONP(OBJ) \
((CONSP (OBJ) && EQ (XCAR (OBJ), Qlambda)) \
|| (SYMBOLP (OBJ) && !NILP (Ffboundp (OBJ))) \
|| FUNVECP (OBJ) \
|| COMPILEDP (OBJ) \
|| SUBRP (OBJ))
/* defsubr (Sname);
@ -2725,7 +2704,6 @@ EXFUN (Fmake_list, 2);
extern Lisp_Object allocate_misc (void);
EXFUN (Fmake_vector, 2);
EXFUN (Fvector, MANY);
EXFUN (Ffunvec, MANY);
EXFUN (Fmake_symbol, 1);
EXFUN (Fmake_marker, 0);
EXFUN (Fmake_string, 2);
@ -2745,7 +2723,6 @@ extern Lisp_Object make_pure_c_string (const char *data);
extern Lisp_Object pure_cons (Lisp_Object, Lisp_Object);
extern Lisp_Object make_pure_vector (EMACS_INT);
EXFUN (Fgarbage_collect, 0);
extern Lisp_Object make_funvec (Lisp_Object, int, int, Lisp_Object *);
EXFUN (Fmake_byte_code, MANY);
EXFUN (Fmake_bool_vector, 2);
extern Lisp_Object Qchar_table_extra_slots;

View file

@ -2497,8 +2497,14 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
invalid_syntax ("#&...", 5);
}
if (c == '[')
/* `function vector' objects, including byte-compiled functions. */
return read_vector (readcharfun, 1);
{
/* Accept compiled functions at read-time so that we don't have to
build them using function calls. */
Lisp_Object tmp;
tmp = read_vector (readcharfun, 1);
return Fmake_byte_code (XVECTOR (tmp)->size,
XVECTOR (tmp)->contents);
}
if (c == '(')
{
Lisp_Object tmp;
@ -3311,7 +3317,7 @@ isfloat_string (const char *cp, int ignore_trailing)
static Lisp_Object
read_vector (Lisp_Object readcharfun, int read_funvec)
read_vector (Lisp_Object readcharfun, int bytecodeflag)
{
register int i;
register int size;
@ -3319,11 +3325,6 @@ read_vector (Lisp_Object readcharfun, int read_funvec)
register Lisp_Object tem, item, vector;
register struct Lisp_Cons *otem;
Lisp_Object len;
/* If we're reading a funvec object we start out assuming it's also a
byte-code object (a subset of funvecs), so we can do any special
processing needed. If it's just an ordinary funvec object, we'll
realize that as soon as we've read the first element. */
int read_bytecode = read_funvec;
tem = read_list (1, readcharfun);
len = Flength (tem);
@ -3335,18 +3336,11 @@ read_vector (Lisp_Object readcharfun, int read_funvec)
{
item = Fcar (tem);
/* If READ_BYTECODE is set, check whether this is really a byte-code
object, or just an ordinary `funvec' object -- non-byte-code
funvec objects use the same reader syntax. We can tell from the
first element which one it is. */
if (read_bytecode && i == 0 && ! FUNVEC_COMPILED_TAG_P (item))
read_bytecode = 0; /* Nope. */
/* If `load-force-doc-strings' is t when reading a lazily-loaded
bytecode object, the docstring containing the bytecode and
constants values must be treated as unibyte and passed to
Fread, to get the actual bytecode string and constants vector. */
if (read_bytecode && load_force_doc_strings)
if (bytecodeflag && load_force_doc_strings)
{
if (i == COMPILED_BYTECODE)
{
@ -3400,13 +3394,6 @@ read_vector (Lisp_Object readcharfun, int read_funvec)
free_cons (otem);
}
if (read_bytecode && size >= 4)
/* Convert this vector to a bytecode object. */
vector = Fmake_byte_code (size, XVECTOR (vector)->contents);
else if (read_funvec && size >= 1)
/* Convert this vector to an ordinary funvec object. */
XSETFUNVEC (vector, XVECTOR (vector));
return vector;
}

View file

@ -1155,7 +1155,7 @@ print_preprocess (Lisp_Object obj)
loop:
if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
|| FUNVECP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
|| COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
|| HASH_TABLE_P (obj)
|| (! NILP (Vprint_gensym)
&& SYMBOLP (obj)
@ -1337,7 +1337,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
/* Detect circularities and truncate them. */
if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
|| FUNVECP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
|| COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
|| HASH_TABLE_P (obj)
|| (! NILP (Vprint_gensym)
&& SYMBOLP (obj)
@ -1960,7 +1960,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
else
{
EMACS_INT size = XVECTOR (obj)->size;
if (FUNVECP (obj))
if (COMPILEDP (obj))
{
PRINTCHAR ('#');
size &= PSEUDOVECTOR_SIZE_MASK;