1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

fix examples

This commit is contained in:
schaeff 2018-09-12 14:13:54 +02:00
parent 60c63c1aef
commit fec876a32a
14 changed files with 142 additions and 80 deletions

View file

@ -1,5 +1,5 @@
def sub(field a) -> (field): def sub(field a) -> (field):
field a = a + 3 a = a + 3
return a return a
def main() -> (field): def main() -> (field):

View file

@ -0,0 +1,7 @@
def foo() -> (field):
return 1
def main() -> (field):
bool a
field a = foo()
return 1

View file

@ -4,7 +4,7 @@ def add(field a,field b) -> (field):
// Expected for inputs 1,1: c=4, d=7, e=10 // Expected for inputs 1,1: c=4, d=7, e=10
def main(field a,field b) -> (field): def main(field a,field b) -> (field):
field c = add(a*2+3*b-a,b-1) c = add(a*2+3*b-a,b-1)
field d = add(a*b+2, a*b*c) d = add(a*b+2, a*b*c)
field e = add(add(a,d),add(a,b)) e = add(add(a,d),add(a,b))
return e return e

View file

@ -2,5 +2,5 @@ def add(field f,field g) -> (field):
return f+g return f+g
def main(field a, field b) -> (field): def main(field a, field b) -> (field):
field c = add(a,b) c = add(a,b)
return c return c

View file

@ -4,10 +4,10 @@ def add(field a, field b) -> (field):
def main(field a, field b,field c, field d) -> (field): def main(field a, field b,field c, field d) -> (field):
field g = a + b field g = a + b
field x = add(a,b) x = add(a,b)
field y = add(c,d) y = add(c,d)
field g = add(x, g) g = add(x, g)
g = add(x, g) g = add(x, g)
field f = c + d + a 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 return x + y + g + f

View file

@ -6,6 +6,6 @@ def sub(field a, field b) -> (field):
return a-b return a-b
def main(field a, field b) -> (field): def main(field a, field b) -> (field):
field c = add(a,b) c = add(a,b)
field d = sub(a,b) d = sub(a,b)
return 0 return 0

View file

@ -2,7 +2,7 @@ def const() -> (field):
return 123123 return 123123
def add(field a,field b) -> (field): def add(field a,field b) -> (field):
field a=const() a=const()
return a+b return a+b
def main(field a,field b) -> (field): def main(field a,field b) -> (field):

View file

@ -3,5 +3,5 @@ def main(field x) -> (field):
field b = a + x field b = a + x
a = 7 a = 7
field c = a + b field c = a + b
field a = a + 5 a = a + 5
return a + c return a + c

View file

@ -6,5 +6,5 @@ import "./or.code" as OR
def main(field a, field b, field car) -> (field, field): def main(field a, field b, field car) -> (field, field):
out1, car1 = HALFADD(a, b) out1, car1 = HALFADD(a, b)
out2, car2 = HALFADD(out1, car) out2, car2 = HALFADD(out1, car)
field car3 = OR(car1, car2) car3 = OR(car1, car2)
return out2, car3 return out2, car3

View file

@ -1,7 +1,7 @@
def wtax(debt,wealth): def wtax(field debt, field wealth) -> (field):
x = if wealth < debt then 0 else (wealth-debt) fi field x = if wealth < debt then 0 else (wealth-debt) fi
return x return x
def main(debt, wealth): def main(private field debt, private field wealth) -> (field):
tax = wtax(debt,wealth) field tax = wtax(debt,wealth)
return tax return tax

View file

