diff --git a/src/engine.rs b/src/engine.rs index 0408d50f..8c860b7f 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -200,8 +200,8 @@ pub fn get_script_function_by_signature<'a>( public_only: bool, ) -> Option<&'a ScriptFnDef> { // Qualifiers (none) + function name + number of arguments. - let hash_fn_def = calc_fn_hash(empty(), name, params, empty()); - let func = module.get_fn(hash_fn_def)?; + let hash_script = calc_fn_hash(empty(), name, params, empty()); + let func = module.get_fn(hash_script)?; if !func.is_script() { return None; } @@ -524,7 +524,7 @@ impl Engine { state: &mut State, lib: &Module, fn_name: &str, - hashes: (u64, u64), + (hash_fn, hash_script): (u64, u64), args: &mut FnCallArgs, is_ref: bool, def_val: Option<&Dynamic>, @@ -532,7 +532,7 @@ impl Engine { ) -> Result<(Dynamic, bool), Box> { self.inc_operations(state)?; - let native_only = hashes.1 == 0; + let native_only = hash_script == 0; // Check for stack overflow #[cfg(not(feature = "no_function"))] @@ -587,14 +587,14 @@ impl Engine { // Then search packages // NOTE: We skip script functions for global_module and packages, and native functions for lib let func = if !native_only { - lib.get_fn(hashes.1) //.or_else(|| lib.get_fn(hashes.0)) + lib.get_fn(hash_script) //.or_else(|| lib.get_fn(hash_fn)) } else { None } - //.or_else(|| self.global_module.get_fn(hashes.1)) - .or_else(|| self.global_module.get_fn(hashes.0)) - //.or_else(|| self.packages.get_fn(hashes.1)) - .or_else(|| self.packages.get_fn(hashes.0)); + //.or_else(|| self.global_module.get_fn(hash_script)) + .or_else(|| self.global_module.get_fn(hash_fn)) + //.or_else(|| self.packages.get_fn(hash_script)) + .or_else(|| self.packages.get_fn(hash_fn)); if let Some(func) = func { // Calling pure function in method-call? @@ -784,18 +784,18 @@ impl Engine { } // Has a system function an override? - fn has_override(&self, lib: &Module, hashes: (u64, u64)) -> bool { + fn has_override(&self, lib: &Module, (hash_fn, hash_script): (u64, u64)) -> bool { // NOTE: We skip script functions for global_module and packages, and native functions for lib // First check script-defined functions - lib.contains_fn(hashes.1) - //|| lib.contains_fn(hashes.0) + lib.contains_fn(hash_script) + //|| lib.contains_fn(hash_fn) // Then check registered functions - //|| self.global_module.contains_fn(hashes.1) - || self.global_module.contains_fn(hashes.0) + //|| self.global_module.contains_fn(hash_script) + || self.global_module.contains_fn(hash_fn) // Then check packages - //|| self.packages.contains_fn(hashes.1) - || self.packages.contains_fn(hashes.0) + //|| self.packages.contains_fn(hash_script) + || self.packages.contains_fn(hash_fn) } /// Perform an actual function call, taking care of special functions @@ -812,7 +812,7 @@ impl Engine { lib: &Module, fn_name: &str, native_only: bool, - hash_fn_def: u64, + hash_script: u64, args: &mut FnCallArgs, is_ref: bool, def_val: Option<&Dynamic>, @@ -821,7 +821,7 @@ impl Engine { // Qualifiers (none) + function name + number of arguments + argument `TypeId`'s. let arg_types = args.iter().map(|a| a.type_id()); let hash_fn = calc_fn_hash(empty(), fn_name, args.len(), arg_types); - let hashes = (hash_fn, if native_only { 0 } else { hash_fn_def }); + let hashes = (hash_fn, if native_only { 0 } else { hash_script }); match fn_name { // type_of @@ -1412,7 +1412,7 @@ impl Engine { Expr::Property(_) => unreachable!(), // Statement block - Expr::Stmt(stmt) => self.eval_stmt(scope, state, lib, &stmt.0, level), + Expr::Stmt(x) => self.eval_stmt(scope, state, lib, &x.0, level), // var op= rhs Expr::Assignment(x) if matches!(x.0, Expr::Variable(_)) => { @@ -1625,7 +1625,7 @@ impl Engine { // Module-qualified function call Expr::FnCall(x) if x.1.is_some() => { - let ((name, _, pos), modules, hash_fn_def, args_expr, def_val) = x.as_ref(); + let ((name, _, pos), modules, hash_script, args_expr, def_val) = x.as_ref(); let modules = modules.as_ref().unwrap(); let mut arg_values = args_expr @@ -1650,13 +1650,13 @@ impl Engine { }; // First search in script-defined functions (can override built-in) - let func = match module.get_qualified_fn(name, *hash_fn_def) { + let func = match module.get_qualified_fn(name, *hash_script) { Err(err) if matches!(*err, EvalAltResult::ErrorFunctionNotFound(_, _)) => { // Then search in Rust functions self.inc_operations(state) .map_err(|err| EvalAltResult::new_position(err, *pos))?; - // Rust functions are indexed in two steps: + // Qualified Rust functions are indexed in two steps: // 1) Calculate a hash in a similar manner to script-defined functions, // i.e. qualifiers + function name + number of arguments. // 2) Calculate a second hash with no qualifiers, empty function name, @@ -1664,9 +1664,9 @@ impl Engine { let hash_fn_args = calc_fn_hash(empty(), "", 0, args.iter().map(|a| a.type_id())); // 3) The final hash is the XOR of the two hashes. - let hash_fn_native = *hash_fn_def ^ hash_fn_args; + let hash_qualified_fn = *hash_script ^ hash_fn_args; - module.get_qualified_fn(name, hash_fn_native) + module.get_qualified_fn(name, hash_qualified_fn) } r => r, }; diff --git a/src/module.rs b/src/module.rs index 1deddee4..e607a3e4 100644 --- a/src/module.rs +++ b/src/module.rs @@ -187,9 +187,9 @@ impl Module { /// If there is an existing function of the same name and number of arguments, it is replaced. pub(crate) fn set_script_fn(&mut self, fn_def: ScriptFnDef) { // None + function name + number of arguments. - let hash_fn_def = calc_fn_hash(empty(), &fn_def.name, fn_def.params.len(), empty()); + let hash_script = calc_fn_hash(empty(), &fn_def.name, fn_def.params.len(), empty()); self.functions.insert( - hash_fn_def, + hash_script, ( fn_def.name.to_string(), fn_def.access, @@ -778,9 +778,9 @@ impl Module { pub(crate) fn get_qualified_fn( &mut self, name: &str, - hash_fn_native: u64, + hash_qualified_fn: u64, ) -> Result<&CallableFunction, Box> { - self.all_functions.get(&hash_fn_native).ok_or_else(|| { + self.all_functions.get(&hash_qualified_fn).ok_or_else(|| { Box::new(EvalAltResult::ErrorFunctionNotFound( name.to_string(), Position::none(), @@ -907,26 +907,26 @@ impl Module { if func.is_script() { let fn_def = func.get_shared_fn_def(); // Qualifiers + function name + number of arguments. - let hash_fn_def = calc_fn_hash( + let hash_qualified_script = calc_fn_hash( qualifiers.iter().map(|&v| v), &fn_def.name, fn_def.params.len(), empty(), ); - functions.push((hash_fn_def, fn_def.into())); + functions.push((hash_qualified_script, fn_def.into())); } else { - // Rust functions are indexed in two steps: + // Qualified Rust functions are indexed in two steps: // 1) Calculate a hash in a similar manner to script-defined functions, // i.e. qualifiers + function name + number of arguments. - let hash_fn_def = + let hash_qualified_script = calc_fn_hash(qualifiers.iter().map(|&v| v), name, params.len(), empty()); // 2) Calculate a second hash with no qualifiers, empty function name, // zero number of arguments, and the actual list of argument `TypeId`'.s let hash_fn_args = calc_fn_hash(empty(), "", 0, params.iter().cloned()); // 3) The final hash is the XOR of the two hashes. - let hash_fn_native = hash_fn_def ^ hash_fn_args; + let hash_qualified_fn = hash_qualified_script ^ hash_fn_args; - functions.push((hash_fn_native, func.clone())); + functions.push((hash_qualified_fn, func.clone())); } } } diff --git a/src/parser.rs b/src/parser.rs index ab8de95c..efdae44d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -7,7 +7,7 @@ use crate::error::{LexError, ParseError, ParseErrorType}; use crate::module::{Module, ModuleRef}; use crate::optimize::{optimize_into_ast, OptimizationLevel}; use crate::scope::{EntryType as ScopeEntryType, Scope}; -use crate::token::{Position, Token, TokenIterator}; +use crate::token::{Position, Token, TokenStream}; use crate::utils::{StaticVec, StraightHasherBuilder}; use crate::stdlib::{ @@ -672,7 +672,7 @@ impl Expr { } /// Consume a particular token, checking that it is the expected one. -fn eat_token(input: &mut Peekable, token: Token) -> Position { +fn eat_token(input: &mut TokenStream, token: Token) -> Position { let (t, pos) = input.next().unwrap(); if t != token { @@ -687,7 +687,7 @@ fn eat_token(input: &mut Peekable, token: Token) -> Position { } /// Match a particular token, consuming it if matched. -fn match_token(input: &mut Peekable, token: Token) -> Result { +fn match_token(input: &mut TokenStream, token: Token) -> Result { let (t, _) = input.peek().unwrap(); if *t == token { eat_token(input, token); @@ -698,8 +698,8 @@ fn match_token(input: &mut Peekable, token: Token) -> Result( - input: &mut Peekable>, +fn parse_paren_expr( + input: &mut TokenStream, state: &mut ParseState, pos: Position, level: usize, @@ -731,8 +731,8 @@ fn parse_paren_expr<'a>( } /// Parse a function call. -fn parse_call_expr<'a>( - input: &mut Peekable>, +fn parse_call_expr( + input: &mut TokenStream, state: &mut ParseState, id: String, mut modules: Option>, @@ -764,7 +764,7 @@ fn parse_call_expr<'a>( Token::RightParen => { eat_token(input, Token::RightParen); - let hash_fn_def = if let Some(modules) = modules.as_mut() { + let hash_script = if let Some(modules) = modules.as_mut() { modules.set_index(state.find_module(&modules.get(0).0)); // Rust functions are indexed in two steps: @@ -783,7 +783,7 @@ fn parse_call_expr<'a>( return Ok(Expr::FnCall(Box::new(( (id.into(), false, begin), modules, - hash_fn_def, + hash_script, args, None, )))); @@ -800,7 +800,7 @@ fn parse_call_expr<'a>( (Token::RightParen, _) => { eat_token(input, Token::RightParen); - let hash_fn_def = if let Some(modules) = modules.as_mut() { + let hash_script = if let Some(modules) = modules.as_mut() { modules.set_index(state.find_module(&modules.get(0).0)); // Rust functions are indexed in two steps: @@ -819,7 +819,7 @@ fn parse_call_expr<'a>( return Ok(Expr::FnCall(Box::new(( (id.into(), false, begin), modules, - hash_fn_def, + hash_script, args, None, )))); @@ -854,8 +854,8 @@ fn parse_call_expr<'a>( /// Parse an indexing chain. /// Indexing binds to the right, so this call parses all possible levels of indexing following in the input. -fn parse_index_chain<'a>( - input: &mut Peekable>, +fn parse_index_chain( + input: &mut TokenStream, state: &mut ParseState, lhs: Expr, pos: Position, @@ -1044,8 +1044,8 @@ fn parse_index_chain<'a>( } /// Parse an array literal. -fn parse_array_literal<'a>( - input: &mut Peekable>, +fn parse_array_literal( + input: &mut TokenStream, state: &mut ParseState, pos: Position, level: usize, @@ -1094,8 +1094,8 @@ fn parse_array_literal<'a>( } /// Parse a map literal. -fn parse_map_literal<'a>( - input: &mut Peekable>, +fn parse_map_literal( + input: &mut TokenStream, state: &mut ParseState, pos: Position, level: usize, @@ -1197,8 +1197,8 @@ fn parse_map_literal<'a>( } /// Parse a primary expression. -fn parse_primary<'a>( - input: &mut Peekable>, +fn parse_primary( + input: &mut TokenStream, state: &mut ParseState, level: usize, if_expr: bool, @@ -1319,8 +1319,8 @@ fn parse_primary<'a>( } /// Parse a potential unary operator. -fn parse_unary<'a>( - input: &mut Peekable>, +fn parse_unary( + input: &mut TokenStream, state: &mut ParseState, level: usize, if_expr: bool, @@ -1470,8 +1470,8 @@ fn make_assignment_stmt<'a>( } /// Parse an operator-assignment expression. -fn parse_op_assignment_stmt<'a>( - input: &mut Peekable>, +fn parse_op_assignment_stmt( + input: &mut TokenStream, state: &mut ParseState, lhs: Expr, level: usize, @@ -1713,8 +1713,8 @@ fn make_in_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result( - input: &mut Peekable>, +fn parse_binary_op( + input: &mut TokenStream, state: &mut ParseState, parent_precedence: u8, lhs: Expr, @@ -1832,8 +1832,8 @@ fn parse_binary_op<'a>( } /// Parse an expression. -fn parse_expr<'a>( - input: &mut Peekable>, +fn parse_expr( + input: &mut TokenStream, state: &mut ParseState, level: usize, if_expr: bool, @@ -1850,10 +1850,7 @@ fn parse_expr<'a>( } /// Make sure that the expression is not a statement expression (i.e. wrapped in `{}`). -fn ensure_not_statement_expr<'a>( - input: &mut Peekable>, - type_name: &str, -) -> Result<(), ParseError> { +fn ensure_not_statement_expr(input: &mut TokenStream, type_name: &str) -> Result<(), ParseError> { match input.peek().unwrap() { // Disallow statement expressions (Token::LeftBrace, pos) | (Token::EOF, pos) => { @@ -1865,7 +1862,7 @@ fn ensure_not_statement_expr<'a>( } /// Make sure that the expression is not a mis-typed assignment (i.e. `a = b` instead of `a == b`). -fn ensure_not_assignment<'a>(input: &mut Peekable>) -> Result<(), ParseError> { +fn ensure_not_assignment(input: &mut TokenStream) -> Result<(), ParseError> { match input.peek().unwrap() { (Token::Equals, pos) => { return Err(PERR::BadInput("Possibly a typo of '=='?".to_string()).into_err(*pos)) @@ -1892,8 +1889,8 @@ fn ensure_not_assignment<'a>(input: &mut Peekable>) -> Result< } /// Parse an if statement. -fn parse_if<'a>( - input: &mut Peekable>, +fn parse_if( + input: &mut TokenStream, state: &mut ParseState, breakable: bool, level: usize, @@ -1930,8 +1927,8 @@ fn parse_if<'a>( } /// Parse a while loop. -fn parse_while<'a>( - input: &mut Peekable>, +fn parse_while( + input: &mut TokenStream, state: &mut ParseState, level: usize, if_expr: bool, @@ -1954,8 +1951,8 @@ fn parse_while<'a>( } /// Parse a loop statement. -fn parse_loop<'a>( - input: &mut Peekable>, +fn parse_loop( + input: &mut TokenStream, state: &mut ParseState, level: usize, if_expr: bool, @@ -1975,8 +1972,8 @@ fn parse_loop<'a>( } /// Parse a for loop. -fn parse_for<'a>( - input: &mut Peekable>, +fn parse_for( + input: &mut TokenStream, state: &mut ParseState, level: usize, if_expr: bool, @@ -2028,8 +2025,8 @@ fn parse_for<'a>( } /// Parse a variable definition statement. -fn parse_let<'a>( - input: &mut Peekable>, +fn parse_let( + input: &mut TokenStream, state: &mut ParseState, var_type: ScopeEntryType, level: usize, @@ -2091,8 +2088,8 @@ fn parse_let<'a>( } /// Parse an import statement. -fn parse_import<'a>( - input: &mut Peekable>, +fn parse_import( + input: &mut TokenStream, state: &mut ParseState, level: usize, if_expr: bool, @@ -2132,8 +2129,8 @@ fn parse_import<'a>( /// Parse an export statement. #[cfg(not(feature = "no_module"))] -fn parse_export<'a>( - input: &mut Peekable>, +fn parse_export( + input: &mut TokenStream, state: &mut ParseState, level: usize, ) -> Result { @@ -2197,8 +2194,8 @@ fn parse_export<'a>( } /// Parse a statement block. -fn parse_block<'a>( - input: &mut Peekable>, +fn parse_block( + input: &mut TokenStream, state: &mut ParseState, breakable: bool, level: usize, @@ -2278,8 +2275,8 @@ fn parse_block<'a>( } /// Parse an expression as a statement. -fn parse_expr_stmt<'a>( - input: &mut Peekable>, +fn parse_expr_stmt( + input: &mut TokenStream, state: &mut ParseState, level: usize, if_expr: bool, @@ -2297,8 +2294,8 @@ fn parse_expr_stmt<'a>( } /// Parse a single statement. -fn parse_stmt<'a>( - input: &mut Peekable>, +fn parse_stmt( + input: &mut TokenStream, state: &mut ParseState, breakable: bool, is_global: bool, @@ -2389,8 +2386,8 @@ fn parse_stmt<'a>( /// Parse a function definition. #[cfg(not(feature = "no_function"))] -fn parse_fn<'a>( - input: &mut Peekable>, +fn parse_fn( + input: &mut TokenStream, state: &mut ParseState, access: FnAccess, level: usize, @@ -2482,8 +2479,8 @@ fn parse_fn<'a>( } /// Parse the global level statements. -fn parse_global_level<'a>( - input: &mut Peekable>, +fn parse_global_level( + input: &mut TokenStream, max_expr_depth: usize, max_function_expr_depth: usize, ) -> Result<(Vec, Vec), ParseError> { @@ -2561,9 +2558,9 @@ fn parse_global_level<'a>( } impl Engine { - pub(crate) fn parse_global_expr<'a>( + pub(crate) fn parse_global_expr( &self, - input: &mut Peekable>, + input: &mut TokenStream, scope: &Scope, optimization_level: OptimizationLevel, ) -> Result { @@ -2589,9 +2586,9 @@ impl Engine { } /// Run the parser on an input stream, returning an AST. - pub(crate) fn parse<'a>( + pub(crate) fn parse( &self, - input: &mut Peekable>, + input: &mut TokenStream, scope: &Scope, optimization_level: OptimizationLevel, ) -> Result { diff --git a/src/token.rs b/src/token.rs index 2967fc02..d6799a6f 100644 --- a/src/token.rs +++ b/src/token.rs @@ -19,6 +19,8 @@ use crate::stdlib::{ type LERR = LexError; +pub type TokenStream<'a> = Peekable>; + /// A location (line number + character position) in the input script. /// /// In order to keep footprint small, both line number and character position have 16-bit unsigned resolution,