Minor code refactor.
This commit is contained in:
parent
cc304ba513
commit
b9de8eaa7f
42
src/ast.rs
42
src/ast.rs
@ -861,24 +861,24 @@ pub struct BinaryExpr {
|
|||||||
/// A function call.
|
/// A function call.
|
||||||
#[derive(Debug, Clone, Hash, Default)]
|
#[derive(Debug, Clone, Hash, Default)]
|
||||||
pub struct FnCallInfo {
|
pub struct FnCallInfo {
|
||||||
/// Function name.
|
/// Pre-calculated hash for a script-defined function of the same name and number of parameters.
|
||||||
/// Use `Cow<'static, str>` because a lot of operators (e.g. `==`, `>=`) are implemented as function calls
|
pub hash: u64,
|
||||||
/// and the function names are predictable, so no need to allocate a new `String`.
|
|
||||||
pub name: Cow<'static, str>,
|
|
||||||
/// Namespace of the function, if any.
|
|
||||||
pub namespace: Option<ModuleRef>,
|
|
||||||
/// Call native functions only? Set to `true` to skip searching for script-defined function overrides
|
/// Call native functions only? Set to `true` to skip searching for script-defined function overrides
|
||||||
/// when it is certain that the function must be native (e.g. an operator).
|
/// when it is certain that the function must be native (e.g. an operator).
|
||||||
pub native_only: bool,
|
pub native_only: bool,
|
||||||
/// Does this function call capture the parent scope?
|
/// Does this function call capture the parent scope?
|
||||||
pub capture: bool,
|
pub capture: bool,
|
||||||
/// Pre-calculated hash for a script-defined function of the same name and number of parameters.
|
|
||||||
pub hash: u64,
|
|
||||||
/// List of function call arguments.
|
|
||||||
pub args: StaticVec<Expr>,
|
|
||||||
/// 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.
|
||||||
/// Type is `bool` in order for `FnCallInfo` to be `Hash`
|
/// Type is `bool` in order for `FnCallInfo` to be `Hash`
|
||||||
pub def_value: Option<bool>,
|
pub def_value: Option<bool>,
|
||||||
|
/// Namespace of the function, if any.
|
||||||
|
pub namespace: Option<Box<ModuleRef>>,
|
||||||
|
/// Function name.
|
||||||
|
/// Use `Cow<'static, str>` 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`.
|
||||||
|
pub name: Cow<'static, str>,
|
||||||
|
/// List of function call arguments.
|
||||||
|
pub args: StaticVec<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// _[INTERNALS]_ An expression sub-tree.
|
/// _[INTERNALS]_ An expression sub-tree.
|
||||||
@ -903,10 +903,10 @@ pub enum Expr {
|
|||||||
StringConstant(Box<IdentX>),
|
StringConstant(Box<IdentX>),
|
||||||
/// FnPtr constant.
|
/// FnPtr constant.
|
||||||
FnPointer(Box<IdentX>),
|
FnPointer(Box<IdentX>),
|
||||||
/// Variable access - (variable name, optional modules, hash, optional index)
|
/// Variable access - (optional index, optional modules, hash, variable name)
|
||||||
Variable(Box<(Ident, Option<ModuleRef>, u64, Option<NonZeroUsize>)>),
|
Variable(Box<(Option<NonZeroUsize>, Option<Box<ModuleRef>>, u64, Ident)>),
|
||||||
/// Property access.
|
/// Property access - (getter, setter), prop
|
||||||
Property(Box<(IdentX, (String, String))>),
|
Property(Box<((String, String), IdentX)>),
|
||||||
/// { stmt }
|
/// { stmt }
|
||||||
Stmt(Box<Stmt>, Position),
|
Stmt(Box<Stmt>, Position),
|
||||||
/// Wrapped expression - should not be optimized away.
|
/// Wrapped expression - should not be optimized away.
|
||||||
@ -1014,7 +1014,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.0).name.as_str()),
|
Self::Variable(x) if !non_qualified || x.1.is_none() => Some((x.3).name.as_str()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1033,9 +1033,9 @@ impl Expr {
|
|||||||
Self::FnPointer(x) => x.pos,
|
Self::FnPointer(x) => x.pos,
|
||||||
Self::Array(_, pos) => *pos,
|
Self::Array(_, pos) => *pos,
|
||||||
Self::Map(_, pos) => *pos,
|
Self::Map(_, pos) => *pos,
|
||||||
Self::Property(x) => (x.0).pos,
|
Self::Property(x) => (x.1).pos,
|
||||||
Self::Stmt(_, pos) => *pos,
|
Self::Stmt(_, pos) => *pos,
|
||||||
Self::Variable(x) => (x.0).pos,
|
Self::Variable(x) => (x.3).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(),
|
||||||
@ -1064,8 +1064,8 @@ impl Expr {
|
|||||||
Self::FnPointer(x) => x.pos = new_pos,
|
Self::FnPointer(x) => x.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.0).pos = new_pos,
|
Self::Variable(x) => (x.3).pos = new_pos,
|
||||||
Self::Property(x) => (x.0).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,
|
||||||
Self::And(_, pos) | Self::Or(_, pos) | Self::In(_, pos) => *pos = new_pos,
|
Self::And(_, pos) | Self::Or(_, pos) | Self::In(_, pos) => *pos = new_pos,
|
||||||
@ -1231,10 +1231,10 @@ impl Expr {
|
|||||||
pub(crate) fn into_property(self) -> Self {
|
pub(crate) fn into_property(self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Variable(x) if x.1.is_none() => {
|
Self::Variable(x) if x.1.is_none() => {
|
||||||
let ident = x.0;
|
let ident = x.3;
|
||||||
let getter = make_getter(&ident.name);
|
let getter = make_getter(&ident.name);
|
||||||
let setter = make_setter(&ident.name);
|
let setter = make_setter(&ident.name);
|
||||||
Self::Property(Box::new((ident.into(), (getter, setter))))
|
Self::Property(Box::new(((getter, setter), ident.into())))
|
||||||
}
|
}
|
||||||
_ => self,
|
_ => self,
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ pub type Map = HashMap<ImmutableString, Dynamic>;
|
|||||||
// `Imports` is implemented as two `Vec`'s of exactly the same length. That's because a `Module` is large,
|
// `Imports` is implemented as two `Vec`'s of exactly the same length. That's because a `Module` is large,
|
||||||
// so packing the import names together improves cache locality.
|
// so packing the import names together improves cache locality.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Imports(StaticVec<ImmutableString>, StaticVec<Module>);
|
pub struct Imports(StaticVec<Module>, StaticVec<ImmutableString>);
|
||||||
|
|
||||||
impl Imports {
|
impl Imports {
|
||||||
/// Get the length of this stack of imported modules.
|
/// Get the length of this stack of imported modules.
|
||||||
@ -86,15 +86,15 @@ impl Imports {
|
|||||||
}
|
}
|
||||||
/// Get the imported module at a particular index.
|
/// Get the imported module at a particular index.
|
||||||
pub fn get(&self, index: usize) -> Option<&Module> {
|
pub fn get(&self, index: usize) -> Option<&Module> {
|
||||||
self.1.get(index)
|
self.0.get(index)
|
||||||
}
|
}
|
||||||
/// Get a mutable reference to the imported module at a particular index.
|
/// Get a mutable reference to the imported module at a particular index.
|
||||||
pub fn get_mut(&mut self, index: usize) -> Option<&mut Module> {
|
pub fn get_mut(&mut self, index: usize) -> Option<&mut Module> {
|
||||||
self.1.get_mut(index)
|
self.0.get_mut(index)
|
||||||
}
|
}
|
||||||
/// Get the index of an imported module by name.
|
/// Get the index of an imported module by name.
|
||||||
pub fn find(&self, name: &str) -> Option<usize> {
|
pub fn find(&self, name: &str) -> Option<usize> {
|
||||||
self.0
|
self.1
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev()
|
.rev()
|
||||||
@ -103,8 +103,8 @@ impl Imports {
|
|||||||
}
|
}
|
||||||
/// Push an imported module onto the stack.
|
/// Push an imported module onto the stack.
|
||||||
pub fn push(&mut self, name: impl Into<ImmutableString>, module: Module) {
|
pub fn push(&mut self, name: impl Into<ImmutableString>, module: Module) {
|
||||||
self.0.push(name.into());
|
self.0.push(module);
|
||||||
self.1.push(module);
|
self.1.push(name.into());
|
||||||
}
|
}
|
||||||
/// Truncate the stack of imported modules to a particular length.
|
/// Truncate the stack of imported modules to a particular length.
|
||||||
pub fn truncate(&mut self, size: usize) {
|
pub fn truncate(&mut self, size: usize) {
|
||||||
@ -114,11 +114,11 @@ impl Imports {
|
|||||||
/// Get an iterator to this stack of imported modules.
|
/// Get an iterator to this stack of imported modules.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn iter(&self) -> impl Iterator<Item = (&str, &Module)> {
|
pub fn iter(&self) -> impl Iterator<Item = (&str, &Module)> {
|
||||||
self.0.iter().map(|name| name.as_str()).zip(self.1.iter())
|
self.1.iter().map(|name| name.as_str()).zip(self.0.iter())
|
||||||
}
|
}
|
||||||
/// Get a consuming iterator to this stack of imported modules.
|
/// Get a consuming iterator to this stack of imported modules.
|
||||||
pub fn into_iter(self) -> impl Iterator<Item = (ImmutableString, Module)> {
|
pub fn into_iter(self) -> impl Iterator<Item = (ImmutableString, Module)> {
|
||||||
self.0.into_iter().zip(self.1.into_iter())
|
self.1.into_iter().zip(self.0.into_iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,7 +812,7 @@ impl Engine {
|
|||||||
match expr {
|
match expr {
|
||||||
Expr::Variable(v) => match v.as_ref() {
|
Expr::Variable(v) => match v.as_ref() {
|
||||||
// Qualified variable
|
// Qualified variable
|
||||||
(Ident { name, pos }, Some(modules), hash_var, _) => {
|
(_, Some(modules), hash_var, Ident { name, pos }) => {
|
||||||
let module = search_imports_mut(mods, state, modules)?;
|
let module = search_imports_mut(mods, state, modules)?;
|
||||||
let target = module.get_qualified_var_mut(*hash_var).map_err(|mut err| {
|
let target = module.get_qualified_var_mut(*hash_var).map_err(|mut err| {
|
||||||
match *err {
|
match *err {
|
||||||
@ -844,7 +844,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, ScopeEntryType, Position), Box<EvalAltResult>> {
|
) -> Result<(Target<'s>, &'a str, ScopeEntryType, Position), Box<EvalAltResult>> {
|
||||||
let (Ident { name, pos }, _, _, index) = match expr {
|
let (index, _, _, Ident { name, pos }) = match expr {
|
||||||
Expr::Variable(v) => v.as_ref(),
|
Expr::Variable(v) => v.as_ref(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
@ -984,7 +984,7 @@ impl Engine {
|
|||||||
let args = &mut [val, &mut idx_val2, &mut new_val.0];
|
let args = &mut [val, &mut idx_val2, &mut new_val.0];
|
||||||
|
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, &None,
|
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, None,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map_err(|err| match *err {
|
.map_err(|err| match *err {
|
||||||
@ -1026,8 +1026,7 @@ impl Engine {
|
|||||||
let def_value = def_value.map(Into::<Dynamic>::into);
|
let def_value = def_value.map(Into::<Dynamic>::into);
|
||||||
let args = idx_val.as_fn_call_args();
|
let args = idx_val.as_fn_call_args();
|
||||||
self.make_method_call(
|
self.make_method_call(
|
||||||
state, lib, name, *hash, target, args, &def_value, *native, false,
|
state, lib, name, *hash, target, args, def_value, *native, false, level,
|
||||||
level,
|
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*pos))
|
.map_err(|err| err.fill_position(*pos))
|
||||||
}
|
}
|
||||||
@ -1035,7 +1034,7 @@ impl Engine {
|
|||||||
Expr::FnCall(_, _) => unreachable!(),
|
Expr::FnCall(_, _) => unreachable!(),
|
||||||
// {xxx:map}.id = ???
|
// {xxx:map}.id = ???
|
||||||
Expr::Property(x) if target.is::<Map>() && new_val.is_some() => {
|
Expr::Property(x) if target.is::<Map>() && new_val.is_some() => {
|
||||||
let IdentX { name, pos } = &x.0;
|
let IdentX { name, pos } = &x.1;
|
||||||
let index = name.clone().into();
|
let index = name.clone().into();
|
||||||
let mut val = self
|
let mut val = self
|
||||||
.get_indexed_mut(state, lib, target, index, *pos, true, false, level)?;
|
.get_indexed_mut(state, lib, target, index, *pos, true, false, level)?;
|
||||||
@ -1045,7 +1044,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// {xxx:map}.id
|
// {xxx:map}.id
|
||||||
Expr::Property(x) if target.is::<Map>() => {
|
Expr::Property(x) if target.is::<Map>() => {
|
||||||
let IdentX { name, pos } = &x.0;
|
let IdentX { name, pos } = &x.1;
|
||||||
let index = name.clone().into();
|
let index = name.clone().into();
|
||||||
let val = self.get_indexed_mut(
|
let val = self.get_indexed_mut(
|
||||||
state, lib, target, index, *pos, false, false, level,
|
state, lib, target, index, *pos, false, false, level,
|
||||||
@ -1055,11 +1054,11 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// xxx.id = ???
|
// xxx.id = ???
|
||||||
Expr::Property(x) if new_val.is_some() => {
|
Expr::Property(x) if new_val.is_some() => {
|
||||||
let (IdentX { pos, .. }, (_, setter)) = x.as_ref();
|
let ((_, setter), IdentX { pos, .. }) = x.as_ref();
|
||||||
let mut new_val = new_val;
|
let mut new_val = new_val;
|
||||||
let mut args = [target.as_mut(), &mut new_val.as_mut().unwrap().0];
|
let mut args = [target.as_mut(), &mut new_val.as_mut().unwrap().0];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, setter, 0, &mut args, is_ref, true, false, None, &None,
|
state, lib, setter, 0, &mut args, is_ref, true, false, None, None,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| (v, true))
|
.map(|(v, _)| (v, true))
|
||||||
@ -1067,10 +1066,10 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(x) => {
|
Expr::Property(x) => {
|
||||||
let (IdentX { pos, .. }, (getter, _)) = x.as_ref();
|
let ((getter, _), IdentX { pos, .. }) = x.as_ref();
|
||||||
let mut args = [target.as_mut()];
|
let mut args = [target.as_mut()];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, getter, 0, &mut args, is_ref, true, false, None, &None,
|
state, lib, getter, 0, &mut args, is_ref, true, false, None, None,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| (v, false))
|
.map(|(v, _)| (v, false))
|
||||||
@ -1080,7 +1079,7 @@ impl Engine {
|
|||||||
Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) if target.is::<Map>() => {
|
Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) if target.is::<Map>() => {
|
||||||
let mut val = match &x.lhs {
|
let mut val = match &x.lhs {
|
||||||
Expr::Property(p) => {
|
Expr::Property(p) => {
|
||||||
let IdentX { name, pos } = &p.0;
|
let IdentX { name, pos } = &p.1;
|
||||||
let index = name.clone().into();
|
let index = name.clone().into();
|
||||||
self.get_indexed_mut(
|
self.get_indexed_mut(
|
||||||
state, lib, target, index, *pos, false, true, level,
|
state, lib, target, index, *pos, false, true, level,
|
||||||
@ -1099,7 +1098,7 @@ impl Engine {
|
|||||||
let args = idx_val.as_fn_call_args();
|
let args = idx_val.as_fn_call_args();
|
||||||
let (val, _) = self
|
let (val, _) = self
|
||||||
.make_method_call(
|
.make_method_call(
|
||||||
state, lib, name, *hash, target, args, &def_value, *native,
|
state, lib, name, *hash, target, args, def_value, *native,
|
||||||
false, level,
|
false, level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*pos))?;
|
.map_err(|err| err.fill_position(*pos))?;
|
||||||
@ -1122,13 +1121,13 @@ impl Engine {
|
|||||||
match &x.lhs {
|
match &x.lhs {
|
||||||
// xxx.prop[expr] | xxx.prop.expr
|
// xxx.prop[expr] | xxx.prop.expr
|
||||||
Expr::Property(p) => {
|
Expr::Property(p) => {
|
||||||
let (IdentX { pos, .. }, (getter, setter)) = p.as_ref();
|
let ((getter, setter), IdentX { pos, .. }) = p.as_ref();
|
||||||
let arg_values = &mut [target.as_mut(), &mut Default::default()];
|
let arg_values = &mut [target.as_mut(), &mut Default::default()];
|
||||||
let args = &mut arg_values[..1];
|
let args = &mut arg_values[..1];
|
||||||
let (mut val, updated) = self
|
let (mut val, updated) = self
|
||||||
.exec_fn_call(
|
.exec_fn_call(
|
||||||
state, lib, getter, 0, args, is_ref, true, false, None,
|
state, lib, getter, 0, args, is_ref, true, false, None,
|
||||||
&None, level,
|
None, level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*pos))?;
|
.map_err(|err| err.fill_position(*pos))?;
|
||||||
|
|
||||||
@ -1154,7 +1153,7 @@ impl Engine {
|
|||||||
arg_values[1] = val;
|
arg_values[1] = val;
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, setter, 0, arg_values, is_ref, true, false,
|
state, lib, setter, 0, arg_values, is_ref, true, false,
|
||||||
None, &None, level,
|
None, None, level,
|
||||||
)
|
)
|
||||||
.or_else(
|
.or_else(
|
||||||
|err| match *err {
|
|err| match *err {
|
||||||
@ -1182,7 +1181,7 @@ impl Engine {
|
|||||||
let args = idx_val.as_fn_call_args();
|
let args = idx_val.as_fn_call_args();
|
||||||
let (mut val, _) = self
|
let (mut val, _) = self
|
||||||
.make_method_call(
|
.make_method_call(
|
||||||
state, lib, name, *hash, target, args, &def_value, *native,
|
state, lib, name, *hash, target, args, def_value, *native,
|
||||||
false, level,
|
false, level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*pos))?;
|
.map_err(|err| err.fill_position(*pos))?;
|
||||||
@ -1257,7 +1256,7 @@ impl Engine {
|
|||||||
let Ident {
|
let Ident {
|
||||||
name: var_name,
|
name: var_name,
|
||||||
pos: var_pos,
|
pos: var_pos,
|
||||||
} = &x.0;
|
} = &x.3;
|
||||||
|
|
||||||
self.inc_operations(state)
|
self.inc_operations(state)
|
||||||
.map_err(|err| err.fill_position(*var_pos))?;
|
.map_err(|err| err.fill_position(*var_pos))?;
|
||||||
@ -1458,7 +1457,7 @@ impl Engine {
|
|||||||
let mut idx = idx;
|
let mut idx = idx;
|
||||||
let args = &mut [val, &mut idx];
|
let args = &mut [val, &mut idx];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, _lib, FN_IDX_GET, 0, args, is_ref, true, false, None, &None, _level,
|
state, _lib, FN_IDX_GET, 0, args, is_ref, true, false, None, None, _level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| v.into())
|
.map(|(v, _)| v.into())
|
||||||
.map_err(|err| match *err {
|
.map_err(|err| match *err {
|
||||||
@ -1504,13 +1503,14 @@ impl Engine {
|
|||||||
|
|
||||||
for value in rhs_value.iter_mut() {
|
for value in rhs_value.iter_mut() {
|
||||||
let args = &mut [&mut lhs_value.clone(), value];
|
let args = &mut [&mut lhs_value.clone(), value];
|
||||||
|
let def_value = def_value.clone();
|
||||||
|
|
||||||
// Qualifiers (none) + function name + number of arguments + argument `TypeId`'s.
|
// Qualifiers (none) + function name + number of arguments + argument `TypeId`'s.
|
||||||
let hash =
|
let hash =
|
||||||
calc_native_fn_hash(empty(), OP_FUNC, args.iter().map(|a| a.type_id()));
|
calc_native_fn_hash(empty(), OP_FUNC, args.iter().map(|a| a.type_id()));
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.call_native_fn(state, lib, OP_FUNC, hash, args, false, false, &def_value)
|
.call_native_fn(state, lib, OP_FUNC, hash, args, false, false, def_value)
|
||||||
.map_err(|err| err.fill_position(rhs.position()))?
|
.map_err(|err| err.fill_position(rhs.position()))?
|
||||||
.0
|
.0
|
||||||
.as_bool()
|
.as_bool()
|
||||||
@ -1520,7 +1520,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(def_value.unwrap())
|
Ok(false.into())
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Dynamic(Union::Map(rhs_value)) => match lhs_value {
|
Dynamic(Union::Map(rhs_value)) => match lhs_value {
|
||||||
@ -1564,11 +1564,11 @@ impl Engine {
|
|||||||
Expr::FnPointer(x) => {
|
Expr::FnPointer(x) => {
|
||||||
Ok(FnPtr::new_unchecked(x.name.clone(), Default::default()).into())
|
Ok(FnPtr::new_unchecked(x.name.clone(), Default::default()).into())
|
||||||
}
|
}
|
||||||
Expr::Variable(x) if (x.0).name == KEYWORD_THIS => {
|
Expr::Variable(x) if (x.3).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.0).pos).into()
|
EvalAltResult::ErrorUnboundThis((x.3).pos).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Variable(_) => {
|
Expr::Variable(_) => {
|
||||||
@ -1623,7 +1623,7 @@ impl Engine {
|
|||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
let def_value = def_value.map(Into::<Dynamic>::into);
|
let def_value = def_value.map(Into::<Dynamic>::into);
|
||||||
self.make_function_call(
|
self.make_function_call(
|
||||||
scope, mods, state, lib, this_ptr, name, args, &def_value, *hash, *native,
|
scope, mods, state, lib, this_ptr, name, args, def_value, *hash, *native,
|
||||||
false, *cap_scope, level,
|
false, *cap_scope, level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*pos))
|
.map_err(|err| err.fill_position(*pos))
|
||||||
@ -1639,8 +1639,9 @@ impl Engine {
|
|||||||
def_value,
|
def_value,
|
||||||
..
|
..
|
||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
|
let modules = namespace.as_ref().map(|v| v.as_ref());
|
||||||
self.make_qualified_function_call(
|
self.make_qualified_function_call(
|
||||||
scope, mods, state, lib, this_ptr, namespace, name, args, *def_value, *hash,
|
scope, mods, state, lib, this_ptr, modules, name, args, *def_value, *hash,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*pos))
|
.map_err(|err| err.fill_position(*pos))
|
||||||
@ -1812,7 +1813,7 @@ impl Engine {
|
|||||||
// Run function
|
// Run function
|
||||||
let (value, _) = self
|
let (value, _) = self
|
||||||
.exec_fn_call(
|
.exec_fn_call(
|
||||||
state, lib, op, 0, args, false, false, false, None, &None,
|
state, lib, op, 0, args, false, false, false, None, None,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*op_pos))?;
|
.map_err(|err| err.fill_position(*op_pos))?;
|
||||||
@ -1850,7 +1851,7 @@ impl Engine {
|
|||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.exec_fn_call(
|
.exec_fn_call(
|
||||||
state, lib, op, 0, args, false, false, false, None, &None, level,
|
state, lib, op, 0, args, false, false, false, None, None, level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
.map_err(|err| err.fill_position(*op_pos))?;
|
.map_err(|err| err.fill_position(*op_pos))?;
|
||||||
|
@ -186,7 +186,7 @@ impl Engine {
|
|||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
is_ref: bool,
|
is_ref: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
def_val: &Option<Dynamic>,
|
def_val: Option<Dynamic>,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
self.inc_operations(state)?;
|
self.inc_operations(state)?;
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Return default value (if any)
|
// Return default value (if any)
|
||||||
if let Some(val) = def_val {
|
if let Some(val) = def_val {
|
||||||
return Ok((val.clone(), false));
|
return Ok((val, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getter function not found?
|
// Getter function not found?
|
||||||
@ -479,7 +479,7 @@ impl Engine {
|
|||||||
_is_method: bool,
|
_is_method: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
_capture_scope: Option<Scope>,
|
_capture_scope: Option<Scope>,
|
||||||
def_val: &Option<Dynamic>,
|
def_val: Option<Dynamic>,
|
||||||
_level: usize,
|
_level: usize,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
// Check for data race.
|
// Check for data race.
|
||||||
@ -686,7 +686,7 @@ impl Engine {
|
|||||||
hash_script: u64,
|
hash_script: u64,
|
||||||
target: &mut Target,
|
target: &mut Target,
|
||||||
mut call_args: StaticVec<Dynamic>,
|
mut call_args: StaticVec<Dynamic>,
|
||||||
def_val: &Option<Dynamic>,
|
def_val: Option<Dynamic>,
|
||||||
native: bool,
|
native: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
level: usize,
|
level: usize,
|
||||||
@ -837,7 +837,7 @@ impl Engine {
|
|||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
name: &str,
|
name: &str,
|
||||||
args_expr: impl AsRef<[Expr]>,
|
args_expr: impl AsRef<[Expr]>,
|
||||||
def_val: &Option<Dynamic>,
|
def_val: Option<Dynamic>,
|
||||||
mut hash_script: u64,
|
mut hash_script: u64,
|
||||||
native: bool,
|
native: bool,
|
||||||
pub_only: bool,
|
pub_only: bool,
|
||||||
@ -1074,7 +1074,7 @@ impl Engine {
|
|||||||
state: &mut State,
|
state: &mut State,
|
||||||
lib: &[&Module],
|
lib: &[&Module],
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
modules: &Option<ModuleRef>,
|
modules: Option<&ModuleRef>,
|
||||||
name: &str,
|
name: &str,
|
||||||
args_expr: impl AsRef<[Expr]>,
|
args_expr: impl AsRef<[Expr]>,
|
||||||
def_val: Option<bool>,
|
def_val: Option<bool>,
|
||||||
|
@ -193,7 +193,7 @@ impl FnPtr {
|
|||||||
has_this,
|
has_this,
|
||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
&None,
|
None,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
|
@ -147,7 +147,7 @@ fn call_fn_with_constant_arguments(
|
|||||||
arg_values.iter_mut().collect::<StaticVec<_>>().as_mut(),
|
arg_values.iter_mut().collect::<StaticVec<_>>().as_mut(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
&None,
|
None,
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
@ -454,7 +454,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr {
|
|||||||
Expr::Dot(x, dot_pos) => match (x.lhs, x.rhs) {
|
Expr::Dot(x, dot_pos) => match (x.lhs, x.rhs) {
|
||||||
// map.string
|
// map.string
|
||||||
(Expr::Map(m, pos), Expr::Property(p)) if m.iter().all(|(_, x)| x.is_pure()) => {
|
(Expr::Map(m, pos), Expr::Property(p)) if m.iter().all(|(_, x)| x.is_pure()) => {
|
||||||
let prop = &p.0.name;
|
let prop = &p.1.name;
|
||||||
// Map literal where everything is pure - promote the indexed item.
|
// Map literal where everything is pure - promote the indexed item.
|
||||||
// All other items can be thrown away.
|
// All other items can be thrown away.
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
@ -686,12 +686,12 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// constant-name
|
// constant-name
|
||||||
Expr::Variable(x) if x.1.is_none() && state.contains_constant(&x.0.name) => {
|
Expr::Variable(x) if x.1.is_none() && state.contains_constant(&x.3.name) => {
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
|
|
||||||
// Replace constant with value
|
// Replace constant with value
|
||||||
let mut expr = state.find_constant(&x.0.name).unwrap().clone();
|
let mut expr = state.find_constant(&x.3.name).unwrap().clone();
|
||||||
expr.set_position(x.0.pos);
|
expr.set_position(x.3.pos);
|
||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ fn parse_fn_call(
|
|||||||
lib: &mut FunctionsLib,
|
lib: &mut FunctionsLib,
|
||||||
id: String,
|
id: String,
|
||||||
capture: bool,
|
capture: bool,
|
||||||
mut namespace: Option<ModuleRef>,
|
mut namespace: Option<Box<ModuleRef>>,
|
||||||
settings: ParseSettings,
|
settings: ParseSettings,
|
||||||
) -> Result<Expr, ParseError> {
|
) -> Result<Expr, ParseError> {
|
||||||
let (token, token_pos) = input.peek().unwrap();
|
let (token, token_pos) = input.peek().unwrap();
|
||||||
@ -788,7 +788,7 @@ fn parse_primary(
|
|||||||
{
|
{
|
||||||
state.allow_capture = true;
|
state.allow_capture = true;
|
||||||
}
|
}
|
||||||
Expr::Variable(Box::new((Ident::new(s, settings.pos), None, 0, None)))
|
Expr::Variable(Box::new((None, None, 0, Ident::new(s, settings.pos))))
|
||||||
}
|
}
|
||||||
// Module qualification
|
// Module qualification
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -798,18 +798,18 @@ fn parse_primary(
|
|||||||
{
|
{
|
||||||
state.allow_capture = true;
|
state.allow_capture = true;
|
||||||
}
|
}
|
||||||
Expr::Variable(Box::new((Ident::new(s, settings.pos), None, 0, None)))
|
Expr::Variable(Box::new((None, None, 0, Ident::new(s, settings.pos))))
|
||||||
}
|
}
|
||||||
// Normal variable access
|
// Normal variable access
|
||||||
Token::Identifier(s) => {
|
Token::Identifier(s) => {
|
||||||
let index = state.access_var(&s, settings.pos);
|
let index = state.access_var(&s, settings.pos);
|
||||||
Expr::Variable(Box::new((Ident::new(s, settings.pos), None, 0, index)))
|
Expr::Variable(Box::new((index, None, 0, Ident::new(s, settings.pos))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function call is allowed to have reserved keyword
|
// Function call is allowed to have reserved keyword
|
||||||
Token::Reserved(s) if *next_token == Token::LeftParen || *next_token == Token::Bang => {
|
Token::Reserved(s) if *next_token == Token::LeftParen || *next_token == Token::Bang => {
|
||||||
if is_keyword_function(&s) {
|
if is_keyword_function(&s) {
|
||||||
Expr::Variable(Box::new((Ident::new(s, settings.pos), None, 0, None)))
|
Expr::Variable(Box::new((None, None, 0, Ident::new(s, settings.pos))))
|
||||||
} else {
|
} else {
|
||||||
return Err(PERR::Reserved(s).into_err(settings.pos));
|
return Err(PERR::Reserved(s).into_err(settings.pos));
|
||||||
}
|
}
|
||||||
@ -824,7 +824,7 @@ fn parse_primary(
|
|||||||
)))
|
)))
|
||||||
.into_err(settings.pos));
|
.into_err(settings.pos));
|
||||||
} else {
|
} else {
|
||||||
Expr::Variable(Box::new((Ident::new(s, settings.pos), None, 0, None)))
|
Expr::Variable(Box::new((None, None, 0, Ident::new(s, settings.pos))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,13 +883,13 @@ fn parse_primary(
|
|||||||
.into_err(pos));
|
.into_err(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (Ident { name, pos }, modules, _, _) = *x;
|
let (_, modules, _, Ident { name, pos }) = *x;
|
||||||
settings.pos = pos;
|
settings.pos = pos;
|
||||||
parse_fn_call(input, state, lib, name, true, modules, settings.level_up())?
|
parse_fn_call(input, state, lib, name, true, modules, settings.level_up())?
|
||||||
}
|
}
|
||||||
// Function call
|
// Function call
|
||||||
(Expr::Variable(x), Token::LeftParen) => {
|
(Expr::Variable(x), Token::LeftParen) => {
|
||||||
let (Ident { name, pos }, modules, _, _) = *x;
|
let (_, modules, _, Ident { name, pos }) = *x;
|
||||||
settings.pos = pos;
|
settings.pos = pos;
|
||||||
parse_fn_call(input, state, lib, name, false, modules, settings.level_up())?
|
parse_fn_call(input, state, lib, name, false, modules, settings.level_up())?
|
||||||
}
|
}
|
||||||
@ -897,17 +897,17 @@ fn parse_primary(
|
|||||||
// 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 (var_name_def, mut modules, _, index) = *x;
|
let (index, mut modules, _, var_name_def) = *x;
|
||||||
|
|
||||||
if let Some(ref mut modules) = modules {
|
if let Some(ref mut modules) = modules {
|
||||||
modules.push(var_name_def);
|
modules.push(var_name_def);
|
||||||
} else {
|
} else {
|
||||||
let mut m: ModuleRef = Default::default();
|
let mut m: ModuleRef = Default::default();
|
||||||
m.push(var_name_def);
|
m.push(var_name_def);
|
||||||
modules = Some(m);
|
modules = Some(Box::new(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Variable(Box::new((Ident::new(id2, pos2), modules, 0, index)))
|
Expr::Variable(Box::new((index, modules, 0, Ident::new(id2, pos2))))
|
||||||
}
|
}
|
||||||
(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));
|
||||||
@ -931,7 +931,7 @@ fn parse_primary(
|
|||||||
match &mut root_expr {
|
match &mut root_expr {
|
||||||
// Cache the hash key for module-qualified variables
|
// Cache the hash key for module-qualified variables
|
||||||
Expr::Variable(x) if x.1.is_some() => {
|
Expr::Variable(x) if x.1.is_some() => {
|
||||||
let (Ident { name, .. }, modules, hash, _) = x.as_mut();
|
let (_, modules, hash, Ident { name, .. }) = x.as_mut();
|
||||||
let modules = modules.as_mut().unwrap();
|
let modules = modules.as_mut().unwrap();
|
||||||
|
|
||||||
// Qualifiers + variable name
|
// Qualifiers + variable name
|
||||||
@ -1087,19 +1087,19 @@ fn make_assignment_stmt<'a>(
|
|||||||
) -> Result<Stmt, ParseError> {
|
) -> Result<Stmt, ParseError> {
|
||||||
match &lhs {
|
match &lhs {
|
||||||
// var (non-indexed) = rhs
|
// var (non-indexed) = rhs
|
||||||
Expr::Variable(x) if x.3.is_none() => {
|
Expr::Variable(x) if x.1.is_none() => {
|
||||||
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
||||||
}
|
}
|
||||||
// var (indexed) = rhs
|
// var (indexed) = rhs
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let (
|
let (
|
||||||
|
index,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
Ident {
|
Ident {
|
||||||
name,
|
name,
|
||||||
pos: name_pos,
|
pos: name_pos,
|
||||||
},
|
},
|
||||||
_,
|
|
||||||
_,
|
|
||||||
index,
|
|
||||||
) = x.as_ref();
|
) = x.as_ref();
|
||||||
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
|
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
|
||||||
ScopeEntryType::Normal => {
|
ScopeEntryType::Normal => {
|
||||||
@ -1114,19 +1114,19 @@ fn make_assignment_stmt<'a>(
|
|||||||
// xxx[???] = rhs, xxx.??? = rhs
|
// xxx[???] = rhs, xxx.??? = rhs
|
||||||
Expr::Index(x, _) | Expr::Dot(x, _) => match &x.lhs {
|
Expr::Index(x, _) | Expr::Dot(x, _) => match &x.lhs {
|
||||||
// var[???] (non-indexed) = rhs, var.??? (non-indexed) = rhs
|
// var[???] (non-indexed) = rhs, var.??? (non-indexed) = rhs
|
||||||
Expr::Variable(x) if x.3.is_none() => {
|
Expr::Variable(x) if x.1.is_none() => {
|
||||||
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
||||||
}
|
}
|
||||||
// var[???] (indexed) = rhs, var.??? (indexed) = rhs
|
// var[???] (indexed) = rhs, var.??? (indexed) = rhs
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let (
|
let (
|
||||||
|
index,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
Ident {
|
Ident {
|
||||||
name,
|
name,
|
||||||
pos: name_pos,
|
pos: name_pos,
|
||||||
},
|
},
|
||||||
_,
|
|
||||||
_,
|
|
||||||
index,
|
|
||||||
) = x.as_ref();
|
) = x.as_ref();
|
||||||
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
|
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
|
||||||
ScopeEntryType::Normal => {
|
ScopeEntryType::Normal => {
|
||||||
@ -1204,10 +1204,10 @@ fn make_dot_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result<Expr, ParseEr
|
|||||||
}
|
}
|
||||||
// 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.0;
|
let ident = x.3;
|
||||||
let getter = make_getter(&ident.name);
|
let getter = make_getter(&ident.name);
|
||||||
let setter = make_setter(&ident.name);
|
let setter = make_setter(&ident.name);
|
||||||
let rhs = Expr::Property(Box::new((ident.into(), (getter, setter))));
|
let rhs = Expr::Property(Box::new(((getter, setter), ident.into())));
|
||||||
|
|
||||||
Expr::Dot(Box::new(BinaryExpr { lhs, rhs }), op_pos)
|
Expr::Dot(Box::new(BinaryExpr { lhs, rhs }), op_pos)
|
||||||
}
|
}
|
||||||
@ -1642,10 +1642,10 @@ fn parse_custom_syntax(
|
|||||||
(Token::Identifier(s), pos) => {
|
(Token::Identifier(s), pos) => {
|
||||||
segments.push(s.clone());
|
segments.push(s.clone());
|
||||||
exprs.push(Expr::Variable(Box::new((
|
exprs.push(Expr::Variable(Box::new((
|
||||||
Ident::new(s, pos),
|
None,
|
||||||
None,
|
None,
|
||||||
0,
|
0,
|
||||||
None,
|
Ident::new(s, pos),
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
||||||
@ -2500,12 +2500,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| {
|
||||||
args.push(Expr::Variable(Box::new((x.clone(), None, 0, None))));
|
args.push(Expr::Variable(Box::new((None, None, 0, x.clone()))));
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(feature = "no_closure")]
|
#[cfg(feature = "no_closure")]
|
||||||
externals.into_iter().for_each(|x| {
|
externals.into_iter().for_each(|x| {
|
||||||
args.push(Expr::Variable(Box::new((x.clone(), None, 0, None))));
|
args.push(Expr::Variable(Box::new((None, None, 0, x.clone()))));
|
||||||
});
|
});
|
||||||
|
|
||||||
let hash = calc_script_fn_hash(empty(), KEYWORD_FN_PTR_CURRY, num_externals + 1);
|
let hash = calc_script_fn_hash(empty(), KEYWORD_FN_PTR_CURRY, num_externals + 1);
|
||||||
|
@ -66,12 +66,12 @@ impl EntryType {
|
|||||||
// The variable type is packed separately into another array because it is even smaller.
|
// The variable type is packed separately into another array because it is even smaller.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Scope<'a> {
|
pub struct Scope<'a> {
|
||||||
/// (Name, alias) of the entry.
|
|
||||||
names: Vec<(Cow<'a, str>, Option<String>)>,
|
|
||||||
/// Type of the entry.
|
|
||||||
types: Vec<EntryType>,
|
|
||||||
/// Current value of the entry.
|
/// Current value of the entry.
|
||||||
values: Vec<Dynamic>,
|
values: Vec<Dynamic>,
|
||||||
|
/// Type of the entry.
|
||||||
|
types: Vec<EntryType>,
|
||||||
|
/// (Name, alias) of the entry.
|
||||||
|
names: Vec<(Cow<'a, str>, Option<String>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Scope<'a> {
|
impl<'a> Scope<'a> {
|
||||||
|
101
src/token.rs
101
src/token.rs
@ -45,9 +45,14 @@ pub struct Position {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// No `Position`.
|
/// No `Position`.
|
||||||
pub const NO_POS: Position = Position { line: 0, pos: 0 };
|
pub const NO_POS: Position = Position::NONE;
|
||||||
|
|
||||||
impl Position {
|
impl Position {
|
||||||
|
/// A `Position` representing no position.
|
||||||
|
pub const NONE: Self = Self { line: 0, pos: 0 };
|
||||||
|
/// A `Position` representing the first position.
|
||||||
|
pub const START: Self = Self { line: 1, pos: 0 };
|
||||||
|
|
||||||
/// Create a new `Position`.
|
/// Create a new `Position`.
|
||||||
///
|
///
|
||||||
/// `line` must not be zero.
|
/// `line` must not be zero.
|
||||||
@ -65,27 +70,24 @@ impl Position {
|
|||||||
pos: position,
|
pos: position,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the line number (1-based), or `None` if there is no position.
|
/// Get the line number (1-based), or `None` if there is no position.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn line(&self) -> Option<usize> {
|
pub fn line(self) -> Option<usize> {
|
||||||
if self.is_none() {
|
if self.is_none() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(self.line as usize)
|
Some(self.line as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the character position (1-based), or `None` if at beginning of a line.
|
/// Get the character position (1-based), or `None` if at beginning of a line.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn position(&self) -> Option<usize> {
|
pub fn position(self) -> Option<usize> {
|
||||||
if self.is_none() || self.pos == 0 {
|
if self.is_none() || self.pos == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(self.pos as usize)
|
Some(self.pos as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advance by one character position.
|
/// Advance by one character position.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn advance(&mut self) {
|
pub(crate) fn advance(&mut self) {
|
||||||
@ -96,7 +98,6 @@ impl Position {
|
|||||||
self.pos += 1;
|
self.pos += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Go backwards by one character position.
|
/// Go backwards by one character position.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
@ -108,7 +109,6 @@ impl Position {
|
|||||||
assert!(self.pos > 0, "cannot rewind at position 0");
|
assert!(self.pos > 0, "cannot rewind at position 0");
|
||||||
self.pos -= 1;
|
self.pos -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advance to the next line.
|
/// Advance to the next line.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn new_line(&mut self) {
|
pub(crate) fn new_line(&mut self) {
|
||||||
@ -120,24 +120,22 @@ impl Position {
|
|||||||
self.pos = 0;
|
self.pos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Is this `Position` at the beginning of a line?
|
||||||
/// Create a `Position` representing no position.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn none() -> Self {
|
pub fn is_beginning_of_line(self) -> bool {
|
||||||
NO_POS
|
self.line == 0 && !self.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is there no `Position`?
|
/// Is there no `Position`?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_none(&self) -> bool {
|
pub fn is_none(self) -> bool {
|
||||||
self.line == 0 && self.pos == 0
|
self == Self::NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Position {
|
impl Default for Position {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(1, 0)
|
Self::START
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +328,7 @@ pub enum Token {
|
|||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
As,
|
As,
|
||||||
/// A lexer error.
|
/// A lexer error.
|
||||||
LexError(Box<LexError>),
|
LexError(LexError),
|
||||||
/// A comment block.
|
/// A comment block.
|
||||||
Comment(String),
|
Comment(String),
|
||||||
/// A reserved symbol.
|
/// A reserved symbol.
|
||||||
@ -1120,9 +1118,7 @@ fn get_next_token_inner(
|
|||||||
INT::from_str_radix(&out, radix)
|
INT::from_str_radix(&out, radix)
|
||||||
.map(Token::IntegerConstant)
|
.map(Token::IntegerConstant)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
Token::LexError(Box::new(LERR::MalformedNumber(
|
Token::LexError(LERR::MalformedNumber(result.into_iter().collect()))
|
||||||
result.into_iter().collect(),
|
|
||||||
)))
|
|
||||||
}),
|
}),
|
||||||
start_pos,
|
start_pos,
|
||||||
));
|
));
|
||||||
@ -1136,9 +1132,7 @@ fn get_next_token_inner(
|
|||||||
|
|
||||||
return Some((
|
return Some((
|
||||||
num.unwrap_or_else(|_| {
|
num.unwrap_or_else(|_| {
|
||||||
Token::LexError(Box::new(LERR::MalformedNumber(
|
Token::LexError(LERR::MalformedNumber(result.into_iter().collect()))
|
||||||
result.into_iter().collect(),
|
|
||||||
)))
|
|
||||||
}),
|
}),
|
||||||
start_pos,
|
start_pos,
|
||||||
));
|
));
|
||||||
@ -1153,7 +1147,7 @@ fn get_next_token_inner(
|
|||||||
// " - string literal
|
// " - string literal
|
||||||
('"', _) => {
|
('"', _) => {
|
||||||
return parse_string_literal(stream, state, pos, '"').map_or_else(
|
return parse_string_literal(stream, state, pos, '"').map_or_else(
|
||||||
|err| Some((Token::LexError(Box::new(err.0)), err.1)),
|
|err| Some((Token::LexError(err.0), err.1)),
|
||||||
|out| Some((Token::StringConstant(out), start_pos)),
|
|out| Some((Token::StringConstant(out), start_pos)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1161,22 +1155,19 @@ fn get_next_token_inner(
|
|||||||
// ' - character literal
|
// ' - character literal
|
||||||
('\'', '\'') => {
|
('\'', '\'') => {
|
||||||
return Some((
|
return Some((
|
||||||
Token::LexError(Box::new(LERR::MalformedChar("".to_string()))),
|
Token::LexError(LERR::MalformedChar("".to_string())),
|
||||||
start_pos,
|
start_pos,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
('\'', _) => {
|
('\'', _) => {
|
||||||
return Some(parse_string_literal(stream, state, pos, '\'').map_or_else(
|
return Some(parse_string_literal(stream, state, pos, '\'').map_or_else(
|
||||||
|err| (Token::LexError(Box::new(err.0)), err.1),
|
|err| (Token::LexError(err.0), err.1),
|
||||||
|result| {
|
|result| {
|
||||||
let mut chars = result.chars();
|
let mut chars = result.chars();
|
||||||
let first = chars.next().unwrap();
|
let first = chars.next().unwrap();
|
||||||
|
|
||||||
if chars.next().is_some() {
|
if chars.next().is_some() {
|
||||||
(
|
(Token::LexError(LERR::MalformedChar(result)), start_pos)
|
||||||
Token::LexError(Box::new(LERR::MalformedChar(result))),
|
|
||||||
start_pos,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(Token::CharConstant(first), start_pos)
|
(Token::CharConstant(first), start_pos)
|
||||||
}
|
}
|
||||||
@ -1452,7 +1443,7 @@ fn get_next_token_inner(
|
|||||||
}
|
}
|
||||||
(ch, _) => {
|
(ch, _) => {
|
||||||
return Some((
|
return Some((
|
||||||
Token::LexError(Box::new(LERR::UnexpectedInput(ch.to_string()))),
|
Token::LexError(LERR::UnexpectedInput(ch.to_string())),
|
||||||
start_pos,
|
start_pos,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -1494,7 +1485,7 @@ fn get_identifier(
|
|||||||
|
|
||||||
if !is_valid_identifier {
|
if !is_valid_identifier {
|
||||||
return Some((
|
return Some((
|
||||||
Token::LexError(Box::new(LERR::MalformedIdentifier(identifier))),
|
Token::LexError(LERR::MalformedIdentifier(identifier)),
|
||||||
start_pos,
|
start_pos,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -1652,42 +1643,42 @@ impl<'a> Iterator for TokenIterator<'a, '_> {
|
|||||||
Some((Token::Reserved(s), pos)) => Some((match
|
Some((Token::Reserved(s), pos)) => Some((match
|
||||||
(s.as_str(), self.engine.custom_keywords.contains_key(&s))
|
(s.as_str(), self.engine.custom_keywords.contains_key(&s))
|
||||||
{
|
{
|
||||||
("===", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
("===", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"'===' is not a valid operator. This is not JavaScript! Should it be '=='?".to_string(),
|
"'===' is not a valid operator. This is not JavaScript! Should it be '=='?".to_string(),
|
||||||
))),
|
)),
|
||||||
("!==", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
("!==", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"'!==' is not a valid operator. This is not JavaScript! Should it be '!='?".to_string(),
|
"'!==' is not a valid operator. This is not JavaScript! Should it be '!='?".to_string(),
|
||||||
))),
|
)),
|
||||||
("->", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
("->", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"'->' is not a valid symbol. This is not C or C++!".to_string()))),
|
"'->' is not a valid symbol. This is not C or C++!".to_string())),
|
||||||
("<-", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
("<-", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"'<-' is not a valid symbol. This is not Go! Should it be '<='?".to_string(),
|
"'<-' is not a valid symbol. This is not Go! Should it be '<='?".to_string(),
|
||||||
))),
|
)),
|
||||||
("=>", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
("=>", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"'=>' is not a valid symbol. This is not Rust! Should it be '>='?".to_string(),
|
"'=>' is not a valid symbol. This is not Rust! Should it be '>='?".to_string(),
|
||||||
))),
|
)),
|
||||||
(":=", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
(":=", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"':=' is not a valid assignment operator. This is not Go! Should it be simply '='?".to_string(),
|
"':=' is not a valid assignment operator. This is not Go! Should it be simply '='?".to_string(),
|
||||||
))),
|
)),
|
||||||
("::<", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
("::<", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"'::<>' is not a valid symbol. This is not Rust! Should it be '::'?".to_string(),
|
"'::<>' is not a valid symbol. This is not Rust! Should it be '::'?".to_string(),
|
||||||
))),
|
)),
|
||||||
("(*", false) | ("*)", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
("(*", false) | ("*)", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"'(* .. *)' is not a valid comment format. This is not Pascal! Should it be '/* .. */'?".to_string(),
|
"'(* .. *)' is not a valid comment format. This is not Pascal! Should it be '/* .. */'?".to_string(),
|
||||||
))),
|
)),
|
||||||
("#", false) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
("#", false) => Token::LexError(LERR::ImproperSymbol(
|
||||||
"'#' is not a valid symbol. Should it be '#{'?".to_string(),
|
"'#' is not a valid symbol. Should it be '#{'?".to_string(),
|
||||||
))),
|
)),
|
||||||
// Reserved keyword/operator that is custom.
|
// Reserved keyword/operator that is custom.
|
||||||
(_, true) => Token::Custom(s),
|
(_, true) => Token::Custom(s),
|
||||||
// Reserved operator that is not custom.
|
// Reserved operator that is not custom.
|
||||||
(token, false) if !is_valid_identifier(token.chars()) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
(token, false) if !is_valid_identifier(token.chars()) => Token::LexError(LERR::ImproperSymbol(
|
||||||
format!("'{}' is a reserved symbol", token)
|
format!("'{}' is a reserved symbol", token)
|
||||||
))),
|
)),
|
||||||
// Reserved keyword that is not custom and disabled.
|
// Reserved keyword that is not custom and disabled.
|
||||||
(token, false) if self.engine.disabled_symbols.contains(token) => Token::LexError(Box::new(LERR::ImproperSymbol(
|
(token, false) if self.engine.disabled_symbols.contains(token) => Token::LexError(LERR::ImproperSymbol(
|
||||||
format!("reserved symbol '{}' is disabled", token)
|
format!("reserved symbol '{}' is disabled", token)
|
||||||
))),
|
)),
|
||||||
// Reserved keyword/operator that is not custom.
|
// Reserved keyword/operator that is not custom.
|
||||||
(_, false) => Token::Reserved(s),
|
(_, false) => Token::Reserved(s),
|
||||||
}, pos)),
|
}, pos)),
|
||||||
@ -1708,7 +1699,7 @@ impl<'a> Iterator for TokenIterator<'a, '_> {
|
|||||||
// Disabled operator
|
// Disabled operator
|
||||||
Some((token, pos)) if token.is_operator() && self.engine.disabled_symbols.contains(token.syntax().as_ref()) => {
|
Some((token, pos)) if token.is_operator() && self.engine.disabled_symbols.contains(token.syntax().as_ref()) => {
|
||||||
Some((
|
Some((
|
||||||
Token::LexError(Box::new(LexError::UnexpectedInput(token.syntax().into()))),
|
Token::LexError(LexError::UnexpectedInput(token.syntax().into())),
|
||||||
pos,
|
pos,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user