diff --git a/src/ast.rs b/src/ast.rs index b3eda699..01baba7f 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1574,14 +1574,19 @@ pub enum Expr { ), /// () Unit(Position), - /// Variable access - optional short index, (optional index, optional (hash, modules), variable name) + /// Variable access - optional short index, position, (optional index, optional (hash, modules), variable name) /// /// The short index is [`u8`] which is used when the index is <= 255, which should be the vast /// majority of cases (unless there are more than 255 variables defined!). /// This is to avoid reading a pointer redirection during each variable access. Variable( Option, - Box<(Option, Option<(u64, NamespaceRef)>, Ident)>, + Position, + Box<( + Option, + Option<(u64, NamespaceRef)>, + Identifier, + )>, ), /// Property access - ((getter, hash), (setter, hash), prop) Property(Box<((Identifier, u64), (Identifier, u64), Ident)>), @@ -1647,11 +1652,19 @@ impl Expr { _ => return None, }) } + /// Is the expression a simple variable access? + #[inline(always)] + pub(crate) fn is_variable_access(&self, non_qualified: bool) -> bool { + match self { + Self::Variable(_, _, x) => !non_qualified || x.1.is_none(), + _ => false, + } + } /// Return the variable name if the expression a simple variable access. #[inline(always)] - pub(crate) fn get_variable_access(&self, non_qualified: bool) -> Option<&str> { + pub(crate) fn get_variable_name(&self, non_qualified: bool) -> Option<&str> { match self { - Self::Variable(_, x) if !non_qualified || x.1.is_none() => Some((x.2).name.as_str()), + Self::Variable(_, _, x) if !non_qualified || x.1.is_none() => Some(x.2.as_str()), _ => None, } } @@ -1673,7 +1686,7 @@ impl Expr { Self::Map(_, pos) => *pos, Self::Property(x) => (x.2).pos, Self::Stmt(x) => x.pos, - Self::Variable(_, x) => (x.2).pos, + Self::Variable(_, pos, _) => *pos, Self::FnCall(_, pos) => *pos, Self::And(x, _) | Self::Or(x, _) => x.lhs.position(), @@ -1703,7 +1716,7 @@ impl Expr { Self::FnPointer(_, pos) => *pos = new_pos, Self::Array(_, pos) => *pos = new_pos, Self::Map(_, pos) => *pos = new_pos, - Self::Variable(_, x) => (x.2).pos = new_pos, + Self::Variable(_, pos, _) => *pos = new_pos, Self::Property(x) => (x.2).pos = new_pos, Self::Stmt(x) => x.pos = new_pos, Self::FnCall(_, pos) => *pos = new_pos, @@ -1731,7 +1744,7 @@ impl Expr { Self::Stmt(x) => x.statements.iter().all(Stmt::is_pure), - Self::Variable(_, _) => true, + Self::Variable(_, _, _) => true, _ => self.is_constant(), } @@ -1801,7 +1814,7 @@ impl Expr { _ => false, }, - Self::Variable(_, _) => match token { + Self::Variable(_, _, _) => match token { #[cfg(not(feature = "no_index"))] Token::LeftBracket => true, Token::LeftParen => true, diff --git a/src/engine.rs b/src/engine.rs index aeb0c16b..17a84051 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -959,14 +959,14 @@ impl Engine { expr: &Expr, ) -> Result<(Target<'s>, Position), Box> { match expr { - Expr::Variable(Some(_), _) => { + Expr::Variable(Some(_), _, _) => { self.search_scope_only(scope, mods, state, lib, this_ptr, expr) } - Expr::Variable(None, v) => match v.as_ref() { + Expr::Variable(None, var_pos, v) => match v.as_ref() { // Normal variable access (_, None, _) => self.search_scope_only(scope, mods, state, lib, this_ptr, expr), // Qualified variable - (_, Some((hash_var, modules)), Ident { name, pos, .. }) => { + (_, Some((hash_var, modules)), var_name) => { let module = self.search_imports(mods, state, modules).ok_or_else(|| { EvalAltResult::ErrorModuleNotFound( modules[0].name.to_string(), @@ -976,17 +976,17 @@ impl Engine { let target = module.get_qualified_var(*hash_var).map_err(|mut err| { match *err { EvalAltResult::ErrorVariableNotFound(ref mut err_name, _) => { - *err_name = format!("{}{}", modules, name); + *err_name = format!("{}{}", modules, var_name); } _ => (), } - err.fill_position(*pos) + err.fill_position(*var_pos) })?; // Module variables are constant let mut target = target.clone(); target.set_access_mode(AccessMode::ReadOnly); - Ok((target.into(), *pos)) + Ok((target.into(), *var_pos)) } }, _ => unreachable!("Expr::Variable expected, but gets {:?}", expr), @@ -1003,30 +1003,23 @@ impl Engine { this_ptr: &'s mut Option<&mut Dynamic>, expr: &Expr, ) -> Result<(Target<'s>, Position), Box> { - let (short_index, (index, _, Ident { name, pos, .. })) = match expr { - Expr::Variable(i, v) => (i, v.as_ref()), + // Make sure that the pointer indirection is taken only when absolutely necessary. + + let (index, var_pos) = match expr { + // Check if the variable is `this` + Expr::Variable(None, pos, v) if v.0.is_none() && v.2 == KEYWORD_THIS => { + return if let Some(val) = this_ptr { + Ok(((*val).into(), *pos)) + } else { + EvalAltResult::ErrorUnboundThis(*pos).into() + } + } + _ if state.always_search => (0, expr.position()), + Expr::Variable(Some(i), pos, _) => (i.get() as usize, *pos), + Expr::Variable(None, pos, v) => (v.0.map(NonZeroUsize::get).unwrap_or(0), *pos), _ => unreachable!("Expr::Variable expected, but gets {:?}", expr), }; - // Check if the variable is `this` - if *name == KEYWORD_THIS { - return if let Some(val) = this_ptr { - Ok(((*val).into(), *pos)) - } else { - EvalAltResult::ErrorUnboundThis(*pos).into() - }; - } - - // Check if it is directly indexed - let index = if state.always_search { - 0 - } else { - short_index.map_or_else( - || index.map(NonZeroUsize::get).unwrap_or(0), - |x| x.get() as usize, - ) - }; - // Check the variable resolver, if any if let Some(ref resolve_var) = self.resolve_var { let context = EvalContext { @@ -1039,10 +1032,11 @@ impl Engine { level: 0, }; if let Some(mut result) = - resolve_var(name, index, &context).map_err(|err| err.fill_position(*pos))? + resolve_var(expr.get_variable_name(true).unwrap(), index, &context) + .map_err(|err| err.fill_position(var_pos))? { result.set_access_mode(AccessMode::ReadOnly); - return Ok((result.into(), *pos)); + return Ok((result.into(), var_pos)); } } @@ -1050,15 +1044,16 @@ impl Engine { scope.len() - index } else { // Find the variable in the scope + let var_name = expr.get_variable_name(true).unwrap(); scope - .get_index(name) - .ok_or_else(|| EvalAltResult::ErrorVariableNotFound(name.to_string(), *pos))? + .get_index(var_name) + .ok_or_else(|| EvalAltResult::ErrorVariableNotFound(var_name.to_string(), var_pos))? .0 }; let val = scope.get_mut_by_index(index); - Ok((val.into(), *pos)) + Ok((val.into(), var_pos)) } /// Chain-evaluate a dot/index chain. @@ -1410,13 +1405,7 @@ impl Engine { match lhs { // id.??? or id[???] - Expr::Variable(_, x) => { - let Ident { - name: var_name, - pos: var_pos, - .. - } = &x.2; - + Expr::Variable(_, var_pos, x) => { self.inc_operations(state, *var_pos)?; let (target, pos) = @@ -1424,8 +1413,7 @@ impl Engine { // Constants cannot be modified if target.as_ref().is_read_only() && new_val.is_some() { - return EvalAltResult::ErrorAssignmentToConstant(var_name.to_string(), pos) - .into(); + return EvalAltResult::ErrorAssignmentToConstant(x.2.to_string(), pos).into(); } let obj_ptr = &mut target.into(); @@ -1688,11 +1676,11 @@ impl Engine { Expr::CharConstant(x, _) => Ok((*x).into()), Expr::FnPointer(x, _) => Ok(FnPtr::new_unchecked(x.clone(), Default::default()).into()), - Expr::Variable(None, x) if x.0.is_none() && (x.2).name == KEYWORD_THIS => this_ptr + Expr::Variable(None, var_pos, x) if x.0.is_none() && x.2 == KEYWORD_THIS => this_ptr .as_deref() .cloned() - .ok_or_else(|| EvalAltResult::ErrorUnboundThis((x.2).pos).into()), - Expr::Variable(_, _) => self + .ok_or_else(|| EvalAltResult::ErrorUnboundThis(*var_pos).into()), + Expr::Variable(_, _, _) => self .search_namespace(scope, mods, state, lib, this_ptr, expr) .map(|(val, _)| val.take_or_clone()), @@ -2019,7 +2007,7 @@ impl Engine { .flatten()), // var op= rhs - Stmt::Assignment(x, op_pos) if x.0.get_variable_access(false).is_some() => { + Stmt::Assignment(x, op_pos) if x.0.is_variable_access(false) => { let (lhs_expr, op_info, rhs_expr) = x.as_ref(); let rhs_val = self .eval_expr(scope, mods, state, lib, this_ptr, rhs_expr, level)? @@ -2029,7 +2017,7 @@ impl Engine { if !lhs_ptr.is_ref() { return EvalAltResult::ErrorAssignmentToConstant( - lhs_expr.get_variable_access(false).unwrap().to_string(), + lhs_expr.get_variable_name(false).unwrap().to_string(), pos, ) .into(); @@ -2040,7 +2028,7 @@ impl Engine { if lhs_ptr.as_ref().is_read_only() { // Assignment to constant variable EvalAltResult::ErrorAssignmentToConstant( - lhs_expr.get_variable_access(false).unwrap().to_string(), + lhs_expr.get_variable_name(false).unwrap().to_string(), pos, ) .into() @@ -2070,7 +2058,7 @@ impl Engine { // Must be either `var[index] op= val` or `var.prop op= val` match lhs_expr { // name op= rhs (handled above) - Expr::Variable(_, _) => { + Expr::Variable(_, _, _) => { unreachable!("Expr::Variable case should already been handled") } // idx_lhs[idx_expr] op= rhs diff --git a/src/fn_call.rs b/src/fn_call.rs index ccf67349..c0d2845e 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -1293,10 +1293,7 @@ impl Engine { // If the first argument is a variable, and there is no curried arguments, // convert to method-call style in order to leverage potential &mut first argument and // avoid cloning the value - if curry.is_empty() - && !args_expr.is_empty() - && args_expr[0].get_variable_access(false).is_some() - { + if curry.is_empty() && !args_expr.is_empty() && args_expr[0].is_variable_access(false) { // func(x, ...) -> x.func(...) arg_values = args_expr .iter() @@ -1378,7 +1375,7 @@ impl Engine { // See if the first argument is a variable (not namespace-qualified). // If so, convert to method-call style in order to leverage potential // &mut first argument and avoid cloning the value - if !args_expr.is_empty() && args_expr[0].get_variable_access(true).is_some() { + if !args_expr.is_empty() && args_expr[0].is_variable_access(true) { // func(x, ...) -> x.func(...) arg_values = args_expr .iter() diff --git a/src/optimize.rs b/src/optimize.rs index 796af57f..de82a8f9 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -385,7 +385,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) { match stmt { // expr op= expr Stmt::Assignment(x, _) => match x.0 { - Expr::Variable(_, _) => optimize_expr(&mut x.2, state), + Expr::Variable(_, _, _) => optimize_expr(&mut x.2, state), _ => { optimize_expr(&mut x.0, state); optimize_expr(&mut x.2, state); @@ -635,7 +635,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) { .unwrap_or_else(|| Expr::Unit(*pos)); } // var.rhs - (Expr::Variable(_, _), rhs) => optimize_expr(rhs, state), + (Expr::Variable(_, _, _), rhs) => optimize_expr(rhs, state), // lhs.rhs (lhs, rhs) => { optimize_expr(lhs, state); optimize_expr(rhs, state); } } @@ -670,7 +670,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) { *expr = Expr::CharConstant(s.chars().nth(*i as usize).unwrap(), *pos); } // var[rhs] - (Expr::Variable(_, _), rhs) => optimize_expr(rhs, state), + (Expr::Variable(_, _, _), rhs) => optimize_expr(rhs, state), // lhs[rhs] (lhs, rhs) => { optimize_expr(lhs, state); optimize_expr(rhs, state); } }, @@ -901,12 +901,12 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) { } // constant-name - Expr::Variable(_, x) if x.1.is_none() && state.find_constant(&x.2.name).is_some() => { + Expr::Variable(_, pos, x) if x.1.is_none() && state.find_constant(&x.2).is_some() => { state.set_dirty(); // Replace constant with value - let mut result = state.find_constant(&x.2.name).unwrap().clone(); - result.set_position(x.2.pos); + let mut result = state.find_constant(&x.2).unwrap().clone(); + result.set_position(*pos); *expr = result; } diff --git a/src/parser.rs b/src/parser.rs index f1db5fd8..409b6723 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -225,17 +225,20 @@ impl Expr { #[inline(always)] fn into_property(self, state: &mut ParseState) -> Self { match self { - Self::Variable(_, x) if x.1.is_none() => { + Self::Variable(_, pos, x) if x.1.is_none() => { let ident = x.2; - let getter = state.get_identifier(crate::engine::make_getter(&ident.name)); + let getter = state.get_identifier(crate::engine::make_getter(&ident)); let hash_get = calc_fn_hash(empty(), &getter, 1); - let setter = state.get_identifier(crate::engine::make_setter(&ident.name)); + let setter = state.get_identifier(crate::engine::make_setter(&ident)); let hash_set = calc_fn_hash(empty(), &setter, 2); Self::Property(Box::new(( (getter, hash_get), (setter, hash_set), - ident.into(), + Ident { + name: state.get_identifier(ident), + pos, + }, ))) } _ => self, @@ -1077,11 +1080,11 @@ fn parse_primary( // Once the identifier consumed we must enable next variables capturing state.allow_capture = true; } - let var_name_def = Ident { - name: state.get_identifier(s), - pos: settings.pos, - }; - Expr::Variable(None, Box::new((None, None, var_name_def))) + Expr::Variable( + None, + settings.pos, + Box::new((None, None, state.get_identifier(s))), + ) } // Namespace qualification #[cfg(not(feature = "no_module"))] @@ -1091,19 +1094,15 @@ fn parse_primary( // Once the identifier consumed we must enable next variables capturing state.allow_capture = true; } - let var_name_def = Ident { - name: state.get_identifier(s), - pos: settings.pos, - }; - Expr::Variable(None, Box::new((None, None, var_name_def))) + Expr::Variable( + None, + settings.pos, + Box::new((None, None, state.get_identifier(s))), + ) } // Normal variable access _ => { let index = state.access_var(&s, settings.pos); - let var_name_def = Ident { - name: state.get_identifier(s), - pos: settings.pos, - }; let short_index = index.and_then(|x| { if x.get() <= u8::MAX as usize { NonZeroU8::new(x.get() as u8) @@ -1111,7 +1110,11 @@ fn parse_primary( None } }); - Expr::Variable(short_index, Box::new((index, None, var_name_def))) + Expr::Variable( + short_index, + settings.pos, + Box::new((index, None, state.get_identifier(s))), + ) } } } @@ -1125,21 +1128,17 @@ fn parse_primary( match input.peek().unwrap().0 { // Function call is allowed to have reserved keyword - Token::LeftParen | Token::Bang if is_keyword_function(&s) => { - let var_name_def = Ident { - name: state.get_identifier(s), - pos: settings.pos, - }; - Expr::Variable(None, Box::new((None, None, var_name_def))) - } + Token::LeftParen | Token::Bang if is_keyword_function(&s) => Expr::Variable( + None, + settings.pos, + Box::new((None, None, state.get_identifier(s))), + ), // Access to `this` as a variable is OK within a function scope - _ if s == KEYWORD_THIS && settings.is_function_scope => { - let var_name_def = Ident { - name: state.get_identifier(s), - pos: settings.pos, - }; - Expr::Variable(None, Box::new((None, None, var_name_def))) - } + _ if s == KEYWORD_THIS && settings.is_function_scope => Expr::Variable( + None, + settings.pos, + Box::new((None, None, state.get_identifier(s))), + ), // Cannot access to `this` as a variable not in a function scope _ if s == KEYWORD_THIS => { let msg = format!("'{}' can only be used in functions", s); @@ -1175,7 +1174,7 @@ fn parse_primary( root_expr = match (root_expr, tail_token) { // Qualified function call with ! - (Expr::Variable(_, x), Token::Bang) if x.1.is_some() => { + (Expr::Variable(_, _, x), Token::Bang) if x.1.is_some() => { return Err(if !match_token(input, Token::LeftParen).0 { LexError::UnexpectedInput(Token::Bang.syntax().to_string()).into_err(tail_pos) } else { @@ -1187,7 +1186,7 @@ fn parse_primary( }); } // Function call with ! - (Expr::Variable(_, x), Token::Bang) => { + (Expr::Variable(_, var_pos, x), Token::Bang) => { let (matched, pos) = match_token(input, Token::LeftParen); if !matched { return Err(PERR::MissingToken( @@ -1197,22 +1196,26 @@ fn parse_primary( .into_err(pos)); } - let (_, namespace, Ident { name, pos, .. }) = *x; - settings.pos = pos; + let (_, namespace, name) = *x; + settings.pos = var_pos; let ns = namespace.map(|(_, ns)| ns); parse_fn_call(input, state, lib, name, true, ns, settings.level_up())? } // Function call - (Expr::Variable(_, x), Token::LeftParen) => { - let (_, namespace, Ident { name, pos, .. }) = *x; - settings.pos = pos; + (Expr::Variable(_, var_pos, x), Token::LeftParen) => { + let (_, namespace, name) = *x; + settings.pos = var_pos; let ns = namespace.map(|(_, ns)| ns); parse_fn_call(input, state, lib, name, false, ns, settings.level_up())? } // module access - (Expr::Variable(_, x), Token::DoubleColon) => match input.next().unwrap() { + (Expr::Variable(_, var_pos, x), Token::DoubleColon) => match input.next().unwrap() { (Token::Identifier(id2), pos2) => { - let (_, mut namespace, var_name_def) = *x; + let (_, mut namespace, var_name) = *x; + let var_name_def = Ident { + name: var_name, + pos: var_pos, + }; if let Some((_, ref mut namespace)) = namespace { namespace.push(var_name_def); @@ -1222,11 +1225,11 @@ fn parse_primary( namespace = Some((42, ns)); } - let var_name_def = Ident { - name: state.get_identifier(id2), - pos: pos2, - }; - Expr::Variable(None, Box::new((None, namespace, var_name_def))) + Expr::Variable( + None, + pos2, + Box::new((None, namespace, state.get_identifier(id2))), + ) } (Token::Reserved(id2), pos2) if is_valid_identifier(id2.chars()) => { return Err(PERR::Reserved(id2).into_err(pos2)); @@ -1269,15 +1272,15 @@ fn parse_primary( // Cache the hash key for namespace-qualified variables match &mut root_expr { - Expr::Variable(_, x) if x.1.is_some() => Some(x), + Expr::Variable(_, _, x) if x.1.is_some() => Some(x), Expr::Index(x, _) | Expr::Dot(x, _) => match &mut x.lhs { - Expr::Variable(_, x) if x.1.is_some() => Some(x), + Expr::Variable(_, _, x) if x.1.is_some() => Some(x), _ => None, }, _ => None, } .map(|x| match x.as_mut() { - (_, Some((ref mut hash, ref mut namespace)), Ident { name, .. }) => { + (_, Some((ref mut hash, ref mut namespace)), name) => { *hash = calc_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0); #[cfg(not(feature = "no_module"))] @@ -1429,12 +1432,12 @@ fn make_assignment_stmt<'a>( Err(PERR::AssignmentToConstant("".into()).into_err(lhs.position())) } // var (non-indexed) = rhs - Expr::Variable(None, x) if x.0.is_none() => { + Expr::Variable(None, _, x) if x.0.is_none() => { Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos)) } // var (indexed) = rhs - Expr::Variable(i, x) => { - let (index, _, Ident { name, pos, .. }) = x.as_ref(); + Expr::Variable(i, var_pos, x) => { + let (index, _, name) = x.as_ref(); let index = i.map_or_else(|| index.unwrap().get(), |n| n.get() as usize); match state.stack[state.stack.len() - index].1 { AccessMode::ReadWrite => { @@ -1442,7 +1445,7 @@ fn make_assignment_stmt<'a>( } // Constant values cannot be assigned to AccessMode::ReadOnly => { - Err(PERR::AssignmentToConstant(name.to_string()).into_err(*pos)) + Err(PERR::AssignmentToConstant(name.to_string()).into_err(*var_pos)) } } } @@ -1451,12 +1454,12 @@ fn make_assignment_stmt<'a>( match check_lvalue(&x.rhs, matches!(lhs, Expr::Dot(_, _))) { Position::NONE => match &x.lhs { // var[???] (non-indexed) = rhs, var.??? (non-indexed) = rhs - Expr::Variable(None, x) if x.0.is_none() => { + Expr::Variable(None, _, x) if x.0.is_none() => { Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos)) } // var[???] (indexed) = rhs, var.??? (indexed) = rhs - Expr::Variable(i, x) => { - let (index, _, Ident { name, pos, .. }) = x.as_ref(); + Expr::Variable(i, var_pos, x) => { + let (index, _, name) = x.as_ref(); let index = i.map_or_else(|| index.unwrap().get(), |n| n.get() as usize); match state.stack[state.stack.len() - index].1 { AccessMode::ReadWrite => { @@ -1464,7 +1467,7 @@ fn make_assignment_stmt<'a>( } // Constant values cannot be assigned to AccessMode::ReadOnly => { - Err(PERR::AssignmentToConstant(name.to_string()).into_err(*pos)) + Err(PERR::AssignmentToConstant(name.to_string()).into_err(*var_pos)) } } } @@ -1540,19 +1543,26 @@ fn make_dot_expr( Expr::Index(x, pos) } // lhs.id - (lhs, Expr::Variable(_, x)) if x.1.is_none() => { + (lhs, Expr::Variable(_, var_pos, x)) if x.1.is_none() => { let ident = x.2; - let getter = state.get_identifier(crate::engine::make_getter(&ident.name)); + let getter = state.get_identifier(crate::engine::make_getter(&ident)); let hash_get = calc_fn_hash(empty(), &getter, 1); - let setter = state.get_identifier(crate::engine::make_setter(&ident.name)); + let setter = state.get_identifier(crate::engine::make_setter(&ident)); let hash_set = calc_fn_hash(empty(), &setter, 2); - let rhs = Expr::Property(Box::new(((getter, hash_get), (setter, hash_set), ident))); + let rhs = Expr::Property(Box::new(( + (getter, hash_get), + (setter, hash_set), + Ident { + name: state.get_identifier(ident), + pos: var_pos, + }, + ))); Expr::Dot(Box::new(BinaryExpr { lhs, rhs }), op_pos) } // lhs.module::id - syntax error - (_, Expr::Variable(_, x)) if x.1.is_some() => { + (_, Expr::Variable(_, _, x)) if x.1.is_some() => { return Err(PERR::PropertyExpected.into_err(x.1.unwrap().1[0].pos)) } // lhs.prop @@ -1561,7 +1571,7 @@ fn make_dot_expr( } // lhs.dot_lhs.dot_rhs (lhs, Expr::Dot(x, pos)) => match x.lhs { - Expr::Variable(_, _) | Expr::Property(_) => { + Expr::Variable(_, _, _) | Expr::Property(_) => { let rhs = Expr::Dot( Box::new(BinaryExpr { lhs: x.lhs.into_property(state), @@ -1876,8 +1886,7 @@ fn parse_custom_syntax( let name = state.get_identifier(s); segments.push(name.clone().into()); tokens.push(state.get_identifier(MARKER_IDENT)); - let var_name_def = Ident { name, pos }; - keywords.push(Expr::Variable(None, Box::new((None, None, var_name_def)))); + keywords.push(Expr::Variable(None, pos, Box::new((None, None, name)))); } (Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => { return Err(PERR::Reserved(s).into_err(pos)); @@ -2829,11 +2838,11 @@ fn make_curry_from_externals( args.push(fn_expr); externals.iter().for_each(|x| { - let var_def = Ident { - name: x.clone(), - pos: Position::NONE, - }; - args.push(Expr::Variable(None, Box::new((None, None, var_def)))); + args.push(Expr::Variable( + None, + Position::NONE, + Box::new((None, None, x.clone())), + )); }); let expr = Expr::FnCall( diff --git a/src/syntax.rs b/src/syntax.rs index 3eea6244..dc661ea8 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -45,7 +45,7 @@ impl Expression<'_> { /// If this expression is a variable name, return it. Otherwise [`None`]. #[inline(always)] pub fn get_variable_name(&self) -> Option<&str> { - self.0.get_variable_access(true) + self.0.get_variable_name(true) } /// Get the expression. #[inline(always)]