Skip to content

Commit 2924911

Browse files
committed
add "saturating_sub" in zkDSL (constant expression)
1 parent 85038a5 commit 2924911

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

crates/lean_compiler/src/grammar.pest

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,14 @@ primary = {
9191
"(" ~ expression ~ ")" |
9292
log2_ceil_expr |
9393
next_multiple_of_expr |
94+
saturating_sub_expr |
9495
len_expr |
9596
array_access_expr |
9697
var_or_constant
9798
}
9899
log2_ceil_expr = { "log2_ceil" ~ "(" ~ expression ~ ")" }
99100
next_multiple_of_expr = { "next_multiple_of" ~ "(" ~ expression ~ "," ~ expression ~ ")" }
101+
saturating_sub_expr = { "saturating_sub" ~ "(" ~ expression ~ "," ~ expression ~ ")" }
100102
len_expr = { "len" ~ "(" ~ identifier ~ ")" }
101103
array_access_expr = { identifier ~ "[" ~ expression ~ "]" }
102104

crates/lean_compiler/src/lang.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,13 +257,15 @@ pub enum Expression {
257257
pub enum MathExpr {
258258
Log2Ceil,
259259
NextMultipleOf,
260+
SaturatingSub,
260261
}
261262

262263
impl Display for MathExpr {
263264
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
264265
match self {
265266
Self::Log2Ceil => write!(f, "log2_ceil"),
266267
Self::NextMultipleOf => write!(f, "next_multiple_of"),
268+
Self::SaturatingSub => write!(f, "saturating_sub"),
267269
}
268270
}
269271
}
@@ -273,6 +275,7 @@ impl MathExpr {
273275
match self {
274276
Self::Log2Ceil => 1,
275277
Self::NextMultipleOf => 2,
278+
Self::SaturatingSub => 2,
276279
}
277280
}
278281
pub fn eval(&self, args: &[F]) -> F {
@@ -291,6 +294,10 @@ impl MathExpr {
291294
let res = value_usize.next_multiple_of(multiple_usize);
292295
F::from_usize(res)
293296
}
297+
Self::SaturatingSub => {
298+
assert_eq!(args.len(), 2);
299+
F::from_usize(args[0].to_usize().saturating_sub(args[1].to_usize()))
300+
}
294301
}
295302
}
296303
}

crates/lean_compiler/src/parser/parsers/expression.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ impl Parse<Expression> for PrimaryExpressionParser {
7777
Rule::array_access_expr => ArrayAccessParser.parse(inner, ctx),
7878
Rule::log2_ceil_expr => MathExpr::Log2Ceil.parse(inner, ctx),
7979
Rule::next_multiple_of_expr => MathExpr::NextMultipleOf.parse(inner, ctx),
80+
Rule::saturating_sub_expr => MathExpr::SaturatingSub.parse(inner, ctx),
8081
Rule::len_expr => LenParser.parse(inner, ctx),
8182
_ => Err(SemanticError::new("Invalid primary expression").into()),
8283
}

crates/lean_compiler/tests/test_compiler.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,3 +881,26 @@ fn intertwined_unrolled_loops_and_const_function_arguments() {
881881
"#;
882882
compile_and_run(program.to_string(), (&[], &[]), DEFAULT_NO_VEC_RUNTIME_MEMORY, false);
883883
}
884+
885+
#[test]
886+
fn test_const_fibonacci() {
887+
let program = r#"
888+
fn main() {
889+
res = fib(8);
890+
assert res == 21;
891+
return;
892+
}
893+
fn fib(const n) -> 1 {
894+
if n == 0 {
895+
return 0;
896+
}
897+
if n == 1 {
898+
return 1;
899+
}
900+
a = fib(saturating_sub(n, 1));
901+
b = fib(saturating_sub(n, 2));
902+
return a + b;
903+
}
904+
"#;
905+
compile_and_run(program.to_string(), (&[], &[]), DEFAULT_NO_VEC_RUNTIME_MEMORY, false);
906+
}

0 commit comments

Comments
 (0)