IdentX -> Ident.
This commit is contained in:
parent
7cd24ec197
commit
2e7ec8f1db
56
src/ast.rs
56
src/ast.rs
@ -640,25 +640,6 @@ impl AsRef<Module> for AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// _(INTERNALS)_ An identifier containing a [string][String] name and a [position][Position].
|
|
||||||
/// Exported under the `internals` feature only.
|
|
||||||
///
|
|
||||||
/// ## WARNING
|
|
||||||
///
|
|
||||||
/// This type is volatile and may change.
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub struct Ident {
|
|
||||||
pub name: String,
|
|
||||||
pub pos: Position,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ident {
|
|
||||||
/// Create a new `Identifier`.
|
|
||||||
pub fn new(name: String, pos: Position) -> Self {
|
|
||||||
Self { name, pos }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// _(INTERNALS)_ An identifier containing an [immutable string][ImmutableString] name and a [position][Position].
|
/// _(INTERNALS)_ An identifier containing an [immutable string][ImmutableString] name and a [position][Position].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
@ -666,30 +647,11 @@ impl Ident {
|
|||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct IdentX {
|
pub struct Ident {
|
||||||
pub name: ImmutableString,
|
pub name: ImmutableString,
|
||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Ident> for IdentX {
|
|
||||||
fn from(value: Ident) -> Self {
|
|
||||||
Self {
|
|
||||||
name: value.name.into(),
|
|
||||||
pos: value.pos,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IdentX {
|
|
||||||
/// Create a new `Identifier`.
|
|
||||||
pub fn new(name: impl Into<ImmutableString>, pos: Position) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.into(),
|
|
||||||
pos,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// _(INTERNALS)_ A type encapsulating the mode of a `return`/`throw` statement.
|
/// _(INTERNALS)_ A type encapsulating the mode of a `return`/`throw` statement.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
@ -729,9 +691,9 @@ pub enum Stmt {
|
|||||||
/// `for` id `in` expr `{` stmt `}`
|
/// `for` id `in` expr `{` stmt `}`
|
||||||
For(Expr, Box<(String, Stmt)>, Position),
|
For(Expr, Box<(String, Stmt)>, Position),
|
||||||
/// \[`export`\] `let` id `=` expr
|
/// \[`export`\] `let` id `=` expr
|
||||||
Let(Box<IdentX>, Option<Expr>, bool, Position),
|
Let(Box<Ident>, Option<Expr>, bool, Position),
|
||||||
/// \[`export`\] `const` id `=` expr
|
/// \[`export`\] `const` id `=` expr
|
||||||
Const(Box<IdentX>, Option<Expr>, bool, Position),
|
Const(Box<Ident>, Option<Expr>, bool, Position),
|
||||||
/// expr op`=` expr
|
/// expr op`=` expr
|
||||||
Assignment(Box<(Expr, Cow<'static, str>, Expr)>, Position),
|
Assignment(Box<(Expr, Cow<'static, str>, Expr)>, Position),
|
||||||
/// `{` stmt`;` ... `}`
|
/// `{` stmt`;` ... `}`
|
||||||
@ -748,13 +710,13 @@ pub enum Stmt {
|
|||||||
Return((ReturnType, Position), Option<Expr>, Position),
|
Return((ReturnType, Position), Option<Expr>, Position),
|
||||||
/// `import` expr `as` var
|
/// `import` expr `as` var
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
Import(Expr, Option<Box<IdentX>>, Position),
|
Import(Expr, Option<Box<Ident>>, Position),
|
||||||
/// `export` var `as` var `,` ...
|
/// `export` var `as` var `,` ...
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
Export(Vec<(IdentX, Option<IdentX>)>, Position),
|
Export(Vec<(Ident, Option<Ident>)>, Position),
|
||||||
/// Convert a variable to shared.
|
/// Convert a variable to shared.
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Share(IdentX),
|
Share(Ident),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Stmt {
|
impl Default for Stmt {
|
||||||
@ -996,13 +958,13 @@ pub enum Expr {
|
|||||||
/// [ expr, ... ]
|
/// [ expr, ... ]
|
||||||
Array(Box<StaticVec<Expr>>, Position),
|
Array(Box<StaticVec<Expr>>, Position),
|
||||||
/// #{ name:expr, ... }
|
/// #{ name:expr, ... }
|
||||||
Map(Box<StaticVec<(IdentX, 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 modules, hash, variable name)
|
||||||
Variable(Box<(Option<NonZeroUsize>, Option<Box<NamespaceRef>>, u64, IdentX)>),
|
Variable(Box<(Option<NonZeroUsize>, Option<Box<NamespaceRef>>, u64, Ident)>),
|
||||||
/// Property access - (getter, setter), prop
|
/// Property access - (getter, setter), prop
|
||||||
Property(Box<((ImmutableString, ImmutableString), IdentX)>),
|
Property(Box<((ImmutableString, ImmutableString), Ident)>),
|
||||||
/// { [statement][Stmt] }
|
/// { [statement][Stmt] }
|
||||||
Stmt(Box<StaticVec<Stmt>>, Position),
|
Stmt(Box<StaticVec<Stmt>>, Position),
|
||||||
/// Wrapped [expression][`Expr`] - should not be optimized away.
|
/// Wrapped [expression][`Expr`] - should not be optimized away.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Main module defining the script evaluation [`Engine`].
|
//! Main module defining the script evaluation [`Engine`].
|
||||||
|
|
||||||
use crate::ast::{Expr, FnCallExpr, Ident, IdentX, ReturnType, Stmt};
|
use crate::ast::{Expr, FnCallExpr, Ident, ReturnType, Stmt};
|
||||||
use crate::dynamic::{map_std_type_name, AccessMode, Union, Variant};
|
use crate::dynamic::{map_std_type_name, AccessMode, Union, Variant};
|
||||||
use crate::fn_call::run_builtin_op_assignment;
|
use crate::fn_call::run_builtin_op_assignment;
|
||||||
use crate::fn_native::{
|
use crate::fn_native::{
|
||||||
@ -734,7 +734,7 @@ pub fn search_imports(
|
|||||||
state: &mut State,
|
state: &mut State,
|
||||||
namespace: &NamespaceRef,
|
namespace: &NamespaceRef,
|
||||||
) -> Result<Shared<Module>, Box<EvalAltResult>> {
|
) -> Result<Shared<Module>, Box<EvalAltResult>> {
|
||||||
let IdentX { name: root, pos } = &namespace[0];
|
let Ident { name: root, pos } = &namespace[0];
|
||||||
|
|
||||||
// Qualified - check if the root module is directly indexed
|
// Qualified - check if the root module is directly indexed
|
||||||
let index = if state.always_search {
|
let index = if state.always_search {
|
||||||
@ -884,7 +884,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
|
||||||
(_, Some(modules), hash_var, IdentX { name, pos }) => {
|
(_, Some(modules), hash_var, Ident { name, pos }) => {
|
||||||
let module = search_imports(mods, state, modules)?;
|
let module = search_imports(mods, state, modules)?;
|
||||||
let target = module.get_qualified_var(*hash_var).map_err(|mut err| {
|
let target = module.get_qualified_var(*hash_var).map_err(|mut err| {
|
||||||
match *err {
|
match *err {
|
||||||
@ -918,7 +918,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, _, _, IdentX { 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!(),
|
||||||
};
|
};
|
||||||
@ -1115,7 +1115,7 @@ impl Engine {
|
|||||||
Expr::FnCall(_, _) => unreachable!(),
|
Expr::FnCall(_, _) => unreachable!(),
|
||||||
// {xxx:map}.id = ???
|
// {xxx:map}.id = ???
|
||||||
Expr::Property(x) if target_val.is::<Map>() && new_val.is_some() => {
|
Expr::Property(x) if target_val.is::<Map>() && new_val.is_some() => {
|
||||||
let IdentX { name, pos } = &x.1;
|
let Ident { name, pos } = &x.1;
|
||||||
let index = name.clone().into();
|
let index = name.clone().into();
|
||||||
let mut val = self.get_indexed_mut(
|
let mut val = self.get_indexed_mut(
|
||||||
mods, state, lib, target_val, index, *pos, true, is_ref, false, level,
|
mods, state, lib, target_val, index, *pos, true, is_ref, false, level,
|
||||||
@ -1128,7 +1128,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// {xxx:map}.id
|
// {xxx:map}.id
|
||||||
Expr::Property(x) if target_val.is::<Map>() => {
|
Expr::Property(x) if target_val.is::<Map>() => {
|
||||||
let IdentX { name, pos } = &x.1;
|
let Ident { 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(
|
||||||
mods, state, lib, target_val, index, *pos, false, is_ref, false, level,
|
mods, state, lib, target_val, index, *pos, false, is_ref, false, level,
|
||||||
@ -1138,7 +1138,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// xxx.id = ???
|
// xxx.id = ???
|
||||||
Expr::Property(x) if new_val.is_some() => {
|
Expr::Property(x) if new_val.is_some() => {
|
||||||
let ((_, setter), IdentX { pos, .. }) = x.as_ref();
|
let ((_, setter), Ident { pos, .. }) = x.as_ref();
|
||||||
let mut new_val = new_val;
|
let mut new_val = new_val;
|
||||||
let mut args = [target_val, &mut new_val.as_mut().unwrap().0];
|
let mut args = [target_val, &mut new_val.as_mut().unwrap().0];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
@ -1150,7 +1150,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(x) => {
|
Expr::Property(x) => {
|
||||||
let ((getter, _), IdentX { pos, .. }) = x.as_ref();
|
let ((getter, _), Ident { pos, .. }) = x.as_ref();
|
||||||
let mut args = [target_val];
|
let mut args = [target_val];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
mods, state, lib, getter, 0, &mut args, is_ref, true, false, *pos,
|
mods, state, lib, getter, 0, &mut args, is_ref, true, false, *pos,
|
||||||
@ -1163,7 +1163,7 @@ impl Engine {
|
|||||||
Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) if target_val.is::<Map>() => {
|
Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) if target_val.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.1;
|
let Ident { name, pos } = &p.1;
|
||||||
let index = name.clone().into();
|
let index = name.clone().into();
|
||||||
self.get_indexed_mut(
|
self.get_indexed_mut(
|
||||||
mods, state, lib, target_val, index, *pos, false, is_ref, true,
|
mods, state, lib, target_val, index, *pos, false, is_ref, true,
|
||||||
@ -1204,7 +1204,7 @@ 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 ((getter, setter), IdentX { pos, .. }) = p.as_ref();
|
let ((getter, setter), Ident { pos, .. }) = p.as_ref();
|
||||||
let arg_values = &mut [target_val, &mut Default::default()];
|
let arg_values = &mut [target_val, &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
|
||||||
@ -1319,7 +1319,7 @@ impl Engine {
|
|||||||
match lhs {
|
match lhs {
|
||||||
// id.??? or id[???]
|
// id.??? or id[???]
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let IdentX {
|
let Ident {
|
||||||
name: var_name,
|
name: var_name,
|
||||||
pos: var_pos,
|
pos: var_pos,
|
||||||
} = &x.3;
|
} = &x.3;
|
||||||
@ -1675,7 +1675,7 @@ impl Engine {
|
|||||||
|
|
||||||
if target.is::<Map>() {
|
if target.is::<Map>() {
|
||||||
// map.prop - point directly to the item
|
// map.prop - point directly to the item
|
||||||
let (_, IdentX { name, pos }) = p.as_ref();
|
let (_, Ident { name, pos }) = p.as_ref();
|
||||||
let idx = name.clone().into();
|
let idx = name.clone().into();
|
||||||
|
|
||||||
if target.is_shared() || target.is_value() {
|
if target.is_shared() || target.is_value() {
|
||||||
@ -1693,7 +1693,7 @@ impl Engine {
|
|||||||
.map(|v| (v, *pos))
|
.map(|v| (v, *pos))
|
||||||
} else {
|
} else {
|
||||||
// var.prop - call property getter
|
// var.prop - call property getter
|
||||||
let ((getter, _), IdentX { pos, .. }) = p.as_ref();
|
let ((getter, _), Ident { pos, .. }) = p.as_ref();
|
||||||
let mut args = [target.as_mut()];
|
let mut args = [target.as_mut()];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
mods, state, lib, getter, 0, &mut args, is_ref, true, false, *pos,
|
mods, state, lib, getter, 0, &mut args, is_ref, true, false, *pos,
|
||||||
@ -1781,7 +1781,7 @@ impl Engine {
|
|||||||
Expr::Map(x, _) => {
|
Expr::Map(x, _) => {
|
||||||
let mut map =
|
let mut map =
|
||||||
Map::with_capacity(crate::stdlib::cmp::max(TYPICAL_MAP_SIZE, x.len()));
|
Map::with_capacity(crate::stdlib::cmp::max(TYPICAL_MAP_SIZE, x.len()));
|
||||||
for (IdentX { name: key, .. }, expr) in x.as_ref() {
|
for (Ident { name: key, .. }, expr) in x.as_ref() {
|
||||||
map.insert(
|
map.insert(
|
||||||
key.clone(),
|
key.clone(),
|
||||||
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?,
|
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?,
|
||||||
@ -2272,9 +2272,9 @@ impl Engine {
|
|||||||
|
|
||||||
if let Some(Ident { name, .. }) = var_def {
|
if let Some(Ident { name, .. }) = var_def {
|
||||||
let var_name: Cow<'_, str> = if state.is_global() {
|
let var_name: Cow<'_, str> = if state.is_global() {
|
||||||
name.clone().into()
|
name.to_string().into()
|
||||||
} else {
|
} else {
|
||||||
unsafe_cast_var_name_to_lifetime(name).into()
|
unsafe_cast_var_name_to_lifetime(&name).into()
|
||||||
};
|
};
|
||||||
scope.push(var_name, value);
|
scope.push(var_name, value);
|
||||||
}
|
}
|
||||||
@ -2410,7 +2410,7 @@ impl Engine {
|
|||||||
// Export statement
|
// Export statement
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
Stmt::Export(list, _) => {
|
Stmt::Export(list, _) => {
|
||||||
for (IdentX { name, pos: id_pos }, rename) in list.iter() {
|
for (Ident { name, pos: id_pos }, rename) in list.iter() {
|
||||||
// Mark scope variables as public
|
// Mark scope variables as public
|
||||||
if let Some(index) = scope.get_index(name).map(|(i, _)| i) {
|
if let Some(index) = scope.get_index(name).map(|(i, _)| i) {
|
||||||
let alias = rename.as_ref().map(|x| &x.name).unwrap_or_else(|| name);
|
let alias = rename.as_ref().map(|x| &x.name).unwrap_or_else(|| name);
|
||||||
|
@ -180,7 +180,7 @@ pub use token::{get_next_token, parse_string_literal, InputStream, Token, Tokeni
|
|||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
#[deprecated(note = "this type is volatile and may change")]
|
#[deprecated(note = "this type is volatile and may change")]
|
||||||
pub use ast::{
|
pub use ast::{
|
||||||
BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt,
|
BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, Ident, ReturnType, ScriptFnDef, Stmt,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Module defining external-loaded modules for Rhai.
|
//! Module defining external-loaded modules for Rhai.
|
||||||
|
|
||||||
use crate::ast::{FnAccess, IdentX};
|
use crate::ast::{FnAccess, Ident};
|
||||||
use crate::dynamic::Variant;
|
use crate::dynamic::Variant;
|
||||||
use crate::fn_native::{shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, SendSync};
|
use crate::fn_native::{shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, SendSync};
|
||||||
use crate::fn_register::by_value as cast_arg;
|
use crate::fn_register::by_value as cast_arg;
|
||||||
@ -1906,7 +1906,7 @@ 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<IdentX>, Option<NonZeroUsize>);
|
pub struct NamespaceRef(StaticVec<Ident>, Option<NonZeroUsize>);
|
||||||
|
|
||||||
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 {
|
||||||
@ -1921,7 +1921,7 @@ impl fmt::Debug for NamespaceRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for NamespaceRef {
|
impl Deref for NamespaceRef {
|
||||||
type Target = StaticVec<IdentX>;
|
type Target = StaticVec<Ident>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
@ -1936,15 +1936,15 @@ impl DerefMut for NamespaceRef {
|
|||||||
|
|
||||||
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 IdentX { name, .. } in self.0.iter() {
|
for Ident { name, .. } in self.0.iter() {
|
||||||
write!(f, "{}{}", name, Token::DoubleColon.syntax())?;
|
write!(f, "{}{}", name, Token::DoubleColon.syntax())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StaticVec<IdentX>> for NamespaceRef {
|
impl From<StaticVec<Ident>> for NamespaceRef {
|
||||||
fn from(modules: StaticVec<IdentX>) -> Self {
|
fn from(modules: StaticVec<Ident>) -> Self {
|
||||||
Self(modules, None)
|
Self(modules, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
155
src/parser.rs
155
src/parser.rs
@ -1,8 +1,6 @@
|
|||||||
//! Main module defining the lexer and parser.
|
//! Main module defining the lexer and parser.
|
||||||
|
|
||||||
use crate::ast::{
|
use crate::ast::{BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, ReturnType, ScriptFnDef, Stmt};
|
||||||
BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt,
|
|
||||||
};
|
|
||||||
use crate::dynamic::{AccessMode, Union};
|
use crate::dynamic::{AccessMode, Union};
|
||||||
use crate::engine::KEYWORD_THIS;
|
use crate::engine::KEYWORD_THIS;
|
||||||
use crate::module::NamespaceRef;
|
use crate::module::NamespaceRef;
|
||||||
@ -703,7 +701,7 @@ fn parse_map_literal(
|
|||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||||
|
|
||||||
let mut map: StaticVec<(IdentX, Expr)> = Default::default();
|
let mut map: StaticVec<(Ident, Expr)> = Default::default();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
const MISSING_RBRACE: &str = "to end this object map literal";
|
const MISSING_RBRACE: &str = "to end this object map literal";
|
||||||
@ -773,7 +771,8 @@ fn parse_map_literal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
||||||
map.push((IdentX::new(name, pos), expr));
|
let name = state.get_interned_string(name);
|
||||||
|
map.push((Ident { name, pos }, expr));
|
||||||
|
|
||||||
match input.peek().unwrap() {
|
match input.peek().unwrap() {
|
||||||
(Token::Comma, _) => {
|
(Token::Comma, _) => {
|
||||||
@ -970,7 +969,10 @@ fn parse_primary(
|
|||||||
{
|
{
|
||||||
state.allow_capture = true;
|
state.allow_capture = true;
|
||||||
}
|
}
|
||||||
let var_name_def = IdentX::new(state.get_interned_string(s), settings.pos);
|
let var_name_def = Ident {
|
||||||
|
name: state.get_interned_string(s),
|
||||||
|
pos: settings.pos,
|
||||||
|
};
|
||||||
Expr::Variable(Box::new((None, None, 0, var_name_def)))
|
Expr::Variable(Box::new((None, None, 0, var_name_def)))
|
||||||
}
|
}
|
||||||
// Namespace qualification
|
// Namespace qualification
|
||||||
@ -981,20 +983,29 @@ fn parse_primary(
|
|||||||
{
|
{
|
||||||
state.allow_capture = true;
|
state.allow_capture = true;
|
||||||
}
|
}
|
||||||
let var_name_def = IdentX::new(state.get_interned_string(s), settings.pos);
|
let var_name_def = Ident {
|
||||||
|
name: state.get_interned_string(s),
|
||||||
|
pos: settings.pos,
|
||||||
|
};
|
||||||
Expr::Variable(Box::new((None, None, 0, var_name_def)))
|
Expr::Variable(Box::new((None, None, 0, var_name_def)))
|
||||||
}
|
}
|
||||||
// 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);
|
||||||
let var_name_def = IdentX::new(state.get_interned_string(s), settings.pos);
|
let var_name_def = Ident {
|
||||||
|
name: state.get_interned_string(s),
|
||||||
|
pos: settings.pos,
|
||||||
|
};
|
||||||
Expr::Variable(Box::new((index, None, 0, var_name_def)))
|
Expr::Variable(Box::new((index, None, 0, var_name_def)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
let var_name_def = IdentX::new(state.get_interned_string(s), settings.pos);
|
let var_name_def = Ident {
|
||||||
|
name: state.get_interned_string(s),
|
||||||
|
pos: settings.pos,
|
||||||
|
};
|
||||||
Expr::Variable(Box::new((None, None, 0, var_name_def)))
|
Expr::Variable(Box::new((None, None, 0, var_name_def)))
|
||||||
} else {
|
} else {
|
||||||
return Err(PERR::Reserved(s).into_err(settings.pos));
|
return Err(PERR::Reserved(s).into_err(settings.pos));
|
||||||
@ -1007,7 +1018,10 @@ fn parse_primary(
|
|||||||
let msg = format!("'{}' can only be used in functions", s);
|
let msg = format!("'{}' can only be used in functions", s);
|
||||||
return Err(LexError::ImproperSymbol(s, msg).into_err(settings.pos));
|
return Err(LexError::ImproperSymbol(s, msg).into_err(settings.pos));
|
||||||
} else {
|
} else {
|
||||||
let var_name_def = IdentX::new(state.get_interned_string(s), settings.pos);
|
let var_name_def = Ident {
|
||||||
|
name: state.get_interned_string(s),
|
||||||
|
pos: settings.pos,
|
||||||
|
};
|
||||||
Expr::Variable(Box::new((None, None, 0, var_name_def)))
|
Expr::Variable(Box::new((None, None, 0, var_name_def)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1067,13 +1081,13 @@ fn parse_primary(
|
|||||||
.into_err(pos));
|
.into_err(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_, modules, _, IdentX { name, pos }) = *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 (_, modules, _, IdentX { name, pos }) = *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())?
|
||||||
}
|
}
|
||||||
@ -1091,7 +1105,10 @@ fn parse_primary(
|
|||||||
modules = Some(Box::new(m));
|
modules = Some(Box::new(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
let var_name_def = IdentX::new(state.get_interned_string(id2), pos2);
|
let var_name_def = Ident {
|
||||||
|
name: state.get_interned_string(id2),
|
||||||
|
pos: pos2,
|
||||||
|
};
|
||||||
Expr::Variable(Box::new((index, modules, 0, var_name_def)))
|
Expr::Variable(Box::new((index, modules, 0, var_name_def)))
|
||||||
}
|
}
|
||||||
(Token::Reserved(id2), pos2) if is_valid_identifier(id2.chars()) => {
|
(Token::Reserved(id2), pos2) if is_valid_identifier(id2.chars()) => {
|
||||||
@ -1129,7 +1146,7 @@ fn parse_primary(
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
let (_, modules, hash, IdentX { name, .. }) = x.as_mut();
|
let (_, modules, hash, Ident { name, .. }) = x.as_mut();
|
||||||
let namespace = modules.as_mut().unwrap();
|
let namespace = modules.as_mut().unwrap();
|
||||||
|
|
||||||
// Qualifiers + variable name
|
// Qualifiers + variable name
|
||||||
@ -1311,58 +1328,46 @@ fn make_assignment_stmt<'a>(
|
|||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
lhs: Expr,
|
lhs: Expr,
|
||||||
rhs: Expr,
|
rhs: Expr,
|
||||||
pos: Position,
|
op_pos: Position,
|
||||||
) -> Result<Stmt, ParseError> {
|
) -> Result<Stmt, ParseError> {
|
||||||
match &lhs {
|
match &lhs {
|
||||||
// var (non-indexed) = rhs
|
// var (non-indexed) = rhs
|
||||||
Expr::Variable(x) if x.0.is_none() => {
|
Expr::Variable(x) if x.0.is_none() => Ok(Stmt::Assignment(
|
||||||
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
Box::new((lhs, fn_name.into(), rhs)),
|
||||||
}
|
op_pos,
|
||||||
|
)),
|
||||||
// var (indexed) = rhs
|
// var (indexed) = rhs
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let (
|
let (index, _, _, Ident { name, pos }) = x.as_ref();
|
||||||
index,
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
IdentX {
|
|
||||||
name,
|
|
||||||
pos: 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 => {
|
AccessMode::ReadWrite => Ok(Stmt::Assignment(
|
||||||
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
Box::new((lhs, fn_name.into(), rhs)),
|
||||||
}
|
op_pos,
|
||||||
|
)),
|
||||||
// Constant values cannot be assigned to
|
// Constant values cannot be assigned to
|
||||||
AccessMode::ReadOnly => {
|
AccessMode::ReadOnly => {
|
||||||
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*name_pos))
|
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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.0.is_none() => {
|
Expr::Variable(x) if x.0.is_none() => Ok(Stmt::Assignment(
|
||||||
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
Box::new((lhs, fn_name.into(), rhs)),
|
||||||
}
|
op_pos,
|
||||||
|
)),
|
||||||
// var[???] (indexed) = rhs, var.??? (indexed) = rhs
|
// var[???] (indexed) = rhs, var.??? (indexed) = rhs
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let (
|
let (index, _, _, Ident { name, pos }) = x.as_ref();
|
||||||
index,
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
IdentX {
|
|
||||||
name,
|
|
||||||
pos: 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 => {
|
AccessMode::ReadWrite => Ok(Stmt::Assignment(
|
||||||
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
Box::new((lhs, fn_name.into(), rhs)),
|
||||||
}
|
op_pos,
|
||||||
|
)),
|
||||||
// Constant values cannot be assigned to
|
// Constant values cannot be assigned to
|
||||||
AccessMode::ReadOnly => {
|
AccessMode::ReadOnly => {
|
||||||
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*name_pos))
|
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1378,7 +1383,7 @@ fn make_assignment_stmt<'a>(
|
|||||||
"=".to_string(),
|
"=".to_string(),
|
||||||
"Possibly a typo of '=='?".to_string(),
|
"Possibly a typo of '=='?".to_string(),
|
||||||
)
|
)
|
||||||
.into_err(pos)),
|
.into_err(op_pos)),
|
||||||
// expr = rhs
|
// expr = rhs
|
||||||
_ => Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(lhs.position())),
|
_ => Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(lhs.position())),
|
||||||
}
|
}
|
||||||
@ -1883,11 +1888,11 @@ fn parse_custom_syntax(
|
|||||||
match required_token.as_str() {
|
match required_token.as_str() {
|
||||||
MARKER_IDENT => match input.next().unwrap() {
|
MARKER_IDENT => match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => {
|
(Token::Identifier(s), pos) => {
|
||||||
let ident = state.get_interned_string(s);
|
let name = state.get_interned_string(s);
|
||||||
let var_name_def = IdentX::new(ident.clone(), pos);
|
segments.push(name.clone());
|
||||||
keywords.push(Expr::Variable(Box::new((None, None, 0, var_name_def))));
|
|
||||||
segments.push(ident);
|
|
||||||
tokens.push(state.get_interned_string(MARKER_IDENT));
|
tokens.push(state.get_interned_string(MARKER_IDENT));
|
||||||
|
let var_name_def = Ident { name, pos };
|
||||||
|
keywords.push(Expr::Variable(Box::new((None, None, 0, 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));
|
||||||
@ -2208,16 +2213,16 @@ fn parse_let(
|
|||||||
match var_type {
|
match var_type {
|
||||||
// let name = expr
|
// let name = expr
|
||||||
AccessMode::ReadWrite => {
|
AccessMode::ReadWrite => {
|
||||||
let var_name = state.get_interned_string(name.clone());
|
let name = state.get_interned_string(name);
|
||||||
state.stack.push((var_name, AccessMode::ReadWrite));
|
state.stack.push((name.clone(), AccessMode::ReadWrite));
|
||||||
let var_def = IdentX::new(name, pos);
|
let var_def = Ident { name, pos };
|
||||||
Ok(Stmt::Let(Box::new(var_def), init_expr, export, token_pos))
|
Ok(Stmt::Let(Box::new(var_def), init_expr, export, token_pos))
|
||||||
}
|
}
|
||||||
// const name = { expr:constant }
|
// const name = { expr:constant }
|
||||||
AccessMode::ReadOnly => {
|
AccessMode::ReadOnly => {
|
||||||
let var_name = state.get_interned_string(name.clone());
|
let name = state.get_interned_string(name);
|
||||||
state.stack.push((var_name, AccessMode::ReadOnly));
|
state.stack.push((name.clone(), AccessMode::ReadOnly));
|
||||||
let var_def = IdentX::new(name, pos);
|
let var_def = Ident { name, pos };
|
||||||
Ok(Stmt::Const(Box::new(var_def), init_expr, export, token_pos))
|
Ok(Stmt::Const(Box::new(var_def), init_expr, export, token_pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2261,7 +2266,10 @@ fn parse_import(
|
|||||||
|
|
||||||
Ok(Stmt::Import(
|
Ok(Stmt::Import(
|
||||||
expr,
|
expr,
|
||||||
Some(Box::new(IdentX::new(name, settings.pos))),
|
Some(Box::new(Ident {
|
||||||
|
name,
|
||||||
|
pos: settings.pos,
|
||||||
|
})),
|
||||||
token_pos,
|
token_pos,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -2310,7 +2318,10 @@ fn parse_export(
|
|||||||
|
|
||||||
let rename = if match_token(input, Token::As).0 {
|
let rename = if match_token(input, Token::As).0 {
|
||||||
match input.next().unwrap() {
|
match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => Some(IdentX::new(state.get_interned_string(s), pos)),
|
(Token::Identifier(s), pos) => Some(Ident {
|
||||||
|
name: state.get_interned_string(s),
|
||||||
|
pos,
|
||||||
|
}),
|
||||||
(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));
|
||||||
}
|
}
|
||||||
@ -2321,7 +2332,13 @@ fn parse_export(
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.push((IdentX::new(state.get_interned_string(id), id_pos), rename));
|
exports.push((
|
||||||
|
Ident {
|
||||||
|
name: state.get_interned_string(id),
|
||||||
|
pos: id_pos,
|
||||||
|
},
|
||||||
|
rename,
|
||||||
|
));
|
||||||
|
|
||||||
match input.peek().unwrap() {
|
match input.peek().unwrap() {
|
||||||
(Token::Comma, _) => {
|
(Token::Comma, _) => {
|
||||||
@ -2651,7 +2668,10 @@ fn parse_try_catch(
|
|||||||
// try { body } catch (
|
// try { body } catch (
|
||||||
let var_def = if match_token(input, Token::LeftParen).0 {
|
let var_def = if match_token(input, Token::LeftParen).0 {
|
||||||
let id = match input.next().unwrap() {
|
let id = match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => Ident::new(s, pos),
|
(Token::Identifier(s), pos) => Ident {
|
||||||
|
name: state.get_interned_string(s),
|
||||||
|
pos,
|
||||||
|
},
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2780,7 +2800,7 @@ fn parse_fn(
|
|||||||
|
|
||||||
/// Creates a curried expression from a list of external variables
|
/// Creates a curried expression from a list of external variables
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
fn make_curry_from_externals(fn_expr: Expr, externals: StaticVec<IdentX>, pos: Position) -> Expr {
|
fn make_curry_from_externals(fn_expr: Expr, externals: StaticVec<Ident>, pos: Position) -> Expr {
|
||||||
if externals.is_empty() {
|
if externals.is_empty() {
|
||||||
return fn_expr;
|
return fn_expr;
|
||||||
}
|
}
|
||||||
@ -2889,13 +2909,16 @@ fn parse_anon_fn(
|
|||||||
|
|
||||||
// External variables may need to be processed in a consistent order,
|
// External variables may need to be processed in a consistent order,
|
||||||
// so extract them into a list.
|
// so extract them into a list.
|
||||||
let externals: StaticVec<IdentX> = {
|
let externals: StaticVec<Ident> = {
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
{
|
{
|
||||||
state
|
state
|
||||||
.externals
|
.externals
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, &v)| IdentX::new(k.clone(), v))
|
.map(|(name, &pos)| Ident {
|
||||||
|
name: name.clone(),
|
||||||
|
pos,
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
#[cfg(feature = "no_closure")]
|
#[cfg(feature = "no_closure")]
|
||||||
@ -3114,7 +3137,7 @@ pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
|
|||||||
Union::Map(map, _) => {
|
Union::Map(map, _) => {
|
||||||
let items: Vec<_> = map
|
let items: Vec<_> = map
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| (IdentX::new(k, pos), map_dynamic_to_expr(v, pos)))
|
.map(|(name, value)| (Ident { name, pos }, map_dynamic_to_expr(value, pos)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if items.iter().all(|(_, expr)| expr.is_some()) {
|
if items.iter().all(|(_, expr)| expr.is_some()) {
|
||||||
|
@ -55,7 +55,7 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?;
|
let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?;
|
||||||
|
|
||||||
assert!(format!("{:?}", ast).starts_with(r#"AST { source: None, statements: [Block([Const(IdentX { name: "DECISION", pos: 1:9 }, Some(Unit(0:0)), false, 1:3), Expr(IntegerConstant(123, 1:53))], 1:1)]"#));
|
assert!(format!("{:?}", ast).starts_with(r#"AST { source: None, statements: [Block([Const(Ident { name: "DECISION", pos: 1:9 }, Some(Unit(0:0)), false, 1:3), Expr(IntegerConstant(123, 1:53))], 1:1)]"#));
|
||||||
|
|
||||||
let ast = engine.compile("if 1 == 2 { 42 }")?;
|
let ast = engine.compile("if 1 == 2 { 42 }")?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user