Simplify code.
This commit is contained in:
parent
5848339d5a
commit
bc0d43d68f
187
src/engine.rs
187
src/engine.rs
@ -172,11 +172,10 @@ impl FunctionsLib {
|
|||||||
}
|
}
|
||||||
/// 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> {
|
||||||
if let Ok(n) = self.0.binary_search_by(|f| f.compare(name, params)) {
|
self.0
|
||||||
Some(&self.0[n])
|
.binary_search_by(|f| f.compare(name, params))
|
||||||
} else {
|
.ok()
|
||||||
None
|
.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 {
|
||||||
@ -441,58 +440,56 @@ impl Engine<'_> {
|
|||||||
const fn_lib: Option<&FunctionsLib> = None;
|
const fn_lib: Option<&FunctionsLib> = None;
|
||||||
|
|
||||||
// First search in script-defined functions (can override built-in)
|
// First search in script-defined functions (can override built-in)
|
||||||
if let Some(lib) = fn_lib {
|
if let Some(fn_def) = fn_lib.and_then(|lib| lib.get_function(fn_name, args.len())) {
|
||||||
if let Some(fn_def) = lib.get_function(fn_name, args.len()) {
|
match scope {
|
||||||
match scope {
|
// Extern scope passed in which is not empty
|
||||||
// Extern scope passed in which is not empty
|
Some(scope) if scope.len() > 0 => {
|
||||||
Some(scope) if scope.len() > 0 => {
|
let scope_len = scope.len();
|
||||||
let scope_len = scope.len();
|
|
||||||
|
|
||||||
scope.extend(
|
scope.extend(
|
||||||
// Put arguments into scope as variables - variable name is copied
|
// Put arguments into scope as variables - variable name is copied
|
||||||
// TODO - avoid copying variable name
|
// TODO - avoid copying variable name
|
||||||
fn_def
|
fn_def
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.zip(args.into_iter().map(|x| (*x).into_dynamic()))
|
.zip(args.into_iter().map(|x| (*x).into_dynamic()))
|
||||||
.map(|(name, value)| (name.clone(), ScopeEntryType::Normal, value)),
|
.map(|(name, value)| (name.clone(), ScopeEntryType::Normal, value)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Evaluate the function at one higher level of call depth
|
// Evaluate the function at one higher level of call depth
|
||||||
let result = self
|
let result = self
|
||||||
.eval_stmt(scope, fn_lib, &fn_def.body, level + 1)
|
.eval_stmt(scope, fn_lib, &fn_def.body, level + 1)
|
||||||
.or_else(|err| match err {
|
.or_else(|err| match err {
|
||||||
// Convert return statement to return value
|
// Convert return statement to return value
|
||||||
EvalAltResult::Return(x, _) => Ok(x),
|
EvalAltResult::Return(x, _) => Ok(x),
|
||||||
err => Err(err.set_position(pos)),
|
err => Err(err.set_position(pos)),
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.rewind(scope_len);
|
scope.rewind(scope_len);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// No new scope - create internal scope
|
// No new scope - create internal scope
|
||||||
_ => {
|
_ => {
|
||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
|
|
||||||
scope.extend(
|
scope.extend(
|
||||||
// Put arguments into scope as variables
|
// Put arguments into scope as variables
|
||||||
fn_def
|
fn_def
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.zip(args.into_iter().map(|x| (*x).into_dynamic()))
|
.zip(args.into_iter().map(|x| (*x).into_dynamic()))
|
||||||
.map(|(name, value)| (name, ScopeEntryType::Normal, value)),
|
.map(|(name, value)| (name, ScopeEntryType::Normal, value)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Evaluate the function at one higher level of call depth
|
// Evaluate the function at one higher level of call depth
|
||||||
return self
|
return self
|
||||||
.eval_stmt(&mut scope, fn_lib, &fn_def.body, level + 1)
|
.eval_stmt(&mut scope, fn_lib, &fn_def.body, level + 1)
|
||||||
.or_else(|err| match err {
|
.or_else(|err| match err {
|
||||||
// Convert return statement to return value
|
// Convert return statement to return value
|
||||||
EvalAltResult::Return(x, _) => Ok(x),
|
EvalAltResult::Return(x, _) => Ok(x),
|
||||||
err => Err(err.set_position(pos)),
|
err => Err(err.set_position(pos)),
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -510,25 +507,23 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
if let Some(functions) = &self.functions {
|
if let Some(func) = self.functions.as_ref().and_then(|f| f.get(&spec)) {
|
||||||
if let Some(func) = functions.get(&spec) {
|
// Run external function
|
||||||
// Run external function
|
let result = func(args, pos)?;
|
||||||
let result = func(args, pos)?;
|
|
||||||
|
|
||||||
// See if the function match print/debug (which requires special processing)
|
// See if the function match print/debug (which requires special processing)
|
||||||
return Ok(match fn_name {
|
return match fn_name {
|
||||||
KEYWORD_PRINT if self.on_print.is_some() => {
|
KEYWORD_PRINT if self.on_print.is_some() => Ok(self.on_print.as_ref().unwrap()(
|
||||||
self.on_print.as_ref().unwrap()(cast_to_string(result.as_ref(), pos)?)
|
cast_to_string(result.as_ref(), pos)?,
|
||||||
.into_dynamic()
|
)
|
||||||
}
|
.into_dynamic()),
|
||||||
KEYWORD_DEBUG if self.on_debug.is_some() => {
|
KEYWORD_DEBUG if self.on_debug.is_some() => Ok(self.on_debug.as_ref().unwrap()(
|
||||||
self.on_debug.as_ref().unwrap()(cast_to_string(result.as_ref(), pos)?)
|
cast_to_string(result.as_ref(), pos)?,
|
||||||
.into_dynamic()
|
)
|
||||||
}
|
.into_dynamic()),
|
||||||
KEYWORD_PRINT | KEYWORD_DEBUG => ().into_dynamic(),
|
KEYWORD_PRINT | KEYWORD_DEBUG => Ok(().into_dynamic()),
|
||||||
_ => result,
|
_ => Ok(result),
|
||||||
});
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prop) = extract_prop_from_getter(fn_name) {
|
if let Some(prop) = extract_prop_from_getter(fn_name) {
|
||||||
@ -1603,33 +1598,29 @@ impl Engine<'_> {
|
|||||||
let arr = self.eval_expr(scope, fn_lib, expr, level)?;
|
let arr = self.eval_expr(scope, fn_lib, expr, level)?;
|
||||||
let tid = Any::type_id(arr.as_ref());
|
let tid = Any::type_id(arr.as_ref());
|
||||||
|
|
||||||
if let Some(type_iterators) = &self.type_iterators {
|
if let Some(iter_fn) = self.type_iterators.as_ref().and_then(|t| t.get(&tid)) {
|
||||||
if let Some(iter_fn) = type_iterators.get(&tid) {
|
// Add the loop variable - variable name is copied
|
||||||
// Add the loop variable - variable name is copied
|
// TODO - avoid copying variable name
|
||||||
// TODO - avoid copying variable name
|
scope.push(name.clone(), ());
|
||||||
scope.push(name.clone(), ());
|
|
||||||
|
|
||||||
let entry = ScopeSource {
|
let entry = ScopeSource {
|
||||||
name,
|
name,
|
||||||
index: scope.len() - 1,
|
index: scope.len() - 1,
|
||||||
typ: ScopeEntryType::Normal,
|
typ: ScopeEntryType::Normal,
|
||||||
};
|
};
|
||||||
|
|
||||||
for a in iter_fn(&arr) {
|
for a in iter_fn(&arr) {
|
||||||
*scope.get_mut(entry) = a;
|
*scope.get_mut(entry) = a;
|
||||||
|
|
||||||
match self.eval_stmt(scope, fn_lib, body, level) {
|
match self.eval_stmt(scope, fn_lib, body, level) {
|
||||||
Ok(_) | Err(EvalAltResult::ErrorLoopBreak(false, _)) => (),
|
Ok(_) | Err(EvalAltResult::ErrorLoopBreak(false, _)) => (),
|
||||||
Err(EvalAltResult::ErrorLoopBreak(true, _)) => break,
|
Err(EvalAltResult::ErrorLoopBreak(true, _)) => break,
|
||||||
Err(x) => return Err(x),
|
Err(x) => return Err(x),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.rewind(scope.len() - 1);
|
|
||||||
Ok(().into_dynamic())
|
|
||||||
} else {
|
|
||||||
Err(EvalAltResult::ErrorFor(expr.position()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope.rewind(scope.len() - 1);
|
||||||
|
Ok(().into_dynamic())
|
||||||
} else {
|
} else {
|
||||||
Err(EvalAltResult::ErrorFor(expr.position()))
|
Err(EvalAltResult::ErrorFor(expr.position()))
|
||||||
}
|
}
|
||||||
@ -1694,16 +1685,10 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
/// Map a type_name into a pretty-print name
|
/// Map a type_name into a pretty-print name
|
||||||
pub(crate) fn map_type_name<'a>(&'a self, name: &'a str) -> &'a str {
|
pub(crate) fn map_type_name<'a>(&'a self, name: &'a str) -> &'a str {
|
||||||
if self.type_names.is_none() {
|
self.type_names
|
||||||
name
|
.as_ref()
|
||||||
} else {
|
.and_then(|list| list.get(name).map(String::as_str))
|
||||||
self.type_names
|
.unwrap_or(name)
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.get(name)
|
|
||||||
.map(String::as_str)
|
|
||||||
.unwrap_or(name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,16 +663,18 @@ fn optimize<'a>(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, stmt)| {
|
.map(|(i, stmt)| {
|
||||||
if let Stmt::Const(name, value, _) = &stmt {
|
match stmt {
|
||||||
// Load constants
|
Stmt::Const(ref name, ref value, _) => {
|
||||||
state.push_constant(name, value.as_ref().clone());
|
// Load constants
|
||||||
stmt // Keep it in the global scope
|
state.push_constant(name.as_ref(), value.as_ref().clone());
|
||||||
} else {
|
stmt // Keep it in the global scope
|
||||||
// Keep all variable declarations at this level
|
}
|
||||||
// and always keep the last return value
|
_ => {
|
||||||
let keep = matches!(stmt, Stmt::Let(_, _, _)) || i == num_statements - 1;
|
// Keep all variable declarations at this level
|
||||||
|
// and always keep the last return value
|
||||||
optimize_stmt(stmt, &mut state, keep)
|
let keep = matches!(stmt, Stmt::Let(_, _, _)) || i == num_statements - 1;
|
||||||
|
optimize_stmt(stmt, &mut state, keep)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -2192,11 +2192,10 @@ fn parse_binary_op<'a>(
|
|||||||
let mut current_lhs = lhs;
|
let mut current_lhs = lhs;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (current_precedence, bind_right) = if let Some((current_op, _)) = input.peek() {
|
let (current_precedence, bind_right) = input.peek().map_or_else(
|
||||||
(current_op.precedence(), current_op.is_bind_right())
|
|| (0, false),
|
||||||
} else {
|
|(current_op, _)| (current_op.precedence(), current_op.is_bind_right()),
|
||||||
(0, false)
|
);
|
||||||
};
|
|
||||||
|
|
||||||
// Bind left to the parent lhs expression if precedence is higher
|
// Bind left to the parent lhs expression if precedence is higher
|
||||||
// If same precedence, then check if the operator binds right
|
// If same precedence, then check if the operator binds right
|
||||||
|
Loading…
x
Reference in New Issue
Block a user