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

make arrays generic over types. wip

This commit is contained in:
schaeff 2019-06-22 17:24:18 +02:00
parent dfabfa06ef
commit 17f9473c51
6 changed files with 153 additions and 76 deletions

View file

@ -1,6 +1,2 @@
def main(bool[3] a) -> (field[3]):
field[3] result = [0; 3]
for field i in 0..3 do
result[i] = if a[i] then 1 else 0 fi
endfor
return result
def main(bool[1] a) -> (field):
return if a[0] then 1 else 0 fi

View file

@ -159,12 +159,18 @@ pub fn compile_aux<T: Field, R: BufRead, S: BufRead, E: Into<imports::Error>>(
)
})?;
println!("{}", typed_ast);
// analyse (unroll and constant propagation)
let typed_ast = typed_ast.analyse();
println!("analysed {}", typed_ast);
// flatten input program
let program_flattened = Flattener::flatten(typed_ast);
println!("{}", program_flattened);
// analyse (constant propagation after call resolution)
let program_flattened = program_flattened.analyse();

View file

@ -401,7 +401,7 @@ impl<'ast> Flattener<'ast> {
functions_flattened,
statements_flattened,
&"_if_else_field".to_string(),
vec![Type::Boolean],
vec![Type::FieldElement],
&vec![
condition.into(),
FieldElementExpression::FunctionCall(
@ -423,9 +423,6 @@ impl<'ast> Flattener<'ast> {
let ty = array.inner_type();
assert_eq!(ty, &Type::Boolean);
println!("{}[{}]", array, index);
println!("{:?}", self.layout);
match index {
FieldElementExpression::Number(n) => match array.inner {
ArrayExpressionInner::Identifier(id) => {
@ -1025,6 +1022,7 @@ impl<'ast> Flattener<'ast> {
expr: ArrayExpression<'ast, T>,
) -> Vec<FlatExpression<T>> {
let ty = expr.get_type();
let inner_type = expr.inner_type().clone();
let size = expr.size();
match expr.inner {
@ -1037,52 +1035,69 @@ impl<'ast> Flattener<'ast> {
.collect(),
ArrayExpressionInner::Value(values) => {
assert_eq!(size, values.len());
values
.into_iter()
.map(|v| {
self.flatten_field_expression(
functions_flattened,
statements_flattened,
FieldElementExpression::try_from(v).unwrap(),
)
})
.collect()
match inner_type {
Type::FieldElement => values
.into_iter()
.map(|v| {
self.flatten_field_expression(
functions_flattened,
statements_flattened,
FieldElementExpression::try_from(v).unwrap(),
)
})
.collect(),
Type::Boolean => values
.into_iter()
.map(|v| {
self.flatten_boolean_expression(
functions_flattened,
statements_flattened,
BooleanExpression::try_from(v).unwrap(),
)
})
.collect(),
t => unimplemented!("array of {}", t),
}
}
ArrayExpressionInner::FunctionCall(ref id, ref param_expressions) => {
let exprs_flattened = self.flatten_function_call(
functions_flattened,
statements_flattened,
id,
vec![Type::array(ty, size)],
vec![ty],
param_expressions,
);
assert!(exprs_flattened.expressions.len() == size); // outside of MultipleDefinition, FunctionCalls must return a single value
exprs_flattened.expressions
}
ArrayExpressionInner::IfElse(ref condition, ref consequence, ref alternative) => {
let size = match consequence.get_type() {
Type::Array(_, n) => n,
let (inner_type, size) = match consequence.get_type() {
Type::Array(t, n) => (*t, n),
_ => unreachable!(),
};
(0..size)
.map(|i| {
self.flatten_field_expression(
functions_flattened,
statements_flattened,
FieldElementExpression::IfElse(
condition.clone(),
box FieldElementExpression::Select(
consequence.clone(),
box FieldElementExpression::Number(T::from(i)),
match inner_type {
Type::FieldElement => (0..size)
.map(|i| {
self.flatten_field_expression(
functions_flattened,
statements_flattened,
FieldElementExpression::IfElse(
condition.clone(),
box FieldElementExpression::Select(
consequence.clone(),
box FieldElementExpression::Number(T::from(i)),
),
box FieldElementExpression::Select(
alternative.clone(),
box FieldElementExpression::Number(T::from(i)),
),
),
box FieldElementExpression::Select(
alternative.clone(),
box FieldElementExpression::Number(T::from(i)),
),
),
)
})
.collect()
)
})
.collect(),
Type::Boolean => unimplemented!(),
Type::Array(..) => unimplemented!(),
}
}
}
}
@ -1095,6 +1110,15 @@ impl<'ast> Flattener<'ast> {
) {
match stat {
TypedStatement::Return(exprs) => {
println!(
"BEFORE {}\n\n",
statements_flattened
.iter()
.map(|x| format!("{}", x))
.collect::<Vec<_>>()
.join("\n")
);
let flat_expressions = exprs
.into_iter()
.map(|expr| {
@ -1103,6 +1127,15 @@ impl<'ast> Flattener<'ast> {
.flat_map(|x| x)
.collect::<Vec<_>>();
println!(
"AFTER {}\n\n",
statements_flattened
.iter()
.map(|x| format!("{}", x))
.collect::<Vec<_>>()
.join("\n")
);
statements_flattened.push(FlatStatement::Return(FlatExpressionList {
expressions: flat_expressions,
}));
@ -1447,6 +1480,9 @@ impl<'ast> Flattener<'ast> {
let variables = self.use_variable(&parameter.id);
match parameter.id.get_type() {
Type::Boolean => statements.extend(Self::boolean_constraint(&variables)),
Type::Array(box Type::Boolean, _) => {
statements.extend(Self::boolean_constraint(&variables))
}
_ => {}
};

View file

@ -47,7 +47,11 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
TypedExpression::Array(e) => {
let inner_type = e.inner_type();
match e.inner {
ArrayExpressionInner::Value(array) =>
ArrayExpressionInner::Value(array) => {
let array: Vec<_> = array.into_iter().map(|e| self.fold_expression(e)).collect();
println!("{}", ArrayExpressionInner::Value(array.clone()));
match array.iter().all(|e| match e {
TypedExpression::FieldElement(FieldElementExpression::Number(..)) => true,
TypedExpression::Boolean(BooleanExpression::Value(..)) => true,
@ -66,7 +70,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
..e}.into()))
}
}
,
},
e => unimplemented!()
}
},
@ -416,6 +420,15 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
e => e,
}
}
BooleanExpression::IfElse(box condition, box consequence, box alternative) => {
let consequence = self.fold_boolean_expression(consequence);
let alternative = self.fold_boolean_expression(alternative);
match self.fold_boolean_expression(condition) {
BooleanExpression::Value(true) => consequence,
BooleanExpression::Value(false) => alternative,
c => BooleanExpression::IfElse(box c, box consequence, box alternative),
}
}
e => fold_boolean_expression(self, e),
}
}

View file

@ -80,40 +80,66 @@ impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> {
_ => panic!("array identifier should be a field element array"),
};
let expr = match expr {
TypedExpression::FieldElement(e) => e,
_ => panic!("right side of array element definition must be a field element"),
};
let new_variable = self.issue_next_ssa_variable(original_variable);
let new_array = ArrayExpression {
ty: Type::FieldElement,
size: array_size,
inner: ArrayExpressionInner::Value(
(0..array_size)
.map(|i| {
FieldElementExpression::IfElse(
box BooleanExpression::Eq(
box index.clone(),
box FieldElementExpression::Number(T::from(i)),
),
box expr.clone(),
box FieldElementExpression::Select(
box ArrayExpression {
ty: Type::FieldElement,
size: array_size,
inner: ArrayExpressionInner::Identifier(
current_ssa_variable.id.clone(),
),
},
box FieldElementExpression::Number(T::from(i)),
),
)
.into()
})
.collect(),
),
let new_array = match expr {
TypedExpression::FieldElement(e) => ArrayExpression {
ty: Type::FieldElement,
size: array_size,
inner: ArrayExpressionInner::Value(
(0..array_size)
.map(|i| {
FieldElementExpression::IfElse(
box BooleanExpression::Eq(
box index.clone(),
box FieldElementExpression::Number(T::from(i)),
),
box e.clone(),
box FieldElementExpression::Select(
box ArrayExpression {
ty: Type::FieldElement,
size: array_size,
inner: ArrayExpressionInner::Identifier(
current_ssa_variable.id.clone(),
),
},
box FieldElementExpression::Number(T::from(i)),
),
)
.into()
})
.collect(),
),
},
TypedExpression::Boolean(e) => ArrayExpression {
ty: Type::Boolean,
size: array_size,
inner: ArrayExpressionInner::Value(
(0..array_size)
.map(|i| {
BooleanExpression::IfElse(
box BooleanExpression::Eq(
box index.clone(),
box FieldElementExpression::Number(T::from(i)),
),
box e.clone(),
box BooleanExpression::Select(
box ArrayExpression {
ty: Type::Boolean,
size: array_size,
inner: ArrayExpressionInner::Identifier(
current_ssa_variable.id.clone(),
),
},
box FieldElementExpression::Number(T::from(i)),
),
)
.into()
})
.collect(),
),
},
TypedExpression::Array(..) => unimplemented!(),
};
vec![TypedStatement::Definition(

View file

@ -192,7 +192,7 @@ impl<'ast, T: Field> Typed for TypedAssignee<'ast, T> {
TypedAssignee::ArrayElement(ref a, _) => {
let a_type = a.get_type();
match a_type {
Type::Array(..) => Type::FieldElement,
Type::Array(box t, _) => t,
_ => panic!("array element has to take array"),
}
}