Skip to content

Commit eecbeec

Browse files
authored
Final Changes for v9 (1BADragon#33)
* Added 3 argument map macro * Some minor updates to macro code to clean it up * Some cleanup in the compiler and interpreter * Update docs
1 parent aac408a commit eecbeec

File tree

6 files changed

+85
-106
lines changed

6 files changed

+85
-106
lines changed

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
[package]
22
name = "rscel"
3-
version = "0.8.0"
3+
version = "0.9.0"
44
edition = "2021"
55
description = "Cel interpreter in rust"
66
license = "MIT"
77

88
[lib]
99
crate-type = ["cdylib", "rlib"]
1010

11+
[profile.release-with-debug]
12+
inherits = "release"
13+
debug = true
14+
1115
[features]
1216
default = ["type_prop"]
1317
ast_ser = []

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@ let mut ctx = CelContext::new();
2222
let mut exec_ctx = BindContext::new();
2323

2424
ctx.add_program_str("main", "foo + 3").unwrap();
25-
exec_ctx.bind_param("foo", 3.into()); // convert to serde_json::Value
25+
exec_ctx.bind_param("foo", 3.into()); // convert to CelValue
2626

27-
let res = ctx.exec("main", &exec_ctx).unwrap(); // ValueCell::Int(6)
27+
let res = ctx.exec("main", &exec_ctx).unwrap(); // CelValue::Int(6)
2828
assert!(TryInto::<i64>::try_into(res).unwrap() == 6);
2929
```
3030

3131
## Current Benchmark Times
3232
| Bench Run | Time |
3333
|--------------------------|----------------|
34-
|Run One No Binding: | 0.000310S |
35-
|Run Many No Binding: | 0.003657S |
36-
|Run One With Binding: | 0.000033S |
37-
|Run Many With Bindings: | 0.004281S |
38-
|Build Many: | 0.002312S |
39-
|Build Many With Bindings: | 0.051369S |
34+
|Run One No Binding | 0.000070054S |
35+
|Run Many No Binding | 0.003451698S |
36+
|Run One With Binding | 0.000015177S |
37+
|Run Many With Bindings | 0.004443471S |
38+
|Build Many | 0.006989954S |
39+
|Build Many With Bindings | 0.084859163S |
4040

4141
Build status: [![Rust](https://github.com/1BADragon/rscel/actions/workflows/rust.yml/badge.svg)](https://github.com/1BADragon/rscel/actions/workflows/rust.yml)

src/compiler/compiler.rs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,6 @@ impl<'l> CelCompiler<'l> {
2424

2525
let prog = res.into_program(self.tokenizer.source().to_string(), ast);
2626

27-
#[cfg(feature = "debug_output")]
28-
{
29-
println!(
30-
"Built program:\n{}",
31-
serde_json::to_string_pretty(&prog).unwrap()
32-
);
33-
}
34-
3527
Ok(prog)
3628
}
3729

@@ -270,7 +262,7 @@ impl<'l> CelCompiler<'l> {
270262
}
271263
}
272264

273-
return Ok((current_node, current_ast));
265+
Ok((current_node, current_ast))
274266
}
275267

276268
fn parse_addition(&mut self) -> CelResult<(ParseResult, AstNode<Addition>)> {
@@ -387,7 +379,7 @@ impl<'l> CelCompiler<'l> {
387379
}
388380
}
389381

390-
return Ok((current_node, current_ast));
382+
Ok((current_node, current_ast))
391383
}
392384

393385
fn parse_unary(&mut self) -> CelResult<(ParseResult, AstNode<Unary>)> {
@@ -552,12 +544,12 @@ impl<'l> CelCompiler<'l> {
552544

553545
let token = self.tokenizer.next()?;
554546
if token != Some(Token::RParen) {
555-
return Err(SyntaxError::from_location(self.tokenizer.location())
547+
Err(SyntaxError::from_location(self.tokenizer.location())
556548
.with_message(format!(
557549
"Unexpected token {}, expected RPARAN",
558550
&token.map_or("NOTHING".to_string(), |x| format!("{:?}", x))
559551
))
560-
.into());
552+
.into())
561553
} else {
562554
let (child, child_ast) = self.parse_member_prime()?;
563555
Ok((
@@ -599,14 +591,12 @@ impl<'l> CelCompiler<'l> {
599591
),
600592
))
601593
}
602-
_ => {
603-
return Err(SyntaxError::from_location(self.tokenizer.location())
604-
.with_message(format!(
605-
"Unexpected token {}, expected RPARAN",
606-
&next_token.map_or("NOTHING".to_string(), |x| format!("{:?}", x))
607-
))
608-
.into())
609-
}
594+
_ => Err(SyntaxError::from_location(self.tokenizer.location())
595+
.with_message(format!(
596+
"Unexpected token {}, expected RPARAN",
597+
&next_token.map_or("NOTHING".to_string(), |x| format!("{:?}", x))
598+
))
599+
.into()),
610600
}
611601
}
612602
_ => Ok((

src/context/default_macros.rs

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,7 @@ fn all_impl(ctx: &Interpreter, this: CelValue, bytecode: &[&[ByteCode]]) -> CelR
4646
));
4747
}
4848

49-
let ident_prog = ctx.run_raw(bytecode[0], false)?;
50-
let ident_name = if let CelValue::Ident(ident) = ident_prog {
51-
ident
52-
} else {
53-
return Err(CelError::argument("all() predicate must be ident"));
54-
};
55-
49+
let ident_name = eval_ident(bytecode[0])?;
5650
if let CelValue::List(list) = this {
5751
let cel = ctx.cel_copy().unwrap_or_else(|| CelContext::new());
5852
let mut bindings = ctx.bindings_copy().unwrap_or_else(|| BindContext::new());
@@ -64,14 +58,12 @@ fn all_impl(ctx: &Interpreter, this: CelValue, bytecode: &[&[ByteCode]]) -> CelR
6458

6559
let res = interp.run_raw(bytecode[1], true)?;
6660

67-
if let CelValue::Bool(b) = res {
68-
if !b {
69-
return Ok(false.into());
70-
}
61+
if !res.is_truthy() {
62+
return Ok(false.into());
7163
}
7264
}
7365

74-
return Ok(true.into());
66+
Ok(true.into())
7567
} else {
7668
Err(CelError::value("all() only available on list"))
7769
}
@@ -85,7 +77,6 @@ fn exists_impl(ctx: &Interpreter, this: CelValue, bytecode: &[&[ByteCode]]) -> C
8577
}
8678

8779
let ident_name = eval_ident(bytecode[0])?;
88-
8980
if let CelValue::List(list) = this {
9081
let cel = ctx.cel_copy().unwrap_or_else(|| CelContext::new());
9182
let mut bindings = ctx.bindings_copy().unwrap_or_else(|| BindContext::new());
@@ -96,14 +87,12 @@ fn exists_impl(ctx: &Interpreter, this: CelValue, bytecode: &[&[ByteCode]]) -> C
9687

9788
let res = interp.run_raw(bytecode[1], true)?;
9889

99-
if let CelValue::Bool(b) = res {
100-
if b {
101-
return Ok(true.into());
102-
}
90+
if res.is_truthy() {
91+
return Ok(true.into());
10392
}
10493
}
10594

106-
return Ok(false.into());
95+
Ok(false.into())
10796
} else {
10897
Err(CelError::value("exists() only available on list"))
10998
}
@@ -133,18 +122,16 @@ fn exists_one_impl(
133122

134123
let res = interp.run_raw(bytecode[1], true)?;
135124

136-
if let CelValue::Bool(b) = res {
137-
if b {
138-
count += 1;
125+
if res.is_truthy() {
126+
count += 1;
139127

140-
if count > 1 {
141-
return Ok(false.into());
142-
}
128+
if count > 1 {
129+
return Ok(false.into());
143130
}
144131
}
145132
}
146133

147-
return Ok((count == 1).into());
134+
Ok((count == 1).into())
148135
} else {
149136
Err(CelError::value("exists_one() only available on list"))
150137
}
@@ -169,10 +156,8 @@ fn filter_impl(ctx: &Interpreter, this: CelValue, bytecode: &[&[ByteCode]]) -> C
169156
bindings.bind_param(&ident_name, v.clone());
170157
let interp = Interpreter::new(&cel, &bindings);
171158

172-
if let CelValue::Bool(b) = interp.run_raw(bytecode[1], true)? {
173-
if b {
174-
filtered_list.push(v.clone());
175-
}
159+
if interp.run_raw(bytecode[1], true)?.is_truthy() {
160+
filtered_list.push(v.clone());
176161
}
177162
}
178163
Ok(filtered_list.into())
@@ -193,21 +178,19 @@ fn map_impl(ctx: &Interpreter, this: CelValue, bytecode: &[&[ByteCode]]) -> CelR
193178
if let CelValue::List(list) = this {
194179
let mut mapped_list: Vec<CelValue> = Vec::new();
195180
let cel = ctx.cel_copy().unwrap_or_else(|| CelContext::new());
181+
// make a copy of the context to make borrow checker happy
196182
let mut bindings = ctx.bindings_copy().unwrap_or_else(|| BindContext::new());
197183

198184
// optimize so we are only checking bytecode's len once
199185
if bytecode.len() == 2 {
200186
for v in list.into_iter() {
201-
// make a copy of the context to make borrow checker happy
202187
bindings.bind_param(&ident_name, v.clone());
203188
let interp = Interpreter::new(&cel, &bindings);
204189

205-
// bytecode.len() should either be 2 or 3 at this point
206190
mapped_list.push(interp.run_raw(bytecode[1], true)?);
207191
}
208192
} else if bytecode.len() == 3 {
209193
for v in list.into_iter() {
210-
// make a copy of the context to make borrow checker happy
211194
bindings.bind_param(&ident_name, v.clone());
212195
let interp = Interpreter::new(&cel, &bindings);
213196

src/interp/mod.rs

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,16 @@ impl<'a, 'b> InterpStack<'a, 'b> {
4040
if let CelValue::Ident(name) = val {
4141
if let Some(val) = self.ctx.get_param_by_name(&name) {
4242
return Ok(CelStackValue::Value(val.clone()));
43-
} else if let Some(ctx) = self.ctx.cel {
43+
}
44+
45+
if let Some(ctx) = self.ctx.cel {
4446
// Allow for loaded programs to run as values
4547
if let Some(prog) = ctx.get_program(&name) {
4648
return self.ctx.run_raw(prog.bytecode(), true).map(|x| x.into());
4749
}
4850
}
4951

50-
return Err(CelError::binding(&name));
52+
Err(CelError::binding(&name))
5153
} else {
5254
Ok(val.into())
5355
}
@@ -205,6 +207,48 @@ impl<'a> Interpreter<'a> {
205207

206208
stack.push_val((v1 % v2)?);
207209
}
210+
ByteCode::Lt => {
211+
let v2 = stack.pop_val()?;
212+
let v1 = stack.pop_val()?;
213+
214+
stack.push_val(v1.lt(&v2)?);
215+
}
216+
ByteCode::Le => {
217+
let v2 = stack.pop_val()?;
218+
let v1 = stack.pop_val()?;
219+
220+
stack.push_val(v1.le(&v2)?);
221+
}
222+
ByteCode::Eq => {
223+
let v2 = stack.pop_val()?;
224+
let v1 = stack.pop_val()?;
225+
226+
stack.push_val(v1.eq(&v2)?);
227+
}
228+
ByteCode::Ne => {
229+
let v2 = stack.pop_val()?;
230+
let v1 = stack.pop_val()?;
231+
232+
stack.push_val(v1.neq(&v2)?);
233+
}
234+
ByteCode::Ge => {
235+
let v2 = stack.pop_val()?;
236+
let v1 = stack.pop_val()?;
237+
238+
stack.push_val(v1.ge(&v2)?);
239+
}
240+
ByteCode::Gt => {
241+
let v2 = stack.pop_val()?;
242+
let v1 = stack.pop_val()?;
243+
244+
stack.push_val(v1.gt(&v2)?);
245+
}
246+
ByteCode::In => {
247+
let rhs = stack.pop_val()?;
248+
let lhs = stack.pop_val()?;
249+
250+
stack.push_val(lhs.in_(&rhs)?);
251+
}
208252
ByteCode::Jmp(dist) => pc = pc + *dist as usize,
209253
ByteCode::JmpCond {
210254
when,
@@ -252,48 +296,6 @@ impl<'a> Interpreter<'a> {
252296
stack.push_val(v1);
253297
}
254298
}
255-
ByteCode::Lt => {
256-
let v2 = stack.pop_val()?;
257-
let v1 = stack.pop_val()?;
258-
259-
stack.push_val(v1.lt(&v2)?);
260-
}
261-
ByteCode::Le => {
262-
let v2 = stack.pop_val()?;
263-
let v1 = stack.pop_val()?;
264-
265-
stack.push_val(v1.le(&v2)?);
266-
}
267-
ByteCode::Eq => {
268-
let v2 = stack.pop_val()?;
269-
let v1 = stack.pop_val()?;
270-
271-
stack.push_val(v1.eq(&v2)?);
272-
}
273-
ByteCode::Ne => {
274-
let v2 = stack.pop_val()?;
275-
let v1 = stack.pop_val()?;
276-
277-
stack.push_val(v1.neq(&v2)?);
278-
}
279-
ByteCode::Ge => {
280-
let v2 = stack.pop_val()?;
281-
let v1 = stack.pop_val()?;
282-
283-
stack.push_val(v1.ge(&v2)?);
284-
}
285-
ByteCode::Gt => {
286-
let v2 = stack.pop_val()?;
287-
let v1 = stack.pop_val()?;
288-
289-
stack.push_val(v1.gt(&v2)?);
290-
}
291-
ByteCode::In => {
292-
let rhs = stack.pop_val()?;
293-
let lhs = stack.pop_val()?;
294-
295-
stack.push_val(lhs.in_(&rhs)?);
296-
}
297299
ByteCode::MkList(size) => {
298300
let mut v = Vec::new();
299301

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
//! ctx.add_program_str("main", "foo + 3").unwrap();
2323
//! exec_ctx.bind_param("foo", 3.into()); // 3 converted to CelValue
2424
//!
25-
//! let res = ctx.exec("main", &exec_ctx).unwrap(); // ValueCell::Int(6)
25+
//! let res = ctx.exec("main", &exec_ctx).unwrap(); // CelValue::Int(6)
2626
//! assert!(TryInto::<i64>::try_into(res).unwrap() == 6);
2727
//! ```
2828

0 commit comments

Comments
 (0)