Streamline data types.

This commit is contained in:
Stephen Chung 2023-04-10 18:47:53 +08:00
parent ac52d3cd87
commit 26ad454cb1
6 changed files with 44 additions and 48 deletions

View File

@ -721,7 +721,7 @@ pub enum Stmt {
/// This variant does not map to any language structure. It is currently only used only to /// This variant does not map to any language structure. It is currently only used only to
/// convert normal variables into shared variables when they are _captured_ by a closure. /// convert normal variables into shared variables when they are _captured_ by a closure.
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Share(Box<crate::FnArgsVec<(crate::ImmutableString, Option<NonZeroUsize>, Position)>>), Share(Box<crate::FnArgsVec<(crate::ast::Ident, Option<NonZeroUsize>)>>),
} }
impl Default for Stmt { impl Default for Stmt {
@ -816,7 +816,7 @@ impl Stmt {
Self::Export(.., pos) => *pos, Self::Export(.., pos) => *pos,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Self::Share(x) => x[0].2, Self::Share(x) => x[0].0.pos,
} }
} }
/// Override the [position][Position] of this statement. /// Override the [position][Position] of this statement.
@ -848,7 +848,7 @@ impl Stmt {
Self::Export(.., pos) => *pos = new_pos, Self::Export(.., pos) => *pos = new_pos,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Self::Share(x) => x.iter_mut().for_each(|(_, _, pos)| *pos = new_pos), Self::Share(x) => x.iter_mut().for_each(|(x, _)| x.pos = new_pos),
} }
self self

View File

@ -927,10 +927,10 @@ impl Engine {
// Share statement // Share statement
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(x) => { Stmt::Share(x) => {
for (name, index, pos) in &**x { for (var, index) in &**x {
if let Some(index) = index if let Some(index) = index
.map(|n| scope.len() - n.get()) .map(|n| scope.len() - n.get())
.or_else(|| scope.search(name)) .or_else(|| scope.search(&var.name))
{ {
let val = scope.get_mut_by_index(index); let val = scope.get_mut_by_index(index);
@ -939,7 +939,9 @@ impl Engine {
*val = std::mem::take(val).into_shared(); *val = std::mem::take(val).into_shared();
} }
} else { } else {
return Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into()); return Err(
ERR::ErrorVariableNotFound(var.name.to_string(), var.pos).into()
);
} }
} }

View File

@ -1986,23 +1986,35 @@ impl Module {
} }
/// Get an iterator to the sub-modules in the [`Module`]. /// Get an iterator to the sub-modules in the [`Module`].
#[inline] #[inline(always)]
pub fn iter_sub_modules(&self) -> impl Iterator<Item = (&str, &SharedModule)> { pub fn iter_sub_modules(&self) -> impl Iterator<Item = (&str, &SharedModule)> {
self.iter_sub_modules_raw().map(|(k, m)| (k.as_str(), m))
}
/// Get an iterator to the sub-modules in the [`Module`].
#[inline]
pub(crate) fn iter_sub_modules_raw(
&self,
) -> impl Iterator<Item = (&Identifier, &SharedModule)> {
self.modules self.modules
.as_ref() .as_ref()
.into_iter() .into_iter()
.flatten() .flatten()
.map(|(k, m)| (k.as_str(), m)) .map(|(k, m)| (k, m))
} }
/// Get an iterator to the variables in the [`Module`]. /// Get an iterator to the variables in the [`Module`].
#[inline] #[inline(always)]
pub fn iter_var(&self) -> impl Iterator<Item = (&str, &Dynamic)> { pub fn iter_var(&self) -> impl Iterator<Item = (&str, &Dynamic)> {
self.iter_var_raw().map(|(k, v)| (k.as_str(), v))
}
/// Get an iterator to the variables in the [`Module`].
#[inline]
pub(crate) fn iter_var_raw(&self) -> impl Iterator<Item = (&Identifier, &Dynamic)> {
self.variables self.variables
.as_ref() .as_ref()
.into_iter() .into_iter()
.flatten() .flatten()
.map(|(k, v)| (k.as_str(), v)) .map(|(k, v)| (k, v))
} }
/// Get an iterator to the functions in the [`Module`]. /// Get an iterator to the functions in the [`Module`].

View File

