Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bench #22

Merged
merged 4 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
570 changes: 568 additions & 2 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ once_cell = "1.18.0"

[dev-dependencies]
rstest = "0.18.2"
criterion = {version="0.5.1", features=["html_reports"]}

[[bench]]
name = "execute_expression"
harness = false
26 changes: 26 additions & 0 deletions benches/execute_expression.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use criterion::{criterion_group, criterion_main, Criterion};
use expression_engine::{create_context, execute, parse_expression, Value};

fn bench_execute_expression(c: &mut Criterion) {
let input = "c = 5+3; c+=10+f; c";
c.bench_function("execute_expression", |b| {
b.iter(|| {
execute(
input,
create_context!(
"d" => 2,
"b" => true,
"f" => Arc::new(|_| Ok(Value::from(3)))
),
)
})
});
}

fn bench_parse_expression(c: &mut Criterion) {
let input = "c = 5+3; c+=10+f; c";
c.bench_function("parse_expression", |b| b.iter(|| parse_expression(input)));
}

criterion_group!(benches, bench_execute_expression, bench_parse_expression);
criterion_main!(benches);
20 changes: 8 additions & 12 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,27 @@ impl Context {
}

pub fn set_func(&mut self, name: &str, func: Arc<InnerFunction>) {
self.0
.lock()
.unwrap()
.insert(name.to_string(), ContextValue::Function(func.clone()));
self.set(name, ContextValue::Function(func.clone()));
}

pub fn set_variable(&mut self, name: &str, value: Value) {
self.0
.lock()
.unwrap()
.insert(name.to_string(), ContextValue::Variable(value));
self.set(name, ContextValue::Variable(value));
}

pub fn set(&mut self, name: &str, v: ContextValue) {
self.0.lock().unwrap().insert(name.to_string(), v);
}

pub fn get_func(&self, name: &str) -> Option<Arc<InnerFunction>> {
let binding = self.0.lock().unwrap();
let value = binding.get(name)?;
let value = self.get(name)?;
match value {
ContextValue::Function(func) => Some(func.clone()),
ContextValue::Variable(_) => None,
}
}

