Do not construct function pointer for invalid function names.

This commit is contained in:
Stephen Chung 2021-12-02 12:49:57 +08:00
parent d36e2d22d1
commit 5003d836d9

View File

@ -10,13 +10,14 @@ use crate::func::hashing::get_hasher;
use crate::tokenizer::Token; use crate::tokenizer::Token;
use crate::types::dynamic::AccessMode; use crate::types::dynamic::AccessMode;
use crate::{ use crate::{
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, ImmutableString, calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, Position, Scope,
Position, Scope, StaticVec, AST, StaticVec, AST,
}; };
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
use std::{ use std::{
any::TypeId, any::TypeId,
convert::TryFrom,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
mem, mem,
ops::DerefMut, ops::DerefMut,
@ -902,7 +903,10 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
*expr = mem::take(lhs); *expr = mem::take(lhs);
} }
// lhs && rhs // lhs && rhs
(lhs, rhs) => { optimize_expr(lhs, state, false); optimize_expr(rhs, state, false); } (lhs, rhs) => {
optimize_expr(lhs, state, false);
optimize_expr(rhs, state, false);
}
}, },
// lhs || rhs // lhs || rhs
Expr::Or(ref mut x, _) => match (&mut x.lhs, &mut x.rhs) { Expr::Or(ref mut x, _) => match (&mut x.lhs, &mut x.rhs) {
@ -924,7 +928,10 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
*expr = mem::take(lhs); *expr = mem::take(lhs);
} }
// lhs || rhs // lhs || rhs
(lhs, rhs) => { optimize_expr(lhs, state, false); optimize_expr(rhs, state, false); } (lhs, rhs) => {
optimize_expr(lhs, state, false);
optimize_expr(rhs, state, false);
}
}, },
// eval! // eval!
@ -936,24 +943,20 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
if !x.is_qualified() // Non-qualified if !x.is_qualified() // Non-qualified
&& state.optimization_level == OptimizationLevel::Simple // simple optimizations && state.optimization_level == OptimizationLevel::Simple // simple optimizations
&& x.args.len() == 1 && x.args.len() == 1
&& x.args[0].is_constant()
&& x.name == KEYWORD_FN_PTR && x.name == KEYWORD_FN_PTR
&& x.args[0].is_constant()
=> { => {
let fn_name = match x.args[0] { let fn_name = match x.args[0] {
Expr::Stack(slot, _) => Some(x.constants[slot].clone()), Expr::Stack(slot, _) => x.constants[slot].clone(),
Expr::StringConstant(ref s, _) => Some(s.clone().into()), Expr::StringConstant(ref s, _) => s.clone().into(),
_ => None _ => Dynamic::UNIT
}; };
if let Some(fn_name) = fn_name { if let Ok(fn_ptr) = fn_name.into_immutable_string().map_err(|err| err.into()).and_then(FnPtr::try_from) {
if fn_name.is::<ImmutableString>() { state.set_dirty();
state.set_dirty(); *expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos);
let fn_ptr = FnPtr::new_unchecked( } else {
fn_name.as_str_ref().expect("`ImmutableString`").into(), optimize_expr(&mut x.args[0], state, false);
StaticVec::new_const()
);
*expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos);
}
} }
} }