fix integer operation namespaces

This commit is contained in:
collin 2020-06-20 16:30:44 -07:00
parent 837a006e51
commit 2e02d0906c
5 changed files with 300 additions and 126 deletions

View File

@ -66,7 +66,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.add(cs, num_2)?))
Ok(ConstrainedValue::Integer(num_1.add(cs, num_2, span)?))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
Ok(ConstrainedValue::Field(fe_1.add(cs, &fe_2)?))
@ -98,7 +98,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.sub(cs, num_2)?))
Ok(ConstrainedValue::Integer(num_1.sub(cs, num_2, span)?))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
Ok(ConstrainedValue::Field(fe_1.sub(cs, &fe_2)?))
@ -130,7 +130,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.mul(cs, num_2)?))
Ok(ConstrainedValue::Integer(num_1.mul(cs, num_2, span)?))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
Ok(ConstrainedValue::Field(fe_1.mul(cs, &fe_2)?))
@ -161,7 +161,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.div(cs, num_2)?))
Ok(ConstrainedValue::Integer(num_1.div(cs, num_2, span)?))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
Ok(ConstrainedValue::Field(fe_1.div(cs, &fe_2)?))
@ -192,7 +192,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.pow(cs, num_2)?))
Ok(ConstrainedValue::Integer(num_1.pow(cs, num_2, span)?))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;

View File

@ -1,22 +1,11 @@
use crate::{error::Error as FormattedError, Span};
use snarkos_errors::gadgets::SynthesisError;
use std::num::ParseIntError;
#[derive(Debug, Error)]
pub enum IntegerError {
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("Cannot enforce {}", _0)]
CannotEnforce(String),
#[error("Expected integer parameter, got {}", _0)]
InvalidInteger(String),
#[error("{}", _0)]
ParseIntError(#[from] ParseIntError),
#[error("{}", _0)]
SynthesisError(#[from] SynthesisError),
}
@ -37,4 +26,13 @@ impl IntegerError {
Self::new_from_span(message, span)
}
pub fn cannot_enforce(operation: String, span: Span) -> Self {
let message = format!(
"the integer binary operation `{}` can only be enforced on integers of the same type",
operation
);
Self::new_from_span(message, span)
}
}

View File

