Rename AccessType to ReadWrite and ReadOnly.
This commit is contained in:
parent
7598ec136f
commit
dbee0eb0f5
@ -8,6 +8,7 @@ Bug fixes
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
* Constants are no longer propagated by the optimizer if shadowed by a non-constant variable.
|
* Constants are no longer propagated by the optimizer if shadowed by a non-constant variable.
|
||||||
|
* Constants passed as the `this` parameter to Rhai functions now throws an error if assigned to.
|
||||||
|
|
||||||
|
|
||||||
Version 0.19.7
|
Version 0.19.7
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Module defining the AST (abstract syntax tree).
|
//! Module defining the AST (abstract syntax tree).
|
||||||
|
|
||||||
use crate::dynamic::{AccessType, Union};
|
use crate::dynamic::{AccessMode, Union};
|
||||||
use crate::fn_native::shared_make_mut;
|
use crate::fn_native::shared_make_mut;
|
||||||
use crate::module::NamespaceRef;
|
use crate::module::NamespaceRef;
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
@ -942,7 +942,7 @@ impl Expr {
|
|||||||
Self::StringConstant(x, _) => x.clone().into(),
|
Self::StringConstant(x, _) => x.clone().into(),
|
||||||
Self::FnPointer(x, _) => Dynamic(Union::FnPtr(
|
Self::FnPointer(x, _) => Dynamic(Union::FnPtr(
|
||||||
Box::new(FnPtr::new_unchecked(x.clone(), Default::default())),
|
Box::new(FnPtr::new_unchecked(x.clone(), Default::default())),
|
||||||
AccessType::Constant,
|
AccessMode::ReadOnly,
|
||||||
)),
|
)),
|
||||||
Self::BoolConstant(x, _) => (*x).into(),
|
Self::BoolConstant(x, _) => (*x).into(),
|
||||||
Self::Unit(_) => ().into(),
|
Self::Unit(_) => ().into(),
|
||||||
@ -954,7 +954,7 @@ impl Expr {
|
|||||||
x.len(),
|
x.len(),
|
||||||
));
|
));
|
||||||
arr.extend(x.iter().map(|v| v.get_constant_value().unwrap()));
|
arr.extend(x.iter().map(|v| v.get_constant_value().unwrap()));
|
||||||
Dynamic(Union::Array(Box::new(arr), AccessType::Constant))
|
Dynamic(Union::Array(Box::new(arr), AccessMode::ReadOnly))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -967,7 +967,7 @@ impl Expr {
|
|||||||
x.iter()
|
x.iter()
|
||||||
.map(|(k, v)| (k.name.clone(), v.get_constant_value().unwrap())),
|
.map(|(k, v)| (k.name.clone(), v.get_constant_value().unwrap())),
|
||||||
);
|
);
|
||||||
Dynamic(Union::Map(Box::new(map), AccessType::Constant))
|
Dynamic(Union::Map(Box::new(map), AccessMode::ReadOnly))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
124
src/dynamic.rs
124
src/dynamic.rs
@ -116,21 +116,21 @@ impl dyn Variant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type of an entry in the Scope.
|
/// Modes of access.
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
|
||||||
pub enum AccessType {
|
pub enum AccessMode {
|
||||||
/// Normal value.
|
/// Mutable.
|
||||||
Normal,
|
ReadWrite,
|
||||||
/// Immutable constant value.
|
/// Immutable.
|
||||||
Constant,
|
ReadOnly,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccessType {
|
impl AccessMode {
|
||||||
/// Is the access type [`Constant`]?
|
/// Is the access type [`ReadOnly`]?
|
||||||
pub fn is_constant(self) -> bool {
|
pub fn is_read_only(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Normal => false,
|
Self::ReadWrite => false,
|
||||||
Self::Constant => true,
|
Self::ReadOnly => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,25 +142,25 @@ pub struct Dynamic(pub(crate) Union);
|
|||||||
///
|
///
|
||||||
/// Most variants are boxed to reduce the size.
|
/// Most variants are boxed to reduce the size.
|
||||||
pub enum Union {
|
pub enum Union {
|
||||||
Unit((), AccessType),
|
Unit((), AccessMode),
|
||||||
Bool(bool, AccessType),
|
Bool(bool, AccessMode),
|
||||||
Str(ImmutableString, AccessType),
|
Str(ImmutableString, AccessMode),
|
||||||
Char(char, AccessType),
|
Char(char, AccessMode),
|
||||||
Int(INT, AccessType),
|
Int(INT, AccessMode),
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Float(FLOAT, AccessType),
|
Float(FLOAT, AccessMode),
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Array(Box<Array>, AccessType),
|
Array(Box<Array>, AccessMode),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Map(Box<Map>, AccessType),
|
Map(Box<Map>, AccessMode),
|
||||||
FnPtr(Box<FnPtr>, AccessType),
|
FnPtr(Box<FnPtr>, AccessMode),
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
TimeStamp(Box<Instant>, AccessType),
|
TimeStamp(Box<Instant>, AccessMode),
|
||||||
|
|
||||||
Variant(Box<Box<dyn Variant>>, AccessType),
|
Variant(Box<Box<dyn Variant>>, AccessMode),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Shared(crate::Shared<crate::Locked<Dynamic>>, AccessType),
|
Shared(crate::Shared<crate::Locked<Dynamic>>, AccessMode),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Underlying [`Variant`] read guard for [`Dynamic`].
|
/// Underlying [`Variant`] read guard for [`Dynamic`].
|
||||||
@ -506,27 +506,27 @@ impl Clone for Dynamic {
|
|||||||
/// The cloned copy is marked [`AccessType::Normal`] even if the original is constant.
|
/// The cloned copy is marked [`AccessType::Normal`] even if the original is constant.
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Unit(value, _) => Self(Union::Unit(value, AccessType::Normal)),
|
Union::Unit(value, _) => Self(Union::Unit(value, AccessMode::ReadWrite)),
|
||||||
Union::Bool(value, _) => Self(Union::Bool(value, AccessType::Normal)),
|
Union::Bool(value, _) => Self(Union::Bool(value, AccessMode::ReadWrite)),
|
||||||
Union::Str(ref value, _) => Self(Union::Str(value.clone(), AccessType::Normal)),
|
Union::Str(ref value, _) => Self(Union::Str(value.clone(), AccessMode::ReadWrite)),
|
||||||
Union::Char(value, _) => Self(Union::Char(value, AccessType::Normal)),
|
Union::Char(value, _) => Self(Union::Char(value, AccessMode::ReadWrite)),
|
||||||
Union::Int(value, _) => Self(Union::Int(value, AccessType::Normal)),
|
Union::Int(value, _) => Self(Union::Int(value, AccessMode::ReadWrite)),
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Union::Float(value, _) => Self(Union::Float(value, AccessType::Normal)),
|
Union::Float(value, _) => Self(Union::Float(value, AccessMode::ReadWrite)),
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(ref value, _) => Self(Union::Array(value.clone(), AccessType::Normal)),
|
Union::Array(ref value, _) => Self(Union::Array(value.clone(), AccessMode::ReadWrite)),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(ref value, _) => Self(Union::Map(value.clone(), AccessType::Normal)),
|
Union::Map(ref value, _) => Self(Union::Map(value.clone(), AccessMode::ReadWrite)),
|
||||||
Union::FnPtr(ref value, _) => Self(Union::FnPtr(value.clone(), AccessType::Normal)),
|
Union::FnPtr(ref value, _) => Self(Union::FnPtr(value.clone(), AccessMode::ReadWrite)),
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
Union::TimeStamp(ref value, _) => {
|
Union::TimeStamp(ref value, _) => {
|
||||||
Self(Union::TimeStamp(value.clone(), AccessType::Normal))
|
Self(Union::TimeStamp(value.clone(), AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
|
|
||||||
Union::Variant(ref value, _) => (***value).clone_into_dynamic(),
|
Union::Variant(ref value, _) => (***value).clone_into_dynamic(),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(ref cell, _) => Self(Union::Shared(cell.clone(), AccessType::Normal)),
|
Union::Shared(ref cell, _) => Self(Union::Shared(cell.clone(), AccessMode::ReadWrite)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -540,29 +540,29 @@ impl Default for Dynamic {
|
|||||||
|
|
||||||
impl Dynamic {
|
impl Dynamic {
|
||||||
/// A [`Dynamic`] containing a `()`.
|
/// A [`Dynamic`] containing a `()`.
|
||||||
pub const UNIT: Dynamic = Self(Union::Unit((), AccessType::Normal));
|
pub const UNIT: Dynamic = Self(Union::Unit((), AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing a `true`.
|
/// A [`Dynamic`] containing a `true`.
|
||||||
pub const TRUE: Dynamic = Self(Union::Bool(true, AccessType::Normal));
|
pub const TRUE: Dynamic = Self(Union::Bool(true, AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing a [`false`].
|
/// A [`Dynamic`] containing a [`false`].
|
||||||
pub const FALSE: Dynamic = Self(Union::Bool(false, AccessType::Normal));
|
pub const FALSE: Dynamic = Self(Union::Bool(false, AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing the integer zero.
|
/// A [`Dynamic`] containing the integer zero.
|
||||||
pub const ZERO: Dynamic = Self(Union::Int(0, AccessType::Normal));
|
pub const ZERO: Dynamic = Self(Union::Int(0, AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing the integer one.
|
/// A [`Dynamic`] containing the integer one.
|
||||||
pub const ONE: Dynamic = Self(Union::Int(1, AccessType::Normal));
|
pub const ONE: Dynamic = Self(Union::Int(1, AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing the integer negative one.
|
/// A [`Dynamic`] containing the integer negative one.
|
||||||
pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, AccessType::Normal));
|
pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing the floating-point zero.
|
/// A [`Dynamic`] containing the floating-point zero.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
pub const FLOAT_ZERO: Dynamic = Self(Union::Float(0.0, AccessType::Normal));
|
pub const FLOAT_ZERO: Dynamic = Self(Union::Float(0.0, AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing the floating-point one.
|
/// A [`Dynamic`] containing the floating-point one.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
pub const FLOAT_ONE: Dynamic = Self(Union::Float(1.0, AccessType::Normal));
|
pub const FLOAT_ONE: Dynamic = Self(Union::Float(1.0, AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing the floating-point negative one.
|
/// A [`Dynamic`] containing the floating-point negative one.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
pub const FLOAT_NEGATIVE_ONE: Dynamic = Self(Union::Float(-1.0, AccessType::Normal));
|
pub const FLOAT_NEGATIVE_ONE: Dynamic = Self(Union::Float(-1.0, AccessMode::ReadWrite));
|
||||||
|
|
||||||
/// Get the [`AccessType`] for this [`Dynamic`].
|
/// Get the [`AccessMode`] for this [`Dynamic`].
|
||||||
pub(crate) fn access_type(&self) -> AccessType {
|
pub(crate) fn access_mode(&self) -> AccessMode {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Unit(_, access)
|
Union::Unit(_, access)
|
||||||
| Union::Bool(_, access)
|
| Union::Bool(_, access)
|
||||||
@ -584,8 +584,8 @@ impl Dynamic {
|
|||||||
Union::Shared(_, access) => access,
|
Union::Shared(_, access) => access,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Set the [`AccessType`] for this [`Dynamic`].
|
/// Set the [`AccessMode`] for this [`Dynamic`].
|
||||||
pub(crate) fn set_access_type(&mut self, typ: AccessType) {
|
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) {
|
||||||
match &mut self.0 {
|
match &mut self.0 {
|
||||||
Union::Unit(_, access)
|
Union::Unit(_, access)
|
||||||
| Union::Bool(_, access)
|
| Union::Bool(_, access)
|
||||||
@ -615,7 +615,7 @@ impl Dynamic {
|
|||||||
/// if its value is going to be modified. This safe-guards constant values from being modified
|
/// if its value is going to be modified. This safe-guards constant values from being modified
|
||||||
/// from within Rust functions.
|
/// from within Rust functions.
|
||||||
pub fn is_read_only(&self) -> bool {
|
pub fn is_read_only(&self) -> bool {
|
||||||
self.access_type().is_constant()
|
self.access_mode().is_read_only()
|
||||||
}
|
}
|
||||||
/// Create a [`Dynamic`] from any type. A [`Dynamic`] value is simply returned as is.
|
/// Create a [`Dynamic`] from any type. A [`Dynamic`] value is simply returned as is.
|
||||||
///
|
///
|
||||||
@ -733,7 +733,7 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self(Union::Variant(Box::new(boxed), AccessType::Normal))
|
Self(Union::Variant(Box::new(boxed), AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
/// Turn the [`Dynamic`] value into a shared [`Dynamic`] value backed by an [`Rc`][std::rc::Rc]`<`[`RefCell`][std::cell::RefCell]`<`[`Dynamic`]`>>`
|
/// Turn the [`Dynamic`] value into a shared [`Dynamic`] value backed by an [`Rc`][std::rc::Rc]`<`[`RefCell`][std::cell::RefCell]`<`[`Dynamic`]`>>`
|
||||||
/// or [`Arc`][std::sync::Arc]`<`[`RwLock`][std::sync::RwLock]`<`[`Dynamic`]`>>` depending on the `sync` feature.
|
/// or [`Arc`][std::sync::Arc]`<`[`RwLock`][std::sync::RwLock]`<`[`Dynamic`]`>>` depending on the `sync` feature.
|
||||||
@ -750,7 +750,7 @@ impl Dynamic {
|
|||||||
/// Panics under the `no_closure` feature.
|
/// Panics under the `no_closure` feature.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn into_shared(self) -> Self {
|
pub fn into_shared(self) -> Self {
|
||||||
let _access = self.access_type();
|
let _access = self.access_mode();
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
@ -1338,38 +1338,38 @@ impl Dynamic {
|
|||||||
impl From<()> for Dynamic {
|
impl From<()> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: ()) -> Self {
|
fn from(value: ()) -> Self {
|
||||||
Self(Union::Unit(value, AccessType::Normal))
|
Self(Union::Unit(value, AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<bool> for Dynamic {
|
impl From<bool> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: bool) -> Self {
|
fn from(value: bool) -> Self {
|
||||||
Self(Union::Bool(value, AccessType::Normal))
|
Self(Union::Bool(value, AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<INT> for Dynamic {
|
impl From<INT> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: INT) -> Self {
|
fn from(value: INT) -> Self {
|
||||||
Self(Union::Int(value, AccessType::Normal))
|
Self(Union::Int(value, AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl From<FLOAT> for Dynamic {
|
impl From<FLOAT> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: FLOAT) -> Self {
|
fn from(value: FLOAT) -> Self {
|
||||||
Self(Union::Float(value, AccessType::Normal))
|
Self(Union::Float(value, AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<char> for Dynamic {
|
impl From<char> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: char) -> Self {
|
fn from(value: char) -> Self {
|
||||||
Self(Union::Char(value, AccessType::Normal))
|
Self(Union::Char(value, AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<S: Into<ImmutableString>> From<S> for Dynamic {
|
impl<S: Into<ImmutableString>> From<S> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: S) -> Self {
|
fn from(value: S) -> Self {
|
||||||
Self(Union::Str(value.into(), AccessType::Normal))
|
Self(Union::Str(value.into(), AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
@ -1378,7 +1378,7 @@ impl<T: Variant + Clone> From<crate::stdlib::vec::Vec<T>> for Dynamic {
|
|||||||
fn from(value: crate::stdlib::vec::Vec<T>) -> Self {
|
fn from(value: crate::stdlib::vec::Vec<T>) -> Self {
|
||||||
Self(Union::Array(
|
Self(Union::Array(
|
||||||
Box::new(value.into_iter().map(Dynamic::from).collect()),
|
Box::new(value.into_iter().map(Dynamic::from).collect()),
|
||||||
AccessType::Normal,
|
AccessMode::ReadWrite,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1388,7 +1388,7 @@ impl<T: Variant + Clone> From<&[T]> for Dynamic {
|
|||||||
fn from(value: &[T]) -> Self {
|
fn from(value: &[T]) -> Self {
|
||||||
Self(Union::Array(
|
Self(Union::Array(
|
||||||
Box::new(value.iter().cloned().map(Dynamic::from).collect()),
|
Box::new(value.iter().cloned().map(Dynamic::from).collect()),
|
||||||
AccessType::Normal,
|
AccessMode::ReadWrite,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1405,26 +1405,26 @@ impl<K: Into<ImmutableString>, T: Variant + Clone> From<crate::stdlib::collectio
|
|||||||
.map(|(k, v)| (k.into(), Dynamic::from(v)))
|
.map(|(k, v)| (k.into(), Dynamic::from(v)))
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
),
|
||||||
AccessType::Normal,
|
AccessMode::ReadWrite,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<FnPtr> for Dynamic {
|
impl From<FnPtr> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: FnPtr) -> Self {
|
fn from(value: FnPtr) -> Self {
|
||||||
Self(Union::FnPtr(Box::new(value), AccessType::Normal))
|
Self(Union::FnPtr(Box::new(value), AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<Box<FnPtr>> for Dynamic {
|
impl From<Box<FnPtr>> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: Box<FnPtr>) -> Self {
|
fn from(value: Box<FnPtr>) -> Self {
|
||||||
Self(Union::FnPtr(value, AccessType::Normal))
|
Self(Union::FnPtr(value, AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
impl From<Instant> for Dynamic {
|
impl From<Instant> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: Instant) -> Self {
|
fn from(value: Instant) -> Self {
|
||||||
Self(Union::TimeStamp(Box::new(value), AccessType::Normal))
|
Self(Union::TimeStamp(Box::new(value), AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! 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, IdentX, ReturnType, Stmt};
|
||||||
use crate::dynamic::{map_std_type_name, AccessType, 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::{CallableFunction, Callback, IteratorFn, OnVarCallback};
|
use crate::fn_native::{CallableFunction, Callback, IteratorFn, OnVarCallback};
|
||||||
use crate::module::NamespaceRef;
|
use crate::module::NamespaceRef;
|
||||||
@ -850,7 +850,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Module variables are constant
|
// Module variables are constant
|
||||||
let mut target = target.clone();
|
let mut target = target.clone();
|
||||||
target.set_access_type(AccessType::Constant);
|
target.set_access_mode(AccessMode::ReadOnly);
|
||||||
Ok((target.into(), name, *pos))
|
Ok((target.into(), name, *pos))
|
||||||
}
|
}
|
||||||
// Normal variable access
|
// Normal variable access
|
||||||
@ -905,7 +905,7 @@ impl Engine {
|
|||||||
if let Some(mut result) =
|
if let Some(mut result) =
|
||||||
resolve_var(name, index, &context).map_err(|err| err.fill_position(*pos))?
|
resolve_var(name, index, &context).map_err(|err| err.fill_position(*pos))?
|
||||||
{
|
{
|
||||||
result.set_access_type(AccessType::Constant);
|
result.set_access_mode(AccessMode::ReadOnly);
|
||||||
return Ok((result.into(), name, *pos));
|
return Ok((result.into(), name, *pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1732,7 +1732,7 @@ impl Engine {
|
|||||||
for item in x.as_ref() {
|
for item in x.as_ref() {
|
||||||
arr.push(self.eval_expr(scope, mods, state, lib, this_ptr, item, level)?);
|
arr.push(self.eval_expr(scope, mods, state, lib, this_ptr, item, level)?);
|
||||||
}
|
}
|
||||||
Ok(Dynamic(Union::Array(Box::new(arr), AccessType::Normal)))
|
Ok(Dynamic(Union::Array(Box::new(arr), AccessMode::ReadWrite)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -1745,7 +1745,7 @@ impl Engine {
|
|||||||
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?,
|
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(Dynamic(Union::Map(Box::new(map), AccessType::Normal)))
|
Ok(Dynamic(Union::Map(Box::new(map), AccessMode::ReadWrite)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal function call
|
// Normal function call
|
||||||
@ -2289,8 +2289,8 @@ impl Engine {
|
|||||||
// Let/const statement
|
// Let/const statement
|
||||||
Stmt::Let(var_def, expr, export, _) | Stmt::Const(var_def, expr, export, _) => {
|
Stmt::Let(var_def, expr, export, _) | Stmt::Const(var_def, expr, export, _) => {
|
||||||
let entry_type = match stmt {
|
let entry_type = match stmt {
|
||||||
Stmt::Let(_, _, _, _) => AccessType::Normal,
|
Stmt::Let(_, _, _, _) => AccessMode::ReadWrite,
|
||||||
Stmt::Const(_, _, _, _) => AccessType::Constant,
|
Stmt::Const(_, _, _, _) => AccessMode::ReadOnly,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2384,7 +2384,7 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Stmt::Share(x) => {
|
Stmt::Share(x) => {
|
||||||
match scope.get_index(&x.name) {
|
match scope.get_index(&x.name) {
|
||||||
Some((index, AccessType::Normal)) => {
|
Some((index, AccessMode::ReadWrite)) => {
|
||||||
let val = scope.get_mut(index);
|
let val = scope.get_mut(index);
|
||||||
|
|
||||||
if !val.is_shared() {
|
if !val.is_shared() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module implementing the [`AST`] optimizer.
|
//! Module implementing the [`AST`] optimizer.
|
||||||
|
|
||||||
use crate::ast::{Expr, ScriptFnDef, Stmt};
|
use crate::ast::{Expr, ScriptFnDef, Stmt};
|
||||||
use crate::dynamic::AccessType;
|
use crate::dynamic::AccessMode;
|
||||||
use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF};
|
use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF};
|
||||||
use crate::fn_call::run_builtin_binary_op;
|
use crate::fn_call::run_builtin_binary_op;
|
||||||
use crate::parser::map_dynamic_to_expr;
|
use crate::parser::map_dynamic_to_expr;
|
||||||
@ -59,7 +59,7 @@ struct State<'a> {
|
|||||||
/// Has the [`AST`] been changed during this pass?
|
/// Has the [`AST`] been changed during this pass?
|
||||||
changed: bool,
|
changed: bool,
|
||||||
/// Collection of constants to use for eager function evaluations.
|
/// Collection of constants to use for eager function evaluations.
|
||||||
variables: Vec<(String, AccessType, Expr)>,
|
variables: Vec<(String, AccessMode, Expr)>,
|
||||||
/// An [`Engine`] instance for eager function evaluation.
|
/// An [`Engine`] instance for eager function evaluation.
|
||||||
engine: &'a Engine,
|
engine: &'a Engine,
|
||||||
/// [Module] containing script-defined functions.
|
/// [Module] containing script-defined functions.
|
||||||
@ -102,7 +102,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
/// Add a new constant to the list.
|
/// Add a new constant to the list.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_var(&mut self, name: &str, access: AccessType, value: Expr) {
|
pub fn push_var(&mut self, name: &str, access: AccessMode, value: Expr) {
|
||||||
self.variables.push((name.into(), access, value))
|
self.variables.push((name.into(), access, value))
|
||||||
}
|
}
|
||||||
/// Look up a constant from the list.
|
/// Look up a constant from the list.
|
||||||
@ -110,7 +110,7 @@ impl<'a> State<'a> {
|
|||||||
pub fn find_constant(&self, name: &str) -> Option<&Expr> {
|
pub fn find_constant(&self, name: &str) -> Option<&Expr> {
|
||||||
for (n, access, expr) in self.variables.iter().rev() {
|
for (n, access, expr) in self.variables.iter().rev() {
|
||||||
if n == name {
|
if n == name {
|
||||||
return if access.is_constant() {
|
return if access.is_read_only() {
|
||||||
Some(expr)
|
Some(expr)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -163,14 +163,18 @@ fn optimize_stmt_block(
|
|||||||
statements.iter_mut().for_each(|stmt| match stmt {
|
statements.iter_mut().for_each(|stmt| match stmt {
|
||||||
// Add constant literals into the state
|
// Add constant literals into the state
|
||||||
Stmt::Const(var_def, Some(expr), _, _) if expr.is_constant() => {
|
Stmt::Const(var_def, Some(expr), _, _) if expr.is_constant() => {
|
||||||
state.push_var(&var_def.name, AccessType::Constant, mem::take(expr));
|
state.push_var(&var_def.name, AccessMode::ReadOnly, mem::take(expr));
|
||||||
}
|
}
|
||||||
Stmt::Const(var_def, None, _, _) => {
|
Stmt::Const(var_def, None, _, _) => {
|
||||||
state.push_var(&var_def.name, AccessType::Constant, Expr::Unit(var_def.pos));
|
state.push_var(&var_def.name, AccessMode::ReadOnly, Expr::Unit(var_def.pos));
|
||||||
}
|
}
|
||||||
// Add variables into the state
|
// Add variables into the state
|
||||||
Stmt::Let(var_def, _, _, _) => {
|
Stmt::Let(var_def, _, _, _) => {
|
||||||
state.push_var(&var_def.name, AccessType::Normal, Expr::Unit(var_def.pos));
|
state.push_var(
|
||||||
|
&var_def.name,
|
||||||
|
AccessMode::ReadWrite,
|
||||||
|
Expr::Unit(var_def.pos),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Optimize the statement
|
// Optimize the statement
|
||||||
_ => optimize_stmt(stmt, state, preserve_result),
|
_ => optimize_stmt(stmt, state, preserve_result),
|
||||||
@ -749,11 +753,11 @@ fn optimize_top_level(
|
|||||||
// Add constants and variables from the scope
|
// Add constants and variables from the scope
|
||||||
scope.iter().for_each(|(name, constant, value)| {
|
scope.iter().for_each(|(name, constant, value)| {
|
||||||
if !constant {
|
if !constant {
|
||||||
state.push_var(name, AccessType::Normal, Expr::Unit(Position::NONE));
|
state.push_var(name, AccessMode::ReadWrite, Expr::Unit(Position::NONE));
|
||||||
} else if let Some(val) = map_dynamic_to_expr(value, Position::NONE) {
|
} else if let Some(val) = map_dynamic_to_expr(value, Position::NONE) {
|
||||||
state.push_var(name, AccessType::Constant, val);
|
state.push_var(name, AccessMode::ReadOnly, val);
|
||||||
} else {
|
} else {
|
||||||
state.push_var(name, AccessType::Constant, Expr::Unit(Position::NONE));
|
state.push_var(name, AccessMode::ReadOnly, Expr::Unit(Position::NONE));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -774,7 +778,7 @@ fn optimize_top_level(
|
|||||||
optimize_expr(value_expr, &mut state);
|
optimize_expr(value_expr, &mut state);
|
||||||
|
|
||||||
if value_expr.is_constant() {
|
if value_expr.is_constant() {
|
||||||
state.push_var(&var_def.name, AccessType::Constant, value_expr.clone());
|
state.push_var(&var_def.name, AccessMode::ReadOnly, value_expr.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep it in the global scope
|
// Keep it in the global scope
|
||||||
@ -784,10 +788,14 @@ fn optimize_top_level(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::Const(var_def, None, _, _) => {
|
Stmt::Const(var_def, None, _, _) => {
|
||||||
state.push_var(&var_def.name, AccessType::Constant, Expr::Unit(var_def.pos));
|
state.push_var(&var_def.name, AccessMode::ReadOnly, Expr::Unit(var_def.pos));
|
||||||
}
|
}
|
||||||
Stmt::Let(var_def, _, _, _) => {
|
Stmt::Let(var_def, _, _, _) => {
|
||||||
state.push_var(&var_def.name, AccessType::Normal, Expr::Unit(var_def.pos));
|
state.push_var(
|
||||||
|
&var_def.name,
|
||||||
|
AccessMode::ReadWrite,
|
||||||
|
Expr::Unit(var_def.pos),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Keep all variable declarations at this level
|
// Keep all variable declarations at this level
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt,
|
BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt,
|
||||||
};
|
};
|
||||||
use crate::dynamic::{AccessType, Union};
|
use crate::dynamic::{AccessMode, Union};
|
||||||
use crate::engine::{KEYWORD_THIS, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
use crate::engine::{KEYWORD_THIS, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
||||||
use crate::module::NamespaceRef;
|
use crate::module::NamespaceRef;
|
||||||
use crate::optimize::optimize_into_ast;
|
use crate::optimize::optimize_into_ast;
|
||||||
@ -48,7 +48,7 @@ struct ParseState<'e> {
|
|||||||
/// Interned strings.
|
/// Interned strings.
|
||||||
strings: HashMap<String, ImmutableString>,
|
strings: HashMap<String, ImmutableString>,
|
||||||
/// Encapsulates a local stack with variable names to simulate an actual runtime scope.
|
/// Encapsulates a local stack with variable names to simulate an actual runtime scope.
|
||||||
stack: Vec<(ImmutableString, AccessType)>,
|
stack: Vec<(ImmutableString, AccessMode)>,
|
||||||
/// Size of the local variables stack upon entry of the current block scope.
|
/// Size of the local variables stack upon entry of the current block scope.
|
||||||
entry_stack_len: usize,
|
entry_stack_len: usize,
|
||||||
/// Tracks a list of external variables (variables that are not explicitly declared in the scope).
|
/// Tracks a list of external variables (variables that are not explicitly declared in the scope).
|
||||||
@ -1290,11 +1290,11 @@ fn make_assignment_stmt<'a>(
|
|||||||
},
|
},
|
||||||
) = 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 {
|
||||||
AccessType::Normal => {
|
AccessMode::ReadWrite => {
|
||||||
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
||||||
}
|
}
|
||||||
// Constant values cannot be assigned to
|
// Constant values cannot be assigned to
|
||||||
AccessType::Constant => {
|
AccessMode::ReadOnly => {
|
||||||
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*name_pos))
|
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*name_pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1317,11 +1317,11 @@ fn make_assignment_stmt<'a>(
|
|||||||
},
|
},
|
||||||
) = 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 {
|
||||||
AccessType::Normal => {
|
AccessMode::ReadWrite => {
|
||||||
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
|
||||||
}
|
}
|
||||||
// Constant values cannot be assigned to
|
// Constant values cannot be assigned to
|
||||||
AccessType::Constant => {
|
AccessMode::ReadOnly => {
|
||||||
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*name_pos))
|
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*name_pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1810,7 +1810,7 @@ fn parse_custom_syntax(
|
|||||||
// Variable searches stop at the first empty variable name.
|
// Variable searches stop at the first empty variable name.
|
||||||
state.stack.resize(
|
state.stack.resize(
|
||||||
state.stack.len() + delta as usize,
|
state.stack.len() + delta as usize,
|
||||||
("".into(), AccessType::Normal),
|
("".into(), AccessMode::ReadWrite),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
delta if delta < 0 && state.stack.len() <= delta.abs() as usize => state.stack.clear(),
|
delta if delta < 0 && state.stack.len() <= delta.abs() as usize => state.stack.clear(),
|
||||||
@ -2109,7 +2109,7 @@ fn parse_for(
|
|||||||
|
|
||||||
let loop_var = state.get_interned_string(name.clone());
|
let loop_var = state.get_interned_string(name.clone());
|
||||||
let prev_stack_len = state.stack.len();
|
let prev_stack_len = state.stack.len();
|
||||||
state.stack.push((loop_var, AccessType::Normal));
|
state.stack.push((loop_var, AccessMode::ReadWrite));
|
||||||
|
|
||||||
settings.is_breakable = true;
|
settings.is_breakable = true;
|
||||||
let body = parse_block(input, state, lib, settings.level_up())?;
|
let body = parse_block(input, state, lib, settings.level_up())?;
|
||||||
@ -2124,7 +2124,7 @@ fn parse_let(
|
|||||||
input: &mut TokenStream,
|
input: &mut TokenStream,
|
||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
lib: &mut FunctionsLib,
|
lib: &mut FunctionsLib,
|
||||||
var_type: AccessType,
|
var_type: AccessMode,
|
||||||
export: bool,
|
export: bool,
|
||||||
mut settings: ParseSettings,
|
mut settings: ParseSettings,
|
||||||
) -> Result<Stmt, ParseError> {
|
) -> Result<Stmt, ParseError> {
|
||||||
@ -2155,16 +2155,16 @@ fn parse_let(
|
|||||||
|
|
||||||
match var_type {
|
match var_type {
|
||||||
// let name = expr
|
// let name = expr
|
||||||
AccessType::Normal => {
|
AccessMode::ReadWrite => {
|
||||||
let var_name = state.get_interned_string(name.clone());
|
let var_name = state.get_interned_string(name.clone());
|
||||||
state.stack.push((var_name, AccessType::Normal));
|
state.stack.push((var_name, AccessMode::ReadWrite));
|
||||||
let var_def = Ident::new(name, pos);
|
let var_def = Ident::new(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 }
|
||||||
AccessType::Constant => {
|
AccessMode::ReadOnly => {
|
||||||
let var_name = state.get_interned_string(name.clone());
|
let var_name = state.get_interned_string(name.clone());
|
||||||
state.stack.push((var_name, AccessType::Constant));
|
state.stack.push((var_name, AccessMode::ReadOnly));
|
||||||
let var_def = Ident::new(name, pos);
|
let var_def = Ident::new(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))
|
||||||
}
|
}
|
||||||
@ -2231,13 +2231,13 @@ fn parse_export(
|
|||||||
match input.peek().unwrap() {
|
match input.peek().unwrap() {
|
||||||
(Token::Let, pos) => {
|
(Token::Let, pos) => {
|
||||||
let pos = *pos;
|
let pos = *pos;
|
||||||
let mut stmt = parse_let(input, state, lib, AccessType::Normal, true, settings)?;
|
let mut stmt = parse_let(input, state, lib, AccessMode::ReadWrite, true, settings)?;
|
||||||
stmt.set_position(pos);
|
stmt.set_position(pos);
|
||||||
return Ok(stmt);
|
return Ok(stmt);
|
||||||
}
|
}
|
||||||
(Token::Const, pos) => {
|
(Token::Const, pos) => {
|
||||||
let pos = *pos;
|
let pos = *pos;
|
||||||
let mut stmt = parse_let(input, state, lib, AccessType::Constant, true, settings)?;
|
let mut stmt = parse_let(input, state, lib, AccessMode::ReadOnly, true, settings)?;
|
||||||
stmt.set_position(pos);
|
stmt.set_position(pos);
|
||||||
return Ok(stmt);
|
return Ok(stmt);
|
||||||
}
|
}
|
||||||
@ -2392,7 +2392,7 @@ fn parse_stmt(
|
|||||||
lib: &mut FunctionsLib,
|
lib: &mut FunctionsLib,
|
||||||
mut settings: ParseSettings,
|
mut settings: ParseSettings,
|
||||||
) -> Result<Option<Stmt>, ParseError> {
|
) -> Result<Option<Stmt>, ParseError> {
|
||||||
use AccessType::{Constant, Normal};
|
use AccessMode::{ReadOnly, ReadWrite};
|
||||||
|
|
||||||
let (token, token_pos) = match input.peek().unwrap() {
|
let (token, token_pos) = match input.peek().unwrap() {
|
||||||
(Token::EOF, pos) => return Ok(Some(Stmt::Noop(*pos))),
|
(Token::EOF, pos) => return Ok(Some(Stmt::Noop(*pos))),
|
||||||
@ -2520,9 +2520,9 @@ fn parse_stmt(
|
|||||||
|
|
||||||
Token::Try => parse_try_catch(input, state, lib, settings.level_up()).map(Some),
|
Token::Try => parse_try_catch(input, state, lib, settings.level_up()).map(Some),
|
||||||
|
|
||||||
Token::Let => parse_let(input, state, lib, Normal, false, settings.level_up()).map(Some),
|
Token::Let => parse_let(input, state, lib, ReadWrite, false, settings.level_up()).map(Some),
|
||||||
Token::Const => {
|
Token::Const => {
|
||||||
parse_let(input, state, lib, Constant, false, settings.level_up()).map(Some)
|
parse_let(input, state, lib, ReadOnly, false, settings.level_up()).map(Some)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -2636,7 +2636,7 @@ fn parse_fn(
|
|||||||
return Err(PERR::FnDuplicatedParam(name, s).into_err(pos));
|
return Err(PERR::FnDuplicatedParam(name, s).into_err(pos));
|
||||||
}
|
}
|
||||||
let s = state.get_interned_string(s);
|
let s = state.get_interned_string(s);
|
||||||
state.stack.push((s.clone(), AccessType::Normal));
|
state.stack.push((s.clone(), AccessMode::ReadWrite));
|
||||||
params.push((s, pos))
|
params.push((s, pos))
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
@ -2769,7 +2769,7 @@ fn parse_anon_fn(
|
|||||||
return Err(PERR::FnDuplicatedParam("".to_string(), s).into_err(pos));
|
return Err(PERR::FnDuplicatedParam("".to_string(), s).into_err(pos));
|
||||||
}
|
}
|
||||||
let s = state.get_interned_string(s);
|
let s = state.get_interned_string(s);
|
||||||
state.stack.push((s.clone(), AccessType::Normal));
|
state.stack.push((s.clone(), AccessMode::ReadWrite));
|
||||||
params.push((s, pos))
|
params.push((s, pos))
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
|
22
src/scope.rs
22
src/scope.rs
@ -1,6 +1,6 @@
|
|||||||
//! Module that defines the [`Scope`] type representing a function call-stack scope.
|
//! Module that defines the [`Scope`] type representing a function call-stack scope.
|
||||||
|
|
||||||
use crate::dynamic::{AccessType, Variant};
|
use crate::dynamic::{AccessMode, Variant};
|
||||||
use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec};
|
use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec};
|
||||||
use crate::{Dynamic, StaticVec};
|
use crate::{Dynamic, StaticVec};
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ impl<'a> Scope<'a> {
|
|||||||
name: impl Into<Cow<'a, str>>,
|
name: impl Into<Cow<'a, str>>,
|
||||||
value: impl Variant + Clone,
|
value: impl Variant + Clone,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.push_dynamic_value(name, AccessType::Normal, Dynamic::from(value))
|
self.push_dynamic_value(name, AccessMode::ReadWrite, Dynamic::from(value))
|
||||||
}
|
}
|
||||||
/// Add (push) a new [`Dynamic`] entry to the [`Scope`].
|
/// Add (push) a new [`Dynamic`] entry to the [`Scope`].
|
||||||
///
|
///
|
||||||
@ -172,7 +172,7 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_dynamic(&mut self, name: impl Into<Cow<'a, str>>, value: Dynamic) -> &mut Self {
|
pub fn push_dynamic(&mut self, name: impl Into<Cow<'a, str>>, value: Dynamic) -> &mut Self {
|
||||||
self.push_dynamic_value(name, value.access_type(), value)
|
self.push_dynamic_value(name, value.access_mode(), value)
|
||||||
}
|
}
|
||||||
/// Add (push) a new constant to the [`Scope`].
|
/// Add (push) a new constant to the [`Scope`].
|
||||||
///
|
///
|
||||||
@ -195,7 +195,7 @@ impl<'a> Scope<'a> {
|
|||||||
name: impl Into<Cow<'a, str>>,
|
name: impl Into<Cow<'a, str>>,
|
||||||
value: impl Variant + Clone,
|
value: impl Variant + Clone,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.push_dynamic_value(name, AccessType::Constant, Dynamic::from(value))
|
self.push_dynamic_value(name, AccessMode::ReadOnly, Dynamic::from(value))
|
||||||
}
|
}
|
||||||
/// Add (push) a new constant with a [`Dynamic`] value to the Scope.
|
/// Add (push) a new constant with a [`Dynamic`] value to the Scope.
|
||||||
///
|
///
|
||||||
@ -218,18 +218,18 @@ impl<'a> Scope<'a> {
|
|||||||
name: impl Into<Cow<'a, str>>,
|
name: impl Into<Cow<'a, str>>,
|
||||||
value: Dynamic,
|
value: Dynamic,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.push_dynamic_value(name, AccessType::Constant, value)
|
self.push_dynamic_value(name, AccessMode::ReadOnly, value)
|
||||||
}
|
}
|
||||||
/// Add (push) a new entry with a [`Dynamic`] value to the [`Scope`].
|
/// Add (push) a new entry with a [`Dynamic`] value to the [`Scope`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn push_dynamic_value(
|
pub(crate) fn push_dynamic_value(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<Cow<'a, str>>,
|
name: impl Into<Cow<'a, str>>,
|
||||||
access: AccessType,
|
access: AccessMode,
|
||||||
mut value: Dynamic,
|
mut value: Dynamic,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.names.push((name.into(), Box::new(Default::default())));
|
self.names.push((name.into(), Box::new(Default::default())));
|
||||||
value.set_access_type(access);
|
value.set_access_mode(access);
|
||||||
self.values.push(value.into());
|
self.values.push(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -287,14 +287,14 @@ impl<'a> Scope<'a> {
|
|||||||
}
|
}
|
||||||
/// Find an entry in the [`Scope`], starting from the last.
|
/// Find an entry in the [`Scope`], starting from the last.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_index(&self, name: &str) -> Option<(usize, AccessType)> {
|
pub(crate) fn get_index(&self, name: &str) -> Option<(usize, AccessMode)> {
|
||||||
self.names
|
self.names
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev() // Always search a Scope in reverse order
|
.rev() // Always search a Scope in reverse order
|
||||||
.find_map(|(index, (key, _))| {
|
.find_map(|(index, (key, _))| {
|
||||||
if name == key.as_ref() {
|
if name == key.as_ref() {
|
||||||
Some((index, self.values[index].access_type()))
|
Some((index, self.values[index].access_mode()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -349,8 +349,8 @@ impl<'a> Scope<'a> {
|
|||||||
None => {
|
None => {
|
||||||
self.push(name, value);
|
self.push(name, value);
|
||||||
}
|
}
|
||||||
Some((_, AccessType::Constant)) => panic!("variable {} is constant", name),
|
Some((_, AccessMode::ReadOnly)) => panic!("variable {} is constant", name),
|
||||||
Some((index, AccessType::Normal)) => {
|
Some((index, AccessMode::ReadWrite)) => {
|
||||||
*self.values.get_mut(index).unwrap() = Dynamic::from(value);
|
*self.values.get_mut(index).unwrap() = Dynamic::from(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user