Skip to content

Commit

Permalink
Merge pull request #225 from bufferhe4d/plusequal
Browse files Browse the repository at this point in the history
Add += functionality
  • Loading branch information
katat authored Nov 13, 2024
2 parents 8c0ca9d + 7b21812 commit b17ea20
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 20 deletions.
2 changes: 1 addition & 1 deletion examples/assignment.no
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn main(pub xx: Field) {
};

// ideally: thing.xx += 1;
thing.xx = thing.xx + 1;
thing.xx += 1;

try_to_mutate(thing);

Expand Down
16 changes: 16 additions & 0 deletions examples/augmented_assign.no
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
fn main(pub xx: Field, yy: Field) -> Field {
let mut zz = xx + yy;
let mut zz2 = xx + yy;

zz += 1;
zz2 = zz2 + 1;

zz *= zz;
zz2 = zz2 * zz2;

zz -= yy;
zz2 = zz2 - yy;
assert_eq(zz, zz2);

return zz;
}
30 changes: 30 additions & 0 deletions examples/fixture/asm/kimchi/augmented_assign.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@ noname.0.7.0
@ public inputs: 2

DoubleGeneric<1>
DoubleGeneric<1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<1,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,-1>
DoubleGeneric<1,-1>
(0,0) -> (13,0)
(1,0) -> (2,0) -> (3,0)
(2,1) -> (3,1) -> (8,0) -> (10,0)
(2,2) -> (4,0)
(3,2) -> (5,0)
(4,2) -> (6,0) -> (6,1)
(5,2) -> (7,0) -> (7,1)
(6,2) -> (9,0)
(7,2) -> (11,0)
(8,1) -> (9,1)
(9,2) -> (12,0) -> (13,1)
(10,1) -> (11,1)
(11,2) -> (12,1)
7 changes: 7 additions & 0 deletions examples/fixture/asm/r1cs/augmented_assign.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@ noname.0.7.0
@ public inputs: 2

