From 3633c51ad8aee79add7727457c998c42a1638f72 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 28 Feb 2016 00:44:20 -0800 Subject: [PATCH] Re-use the parse tree generated during error detection for execution Prior to this fix, read_ni would use parse_util_detect_errors to lint the script to run, and then parser_t::eval() to execute it. Both functions would parse the script into a parse tree. This allows us to re-use the parse tree, improving perfomance. --- src/parse_util.cpp | 9 +++++++-- src/parse_util.h | 5 +++-- src/reader.cpp | 5 +++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/parse_util.cpp b/src/parse_util.cpp index a528c8986..628e86c59 100644 --- a/src/parse_util.cpp +++ b/src/parse_util.cpp @@ -1287,7 +1287,7 @@ parser_test_error_bits_t parse_util_detect_errors_in_argument(const parse_node_t return err; } -parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, parse_error_list_t *out_errors, bool allow_incomplete) +parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, parse_error_list_t *out_errors, bool allow_incomplete, parse_node_tree_t *out_tree) { parse_node_tree_t node_tree; parse_error_list_t parse_errors; @@ -1546,10 +1546,15 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, pars if (has_unclosed_block || has_unclosed_quote) res |= PARSER_TEST_INCOMPLETE; - if (out_errors) + if (out_errors != NULL) { out_errors->swap(parse_errors); } + + if (out_tree != NULL) + { + out_tree->swap(node_tree); + } return res; diff --git a/src/parse_util.h b/src/parse_util.h index 9bafd8e00..26f472689 100644 --- a/src/parse_util.h +++ b/src/parse_util.h @@ -171,8 +171,9 @@ wcstring parse_util_escape_string_with_quote(const wcstring &cmd, wchar_t quote) /** Given a string, parse it as fish code and then return the indents. The return value has the same size as the string */ std::vector parse_util_compute_indents(const wcstring &src); -/** Given a string, detect parse errors in it. If allow_incomplete is set, then if the string is incomplete (e.g. an unclosed quote), an error is not returned and the PARSER_TEST_INCOMPLETE bit is set in the return value. If allow_incomplete is not set, then incomplete strings result in an error. */ -parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, parse_error_list_t *out_errors = NULL, bool allow_incomplete = true); +/** Given a string, detect parse errors in it. If allow_incomplete is set, then if the string is incomplete (e.g. an unclosed quote), an error is not returned and the PARSER_TEST_INCOMPLETE bit is set in the return value. If allow_incomplete is not set, then incomplete strings result in an error. If out_tree is not NULL, the resulting tree is returned by reference. */ +class parse_node_tree_t; +parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, parse_error_list_t *out_errors = NULL, bool allow_incomplete = true, parse_node_tree_t *out_tree = NULL); /** Test if this argument contains any errors. Detected errors include syntax errors in command substitutions, improperly escaped characters and improper use of the variable expansion operator. diff --git a/src/reader.cpp b/src/reader.cpp index 1b4f8d2d9..3998e5a01 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -4258,9 +4258,10 @@ static int read_ni(int fd, const io_chain_t &io) } parse_error_list_t errors; - if (! parse_util_detect_errors(str, &errors, false /* do not accept incomplete */)) + parse_node_tree_t tree; + if (! parse_util_detect_errors(str, &errors, false /* do not accept incomplete */, &tree)) { - parser.eval(str, io, TOP); + parser.eval_acquiring_tree(str, io, TOP, moved_ref(tree)); } else {