Commit ab21f61a authored by Stefan Monnier's avatar Stefan Monnier

Make syntax.c call syntax-propertize on demand

* lisp/emacs-lisp/syntax.el (syntax--jit-propertize): New function.
(parse-sexp-propertize-function): Use it.
(syntax-propertize): Disable parse-sexp-propertize-function.

* src/syntax.c (parse_sexp_propertize, update_syntax_table_forward):
New functions.
(syms_of_syntax): New vars `parse-sexp-propertize-done' and
`parse-sexp-propertize-function'.

* src/syntax.h (struct gl_state_s): Add `e_property_truncated' field.
(UPDATE_SYNTAX_TABLE_FORWARD): Use update_syntax_table_forward.
(SETUP_BUFFER_SYNTAX_TABLE): Set e_property_truncated.

* lisp/progmodes/elisp-mode.el (elisp-byte-code-syntax-propertize):
Don't assume `point' is set.
parent 74baea08
...@@ -977,6 +977,9 @@ be updated accordingly. ...@@ -977,6 +977,9 @@ be updated accordingly.
* Lisp Changes in Emacs 25.1 * Lisp Changes in Emacs 25.1
** syntax-propertize is now automatically called on-demand during forward
parsing functions like `forward-sexp'.
** New hooks prefix-command-echo-keystrokes-functions and ** New hooks prefix-command-echo-keystrokes-functions and
prefix-command-preserve-state-hook, to allow the definition of prefix prefix-command-preserve-state-hook, to allow the definition of prefix
commands other than the predefined C-u. commands other than the predefined C-u.
......
...@@ -297,7 +297,10 @@ The return value is a function suitable for `syntax-propertize-function'." ...@@ -297,7 +297,10 @@ The return value is a function suitable for `syntax-propertize-function'."
(set (make-local-variable 'parse-sexp-lookup-properties) t) (set (make-local-variable 'parse-sexp-lookup-properties) t)
(save-excursion (save-excursion
(with-silent-modifications (with-silent-modifications
(make-local-variable 'parse-sexp-propertize-done) ;Just in case!
(let* ((start (max syntax-propertize--done (point-min))) (let* ((start (max syntax-propertize--done (point-min)))
;; Avoid recursion!
(parse-sexp-propertize-done most-positive-fixnum)
(end (max pos (end (max pos
(min (point-max) (min (point-max)
(+ start syntax-propertize-chunk-size)))) (+ start syntax-propertize-chunk-size))))
...@@ -324,6 +327,18 @@ The return value is a function suitable for `syntax-propertize-function'." ...@@ -324,6 +327,18 @@ The return value is a function suitable for `syntax-propertize-function'."
'(syntax-table nil syntax-multiline nil)) '(syntax-table nil syntax-multiline nil))
(funcall syntax-propertize-function start end)))))) (funcall syntax-propertize-function start end))))))
;;; Link syntax-propertize with the new parse-sexp-propertize.
(setq-default parse-sexp-propertize-function #'syntax--jit-propertize)
(defun syntax--jit-propertize (charpos)
(if (not syntax-propertize-function)
(setq parse-sexp-propertize-done (1+ (point-max)))
(syntax-propertize charpos)
(setq parse-sexp-propertize-done
(if (= (point-max) syntax-propertize--done)
(1+ (point-max))
syntax-propertize--done))))
;;; Incrementally compute and memoize parser state. ;;; Incrementally compute and memoize parser state.
(defsubst syntax-ppss-depth (ppss) (defsubst syntax-ppss-depth (ppss)
......
...@@ -641,7 +641,7 @@ non-nil result supercedes the xrefs produced by ...@@ -641,7 +641,7 @@ non-nil result supercedes the xrefs produced by
;; FIXME: name should be singular; match xref-find-definition ;; FIXME: name should be singular; match xref-find-definition
(defun elisp--xref-find-definitions (symbol) (defun elisp--xref-find-definitions (symbol)
;; The file name is not known when `symbol' is defined via interactive eval. ;; The file name is not known when `symbol' is defined via interactive eval.
(let (xrefs temp) (let (xrefs)
(let ((temp elisp-xref-find-def-functions)) (let ((temp elisp-xref-find-def-functions))
(while (and (null xrefs) (while (and (null xrefs)
...@@ -928,6 +928,7 @@ Semicolons start comments. ...@@ -928,6 +928,7 @@ Semicolons start comments.
(goto-char end))))))) (goto-char end)))))))
(defun elisp-byte-code-syntax-propertize (start end) (defun elisp-byte-code-syntax-propertize (start end)
(goto-char start)
(elisp--byte-code-comment end (point)) (elisp--byte-code-comment end (point))
(funcall (funcall
(syntax-propertize-rules (syntax-propertize-rules
......
...@@ -247,7 +247,7 @@ SETUP_SYNTAX_TABLE (ptrdiff_t from, ptrdiff_t count) ...@@ -247,7 +247,7 @@ SETUP_SYNTAX_TABLE (ptrdiff_t from, ptrdiff_t count)
gl_state.offset = 0; gl_state.offset = 0;
if (parse_sexp_lookup_properties) if (parse_sexp_lookup_properties)
if (count > 0 || from > BEGV) if (count > 0 || from > BEGV)
update_syntax_table (count > 0 ? from : from - 1, count, 1, Qnil); update_syntax_table (count > 0 ? from : from - 1, count, true, Qnil);
} }
/* Same as above, but in OBJECT. If OBJECT is nil, use current buffer. /* Same as above, but in OBJECT. If OBJECT is nil, use current buffer.
...@@ -313,7 +313,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init, ...@@ -313,7 +313,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init,
{ {
Lisp_Object tmp_table; Lisp_Object tmp_table;
int cnt = 0; int cnt = 0;
bool invalidate = 1; bool invalidate = true;
INTERVAL i; INTERVAL i;
if (init) if (init)
...@@ -323,7 +323,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init, ...@@ -323,7 +323,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init,
gl_state.stop = gl_state.e_property; gl_state.stop = gl_state.e_property;
i = interval_of (charpos, object); i = interval_of (charpos, object);
gl_state.backward_i = gl_state.forward_i = i; gl_state.backward_i = gl_state.forward_i = i;
invalidate = 0; invalidate = false;
if (!i) if (!i)
return; return;
/* interval_of updates only ->position of the return value, so /* interval_of updates only ->position of the return value, so
...@@ -359,7 +359,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init, ...@@ -359,7 +359,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init,
i = update_interval (i, charpos); i = update_interval (i, charpos);
if (INTERVAL_LAST_POS (i) != gl_state.b_property) if (INTERVAL_LAST_POS (i) != gl_state.b_property)
{ {
invalidate = 0; invalidate = false;
gl_state.forward_i = i; gl_state.forward_i = i;
gl_state.e_property = INTERVAL_LAST_POS (i) - gl_state.offset; gl_state.e_property = INTERVAL_LAST_POS (i) - gl_state.offset;
} }
...@@ -372,7 +372,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init, ...@@ -372,7 +372,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init,
i = update_interval (i, charpos); i = update_interval (i, charpos);
if (i->position != gl_state.e_property) if (i->position != gl_state.e_property)
{ {
invalidate = 0; invalidate = false;
gl_state.backward_i = i; gl_state.backward_i = i;
gl_state.b_property = i->position - gl_state.offset; gl_state.b_property = i->position - gl_state.offset;
} }
...@@ -460,14 +460,56 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init, ...@@ -460,14 +460,56 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init,
} }
eassert (i == NULL); /* This property goes to the end. */ eassert (i == NULL); /* This property goes to the end. */
if (count > 0) if (count > 0)
gl_state.e_property = gl_state.stop; {
gl_state.e_property = gl_state.stop;
gl_state.forward_i = i;
}
else else
gl_state.b_property = gl_state.start; gl_state.b_property = gl_state.start;
} }
static void
parse_sexp_propertize (ptrdiff_t charpos)
{
EMACS_INT modiffs = CHARS_MODIFF;
safe_call1 (Vparse_sexp_propertize_function,
make_number (1 + charpos));
if (modiffs != CHARS_MODIFF)
error ("parse-sexp-propertize-function modified the buffer!");
if (parse_sexp_propertize_done <= charpos)
error ("parse-sexp-propertize-function did not move"
" parse-sexp-propertize-done");
SETUP_SYNTAX_TABLE (charpos, 1);
if (gl_state.e_property > parse_sexp_propertize_done)
{
gl_state.e_property = parse_sexp_propertize_done;
gl_state.e_property_truncated = true;
}
}
void
update_syntax_table_forward (ptrdiff_t charpos, bool init,
Lisp_Object object)
{
if (!(gl_state.e_property_truncated))
update_syntax_table (charpos, 1, init, object);
if ((gl_state.e_property > parse_sexp_propertize_done
|| gl_state.e_property_truncated)
&& NILP (object))
{
if (parse_sexp_propertize_done > charpos)
{
gl_state.e_property = parse_sexp_propertize_done;
gl_state.e_property_truncated = true;
}
else
parse_sexp_propertize (charpos);
}
}
/* Returns true if char at CHARPOS is quoted. /* Returns true if char at CHARPOS is quoted.
Global syntax-table data should be set up already to be good at CHARPOS Global syntax-table data should be set up already to be good at CHARPOS
or after. On return global syntax data is good for lookup at CHARPOS. */ or after. On return global syntax data is good for lookup at CHARPOS. */
static bool static bool
char_quoted (ptrdiff_t charpos, ptrdiff_t bytepos) char_quoted (ptrdiff_t charpos, ptrdiff_t bytepos)
...@@ -628,7 +670,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, ...@@ -628,7 +670,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
OFROM[I] is position of the earliest comment-starter seen OFROM[I] is position of the earliest comment-starter seen
which is I+2X quotes from the comment-end. which is I+2X quotes from the comment-end.
PARITY is current parity of quotes from the comment end. */ PARITY is current parity of quotes from the comment end. */
int string_style = -1; /* Presumed outside of any string. */ int string_style = -1; /* Presumed outside of any string. */
bool string_lossage = 0; bool string_lossage = 0;
/* Not a real lossage: indicates that we have passed a matching comment /* Not a real lossage: indicates that we have passed a matching comment
starter plus a non-matching comment-ender, meaning that any matching starter plus a non-matching comment-ender, meaning that any matching
...@@ -645,7 +687,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, ...@@ -645,7 +687,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
ptrdiff_t defun_start = 0; ptrdiff_t defun_start = 0;
ptrdiff_t defun_start_byte = 0; ptrdiff_t defun_start_byte = 0;
enum syntaxcode code; enum syntaxcode code;
ptrdiff_t nesting = 1; /* current comment nesting */ ptrdiff_t nesting = 1; /* Current comment nesting. */
int c; int c;
int syntax = 0; int syntax = 0;
...@@ -876,7 +918,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, ...@@ -876,7 +918,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
is nested, so we need to try again from within the is nested, so we need to try again from within the
surrounding comment. Example: { a (* " *) */ surrounding comment. Example: { a (* " *) */
{ {
/* FIXME: We should advance by one or two chars. */ /* FIXME: We should advance by one or two chars. */
defun_start = state.comstr_start + 2; defun_start = state.comstr_start + 2;
defun_start_byte = CHAR_TO_BYTE (defun_start); defun_start_byte = CHAR_TO_BYTE (defun_start);
} }
...@@ -3588,7 +3630,7 @@ syms_of_syntax (void) ...@@ -3588,7 +3630,7 @@ syms_of_syntax (void)
staticpro (&gl_state.current_syntax_table); staticpro (&gl_state.current_syntax_table);
staticpro (&gl_state.old_prop); staticpro (&gl_state.old_prop);
/* Defined in regex.c */ /* Defined in regex.c. */
staticpro (&re_match_object); staticpro (&re_match_object);
DEFSYM (Qscan_error, "scan-error"); DEFSYM (Qscan_error, "scan-error");
...@@ -3606,6 +3648,20 @@ Otherwise, that text property is simply ignored. ...@@ -3606,6 +3648,20 @@ Otherwise, that text property is simply ignored.
See the info node `(elisp)Syntax Properties' for a description of the See the info node `(elisp)Syntax Properties' for a description of the
`syntax-table' property. */); `syntax-table' property. */);
DEFVAR_INT ("parse-sexp-propertize-done", parse_sexp_propertize_done,
doc: /* Position up to which syntax-table properties have been set. */);
parse_sexp_propertize_done = -1;
DEFVAR_LISP ("parse-sexp-propertize-function",
Vparse_sexp_propertize_function,
doc: /* Function to set the `syntax-table' text property.
Called with one argument, the position at which the property is needed.
After running it, `parse-sexp-propertize-done' should be strictly greater
than the argument passed. */);
/* Note: Qnil is a temporary (and invalid) value; it will be properly set in
syntax.el. */
Vparse_sexp_propertize_function = Qnil;
words_include_escapes = 0; words_include_escapes = 0;
DEFVAR_BOOL ("words-include-escapes", words_include_escapes, DEFVAR_BOOL ("words-include-escapes", words_include_escapes,
doc: /* Non-nil means `forward-word', etc., should treat escape chars part of words. */); doc: /* Non-nil means `forward-word', etc., should treat escape chars part of words. */);
......
...@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ ...@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
INLINE_HEADER_BEGIN INLINE_HEADER_BEGIN
extern void update_syntax_table (ptrdiff_t, EMACS_INT, bool, Lisp_Object); extern void update_syntax_table (ptrdiff_t, EMACS_INT, bool, Lisp_Object);
extern void update_syntax_table_forward (ptrdiff_t, bool, Lisp_Object);
/* The standard syntax table is stored where it will automatically /* The standard syntax table is stored where it will automatically
be used in all new buffers. */ be used in all new buffers. */
...@@ -52,30 +53,32 @@ enum syntaxcode ...@@ -52,30 +53,32 @@ enum syntaxcode
other side by any char with the same syntaxcode. */ other side by any char with the same syntaxcode. */
Sstring_fence, /* Starts/ends string which is delimited on the Sstring_fence, /* Starts/ends string which is delimited on the
other side by any char with the same syntaxcode. */ other side by any char with the same syntaxcode. */
Smax /* Upper bound on codes that are meaningful */ Smax /* Upper bound on codes that are meaningful. */
}; };
struct gl_state_s struct gl_state_s
{ {
Lisp_Object object; /* The object we are scanning. */ Lisp_Object object; /* The object we are scanning. */
ptrdiff_t start; /* Where to stop. */ ptrdiff_t start; /* Where to stop. */
ptrdiff_t stop; /* Where to stop. */ ptrdiff_t stop; /* Where to stop. */
bool use_global; /* Whether to use global_code bool use_global; /* Whether to use global_code
or c_s_t. */ or c_s_t. */
Lisp_Object global_code; /* Syntax code of current char. */ Lisp_Object global_code; /* Syntax code of current char. */
Lisp_Object current_syntax_table; /* Syntax table for current pos. */ Lisp_Object current_syntax_table; /* Syntax table for current pos. */
Lisp_Object old_prop; /* Syntax-table prop at prev pos. */ Lisp_Object old_prop; /* Syntax-table prop at prev pos. */
ptrdiff_t b_property; /* First index where c_s_t is valid. */ ptrdiff_t b_property; /* First index where c_s_t is valid. */
ptrdiff_t e_property; /* First index where c_s_t is ptrdiff_t e_property; /* First index where c_s_t is
not valid. */ not valid. */
INTERVAL forward_i; /* Where to start lookup on forward */ bool e_property_truncated; /* true if e_property if was truncated
by parse_sexp_propertize_done. */
INTERVAL forward_i; /* Where to start lookup on forward. */
INTERVAL backward_i; /* or backward movement. The INTERVAL backward_i; /* or backward movement. The
data in c_s_t is valid data in c_s_t is valid
between these intervals, between these intervals,
and possibly at the and possibly at the
intervals too, depending intervals too, depending
on: */ on: */
/* Offset for positions specified to UPDATE_SYNTAX_TABLE. */ /* Offset for positions specified to UPDATE_SYNTAX_TABLE. */
ptrdiff_t offset; ptrdiff_t offset;
}; };
...@@ -173,7 +176,7 @@ INLINE void ...@@ -173,7 +176,7 @@ INLINE void
UPDATE_SYNTAX_TABLE_FORWARD (ptrdiff_t charpos) UPDATE_SYNTAX_TABLE_FORWARD (ptrdiff_t charpos)
{ {
if (parse_sexp_lookup_properties && charpos >= gl_state.e_property) if (parse_sexp_lookup_properties && charpos >= gl_state.e_property)
update_syntax_table (charpos + gl_state.offset, 1, false, gl_state.object); update_syntax_table_forward (charpos + gl_state.offset, false, gl_state.object);
} }
/* Make syntax table state (gl_state) good for CHARPOS, assuming it is /* Make syntax table state (gl_state) good for CHARPOS, assuming it is
...@@ -201,6 +204,7 @@ INLINE void ...@@ -201,6 +204,7 @@ INLINE void
SETUP_BUFFER_SYNTAX_TABLE (void) SETUP_BUFFER_SYNTAX_TABLE (void)
{ {
gl_state.use_global = false; gl_state.use_global = false;
gl_state.e_property_truncated = false;
gl_state.current_syntax_table = BVAR (current_buffer, syntax_table); gl_state.current_syntax_table = BVAR (current_buffer, syntax_table);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment