fix examples
This commit is contained in:
parent
60c63c1aef
commit
fec876a32a
14 changed files with 142 additions and 80 deletions
|
@ -1,5 +1,5 @@
|
|||
def sub(field a) -> (field):
|
||||
field a = a + 3
|
||||
a = a + 3
|
||||
return a
|
||||
|
||||
def main() -> (field):
|
||||
|
|
7
zokrates_cli/examples/error/duplicate_declaration.code
Normal file
7
zokrates_cli/examples/error/duplicate_declaration.code
Normal file
|
@ -0,0 +1,7 @@
|
|||
def foo() -> (field):
|
||||
return 1
|
||||
|
||||
def main() -> (field):
|
||||
bool a
|
||||
field a = foo()
|
||||
return 1
|
|
@ -4,7 +4,7 @@ def add(field a,field b) -> (field):
|
|||
|
||||
// Expected for inputs 1,1: c=4, d=7, e=10
|
||||
def main(field a,field b) -> (field):
|
||||
field c = add(a*2+3*b-a,b-1)
|
||||
field d = add(a*b+2, a*b*c)
|
||||
field e = add(add(a,d),add(a,b))
|
||||
c = add(a*2+3*b-a,b-1)
|
||||
d = add(a*b+2, a*b*c)
|
||||
e = add(add(a,d),add(a,b))
|
||||
return e
|
||||
|
|
|
@ -2,5 +2,5 @@ def add(field f,field g) -> (field):
|
|||
return f+g
|
||||
|
||||
def main(field a, field b) -> (field):
|
||||
field c = add(a,b)
|
||||
c = add(a,b)
|
||||
return c
|
||||
|
|
|
@ -4,10 +4,10 @@ def add(field a, field b) -> (field):
|
|||
|
||||
def main(field a, field b,field c, field d) -> (field):
|
||||
field g = a + b
|
||||
field x = add(a,b)
|
||||
field y = add(c,d)
|
||||
field g = add(x, g)
|
||||
x = add(a,b)
|
||||
y = add(c,d)
|
||||
g = add(x, g)
|
||||
g = add(x, g)
|
||||
field f = c + d + a
|
||||
field g = add(g+a, add(x,b))
|
||||
g = add(g+a, add(x,b))
|
||||
return x + y + g + f
|
||||
|
|
|
@ -6,6 +6,6 @@ def sub(field a, field b) -> (field):
|
|||
return a-b
|
||||
|
||||
def main(field a, field b) -> (field):
|
||||
field c = add(a,b)
|
||||
field d = sub(a,b)
|
||||
c = add(a,b)
|
||||
d = sub(a,b)
|
||||
return 0
|
||||
|
|
|
@ -2,7 +2,7 @@ def const() -> (field):
|
|||
return 123123
|
||||
|
||||
def add(field a,field b) -> (field):
|
||||
field a=const()
|
||||
a=const()
|
||||
return a+b
|
||||
|
||||
def main(field a,field b) -> (field):
|
||||
|
|
|
@ -3,5 +3,5 @@ def main(field x) -> (field):
|
|||
field b = a + x
|
||||
a = 7
|
||||
field c = a + b
|
||||
field a = a + 5
|
||||
a = a + 5
|
||||
return a + c
|
||||
|
|
|
@ -6,5 +6,5 @@ import "./or.code" as OR
|
|||
def main(field a, field b, field car) -> (field, field):
|
||||
out1, car1 = HALFADD(a, b)
|
||||
out2, car2 = HALFADD(out1, car)
|
||||
field car3 = OR(car1, car2)
|
||||
car3 = OR(car1, car2)
|
||||
return out2, car3
|
|
@ -1,7 +1,7 @@
|
|||
def wtax(debt,wealth):
|
||||
x = if wealth < debt then 0 else (wealth-debt) fi
|
||||
def wtax(field debt, field wealth) -> (field):
|
||||
field x = if wealth < debt then 0 else (wealth-debt) fi
|
||||
return x
|
||||
|
||||
def main(debt, wealth):
|
||||
tax = wtax(debt,wealth)
|
||||
def main(private field debt, private field wealth) -> (field):
|
||||
field tax = wtax(debt,wealth)
|
||||
return tax
|
|
@ -550,31 +550,31 @@ mod tests {
|
|||
use super::*;
|
||||
use self::glob::glob;
|
||||
|
||||
// #[test]
|
||||
// fn examples() {
|
||||
// for p in glob("./examples/**/*.code").expect("Failed to read glob pattern") {
|
||||
// let path = match p {
|
||||
// Ok(x) => x,
|
||||
// Err(why) => panic!("Error: {:?}", why),
|
||||
// };
|
||||
#[test]
|
||||
fn examples() {
|
||||
for p in glob("./examples/**/*.code").expect("Failed to read glob pattern") {
|
||||
let path = match p {
|
||||
Ok(x) => x,
|
||||
Err(why) => panic!("Error: {:?}", why),
|
||||
};
|
||||
|
||||
// if path.to_str().unwrap().contains("error") {
|
||||
// continue
|
||||
// }
|
||||
if path.to_str().unwrap().contains("error") {
|
||||
continue
|
||||
}
|
||||
|
||||
// println!("Testing {:?}", path);
|
||||
println!("Testing {:?}", path);
|
||||
|
||||
// let file = File::open(path.clone()).unwrap();
|
||||
let file = File::open(path.clone()).unwrap();
|
||||
|
||||
// let mut reader = BufReader::new(file);
|
||||
// let location = path.parent().unwrap().to_path_buf().into_os_string().into_string().unwrap();
|
||||
let mut reader = BufReader::new(file);
|
||||
let location = path.parent().unwrap().to_path_buf().into_os_string().into_string().unwrap();
|
||||
|
||||
// let program_flattened: FlatProg<FieldPrime> =
|
||||
// compile(&mut reader, Some(location), Some(fs_resolve), true, false).unwrap();
|
||||
let program_flattened: FlatProg<FieldPrime> =
|
||||
compile(&mut reader, Some(location), Some(fs_resolve), true, false).unwrap();
|
||||
|
||||
// let (..) = r1cs_program(&program_flattened);
|
||||
// }
|
||||
// }
|
||||
let (..) = r1cs_program(&program_flattened);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn examples_with_input_success() {
|
||||
|
|
|
@ -501,7 +501,7 @@ impl Flattener {
|
|||
}
|
||||
}
|
||||
panic!(
|
||||
"TypedFunction definition for function {} with {:?} argument(s) not found.",
|
||||
"TypedFunction definition for function {} with {:?} argument(s) not found. Should have been detected during semantic checking.",
|
||||
id,
|
||||
param_expressions
|
||||
);
|
||||
|
@ -743,7 +743,15 @@ impl Flattener {
|
|||
expr_subbed,
|
||||
)
|
||||
},
|
||||
_ => panic!("Functions can only return expressions of type FieldElement")
|
||||
TypedExpression::Boolean(e) => {
|
||||
let expr_subbed = e.apply_substitution(&self.substitution);
|
||||
self.flatten_boolean_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
expr_subbed,
|
||||
)
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
|
||||
|
@ -764,26 +772,35 @@ impl Flattener {
|
|||
// define n variables with n the number of primitive types for v_type
|
||||
// assign them to the n primitive types for expr
|
||||
|
||||
match expr {
|
||||
let rhs = match expr {
|
||||
TypedExpression::FieldElement(expr) => {
|
||||
let expr_subbed = expr.apply_substitution(&self.substitution);
|
||||
let rhs = self.flatten_field_expression(
|
||||
self.flatten_field_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
expr_subbed,
|
||||
);
|
||||
let var = self.use_variable(&v.id);
|
||||
// handle return of function call
|
||||
let var_to_replace = self.get_latest_var_substitution(&v.id);
|
||||
if !(var == var_to_replace) && self.variables.contains(&var_to_replace) && !self.substitution.contains_key(&var_to_replace){
|
||||
self.substitution.insert(var_to_replace.clone().to_string(),var.clone());
|
||||
}
|
||||
|
||||
statements_flattened.push(FlatStatement::Definition(var, rhs));
|
||||
)
|
||||
},
|
||||
_ => panic!("Definitions must have type FieldElement")
|
||||
TypedExpression::Boolean(expr) => {
|
||||
let expr_subbed = expr.apply_substitution(&self.substitution);
|
||||
self.flatten_boolean_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
expr_subbed,
|
||||
)
|
||||
},
|
||||
};
|
||||
|
||||
let var = self.use_variable(&v.id);
|
||||
// handle return of function call
|
||||
let var_to_replace = self.get_latest_var_substitution(&v.id);
|
||||
if !(var == var_to_replace) && self.variables.contains(&var_to_replace) && !self.substitution.contains_key(&var_to_replace){
|
||||
self.substitution.insert(var_to_replace.clone().to_string(),var.clone());
|
||||
}
|
||||
|
||||
statements_flattened.push(FlatStatement::Definition(var, rhs));
|
||||
}
|
||||
TypedStatement::Condition(expr1, expr2) => {
|
||||
|
||||
|
@ -831,7 +848,47 @@ impl Flattener {
|
|||
};
|
||||
statements_flattened.push(FlatStatement::Condition(lhs, rhs));
|
||||
},
|
||||
_ => panic!("Conditions (Assertions) must be applied to expressions of type FieldElement")
|
||||
(TypedExpression::Boolean(e1), TypedExpression::Boolean(e2)) => {
|
||||
|
||||
let e1_subbed = e1.apply_substitution(&self.substitution);
|
||||
let e2_subbed = e2.apply_substitution(&self.substitution);
|
||||
|
||||
let (lhs, rhs) = if e1_subbed.is_linear() {
|
||||
(
|
||||
self.flatten_boolean_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
e1_subbed
|
||||
),
|
||||
self.flatten_boolean_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
e2_subbed,
|
||||
),
|
||||
)
|
||||
} else if e2_subbed.is_linear() {
|
||||
(
|
||||
self.flatten_boolean_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
e2_subbed,
|
||||
),
|
||||
self.flatten_boolean_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
e1_subbed,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
unimplemented!()
|
||||
};
|
||||
statements_flattened.push(FlatStatement::Condition(lhs, rhs));
|
||||
},
|
||||
_ => panic!("non matching types in condition should have been caught at semantic stage")
|
||||
}
|
||||
}
|
||||
TypedStatement::For(var, start, end, statements) => {
|
||||
|
@ -862,7 +919,7 @@ impl Flattener {
|
|||
let rhs_subbed = rhs.apply_substitution(&self.substitution);
|
||||
|
||||
match rhs_subbed {
|
||||
TypedExpressionList::FunctionCall(fun_id, exprs, types) => {
|
||||
TypedExpressionList::FunctionCall(fun_id, exprs, _) => {
|
||||
let rhs_flattened = self.flatten_function_call(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
|
@ -872,21 +929,15 @@ impl Flattener {
|
|||
&exprs,
|
||||
);
|
||||
|
||||
// this will change for types that have multiple underlying fe
|
||||
for (i, v) in vars.into_iter().enumerate() {
|
||||
let var_type = &types[i];
|
||||
|
||||
match var_type {
|
||||
Type::FieldElement => {
|
||||
let var = self.use_variable(&v.id);
|
||||
// handle return of function call
|
||||
let var_to_replace = self.get_latest_var_substitution(&v.id);
|
||||
if !(var == var_to_replace) && self.variables.contains(&var_to_replace) && !self.substitution.contains_key(&var_to_replace){
|
||||
self.substitution.insert(var_to_replace.clone().to_string(),var.clone());
|
||||
}
|
||||
statements_flattened.push(FlatStatement::Definition(var, rhs_flattened.expressions[i].clone()));
|
||||
},
|
||||
_ => panic!("MultipleDefinition has to define expressions of type FieldElement")
|
||||
let var = self.use_variable(&v.id);
|
||||
// handle return of function call
|
||||
let var_to_replace = self.get_latest_var_substitution(&v.id);
|
||||
if !(var == var_to_replace) && self.variables.contains(&var_to_replace) && !self.substitution.contains_key(&var_to_replace){
|
||||
self.substitution.insert(var_to_replace.clone().to_string(),var.clone());
|
||||
}
|
||||
statements_flattened.push(FlatStatement::Definition(var, rhs_flattened.expressions[i].clone()));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ impl Checker {
|
|||
0 => {
|
||||
|
||||
},
|
||||
_ => panic!("dupllicate function declaration should have been caught")
|
||||
_ => panic!("duplicate function declaration should have been caught")
|
||||
}
|
||||
|
||||
self.enter_scope();
|
||||
|
@ -413,7 +413,20 @@ impl Checker {
|
|||
(TypedExpression::Boolean(condition), TypedExpression::FieldElement(consequence), TypedExpression::FieldElement(alternative)) => {
|
||||
Ok(FieldElementExpression::IfElse(box condition, box consequence, box alternative).into())
|
||||
},
|
||||
_ => panic!("id else only for bool fe fe")
|
||||
(condition, consequence, alternative) =>
|
||||
Err(
|
||||
Error {
|
||||
message:
|
||||
format!("if {{condition}} then {{consequence}} else {{alternative}} should have types {}, {}, {}, found {}, {}, {}",
|
||||
Type::Boolean,
|
||||
Type::FieldElement,
|
||||
Type::FieldElement,
|
||||
condition.get_type(),
|
||||
consequence.get_type(),
|
||||
alternative.get_type(),
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
&Expression::Number(ref n) => Ok(FieldElementExpression::Number(n.clone()).into()),
|
||||
|
@ -443,9 +456,9 @@ impl Checker {
|
|||
let f = &candidates[0];
|
||||
// the return count has to be 1
|
||||
if f.signature.outputs.len() == 1 {
|
||||
match f.signature.outputs[0] {
|
||||
Type::FieldElement => return Ok(FieldElementExpression::FunctionCall(f.id.clone(), arguments_checked).into()),
|
||||
_ => panic!("cannot return booleans")
|
||||
return match f.signature.outputs[0] {
|
||||
Type::FieldElement => Ok(FieldElementExpression::FunctionCall(f.id.clone(), arguments_checked).into()),
|
||||
ref t => Err( Error { message: format!("Outside of assignments, functions must return a single element of type {}, found type {}", Type::FieldElement, t)})
|
||||
}
|
||||
}
|
||||
Err(Error { message: format!("{} returns {} values but is called outside of a definition", f.id, f.signature.outputs.len()) })
|
||||
|
|
|
@ -258,15 +258,6 @@ impl<T: Field> Typed for TypedExpression<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Field> TypedExpression<T> {
|
||||
pub fn is_linear(&self) -> bool {
|
||||
match self {
|
||||
TypedExpression::Boolean(e) => e.is_linear(),
|
||||
TypedExpression::FieldElement(e) => e.is_linear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MultiTyped
|
||||
{
|
||||
fn get_types(&self) -> &Vec<Type>;
|
||||
|
|
Loading…
Reference in a new issue