@ -66,6 +66,37 @@ pub enum Expression {
FunctionCall(Box<Expression>, Vec<Expression>, Span),
}
impl Expression {
pub fn set_span(&mut self, new_span: &Span) {
match self {
Expression::Add(_, _, old_span) => *old_span = new_span.clone(),
Expression::Sub(_, _, old_span) => *old_span = new_span.clone(),
Expression::Mul(_, _, old_span) => *old_span = new_span.clone(),
Expression::Div(_, _, old_span) => *old_span = new_span.clone(),
Expression::Pow(_, _, old_span) => *old_span = new_span.clone(),
Expression::Or(_, _, old_span) => *old_span = new_span.clone(),
Expression::And(_, _, old_span) => *old_span = new_span.clone(),
Expression::Eq(_, _, old_span) => *old_span = new_span.clone(),
Expression::Ge(_, _, old_span) => *old_span = new_span.clone(),
Expression::Gt(_, _, old_span) => *old_span = new_span.clone(),
Expression::Le(_, _, old_span) => *old_span = new_span.clone(),
Expression::Lt(_, _, old_span) => *old_span = new_span.clone(),
Expression::IfElse(_, _, _, old_span) => *old_span = new_span.clone(),
Expression::Array(_, old_span) => *old_span = new_span.clone(),
Expression::ArrayAccess(_, _, old_span) => *old_span = new_span.clone(),
Expression::Circuit(_, _, old_span) => *old_span = new_span.clone(),
Expression::CircuitMemberAccess(_, _, old_span) => *old_span = new_span.clone(),
Expression::CircuitStaticFunctionAccess(_, _, old_span) => *old_span = new_span.clone(),
Expression::FunctionCall(_, _, old_span) => *old_span = new_span.clone(),
_ => {}
}
}
}
impl<'ast> Expression {
pub(crate) fn get_count(count: Value<'ast>) -> usize {
match count {

View File

@ -174,44 +174,70 @@ impl Integer {
self,
cs: &mut CS,
other: Self,
span: Span,
) -> Result<Self, IntegerError> {
Ok(match (self, other) {
(Integer::U8(left_u8), Integer::U8(right_u8)) => {
let result = UInt8::addmany(
cs.ns(|| format!("enforce {} + {}", left_u8.value.unwrap(), right_u8.value.unwrap())),
&[left_u8, right_u8],
)?;
let unique_namespace = format!(
"enforce {} + {} {}:{}",
left_u8.value.unwrap(),
right_u8.value.unwrap(),
span.line,
span.start
);
let result = UInt8::addmany(cs.ns(|| unique_namespace), &[left_u8, right_u8])?;
Integer::U8(result)
}
(Integer::U16(left_u16), Integer::U16(right_u16)) => {
let result = UInt16::addmany(
cs.ns(|| format!("enforce {} + {}", left_u16.value.unwrap(), right_u16.value.unwrap())),
&[left_u16, right_u16],
)?;
let unique_namespace = format!(
"enforce {} + {} {}:{}",
left_u16.value.unwrap(),
right_u16.value.unwrap(),
span.line,
span.start
);
let result = UInt16::addmany(cs.ns(|| unique_namespace), &[left_u16, right_u16])?;
Integer::U16(result)
}
(Integer::U32(left_u32), Integer::U32(right_u32)) => {
let result = UInt32::addmany(
cs.ns(|| format!("enforce {} + {}", left_u32.value.unwrap(), right_u32.value.unwrap())),
&[left_u32, right_u32],
)?;
let unique_namespace = format!(
"enforce {} + {} {}:{}",
left_u32.value.unwrap(),
right_u32.value.unwrap(),
span.line,
span.start
);
let result = UInt32::addmany(cs.ns(|| unique_namespace), &[left_u32, right_u32])?;
Integer::U32(result)
}
(Integer::U64(left_u64), Integer::U64(right_u64)) => {
let result = UInt64::addmany(
cs.ns(|| format!("enforce {} + {}", left_u64.value.unwrap(), right_u64.value.unwrap())),
&[left_u64, right_u64],
)?;
let unique_namespace = format!(
"enforce {} + {} {}:{}",
left_u64.value.unwrap(),
right_u64.value.unwrap(),
span.line,
span.start
);
let result = UInt64::addmany(cs.ns(|| unique_namespace), &[left_u64, right_u64])?;
Integer::U64(result)
}
(Integer::U128(left_u128), Integer::U128(right_u128)) => {
let result = UInt128::addmany(
cs.ns(|| format!("enforce {} + {}", left_u128.value.unwrap(), right_u128.value.unwrap())),
&[left_u128, right_u128],
)?;
let unique_namespace = format!(
"enforce {} + {} {}:{}",
left_u128.value.unwrap(),
right_u128.value.unwrap(),
span.line,
span.start
);
let result = UInt128::addmany(cs.ns(|| unique_namespace), &[left_u128, right_u128])?;
Integer::U128(result)
}
(left, right) => return Err(IntegerError::CannotEnforce(format!("{} + {}", left, right))),
(_, _) => return Err(IntegerError::cannot_enforce(format!("+"), span)),
})
}
@ -219,44 +245,70 @@ impl Integer {
self,
cs: &mut CS,
other: Self,
span: Span,
) -> Result<Self, IntegerError> {
Ok(match (self, other) {
(Integer::U8(left_u8), Integer::U8(right_u8)) => {
let result = left_u8.sub(
cs.ns(|| format!("enforce {} - {}", left_u8.value.unwrap(), right_u8.value.unwrap())),
&right_u8,
)?;
let unique_namespace = format!(
"enforce {} - {} {}:{}",
left_u8.value.unwrap(),
right_u8.value.unwrap(),
span.line,
span.start
);
let result = left_u8.sub(cs.ns(|| unique_namespace), &right_u8)?;
Integer::U8(result)
}
(Integer::U16(left_u16), Integer::U16(right_u16)) => {
let result = left_u16.sub(
cs.ns(|| format!("enforce {} - {}", left_u16.value.unwrap(), right_u16.value.unwrap())),
&right_u16,
)?;
let unique_namespace = format!(
"enforce {} - {} {}:{}",
left_u16.value.unwrap(),
right_u16.value.unwrap(),
span.line,
span.start
);
let result = left_u16.sub(cs.ns(|| unique_namespace), &right_u16)?;
Integer::U16(result)
}
(Integer::U32(left_u32), Integer::U32(right_u32)) => {
let result = left_u32.sub(
cs.ns(|| format!("enforce {} - {}", left_u32.value.unwrap(), right_u32.value.unwrap())),
&right_u32,
)?;
let unique_namespace = format!(
"enforce {} - {} {}:{}",
left_u32.value.unwrap(),
right_u32.value.unwrap(),
span.line,
span.start
);
let result = left_u32.sub(cs.ns(|| unique_namespace), &right_u32)?;
Integer::U32(result)
}
(Integer::U64(left_u64), Integer::U64(right_u64)) => {
let result = left_u64.sub(
cs.ns(|| format!("enforce {} - {}", left_u64.value.unwrap(), right_u64.value.unwrap())),
&right_u64,
)?;
let unique_namespace = format!(
"enforce {} - {} {}:{}",
left_u64.value.unwrap(),
right_u64.value.unwrap(),
span.line,
span.start
);
let result = left_u64.sub(cs.ns(|| unique_namespace), &right_u64)?;
Integer::U64(result)
}
(Integer::U128(left_u128), Integer::U128(right_u128)) => {
let result = left_u128.sub(
cs.ns(|| format!("enforce {} - {}", left_u128.value.unwrap(), right_u128.value.unwrap())),
&right_u128,
)?;
let unique_namespace = format!(
"enforce {} - {} {}:{}",
left_u128.value.unwrap(),
right_u128.value.unwrap(),
span.line,
span.start
);
let result = left_u128.sub(cs.ns(|| unique_namespace), &right_u128)?;
Integer::U128(result)
}
(left, right) => return Err(IntegerError::CannotEnforce(format!("{} - {}", left, right))),
(_, _) => return Err(IntegerError::cannot_enforce(format!("-"), span)),
})
}
@ -264,44 +316,70 @@ impl Integer {
self,
cs: &mut CS,
other: Self,
span: Span,
) -> Result<Self, IntegerError> {
Ok(match (self, other) {
(Integer::U8(left_u8), Integer::U8(right_u8)) => {
let result = left_u8.mul(
cs.ns(|| format!("enforce {} * {}", left_u8.value.unwrap(), right_u8.value.unwrap())),
&right_u8,
)?;
let unique_namespace = format!(
"enforce {} * {} {}:{}",
left_u8.value.unwrap(),
right_u8.value.unwrap(),
span.line,
span.start
);
let result = left_u8.mul(cs.ns(|| unique_namespace), &right_u8)?;
Integer::U8(result)
}
(Integer::U16(left_u16), Integer::U16(right_u16)) => {
let result = left_u16.mul(
cs.ns(|| format!("enforce {} * {}", left_u16.value.unwrap(), right_u16.value.unwrap())),
&right_u16,
)?;
let unique_namespace = format!(
"enforce {} * {} {}:{}",
left_u16.value.unwrap(),
right_u16.value.unwrap(),
span.line,
span.start
);
let result = left_u16.mul(cs.ns(|| unique_namespace), &right_u16)?;
Integer::U16(result)
}
(Integer::U32(left_u32), Integer::U32(right_u32)) => {
let result = left_u32.mul(
cs.ns(|| format!("enforce {} * {}", left_u32.value.unwrap(), right_u32.value.unwrap())),
&right_u32,
)?;
let unique_namespace = format!(
"enforce {} * {} {}:{}",
left_u32.value.unwrap(),
right_u32.value.unwrap(),
span.line,
span.start
);
let result = left_u32.mul(cs.ns(|| unique_namespace), &right_u32)?;
Integer::U32(result)
}
(Integer::U64(left_u64), Integer::U64(right_u64)) => {
let result = left_u64.mul(
cs.ns(|| format!("enforce {} * {}", left_u64.value.unwrap(), right_u64.value.unwrap())),
&right_u64,
)?;
let unique_namespace = format!(
"enforce {} * {} {}:{}",
left_u64.value.unwrap(),
right_u64.value.unwrap(),
span.line,
span.start
);
let result = left_u64.mul(cs.ns(|| unique_namespace), &right_u64)?;
Integer::U64(result)
}
(Integer::U128(left_u128), Integer::U128(right_u128)) => {
let result = left_u128.mul(
cs.ns(|| format!("enforce {} * {}", left_u128.value.unwrap(), right_u128.value.unwrap())),
&right_u128,
)?;
let unique_namespace = format!(
"enforce {} * {} {}:{}",
left_u128.value.unwrap(),
right_u128.value.unwrap(),
span.line,
span.start
);
let result = left_u128.mul(cs.ns(|| unique_namespace), &right_u128)?;
Integer::U128(result)
}
(left, right) => return Err(IntegerError::CannotEnforce(format!("{} * {}", left, right))),
(_, _) => return Err(IntegerError::cannot_enforce(format!("*"), span)),
})
}
@ -309,44 +387,70 @@ impl Integer {
self,
cs: &mut CS,
other: Self,
span: Span,
) -> Result<Self, IntegerError> {
Ok(match (self, other) {
(Integer::U8(left_u8), Integer::U8(right_u8)) => {
let result = left_u8.div(
cs.ns(|| format!("enforce {} ÷ {}", left_u8.value.unwrap(), right_u8.value.unwrap())),
&right_u8,
)?;
let unique_namespace = format!(
"enforce {} / {} {}:{}",
left_u8.value.unwrap(),
right_u8.value.unwrap(),
span.line,
span.start
);
let result = left_u8.div(cs.ns(|| unique_namespace), &right_u8)?;
Integer::U8(result)
}
(Integer::U16(left_u16), Integer::U16(right_u16)) => {
let result = left_u16.div(
cs.ns(|| format!("enforce {} ÷ {}", left_u16.value.unwrap(), right_u16.value.unwrap())),
&right_u16,
)?;
let unique_namespace = format!(
"enforce {} / {} {}:{}",
left_u16.value.unwrap(),
right_u16.value.unwrap(),
span.line,
span.start
);
let result = left_u16.div(cs.ns(|| unique_namespace), &right_u16)?;
Integer::U16(result)
}
(Integer::U32(left_u32), Integer::U32(right_u32)) => {
let result = left_u32.div(
cs.ns(|| format!("enforce {} ÷ {}", left_u32.value.unwrap(), right_u32.value.unwrap())),
&right_u32,
)?;
let unique_namespace = format!(
"enforce {} / {} {}:{}",
left_u32.value.unwrap(),
right_u32.value.unwrap(),
span.line,
span.start
);
let result = left_u32.div(cs.ns(|| unique_namespace), &right_u32)?;
Integer::U32(result)
}
(Integer::U64(left_u64), Integer::U64(right_u64)) => {
let result = left_u64.div(
cs.ns(|| format!("enforce {} ÷ {}", left_u64.value.unwrap(), right_u64.value.unwrap())),
&right_u64,
)?;
let unique_namespace = format!(
"enforce {} / {} {}:{}",
left_u64.value.unwrap(),
right_u64.value.unwrap(),
span.line,
span.start
);
let result = left_u64.div(cs.ns(|| unique_namespace), &right_u64)?;
Integer::U64(result)
}
(Integer::U128(left_u128), Integer::U128(right_u128)) => {
let result = left_u128.div(
cs.ns(|| format!("enforce {} ÷ {}", left_u128.value.unwrap(), right_u128.value.unwrap())),
&right_u128,
)?;
let unique_namespace = format!(
"enforce {} / {} {}:{}",
left_u128.value.unwrap(),
right_u128.value.unwrap(),
span.line,
span.start
);
let result = left_u128.div(cs.ns(|| unique_namespace), &right_u128)?;
Integer::U128(result)
}
(left, right) => return Err(IntegerError::CannotEnforce(format!("{} ÷ {}", left, right))),
(_, _) => return Err(IntegerError::cannot_enforce(format!("÷"), span)),
})
}
@ -354,44 +458,70 @@ impl Integer {
self,
cs: &mut CS,
other: Self,
span: Span,
) -> Result<Self, IntegerError> {
Ok(match (self, other) {
(Integer::U8(left_u8), Integer::U8(right_u8)) => {
let result = left_u8.pow(
cs.ns(|| format!("enforce {} ** {}", left_u8.value.unwrap(), right_u8.value.unwrap())),
&right_u8,
)?;
let unique_namespace = format!(
"enforce {} ** {} {}:{}",
left_u8.value.unwrap(),
right_u8.value.unwrap(),
span.line,
span.start
);
let result = left_u8.pow(cs.ns(|| unique_namespace), &right_u8)?;
Integer::U8(result)
}
(Integer::U16(left_u16), Integer::U16(right_u16)) => {
let result = left_u16.pow(
cs.ns(|| format!("enforce {} ** {}", left_u16.value.unwrap(), right_u16.value.unwrap())),
&right_u16,
)?;
let unique_namespace = format!(
"enforce {} ** {} {}:{}",
left_u16.value.unwrap(),
right_u16.value.unwrap(),
span.line,
span.start
);
let result = left_u16.pow(cs.ns(|| unique_namespace), &right_u16)?;
Integer::U16(result)
}
(Integer::U32(left_u32), Integer::U32(right_u32)) => {
let result = left_u32.pow(
cs.ns(|| format!("enforce {} ** {}", left_u32.value.unwrap(), right_u32.value.unwrap())),
&right_u32,
)?;
let unique_namespace = format!(
"enforce {} ** {} {}:{}",
left_u32.value.unwrap(),
right_u32.value.unwrap(),
span.line,
span.start
);
let result = left_u32.pow(cs.ns(|| unique_namespace), &right_u32)?;
Integer::U32(result)
}
(Integer::U64(left_u64), Integer::U64(right_u64)) => {
let result = left_u64.pow(
cs.ns(|| format!("enforce {} ** {}", left_u64.value.unwrap(), right_u64.value.unwrap())),
&right_u64,
)?;
let unique_namespace = format!(
"enforce {} ** {} {}:{}",
left_u64.value.unwrap(),
right_u64.value.unwrap(),
span.line,
span.start
);
let result = left_u64.pow(cs.ns(|| unique_namespace), &right_u64)?;
Integer::U64(result)
}
(Integer::U128(left_u128), Integer::U128(right_u128)) => {
let result = left_u128.pow(
cs.ns(|| format!("enforce {} ** {}", left_u128.value.unwrap(), right_u128.value.unwrap())),
&right_u128,
)?;
let unique_namespace = format!(
"enforce {} ** {} {}:{}",
left_u128.value.unwrap(),
right_u128.value.unwrap(),
span.line,
span.start
);
let result = left_u128.pow(cs.ns(|| unique_namespace), &right_u128)?;
Integer::U128(result)
}
(left, right) => return Err(IntegerError::CannotEnforce(format!("{} ** {}", left, right))),
(_, _) => return Err(IntegerError::cannot_enforce(format!("**"), span)),
})
}
}

View File

@ -30,24 +30,34 @@ pub enum Statement {
impl<'ast> From<ReturnStatement<'ast>> for Statement {
fn from(statement: ReturnStatement<'ast>) -> Self {
let span = Span::from(statement.span);
Statement::Return(
statement
.expressions
.into_iter()
.map(|expression| Expression::from(expression))
.map(|expression| {
let mut expression = Expression::from(expression);
expression.set_span(&span);
expression
})
.collect(),
Span::from(statement.span),
span,
)
}
}
impl<'ast> From<DefinitionStatement<'ast>> for Statement {
fn from(statement: DefinitionStatement<'ast>) -> Self {
let span = Span::from(statement.span);
let mut expression = Expression::from(statement.expression);
expression.set_span(&span);
Statement::Definition(
Declare::from(statement.declare),
Variable::from(statement.variable),
Expression::from(statement.expression),
Span::from(statement.span),
expression,
span,
)
}
}
@ -178,7 +188,12 @@ impl<'ast> From<AssertStatement<'ast>> for Statement {
impl<'ast> From<ExpressionStatement<'ast>> for Statement {
fn from(statement: ExpressionStatement<'ast>) -> Self {
Statement::Expression(Expression::from(statement.expression), Span::from(statement.span))
let span = Span::from(statement.span);
let mut expression = Expression::from(statement.expression);
expression.set_span(&span);
Statement::Expression(expression, span)
}
}