pub fn get_variable(&self, name: &str) -> Option<Value> {
let binding = self.0.lock().unwrap();
let value = binding.get(name)?;
let value = self.get(name)?;
match value {
ContextValue::Variable(v) => Some(v.clone()),
ContextValue::Function(_) => None,
Expand Down
27 changes: 9 additions & 18 deletions src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ impl DescriptorManager {
pub fn set_unary_descriptor(&mut self, op: String, descriptor: Arc<UnaryDescriptor>) {
let key = DescriptorKey::UNARY(op);
let value = Descriptor::UNARY(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_unary_descriptor(&self, op: String) -> Arc<UnaryDescriptor> {
Expand All @@ -85,8 +84,7 @@ impl DescriptorManager {
pub fn set_binary_descriptor(&mut self, op: String, descriptor: Arc<BinaryDescriptor>) {
let key = DescriptorKey::BINARY(op);
let value = Descriptor::BINARY(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_binary_descriptor(&self, op: String) -> Arc<BinaryDescriptor> {
Expand All @@ -104,8 +102,7 @@ impl DescriptorManager {
pub fn set_postfix_descriptor(&mut self, op: String, descriptor: Arc<UnaryDescriptor>) {
let key = DescriptorKey::POSTFIX(op);
let value = Descriptor::POSTFIX(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_postfix_descriptor(&self, op: String) -> Arc<UnaryDescriptor> {
Expand All @@ -123,8 +120,7 @@ impl DescriptorManager {
pub fn set_ternary_descriptor(&mut self, descriptor: Arc<TernaryDescriptor>) {
let key = DescriptorKey::TERNARY;
let value = Descriptor::TERNARY(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_ternary_descriptor(&self) -> Arc<TernaryDescriptor> {
Expand All @@ -142,8 +138,7 @@ impl DescriptorManager {
pub fn set_function_descriptor(&mut self, name: String, descriptor: Arc<FunctionDescriptor>) {
let key = DescriptorKey::FUNCTION(name);
let value = Descriptor::FUNCTION(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_function_descriptor(&self, name: String) -> Arc<FunctionDescriptor> {
Expand All @@ -161,8 +156,7 @@ impl DescriptorManager {
pub fn set_reference_descriptor(&mut self, name: String, descriptor: Arc<ReferenceDescriptor>) {
let key = DescriptorKey::REFERENCE(name);
let value = Descriptor::REFERENCE(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_reference_descriptor(&self, name: String) -> Arc<ReferenceDescriptor> {
Expand All @@ -180,8 +174,7 @@ impl DescriptorManager {
pub fn set_list_descriptor(&mut self, descriptor: Arc<ListDescriptor>) {
let key = DescriptorKey::LIST;
let value = Descriptor::LIST(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_list_descriptor(&self) -> Arc<ListDescriptor> {
Expand All @@ -199,8 +192,7 @@ impl DescriptorManager {
pub fn set_map_descriptor(&mut self, descriptor: Arc<MapDescriptor>) {
let key = DescriptorKey::MAP;
let value = Descriptor::MAP(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_map_descriptor(&self) -> Arc<MapDescriptor> {
Expand All @@ -218,8 +210,7 @@ impl DescriptorManager {
pub fn set_chain_descriptor(&mut self, descriptor: Arc<ChainDescriptor>) {
let key = DescriptorKey::CHAIN;
let value = Descriptor::CHAIN(descriptor);
let mut binding = self.store.lock().unwrap();
binding.insert(key, value);
self.set(key, value)
}

pub fn get_chain_descriptor(&self) -> Arc<ChainDescriptor> {
Expand Down
12 changes: 8 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,20 @@ mod init;
/// let ans = execute(input, ctx).unwrap();
/// assert_eq!(ans, Value::from(21))
/// ```
pub fn execute(expr: &str, mut ctx: context::Context) -> define::Result<value::Value> {
pub fn execute(expr: &str, mut ctx: context::Context) -> Result<Value> {
parse_expression(expr)?.exec(&mut ctx)
}

pub fn parse_expression(expr: &str) -> Result<ExprAST> {
use crate::init::init;
init();
parser::Parser::new(expr)?
.parse_chain_expression()?
.exec(&mut ctx)
parser::Parser::new(expr)?.parse_stmt()
}

pub type Value = value::Value;
pub type Context = context::Context;
pub type Result<T> = define::Result<T>;
pub type ExprAST<'a> = parser::ExprAST<'a>;

#[test]
fn test_exec() {
Expand Down
39 changes: 29 additions & 10 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub enum ExprAST<'a> {
Function(&'a str, Vec<ExprAST<'a>>),
List(Vec<ExprAST<'a>>),
Map(Vec<(ExprAST<'a>, ExprAST<'a>)>),
Chain(Vec<ExprAST<'a>>),
Stmt(Vec<ExprAST<'a>>),
None,
}

Expand Down Expand Up @@ -93,7 +93,7 @@ impl<'a> fmt::Display for ExprAST<'a> {
}
write!(f, "Map AST: {}", s)
}
Self::Chain(exprs) => {
Self::Stmt(exprs) => {
let mut s = String::new();
for expr in exprs {
s.push_str(format!("{};", expr.clone()).as_str());
Expand All @@ -117,7 +117,7 @@ impl<'a> ExprAST<'a> {
Postfix(lhs, op) => self.exec_postfix(lhs, op.clone(), ctx),
Ternary(condition, lhs, rhs) => self.exec_ternary(condition, lhs, rhs, ctx),
List(params) => self.exec_list(params.clone(), ctx),
Chain(exprs) => self.exec_chain(exprs.clone(), ctx),
Stmt(exprs) => self.exec_chain(exprs.clone(), ctx),
Map(m) => self.exec_map(m.clone(), ctx),
None => Ok(Value::None),
}
Expand Down Expand Up @@ -252,7 +252,7 @@ impl<'a> ExprAST<'a> {
Self::Ternary(condition, lhs, rhs) => self.ternary_expr(condition, lhs, rhs),
Self::List(params) => self.list_expr(params.clone()),
Self::Map(m) => self.map_expr(m.clone()),
Self::Chain(exprs) => self.chain_expr(exprs.clone()),
Self::Stmt(exprs) => self.chain_expr(exprs.clone()),
Self::None => "".to_string(),
}
}
Expand Down Expand Up @@ -396,7 +396,7 @@ impl<'a> ExprAST<'a> {
.get_reference_descriptor(name.to_string())(
name.to_string()
),
Self::Chain(values) => DescriptorManager::new().get_chain_descriptor()(
Self::Stmt(values) => DescriptorManager::new().get_chain_descriptor()(
values.into_iter().map(|v| v.describe()).collect(),
),
Self::Ternary(condition, lhs, rhs) => {
Expand Down Expand Up @@ -467,7 +467,7 @@ impl<'a> Parser<'a> {
}
}

pub fn parse_chain_expression(&mut self) -> Result<ExprAST<'a>> {
pub fn parse_stmt(&mut self) -> Result<ExprAST<'a>> {
let mut ans = Vec::new();
loop {
if self.is_eof() {
Expand All @@ -481,7 +481,7 @@ impl<'a> Parser<'a> {
if ans.len() == 1 {
return Ok(ans[0].clone());
}
Ok(ExprAST::Chain(ans))
Ok(ExprAST::Stmt(ans))
}

pub fn parse_expression(&mut self) -> Result<ExprAST<'a>> {
Expand Down Expand Up @@ -781,6 +781,25 @@ mod tests {
assert!(expr_ast.is_err());
}

#[rstest]
#[case("+true")]
#[case("- 'hha'")]
#[case("! 'haha'")]
#[case("fasle ++")]
#[case("'haha' --")]
fn test_execute_error(#[case] input: &str) {
init();
let parser = Parser::new(input);
assert!(parser.is_ok());
let expr_ast = parser.unwrap().parse_expression();
assert!(expr_ast.is_ok());
let mut ctx = create_context!(
"d" => 3,
"f" => Arc::new(|_| Ok(Value::from(3)))
);
assert!(expr_ast.unwrap().exec(&mut ctx).is_err())
}

#[rstest]
#[case(
"
Expand All @@ -789,7 +808,7 @@ mod tests {
b=a+5;
[a,b]
",
ExprAST::Chain(
ExprAST::Stmt(
vec![
ExprAST::Binary(
"=",
Expand Down Expand Up @@ -853,7 +872,7 @@ mod tests {
init();
let parser = Parser::new(input);
assert!(parser.is_ok());
let expr_ast = parser.unwrap().parse_chain_expression();
let expr_ast = parser.unwrap().parse_stmt();
assert!(expr_ast.is_ok());
assert_eq!(expr_ast.unwrap(), output);
}
Expand Down Expand Up @@ -954,7 +973,7 @@ mod tests {
InnerFunctionManager::new().register("d", Arc::new(|_| Ok(4.into())));
let parser = Parser::new(input);
assert!(parser.is_ok());
let expr_ast = parser.unwrap().parse_chain_expression();
let expr_ast = parser.unwrap().parse_stmt();
assert!(expr_ast.is_ok());
let ast = expr_ast.unwrap();
let ans = ast.clone().exec(&mut ctx);
Expand Down
26 changes: 25 additions & 1 deletion src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ impl<'input> fmt::Display for Token<'input> {

#[cfg(test)]
mod tests {
use super::DelimTokenType;
use super::{DelimTokenType, Span, Token};
use rstest::rstest;

#[rstest]
Expand All @@ -247,4 +247,28 @@ mod tests {
fn test_delim_token_type_from_char(#[case] input: char, #[case] output: DelimTokenType) {
assert_eq!(DelimTokenType::from(input), output)
}

#[rstest]
#[case(Token::Delim(DelimTokenType::OpenParen, Span(0, 0)), true)]
#[case(Token::Delim(DelimTokenType::CloseParen, Span(0, 0)), false)]
#[case(Token::Bool(false, Span(0, 0)), false)]
fn test_is_open_paren(#[case] input: Token, #[case] output: bool) {
assert_eq!(input.is_open_paren(), output)
}

#[rstest]
#[case(Token::Delim(DelimTokenType::OpenBrace, Span(0, 0)), true)]
#[case(Token::Delim(DelimTokenType::CloseBrace, Span(0, 0)), false)]
#[case(Token::Bool(false, Span(0, 0)), false)]
fn test_is_open_brace(#[case] input: Token, #[case] output: bool) {
assert_eq!(input.is_open_brace(), output)
}

#[rstest]
#[case(Token::Delim(DelimTokenType::OpenBracket, Span(0, 0)), true)]
#[case(Token::Delim(DelimTokenType::CloseBracket, Span(0, 0)), false)]
#[case(Token::Bool(false, Span(0, 0)), false)]
fn test_is_open_bracket(#[case] input: Token, #[case] output: bool) {
assert_eq!(input.is_open_bracket(), output)
}
}
Loading