make arrays generic over types. wip
This commit is contained in:
parent
dfabfa06ef
commit
17f9473c51
6 changed files with 153 additions and 76 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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(¶meter.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))
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue