Reduce indirections.
This commit is contained in:
parent
809b813def
commit
8f969b1ab5
13
src/ast.rs
13
src/ast.rs
@ -921,7 +921,7 @@ pub struct FnCallExpr {
|
|||||||
/// Default value when the function is not found, mostly used to provide a default for comparison functions.
|
/// Default value when the function is not found, mostly used to provide a default for comparison functions.
|
||||||
pub def_value: Option<Dynamic>,
|
pub def_value: Option<Dynamic>,
|
||||||
/// Namespace of the function, if any. Boxed because it occurs rarely.
|
/// Namespace of the function, if any. Boxed because it occurs rarely.
|
||||||
pub namespace: Option<Box<NamespaceRef>>,
|
pub namespace: Option<NamespaceRef>,
|
||||||
/// Function name.
|
/// Function name.
|
||||||
/// Use [`Cow<'static, str>`][Cow] because a lot of operators (e.g. `==`, `>=`) are implemented as
|
/// Use [`Cow<'static, str>`][Cow] because a lot of operators (e.g. `==`, `>=`) are implemented as
|
||||||
/// function calls and the function names are predictable, so no need to allocate a new [`String`].
|
/// function calls and the function names are predictable, so no need to allocate a new [`String`].
|
||||||
@ -961,12 +961,11 @@ pub enum Expr {
|
|||||||
Map(Box<StaticVec<(Ident, Expr)>>, Position),
|
Map(Box<StaticVec<(Ident, Expr)>>, Position),
|
||||||
/// ()
|
/// ()
|
||||||
Unit(Position),
|
Unit(Position),
|
||||||
/// Variable access - (optional index, optional modules, hash, variable name)
|
/// Variable access - (optional index, optional (hash, modules), variable name)
|
||||||
Variable(
|
Variable(
|
||||||
Box<(
|
Box<(
|
||||||
Option<NonZeroUsize>,
|
Option<NonZeroUsize>,
|
||||||
Option<Box<NamespaceRef>>,
|
Option<(NonZeroU64, NamespaceRef)>,
|
||||||
Option<NonZeroU64>,
|
|
||||||
Ident,
|
Ident,
|
||||||
)>,
|
)>,
|
||||||
),
|
),
|
||||||
@ -1049,7 +1048,7 @@ impl Expr {
|
|||||||
/// Is the expression a simple variable access?
|
/// Is the expression a simple variable access?
|
||||||
pub(crate) fn get_variable_access(&self, non_qualified: bool) -> Option<&str> {
|
pub(crate) fn get_variable_access(&self, non_qualified: bool) -> Option<&str> {
|
||||||
match self {
|
match self {
|
||||||
Self::Variable(x) if !non_qualified || x.1.is_none() => Some((x.3).name.as_str()),
|
Self::Variable(x) if !non_qualified || x.1.is_none() => Some((x.2).name.as_str()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1071,7 +1070,7 @@ impl Expr {
|
|||||||
Self::Map(_, pos) => *pos,
|
Self::Map(_, pos) => *pos,
|
||||||
Self::Property(x) => (x.1).pos,
|
Self::Property(x) => (x.1).pos,
|
||||||
Self::Stmt(_, pos) => *pos,
|
Self::Stmt(_, pos) => *pos,
|
||||||
Self::Variable(x) => (x.3).pos,
|
Self::Variable(x) => (x.2).pos,
|
||||||
Self::FnCall(_, pos) => *pos,
|
Self::FnCall(_, pos) => *pos,
|
||||||
|
|
||||||
Self::And(x, _) | Self::Or(x, _) | Self::In(x, _) => x.lhs.position(),
|
Self::And(x, _) | Self::Or(x, _) | Self::In(x, _) => x.lhs.position(),
|
||||||
@ -1101,7 +1100,7 @@ impl Expr {
|
|||||||
Self::FnPointer(_, pos) => *pos = new_pos,
|
Self::FnPointer(_, pos) => *pos = new_pos,
|
||||||
Self::Array(_, pos) => *pos = new_pos,
|
Self::Array(_, pos) => *pos = new_pos,
|
||||||
Self::Map(_, pos) => *pos = new_pos,
|
Self::Map(_, pos) => *pos = new_pos,
|
||||||
Self::Variable(x) => (x.3).pos = new_pos,
|
Self::Variable(x) => (x.2).pos = new_pos,
|
||||||
Self::Property(x) => (x.1).pos = new_pos,
|
Self::Property(x) => (x.1).pos = new_pos,
|
||||||
Self::Stmt(_, pos) => *pos = new_pos,
|
Self::Stmt(_, pos) => *pos = new_pos,
|
||||||
Self::FnCall(_, pos) => *pos = new_pos,
|
Self::FnCall(_, pos) => *pos = new_pos,
|
||||||
|
@ -861,12 +861,9 @@ impl Engine {
|
|||||||
match expr {
|
match expr {
|
||||||
Expr::Variable(v) => match v.as_ref() {
|
Expr::Variable(v) => match v.as_ref() {
|
||||||
// Qualified variable
|
// Qualified variable
|
||||||
(_, Some(modules), hash_var, Ident { name, pos }) => {
|
(_, Some((hash_var, modules)), Ident { name, pos }) => {
|
||||||
let module = search_imports(mods, state, modules)?;
|
let module = search_imports(mods, state, modules)?;
|
||||||
let target =
|
let target = module.get_qualified_var(*hash_var).map_err(|mut err| {
|
||||||
module
|
|
||||||
.get_qualified_var(hash_var.unwrap())
|
|
||||||
.map_err(|mut err| {
|
|
||||||
match *err {
|
match *err {
|
||||||
EvalAltResult::ErrorVariableNotFound(ref mut err_name, _) => {
|
EvalAltResult::ErrorVariableNotFound(ref mut err_name, _) => {
|
||||||
*err_name = format!("{}{}", modules, name);
|
*err_name = format!("{}{}", modules, name);
|
||||||
@ -898,7 +895,7 @@ impl Engine {
|
|||||||
this_ptr: &'s mut Option<&mut Dynamic>,
|
this_ptr: &'s mut Option<&mut Dynamic>,
|
||||||
expr: &'a Expr,
|
expr: &'a Expr,
|
||||||
) -> Result<(Target<'s>, &'a str, Position), Box<EvalAltResult>> {
|
) -> Result<(Target<'s>, &'a str, Position), Box<EvalAltResult>> {
|
||||||
let (index, _, _, Ident { name, pos }) = match expr {
|
let (index, _, Ident { name, pos }) = match expr {
|
||||||
Expr::Variable(v) => v.as_ref(),
|
Expr::Variable(v) => v.as_ref(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
@ -1299,7 +1296,7 @@ impl Engine {
|
|||||||
let Ident {
|
let Ident {
|
||||||
name: var_name,
|
name: var_name,
|
||||||
pos: var_pos,
|
pos: var_pos,
|
||||||
} = &x.3;
|
} = &x.2;
|
||||||
|
|
||||||
self.inc_operations(state, *var_pos)?;
|
self.inc_operations(state, *var_pos)?;
|
||||||
|
|
||||||
@ -1715,11 +1712,11 @@ impl Engine {
|
|||||||
Expr::StringConstant(x, _) => Ok(x.clone().into()),
|
Expr::StringConstant(x, _) => Ok(x.clone().into()),
|
||||||
Expr::CharConstant(x, _) => Ok((*x).into()),
|
Expr::CharConstant(x, _) => Ok((*x).into()),
|
||||||
Expr::FnPointer(x, _) => Ok(FnPtr::new_unchecked(x.clone(), Default::default()).into()),
|
Expr::FnPointer(x, _) => Ok(FnPtr::new_unchecked(x.clone(), Default::default()).into()),
|
||||||
Expr::Variable(x) if (x.3).name == KEYWORD_THIS => {
|
Expr::Variable(x) if (x.2).name == KEYWORD_THIS => {
|
||||||
if let Some(val) = this_ptr {
|
if let Some(val) = this_ptr {
|
||||||
Ok(val.clone())
|
Ok(val.clone())
|
||||||
} else {
|
} else {
|
||||||
EvalAltResult::ErrorUnboundThis((x.3).pos).into()
|
EvalAltResult::ErrorUnboundThis((x.2).pos).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Variable(_) => {
|
Expr::Variable(_) => {
|
||||||
@ -1795,7 +1792,7 @@ impl Engine {
|
|||||||
def_value,
|
def_value,
|
||||||
..
|
..
|
||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
let namespace = namespace.as_ref().map(|v| v.as_ref());
|
let namespace = namespace.as_ref();
|
||||||
let hash = hash.unwrap();
|
let hash = hash.unwrap();
|
||||||
let def_value = def_value.as_ref();
|
let def_value = def_value.as_ref();
|
||||||
self.make_qualified_function_call(
|
self.make_qualified_function_call(
|
||||||
|
@ -1913,7 +1913,7 @@ impl Module {
|
|||||||
/// _(INTERNALS)_ A chain of [module][Module] names to namespace-qualify a variable or function call.
|
/// _(INTERNALS)_ A chain of [module][Module] names to namespace-qualify a variable or function call.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// A [`NonZeroU64`] hash key is cached for quick search purposes.
|
/// A [`NonZeroU64`] offset to the current [`Scope`][crate::Scope] is cached for quick search purposes.
|
||||||
///
|
///
|
||||||
/// A [`StaticVec`] is used because most namespace-qualified access contains only one level,
|
/// A [`StaticVec`] is used because most namespace-qualified access contains only one level,
|
||||||
/// and it is wasteful to always allocate a [`Vec`] with one element.
|
/// and it is wasteful to always allocate a [`Vec`] with one element.
|
||||||
@ -1922,13 +1922,13 @@ impl Module {
|
|||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
||||||
pub struct NamespaceRef(StaticVec<Ident>, Option<NonZeroUsize>);
|
pub struct NamespaceRef(Option<NonZeroUsize>, StaticVec<Ident>);
|
||||||
|
|
||||||
impl fmt::Debug for NamespaceRef {
|
impl fmt::Debug for NamespaceRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Debug::fmt(&self.0, f)?;
|
fmt::Debug::fmt(&self.1, f)?;
|
||||||
|
|
||||||
if let Some(index) = self.1 {
|
if let Some(index) = self.0 {
|
||||||
write!(f, " -> {}", index)
|
write!(f, " -> {}", index)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1940,19 +1940,19 @@ impl Deref for NamespaceRef {
|
|||||||
type Target = StaticVec<Ident>;
|
type Target = StaticVec<Ident>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for NamespaceRef {
|
impl DerefMut for NamespaceRef {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for NamespaceRef {
|
impl fmt::Display for NamespaceRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
for Ident { name, .. } in self.0.iter() {
|
for Ident { name, .. } in self.1.iter() {
|
||||||
write!(f, "{}{}", name, Token::DoubleColon.syntax())?;
|
write!(f, "{}{}", name, Token::DoubleColon.syntax())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1961,7 +1961,7 @@ impl fmt::Display for NamespaceRef {
|
|||||||
|
|
||||||
impl From<StaticVec<Ident>> for NamespaceRef {
|
impl From<StaticVec<Ident>> for NamespaceRef {
|
||||||
fn from(modules: StaticVec<Ident>) -> Self {
|
fn from(modules: StaticVec<Ident>) -> Self {
|
||||||
Self(modules, None)
|
Self(None, modules)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1991,12 +1991,14 @@ impl<M: Into<Module>> AddAssign<M> for Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NamespaceRef {
|
impl NamespaceRef {
|
||||||
|
/// Get the [`Scope`][crate::Scope] index offset.
|
||||||
pub(crate) fn index(&self) -> Option<NonZeroUsize> {
|
pub(crate) fn index(&self) -> Option<NonZeroUsize> {
|
||||||
self.1
|
self.0
|
||||||
}
|
}
|
||||||
|
/// Set the [`Scope`][crate::Scope] index offset.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) {
|
pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) {
|
||||||
self.1 = index
|
self.0 = index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,12 +717,12 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
|||||||
Expr::FnCall(x, _) => x.args.iter_mut().for_each(|a| optimize_expr(a, state)),
|
Expr::FnCall(x, _) => x.args.iter_mut().for_each(|a| optimize_expr(a, state)),
|
||||||
|
|
||||||
// constant-name
|
// constant-name
|
||||||
Expr::Variable(x) if x.1.is_none() && state.find_constant(&x.3.name).is_some() => {
|
Expr::Variable(x) if x.1.is_none() && state.find_constant(&x.2.name).is_some() => {
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
|
|
||||||
// Replace constant with value
|
// Replace constant with value
|
||||||
let mut result = state.find_constant(&x.3.name).unwrap().clone();
|
let mut result = state.find_constant(&x.2.name).unwrap().clone();
|
||||||
result.set_position(x.3.pos);
|
result.set_position(x.2.pos);
|
||||||
*expr = result;
|
*expr = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ impl Expr {
|
|||||||
fn into_property(self, state: &mut ParseState) -> Self {
|
fn into_property(self, state: &mut ParseState) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Variable(x) if x.1.is_none() => {
|
Self::Variable(x) if x.1.is_none() => {
|
||||||
let ident = x.3;
|
let ident = x.2;
|
||||||
let getter = state.get_interned_string(crate::engine::make_getter(&ident.name));
|
let getter = state.get_interned_string(crate::engine::make_getter(&ident.name));
|
||||||
let setter = state.get_interned_string(crate::engine::make_setter(&ident.name));
|
let setter = state.get_interned_string(crate::engine::make_setter(&ident.name));
|
||||||
Self::Property(Box::new(((getter, setter), ident.into())))
|
Self::Property(Box::new(((getter, setter), ident.into())))
|
||||||
@ -310,7 +310,7 @@ fn parse_fn_call(
|
|||||||
lib: &mut FunctionsLib,
|
lib: &mut FunctionsLib,
|
||||||
id: ImmutableString,
|
id: ImmutableString,
|
||||||
capture: bool,
|
capture: bool,
|
||||||
mut namespace: Option<Box<NamespaceRef>>,
|
mut namespace: Option<NamespaceRef>,
|
||||||
settings: ParseSettings,
|
settings: ParseSettings,
|
||||||
) -> Result<Expr, ParseError> {
|
) -> Result<Expr, ParseError> {
|
||||||
let (token, token_pos) = input.peek().unwrap();
|
let (token, token_pos) = input.peek().unwrap();
|
||||||
@ -335,7 +335,7 @@ fn parse_fn_call(
|
|||||||
Token::RightParen => {
|
Token::RightParen => {
|
||||||
eat_token(input, Token::RightParen);
|
eat_token(input, Token::RightParen);
|
||||||
|
|
||||||
let mut hash_script = if let Some(modules) = namespace.as_mut() {
|
let mut hash_script = if let Some(ref mut modules) = namespace {
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
modules.set_index(state.find_module(&modules[0].name));
|
modules.set_index(state.find_module(&modules[0].name));
|
||||||
|
|
||||||
@ -981,7 +981,7 @@ fn parse_primary(
|
|||||||
name: state.get_interned_string(s),
|
name: state.get_interned_string(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
}
|
}
|
||||||
// Namespace qualification
|
// Namespace qualification
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -995,7 +995,7 @@ fn parse_primary(
|
|||||||
name: state.get_interned_string(s),
|
name: state.get_interned_string(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
}
|
}
|
||||||
// Normal variable access
|
// Normal variable access
|
||||||
Token::Identifier(s) => {
|
Token::Identifier(s) => {
|
||||||
@ -1004,7 +1004,7 @@ fn parse_primary(
|
|||||||
name: state.get_interned_string(s),
|
name: state.get_interned_string(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((index, None, None, var_name_def)))
|
Expr::Variable(Box::new((index, None, var_name_def)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function call is allowed to have reserved keyword
|
// Function call is allowed to have reserved keyword
|
||||||
@ -1014,7 +1014,7 @@ fn parse_primary(
|
|||||||
name: state.get_interned_string(s),
|
name: state.get_interned_string(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
} else {
|
} else {
|
||||||
return Err(PERR::Reserved(s).into_err(settings.pos));
|
return Err(PERR::Reserved(s).into_err(settings.pos));
|
||||||
}
|
}
|
||||||
@ -1030,7 +1030,7 @@ fn parse_primary(
|
|||||||
name: state.get_interned_string(s),
|
name: state.get_interned_string(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1089,35 +1089,38 @@ fn parse_primary(
|
|||||||
.into_err(pos));
|
.into_err(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_, modules, _, Ident { name, pos }) = *x;
|
let (_, namespace, Ident { name, pos }) = *x;
|
||||||
settings.pos = pos;
|
settings.pos = pos;
|
||||||
parse_fn_call(input, state, lib, name, true, modules, settings.level_up())?
|
let ns = namespace.map(|(_, ns)| ns);
|
||||||
|
parse_fn_call(input, state, lib, name, true, ns, settings.level_up())?
|
||||||
}
|
}
|
||||||
// Function call
|
// Function call
|
||||||
(Expr::Variable(x), Token::LeftParen) => {
|
(Expr::Variable(x), Token::LeftParen) => {
|
||||||
let (_, modules, _, Ident { name, pos }) = *x;
|
let (_, namespace, Ident { name, pos }) = *x;
|
||||||
settings.pos = pos;
|
settings.pos = pos;
|
||||||
parse_fn_call(input, state, lib, name, false, modules, settings.level_up())?
|
let ns = namespace.map(|(_, ns)| ns);
|
||||||
|
parse_fn_call(input, state, lib, name, false, ns, settings.level_up())?
|
||||||
}
|
}
|
||||||
(Expr::Property(_), _) => unreachable!(),
|
(Expr::Property(_), _) => unreachable!(),
|
||||||
// module access
|
// module access
|
||||||
(Expr::Variable(x), Token::DoubleColon) => match input.next().unwrap() {
|
(Expr::Variable(x), Token::DoubleColon) => match input.next().unwrap() {
|
||||||
(Token::Identifier(id2), pos2) => {
|
(Token::Identifier(id2), pos2) => {
|
||||||
let (index, mut modules, _, var_name_def) = *x;
|
let (index, mut namespace, var_name_def) = *x;
|
||||||
|
|
||||||
if let Some(ref mut modules) = modules {
|
if let Some((_, ref mut namespace)) = namespace {
|
||||||
modules.push(var_name_def);
|
namespace.push(var_name_def);
|
||||||
} else {
|
} else {
|
||||||
let mut m: NamespaceRef = Default::default();
|
let mut ns: NamespaceRef = Default::default();
|
||||||
m.push(var_name_def);
|
ns.push(var_name_def);
|
||||||
modules = Some(Box::new(m));
|
let index = NonZeroU64::new(42).unwrap(); // Dummy
|
||||||
|
namespace = Some((index, ns));
|
||||||
}
|
}
|
||||||
|
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
name: state.get_interned_string(id2),
|
name: state.get_interned_string(id2),
|
||||||
pos: pos2,
|
pos: pos2,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((index, modules, None, var_name_def)))
|
Expr::Variable(Box::new((index, namespace, var_name_def)))
|
||||||
}
|
}
|
||||||
(Token::Reserved(id2), pos2) if is_valid_identifier(id2.chars()) => {
|
(Token::Reserved(id2), pos2) if is_valid_identifier(id2.chars()) => {
|
||||||
return Err(PERR::Reserved(id2).into_err(pos2));
|
return Err(PERR::Reserved(id2).into_err(pos2));
|
||||||
@ -1154,14 +1157,16 @@ fn parse_primary(
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
let (_, modules, hash, Ident { name, .. }) = x.as_mut();
|
if let (_, Some((ref mut hash, ref mut namespace)), Ident { name, .. }) = x.as_mut() {
|
||||||
let namespace = modules.as_mut().unwrap();
|
|
||||||
|
|
||||||
// Qualifiers + variable name
|
// Qualifiers + variable name
|
||||||
*hash = calc_script_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0);
|
*hash =
|
||||||
|
calc_script_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0).unwrap();
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
namespace.set_index(state.find_module(&namespace[0].name));
|
namespace.set_index(state.find_module(&namespace[0].name));
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make sure identifiers are valid
|
// Make sure identifiers are valid
|
||||||
@ -1335,7 +1340,7 @@ fn make_assignment_stmt<'a>(
|
|||||||
)),
|
)),
|
||||||
// var (indexed) = rhs
|
// var (indexed) = rhs
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let (index, _, _, Ident { name, pos }) = x.as_ref();
|
let (index, _, Ident { name, pos }) = x.as_ref();
|
||||||
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
|
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
|
||||||
AccessMode::ReadWrite => Ok(Stmt::Assignment(
|
AccessMode::ReadWrite => Ok(Stmt::Assignment(
|
||||||
Box::new((lhs, fn_name.into(), rhs)),
|
Box::new((lhs, fn_name.into(), rhs)),
|
||||||
@ -1356,7 +1361,7 @@ fn make_assignment_stmt<'a>(
|
|||||||
)),
|
)),
|
||||||
// var[???] (indexed) = rhs, var.??? (indexed) = rhs
|
// var[???] (indexed) = rhs, var.??? (indexed) = rhs
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let (index, _, _, Ident { name, pos }) = x.as_ref();
|
let (index, _, Ident { name, pos }) = x.as_ref();
|
||||||
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
|
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
|
||||||
AccessMode::ReadWrite => Ok(Stmt::Assignment(
|
AccessMode::ReadWrite => Ok(Stmt::Assignment(
|
||||||
Box::new((lhs, fn_name.into(), rhs)),
|
Box::new((lhs, fn_name.into(), rhs)),
|
||||||
@ -1440,7 +1445,7 @@ fn make_dot_expr(
|
|||||||
}
|
}
|
||||||
// lhs.id
|
// lhs.id
|
||||||
(lhs, Expr::Variable(x)) if x.1.is_none() => {
|
(lhs, Expr::Variable(x)) if x.1.is_none() => {
|
||||||
let ident = x.3;
|
let ident = x.2;
|
||||||
let getter = state.get_interned_string(crate::engine::make_getter(&ident.name));
|
let getter = state.get_interned_string(crate::engine::make_getter(&ident.name));
|
||||||
let setter = state.get_interned_string(crate::engine::make_setter(&ident.name));
|
let setter = state.get_interned_string(crate::engine::make_setter(&ident.name));
|
||||||
let rhs = Expr::Property(Box::new(((getter, setter), ident)));
|
let rhs = Expr::Property(Box::new(((getter, setter), ident)));
|
||||||
@ -1449,7 +1454,7 @@ fn make_dot_expr(
|
|||||||
}
|
}
|
||||||
// lhs.module::id - syntax error
|
// 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()[0].pos));
|
return Err(PERR::PropertyExpected.into_err(x.1.unwrap().1[0].pos));
|
||||||
}
|
}
|
||||||
// lhs.prop
|
// lhs.prop
|
||||||
(lhs, prop @ Expr::Property(_)) => {
|
(lhs, prop @ Expr::Property(_)) => {
|
||||||
@ -1877,7 +1882,7 @@ fn parse_custom_syntax(
|
|||||||
segments.push(name.clone());
|
segments.push(name.clone());
|
||||||
tokens.push(state.get_interned_string(MARKER_IDENT));
|
tokens.push(state.get_interned_string(MARKER_IDENT));
|
||||||
let var_name_def = Ident { name, pos };
|
let var_name_def = Ident { name, pos };
|
||||||
keywords.push(Expr::Variable(Box::new((None, None, None, var_name_def))));
|
keywords.push(Expr::Variable(Box::new((None, None, var_name_def))));
|
||||||
}
|
}
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
||||||
return Err(PERR::Reserved(s).into_err(pos));
|
return Err(PERR::Reserved(s).into_err(pos));
|
||||||
@ -2797,14 +2802,12 @@ fn make_curry_from_externals(fn_expr: Expr, externals: StaticVec<Ident>, pos: Po
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
externals.iter().for_each(|x| {
|
externals.iter().for_each(|x| {
|
||||||
let expr = Expr::Variable(Box::new((None, None, None, x.clone().into())));
|
args.push(Expr::Variable(Box::new((None, None, x.clone().into()))));
|
||||||
args.push(expr);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(feature = "no_closure")]
|
#[cfg(feature = "no_closure")]
|
||||||
externals.into_iter().for_each(|x| {
|
externals.into_iter().for_each(|x| {
|
||||||
let expr = Expr::Variable(Box::new((None, None, None, x.clone().into())));
|
args.push(Expr::Variable(Box::new((None, None, x.clone().into()))));
|
||||||
args.push(expr);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let curry_func = crate::engine::KEYWORD_FN_PTR_CURRY;
|
let curry_func = crate::engine::KEYWORD_FN_PTR_CURRY;
|
||||||
|
12
src/utils.rs
12
src/utils.rs
@ -22,23 +22,21 @@ use crate::Shared;
|
|||||||
///
|
///
|
||||||
/// Panics when hashing any data type other than a [`NonZeroU64`].
|
/// Panics when hashing any data type other than a [`NonZeroU64`].
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
pub struct StraightHasher(u64);
|
pub struct StraightHasher(NonZeroU64);
|
||||||
|
|
||||||
impl Hasher for StraightHasher {
|
impl Hasher for StraightHasher {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn finish(&self) -> u64 {
|
fn finish(&self) -> u64 {
|
||||||
self.0
|
self.0.get()
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn write(&mut self, bytes: &[u8]) {
|
fn write(&mut self, bytes: &[u8]) {
|
||||||
let mut key = [0_u8; 8];
|
let mut key = [0_u8; 8];
|
||||||
key.copy_from_slice(&bytes[..8]); // Panics if fewer than 8 bytes
|
key.copy_from_slice(&bytes[..8]); // Panics if fewer than 8 bytes
|
||||||
self.0 = u64::from_le_bytes(key);
|
|
||||||
|
|
||||||
// HACK - If it so happens to hash directly to zero (OMG!) then change it to 42...
|
// HACK - If it so happens to hash directly to zero (OMG!) then change it to 42...
|
||||||
if self.0 == 0 {
|
self.0 = NonZeroU64::new(u64::from_le_bytes(key))
|
||||||
self.0 = 42;
|
.unwrap_or_else(|| NonZeroU64::new(42).unwrap());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +49,7 @@ impl BuildHasher for StraightHasherBuilder {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn build_hasher(&self) -> Self::Hasher {
|
fn build_hasher(&self) -> Self::Hasher {
|
||||||
StraightHasher(1)
|
StraightHasher(NonZeroU64::new(42).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user