@ -14,10 +14,9 @@ use crate::func::builtin::get_builtin_binary_op_fn;
use crate::func::hashing::get_hasher; use crate::func::hashing::get_hasher;
use crate::module::ModuleFlags; use crate::module::ModuleFlags;
use crate::tokenizer::Token; use crate::tokenizer::Token;
use crate::types::dynamic::AccessMode;
use crate::{ use crate::{
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnPtr, Identifier, ImmutableString, Position, calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnPtr, ImmutableString, Position, Scope,
Scope, StaticVec, AST, StaticVec, AST,
}; };
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
@ -54,8 +53,8 @@ impl Default for OptimizationLevel {
struct OptimizerState<'a> { struct OptimizerState<'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 variables/constants to use for eager function evaluations.
variables: StaticVec<(Identifier, AccessMode, Option<Dynamic>)>, variables: StaticVec<(ImmutableString, Option<Dynamic>)>,
/// Activate constants propagation? /// Activate constants propagation?
propagate_constants: bool, propagate_constants: bool,
/// An [`Engine`] instance for eager function evaluation. /// An [`Engine`] instance for eager function evaluation.
@ -115,14 +114,11 @@ impl<'a> OptimizerState<'a> {
self.variables.truncate(len); self.variables.truncate(len);
} }
/// Add a new variable to the list. /// Add a new variable to the list.
///
/// `Some(value)` if constant, `None` or otherwise.
#[inline(always)] #[inline(always)]
pub fn push_var( pub fn push_var(&mut self, name: ImmutableString, value: Option<Dynamic>) {
&mut self, self.variables.push((name, value));
name: impl Into<Identifier>,
access: AccessMode,
value: Option<Dynamic>,
) {
self.variables.push((name.into(), access, value));
} }
/// Look up a constant from the list. /// Look up a constant from the list.
#[inline] #[inline]
@ -131,12 +127,9 @@ impl<'a> OptimizerState<'a> {
return None; return None;
} }
for (n, access, value) in self.variables.iter().rev() { for (n, value) in self.variables.iter().rev() {
if n == name { if n.as_str() == name {
return match access { return value.as_ref();
AccessMode::ReadWrite => None,
AccessMode::ReadOnly => value.as_ref(),
};
} }
} }
@ -237,16 +230,13 @@ fn optimize_stmt_block(
optimize_expr(&mut x.1, state, false); optimize_expr(&mut x.1, state, false);
if x.1.is_constant() { if x.1.is_constant() {
state.push_var( state
x.0.as_str(), .push_var(x.0.name.clone(), Some(x.1.get_literal_value().unwrap()));
AccessMode::ReadOnly,
x.1.get_literal_value(),
);
} }
} else { } else {
// Add variables into the state // Add variables into the state
optimize_expr(&mut x.1, state, false); optimize_expr(&mut x.1, state, false);
state.push_var(x.0.as_str(), AccessMode::ReadWrite, None); state.push_var(x.0.name.clone(), None);
} }
} }
// Optimize the statement // Optimize the statement
@ -858,7 +848,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(x) => { Stmt::Share(x) => {
let len = x.len(); let len = x.len();
x.retain(|(v, _, _)| !state.find_constant(v).is_some()); x.retain(|(v, _)| !state.find_constant(v).is_some());
if x.len() != len { if x.len() != len {
state.set_dirty(); state.set_dirty();
} }
@ -1335,20 +1325,14 @@ impl Engine {
.iter() .iter()
.rev() .rev()
.flat_map(|m| m.iter_var()) .flat_map(|m| m.iter_var())
.for_each(|(name, value)| { .for_each(|(name, value)| state.push_var(name.into(), Some(value.clone())));
state.push_var(name, AccessMode::ReadOnly, Some(value.clone()))
});
// Add constants and variables from the scope // Add constants and variables from the scope
scope scope
.into_iter() .into_iter()
.flat_map(Scope::iter) .flat_map(Scope::iter)
.for_each(|(name, constant, value)| { .for_each(|(name, constant, value)| {
if constant { state.push_var(name.into(), if constant { Some(value) } else { None });
state.push_var(name, AccessMode::ReadOnly, Some(value));
} else {
state.push_var(name, AccessMode::ReadWrite, None);
}
}); });
optimize_stmt_block(statements, &mut state, true, false, true) optimize_stmt_block(statements, &mut state, true, false, true)

View File

@ -3781,9 +3781,9 @@ impl Engine {
statements.push(Stmt::Share( statements.push(Stmt::Share(
externals externals
.into_iter() .into_iter()
.map(|Ident { name, pos }| { .map(|var| {
let (index, _) = parent.access_var(&name, lib, pos); let (index, _) = parent.access_var(&var.name, lib, var.pos);
(name, index, pos) (var, index)
}) })
.collect::<crate::FnArgsVec<_>>() .collect::<crate::FnArgsVec<_>>()
.into(), .into(),

View File

@ -182,8 +182,6 @@ fn test_optimizer_reoptimize() -> Result<(), Box<EvalAltResult>> {
let scope: Scope = ast.iter_literal_variables(true, false).collect(); let scope: Scope = ast.iter_literal_variables(true, false).collect();
let ast = engine.optimize_ast(&scope, ast, OptimizationLevel::Simple); let ast = engine.optimize_ast(&scope, ast, OptimizationLevel::Simple);
println!("{ast:#?}");
assert_eq!(engine.eval_ast::<INT>(&ast)?, 84); assert_eq!(engine.eval_ast::<INT>(&ast)?, 84);
Ok(()) Ok(())