@ -550,31 +550,31 @@ mod tests {
use super::*; use super::*;
use self::glob::glob; use self::glob::glob;
// #[test] #[test]
// fn examples() { fn examples() {
// for p in glob("./examples/**/*.code").expect("Failed to read glob pattern") { for p in glob("./examples/**/*.code").expect("Failed to read glob pattern") {
// let path = match p { let path = match p {
// Ok(x) => x, Ok(x) => x,
// Err(why) => panic!("Error: {:?}", why), Err(why) => panic!("Error: {:?}", why),
// }; };
// if path.to_str().unwrap().contains("error") { if path.to_str().unwrap().contains("error") {
// continue 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 mut reader = BufReader::new(file);
// let location = path.parent().unwrap().to_path_buf().into_os_string().into_string().unwrap(); let location = path.parent().unwrap().to_path_buf().into_os_string().into_string().unwrap();
// let program_flattened: FlatProg<FieldPrime> = let program_flattened: FlatProg<FieldPrime> =
// compile(&mut reader, Some(location), Some(fs_resolve), true, false).unwrap(); compile(&mut reader, Some(location), Some(fs_resolve), true, false).unwrap();
// let (..) = r1cs_program(&program_flattened); let (..) = r1cs_program(&program_flattened);
// } }
// } }
#[test] #[test]
fn examples_with_input_success() { fn examples_with_input_success() {

View file

@ -501,7 +501,7 @@ impl Flattener {
} }
} }
panic!( 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, id,
param_expressions param_expressions
); );
@ -743,7 +743,15 @@ impl Flattener {
expr_subbed, 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(); }).collect();
@ -764,26 +772,35 @@ impl Flattener {
// define n variables with n the number of primitive types for v_type // define n variables with n the number of primitive types for v_type
// assign them to the n primitive types for expr // assign them to the n primitive types for expr
match expr { let rhs = match expr {
TypedExpression::FieldElement(expr) => { TypedExpression::FieldElement(expr) => {
let expr_subbed = expr.apply_substitution(&self.substitution); let expr_subbed = expr.apply_substitution(&self.substitution);
let rhs = self.flatten_field_expression( self.flatten_field_expression(
functions_flattened, functions_flattened,
arguments_flattened, arguments_flattened,
statements_flattened, statements_flattened,
expr_subbed, 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) => { TypedStatement::Condition(expr1, expr2) => {
@ -831,7 +848,47 @@ impl Flattener {
}; };
statements_flattened.push(FlatStatement::Condition(lhs, rhs)); 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) => { TypedStatement::For(var, start, end, statements) => {
@ -862,7 +919,7 @@ impl Flattener {
let rhs_subbed = rhs.apply_substitution(&self.substitution); let rhs_subbed = rhs.apply_substitution(&self.substitution);
match rhs_subbed { match rhs_subbed {
TypedExpressionList::FunctionCall(fun_id, exprs, types) => { TypedExpressionList::FunctionCall(fun_id, exprs, _) => {
let rhs_flattened = self.flatten_function_call( let rhs_flattened = self.flatten_function_call(
functions_flattened, functions_flattened,
arguments_flattened, arguments_flattened,
@ -872,21 +929,15 @@ impl Flattener {
&exprs, &exprs,
); );
// this will change for types that have multiple underlying fe
for (i, v) in vars.into_iter().enumerate() { for (i, v) in vars.into_iter().enumerate() {
let var_type = &types[i]; let var = self.use_variable(&v.id);
// handle return of function call
match var_type { let var_to_replace = self.get_latest_var_substitution(&v.id);
Type::FieldElement => { if !(var == var_to_replace) && self.variables.contains(&var_to_replace) && !self.substitution.contains_key(&var_to_replace){
let var = self.use_variable(&v.id); self.substitution.insert(var_to_replace.clone().to_string(),var.clone());
// 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")
} }
statements_flattened.push(FlatStatement::Definition(var, rhs_flattened.expressions[i].clone()));
} }
}, },
} }

View file

@ -184,7 +184,7 @@ impl Checker {
0 => { 0 => {
}, },
_ => panic!("dupllicate function declaration should have been caught") _ => panic!("duplicate function declaration should have been caught")
} }
self.enter_scope(); self.enter_scope();
@ -413,7 +413,20 @@ impl Checker {
(TypedExpression::Boolean(condition), TypedExpression::FieldElement(consequence), TypedExpression::FieldElement(alternative)) => { (TypedExpression::Boolean(condition), TypedExpression::FieldElement(consequence), TypedExpression::FieldElement(alternative)) => {
Ok(FieldElementExpression::IfElse(box condition, box consequence, box alternative).into()) 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()), &Expression::Number(ref n) => Ok(FieldElementExpression::Number(n.clone()).into()),
@ -443,9 +456,9 @@ impl Checker {
let f = &candidates[0]; let f = &candidates[0];
// the return count has to be 1 // the return count has to be 1
if f.signature.outputs.len() == 1 { if f.signature.outputs.len() == 1 {
match f.signature.outputs[0] { return match f.signature.outputs[0] {
Type::FieldElement => return Ok(FieldElementExpression::FunctionCall(f.id.clone(), arguments_checked).into()), Type::FieldElement => Ok(FieldElementExpression::FunctionCall(f.id.clone(), arguments_checked).into()),
_ => panic!("cannot return booleans") 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()) }) Err(Error { message: format!("{} returns {} values but is called outside of a definition", f.id, f.signature.outputs.len()) })

View file

@ -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 pub trait MultiTyped
{ {
fn get_types(&self) -> &Vec<Type>; fn get_types(&self) -> &Vec<Type>;