v_4 == (v_2 + v_3 + 1) * (v_2 + v_3 + 1)
v_5 == (v_2 + v_3 + 1) * (v_2 + v_3 + 1)
-1 * v_3 + v_5 == (-1 * v_3 + v_4) * (1)
-1 * v_3 + v_4 == (v_1) * (1)
2 changes: 1 addition & 1 deletion examples/iterate.no
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn House.windows(house: House) -> Field {
let mut windows_count = 0;
for room in house.rooms {
// ideally: windows +=
windows_count = windows_count + room.windows();
windows_count += room.windows();
}

return windows_count;
Expand Down
39 changes: 32 additions & 7 deletions src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ pub enum TokenKind {
DoublePipe, // ||
Exclamation, // !
Question, // ?
PlusEqual, // +=
MinusEqual, // -=
StarEqual, // *=
// Literal, // "thing"
}

Expand Down Expand Up @@ -199,6 +202,9 @@ impl Display for TokenKind {
DoublePipe => "`||`",
Exclamation => "`!`",
Question => "`?`",
PlusEqual => "`+=`",
MinusEqual => "`-=`",
StarEqual => "`*=`",
// TokenType::Literal => "`\"something\"",
};

Expand Down Expand Up @@ -387,19 +393,38 @@ impl Token {
}
}
'+' => {
tokens.push(TokenKind::Plus.new_token(ctx, 1));
}
'-' => {
let next_c = chars.peek();
if matches!(next_c, Some(&'>')) {
tokens.push(TokenKind::RightArrow.new_token(ctx, 2));
if matches!(next_c, Some(&'=')) {
tokens.push(TokenKind::PlusEqual.new_token(ctx, 2));
chars.next();
} else {
tokens.push(TokenKind::Minus.new_token(ctx, 1));
tokens.push(TokenKind::Plus.new_token(ctx, 1));
}
}
'-' => {
let next_c = chars.peek();
match next_c {
Some(&'>') => {
tokens.push(TokenKind::RightArrow.new_token(ctx, 2));
chars.next();
}
Some(&'=') => {
tokens.push(TokenKind::MinusEqual.new_token(ctx, 2));
chars.next();
}
_ => {
tokens.push(TokenKind::Minus.new_token(ctx, 1));
}
}
}
'*' => {
tokens.push(TokenKind::Star.new_token(ctx, 1));
let next_c = chars.peek();
if matches!(next_c, Some(&'=')) {
tokens.push(TokenKind::StarEqual.new_token(ctx, 2));
chars.next();
} else {
tokens.push(TokenKind::Star.new_token(ctx, 1));
}
}
'&' => {
let next_c = chars.peek();
Expand Down
62 changes: 51 additions & 11 deletions src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,12 +428,17 @@ impl Expr {
// the expression `self` we just parsed.
// warning: ALL of the rules here should make use of `self`.
let lhs = match tokens.peek() {
// assignment
// assignment or augmented assignment
// lhs = rhs | lhs += rhs | lhs -= rhs | lhs *= rhs
Some(Token {
kind: TokenKind::Equal,
kind:
TokenKind::Equal
| TokenKind::PlusEqual
| TokenKind::MinusEqual
| TokenKind::StarEqual,
span,
}) => {
tokens.bump(ctx); // =
let token = tokens.bump(ctx).unwrap();

// sanitize
if !matches!(
Expand All @@ -451,14 +456,49 @@ impl Expr {
let rhs = Expr::parse(ctx, tokens)?;
let span = self.span.merge_with(rhs.span);

Expr::new(
ctx,
ExprKind::Assignment {
lhs: Box::new(self),
rhs: Box::new(rhs),
},
span,
)
match token.kind {
// regular assignment
TokenKind::Equal => Expr::new(
ctx,
ExprKind::Assignment {
lhs: Box::new(self),
rhs: Box::new(rhs),
},
span,
),
// augmented assignments
TokenKind::PlusEqual | TokenKind::MinusEqual | TokenKind::StarEqual => {
let op = match token.kind {
TokenKind::PlusEqual => Op2::Addition,
TokenKind::MinusEqual => Op2::Subtraction,
TokenKind::StarEqual => Op2::Multiplication,
_ => unreachable!(),
};

// create the binary operation: lhs <op> rhs
let binary_op = Expr::new(
ctx,
ExprKind::BinaryOp {
op,
lhs: Box::new(self.clone()),
rhs: Box::new(rhs),
protected: false,
},
span,
);

// create the assignment with rhs obtained above: lhs = (binary_op)
Expr::new(
ctx,
ExprKind::Assignment {
lhs: Box::new(self),
rhs: Box::new(binary_op),
},
span,
)
}
_ => unreachable!(),
}
}

// binary operation
Expand Down
19 changes: 19 additions & 0 deletions src/tests/examples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,25 @@ fn test_assignment(#[case] backend: BackendKind) -> miette::Result<()> {
Ok(())
}

#[rstest]
#[case::kimchi_vesta(BackendKind::KimchiVesta(KimchiVesta::new(false)))]
#[case::r1cs(BackendKind::R1csBls12_381(R1CS::new()))]
fn test_augmented_assign(#[case] backend: BackendKind) -> miette::Result<()> {
let private_inputs = r#"{"yy": "2"}"#;
let public_inputs = r#"{"xx": "3"}"#;
let expected_public_output = vec!["34"];

test_file(
"augmented_assign",
public_inputs,
private_inputs,
expected_public_output,
backend,
)?;

Ok(())
}

#[rstest]
#[case::kimchi_vesta(BackendKind::KimchiVesta(KimchiVesta::new(false)))]
#[case::r1cs(BackendKind::R1csBls12_381(R1CS::new()))]
Expand Down

0 comments on commit b17ea20

Please sign in to comment.