From 66d7c00ba3bc215cd8fc09f21b8253a9e5dc4e3e Mon Sep 17 00:00:00 2001 From: Fabian Boehm Date: Fri, 31 Jan 2025 23:22:26 +0100 Subject: [PATCH] Let parser eval string directly This gets the reader out of asting the source and is needed for autoloader to get it to read a source string directly Also add an "eval_file_wstr" method as a convenience to run a wstr as if it is a *file*, with a block and stuff --- src/parser.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/reader.rs | 32 +++++++++----------------------- 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 981856009..86c1a2c3f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -565,6 +565,52 @@ pub fn eval_parsed_source( } } + pub fn eval_wstr( + &self, + src: WString, + io: &IoChain, + job_group: Option<&JobGroupRef>, + block_type: BlockType, + ) -> Result { + use crate::parse_tree::ParsedSource; + use crate::parse_util::parse_util_detect_errors_in_ast; + let mut errors = vec![]; + let ast = Ast::parse(&src, ParseTreeFlags::empty(), Some(&mut errors)); + let mut errored = ast.errored(); + if !errored { + errored = parse_util_detect_errors_in_ast(&ast, &src, Some(&mut errors)).is_err(); + } + if errored { + let sb = self.get_backtrace(&src, &errors); + return Err(sb); + } + + // Construct a parsed source ref. + // Be careful to transfer ownership, this could be a very large string. + let ps = Arc::new(ParsedSource::new(src, ast)); + Ok(self.eval_parsed_source(&ps, io, job_group, block_type)) + } + + pub fn eval_file_wstr( + &self, + src: WString, + filename: Arc, + io: &IoChain, + job_group: Option<&JobGroupRef>, + ) -> Result { + let _interactive_push = self.push_scope(|s| s.is_interactive = false); + let sb = self.push_block(Block::source_block(filename.clone())); + let _filename_push = self + .library_data + .scoped_set(Some(filename.clone()), |s| &mut s.current_filename); + + let ret = self.eval_wstr(src, io, job_group, BlockType::top); + + self.pop_block(sb); + self.libdata_mut().exit_current_script = false; + ret + } + /// Evaluates a node. /// The node type must be ast::Statement or ast::JobList. pub fn eval_node( diff --git a/src/reader.rs b/src/reader.rs index d8f8aeff7..e00294af6 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -101,16 +101,14 @@ use crate::panic::AT_EXIT; use crate::parse_constants::SourceRange; use crate::parse_constants::{ParseTreeFlags, ParserTestErrorBits}; -use crate::parse_tree::ParsedSource; use crate::parse_util::parse_util_process_extent; use crate::parse_util::MaybeParentheses; use crate::parse_util::SPACES_PER_INDENT; use crate::parse_util::{ parse_util_cmdsubst_extent, parse_util_compute_indents, parse_util_contains_wildcards, - parse_util_detect_errors, parse_util_detect_errors_in_ast, parse_util_escape_string_with_quote, - parse_util_escape_wildcards, parse_util_get_line_from_offset, parse_util_get_offset, - parse_util_get_offset_from_line, parse_util_lineno, parse_util_locate_cmdsubst_range, - parse_util_token_extent, + parse_util_detect_errors, parse_util_escape_string_with_quote, parse_util_escape_wildcards, + parse_util_get_line_from_offset, parse_util_get_offset, parse_util_get_offset_from_line, + parse_util_lineno, parse_util_locate_cmdsubst_range, parse_util_token_extent, }; use crate::parser::{BlockType, EvalRes, Parser}; use crate::proc::{ @@ -818,25 +816,13 @@ fn read_ni(parser: &Parser, fd: RawFd, io: &IoChain) -> Result<(), ErrorCode> { s.remove(0); } - // Parse into an ast and detect errors. - let mut errors = vec![]; - let ast = Ast::parse(&s, ParseTreeFlags::empty(), Some(&mut errors)); - let mut errored = ast.errored(); - if !errored { - errored = parse_util_detect_errors_in_ast(&ast, &s, Some(&mut errors)).is_err(); + match parser.eval_wstr(s, io, None, BlockType::top) { + Ok(_) => Ok(()), + Err(msg) => { + eprintf!("%ls", msg); + Err(STATUS_CMD_ERROR) + } } - if errored { - let sb = parser.get_backtrace(&s, &errors); - eprintf!("%ls", sb); - return Err(STATUS_CMD_ERROR); - } - - // Construct a parsed source ref. - // Be careful to transfer ownership, this could be a very large string. - let ps = Arc::new(ParsedSource::new(s, ast)); - parser.eval_parsed_source(&ps, io, None, BlockType::top); - - Ok(()) } /// Initialize the reader.