Add Dynamic::NULL to simplify this pointer binding.

This commit is contained in:
Stephen Chung
2022-11-08 16:16:42 +08:00
parent 6053aa1641
commit 8f128f37f0
16 changed files with 126 additions and 77 deletions

View File

@@ -50,7 +50,7 @@ struct OptimizerState<'a> {
/// Has the [`AST`] been changed during this pass?
changed: bool,
/// Collection of constants to use for eager function evaluations.
variables: StaticVec<(Identifier, AccessMode, Option<Dynamic>)>,
variables: StaticVec<(Identifier, AccessMode, Dynamic)>,
/// Activate constants propagation?
propagate_constants: bool,
/// An [`Engine`] instance for eager function evaluation.
@@ -108,12 +108,7 @@ impl<'a> OptimizerState<'a> {
}
/// Add a new variable to the list.
#[inline(always)]
pub fn push_var(
&mut self,
name: impl Into<Identifier>,
access: AccessMode,
value: Option<Dynamic>,
) {
pub fn push_var(&mut self, name: impl Into<Identifier>, access: AccessMode, value: Dynamic) {
self.variables.push((name.into(), access, value));
}
/// Look up a constant from the list.
@@ -127,7 +122,8 @@ impl<'a> OptimizerState<'a> {
if n == name {
return match access {
AccessMode::ReadWrite => None,
AccessMode::ReadOnly => value.as_ref(),
AccessMode::ReadOnly if value.is_null() => None,
AccessMode::ReadOnly => Some(value),
};
}
}
@@ -141,7 +137,7 @@ impl<'a> OptimizerState<'a> {
fn_name: &str,
op_token: Option<&Token>,
arg_values: &mut [Dynamic],
) -> Option<Dynamic> {
) -> Dynamic {
#[cfg(not(feature = "no_function"))]
let lib = self.lib;
#[cfg(feature = "no_function")]
@@ -160,8 +156,7 @@ impl<'a> OptimizerState<'a> {
false,
Position::NONE,
)
.ok()
.map(|(v, ..)| v)
.map_or(Dynamic::NULL, |(v, ..)| v)
}
}
@@ -271,13 +266,13 @@ fn optimize_stmt_block(
state.push_var(
x.0.as_str(),
AccessMode::ReadOnly,
x.1.get_literal_value(),
x.1.get_literal_value().unwrap_or(Dynamic::NULL),
);
}
} else {
// Add variables into the state
optimize_expr(&mut x.1, state, false);
state.push_var(x.0.as_str(), AccessMode::ReadWrite, None);
state.push_var(x.0.as_str(), AccessMode::ReadWrite, Dynamic::NULL);
}
}
// Optimize the statement
@@ -1197,13 +1192,13 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
let arg_values = &mut x.args.iter().map(Expr::get_literal_value).collect::<Option<StaticVec<_>>>().unwrap();
let result = match x.name.as_str() {
KEYWORD_TYPE_OF if arg_values.len() == 1 => Some(state.engine.map_type_name(arg_values[0].type_name()).into()),
KEYWORD_TYPE_OF if arg_values.len() == 1 => state.engine.map_type_name(arg_values[0].type_name()).into(),
#[cfg(not(feature = "no_closure"))]
crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Some(Dynamic::FALSE),
crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Dynamic::FALSE,
_ => state.call_fn_with_constant_arguments(&x.name, x.op_token.as_ref(), arg_values)
};
if let Some(result) = result {
if !result.is_null() {
state.set_dirty();
*expr = Expr::from_dynamic(result, *pos);
return;
@@ -1289,15 +1284,15 @@ fn optimize_top_level(
.rev()
.flat_map(|m| m.iter_var())
{
state.push_var(name, AccessMode::ReadOnly, Some(value.clone()));
state.push_var(name, AccessMode::ReadOnly, value.clone());
}
// Add constants and variables from the scope
for (name, constant, value) in scope.iter() {
if constant {
state.push_var(name, AccessMode::ReadOnly, Some(value));
state.push_var(name, AccessMode::ReadOnly, value);
} else {
state.push_var(name, AccessMode::ReadWrite, None);
state.push_var(name, AccessMode::ReadWrite, Dynamic::NULL);
}
}