merge original alias branch
This commit is contained in:
commit
b38a9bc64e
19 changed files with 383 additions and 289 deletions
|
@ -413,11 +413,8 @@ mod tests {
|
|||
fn array() {
|
||||
let s = "[[true, false]]";
|
||||
assert_eq!(
|
||||
parse_strict::<Bn128Field>(
|
||||
s,
|
||||
vec![ConcreteType::array((ConcreteType::Boolean, 2usize))]
|
||||
)
|
||||
.unwrap(),
|
||||
parse_strict::<Bn128Field>(s, vec![ConcreteType::array((ConcreteType::Boolean, 2u32))])
|
||||
.unwrap(),
|
||||
Values(vec![Value::Array(vec![
|
||||
Value::Boolean(true),
|
||||
Value::Boolean(false)
|
||||
|
|
|
@ -247,6 +247,8 @@ fn check_with_arena<'ast, T: Field, E: Into<imports::Error>>(
|
|||
let typed_ast = Checker::check(compiled)
|
||||
.map_err(|errors| CompileErrors(errors.into_iter().map(CompileError::from).collect()))?;
|
||||
|
||||
log::trace!("\n{}", typed_ast);
|
||||
|
||||
let main_module = typed_ast.main.clone();
|
||||
|
||||
log::debug!("Run static analysis");
|
||||
|
|
|
@ -50,25 +50,16 @@ impl FlatEmbed {
|
|||
match self {
|
||||
FlatEmbed::BitArrayLe => DeclarationSignature::new()
|
||||
.generics(vec![Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier {
|
||||
name: "N",
|
||||
index: 0,
|
||||
},
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
))])
|
||||
.inputs(vec![
|
||||
DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
GenericIdentifier {
|
||||
name: "N",
|
||||
index: 0,
|
||||
},
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
)),
|
||||
DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
GenericIdentifier {
|
||||
name: "N",
|
||||
index: 0,
|
||||
},
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
)),
|
||||
])
|
||||
.outputs(vec![DeclarationType::Boolean]),
|
||||
|
@ -77,104 +68,90 @@ impl FlatEmbed {
|
|||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
FlatEmbed::Unpack => DeclarationSignature::new()
|
||||
.generics(vec![Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier {
|
||||
name: "N",
|
||||
index: 0,
|
||||
},
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
))])
|
||||
.inputs(vec![DeclarationType::FieldElement])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
GenericIdentifier {
|
||||
name: "N",
|
||||
index: 0,
|
||||
},
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
))]),
|
||||
FlatEmbed::U8ToBits => DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::uint(8)])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
8usize,
|
||||
8u32,
|
||||
))]),
|
||||
FlatEmbed::U16ToBits => DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::uint(16)])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
16usize,
|
||||
16u32,
|
||||
))]),
|
||||
FlatEmbed::U32ToBits => DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::uint(32)])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
32usize,
|
||||
32u32,
|
||||
))]),
|
||||
FlatEmbed::U64ToBits => DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::uint(64)])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
64usize,
|
||||
64u32,
|
||||
))]),
|
||||
FlatEmbed::U8FromBits => DeclarationSignature::new()
|
||||
.outputs(vec![DeclarationType::uint(8)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
8usize,
|
||||
8u32,
|
||||
))]),
|
||||
FlatEmbed::U16FromBits => DeclarationSignature::new()
|
||||
.outputs(vec![DeclarationType::uint(16)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
16usize,
|
||||
16u32,
|
||||
))]),
|
||||
FlatEmbed::U32FromBits => DeclarationSignature::new()
|
||||
.outputs(vec![DeclarationType::uint(32)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
32usize,
|
||||
32u32,
|
||||
))]),
|
||||
FlatEmbed::U64FromBits => DeclarationSignature::new()
|
||||
.outputs(vec![DeclarationType::uint(64)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
64usize,
|
||||
64u32,
|
||||
))]),
|
||||
#[cfg(feature = "bellman")]
|
||||
FlatEmbed::Sha256Round => DeclarationSignature::new()
|
||||
.inputs(vec![
|
||||
DeclarationType::array((DeclarationType::Boolean, 512usize)),
|
||||
DeclarationType::array((DeclarationType::Boolean, 256usize)),
|
||||
DeclarationType::array((DeclarationType::Boolean, 512u32)),
|
||||
DeclarationType::array((DeclarationType::Boolean, 256u32)),
|
||||
])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::Boolean,
|
||||
256usize,
|
||||
256u32,
|
||||
))]),
|
||||
#[cfg(feature = "ark")]
|
||||
FlatEmbed::SnarkVerifyBls12377 => DeclarationSignature::new()
|
||||
.generics(vec![
|
||||
Some(DeclarationConstant::Generic(GenericIdentifier {
|
||||
name: "N",
|
||||
index: 0,
|
||||
})),
|
||||
Some(DeclarationConstant::Generic(GenericIdentifier {
|
||||
name: "V",
|
||||
index: 1,
|
||||
})),
|
||||
Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
)),
|
||||
Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier::with_name("V").with_index(1),
|
||||
)),
|
||||
])
|
||||
.inputs(vec![
|
||||
DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier {
|
||||
name: "N",
|
||||
index: 0,
|
||||
},
|
||||
GenericIdentifier::with_name("N").with_index(0),
|
||||
)), // inputs
|
||||
DeclarationType::array((DeclarationType::FieldElement, 8usize)), // proof
|
||||
DeclarationType::array((DeclarationType::FieldElement, 8u32)), // proof
|
||||
DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier {
|
||||
name: "V",
|
||||
index: 1,
|
||||
},
|
||||
GenericIdentifier::with_name("V").with_index(1),
|
||||
)), // 18 + (2 * n) // vk
|
||||
])
|
||||
.outputs(vec![DeclarationType::Boolean]),
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use crate::absy::Identifier;
|
||||
use crate::absy::*;
|
||||
use crate::typed_absy::types::{try_from_g_type, GGenericsAssignment};
|
||||
use crate::typed_absy::types::{try_from_g_type, GGenericsAssignment, GenericsAssignment};
|
||||
use crate::typed_absy::*;
|
||||
use crate::typed_absy::{DeclarationParameter, DeclarationVariable, Variable};
|
||||
use num_bigint::BigUint;
|
||||
|
@ -55,7 +55,7 @@ impl ErrorInner {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum TypeKind<'ast> {
|
||||
Canonical(DeclarationType<'ast>),
|
||||
Alias(
|
||||
|
@ -396,10 +396,9 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
} else {
|
||||
match generics_map.insert(g.value, index).is_none() {
|
||||
true => {
|
||||
generics.push(Some(DeclarationConstant::Generic(GenericIdentifier {
|
||||
name: g.value,
|
||||
index,
|
||||
})));
|
||||
generics.push(Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier::with_name(g.value).with_index(index),
|
||||
)));
|
||||
}
|
||||
false => {
|
||||
errors.push(ErrorInner {
|
||||
|
@ -529,10 +528,9 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
} else {
|
||||
match generics_map.insert(g.value, index).is_none() {
|
||||
true => {
|
||||
generics.push(Some(DeclarationConstant::Generic(GenericIdentifier {
|
||||
name: g.value,
|
||||
index,
|
||||
})));
|
||||
generics.push(Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier::with_name(g.value).with_index(index),
|
||||
)));
|
||||
}
|
||||
false => {
|
||||
errors.push(ErrorInner {
|
||||
|
@ -1050,17 +1048,26 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
|
||||
match self.check_signature(funct.signature, module_id, state) {
|
||||
Ok(s) => {
|
||||
// initialise generics map
|
||||
let mut generics: GenericsAssignment<'ast, T> = GGenericsAssignment::default();
|
||||
|
||||
// define variables for the constants
|
||||
for generic in &s.generics {
|
||||
let generic = generic.clone().unwrap(); // for declaration signatures, generics cannot be ignored
|
||||
let generic = match generic.clone().unwrap() {
|
||||
DeclarationConstant::Generic(g) => g,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let v = Variable::with_id_and_type(
|
||||
match generic {
|
||||
DeclarationConstant::Generic(g) => g.name,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Type::Uint(UBitwidth::B32),
|
||||
// for declaration signatures, generics cannot be ignored
|
||||
|
||||
let v = Variable::with_id_and_type(generic.name(), Type::Uint(UBitwidth::B32));
|
||||
|
||||
generics.0.insert(
|
||||
generic.clone(),
|
||||
UExpressionInner::Identifier(generic.name().into())
|
||||
.annotate(UBitwidth::B32),
|
||||
);
|
||||
|
||||
// we don't have to check for conflicts here, because this was done when checking the signature
|
||||
self.insert_into_scope(v.clone());
|
||||
}
|
||||
|
@ -1073,9 +1080,12 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
let decl_v =
|
||||
DeclarationVariable::with_id_and_type(arg.id.value.id, decl_ty.clone());
|
||||
|
||||
match self.insert_into_scope(
|
||||
crate::typed_absy::variable::try_from_g_variable(decl_v.clone()).unwrap(),
|
||||
) {
|
||||
let ty = specialize_declaration_type(decl_v.clone()._type, &generics).unwrap();
|
||||
|
||||
match self.insert_into_scope(crate::typed_absy::variable::Variable {
|
||||
id: decl_v.clone().id,
|
||||
_type: ty,
|
||||
}) {
|
||||
true => {}
|
||||
false => {
|
||||
errors.push(ErrorInner {
|
||||
|
@ -1198,10 +1208,9 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
} else {
|
||||
match generics_map.insert(g.value, index).is_none() {
|
||||
true => {
|
||||
generics.push(Some(DeclarationConstant::Generic(GenericIdentifier {
|
||||
name: g.value,
|
||||
index,
|
||||
})));
|
||||
generics.push(Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier::with_name(g.value).with_index(index),
|
||||
)));
|
||||
}
|
||||
false => {
|
||||
errors.push(ErrorInner {
|
||||
|
@ -1470,7 +1479,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
})
|
||||
}
|
||||
}
|
||||
(None, Some(index)) => Ok(DeclarationConstant::Generic(GenericIdentifier { name, index: *index })),
|
||||
(None, Some(index)) => Ok(DeclarationConstant::Generic(GenericIdentifier::with_name(name).with_index(*index))),
|
||||
_ => Err(ErrorInner {
|
||||
pos: Some(pos),
|
||||
message: format!("Undeclared symbol `{}`", name)
|
||||
|
@ -1567,24 +1576,9 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
}),
|
||||
);
|
||||
|
||||
// generate actual type based on generic type and concrete generics
|
||||
let members = declared_struct_ty
|
||||
.members
|
||||
.into_iter()
|
||||
.map(|m| {
|
||||
Ok(DeclarationStructMember {
|
||||
ty: box specialize_declaration_type(*m.ty, &assignment)
|
||||
.unwrap(),
|
||||
..m
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(DeclarationType::Struct(DeclarationStructType {
|
||||
canonical_location: declared_struct_ty.canonical_location,
|
||||
location: declared_struct_ty.location,
|
||||
generics: checked_generics,
|
||||
members,
|
||||
..declared_struct_ty
|
||||
}))
|
||||
}
|
||||
false => Err(ErrorInner {
|
||||
|
@ -3110,12 +3104,20 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
Some(ty) => Ok(ty),
|
||||
}?;
|
||||
|
||||
let declared_struct_type = match ty {
|
||||
let mut declared_struct_type = match ty {
|
||||
TypeKind::Canonical(DeclarationType::Struct(struct_type))
|
||||
| TypeKind::Alias(DeclarationType::Struct(struct_type), _) => struct_type,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
declared_struct_type.generics = (0..declared_struct_type.generics.len())
|
||||
.map(|index| {
|
||||
Some(DeclarationConstant::Generic(
|
||||
GenericIdentifier::without_name().with_index(index),
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
|
||||
// check that we provided the required number of values
|
||||
if declared_struct_type.members_count() != inline_members.len() {
|
||||
return Err(ErrorInner {
|
||||
|
@ -3670,7 +3672,7 @@ mod tests {
|
|||
"bar",
|
||||
DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into()
|
||||
GenericIdentifier::with_name("K").with_index(0).into()
|
||||
)])
|
||||
.inputs(vec![DeclarationType::FieldElement])
|
||||
));
|
||||
|
@ -3679,11 +3681,11 @@ mod tests {
|
|||
"bar",
|
||||
DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into()
|
||||
GenericIdentifier::with_name("K").with_index(0).into()
|
||||
)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("K").index(0)
|
||||
GenericIdentifier::with_name("K").with_index(0)
|
||||
))])
|
||||
));
|
||||
// a `bar` function with an equivalent signature, just renaming generic parameters
|
||||
|
@ -3691,11 +3693,11 @@ mod tests {
|
|||
"bar",
|
||||
DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("L").index(0).into()
|
||||
GenericIdentifier::with_name("L").with_index(0).into()
|
||||
)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("L").index(0)
|
||||
GenericIdentifier::with_name("L").with_index(0)
|
||||
))])
|
||||
));
|
||||
// a `bar` type isn't allowed as the name is already taken by at least one function
|
||||
|
@ -4259,16 +4261,16 @@ mod tests {
|
|||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("K").index(0)
|
||||
GenericIdentifier::with_name("K").with_index(0)
|
||||
)),
|
||||
GenericIdentifier::with_name("L").index(1)
|
||||
GenericIdentifier::with_name("L").with_index(1)
|
||||
))])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("L").index(1)
|
||||
GenericIdentifier::with_name("L").with_index(1)
|
||||
)),
|
||||
GenericIdentifier::with_name("K").index(0)
|
||||
GenericIdentifier::with_name("K").with_index(0)
|
||||
))]))
|
||||
);
|
||||
}
|
||||
|
@ -5677,9 +5679,8 @@ mod tests {
|
|||
.get(&*MODULE_ID)
|
||||
.unwrap()
|
||||
.get(&"Bar".to_string())
|
||||
.map(|(ty, _)| ty)
|
||||
.unwrap(),
|
||||
&DeclarationType::Struct(DeclarationStructType::new(
|
||||
&TypeKind::Canonical(DeclarationType::Struct(DeclarationStructType::new(
|
||||
(*MODULE_ID).clone(),
|
||||
"Bar".into(),
|
||||
vec![],
|
||||
|
@ -5695,7 +5696,7 @@ mod tests {
|
|||
)]
|
||||
))
|
||||
)]
|
||||
))
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -574,13 +574,13 @@ mod tests {
|
|||
statements: vec![TypedStatement::Return(vec![FieldElementExpression::Add(
|
||||
FieldElementExpression::select(
|
||||
ArrayExpressionInner::Identifier(Identifier::from(const_id))
|
||||
.annotate(GType::FieldElement, 2usize),
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
UExpressionInner::Value(0u128).annotate(UBitwidth::B32),
|
||||
)
|
||||
.into(),
|
||||
FieldElementExpression::select(
|
||||
ArrayExpressionInner::Identifier(Identifier::from(const_id))
|
||||
.annotate(GType::FieldElement, 2usize),
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
UExpressionInner::Value(1u128).annotate(UBitwidth::B32),
|
||||
)
|
||||
.into(),
|
||||
|
@ -608,7 +608,7 @@ mod tests {
|
|||
]
|
||||
.into(),
|
||||
)
|
||||
.annotate(GType::FieldElement, 2usize),
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
))),
|
||||
)]
|
||||
.into_iter()
|
||||
|
@ -649,7 +649,7 @@ mod tests {
|
|||
]
|
||||
.into(),
|
||||
)
|
||||
.annotate(GType::FieldElement, 2usize),
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
UExpressionInner::Value(0u128).annotate(UBitwidth::B32),
|
||||
)
|
||||
.into(),
|
||||
|
@ -661,7 +661,7 @@ mod tests {
|
|||
]
|
||||
.into(),
|
||||
)
|
||||
.annotate(GType::FieldElement, 2usize),
|
||||
.annotate(GType::FieldElement, 2u32),
|
||||
UExpressionInner::Value(1u128).annotate(UBitwidth::B32),
|
||||
)
|
||||
.into(),
|
||||
|
|
|
@ -340,7 +340,7 @@ impl<'ast, T: Field> Flattener<T> {
|
|||
&mut self,
|
||||
statements_buffer: &mut Vec<zir::ZirStatement<'ast, T>>,
|
||||
ty: &typed_absy::types::ConcreteType,
|
||||
size: usize,
|
||||
size: u32,
|
||||
e: typed_absy::ArrayExpressionInner<'ast, T>,
|
||||
) -> Vec<zir::ZirExpression<'ast, T>> {
|
||||
fold_array_expression_inner(self, statements_buffer, ty, size, e)
|
||||
|
@ -404,7 +404,7 @@ fn fold_array_expression_inner<'ast, T: Field>(
|
|||
f: &mut Flattener<T>,
|
||||
statements_buffer: &mut Vec<zir::ZirStatement<'ast, T>>,
|
||||
ty: &typed_absy::types::ConcreteType,
|
||||
size: usize,
|
||||
size: u32,
|
||||
array: typed_absy::ArrayExpressionInner<'ast, T>,
|
||||
) -> Vec<zir::ZirExpression<'ast, T>> {
|
||||
match array {
|
||||
|
@ -437,7 +437,7 @@ fn fold_array_expression_inner<'ast, T: Field>(
|
|||
.flat_map(|e| f.fold_expression_or_spread(statements_buffer, e))
|
||||
.collect();
|
||||
|
||||
assert_eq!(exprs.len(), size * ty.get_primitive_count());
|
||||
assert_eq!(exprs.len(), size as usize * ty.get_primitive_count());
|
||||
|
||||
exprs
|
||||
}
|
||||
|
@ -458,7 +458,7 @@ fn fold_array_expression_inner<'ast, T: Field>(
|
|||
|
||||
match (from.into_inner(), to.into_inner()) {
|
||||
(zir::UExpressionInner::Value(from), zir::UExpressionInner::Value(to)) => {
|
||||
assert_eq!(size, to.saturating_sub(from) as usize);
|
||||
assert_eq!(size, to.saturating_sub(from) as u32);
|
||||
|
||||
let element_size = ty.get_primitive_count();
|
||||
let start = from as usize * element_size;
|
||||
|
@ -1108,10 +1108,7 @@ fn fold_array_expression<'ast, T: Field>(
|
|||
statements_buffer: &mut Vec<zir::ZirStatement<'ast, T>>,
|
||||
e: typed_absy::ArrayExpression<'ast, T>,
|
||||
) -> Vec<zir::ZirExpression<'ast, T>> {
|
||||
let size = match e.size().into_inner() {
|
||||
typed_absy::UExpressionInner::Value(v) => v,
|
||||
_ => unreachable!(),
|
||||
} as usize;
|
||||
let size: u32 = e.size().try_into().unwrap();
|
||||
f.fold_array_expression_inner(
|
||||
statements_buffer,
|
||||
&typed_absy::types::ConcreteType::try_from(e.inner_type().clone()).unwrap(),
|
||||
|
|
|
@ -11,6 +11,7 @@ mod flat_propagation;
|
|||
mod flatten_complex_types;
|
||||
mod propagation;
|
||||
mod reducer;
|
||||
mod struct_concretizer;
|
||||
mod uint_optimizer;
|
||||
mod unconstrained_vars;
|
||||
mod variable_write_remover;
|
||||
|
@ -20,6 +21,7 @@ use self::constant_argument_checker::ConstantArgumentChecker;
|
|||
use self::flatten_complex_types::Flattener;
|
||||
use self::propagation::Propagator;
|
||||
use self::reducer::reduce_program;
|
||||
use self::struct_concretizer::StructConcretizer;
|
||||
use self::uint_optimizer::UintOptimizer;
|
||||
use self::unconstrained_vars::UnconstrainedVariableDetector;
|
||||
use self::variable_write_remover::VariableWriteRemover;
|
||||
|
@ -101,6 +103,14 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
|
|||
let r = reduce_program(r).map_err(Error::from)?;
|
||||
log::trace!("\n{}", r);
|
||||
|
||||
log::debug!("Static analyser: Propagate");
|
||||
let r = Propagator::propagate(r)?;
|
||||
log::trace!("\n{}", r);
|
||||
|
||||
log::debug!("Static analyser: Concretize structs");
|
||||
let r = StructConcretizer::concretize(r);
|
||||
log::trace!("\n{}", r);
|
||||
|
||||
// generate abi
|
||||
log::debug!("Static analyser: Generate abi");
|
||||
let abi = r.abi();
|
||||
|
|
|
@ -1194,16 +1194,14 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
|
|||
let e1 = self.fold_struct_expression(e1)?;
|
||||
let e2 = self.fold_struct_expression(e2)?;
|
||||
|
||||
if let (Ok(t1), Ok(t2)) = (
|
||||
ConcreteType::try_from(e1.get_type()),
|
||||
ConcreteType::try_from(e2.get_type()),
|
||||
) {
|
||||
if t1 != t2 {
|
||||
return Err(Error::Type(format!(
|
||||
"Cannot compare {} of type {} to {} of type {}",
|
||||
e1, t1, e2, t2
|
||||
)));
|
||||
}
|
||||
let t1 = e1.get_type();
|
||||
let t2 = e2.get_type();
|
||||
|
||||
if t1 != t2 {
|
||||
return Err(Error::Type(format!(
|
||||
"Cannot compare {} of type {} to {} of type {}",
|
||||
e1, t1, e2, t2
|
||||
)));
|
||||
};
|
||||
|
||||
Ok(BooleanExpression::StructEq(box e1, box e2))
|
||||
|
@ -1465,7 +1463,7 @@ mod tests {
|
|||
]
|
||||
.into(),
|
||||
)
|
||||
.annotate(Type::FieldElement, 3usize),
|
||||
.annotate(Type::FieldElement, 3u32),
|
||||
UExpressionInner::Add(box 1u32.into(), box 1u32.into())
|
||||
.annotate(UBitwidth::B32),
|
||||
);
|
||||
|
|
|
@ -830,22 +830,22 @@ mod tests {
|
|||
|
||||
let foo_signature = DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into(),
|
||||
GenericIdentifier::with_name("K").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)),
|
||||
))])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)),
|
||||
))]);
|
||||
|
||||
let foo: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![DeclarationVariable::array(
|
||||
"a",
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("K").index(0),
|
||||
GenericIdentifier::with_name("K").with_index(0),
|
||||
)
|
||||
.into()],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
|
@ -954,7 +954,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "foo")
|
||||
.signature(foo_signature.clone()),
|
||||
GGenericsAssignment(
|
||||
vec![(GenericIdentifier::with_name("K").index(0), 1)]
|
||||
vec![(GenericIdentifier::with_name("K").with_index(0), 1)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
|
@ -1049,22 +1049,22 @@ mod tests {
|
|||
|
||||
let foo_signature = DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into(),
|
||||
GenericIdentifier::with_name("K").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)),
|
||||
))])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)),
|
||||
))]);
|
||||
|
||||
let foo: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![DeclarationVariable::array(
|
||||
"a",
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("K").index(0),
|
||||
GenericIdentifier::with_name("K").with_index(0),
|
||||
)
|
||||
.into()],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
|
@ -1182,7 +1182,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "foo")
|
||||
.signature(foo_signature.clone()),
|
||||
GGenericsAssignment(
|
||||
vec![(GenericIdentifier::with_name("K").index(0), 1)]
|
||||
vec![(GenericIdentifier::with_name("K").with_index(0), 1)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
|
@ -1280,21 +1280,21 @@ mod tests {
|
|||
let foo_signature = DeclarationSignature::new()
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)),
|
||||
))])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)),
|
||||
))])
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into(),
|
||||
GenericIdentifier::with_name("K").with_index(0).into(),
|
||||
)]);
|
||||
|
||||
let foo: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![DeclarationVariable::array(
|
||||
"a",
|
||||
DeclarationType::FieldElement,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)),
|
||||
)
|
||||
.into()],
|
||||
statements: vec![
|
||||
|
@ -1358,7 +1358,7 @@ mod tests {
|
|||
arguments: vec![DeclarationVariable::array(
|
||||
"a",
|
||||
DeclarationType::FieldElement,
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||
DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)),
|
||||
)
|
||||
.into()],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
|
@ -1433,7 +1433,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "foo")
|
||||
.signature(foo_signature.clone()),
|
||||
GGenericsAssignment(
|
||||
vec![(GenericIdentifier::with_name("K").index(0), 1)]
|
||||
vec![(GenericIdentifier::with_name("K").with_index(0), 1)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
|
@ -1442,7 +1442,7 @@ mod tests {
|
|||
DeclarationFunctionKey::with_location("main", "bar")
|
||||
.signature(foo_signature.clone()),
|
||||
GGenericsAssignment(
|
||||
vec![(GenericIdentifier::with_name("K").index(0), 2)]
|
||||
vec![(GenericIdentifier::with_name("K").with_index(0), 2)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
|
@ -1489,22 +1489,22 @@ mod tests {
|
|||
|
||||
let foo_signature = DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into(),
|
||||
GenericIdentifier::with_name("K").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("K").index(0),
|
||||
GenericIdentifier::with_name("K").with_index(0),
|
||||
))])
|
||||
.outputs(vec![DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("K").index(0),
|
||||
GenericIdentifier::with_name("K").with_index(0),
|
||||
))]);
|
||||
|
||||
let foo: TypedFunction<Bn128Field> = TypedFunction {
|
||||
arguments: vec![DeclarationVariable::array(
|
||||
"a",
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier::with_name("K").index(0),
|
||||
GenericIdentifier::with_name("K").with_index(0),
|
||||
)
|
||||
.into()],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
|
|
|
@ -105,7 +105,7 @@ impl<'ast, 'a> ShallowTransformer<'ast, 'a> {
|
|||
.map(|(g, v)| {
|
||||
TypedStatement::Definition(
|
||||
TypedAssignee::Identifier(Variable::with_id_and_type(
|
||||
g.name,
|
||||
g.name(),
|
||||
Type::Uint(UBitwidth::B32),
|
||||
)),
|
||||
UExpression::from(*v as u32).into(),
|
||||
|
@ -662,7 +662,7 @@ mod tests {
|
|||
],
|
||||
signature: DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into(),
|
||||
GenericIdentifier::with_name("K").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::FieldElement])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
|
@ -673,7 +673,7 @@ mod tests {
|
|||
let ssa = ShallowTransformer::transform(
|
||||
f,
|
||||
&GGenericsAssignment(
|
||||
vec![(GenericIdentifier::with_name("K").index(0), 1)]
|
||||
vec![(GenericIdentifier::with_name("K").with_index(0), 1)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
|
@ -742,7 +742,7 @@ mod tests {
|
|||
],
|
||||
signature: DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into(),
|
||||
GenericIdentifier::with_name("K").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::FieldElement])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
|
@ -851,7 +851,7 @@ mod tests {
|
|||
],
|
||||
signature: DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into(),
|
||||
GenericIdentifier::with_name("K").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::FieldElement])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
|
@ -862,7 +862,7 @@ mod tests {
|
|||
let ssa = ShallowTransformer::transform(
|
||||
f,
|
||||
&GGenericsAssignment(
|
||||
vec![(GenericIdentifier::with_name("K").index(0), 1)]
|
||||
vec![(GenericIdentifier::with_name("K").with_index(0), 1)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
|
@ -934,7 +934,7 @@ mod tests {
|
|||
],
|
||||
signature: DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier::with_name("K").index(0).into(),
|
||||
GenericIdentifier::with_name("K").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::FieldElement])
|
||||
.outputs(vec![DeclarationType::FieldElement]),
|
||||
|
|
91
zokrates_core/src/static_analysis/struct_concretizer.rs
Normal file
91
zokrates_core/src/static_analysis/struct_concretizer.rs
Normal file
|
@ -0,0 +1,91 @@
|
|||
// After all generics are inlined, a program should be completely "concrete", which means that all types must only contain
|
||||
// litterals for array sizes. This is especially important to generate the ABI of the program.
|
||||
// It is direct to ensure that with most types, however the way structs are implemented requires a slightly different process:
|
||||
// Where for an array, `field[N]` ends up being propagated to `field[42]` which is direct to turn into a concrete type,
|
||||
// for structs, `Foo<N> { field[N] a }` is propagated to `Foo<42> { field[N] a }`. The missing step is replacing `N` by `42`
|
||||
// *inside* the canonical type, so that it can be concretized in the same way arrays are.
|
||||
// We apply this transformation only to the main function.
|
||||
|
||||
use crate::typed_absy::folder::*;
|
||||
use crate::typed_absy::{
|
||||
types::{
|
||||
ConcreteGenericsAssignment, DeclarationArrayType, DeclarationConstant,
|
||||
DeclarationStructMember, GGenericsAssignment,
|
||||
},
|
||||
DeclarationStructType, GenericIdentifier, TypedProgram,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
use zokrates_field::Field;
|
||||
|
||||
pub struct StructConcretizer<'ast, T> {
|
||||
generics: ConcreteGenericsAssignment<'ast>,
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'ast, T: Field> StructConcretizer<'ast, T> {
|
||||
pub fn concretize(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> {
|
||||
StructConcretizer::with_generics(ConcreteGenericsAssignment::default()).fold_program(p)
|
||||
}
|
||||
|
||||
pub fn with_generics(generics: ConcreteGenericsAssignment<'ast>) -> Self {
|
||||
Self {
|
||||
generics,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T: Field> Folder<'ast, T> for StructConcretizer<'ast, T> {
|
||||
fn fold_declaration_struct_type(
|
||||
&mut self,
|
||||
ty: DeclarationStructType<'ast>,
|
||||
) -> DeclarationStructType<'ast> {
|
||||
let concrete_generics: Vec<u32> = ty
|
||||
.generics
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|g| g.unwrap().map_concrete(&self.generics).unwrap())
|
||||
.collect();
|
||||
|
||||
let concrete_generics_map: ConcreteGenericsAssignment = GGenericsAssignment(
|
||||
concrete_generics
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, g)| (GenericIdentifier::without_name().with_index(index), *g))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let mut internal_concretizer: StructConcretizer<'ast, T> =
|
||||
StructConcretizer::with_generics(concrete_generics_map);
|
||||
|
||||
DeclarationStructType {
|
||||
members: ty
|
||||
.members
|
||||
.into_iter()
|
||||
.map(|member| {
|
||||
DeclarationStructMember::new(
|
||||
member.id,
|
||||
internal_concretizer.fold_declaration_type(*member.ty),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
generics: concrete_generics
|
||||
.into_iter()
|
||||
.map(|g| Some(DeclarationConstant::Concrete(g as u32)))
|
||||
.collect(),
|
||||
..ty
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_declaration_array_type(
|
||||
&mut self,
|
||||
ty: DeclarationArrayType<'ast>,
|
||||
) -> DeclarationArrayType<'ast> {
|
||||
let size = ty.size.map_concrete(&self.generics).unwrap();
|
||||
|
||||
DeclarationArrayType {
|
||||
size: DeclarationConstant::Concrete(size),
|
||||
ty: box self.fold_declaration_type(*ty.ty),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,10 +37,9 @@ impl<'ast> VariableWriteRemover {
|
|||
let inner_ty = base.inner_type();
|
||||
let size = base.size();
|
||||
|
||||
let size = match size.as_inner() {
|
||||
UExpressionInner::Value(v) => *v as u32,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
let size: u32 = size.try_into().unwrap();
|
||||
|
||||
let head = indices.remove(0);
|
||||
let tail = indices;
|
||||
|
|
|
@ -231,12 +231,12 @@ mod tests {
|
|||
ty: ConcreteType::Struct(ConcreteStructType::new(
|
||||
"".into(),
|
||||
"Bar".into(),
|
||||
vec![Some(1usize)],
|
||||
vec![Some(1u32)],
|
||||
vec![ConcreteStructMember::new(
|
||||
String::from("a"),
|
||||
ConcreteType::Array(ConcreteArrayType::new(
|
||||
ConcreteType::FieldElement,
|
||||
1usize,
|
||||
1u32,
|
||||
)),
|
||||
)],
|
||||
)),
|
||||
|
@ -400,7 +400,7 @@ mod tests {
|
|||
ConcreteStructMember::new(String::from("c"), ConcreteType::Boolean),
|
||||
],
|
||||
)),
|
||||
2usize,
|
||||
2u32,
|
||||
)),
|
||||
}],
|
||||
outputs: vec![ConcreteType::Boolean],
|
||||
|
@ -454,8 +454,8 @@ mod tests {
|
|||
name: String::from("a"),
|
||||
public: false,
|
||||
ty: ConcreteType::Array(ConcreteArrayType::new(
|
||||
ConcreteType::Array(ConcreteArrayType::new(ConcreteType::FieldElement, 2usize)),
|
||||
2usize,
|
||||
ConcreteType::Array(ConcreteArrayType::new(ConcreteType::FieldElement, 2u32)),
|
||||
2u32,
|
||||
)),
|
||||
}],
|
||||
outputs: vec![ConcreteType::FieldElement],
|
||||
|
|
|
@ -57,21 +57,39 @@ impl<'ast, T> Types<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, Ord)]
|
||||
#[derive(Debug, Clone, Eq)]
|
||||
pub struct GenericIdentifier<'ast> {
|
||||
pub name: &'ast str,
|
||||
pub index: usize,
|
||||
name: Option<&'ast str>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'ast> GenericIdentifier<'ast> {
|
||||
pub fn with_name(name: &'ast str) -> Self {
|
||||
Self { name, index: 0 }
|
||||
pub fn without_name() -> Self {
|
||||
Self {
|
||||
name: None,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index(mut self, index: usize) -> Self {
|
||||
pub fn with_name(name: &'ast str) -> Self {
|
||||
Self {
|
||||
name: Some(name),
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_index(mut self, index: usize) -> Self {
|
||||
self.index = index;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &'ast str {
|
||||
self.name.unwrap()
|
||||
}
|
||||
|
||||
pub fn index(&self) -> usize {
|
||||
self.index
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> PartialEq for GenericIdentifier<'ast> {
|
||||
|
@ -86,6 +104,12 @@ impl<'ast> PartialOrd for GenericIdentifier<'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast> Ord for GenericIdentifier<'ast> {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> Hash for GenericIdentifier<'ast> {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.index.hash(state);
|
||||
|
@ -94,7 +118,7 @@ impl<'ast> Hash for GenericIdentifier<'ast> {
|
|||
|
||||
impl<'ast> fmt::Display for GenericIdentifier<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
write!(f, "{}", self.name())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,6 +155,32 @@ pub enum DeclarationConstant<'ast> {
|
|||
Constant(CanonicalConstantIdentifier<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> DeclarationConstant<'ast> {
|
||||
pub fn map<S: From<CanonicalConstantIdentifier<'ast>> + From<u32> + Clone>(
|
||||
self,
|
||||
generics: &GGenericsAssignment<'ast, S>,
|
||||
) -> Result<S, GenericIdentifier<'ast>> {
|
||||
match self {
|
||||
DeclarationConstant::Generic(g) => generics.0.get(&g).cloned().ok_or(g),
|
||||
DeclarationConstant::Concrete(v) => Ok(v.into()),
|
||||
DeclarationConstant::Constant(c) => Ok(c.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_concrete<S: From<u32> + Clone>(
|
||||
self,
|
||||
generics: &GGenericsAssignment<'ast, S>,
|
||||
) -> Result<S, GenericIdentifier<'ast>> {
|
||||
match self {
|
||||
DeclarationConstant::Constant(_) => unreachable!(
|
||||
"called map_concrete on a constant, it should have been resolved before"
|
||||
),
|
||||
DeclarationConstant::Generic(g) => generics.0.get(&g).cloned().ok_or(g),
|
||||
DeclarationConstant::Concrete(v) => Ok(v.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> PartialEq<UExpression<'ast, T>> for DeclarationConstant<'ast> {
|
||||
fn eq(&self, other: &UExpression<'ast, T>) -> bool {
|
||||
match (self, other.as_inner()) {
|
||||
|
@ -152,12 +202,6 @@ impl<'ast> From<u32> for DeclarationConstant<'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<usize> for DeclarationConstant<'ast> {
|
||||
fn from(e: usize) -> Self {
|
||||
DeclarationConstant::Concrete(e as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GenericIdentifier<'ast>> for DeclarationConstant<'ast> {
|
||||
fn from(e: GenericIdentifier<'ast>) -> Self {
|
||||
DeclarationConstant::Generic(e)
|
||||
|
@ -174,8 +218,8 @@ impl<'ast> fmt::Display for DeclarationConstant<'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> From<usize> for UExpression<'ast, T> {
|
||||
fn from(i: usize) -> Self {
|
||||
impl<'ast, T> From<u32> for UExpression<'ast, T> {
|
||||
fn from(i: u32) -> Self {
|
||||
UExpressionInner::Value(i as u128).annotate(UBitwidth::B32)
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +228,7 @@ impl<'ast, T> From<DeclarationConstant<'ast>> for UExpression<'ast, T> {
|
|||
fn from(c: DeclarationConstant<'ast>) -> Self {
|
||||
match c {
|
||||
DeclarationConstant::Generic(i) => {
|
||||
UExpressionInner::Identifier(i.name.into()).annotate(UBitwidth::B32)
|
||||
UExpressionInner::Identifier(i.name().into()).annotate(UBitwidth::B32)
|
||||
}
|
||||
DeclarationConstant::Concrete(v) => {
|
||||
UExpressionInner::Value(v as u128).annotate(UBitwidth::B32)
|
||||
|
@ -196,25 +240,14 @@ impl<'ast, T> From<DeclarationConstant<'ast>> for UExpression<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> TryInto<usize> for UExpression<'ast, T> {
|
||||
impl<'ast, T> TryInto<u32> for UExpression<'ast, T> {
|
||||
type Error = SpecializationError;
|
||||
|
||||
fn try_into(self) -> Result<usize, Self::Error> {
|
||||
fn try_into(self) -> Result<u32, Self::Error> {
|
||||
assert_eq!(self.bitwidth, UBitwidth::B32);
|
||||
|
||||
match self.into_inner() {
|
||||
UExpressionInner::Value(v) => Ok(v as usize),
|
||||
_ => Err(SpecializationError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> TryInto<usize> for DeclarationConstant<'ast> {
|
||||
type Error = SpecializationError;
|
||||
|
||||
fn try_into(self) -> Result<usize, Self::Error> {
|
||||
match self {
|
||||
DeclarationConstant::Concrete(v) => Ok(v as usize),
|
||||
UExpressionInner::Value(v) => Ok(v as u32),
|
||||
_ => Err(SpecializationError),
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +264,7 @@ pub struct GStructMember<S> {
|
|||
}
|
||||
|
||||
pub type DeclarationStructMember<'ast> = GStructMember<DeclarationConstant<'ast>>;
|
||||
pub type ConcreteStructMember = GStructMember<usize>;
|
||||
pub type ConcreteStructMember = GStructMember<u32>;
|
||||
pub type StructMember<'ast, T> = GStructMember<UExpression<'ast, T>>;
|
||||
|
||||
impl<'ast, S, R: PartialEq<S>> PartialEq<GStructMember<S>> for GStructMember<R> {
|
||||
|
@ -271,7 +304,7 @@ pub struct GArrayType<S> {
|
|||
}
|
||||
|
||||
pub type DeclarationArrayType<'ast> = GArrayType<DeclarationConstant<'ast>>;
|
||||
pub type ConcreteArrayType = GArrayType<usize>;
|
||||
pub type ConcreteArrayType = GArrayType<u32>;
|
||||
pub type ArrayType<'ast, T> = GArrayType<UExpression<'ast, T>>;
|
||||
|
||||
impl<'ast, S, R: PartialEq<S>> PartialEq<GArrayType<S>> for GArrayType<R> {
|
||||
|
@ -353,7 +386,7 @@ pub struct GStructType<S> {
|
|||
}
|
||||
|
||||
pub type DeclarationStructType<'ast> = GStructType<DeclarationConstant<'ast>>;
|
||||
pub type ConcreteStructType = GStructType<usize>;
|
||||
pub type ConcreteStructType = GStructType<u32>;
|
||||
pub type StructType<'ast, T> = GStructType<UExpression<'ast, T>>;
|
||||
|
||||
impl<'ast, S, R: PartialEq<S>> PartialEq<GStructType<S>> for GStructType<R> {
|
||||
|
@ -365,8 +398,7 @@ impl<'ast, S, R: PartialEq<S>> PartialEq<GStructType<S>> for GStructType<R> {
|
|||
.zip(other.generics.iter())
|
||||
.all(|(a, b)| match (a, b) {
|
||||
(Some(a), Some(b)) => a == b,
|
||||
(None, None) => true,
|
||||
_ => false,
|
||||
_ => true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -610,7 +642,7 @@ impl<'de, S: Deserialize<'de>> Deserialize<'de> for GType<S> {
|
|||
}
|
||||
|
||||
pub type DeclarationType<'ast> = GType<DeclarationConstant<'ast>>;
|
||||
pub type ConcreteType = GType<usize>;
|
||||
pub type ConcreteType = GType<u32>;
|
||||
pub type Type<'ast, T> = GType<UExpression<'ast, T>>;
|
||||
|
||||
impl<'ast, S, R: PartialEq<S>> PartialEq<GType<S>> for GType<R> {
|
||||
|
@ -799,7 +831,9 @@ impl ConcreteType {
|
|||
GType::FieldElement => 1,
|
||||
GType::Boolean => 1,
|
||||
GType::Uint(_) => 1,
|
||||
GType::Array(array_type) => array_type.size * array_type.ty.get_primitive_count(),
|
||||
GType::Array(array_type) => {
|
||||
array_type.size as usize * array_type.ty.get_primitive_count()
|
||||
}
|
||||
GType::Int => unreachable!(),
|
||||
GType::Struct(struct_type) => struct_type
|
||||
.iter()
|
||||
|
@ -819,7 +853,7 @@ pub struct GFunctionKey<'ast, S> {
|
|||
}
|
||||
|
||||
pub type DeclarationFunctionKey<'ast> = GFunctionKey<'ast, DeclarationConstant<'ast>>;
|
||||
pub type ConcreteFunctionKey<'ast> = GFunctionKey<'ast, usize>;
|
||||
pub type ConcreteFunctionKey<'ast> = GFunctionKey<'ast, u32>;
|
||||
pub type FunctionKey<'ast, T> = GFunctionKey<'ast, UExpression<'ast, T>>;
|
||||
|
||||
impl<'ast, S: fmt::Display> fmt::Display for GFunctionKey<'ast, S> {
|
||||
|
@ -831,7 +865,7 @@ impl<'ast, S: fmt::Display> fmt::Display for GFunctionKey<'ast, S> {
|
|||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||
pub struct GGenericsAssignment<'ast, S>(pub BTreeMap<GenericIdentifier<'ast>, S>);
|
||||
|
||||
pub type ConcreteGenericsAssignment<'ast> = GGenericsAssignment<'ast, usize>;
|
||||
pub type ConcreteGenericsAssignment<'ast> = GGenericsAssignment<'ast, u32>;
|
||||
pub type GenericsAssignment<'ast, T> = GGenericsAssignment<'ast, UExpression<'ast, T>>;
|
||||
|
||||
impl<'ast, S> Default for GGenericsAssignment<'ast, S> {
|
||||
|
@ -931,7 +965,7 @@ impl<'ast> ConcreteFunctionKey<'ast> {
|
|||
|
||||
use std::collections::btree_map::Entry;
|
||||
|
||||
pub fn check_type<'ast, S: Clone + PartialEq + PartialEq<usize>>(
|
||||
pub fn check_type<'ast, S: Clone + PartialEq + PartialEq<u32>>(
|
||||
decl_ty: &DeclarationType<'ast>,
|
||||
ty: >ype<S>,
|
||||
constants: &mut GGenericsAssignment<'ast, S>,
|
||||
|
@ -952,7 +986,7 @@ pub fn check_type<'ast, S: Clone + PartialEq + PartialEq<usize>>(
|
|||
true
|
||||
}
|
||||
},
|
||||
DeclarationConstant::Concrete(s0) => s1 == *s0 as usize,
|
||||
DeclarationConstant::Concrete(s0) => s1 == *s0 as u32,
|
||||
// in the case of a constant, we do not know the value yet, so we optimistically assume it's correct
|
||||
// if it does not match, it will be caught during inlining
|
||||
DeclarationConstant::Constant(..) => true,
|
||||
|
@ -995,51 +1029,55 @@ pub fn specialize_declaration_type<
|
|||
Ok(match decl_ty {
|
||||
DeclarationType::Int => unreachable!(),
|
||||
DeclarationType::Array(t0) => {
|
||||
// let s1 = t1.size.clone();
|
||||
|
||||
let ty = box specialize_declaration_type(*t0.ty, &generics)?;
|
||||
let size = match t0.size {
|
||||
DeclarationConstant::Generic(s) => generics.0.get(&s).cloned().ok_or(s),
|
||||
DeclarationConstant::Concrete(s) => Ok(s.into()),
|
||||
DeclarationConstant::Constant(c) => Ok(c.into()),
|
||||
}?;
|
||||
|
||||
let size = t0.size.map(generics)?;
|
||||
|
||||
GType::Array(GArrayType { size, ty })
|
||||
}
|
||||
DeclarationType::FieldElement => GType::FieldElement,
|
||||
DeclarationType::Boolean => GType::Boolean,
|
||||
DeclarationType::Uint(b0) => GType::Uint(b0),
|
||||
DeclarationType::Struct(s0) => GType::Struct(GStructType {
|
||||
members: s0
|
||||
.members
|
||||
.into_iter()
|
||||
.map(|m| {
|
||||
let id = m.id;
|
||||
specialize_declaration_type(*m.ty, generics)
|
||||
.map(|ty| GStructMember { ty: box ty, id })
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
generics: s0
|
||||
.generics
|
||||
.into_iter()
|
||||
.map(|g| match g {
|
||||
Some(constant) => match constant {
|
||||
DeclarationConstant::Generic(s) => {
|
||||
generics.0.get(&s).cloned().ok_or(s).map(Some)
|
||||
}
|
||||
DeclarationConstant::Concrete(s) => Ok(Some(s.into())),
|
||||
DeclarationConstant::Constant(..) => {
|
||||
unreachable!(
|
||||
"identifiers should have been removed in constant inlining"
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => Ok(None),
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
canonical_location: s0.canonical_location,
|
||||
location: s0.location,
|
||||
}),
|
||||
DeclarationType::Struct(s0) => {
|
||||
// here we specialize Foo<Generics> {FooDef<InsideGenerics>} with some values for Generics
|
||||
// we need to remap these values for InsideGenerics to then visit the members
|
||||
|
||||
let inside_generics = GGenericsAssignment(
|
||||
s0.generics
|
||||
.clone()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(index, g)| {
|
||||
(
|
||||
GenericIdentifier::without_name().with_index(index),
|
||||
g.map(|g| g.map(generics).unwrap()).unwrap(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
|
||||
GType::Struct(GStructType {
|
||||
members: s0
|
||||
.members
|
||||
.into_iter()
|
||||
.map(|m| {
|
||||
let id = m.id;
|
||||
specialize_declaration_type(*m.ty, &inside_generics)
|
||||
.map(|ty| GStructMember { ty: box ty, id })
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
generics: s0
|
||||
.generics
|
||||
.into_iter()
|
||||
.map(|g| match g {
|
||||
Some(constant) => constant.map(generics).map(Some),
|
||||
_ => Ok(None),
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
canonical_location: s0.canonical_location,
|
||||
location: s0.location,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1097,7 +1135,7 @@ pub mod signature {
|
|||
}
|
||||
|
||||
pub type DeclarationSignature<'ast> = GSignature<DeclarationConstant<'ast>>;
|
||||
pub type ConcreteSignature = GSignature<usize>;
|
||||
pub type ConcreteSignature = GSignature<u32>;
|
||||
pub type Signature<'ast, T> = GSignature<UExpression<'ast, T>>;
|
||||
|
||||
impl<'ast> PartialEq<DeclarationSignature<'ast>> for ConcreteSignature {
|
||||
|
@ -1110,7 +1148,7 @@ pub mod signature {
|
|||
.iter()
|
||||
.chain(other.outputs.iter())
|
||||
.zip(self.inputs.iter().chain(self.outputs.iter()))
|
||||
.all(|(decl_ty, ty)| check_type::<usize>(decl_ty, ty, &mut constants))
|
||||
.all(|(decl_ty, ty)| check_type::<u32>(decl_ty, ty, &mut constants))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1135,7 +1173,7 @@ pub mod signature {
|
|||
constants.0.extend(
|
||||
decl_generics
|
||||
.zip(values.into_iter())
|
||||
.filter_map(|(g, v)| v.map(|v| (g, v as usize))),
|
||||
.filter_map(|(g, v)| v.map(|v| (g, v))),
|
||||
);
|
||||
|
||||
let condition = self
|
||||
|
@ -1367,33 +1405,19 @@ pub mod signature {
|
|||
|
||||
let generic1 = DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier {
|
||||
name: "P",
|
||||
index: 0,
|
||||
}
|
||||
.into(),
|
||||
GenericIdentifier::with_name("P").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::array(DeclarationArrayType::new(
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier {
|
||||
name: "P",
|
||||
index: 0,
|
||||
},
|
||||
GenericIdentifier::with_name("P").with_index(0),
|
||||
))]);
|
||||
let generic2 = DeclarationSignature::new()
|
||||
.generics(vec![Some(
|
||||
GenericIdentifier {
|
||||
name: "Q",
|
||||
index: 0,
|
||||
}
|
||||
.into(),
|
||||
GenericIdentifier::with_name("Q").with_index(0).into(),
|
||||
)])
|
||||
.inputs(vec![DeclarationType::array(DeclarationArrayType::new(
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier {
|
||||
name: "Q",
|
||||
index: 0,
|
||||
},
|
||||
GenericIdentifier::with_name("Q").with_index(0),
|
||||
))]);
|
||||
|
||||
assert_eq!(generic1, generic2);
|
||||
|
@ -1458,8 +1482,8 @@ pub mod signature {
|
|||
fn array_slug() {
|
||||
let s = ConcreteSignature::new()
|
||||
.inputs(vec![
|
||||
ConcreteType::array((ConcreteType::FieldElement, 42usize)),
|
||||
ConcreteType::array((ConcreteType::FieldElement, 21usize)),
|
||||
ConcreteType::array((ConcreteType::FieldElement, 42u32)),
|
||||
ConcreteType::array((ConcreteType::FieldElement, 21u32)),
|
||||
])
|
||||
.outputs(vec![]);
|
||||
|
||||
|
@ -1474,7 +1498,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn array() {
|
||||
let t = ConcreteType::Array(ConcreteArrayType::new(ConcreteType::FieldElement, 42usize));
|
||||
let t = ConcreteType::Array(ConcreteArrayType::new(ConcreteType::FieldElement, 42u32));
|
||||
assert_eq!(t.get_primitive_count(), 42);
|
||||
}
|
||||
|
||||
|
@ -1482,8 +1506,8 @@ mod tests {
|
|||
fn array_display() {
|
||||
// field[1][2]
|
||||
let t = ConcreteType::Array(ConcreteArrayType::new(
|
||||
ConcreteType::Array(ConcreteArrayType::new(ConcreteType::FieldElement, 2usize)),
|
||||
1usize,
|
||||
ConcreteType::Array(ConcreteArrayType::new(ConcreteType::FieldElement, 2u32)),
|
||||
1u32,
|
||||
));
|
||||
assert_eq!(format!("{}", t), "field[1][2]");
|
||||
}
|
||||
|
|
|
@ -146,12 +146,6 @@ pub struct UExpression<'ast, T> {
|
|||
pub inner: UExpressionInner<'ast, T>,
|
||||
}
|
||||
|
||||
impl<'ast, T> From<u32> for UExpression<'ast, T> {
|
||||
fn from(u: u32) -> Self {
|
||||
UExpressionInner::Value(u as u128).annotate(UBitwidth::B32)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> From<u16> for UExpression<'ast, T> {
|
||||
fn from(u: u16) -> Self {
|
||||
UExpressionInner::Value(u as u128).annotate(UBitwidth::B16)
|
||||
|
@ -164,8 +158,8 @@ impl<'ast, T> From<u8> for UExpression<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> PartialEq<usize> for UExpression<'ast, T> {
|
||||
fn eq(&self, other: &usize) -> bool {
|
||||
impl<'ast, T> PartialEq<u32> for UExpression<'ast, T> {
|
||||
fn eq(&self, other: &u32) -> bool {
|
||||
match self.as_inner() {
|
||||
UExpressionInner::Value(v) => *v == *other as u128,
|
||||
_ => true,
|
||||
|
|
|
@ -12,7 +12,7 @@ pub struct GVariable<'ast, S> {
|
|||
}
|
||||
|
||||
pub type DeclarationVariable<'ast> = GVariable<'ast, DeclarationConstant<'ast>>;
|
||||
pub type ConcreteVariable<'ast> = GVariable<'ast, usize>;
|
||||
pub type ConcreteVariable<'ast> = GVariable<'ast, u32>;
|
||||
pub type Variable<'ast, T> = GVariable<'ast, UExpression<'ast, T>>;
|
||||
|
||||
impl<'ast, T> TryFrom<Variable<'ast, T>> for ConcreteVariable<'ast> {
|
||||
|
|
|
@ -11,7 +11,7 @@ pub enum Identifier<'ast> {
|
|||
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
|
||||
pub enum SourceIdentifier<'ast> {
|
||||
Basic(CoreIdentifier<'ast>),
|
||||
Select(Box<SourceIdentifier<'ast>>, usize),
|
||||
Select(Box<SourceIdentifier<'ast>>, u32),
|
||||
Member(Box<SourceIdentifier<'ast>>, MemberId),
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ ace.define("ace/mode/zokrates_highlight_rules",["require","exports","module","ac
|
|||
var ZoKratesHighlightRules = function () {
|
||||
|
||||
var keywords = (
|
||||
"assert|as|bool|byte|const|def|do|else|endfor|export|false|field|for|if|then|fi|import|from|in|private|public|return|struct|true|u8|u16|u32|u64"
|
||||
"assert|as|bool|byte|const|def|do|else|endfor|export|false|field|for|if|then|fi|import|from|in|private|public|return|struct|true|type|u8|u16|u32|u64"
|
||||
);
|
||||
|
||||
var keywordMapper = this.createKeywordMapper({
|
||||
|
|
|
@ -202,19 +202,23 @@ repository:
|
|||
-
|
||||
comment: 'control flow keywords'
|
||||
name: keyword.control.zokrates
|
||||
match: \b(do|else|for|do|endfor|if|then|fi|return|assert)\b
|
||||
match: \b(for|in|do|endfor|if|then|else|fi|return|assert)\b
|
||||
-
|
||||
comment: 'storage keywords'
|
||||
name: storage.type.zokrates
|
||||
match: \b(struct)\b
|
||||
-
|
||||
comment: const
|
||||
comment: 'const keyword'
|
||||
name: keyword.other.const.zokrates
|
||||
match: \bconst\b
|
||||
match: \b(const)\b
|
||||
-
|
||||
comment: def
|
||||
comment: 'type keyword'
|
||||
name: keyword.other.type.zokrates
|
||||
match: \b(type)\b
|
||||
-
|
||||
comment: 'def keyword'
|
||||
name: keyword.other.def.zokrates
|
||||
match: \bdef\b
|
||||
match: \b(def)\b
|
||||
-
|
||||
comment: 'import keywords'
|
||||
name: keyword.other.import.zokrates
|
||||
|
|
Loading…
Reference in a new issue