Make FunctionsLib a HashMap.
This commit is contained in:
parent
f8e9d66a0b
commit
3a93ab8240
@ -956,7 +956,11 @@ impl Engine {
|
|||||||
ast: AST,
|
ast: AST,
|
||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
) -> AST {
|
) -> AST {
|
||||||
let fn_lib = ast.1.iter().map(|fn_def| fn_def.as_ref().clone()).collect();
|
let fn_lib = ast
|
||||||
|
.1
|
||||||
|
.iter()
|
||||||
|
.map(|(_, fn_def)| fn_def.as_ref().clone())
|
||||||
|
.collect();
|
||||||
optimize_into_ast(self, scope, ast.0, fn_lib, optimization_level)
|
optimize_into_ast(self, scope, ast.0, fn_lib, optimization_level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ use crate::token::Position;
|
|||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
cmp::Ordering,
|
|
||||||
collections::{hash_map::DefaultHasher, HashMap},
|
collections::{hash_map::DefaultHasher, HashMap},
|
||||||
format,
|
format,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
@ -125,48 +124,41 @@ impl<'a> From<&'a mut Dynamic> for Target<'a> {
|
|||||||
/// So instead this is implemented as a sorted list and binary searched.
|
/// So instead this is implemented as a sorted list and binary searched.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FunctionsLib(
|
pub struct FunctionsLib(
|
||||||
#[cfg(feature = "sync")] Vec<Arc<FnDef>>,
|
#[cfg(feature = "sync")] HashMap<u64, Arc<FnDef>>,
|
||||||
#[cfg(not(feature = "sync"))] Vec<Rc<FnDef>>,
|
#[cfg(not(feature = "sync"))] HashMap<u64, Rc<FnDef>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl FnDef {
|
|
||||||
/// Function to order two FnDef records, for binary search.
|
|
||||||
pub fn compare(&self, name: &str, params_len: usize) -> Ordering {
|
|
||||||
// First order by name
|
|
||||||
match self.name.as_str().cmp(name) {
|
|
||||||
// Then by number of parameters
|
|
||||||
Ordering::Equal => self.params.len().cmp(¶ms_len),
|
|
||||||
order => order,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FunctionsLib {
|
impl FunctionsLib {
|
||||||
/// Create a new `FunctionsLib`.
|
/// Create a new `FunctionsLib`.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
FunctionsLib(Vec::new())
|
FunctionsLib(HashMap::new())
|
||||||
}
|
}
|
||||||
/// Create a new `FunctionsLib` from a collection of `FnDef`.
|
/// Create a new `FunctionsLib` from a collection of `FnDef`.
|
||||||
pub fn from_vec(vec: Vec<FnDef>) -> Self {
|
pub fn from_vec(vec: Vec<FnDef>) -> Self {
|
||||||
#[cfg(feature = "sync")]
|
FunctionsLib(
|
||||||
{
|
vec.into_iter()
|
||||||
FunctionsLib(vec.into_iter().map(Arc::new).collect())
|
.map(|f| {
|
||||||
}
|
let hash = calc_fn_def(&f.name, f.params.len());
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
{
|
#[cfg(feature = "sync")]
|
||||||
FunctionsLib(vec.into_iter().map(Rc::new).collect())
|
{
|
||||||
}
|
(hash, Arc::new(f))
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
{
|
||||||
|
(hash, Rc::new(f))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/// Does a certain function exist in the `FunctionsLib`?
|
/// Does a certain function exist in the `FunctionsLib`?
|
||||||
pub fn has_function(&self, name: &str, params: usize) -> bool {
|
pub fn has_function(&self, name: &str, params: usize) -> bool {
|
||||||
self.0.binary_search_by(|f| f.compare(name, params)).is_ok()
|
self.contains_key(&calc_fn_def(name, params))
|
||||||
}
|
}
|
||||||
/// Get a function definition from the `FunctionsLib`.
|
/// Get a function definition from the `FunctionsLib`.
|
||||||
pub fn get_function(&self, name: &str, params: usize) -> Option<&FnDef> {
|
pub fn get_function(&self, name: &str, params: usize) -> Option<&FnDef> {
|
||||||
self.0
|
self.get(&calc_fn_def(name, params)).map(|f| f.as_ref())
|
||||||
.binary_search_by(|f| f.compare(name, params))
|
|
||||||
.ok()
|
|
||||||
.map(|n| self.0[n].as_ref())
|
|
||||||
}
|
}
|
||||||
/// Merge another `FunctionsLib` into this `FunctionsLib`.
|
/// Merge another `FunctionsLib` into this `FunctionsLib`.
|
||||||
pub fn merge(&self, other: &Self) -> Self {
|
pub fn merge(&self, other: &Self) -> Self {
|
||||||
@ -177,16 +169,8 @@ impl FunctionsLib {
|
|||||||
} else {
|
} else {
|
||||||
let mut functions = self.clone();
|
let mut functions = self.clone();
|
||||||
|
|
||||||
other.iter().cloned().for_each(|fn_def| {
|
other.iter().for_each(|(hash, fn_def)| {
|
||||||
if let Some((n, _)) = functions
|
functions.insert(*hash, fn_def.clone());
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.find(|(_, f)| f.name == fn_def.name && f.params.len() == fn_def.params.len())
|
|
||||||
{
|
|
||||||
functions[n] = fn_def;
|
|
||||||
} else {
|
|
||||||
functions.push(fn_def);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
functions
|
functions
|
||||||
@ -196,9 +180,9 @@ impl FunctionsLib {
|
|||||||
|
|
||||||
impl Deref for FunctionsLib {
|
impl Deref for FunctionsLib {
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
type Target = Vec<Arc<FnDef>>;
|
type Target = HashMap<u64, Arc<FnDef>>;
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
type Target = Vec<Rc<FnDef>>;
|
type Target = HashMap<u64, Rc<FnDef>>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
@ -207,11 +191,11 @@ impl Deref for FunctionsLib {
|
|||||||
|
|
||||||
impl DerefMut for FunctionsLib {
|
impl DerefMut for FunctionsLib {
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
fn deref_mut(&mut self) -> &mut Vec<Arc<FnDef>> {
|
fn deref_mut(&mut self) -> &mut HashMap<u64, Arc<FnDef>> {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
fn deref_mut(&mut self) -> &mut Vec<Rc<FnDef>> {
|
fn deref_mut(&mut self) -> &mut HashMap<u64, Rc<FnDef>> {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,6 +333,13 @@ pub(crate) fn calc_fn_spec(fn_name: &str, params: impl Iterator<Item = TypeId>)
|
|||||||
s.finish()
|
s.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn calc_fn_def(fn_name: &str, params: usize) -> u64 {
|
||||||
|
let mut s = DefaultHasher::new();
|
||||||
|
fn_name.hash(&mut s);
|
||||||
|
params.hash(&mut s);
|
||||||
|
s.finish()
|
||||||
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
/// Create a new `Engine`
|
/// Create a new `Engine`
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Main module defining the lexer and parser.
|
//! Main module defining the lexer and parser.
|
||||||
|
|
||||||
use crate::any::{Dynamic, Union};
|
use crate::any::{Dynamic, Union};
|
||||||
use crate::engine::{Engine, FunctionsLib};
|
use crate::engine::{calc_fn_def, Engine, FunctionsLib};
|
||||||
use crate::error::{LexError, ParseError, ParseErrorType};
|
use crate::error::{LexError, ParseError, ParseErrorType};
|
||||||
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||||
@ -1787,9 +1787,9 @@ pub fn parse_global_expr<'a>(
|
|||||||
/// Parse the global level statements.
|
/// Parse the global level statements.
|
||||||
fn parse_global_level<'a>(
|
fn parse_global_level<'a>(
|
||||||
input: &mut Peekable<TokenIterator<'a>>,
|
input: &mut Peekable<TokenIterator<'a>>,
|
||||||
) -> Result<(Vec<Stmt>, Vec<FnDef>), ParseError> {
|
) -> Result<(Vec<Stmt>, HashMap<u64, FnDef>), ParseError> {
|
||||||
let mut statements = Vec::<Stmt>::new();
|
let mut statements = Vec::<Stmt>::new();
|
||||||
let mut functions = Vec::<FnDef>::new();
|
let mut functions = HashMap::<u64, FnDef>::new();
|
||||||
|
|
||||||
while input.peek().is_some() {
|
while input.peek().is_some() {
|
||||||
// Collect all the function definitions
|
// Collect all the function definitions
|
||||||
@ -1797,13 +1797,7 @@ fn parse_global_level<'a>(
|
|||||||
{
|
{
|
||||||
if matches!(input.peek().expect("should not be None"), (Token::Fn, _)) {
|
if matches!(input.peek().expect("should not be None"), (Token::Fn, _)) {
|
||||||
let f = parse_fn(input, true)?;
|
let f = parse_fn(input, true)?;
|
||||||
|
functions.insert(calc_fn_def(&f.name, f.params.len()), f);
|
||||||
// Ensure list is sorted
|
|
||||||
match functions.binary_search_by(|fn_def| fn_def.compare(&f.name, f.params.len())) {
|
|
||||||
Ok(n) => functions[n] = f, // Override previous definition
|
|
||||||
Err(n) => functions.insert(n, f), // New function definition
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1849,9 +1843,10 @@ pub fn parse<'a>(
|
|||||||
) -> Result<AST, ParseError> {
|
) -> Result<AST, ParseError> {
|
||||||
let (statements, functions) = parse_global_level(input)?;
|
let (statements, functions) = parse_global_level(input)?;
|
||||||
|
|
||||||
|
let fn_lib = functions.into_iter().map(|(_, v)| v).collect();
|
||||||
Ok(
|
Ok(
|
||||||
// Optimize AST
|
// Optimize AST
|
||||||
optimize_into_ast(engine, scope, statements, functions, optimization_level),
|
optimize_into_ast(engine, scope, statements, fn_lib, optimization_level),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,13 +397,6 @@ impl<'a> Scope<'a> {
|
|||||||
&mut entry.value
|
&mut entry.value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to an entry in the Scope and downcast it to a specific type
|
|
||||||
pub(crate) fn get_mut_by_type<T: Variant + Clone>(&mut self, key: EntryRef) -> &mut T {
|
|
||||||
self.get_mut(key)
|
|
||||||
.downcast_mut::<T>()
|
|
||||||
.expect("wrong type cast")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get an iterator to entries in the Scope.
|
/// Get an iterator to entries in the Scope.
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &Entry> {
|
pub fn iter(&self) -> impl Iterator<Item = &Entry> {
|
||||||
self.0.iter().rev() // Always search a Scope in reverse order
|
self.0.iter().rev() // Always search a Scope in reverse order
|
||||||
|
Loading…
Reference in New Issue
Block a user