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

Builtin operators #197

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions examples/arithmetic.no
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ fn main(pub public_input: Field, private_input: Field) {
let div_var_res = xx / private_input;
assert_eq(div_res, 2);

// left shift
let lf_res = xx << 2;
assert_eq(lf_res, 16);
}
1 change: 1 addition & 0 deletions src/circuit_writer/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ impl<B: Backend> CircuitWriter<B> {
// todo: refactor the input vars from Var to VarInfo,
// which contain the type to provide the info about the bit length
Op2::LessThan => field::less_than(self, None, &lhs[0], &rhs[0], expr.span),
Op2::LeftShift => field::left_shift(self, &lhs[0], &rhs[0], expr.span),
Op2::BoolAnd => boolean::and(self, &lhs[0], &rhs[0], expr.span),
Op2::BoolOr => boolean::or(self, &lhs[0], &rhs[0], expr.span),
};
Expand Down
27 changes: 27 additions & 0 deletions src/constraints/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,33 @@ pub fn modulus<B: Backend>(
}
}

/// Left shift operation
pub fn left_shift<B: Backend>(
compiler: &mut CircuitWriter<B>,
lhs: &ConstOrCell<B::Field, B::Var>,
rhs: &ConstOrCell<B::Field, B::Var>,
span: Span,
) -> Var<B::Field, B::Var> {
// to constrain lhs * (1 << rhs) = res

match (lhs, rhs) {
(ConstOrCell::Const(lhs), ConstOrCell::Const(rhs)) => {
// convert to bigint
let pow2 = B::Field::from(2u32).pow(rhs.into_repr());
let res = *lhs * pow2;
Var::new_constant(res, span)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should return an error on overflow perhaps

}
(ConstOrCell::Cell(lhs_), ConstOrCell::Const(rhs_)) => {
let pow2 = B::Field::from(2u32).pow(rhs_.into_repr());
let res = compiler.backend.mul_const(lhs_, &pow2, span);
Var::new_var(res, span)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The weird thing to me is that at this point there is no way to tell if there is an overflow, the modulus length also impacts that. Maybe that's fine though... But I'm not sure what people would expect. Is this operator implemented in any other DSL? How do they handle overflows?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, overflow is probably something to take care of here.

One of the compilers restricts the value type to be integer and the shift amount to be u8. I guess the reason it restrict to be integer is for range checking the resulted value.

}
// todo: wrap rhs in a symbolic value
(ConstOrCell::Const(_), ConstOrCell::Cell(_)) => todo!(),
(ConstOrCell::Cell(_), ConstOrCell::Cell(_)) => todo!(),
}
}

/// This takes variables that can be anything, and returns a boolean
// TODO: so perhaps it's not really relevant in this file?
pub fn equal<B: Backend>(
Expand Down
20 changes: 18 additions & 2 deletions src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ pub enum TokenKind {
DoubleAmpersand, // &&
Pipe, // |
DoublePipe, // ||
LeftShift, // <<
RightShift, // >>
Exclamation, // !
Question, // ?
// Literal, // "thing"
Expand Down Expand Up @@ -192,6 +194,8 @@ impl Display for TokenKind {
DoublePipe => "`||`",
Exclamation => "`!`",
Question => "`?`",
LeftShift => "`<<`",
RightShift => "`>>`",
// TokenType::Literal => "`\"something\"",
};

Expand Down Expand Up @@ -365,10 +369,22 @@ impl Token {
}
}
'>' => {
tokens.push(TokenKind::Greater.new_token(ctx, 1));
let next_c = chars.peek();
if matches!(next_c, Some(&'>')) {
tokens.push(TokenKind::RightShift.new_token(ctx, 2));
chars.next();
} else {
tokens.push(TokenKind::Greater.new_token(ctx, 1));
}
}
'<' => {
tokens.push(TokenKind::Less.new_token(ctx, 1));
let next_c = chars.peek();
if matches!(next_c, Some(&'<')) {
tokens.push(TokenKind::LeftShift.new_token(ctx, 2));
chars.next();
} else {
tokens.push(TokenKind::Less.new_token(ctx, 1));
}
}
'=' => {
let next_c = chars.peek();
Expand Down
3 changes: 2 additions & 1 deletion src/mast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,8 @@ fn monomorphize_expr<B: Backend>(
| Op2::Division
| Op2::Modulus
| Op2::BoolAnd
| Op2::BoolOr => lhs_mono.typ,
| Op2::BoolOr
| Op2::LeftShift => lhs_mono.clone().typ,
};

let ExprMonoInfo { expr: lhs_expr, .. } = lhs_mono;
Expand Down
5 changes: 4 additions & 1 deletion src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ pub enum Op2 {
Equality,
Inequality,
LessThan,
LeftShift,
BoolAnd,
BoolOr,
}
Expand Down Expand Up @@ -444,7 +445,8 @@ impl Expr {
| TokenKind::Less
| TokenKind::DoubleAmpersand
| TokenKind::DoublePipe
| TokenKind::Exclamation,
| TokenKind::Exclamation
| TokenKind::LeftShift,
..
}) => {
// lhs + rhs
Expand All @@ -458,6 +460,7 @@ impl Expr {
TokenKind::DoubleEqual => Op2::Equality,
TokenKind::NotEqual => Op2::Inequality,
TokenKind::Less => Op2::LessThan,
TokenKind::LeftShift => Op2::LeftShift,
TokenKind::DoubleAmpersand => Op2::BoolAnd,
TokenKind::DoublePipe => Op2::BoolOr,
_ => unreachable!(),
Expand Down
2 changes: 1 addition & 1 deletion src/stdlib/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Module for BitsLib {
}
}

fn to_bits<B: Backend>(
pub fn to_bits<B: Backend>(
compiler: &mut CircuitWriter<B>,
generics: &GenericParameters,
vars: &[VarInfo<B::Field, B::Var>],
Expand Down
3 changes: 2 additions & 1 deletion src/type_checker/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,8 @@ impl<B: Backend> TypeChecker<B> {
| Op2::Division
| Op2::Modulus
| Op2::BoolAnd
| Op2::BoolOr => lhs_node.typ,
| Op2::BoolOr
| Op2::LeftShift => lhs_node.typ,
};

Some(ExprTyInfo::new_anon(typ))
Expand Down