1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

merge split

This commit is contained in:
schaeff 2022-07-04 17:02:48 +02:00
commit 81d670e531
382 changed files with 2783 additions and 4198 deletions

View file

@ -0,0 +1 @@
Introduce the `mut` keyword and make variables immutable by default

View file

@ -0,0 +1 @@
Remove multiple returns

View file

@ -0,0 +1 @@
Use signature output for constant parameter inference

View file

@ -277,7 +277,7 @@ fn parse_value<T: Field>(
.map_err(|_| Error::Type(format!("Could not parse `{}` to u64 type", s))),
(ConcreteType::Boolean, serde_json::Value::Bool(b)) => Ok(Value::Boolean(b)),
(ConcreteType::Array(array_type), serde_json::Value::Array(a)) => {
let size = array_type.size;
let size = *array_type.size;
if a.len() != size as usize {
Err(Error::Type(format!(
"Expected array of size {}, found array of size {}",

View file

@ -108,103 +108,6 @@ impl<T: Field + ArkFieldExtensions> Backend<T, GM17> for Ark {
}
}
// impl NonUniversalBackend<Bw6_761Field, GM17> for Ark {
// fn setup<I: IntoIterator<Item = Statement<Bw6_761Field>>>(
// program: ProgIterator<Bw6_761Field, I>,
// ) -> SetupKeypair<<GM17 as Scheme<Bw6_761Field>>::VerificationKey> {
// let computation = Computation::without_witness(program);
// let rng = &mut StdRng::from_entropy();
// let (pk, vk) = ArkGM17::<BW6_761>::circuit_specific_setup(computation, rng).unwrap();
// let mut pk_vec: Vec<u8> = Vec::new();
// pk.serialize_uncompressed(&mut pk_vec).unwrap();
// let vk = VerificationKey {
// h: parse_g2_fq::<Bw6_761Field>(&vk.h_g2),
// g_alpha: parse_g1::<Bw6_761Field>(&vk.g_alpha_g1),
// h_beta: parse_g2_fq::<Bw6_761Field>(&vk.h_beta_g2),
// g_gamma: parse_g1::<Bw6_761Field>(&vk.g_gamma_g1),
// h_gamma: parse_g2_fq::<Bw6_761Field>(&vk.h_gamma_g2),
// query: vk.query.iter().map(parse_g1::<Bw6_761Field>).collect(),
// };
// SetupKeypair::new(vk, pk_vec)
// }
// }
// impl Backend<Bw6_761Field, GM17> for Ark {
// fn generate_proof<I: IntoIterator<Item = Statement<Bw6_761Field>>>(
// program: ProgIterator<Bw6_761Field, I>,
// witness: Witness<Bw6_761Field>,
// proving_key: Vec<u8>,
// ) -> Proof<Bw6_761Field, GM17> {
// let computation = Computation::with_witness(program, witness);
// let inputs = computation
// .public_inputs_values()
// .iter()
// .map(parse_fr::<Bw6_761Field>)
// .collect::<Vec<_>>();
// let pk =
// ProvingKey::<<Bw6_761Field as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed(
// &mut proving_key.as_slice(),
// )
// .unwrap();
// let rng = &mut StdRng::from_entropy();
// let proof = ArkGM17::<BW6_761>::prove(&pk, computation, rng).unwrap();
// let proof_points = ProofPoints {
// a: parse_g1::<Bw6_761Field>(&proof.a),
// b: parse_g2_fq::<Bw6_761Field>(&proof.b),
// c: parse_g1::<Bw6_761Field>(&proof.c),
// };
// Proof::new(proof_points, inputs)
// }
// fn verify(
// vk: <GM17 as Scheme<Bw6_761Field>>::VerificationKey,
// proof: Proof<Bw6_761Field, GM17>,
// ) -> bool {
// let vk = VerifyingKey {
// h_g2: serialization::to_g2_fq::<Bw6_761Field>(vk.h),
// g_alpha_g1: serialization::to_g1::<Bw6_761Field>(vk.g_alpha),
// h_beta_g2: serialization::to_g2_fq::<Bw6_761Field>(vk.h_beta),
// g_gamma_g1: serialization::to_g1::<Bw6_761Field>(vk.g_gamma),
// h_gamma_g2: serialization::to_g2_fq::<Bw6_761Field>(vk.h_gamma),
// query: vk
// .query
// .into_iter()
// .map(serialization::to_g1::<Bw6_761Field>)
// .collect(),
// };
// let ark_proof = ArkProof {
// a: serialization::to_g1::<Bw6_761Field>(proof.proof.a),
// b: serialization::to_g2_fq::<Bw6_761Field>(proof.proof.b),
// c: serialization::to_g1::<Bw6_761Field>(proof.proof.c),
// };
// let pvk: PreparedVerifyingKey<<Bw6_761Field as ArkFieldExtensions>::ArkEngine> =
// prepare_verifying_key(&vk);
// let public_inputs: Vec<_> = proof
// .inputs
// .iter()
// .map(|s| {
// Bw6_761Field::try_from_str(s.trim_start_matches("0x"), 16)
// .unwrap()
// .into_ark()
// })
// .collect::<Vec<_>>();
// verify_proof(&pvk, &ark_proof, &public_inputs).unwrap()
// }
// }
#[cfg(test)]
mod tests {
use zokrates_ast::flat::{Parameter, Variable};

View file

@ -12,12 +12,6 @@ use zokrates_ast::common::Variable;
use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness};
use zokrates_field::{ArkFieldExtensions, Field};
use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field};
pub trait NotBw6_761Field {}
impl NotBw6_761Field for Bls12_377Field {}
impl NotBw6_761Field for Bls12_381Field {}
impl NotBw6_761Field for Bn128Field {}
pub use self::parse::*;
pub struct Ark;
@ -162,6 +156,7 @@ impl<T: Field + ArkFieldExtensions, I: IntoIterator<Item = Statement<T>>>
mod parse {
use super::*;
use ark_ff::ToBytes;
use zokrates_field::G2Type;
use zokrates_proof_systems::{Fr, G1Affine, G2Affine, G2AffineFq, G2AffineFq2};
pub fn parse_g1<T: Field + ArkFieldExtensions>(
@ -192,48 +187,46 @@ mod parse {
e.write(&mut bytes).unwrap();
let length = bytes.len() - 1; // [x, y, infinity] - infinity
let element_length = length / 4;
let mut elements = vec![];
for i in 0..4 {
let start = i * element_length;
let end = start + element_length;
let mut e = bytes[start..end].to_vec();
e.reverse();
elements.push(e);
match T::G2_TYPE {
G2Type::Fq2 => {
let element_length = length / 4;
let mut elements = vec![];
for i in 0..4 {
let start = i * element_length;
let end = start + element_length;
let mut e = bytes[start..end].to_vec();
e.reverse();
elements.push(e);
}
G2Affine::Fq2(G2AffineFq2(
(
format!("0x{}", hex::encode(&elements[0])),
format!("0x{}", hex::encode(&elements[1])),
),
(
format!("0x{}", hex::encode(&elements[2])),
format!("0x{}", hex::encode(&elements[3])),
),
))
}
G2Type::Fq => {
let element_length = length / 2;
let mut x = bytes[0..element_length].to_vec();
let mut y = bytes[element_length..length].to_vec();
x.reverse();
y.reverse();
G2Affine::Fq(G2AffineFq(
format!("0x{}", hex::encode(&x)),
format!("0x{}", hex::encode(&y)),
))
}
}
G2Affine::Fq2(G2AffineFq2(
(
format!("0x{}", hex::encode(&elements[0])),
format!("0x{}", hex::encode(&elements[1])),
),
(
format!("0x{}", hex::encode(&elements[2])),
format!("0x{}", hex::encode(&elements[3])),
),
))
}
pub fn parse_g2_fq<T: ArkFieldExtensions>(
e: &<T::ArkEngine as PairingEngine>::G2Affine,
) -> G2Affine {
let mut bytes: Vec<u8> = Vec::new();
e.write(&mut bytes).unwrap();
let length = bytes.len() - 1; // [x, y, infinity] - infinity
let element_length = length / 2;
let mut x = bytes[0..element_length].to_vec();
let mut y = bytes[element_length..length].to_vec();
x.reverse();
y.reverse();
G2Affine::Fq(G2AffineFq(
format!("0x{}", hex::encode(&x)),
format!("0x{}", hex::encode(&y)),
))
}
pub fn parse_fr<T: ArkFieldExtensions>(e: &<T::ArkEngine as PairingEngine>::Fr) -> Fr {

View file

@ -62,66 +62,76 @@ impl FlatEmbed {
)
.into(),
])
.outputs(vec![UnresolvedType::Boolean.into()]),
.output(UnresolvedType::Boolean.into()),
FlatEmbed::Unpack => UnresolvedSignature::new()
.generics(vec!["N".into()])
.inputs(vec![UnresolvedType::FieldElement.into()])
.outputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::Identifier("N").into(),
)
.into()]),
.output(
UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::Identifier("N").into(),
)
.into(),
),
FlatEmbed::U8ToBits => UnresolvedSignature::new()
.inputs(vec![UnresolvedType::Uint(8).into()])
.outputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(8).into(),
)
.into()]),
.output(
UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(8).into(),
)
.into(),
),
FlatEmbed::U16ToBits => UnresolvedSignature::new()
.inputs(vec![UnresolvedType::Uint(16).into()])
.outputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(16).into(),
)
.into()]),
.output(
UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(16).into(),
)
.into(),
),
FlatEmbed::U32ToBits => UnresolvedSignature::new()
.inputs(vec![UnresolvedType::Uint(32).into()])
.outputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(32).into(),
)
.into()]),
.output(
UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(32).into(),
)
.into(),
),
FlatEmbed::U64ToBits => UnresolvedSignature::new()
.inputs(vec![UnresolvedType::Uint(64).into()])
.outputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(64).into(),
)
.into()]),
.output(
UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(64).into(),
)
.into(),
),
FlatEmbed::U8FromBits => UnresolvedSignature::new()
.outputs(vec![UnresolvedType::Uint(8).into()])
.output(UnresolvedType::Uint(8).into())
.inputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(8).into(),
)
.into()]),
FlatEmbed::U16FromBits => UnresolvedSignature::new()
.outputs(vec![UnresolvedType::Uint(16).into()])
.output(UnresolvedType::Uint(16).into())
.inputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(16).into(),
)
.into()]),
FlatEmbed::U32FromBits => UnresolvedSignature::new()
.outputs(vec![UnresolvedType::Uint(32).into()])
.output(UnresolvedType::Uint(32).into())
.inputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(32).into(),
)
.into()]),
FlatEmbed::U64FromBits => UnresolvedSignature::new()
.outputs(vec![UnresolvedType::Uint(64).into()])
.output(UnresolvedType::Uint(64).into())
.inputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(64).into(),
@ -141,11 +151,13 @@ impl FlatEmbed {
)
.into(),
])
.outputs(vec![UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(256).into(),
)
.into()]),
.output(
UnresolvedType::array(
UnresolvedType::Boolean.into(),
Expression::U32Constant(256).into(),
)
.into(),
),
#[cfg(feature = "ark")]
FlatEmbed::SnarkVerifyBls12377 => UnresolvedSignature::new()
.generics(vec!["N".into(), "V".into()])
@ -166,7 +178,7 @@ impl FlatEmbed {
)
.into(), // 18 + (2 * n) // vk
])
.outputs(vec![UnresolvedType::Boolean.into()]),
.output(UnresolvedType::Boolean.into()),
}
}
@ -186,60 +198,48 @@ impl FlatEmbed {
GenericIdentifier::with_name("N").with_index(0),
)),
])
.outputs(vec![DeclarationType::Boolean]),
.output(DeclarationType::Boolean),
FlatEmbed::Unpack => DeclarationSignature::new()
.generics(vec![Some(DeclarationConstant::Generic(
GenericIdentifier::with_name("N").with_index(0),
))])
.inputs(vec![DeclarationType::FieldElement])
.outputs(vec![DeclarationType::array((
.output(DeclarationType::array((
DeclarationType::Boolean,
GenericIdentifier::with_name("N").with_index(0),
))]),
))),
FlatEmbed::U8ToBits => DeclarationSignature::new()
.inputs(vec![DeclarationType::uint(8)])
.outputs(vec![DeclarationType::array((
DeclarationType::Boolean,
8u32,
))]),
.output(DeclarationType::array((DeclarationType::Boolean, 8u32))),
FlatEmbed::U16ToBits => DeclarationSignature::new()
.inputs(vec![DeclarationType::uint(16)])
.outputs(vec![DeclarationType::array((
DeclarationType::Boolean,
16u32,
))]),
.output(DeclarationType::array((DeclarationType::Boolean, 16u32))),
FlatEmbed::U32ToBits => DeclarationSignature::new()
.inputs(vec![DeclarationType::uint(32)])
.outputs(vec![DeclarationType::array((
DeclarationType::Boolean,
32u32,
))]),
.output(DeclarationType::array((DeclarationType::Boolean, 32u32))),
FlatEmbed::U64ToBits => DeclarationSignature::new()
.inputs(vec![DeclarationType::uint(64)])
.outputs(vec![DeclarationType::array((
DeclarationType::Boolean,
64u32,
))]),
.output(DeclarationType::array((DeclarationType::Boolean, 64u32))),
FlatEmbed::U8FromBits => DeclarationSignature::new()
.outputs(vec![DeclarationType::uint(8)])
.output(DeclarationType::uint(8))
.inputs(vec![DeclarationType::array((
DeclarationType::Boolean,
8u32,
))]),
FlatEmbed::U16FromBits => DeclarationSignature::new()
.outputs(vec![DeclarationType::uint(16)])
.output(DeclarationType::uint(16))
.inputs(vec![DeclarationType::array((
DeclarationType::Boolean,
16u32,
))]),
FlatEmbed::U32FromBits => DeclarationSignature::new()
.outputs(vec![DeclarationType::uint(32)])
.output(DeclarationType::uint(32))
.inputs(vec![DeclarationType::array((
DeclarationType::Boolean,
32u32,
))]),
FlatEmbed::U64FromBits => DeclarationSignature::new()
.outputs(vec![DeclarationType::uint(64)])
.output(DeclarationType::uint(64))
.inputs(vec![DeclarationType::array((
DeclarationType::Boolean,
64u32,
@ -250,10 +250,7 @@ impl FlatEmbed {
DeclarationType::array((DeclarationType::Boolean, 512u32)),
DeclarationType::array((DeclarationType::Boolean, 256u32)),
])
.outputs(vec![DeclarationType::array((
DeclarationType::Boolean,
256u32,
))]),
.output(DeclarationType::array((DeclarationType::Boolean, 256u32))),
#[cfg(feature = "ark")]
FlatEmbed::SnarkVerifyBls12377 => DeclarationSignature::new()
.generics(vec![
@ -275,7 +272,7 @@ impl FlatEmbed {
GenericIdentifier::with_name("V").with_index(1),
)), // 18 + (2 * n) // vk
])
.outputs(vec![DeclarationType::Boolean]),
.output(DeclarationType::Boolean),
}
}
@ -693,73 +690,60 @@ mod tests {
}
}
// MOVE TO CORE
// #[cfg(feature = "bellman")]
// #[cfg(test)]
// mod sha256 {
// use super::*;
// use crate::ir::Interpreter;
#[cfg(feature = "bellman")]
#[cfg(test)]
mod sha256 {
use super::*;
// #[test]
// fn generate_sha256_constraints() {
// let compiled = sha256_round::<Bn128Field>();
#[test]
fn generate_sha256_constraints() {
let compiled = sha256_round::<Bn128Field>();
// let compiled = compiled.collect();
let compiled = compiled.collect();
// // function should have 768 inputs
// assert_eq!(compiled.arguments.len(), 768);
// function should have 768 inputs
assert_eq!(compiled.arguments.len(), 768);
// // function should return 256 values
// assert_eq!(compiled.return_count, 256,);
// function should return 256 values
assert_eq!(compiled.return_count, 256,);
// // directive should take 768 inputs and return n_var outputs
// let directive = compiled
// .statements
// .iter()
// .filter_map(|s| match s {
// FlatStatement::Directive(d) => Some(d.clone()),
// _ => None,
// })
// .next()
// .unwrap();
// assert_eq!(directive.inputs.len(), 768);
// assert_eq!(directive.outputs.len(), 26935);
// // function input should be offset by variable_count
// assert_eq!(
// compiled.arguments[0].id,
// Variable::new(directive.outputs.len() + 1)
// );
// directive should take 768 inputs and return n_var outputs
let directive = compiled
.statements
.iter()
.filter_map(|s| match s {
FlatStatement::Directive(d) => Some(d.clone()),
_ => None,
})
.next()
.unwrap();
assert_eq!(directive.inputs.len(), 768);
assert_eq!(directive.outputs.len(), 26935);
// function input should be offset by variable_count
assert_eq!(
compiled.arguments[0].id,
Variable::new(directive.outputs.len() + 1)
);
// // bellman variable #0: index 0 should equal 1
// assert_eq!(
// compiled.statements[1],
// FlatStatement::Condition(
// Variable::new(0).into(),
// FlatExpression::Number(Bn128Field::from(1)),
// RuntimeError::BellmanOneBinding
// )
// );
// bellman variable #0: index 0 should equal 1
assert_eq!(
compiled.statements[1],
FlatStatement::Condition(
Variable::new(0).into(),
FlatExpression::Number(Bn128Field::from(1)),
RuntimeError::BellmanOneBinding
)
);
// // bellman input #0: index 1 should equal zokrates input #0: index v_count
// assert_eq!(
// compiled.statements[2],
// FlatStatement::Condition(
// Variable::new(1).into(),
// Variable::new(26936).into(),
// RuntimeError::BellmanInputBinding
// )
// );
// let input: Vec<_> = (0..512)
// .map(|_| 0)
// .chain((0..256).map(|_| 1))
// .map(Bn128Field::from)
// .collect();
// let ir = zokrates_ast::ir::from_flat::from_flat(compiled);
// let interpreter = Interpreter::default();
// interpreter.execute(ir, &input).unwrap();
// }
// }
// bellman input #0: index 1 should equal zokrates input #0: index v_count
assert_eq!(
compiled.statements[2],
FlatStatement::Condition(
Variable::new(1).into(),
Variable::new(26936).into(),
RuntimeError::BellmanInputBinding
)
);
}
}
}

View file

@ -14,7 +14,7 @@ pub type AbiOutput = ConcreteType;
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct Abi {
pub inputs: Vec<AbiInput>,
pub outputs: Vec<AbiOutput>,
pub output: AbiOutput,
}
impl Abi {
@ -22,7 +22,7 @@ impl Abi {
ConcreteSignature {
generics: vec![],
inputs: self.inputs.iter().map(|i| i.ty.clone()).collect(),
outputs: self.outputs.clone(),
output: box self.output.clone(),
}
}
}
@ -31,8 +31,10 @@ impl Abi {
mod tests {
use super::*;
use crate::typed::types::{
ConcreteArrayType, ConcreteFunctionKey, ConcreteStructMember, ConcreteStructType, UBitwidth,
ConcreteArrayType, ConcreteFunctionKey, ConcreteStructMember, ConcreteStructType,
GTupleType, UBitwidth,
};
use crate::typed::DeclarationType;
use crate::typed::{
parameter::DeclarationParameter, variable::DeclarationVariable, ConcreteTupleType,
ConcreteType, TypedFunction, TypedFunctionSymbol, TypedFunctionSymbolDeclaration,
@ -48,18 +50,18 @@ mod tests {
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![
DeclarationParameter {
id: DeclarationVariable::field_element("a"),
id: DeclarationVariable::new("a", DeclarationType::FieldElement, true),
private: true,
},
DeclarationParameter {
id: DeclarationVariable::boolean("b"),
id: DeclarationVariable::new("b", DeclarationType::Boolean, false),
private: false,
},
],
statements: vec![],
signature: ConcreteSignature::new()
.inputs(vec![ConcreteType::FieldElement, ConcreteType::Boolean])
.outputs(vec![ConcreteType::FieldElement])
.output(ConcreteType::FieldElement)
.into(),
}),
)
@ -87,7 +89,7 @@ mod tests {
ty: ConcreteType::Boolean,
},
],
outputs: vec![ConcreteType::FieldElement],
output: ConcreteType::FieldElement,
};
assert_eq!(expected_abi, abi);
@ -97,11 +99,14 @@ mod tests {
fn serialize_empty() {
let abi: Abi = Abi {
inputs: vec![],
outputs: vec![],
output: ConcreteType::Tuple(GTupleType::new(vec![])),
};
let json = serde_json::to_string(&abi).unwrap();
assert_eq!(&json, r#"{"inputs":[],"outputs":[]}"#);
assert_eq!(
&json,
r#"{"inputs":[],"output":{"type":"tuple","components":{"elements":[]}}}"#
);
let de_abi: Abi = serde_json::from_str(json.as_ref()).unwrap();
assert_eq!(de_abi, abi);
}
@ -113,7 +118,7 @@ mod tests {
let abi: Abi = Abi {
inputs: vec![],
outputs: vec![ConcreteType::Int],
output: ConcreteType::Int,
};
let _ = serde_json::to_string_pretty(&abi).unwrap();
@ -134,7 +139,7 @@ mod tests {
ty: ConcreteType::FieldElement,
},
],
outputs: vec![ConcreteType::FieldElement],
output: ConcreteType::FieldElement,
};
let json = serde_json::to_string_pretty(&abi).unwrap();
@ -153,11 +158,9 @@ mod tests {
"type": "field"
}
],
"outputs": [
{
"type": "field"
}
]
"output": {
"type": "field"
}
}"#
);
@ -185,7 +188,7 @@ mod tests {
ty: ConcreteType::Uint(UBitwidth::B32),
},
],
outputs: vec![],
output: ConcreteType::Tuple(GTupleType::new(vec![])),
};
let json = serde_json::to_string_pretty(&abi).unwrap();
@ -209,7 +212,12 @@ mod tests {
"type": "u32"
}
],
"outputs": []
"output": {
"type": "tuple",
"components": {
"elements": []
}
}
}"#
);
@ -236,7 +244,7 @@ mod tests {
)],
)),
}],
outputs: vec![ConcreteType::Struct(ConcreteStructType::new(
output: ConcreteType::Struct(ConcreteStructType::new(
"".into(),
"Foo".into(),
vec![],
@ -244,7 +252,7 @@ mod tests {
ConcreteStructMember::new(String::from("a"), ConcreteType::FieldElement),
ConcreteStructMember::new(String::from("b"), ConcreteType::Boolean),
],
))],
)),
};
let json = serde_json::to_string_pretty(&abi).unwrap();
@ -274,25 +282,23 @@ mod tests {
}
}
],
"outputs": [
{
"type": "struct",
"components": {
"name": "Foo",
"generics": [],
"members": [
{
"name": "a",
"type": "field"
},
{
"name": "b",
"type": "bool"
}
]
}
"output": {
"type": "struct",
"components": {
"name": "Foo",
"generics": [],
"members": [
{
"name": "a",
"type": "field"
},
{
"name": "b",
"type": "bool"
}
]
}
]
}
}"#
);
@ -330,7 +336,7 @@ mod tests {
)],
)),
}],
outputs: vec![],
output: ConcreteType::Tuple(GTupleType::new(vec![])),
};
let json = serde_json::to_string_pretty(&abi).unwrap();
@ -368,7 +374,12 @@ mod tests {
}
}
],
"outputs": []
"output": {
"type": "tuple",
"components": {
"elements": []
}
}
}"#
);
@ -398,7 +409,7 @@ mod tests {
2u32,
)),
}],
outputs: vec![ConcreteType::Boolean],
output: ConcreteType::Boolean,
};
let json = serde_json::to_string_pretty(&abi).unwrap();
@ -430,11 +441,9 @@ mod tests {
}
}
],
"outputs": [
{
"type": "bool"
}
]
"output": {
"type": "bool"
}
}"#
);
@ -453,7 +462,7 @@ mod tests {
2u32,
)),
}],
outputs: vec![ConcreteType::FieldElement],
output: ConcreteType::FieldElement,
};
let json = serde_json::to_string_pretty(&abi).unwrap();
@ -475,11 +484,9 @@ mod tests {
}
}
],
"outputs": [
{
"type": "field"
}
]
"output": {
"type": "field"
}
}"#
);
@ -498,9 +505,7 @@ mod tests {
ConcreteType::Boolean,
])),
}],
outputs: vec![ConcreteType::Tuple(ConcreteTupleType::new(vec![
ConcreteType::FieldElement,
]))],
output: ConcreteType::Tuple(ConcreteTupleType::new(vec![ConcreteType::FieldElement])),
};
let json = serde_json::to_string_pretty(&abi).unwrap();
@ -524,18 +529,16 @@ mod tests {
}
}
],
"outputs": [
{
"type": "tuple",
"components": {
"elements": [
{
"type": "field"
}
]
}
"output": {
"type": "tuple",
"components": {
"elements": [
{
"type": "field"
}
]
}
]
}
}"#
);

View file

@ -142,6 +142,7 @@ pub trait Folder<'ast, T: Field>: Sized {
Variable {
id: self.fold_name(v.id),
_type: self.fold_type(v._type),
is_mutable: v.is_mutable,
}
}
@ -152,6 +153,7 @@ pub trait Folder<'ast, T: Field>: Sized {
DeclarationVariable {
id: self.fold_name(v.id),
_type: self.fold_declaration_type(v._type),
is_mutable: v.is_mutable,
}
}
@ -166,14 +168,10 @@ pub trait Folder<'ast, T: Field>: Sized {
}
}
fn fold_types(&mut self, tys: Types<'ast, T>) -> Types<'ast, T> {
fold_types(self, tys)
}
fn fold_array_type(&mut self, t: ArrayType<'ast, T>) -> ArrayType<'ast, T> {
ArrayType {
ty: box self.fold_type(*t.ty),
size: self.fold_uint_expression(t.size),
size: box self.fold_uint_expression(*t.size),
}
}
@ -219,7 +217,7 @@ pub trait Folder<'ast, T: Field>: Sized {
) -> DeclarationArrayType<'ast, T> {
DeclarationArrayType {
ty: box self.fold_declaration_type(*t.ty),
size: self.fold_declaration_constant(t.size),
size: box self.fold_declaration_constant(*t.size),
}
}
@ -266,6 +264,10 @@ pub trait Folder<'ast, T: Field>: Sized {
fold_statement(self, s)
}
fn fold_embed_call(&mut self, e: EmbedCall<'ast, T>) -> EmbedCall<'ast, T> {
fold_embed_call(self, e)
}
fn fold_expression_or_spread(
&mut self,
e: TypedExpressionOrSpread<'ast, T>,
@ -301,15 +303,7 @@ pub trait Folder<'ast, T: Field>: Sized {
}
fn fold_expression(&mut self, e: TypedExpression<'ast, T>) -> TypedExpression<'ast, T> {
match e {
TypedExpression::FieldElement(e) => self.fold_field_expression(e).into(),
TypedExpression::Boolean(e) => self.fold_boolean_expression(e).into(),
TypedExpression::Uint(e) => self.fold_uint_expression(e).into(),
TypedExpression::Array(e) => self.fold_array_expression(e).into(),
TypedExpression::Tuple(e) => self.fold_tuple_expression(e).into(),
TypedExpression::Struct(e) => self.fold_struct_expression(e).into(),
TypedExpression::Int(e) => self.fold_int_expression(e).into(),
}
fold_expression(self, e)
}
fn fold_block_expression<E: Fold<'ast, T>>(
@ -395,21 +389,6 @@ pub trait Folder<'ast, T: Field>: Sized {
fold_tuple_expression(self, e)
}
fn fold_expression_list(
&mut self,
es: TypedExpressionList<'ast, T>,
) -> TypedExpressionList<'ast, T> {
fold_expression_list(self, es)
}
fn fold_expression_list_inner(
&mut self,
tys: Types<'ast, T>,
es: TypedExpressionListInner<'ast, T>,
) -> TypedExpressionListInner<'ast, T> {
fold_expression_list_inner(self, tys, es)
}
fn fold_int_expression(&mut self, e: IntExpression<'ast, T>) -> IntExpression<'ast, T> {
fold_int_expression(self, e)
}
@ -420,12 +399,14 @@ pub trait Folder<'ast, T: Field>: Sized {
) -> FieldElementExpression<'ast, T> {
fold_field_expression(self, e)
}
fn fold_boolean_expression(
&mut self,
e: BooleanExpression<'ast, T>,
) -> BooleanExpression<'ast, T> {
fold_boolean_expression(self, e)
}
fn fold_uint_expression(&mut self, e: UExpression<'ast, T>) -> UExpression<'ast, T> {
fold_uint_expression(self, e)
}
@ -515,16 +496,10 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
s: TypedStatement<'ast, T>,
) -> Vec<TypedStatement<'ast, T>> {
let res = match s {
TypedStatement::Return(expressions) => TypedStatement::Return(
expressions
.into_iter()
.map(|e| f.fold_expression(e))
.collect(),
),
TypedStatement::Return(e) => TypedStatement::Return(f.fold_expression(e)),
TypedStatement::Definition(a, e) => {
TypedStatement::Definition(f.fold_assignee(a), f.fold_expression(e))
}
TypedStatement::Declaration(v) => TypedStatement::Declaration(f.fold_variable(v)),
TypedStatement::Assertion(e, error) => {
TypedStatement::Assertion(f.fold_boolean_expression(e), error)
}
@ -537,18 +512,49 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
.flat_map(|s| f.fold_statement(s))
.collect(),
),
TypedStatement::MultipleDefinition(assignees, elist) => TypedStatement::MultipleDefinition(
assignees.into_iter().map(|a| f.fold_assignee(a)).collect(),
f.fold_expression_list(elist),
),
TypedStatement::Log(s, e) => {
TypedStatement::Log(s, e.into_iter().map(|e| f.fold_expression(e)).collect())
}
TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
TypedStatement::EmbedCallDefinition(
f.fold_assignee(assignee),
f.fold_embed_call(embed_call),
)
}
s => s,
};
vec![res]
}
pub fn fold_embed_call<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
e: EmbedCall<'ast, T>,
) -> EmbedCall<'ast, T> {
EmbedCall {
arguments: e
.arguments
.into_iter()
.map(|s| f.fold_expression(s))
.collect(),
..e
}
}
pub fn fold_expression<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
e: TypedExpression<'ast, T>,
) -> TypedExpression<'ast, T> {
match e {
TypedExpression::FieldElement(e) => f.fold_field_expression(e).into(),
TypedExpression::Boolean(e) => f.fold_boolean_expression(e).into(),
TypedExpression::Uint(e) => f.fold_uint_expression(e).into(),
TypedExpression::Array(e) => f.fold_array_expression(e).into(),
TypedExpression::Tuple(e) => f.fold_tuple_expression(e).into(),
TypedExpression::Struct(e) => f.fold_struct_expression(e).into(),
TypedExpression::Int(e) => f.fold_int_expression(e).into(),
}
}
pub fn fold_array_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
ty: &ArrayType<'ast, T>,
@ -1137,11 +1143,7 @@ fn fold_signature<'ast, T: Field, F: Folder<'ast, T>>(
.into_iter()
.map(|o| f.fold_declaration_type(o))
.collect(),
outputs: s
.outputs
.into_iter()
.map(|o| f.fold_declaration_type(o))
.collect(),
output: box f.fold_declaration_type(*s.output),
}
}
@ -1170,54 +1172,6 @@ pub fn fold_array_expression<'ast, T: Field, F: Folder<'ast, T>>(
}
}
pub fn fold_expression_list<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
es: TypedExpressionList<'ast, T>,
) -> TypedExpressionList<'ast, T> {
let types = f.fold_types(es.types);
TypedExpressionList {
inner: f.fold_expression_list_inner(types.clone(), es.inner),
types,
}
}
pub fn fold_types<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
tys: Types<'ast, T>,
) -> Types<'ast, T> {
Types {
inner: tys.inner.into_iter().map(|t| f.fold_type(t)).collect(),
}
}
pub fn fold_expression_list_inner<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
tys: Types<'ast, T>,
es: TypedExpressionListInner<'ast, T>,
) -> TypedExpressionListInner<'ast, T> {
match es {
TypedExpressionListInner::FunctionCall(function_call) => {
match f.fold_function_call_expression(&tys, function_call) {
FunctionCallOrExpression::FunctionCall(function_call) => {
TypedExpressionListInner::FunctionCall(function_call)
}
FunctionCallOrExpression::Expression(u) => u,
}
}
TypedExpressionListInner::EmbedCall(embed, generics, arguments) => {
TypedExpressionListInner::EmbedCall(
embed,
generics,
arguments
.into_iter()
.map(|a| f.fold_expression(a))
.collect(),
)
}
}
}
pub fn fold_struct_expression<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
e: StructExpression<'ast, T>,

View file

@ -86,7 +86,7 @@ impl<'ast, T: Clone> IntegerInference for ArrayType<'ast, T> {
Ok(DeclarationArrayType::new(
self.ty
.get_common_pattern(*other.ty)
.map_err(|(t, u)| (ArrayType::new(t, s0), ArrayType::new(u, s1)))?,
.map_err(|(t, u)| (ArrayType::new(t, *s0), ArrayType::new(u, *s1)))?,
DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY")), // sizes are not checked at this stage, therefore we insert a dummy generic variable which will be equal to all possible sizes
))
}
@ -659,28 +659,28 @@ impl<'ast, T: Field> ArrayExpression<'ast, T> {
let inner_ty = res.0[0].get_type().0;
Ok(ArrayExpressionInner::Value(res).annotate(inner_ty, array_ty.size))
Ok(ArrayExpressionInner::Value(res).annotate(inner_ty, *array_ty.size))
}
ArrayExpressionInner::Repeat(box e, box count) => {
match &*target_array_ty.ty {
GType::Int => Ok(ArrayExpressionInner::Repeat(box e, box count)
.annotate(Type::Int, array_ty.size)),
.annotate(Type::Int, *array_ty.size)),
// try to align the repeated element to the target type
t => TypedExpression::align_to_type(e, t)
.map(|e| {
let ty = e.get_type().clone();
ArrayExpressionInner::Repeat(box e, box count)
.annotate(ty, array_ty.size)
.annotate(ty, *array_ty.size)
})
.map_err(|(e, _)| e),
}
}
a => {
if *target_array_ty.ty == *array_ty.ty {
Ok(a.annotate(*array_ty.ty, array_ty.size))
Ok(a.annotate(*array_ty.ty, *array_ty.size))
} else {
Err(a.annotate(*array_ty.ty, array_ty.size).into())
Err(a.annotate(*array_ty.ty, *array_ty.size).into())
}
}
}

View file

@ -22,10 +22,11 @@ pub use self::types::{
CanonicalConstantIdentifier, ConcreteFunctionKey, ConcreteSignature, ConcreteTupleType,
ConcreteType, ConstantIdentifier, DeclarationArrayType, DeclarationConstant,
DeclarationFunctionKey, DeclarationSignature, DeclarationStructType, DeclarationType,
GArrayType, GStructType, GType, GenericIdentifier, IntoTypes, Signature, StructType, TupleType,
Type, Types, UBitwidth,
GArrayType, GStructType, GType, GenericIdentifier, Signature, StructType, TupleType, Type,
UBitwidth,
};
use crate::typed::types::ConcreteGenericsAssignment;
use crate::typed::types::{ConcreteGenericsAssignment, IntoType};
use crate::untyped::Position;
pub use self::variable::{ConcreteVariable, DeclarationVariable, GVariable, Variable};
@ -117,21 +118,13 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
.unwrap()
})
.collect(),
outputs: main
.signature
.outputs
.iter()
.map(|ty| {
types::ConcreteType::try_from(
crate::typed::types::try_from_g_type::<
DeclarationConstant<'ast, T>,
UExpression<'ast, T>,
>(ty.clone())
.unwrap(),
)
.unwrap()
})
.collect(),
output: types::ConcreteType::try_from(
types::try_from_g_type::<DeclarationConstant<'ast, T>, UExpression<'ast, T>>(
*main.signature.output.clone(),
)
.unwrap(),
)
.unwrap(),
}
}
}
@ -356,23 +349,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> {
.join(", "),
)?;
write!(
f,
"{} {{",
match self.signature.outputs.len() {
0 => "".into(),
1 => format!(" -> {}", self.signature.outputs[0]),
_ => format!(
" -> ({})",
self.signature
.outputs
.iter()
.map(|x| format!("{}", x))
.collect::<Vec<_>>()
.join(", ")
),
}
)?;
write!(f, " -> {} {{", self.signature.output)?;
writeln!(f)?;
@ -622,13 +599,59 @@ impl fmt::Display for RuntimeError {
}
}
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct EmbedCall<'ast, T> {
pub embed: FlatEmbed,
pub generics: Vec<u32>,
pub arguments: Vec<TypedExpression<'ast, T>>,
}
impl<'ast, T> EmbedCall<'ast, T> {
pub fn new(
embed: FlatEmbed,
generics: Vec<u32>,
arguments: Vec<TypedExpression<'ast, T>>,
) -> Self {
Self {
embed,
generics,
arguments,
}
}
}
impl<'ast, T: fmt::Display> fmt::Display for EmbedCall<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.embed.id())?;
if !self.generics.is_empty() {
write!(
f,
"::<{}>",
self.generics
.iter()
.map(|g| g.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
}
write!(f, "(")?;
let len = self.arguments.len();
for (i, arg) in self.arguments.iter().enumerate() {
write!(f, "{}", arg)?;
if i < len - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
/// A statement in a `TypedFunction`
#[allow(clippy::large_enum_variant)]
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
pub enum TypedStatement<'ast, T> {
Return(Vec<TypedExpression<'ast, T>>),
Return(TypedExpression<'ast, T>),
Definition(TypedAssignee<'ast, T>, TypedExpression<'ast, T>),
Declaration(Variable<'ast, T>),
Assertion(BooleanExpression<'ast, T>, RuntimeError),
For(
Variable<'ast, T>,
@ -636,8 +659,8 @@ pub enum TypedStatement<'ast, T> {
UExpression<'ast, T>,
Vec<TypedStatement<'ast, T>>,
),
MultipleDefinition(Vec<TypedAssignee<'ast, T>>, TypedExpressionList<'ast, T>),
Log(FormatString, Vec<TypedExpression<'ast, T>>),
EmbedCallDefinition(TypedAssignee<'ast, T>, EmbedCall<'ast, T>),
// Aux
PushCallLog(
DeclarationFunctionKey<'ast, T>,
@ -666,17 +689,9 @@ impl<'ast, T: fmt::Display> TypedStatement<'ast, T> {
impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TypedStatement::Return(ref exprs) => {
write!(f, "return ")?;
for (i, expr) in exprs.iter().enumerate() {
write!(f, "{}", expr)?;
if i < exprs.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ";")
TypedStatement::Return(ref e) => {
write!(f, "return {};", e)
}
TypedStatement::Declaration(ref var) => write!(f, "{};", var),
TypedStatement::Definition(ref lhs, ref rhs) => write!(f, "{} = {};", lhs, rhs),
TypedStatement::Assertion(ref e, ref error) => {
write!(f, "assert({}", e)?;
@ -695,14 +710,8 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
}
write!(f, "\t}}")
}
TypedStatement::MultipleDefinition(ref ids, ref rhs) => {
for (i, id) in ids.iter().enumerate() {
write!(f, "{}", id)?;
if i < ids.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, " = {};", rhs)
TypedStatement::EmbedCallDefinition(ref lhs, ref rhs) => {
write!(f, "{} = {};", lhs, rhs)
}
TypedStatement::Log(ref l, ref expressions) => write!(
f,
@ -883,41 +892,6 @@ impl<'ast, T: Clone> Typed<'ast, T> for BooleanExpression<'ast, T> {
}
}
pub trait MultiTyped<'ast, T> {
fn get_types(&self) -> &Vec<Type<'ast, T>>;
}
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
pub struct TypedExpressionList<'ast, T> {
pub inner: TypedExpressionListInner<'ast, T>,
pub types: Types<'ast, T>,
}
impl<'ast, T: fmt::Display> fmt::Display for TypedExpressionList<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.inner)
}
}
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
pub enum TypedExpressionListInner<'ast, T> {
FunctionCall(FunctionCallExpression<'ast, T, TypedExpressionList<'ast, T>>),
EmbedCall(FlatEmbed, Vec<u32>, Vec<TypedExpression<'ast, T>>),
}
impl<'ast, T> MultiTyped<'ast, T> for TypedExpressionList<'ast, T> {
fn get_types(&self) -> &Vec<Type<'ast, T>> {
&self.types.inner
}
}
impl<'ast, T> TypedExpressionListInner<'ast, T> {
pub fn annotate(self, types: Types<'ast, T>) -> TypedExpressionList<'ast, T> {
TypedExpressionList { inner: self, types }
}
}
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
pub struct EqExpression<E> {
pub left: Box<E>,
@ -1305,7 +1279,7 @@ impl<'ast, T: Field> ArrayValue<'ast, T> {
.map(|i| {
Some(U::select(
a.clone()
.annotate(*array_ty.ty.clone(), array_ty.size.clone()),
.annotate(*array_ty.ty.clone(), *array_ty.size.clone()),
i as u32,
))
})
@ -1381,7 +1355,7 @@ impl<'ast, T: Clone> ArrayExpression<'ast, T> {
}
pub fn size(&self) -> UExpression<'ast, T> {
self.ty.size.clone()
*self.ty.size.clone()
}
}
@ -1568,15 +1542,6 @@ impl<'ast, T> From<TypedExpression<'ast, T>> for TupleExpression<'ast, T> {
}
}
// `TypedExpressionList` can technically not be constructed from `TypedExpression`
// However implementing `From<TypedExpression>` is required for `TypedExpressionList` to be `Expr`, which makes generic treatment of function calls possible
// This could maybe be avoided by splitting the `Expr` trait into many, but I did not find a way
impl<'ast, T> From<TypedExpression<'ast, T>> for TypedExpressionList<'ast, T> {
fn from(_: TypedExpression<'ast, T>) -> TypedExpressionList<'ast, T> {
unreachable!()
}
}
impl<'ast, T> From<TypedConstant<'ast, T>> for FieldElementExpression<'ast, T> {
fn from(tc: TypedConstant<'ast, T>) -> FieldElementExpression<'ast, T> {
tc.expression.into()
@ -1750,38 +1715,6 @@ impl<'ast, T: fmt::Display> fmt::Display for ArrayExpressionInner<'ast, T> {
}
}
impl<'ast, T: fmt::Display> fmt::Display for TypedExpressionListInner<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TypedExpressionListInner::FunctionCall(ref function_call) => {
write!(f, "{}", function_call)
}
TypedExpressionListInner::EmbedCall(ref embed, ref generics, ref p) => {
write!(f, "{}", embed.id())?;
if !generics.is_empty() {
write!(
f,
"::<{}>",
generics
.iter()
.map(|g| g.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
}
write!(f, "(")?;
for (i, param) in p.iter().enumerate() {
write!(f, "{}", param)?;
if i < p.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
}
}
// Variable to TypedExpression conversion
impl<'ast, T: Field> From<Variable<'ast, T>> for TypedExpression<'ast, T> {
@ -1790,7 +1723,7 @@ impl<'ast, T: Field> From<Variable<'ast, T>> for TypedExpression<'ast, T> {
Type::FieldElement => FieldElementExpression::Identifier(v.id).into(),
Type::Boolean => BooleanExpression::Identifier(v.id).into(),
Type::Array(ty) => ArrayExpressionInner::Identifier(v.id)
.annotate(*ty.ty, ty.size)
.annotate(*ty.ty, *ty.size)
.into(),
Type::Struct(ty) => StructExpressionInner::Identifier(v.id).annotate(ty).into(),
Type::Tuple(ty) => TupleExpressionInner::Identifier(v.id).annotate(ty).into(),
@ -1804,7 +1737,7 @@ impl<'ast, T: Field> From<Variable<'ast, T>> for TypedExpression<'ast, T> {
pub trait Expr<'ast, T>: fmt::Display + From<TypedExpression<'ast, T>> {
type Inner;
type Ty: Clone + IntoTypes<'ast, T>;
type Ty: Clone + IntoType<'ast, T>;
fn ty(&self) -> &Self::Ty;
@ -1962,27 +1895,6 @@ impl<'ast, T: Field> Expr<'ast, T> for IntExpression<'ast, T> {
}
}
impl<'ast, T: Field> Expr<'ast, T> for TypedExpressionList<'ast, T> {
type Inner = TypedExpressionListInner<'ast, T>;
type Ty = Types<'ast, T>;
fn ty(&self) -> &Self::Ty {
&self.types
}
fn into_inner(self) -> Self::Inner {
self.inner
}
fn as_inner(&self) -> &Self::Inner {
&self.inner
}
fn as_inner_mut(&mut self) -> &mut Self::Inner {
&mut self.inner
}
}
// Enums types to enable returning e.g a member expression OR another type of expression of this type
pub enum FunctionCallOrExpression<'ast, T, E: Expr<'ast, T>> {
@ -2199,7 +2111,8 @@ impl<'ast, T: Clone> Select<'ast, T> for ArrayExpression<'ast, T> {
_ => unreachable!(),
};
ArrayExpressionInner::Select(SelectExpression::new(array, index.into())).annotate(*ty, size)
ArrayExpressionInner::Select(SelectExpression::new(array, index.into()))
.annotate(*ty, *size)
}
}
@ -2265,7 +2178,7 @@ impl<'ast, T: Clone> Member<'ast, T> for ArrayExpression<'ast, T> {
}) => (*array_ty.ty.clone(), array_ty.size.clone()),
_ => unreachable!(),
};
ArrayExpressionInner::Member(MemberExpression::new(s, id)).annotate(ty, size)
ArrayExpressionInner::Member(MemberExpression::new(s, id)).annotate(ty, *size)
}
}
@ -2331,7 +2244,7 @@ impl<'ast, T: Clone> Element<'ast, T> for ArrayExpression<'ast, T> {
Type::Array(array_ty) => (*array_ty.ty.clone(), array_ty.size.clone()),
_ => unreachable!(),
};
ArrayExpressionInner::Element(ElementExpression::new(s, id)).annotate(ty, size)
ArrayExpressionInner::Element(ElementExpression::new(s, id)).annotate(ty, *size)
}
}
@ -2397,15 +2310,6 @@ impl<'ast, T: Field> Id<'ast, T> for TupleExpression<'ast, T> {
}
}
// `TypedExpressionList` does not have an Identifier variant
// However implementing `From<TypedExpression>` is required for `TypedExpressionList` to be `Expr`, which makes generic treatment of function calls possible
// This could maybe be avoided by splitting the `Expr` trait into many, but I did not find a way
impl<'ast, T: Field> Id<'ast, T> for TypedExpressionList<'ast, T> {
fn identifier(_: Identifier<'ast>) -> Self::Inner {
unreachable!()
}
}
pub trait FunctionCall<'ast, T>: Expr<'ast, T> {
fn function_call(
key: DeclarationFunctionKey<'ast, T>,
@ -2474,18 +2378,6 @@ impl<'ast, T: Field> FunctionCall<'ast, T> for StructExpression<'ast, T> {
}
}
impl<'ast, T: Field> FunctionCall<'ast, T> for TypedExpressionList<'ast, T> {
fn function_call(
key: DeclarationFunctionKey<'ast, T>,
generics: Vec<Option<UExpression<'ast, T>>>,
arguments: Vec<TypedExpression<'ast, T>>,
) -> Self::Inner {
TypedExpressionListInner::FunctionCall(FunctionCallExpression::new(
key, generics, arguments,
))
}
}
pub trait Block<'ast, T> {
fn block(statements: Vec<TypedStatement<'ast, T>>, value: Self) -> Self;
}
@ -2513,7 +2405,7 @@ impl<'ast, T: Field> Block<'ast, T> for ArrayExpression<'ast, T> {
fn block(statements: Vec<TypedStatement<'ast, T>>, value: Self) -> Self {
let array_ty = value.ty().clone();
ArrayExpressionInner::Block(BlockExpression::new(statements, value))
.annotate(*array_ty.ty, array_ty.size)
.annotate(*array_ty.ty, *array_ty.size)
}
}
@ -2634,7 +2526,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> {
.collect::<Vec<_>>()
.into(),
)
.annotate(*array_ty.ty, array_ty.size),
.annotate(*array_ty.ty, *array_ty.size),
ArrayExpressionInner::Slice(box a, box from, box to) => {
let from = match from.into_inner() {
UExpressionInner::Value(from) => from as usize,
@ -2660,7 +2552,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> {
.collect::<Vec<_>>()
.into(),
)
.annotate(*array_ty.ty, array_ty.size)
.annotate(*array_ty.ty, *array_ty.size)
}
ArrayExpressionInner::Repeat(box e, box count) => {
let count = match count.into_inner() {
@ -2673,7 +2565,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> {
ArrayExpressionInner::Value(
vec![TypedExpressionOrSpread::Expression(e); count].into(),
)
.annotate(*array_ty.ty, array_ty.size)
.annotate(*array_ty.ty, *array_ty.size)
}
_ => unreachable!(),
}

View file

@ -170,6 +170,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
Ok(Variable {
id: self.fold_name(v.id)?,
_type: self.fold_type(v._type)?,
is_mutable: v.is_mutable,
})
}
@ -180,6 +181,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
Ok(DeclarationVariable {
id: self.fold_name(v.id)?,
_type: self.fold_declaration_type(v._type)?,
is_mutable: v.is_mutable,
})
}
@ -194,10 +196,6 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
}
}
fn fold_types(&mut self, tys: Types<'ast, T>) -> Result<Types<'ast, T>, Self::Error> {
fold_types(self, tys)
}
fn fold_conditional_expression<
E: Expr<'ast, T> + PartialEq + Conditional<'ast, T> + ResultFold<'ast, T>,
>(
@ -273,7 +271,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
) -> Result<ArrayType<'ast, T>, Self::Error> {
Ok(ArrayType {
ty: box self.fold_type(*t.ty)?,
size: self.fold_uint_expression(t.size)?,
size: box self.fold_uint_expression(*t.size)?,
})
}
@ -333,7 +331,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
) -> Result<DeclarationArrayType<'ast, T>, Self::Error> {
Ok(DeclarationArrayType {
ty: box self.fold_declaration_type(*t.ty)?,
size: self.fold_declaration_constant(t.size)?,
size: box self.fold_declaration_constant(*t.size)?,
})
}
@ -387,6 +385,13 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
fold_statement(self, s)
}
fn fold_embed_call(
&mut self,
e: EmbedCall<'ast, T>,
) -> Result<EmbedCall<'ast, T>, Self::Error> {
fold_embed_call(self, e)
}
fn fold_expression_or_spread(
&mut self,
e: TypedExpressionOrSpread<'ast, T>,
@ -414,15 +419,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
&mut self,
e: TypedExpression<'ast, T>,
) -> Result<TypedExpression<'ast, T>, Self::Error> {
match e {
TypedExpression::FieldElement(e) => Ok(self.fold_field_expression(e)?.into()),
TypedExpression::Boolean(e) => Ok(self.fold_boolean_expression(e)?.into()),
TypedExpression::Uint(e) => Ok(self.fold_uint_expression(e)?.into()),
TypedExpression::Array(e) => Ok(self.fold_array_expression(e)?.into()),
TypedExpression::Struct(e) => Ok(self.fold_struct_expression(e)?.into()),
TypedExpression::Tuple(e) => Ok(self.fold_tuple_expression(e)?.into()),
TypedExpression::Int(e) => Ok(self.fold_int_expression(e)?.into()),
}
fold_expression(self, e)
}
fn fold_array_expression(
@ -446,21 +443,6 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
fold_tuple_expression(self, e)
}
fn fold_expression_list_inner(
&mut self,
tys: &Types<'ast, T>,
es: TypedExpressionListInner<'ast, T>,
) -> Result<TypedExpressionListInner<'ast, T>, Self::Error> {
fold_expression_list_inner(self, tys, es)
}
fn fold_expression_list(
&mut self,
es: TypedExpressionList<'ast, T>,
) -> Result<TypedExpressionList<'ast, T>, Self::Error> {
fold_expression_list(self, es)
}
fn fold_int_expression(
&mut self,
e: IntExpression<'ast, T>,
@ -524,16 +506,10 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>(
s: TypedStatement<'ast, T>,
) -> Result<Vec<TypedStatement<'ast, T>>, F::Error> {
let res = match s {
TypedStatement::Return(expressions) => TypedStatement::Return(
expressions
.into_iter()
.map(|e| f.fold_expression(e))
.collect::<Result<_, _>>()?,
),
TypedStatement::Return(e) => TypedStatement::Return(f.fold_expression(e)?),
TypedStatement::Definition(a, e) => {
TypedStatement::Definition(f.fold_assignee(a)?, f.fold_expression(e)?)
}
TypedStatement::Declaration(v) => TypedStatement::Declaration(f.fold_variable(v)?),
TypedStatement::Assertion(e, error) => {
TypedStatement::Assertion(f.fold_boolean_expression(e)?, error)
}
@ -549,24 +525,37 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>(
.flatten()
.collect(),
),
TypedStatement::MultipleDefinition(variables, elist) => TypedStatement::MultipleDefinition(
variables
.into_iter()
.map(|v| f.fold_assignee(v))
.collect::<Result<_, _>>()?,
f.fold_expression_list(elist)?,
),
TypedStatement::Log(s, e) => TypedStatement::Log(
s,
e.into_iter()
.map(|e| f.fold_expression(e))
.collect::<Result<Vec<_>, _>>()?,
),
TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
TypedStatement::EmbedCallDefinition(
f.fold_assignee(assignee)?,
f.fold_embed_call(embed_call)?,
)
}
s => s,
};
Ok(vec![res])
}
pub fn fold_embed_call<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
e: EmbedCall<'ast, T>,
) -> Result<EmbedCall<'ast, T>, F::Error> {
Ok(EmbedCall {
arguments: e
.arguments
.into_iter()
.map(|s| f.fold_expression(s))
.collect::<Result<Vec<_>, _>>()?,
..e
})
}
pub fn fold_array_expression_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
ty: &ArrayType<'ast, T>,
@ -1208,11 +1197,7 @@ pub fn fold_signature<'ast, T: Field, F: ResultFolder<'ast, T>>(
.into_iter()
.map(|o| f.fold_declaration_type(o))
.collect::<Result<_, _>>()?,
outputs: s
.outputs
.into_iter()
.map(|o| f.fold_declaration_type(o))
.collect::<Result<_, _>>()?,
output: box f.fold_declaration_type(*s.output)?,
})
}
@ -1231,6 +1216,21 @@ pub fn fold_declaration_constant<'ast, T: Field, F: ResultFolder<'ast, T>>(
}
}
pub fn fold_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
e: TypedExpression<'ast, T>,
) -> Result<TypedExpression<'ast, T>, F::Error> {
match e {
TypedExpression::FieldElement(e) => Ok(f.fold_field_expression(e)?.into()),
TypedExpression::Boolean(e) => Ok(f.fold_boolean_expression(e)?.into()),
TypedExpression::Uint(e) => Ok(f.fold_uint_expression(e)?.into()),
TypedExpression::Array(e) => Ok(f.fold_array_expression(e)?.into()),
TypedExpression::Struct(e) => Ok(f.fold_struct_expression(e)?.into()),
TypedExpression::Tuple(e) => Ok(f.fold_tuple_expression(e)?.into()),
TypedExpression::Int(e) => Ok(f.fold_int_expression(e)?.into()),
}
}
pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
e: ArrayExpression<'ast, T>,
@ -1243,58 +1243,6 @@ pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
})
}
pub fn fold_expression_list<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
es: TypedExpressionList<'ast, T>,
) -> Result<TypedExpressionList<'ast, T>, F::Error> {
let types = f.fold_types(es.types)?;
Ok(TypedExpressionList {
inner: f.fold_expression_list_inner(&types, es.inner)?,
types,
})
}
pub fn fold_types<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
tys: Types<'ast, T>,
) -> Result<Types<'ast, T>, F::Error> {
Ok(Types {
inner: tys
.inner
.into_iter()
.map(|t| f.fold_type(t))
.collect::<Result<_, _>>()?,
})
}
pub fn fold_expression_list_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
tys: &Types<'ast, T>,
es: TypedExpressionListInner<'ast, T>,
) -> Result<TypedExpressionListInner<'ast, T>, F::Error> {
match es {
TypedExpressionListInner::FunctionCall(function_call) => {
match f.fold_function_call_expression(tys, function_call)? {
FunctionCallOrExpression::FunctionCall(function_call) => {
Ok(TypedExpressionListInner::FunctionCall(function_call))
}
FunctionCallOrExpression::Expression(list) => Ok(list),
}
}
TypedExpressionListInner::EmbedCall(embed, generics, arguments) => {
Ok(TypedExpressionListInner::EmbedCall(
embed,
generics,
arguments
.into_iter()
.map(|a| f.fold_expression(a))
.collect::<Result<_, _>>()?,
))
}
}
}
pub fn fold_struct_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
e: StructExpression<'ast, T>,

View file

@ -8,62 +8,37 @@ use std::fmt;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
pub trait IntoTypes<'ast, T> {
fn into_types(self) -> Types<'ast, T>;
pub trait IntoType<'ast, T> {
fn into_type(self) -> Type<'ast, T>;
}
impl<'ast, T> IntoTypes<'ast, T> for Type<'ast, T> {
fn into_types(self) -> Types<'ast, T> {
Types { inner: vec![self] }
}
}
impl<'ast, T> IntoTypes<'ast, T> for StructType<'ast, T> {
fn into_types(self) -> Types<'ast, T> {
Types {
inner: vec![Type::Struct(self)],
}
}
}
impl<'ast, T> IntoTypes<'ast, T> for ArrayType<'ast, T> {
fn into_types(self) -> Types<'ast, T> {
Types {
inner: vec![Type::Array(self)],
}
}
}
impl<'ast, T> IntoTypes<'ast, T> for TupleType<'ast, T> {
fn into_types(self) -> Types<'ast, T> {
Types {
inner: vec![Type::Tuple(self)],
}
}
}
impl<'ast, T> IntoTypes<'ast, T> for UBitwidth {
fn into_types(self) -> Types<'ast, T> {
Types {
inner: vec![Type::Uint(self)],
}
}
}
impl<'ast, T> IntoTypes<'ast, T> for Types<'ast, T> {
fn into_types(self) -> Types<'ast, T> {
impl<'ast, T> IntoType<'ast, T> for Type<'ast, T> {
fn into_type(self) -> Type<'ast, T> {
self
}
}
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct Types<'ast, T> {
pub inner: Vec<Type<'ast, T>>,
impl<'ast, T> IntoType<'ast, T> for StructType<'ast, T> {
fn into_type(self) -> Type<'ast, T> {
Type::Struct(self)
}
}
impl<'ast, T> Types<'ast, T> {
pub fn new(types: Vec<Type<'ast, T>>) -> Self {
Self { inner: types }
impl<'ast, T> IntoType<'ast, T> for ArrayType<'ast, T> {
fn into_type(self) -> Type<'ast, T> {
Type::Array(self)
}
}
impl<'ast, T> IntoType<'ast, T> for TupleType<'ast, T> {
fn into_type(self) -> Type<'ast, T> {
Type::Tuple(self)
}
}
impl<'ast, T> IntoType<'ast, T> for UBitwidth {
fn into_type(self) -> Type<'ast, T> {
Type::Uint(self)
}
}
@ -337,7 +312,7 @@ impl<'ast, T> From<ConcreteStructMember> for StructMember<'ast, T> {
#[derive(Clone, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Debug)]
pub struct GArrayType<S> {
pub size: S,
pub size: Box<S>,
#[serde(flatten)]
pub ty: Box<GType<S>>,
}
@ -348,7 +323,7 @@ pub type ArrayType<'ast, T> = GArrayType<UExpression<'ast, T>>;
impl<'ast, S, R: PartialEq<S>> PartialEq<GArrayType<S>> for GArrayType<R> {
fn eq(&self, other: &GArrayType<S>) -> bool {
*self.ty == *other.ty && self.size == other.size
*self.ty == *other.ty && *self.size == *other.size
}
}
@ -382,7 +357,7 @@ fn try_from_g_array_type<T: TryInto<U>, U>(
t: GArrayType<T>,
) -> Result<GArrayType<U>, SpecializationError> {
Ok(GArrayType {
size: t.size.try_into().map_err(|_| SpecializationError)?,
size: box (*t.size).try_into().map_err(|_| SpecializationError)?,
ty: box try_from_g_type(*t.ty)?,
})
}
@ -830,7 +805,7 @@ impl<S, U: Into<S>> From<(GType<S>, U)> for GArrayType<S> {
fn from(tup: (GType<S>, U)) -> Self {
GArrayType {
ty: box tup.0,
size: tup.1.into(),
size: box tup.1.into(),
}
}
}
@ -838,8 +813,8 @@ impl<S, U: Into<S>> From<(GType<S>, U)> for GArrayType<S> {
impl<S> GArrayType<S> {
pub fn new<U: Into<S>>(ty: GType<S>, size: U) -> Self {
GArrayType {
ty: Box::new(ty),
size: size.into(),
ty: box ty,
size: box size.into(),
}
}
}
@ -922,7 +897,7 @@ impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> {
(Array(l), Array(r)) => match l.ty.can_be_specialized_to(&r.ty) {
true => {
// check the size if types match
match (&l.size.as_inner(), &r.size) {
match (&l.size.as_inner(), &*r.size) {
// compare the sizes for concrete ones
(UExpressionInner::Value(v), DeclarationConstant::Concrete(c)) => {
(*v as u32) == *c
@ -953,7 +928,7 @@ impl ConcreteType {
GType::Boolean => 1,
GType::Uint(_) => 1,
GType::Array(array_type) => {
array_type.size as usize * array_type.ty.get_primitive_count()
*array_type.size as usize * array_type.ty.get_primitive_count()
}
GType::Tuple(tuple_type) => tuple_type
.elements
@ -1123,7 +1098,7 @@ pub fn check_type<'ast, T, S: Clone + PartialEq + PartialEq<u32>>(
(DeclarationType::Array(t0), GType::Array(t1)) => {
// both the inner type and the size must match
check_type(&t0.ty, &t1.ty, constants)
&& check_generic(&t0.size, Some(&t1.size), constants)
&& check_generic(&*t0.size, Some(&*t1.size), constants)
}
(DeclarationType::FieldElement, GType::FieldElement)
| (DeclarationType::Boolean, GType::Boolean) => true,
@ -1164,7 +1139,7 @@ impl<'ast, T> From<CanonicalConstantIdentifier<'ast>> for DeclarationConstant<'a
pub fn specialize_declaration_type<
'ast,
T: Clone,
S: Clone + PartialEq + From<u32> + fmt::Debug + From<CanonicalConstantIdentifier<'ast>>,
S: Clone + PartialEq + From<u32> + From<CanonicalConstantIdentifier<'ast>>,
>(
decl_ty: DeclarationType<'ast, T>,
generics: &GGenericsAssignment<'ast, S>,
@ -1172,10 +1147,10 @@ pub fn specialize_declaration_type<
Ok(match decl_ty {
DeclarationType::Int => unreachable!(),
DeclarationType::Array(t0) => {
let ty = box specialize_declaration_type(*t0.ty, generics)?;
let ty = specialize_declaration_type(*t0.ty, generics)?;
let size = t0.size.map(generics)?;
GType::Array(GArrayType { size, ty })
GType::Array(GArrayType::new(ty, size))
}
DeclarationType::Tuple(t0) => {
let elements = t0
@ -1244,12 +1219,22 @@ pub mod signature {
pub struct GSignature<S> {
pub generics: Vec<Option<S>>,
pub inputs: Vec<GType<S>>,
pub outputs: Vec<GType<S>>,
pub output: Box<GType<S>>,
}
impl<S> Default for GSignature<S> {
fn default() -> Self {
Self {
generics: vec![],
inputs: vec![],
output: box GType::Tuple(GTupleType::new(vec![])),
}
}
}
impl<S: PartialEq> PartialEq for GSignature<S> {
fn eq(&self, other: &Self) -> bool {
self.inputs == other.inputs && self.outputs == other.outputs
self.inputs == other.inputs && self.output == other.output
}
}
@ -1257,7 +1242,7 @@ pub mod signature {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.inputs
.partial_cmp(&other.inputs)
.map(|c| self.outputs.partial_cmp(&other.outputs).map(|d| c.then(d)))
.map(|c| self.output.partial_cmp(&other.output).map(|d| c.then(d)))
.unwrap()
}
}
@ -1271,17 +1256,7 @@ pub mod signature {
impl<S: Hash> Hash for GSignature<S> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inputs.hash(state);
self.outputs.hash(state);
}
}
impl<S> Default for GSignature<S> {
fn default() -> Self {
GSignature {
generics: vec![],
inputs: vec![],
outputs: vec![],
}
self.output.hash(state);
}
}
@ -1297,13 +1272,13 @@ pub mod signature {
other
.inputs
.iter()
.chain(other.outputs.iter())
.zip(self.inputs.iter().chain(self.outputs.iter()))
.chain(std::iter::once(&*other.output))
.zip(self.inputs.iter().chain(std::iter::once(&*self.output)))
.all(|(decl_ty, ty)| check_type::<T, u32>(decl_ty, ty, &mut constants))
}
}
impl<'ast, T: Clone + PartialEq + fmt::Debug> DeclarationSignature<'ast, T> {
impl<'ast, T: Clone + PartialEq> DeclarationSignature<'ast, T> {
pub fn specialize(
&self,
values: Vec<Option<u32>>,
@ -1312,9 +1287,8 @@ pub mod signature {
// we keep track of the value of constants in a map, as a given constant can only have one value
let mut constants = ConcreteGenericsAssignment::default();
assert_eq!(self.inputs.len(), signature.inputs.len());
assert_eq!(self.outputs.len(), signature.outputs.len());
assert_eq!(self.generics.len(), values.len());
assert_eq!(self.inputs.len(), signature.inputs.len());
let decl_generics = self.generics.iter().map(|g| match g.clone().unwrap() {
DeclarationConstant::Generic(g) => g,
@ -1330,8 +1304,13 @@ pub mod signature {
let condition = self
.inputs
.iter()
.chain(self.outputs.iter())
.zip(signature.inputs.iter().chain(signature.outputs.iter()))
.chain(std::iter::once(&*self.output))
.zip(
signature
.inputs
.iter()
.chain(std::iter::once(&*signature.output)),
)
.all(|(decl_ty, ty)| check_type(decl_ty, ty, &mut constants));
if constants.0.len() != self.generics.len() {
@ -1344,11 +1323,11 @@ pub mod signature {
}
}
pub fn get_output_types(
pub fn get_output_type(
&self,
generics: Vec<Option<UExpression<'ast, T>>>,
inputs: Vec<Type<'ast, T>>,
) -> Result<Vec<Type<'ast, T>>, GenericIdentifier<'ast>> {
) -> Result<Type<'ast, T>, GenericIdentifier<'ast>> {
// we keep track of the value of constants in a map, as a given constant can only have one value
let mut constants = GenericsAssignment::default();
@ -1375,12 +1354,8 @@ pub mod signature {
.zip(inputs.iter())
.all(|(decl_ty, ty)| check_type(decl_ty, ty, &mut constants));
// get the outputs from the map
self.outputs
.clone()
.into_iter()
.map(|t| specialize_declaration_type(t, &constants))
.collect::<Result<_, _>>()
// get the specialized output
specialize_declaration_type(*self.output.clone(), &constants)
}
}
@ -1401,11 +1376,7 @@ pub mod signature {
.into_iter()
.map(try_from_g_type)
.collect::<Result<_, _>>()?,
outputs: t
.outputs
.into_iter()
.map(try_from_g_type)
.collect::<Result<_, _>>()?,
output: box try_from_g_type(*t.output)?,
})
}
@ -1453,21 +1424,7 @@ pub mod signature {
write!(f, ", ")?;
}
}
write!(f, ")")?;
match self.outputs.len() {
0 => write!(f, ""),
1 => write!(f, " -> {}", self.outputs[0]),
_ => {
write!(f, " -> (")?;
for (i, t) in self.outputs.iter().enumerate() {
write!(f, "{}", t)?;
if i < self.outputs.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
write!(f, ") -> {}", self.output)
}
}
@ -1486,8 +1443,8 @@ pub mod signature {
self
}
pub fn outputs(mut self, outputs: Vec<GType<S>>) -> Self {
self.outputs = outputs;
pub fn output(mut self, output: GType<S>) -> Self {
self.output = Box::new(output);
self
}
}
@ -1501,7 +1458,7 @@ pub mod signature {
fn signature() {
let s = ConcreteSignature::new()
.inputs(vec![ConcreteType::FieldElement, ConcreteType::Boolean])
.outputs(vec![ConcreteType::Boolean]);
.output(ConcreteType::Boolean);
assert_eq!(s.to_string(), String::from("(field, bool) -> bool"));
}

View file

@ -5,10 +5,11 @@ use crate::typed::UExpression;
use crate::typed::{TryFrom, TryInto};
use std::fmt;
#[derive(Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
#[derive(Clone, PartialEq, Hash, Eq, PartialOrd, Ord, Debug)]
pub struct GVariable<'ast, S> {
pub id: Identifier<'ast>,
pub _type: GType<S>,
pub is_mutable: bool,
}
pub type DeclarationVariable<'ast, T> = GVariable<'ast, DeclarationConstant<'ast, T>>;
@ -21,7 +22,11 @@ impl<'ast, T> TryFrom<Variable<'ast, T>> for ConcreteVariable<'ast> {
fn try_from(v: Variable<'ast, T>) -> Result<Self, Self::Error> {
let _type = v._type.try_into()?;
Ok(Self { _type, id: v.id })
Ok(Self {
_type,
id: v.id,
is_mutable: v.is_mutable,
})
}
}
@ -29,7 +34,11 @@ impl<'ast, T> From<ConcreteVariable<'ast>> for Variable<'ast, T> {
fn from(v: ConcreteVariable<'ast>) -> Self {
let _type = v._type.into();
Self { _type, id: v.id }
Self {
_type,
id: v.id,
is_mutable: v.is_mutable,
}
}
}
@ -38,34 +47,47 @@ pub fn try_from_g_variable<T: TryInto<U>, U>(
) -> Result<GVariable<U>, SpecializationError> {
let _type = crate::typed::types::try_from_g_type(v._type)?;
Ok(GVariable { _type, id: v.id })
Ok(GVariable {
_type,
id: v.id,
is_mutable: v.is_mutable,
})
}
impl<'ast, S: Clone> GVariable<'ast, S> {
pub fn field_element<I: Into<Identifier<'ast>>>(id: I) -> Self {
Self::with_id_and_type(id, GType::FieldElement)
Self::immutable(id, GType::FieldElement)
}
pub fn boolean<I: Into<Identifier<'ast>>>(id: I) -> Self {
Self::with_id_and_type(id, GType::Boolean)
Self::immutable(id, GType::Boolean)
}
pub fn uint<I: Into<Identifier<'ast>>, W: Into<UBitwidth>>(id: I, bitwidth: W) -> Self {
Self::with_id_and_type(id, GType::uint(bitwidth))
Self::immutable(id, GType::uint(bitwidth))
}
pub fn array<I: Into<Identifier<'ast>>, U: Into<S>>(id: I, ty: GType<S>, size: U) -> Self {
Self::with_id_and_type(id, GType::array((ty, size.into())))
Self::immutable(id, GType::array((ty, size.into())))
}
pub fn struc<I: Into<Identifier<'ast>>>(id: I, ty: GStructType<S>) -> Self {
Self::with_id_and_type(id, GType::Struct(ty))
Self::immutable(id, GType::Struct(ty))
}
pub fn with_id_and_type<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>) -> Self {
pub fn immutable<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>) -> Self {
Self::new(id, _type, false)
}
pub fn mutable<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>) -> Self {
Self::new(id, _type, true)
}
pub fn new<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>, is_mutable: bool) -> Self {
GVariable {
id: id.into(),
_type,
is_mutable,
}
}
@ -79,9 +101,3 @@ impl<'ast, S: fmt::Display> fmt::Display for GVariable<'ast, S> {
write!(f, "{} {}", self._type, self.id,)
}
}
impl<'ast, S: fmt::Debug> fmt::Debug for GVariable<'ast, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Variable(type: {:?}, id: {:?})", self._type, self.id,)
}
}

View file

@ -1,6 +1,4 @@
use crate::untyped;
use crate::untyped::{ConditionalExpression, SymbolDefinition};
use crate::untyped::{self, ConditionalExpression, SymbolDefinition};
use num_bigint::BigUint;
use std::path::Path;
use zokrates_pest_ast as pest;
@ -183,16 +181,13 @@ impl<'ast> From<pest::FunctionDefinition<'ast>> for untyped::SymbolDeclarationNo
.into_iter()
.map(|p| untyped::UnresolvedTypeNode::from(p.ty))
.collect(),
)
.outputs(
function
.returns
.clone()
.into_iter()
.map(untyped::UnresolvedTypeNode::from)
.collect(),
);
let signature = match function.return_type {
Some(ret_ty) => signature.output(untyped::UnresolvedTypeNode::from(ret_ty)),
None => signature,
};
let id = function.id.span.as_str();
let function = untyped::Function {
@ -201,11 +196,7 @@ impl<'ast> From<pest::FunctionDefinition<'ast>> for untyped::SymbolDeclarationNo
.into_iter()
.map(untyped::ParameterNode::from)
.collect(),
statements: function
.statements
.into_iter()
.flat_map(statements_from_statement)
.collect(),
statements: function.statements.into_iter().map(|s| s.into()).collect(),
signature,
}
.span(span.clone());
@ -232,7 +223,7 @@ impl<'ast> From<pest::Parameter<'ast>> for untyped::ParameterNode<'ast> {
fn from(param: pest::Parameter<'ast>) -> untyped::ParameterNode<'ast> {
use crate::untyped::NodeValue;
let private = param
let is_private = param
.visibility
.map(|v| match v {
pest::Visibility::Private(_) => true,
@ -240,23 +231,16 @@ impl<'ast> From<pest::Parameter<'ast>> for untyped::ParameterNode<'ast> {
})
.unwrap_or(false);
let is_mutable = param.mutable.is_some();
let variable = untyped::Variable::new(
param.id.span.as_str(),
untyped::UnresolvedTypeNode::from(param.ty),
is_mutable,
)
.span(param.id.span);
untyped::Parameter::new(variable, private).span(param.span)
}
}
fn statements_from_statement(statement: pest::Statement) -> Vec<untyped::StatementNode> {
match statement {
pest::Statement::Definition(s) => statements_from_definition(s),
pest::Statement::Iteration(s) => vec![untyped::StatementNode::from(s)],
pest::Statement::Assertion(s) => vec![untyped::StatementNode::from(s)],
pest::Statement::Return(s) => vec![untyped::StatementNode::from(s)],
pest::Statement::Log(s) => vec![untyped::StatementNode::from(s)],
untyped::Parameter::new(variable, is_private).span(param.span)
}
}
@ -274,101 +258,53 @@ impl<'ast> From<pest::LogStatement<'ast>> for untyped::StatementNode<'ast> {
}
}
fn statements_from_definition(
definition: pest::DefinitionStatement,
) -> Vec<untyped::StatementNode> {
use crate::untyped::NodeValue;
impl<'ast> From<pest::TypedIdentifier<'ast>> for untyped::VariableNode<'ast> {
fn from(i: pest::TypedIdentifier<'ast>) -> Self {
use crate::untyped::NodeValue;
let lhs = definition.lhs;
untyped::Variable::new(
i.identifier.span.as_str(),
untyped::UnresolvedTypeNode::from(i.ty),
i.mutable.is_some(),
)
.span(i.span)
}
}
match lhs.len() {
1 => {
// Definition or assignment
let a = lhs[0].clone();
impl<'ast> From<pest::Statement<'ast>> for untyped::StatementNode<'ast> {
fn from(statement: pest::Statement<'ast>) -> Self {
match statement {
pest::Statement::Definition(s) => untyped::StatementNode::from(s),
pest::Statement::Iteration(s) => untyped::StatementNode::from(s),
pest::Statement::Assertion(s) => untyped::StatementNode::from(s),
pest::Statement::Return(s) => untyped::StatementNode::from(s),
pest::Statement::Log(s) => untyped::StatementNode::from(s),
}
}
}
let e: untyped::ExpressionNode = untyped::ExpressionNode::from(definition.expression);
impl<'ast> From<pest::DefinitionStatement<'ast>> for untyped::StatementNode<'ast> {
fn from(definition: pest::DefinitionStatement<'ast>) -> Self {
use crate::untyped::NodeValue;
match a {
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
let declaration = untyped::Statement::Declaration(
untyped::Variable::new(
i.identifier.span.as_str(),
untyped::UnresolvedTypeNode::from(i.ty),
)
.span(i.identifier.span.clone()),
)
.span(definition.span.clone());
let lhs = definition.lhs;
let e: untyped::ExpressionNode = untyped::ExpressionNode::from(definition.expression);
let s = match e.value {
untyped::Expression::FunctionCall(..) => {
untyped::Statement::MultipleDefinition(
vec![untyped::AssigneeNode::from(i.identifier.clone())],
e,
)
}
_ => untyped::Statement::Definition(
untyped::AssigneeNode::from(i.identifier.clone()),
e,
),
};
vec![declaration, s.span(definition.span)]
}
pest::TypedIdentifierOrAssignee::Assignee(a) => {
let s = match e.value {
untyped::Expression::FunctionCall(..) => {
untyped::Statement::MultipleDefinition(
vec![untyped::AssigneeNode::from(a)],
e,
)
}
_ => untyped::Statement::Definition(untyped::AssigneeNode::from(a), e),
};
vec![s.span(definition.span)]
}
match lhs {
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => untyped::Statement::Definition(
untyped::Variable::new(
i.identifier.span.as_str(),
untyped::UnresolvedTypeNode::from(i.ty),
i.mutable.is_some(),
)
.span(i.span.clone()),
e,
),
pest::TypedIdentifierOrAssignee::Assignee(a) => {
untyped::Statement::Assignment(untyped::AssigneeNode::from(a), e)
}
}
_ => {
// Multidefinition
let declarations = lhs.clone().into_iter().filter_map(|i| match i {
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
let ty = i.ty;
let id = i.identifier;
Some(
untyped::Statement::Declaration(
untyped::Variable::new(
id.span.as_str(),
untyped::UnresolvedTypeNode::from(ty),
)
.span(id.span),
)
.span(i.span),
)
}
_ => None,
});
let lhs = lhs
.into_iter()
.map(|i| match i {
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
untyped::Assignee::Identifier(i.identifier.span.as_str())
.span(i.identifier.span)
}
pest::TypedIdentifierOrAssignee::Assignee(a) => untyped::AssigneeNode::from(a),
})
.collect();
let multi_def = untyped::Statement::MultipleDefinition(
lhs,
untyped::ExpressionNode::from(definition.expression),
)
.span(definition.span);
declarations.chain(std::iter::once(multi_def)).collect()
}
.span(definition.span.clone())
}
}
@ -376,17 +312,8 @@ impl<'ast> From<pest::ReturnStatement<'ast>> for untyped::StatementNode<'ast> {
fn from(statement: pest::ReturnStatement<'ast>) -> untyped::StatementNode<'ast> {
use crate::untyped::NodeValue;
untyped::Statement::Return(
untyped::ExpressionList {
expressions: statement
.expressions
.into_iter()
.map(untyped::ExpressionNode::from)
.collect(),
}
.span(statement.span.clone()),
)
.span(statement.span)
untyped::Statement::Return(statement.expression.map(untyped::ExpressionNode::from))
.span(statement.span)
}
}
@ -405,19 +332,13 @@ impl<'ast> From<pest::AssertionStatement<'ast>> for untyped::StatementNode<'ast>
impl<'ast> From<pest::IterationStatement<'ast>> for untyped::StatementNode<'ast> {
fn from(statement: pest::IterationStatement<'ast>) -> untyped::StatementNode<'ast> {
use crate::untyped::NodeValue;
let index = untyped::VariableNode::from(statement.index);
let from = untyped::ExpressionNode::from(statement.from);
let to = untyped::ExpressionNode::from(statement.to);
let index = statement.id.identifier.span.as_str();
let ty = untyped::UnresolvedTypeNode::from(statement.id.ty);
let statements: Vec<untyped::StatementNode<'ast>> = statement
.statements
.into_iter()
.flat_map(statements_from_statement)
.collect();
let statements: Vec<untyped::StatementNode<'ast>> =
statement.statements.into_iter().map(|s| s.into()).collect();
let var = untyped::Variable::new(index, ty).span(statement.id.identifier.span);
untyped::Statement::For(var, from, to, statements).span(statement.span)
untyped::Statement::For(index, from, to, statements).span(statement.span)
}
}
@ -536,13 +457,13 @@ impl<'ast> From<pest::IfElseExpression<'ast>> for untyped::ExpressionNode<'ast>
consequence_statements: expression
.consequence_statements
.into_iter()
.flat_map(statements_from_statement)
.map(untyped::StatementNode::from)
.collect(),
consequence: box untyped::ExpressionNode::from(*expression.consequence),
alternative_statements: expression
.alternative_statements
.into_iter()
.flat_map(statements_from_statement)
.map(untyped::StatementNode::from)
.collect(),
alternative: box untyped::ExpressionNode::from(*expression.alternative),
kind: untyped::ConditionalKind::IfElse,
@ -966,18 +887,13 @@ mod tests {
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
untyped::Function {
arguments: vec![],
statements: vec![untyped::Statement::Return(
untyped::ExpressionList {
expressions: vec![
untyped::Expression::IntConstant(42usize.into()).into()
],
}
.into(),
)
statements: vec![untyped::Statement::Return(Some(
untyped::Expression::IntConstant(42usize.into()).into(),
))
.into()],
signature: UnresolvedSignature::new()
.inputs(vec![])
.outputs(vec![UnresolvedType::FieldElement.mock()]),
.output(UnresolvedType::FieldElement.mock()),
}
.into(),
)),
@ -991,37 +907,31 @@ mod tests {
fn return_true() {
let source = "def main() -> bool { return true; }";
let ast = pest::generate_ast(source).unwrap();
let expected: untyped::Module =
untyped::Module {
symbols: vec![untyped::SymbolDeclaration {
id: &source[4..8],
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
untyped::Function {
arguments: vec![],
statements: vec![untyped::Statement::Return(
untyped::ExpressionList {
expressions: vec![
untyped::Expression::BooleanConstant(true).into()
],
}
.into(),
)
.into()],
signature: UnresolvedSignature::new()
.inputs(vec![])
.outputs(vec![UnresolvedType::Boolean.mock()]),
}
.into(),
)),
}
.into()],
};
let expected: untyped::Module = untyped::Module {
symbols: vec![untyped::SymbolDeclaration {
id: &source[4..8],
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
untyped::Function {
arguments: vec![],
statements: vec![untyped::Statement::Return(Some(
untyped::Expression::BooleanConstant(true).into(),
))
.into()],
signature: UnresolvedSignature::new()
.inputs(vec![])
.output(UnresolvedType::Boolean.mock()),
}
.into(),
)),
}
.into()],
};
assert_eq!(untyped::Module::from(ast), expected);
}
#[test]
fn arguments() {
let source = "def main(private field a, bool b) -> field { return 42; }";
let source = "def main(private field a, bool mut b) -> field { return 42; }";
let ast = pest::generate_ast(source).unwrap();
let expected: untyped::Module = untyped::Module {
@ -1031,37 +941,29 @@ mod tests {
untyped::Function {
arguments: vec![
untyped::Parameter::private(
untyped::Variable::new(
&source[23..24],
untyped::Variable::immutable(
"a",
UnresolvedType::FieldElement.mock(),
)
.into(),
)
.into(),
untyped::Parameter::public(
untyped::Variable::new(
&source[31..32],
UnresolvedType::Boolean.mock(),
)
.into(),
untyped::Variable::mutable("b", UnresolvedType::Boolean.mock())
.into(),
)
.into(),
],
statements: vec![untyped::Statement::Return(
untyped::ExpressionList {
expressions: vec![
untyped::Expression::IntConstant(42usize.into()).into()
],
}
.into(),
)
statements: vec![untyped::Statement::Return(Some(
untyped::Expression::IntConstant(42usize.into()).into(),
))
.into()],
signature: UnresolvedSignature::new()
.inputs(vec![
UnresolvedType::FieldElement.mock(),
UnresolvedType::Boolean.mock(),
])
.outputs(vec![UnresolvedType::FieldElement.mock()]),
.output(UnresolvedType::FieldElement.mock()),
}
.into(),
)),
@ -1083,16 +985,10 @@ mod tests {
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
untyped::Function {
arguments: vec![untyped::Parameter::private(
untyped::Variable::new("a", ty.clone().mock()).into(),
)
.into()],
statements: vec![untyped::Statement::Return(
untyped::ExpressionList {
expressions: vec![],
}
.into(),
untyped::Variable::new("a", ty.clone().mock(), false).into(),
)
.into()],
statements: vec![untyped::Statement::Return(None).into()],
signature: UnresolvedSignature::new().inputs(vec![ty.mock()]),
}
.into(),
@ -1156,13 +1052,9 @@ mod tests {
symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(
untyped::Function {
arguments: vec![],
statements: vec![untyped::Statement::Return(
untyped::ExpressionList {
expressions: vec![expression.into()],
}
.into(),
)
.into()],
statements: vec![
untyped::Statement::Return(Some(expression.into())).into()
],
signature: UnresolvedSignature::new(),
}
.into(),
@ -1294,20 +1186,18 @@ mod tests {
let span = Span::new("", 0, 0).unwrap();
// For different definitions, we generate declarations
// Case 1: `id = expr` where `expr` is not a function call
// This is a simple assignment, doesn't implicitely declare a variable
// A `Definition` is generated and no `Declaration`s
// Case 1: `id = expr`
// A simple assignment to an already defined variable
let definition = pest::DefinitionStatement {
lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee {
lhs: pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee {
id: pest::IdentifierExpression {
value: String::from("a"),
span: span.clone(),
},
accesses: vec![],
span: span.clone(),
})],
}),
expression: pest::Expression::Literal(pest::LiteralExpression::DecimalLiteral(
pest::DecimalLiteralExpression {
value: pest::DecimalNumber {
@ -1320,28 +1210,30 @@ mod tests {
span: span.clone(),
};
let statements: Vec<untyped::StatementNode> = statements_from_definition(definition);
let statement = untyped::StatementNode::from(definition);
assert_eq!(statements.len(), 1);
match &statements[0].value {
untyped::Statement::Definition(..) => {}
match statement.value {
untyped::Statement::Assignment(..) => {}
s => {
panic!("should be a Definition, found {}", s);
panic!("should be an Assignment, found {}", s);
}
};
// Case 2: `id = expr` where `expr` is a function call
// A MultiDef is generated
// Case 2: `type id = expr`
// A definition statement is generated
let definition = pest::DefinitionStatement {
lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee {
id: pest::IdentifierExpression {
lhs: pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier {
ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType {
span: span.clone(),
})),
identifier: pest::IdentifierExpression {
value: String::from("a"),
span: span.clone(),
},
accesses: vec![],
mutable: None,
span: span.clone(),
})],
}),
expression: pest::Expression::Postfix(pest::PostfixExpression {
base: box pest::Expression::Identifier(pest::IdentifierExpression {
value: String::from("foo"),
@ -1360,64 +1252,10 @@ mod tests {
span: span.clone(),
};
let statements: Vec<untyped::StatementNode> = statements_from_definition(definition);
let statement = untyped::StatementNode::from(definition);
assert_eq!(statements.len(), 1);
match &statements[0].value {
untyped::Statement::MultipleDefinition(..) => {}
s => {
panic!("should be a Definition, found {}", s);
}
};
// Case 3: `ids = expr` where `expr` is a function call
// This implicitely declares all variables which are type annotated
// `field a, b = foo()`
let definition = pest::DefinitionStatement {
lhs: vec![
pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier {
ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType {
span: span.clone(),
})),
identifier: pest::IdentifierExpression {
value: String::from("a"),
span: span.clone(),
},
span: span.clone(),
}),
pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee {
id: pest::IdentifierExpression {
value: String::from("b"),
span: span.clone(),
},
accesses: vec![],
span: span.clone(),
}),
],
expression: pest::Expression::Postfix(pest::PostfixExpression {
base: box pest::Expression::Identifier(pest::IdentifierExpression {
value: String::from("foo"),
span: span.clone(),
}),
accesses: vec![pest::Access::Call(pest::CallAccess {
explicit_generics: None,
arguments: pest::Arguments {
expressions: vec![],
span: span.clone(),
},
span: span.clone(),
})],
span: span.clone(),
}),
span: span.clone(),
};
let statements: Vec<untyped::StatementNode> = statements_from_definition(definition);
assert_eq!(statements.len(), 2);
match &statements[1].value {
untyped::Statement::MultipleDefinition(..) => {}
match statement.value {
untyped::Statement::Definition(..) => {}
s => {
panic!("should be a Definition, found {}", s);
}

View file

@ -386,9 +386,9 @@ impl<'ast> fmt::Display for Assignee<'ast> {
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, PartialEq)]
pub enum Statement<'ast> {
Return(ExpressionListNode<'ast>),
Declaration(VariableNode<'ast>),
Definition(AssigneeNode<'ast>, ExpressionNode<'ast>),
Return(Option<ExpressionNode<'ast>>),
Definition(VariableNode<'ast>, ExpressionNode<'ast>),
Assignment(AssigneeNode<'ast>, ExpressionNode<'ast>),
Assertion(ExpressionNode<'ast>, Option<String>),
For(
VariableNode<'ast>,
@ -396,7 +396,6 @@ pub enum Statement<'ast> {
ExpressionNode<'ast>,
Vec<StatementNode<'ast>>,
),
MultipleDefinition(Vec<AssigneeNode<'ast>>, ExpressionNode<'ast>),
Log(&'ast str, Vec<ExpressionNode<'ast>>),
}
@ -405,9 +404,17 @@ pub type StatementNode<'ast> = Node<Statement<'ast>>;
impl<'ast> fmt::Display for Statement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Statement::Return(ref expr) => write!(f, "return {};", expr),
Statement::Declaration(ref var) => write!(f, "{};", var),
Statement::Definition(ref lhs, ref rhs) => write!(f, "{} = {};", lhs, rhs),
Statement::Return(ref expr) => {
write!(f, "return")?;
match expr {
Some(e) => write!(f, " {};", e),
None => write!(f, ";"),
}
}
Statement::Definition(ref var, ref rhs) => {
write!(f, "{} = {};", var, rhs)
}
Statement::Assignment(ref lhs, ref rhs) => write!(f, "{} = {};", lhs, rhs),
Statement::Assertion(ref e, ref message) => {
write!(f, "assert({}", e)?;
match message {
@ -422,15 +429,6 @@ impl<'ast> fmt::Display for Statement<'ast> {
}
write!(f, "\t}}")
}
Statement::MultipleDefinition(ref ids, ref rhs) => {
for (i, id) in ids.iter().enumerate() {
write!(f, "{}", id)?;
if i < ids.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, " = {};", rhs)
}
Statement::Log(ref l, ref expressions) => write!(
f,
"log!({}, {})",
@ -714,23 +712,3 @@ impl<'ast> fmt::Display for Expression<'ast> {
}
}
}
/// A list of expressions, used in return statements
#[derive(Debug, Clone, PartialEq, Default)]
pub struct ExpressionList<'ast> {
pub expressions: Vec<ExpressionNode<'ast>>,
}
pub type ExpressionListNode<'ast> = Node<ExpressionList<'ast>>;
impl<'ast> fmt::Display for ExpressionList<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, param) in self.expressions.iter().enumerate() {
write!(f, "{}", param)?;
if i < self.expressions.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "")
}
}

View file

@ -82,7 +82,6 @@ impl<V: NodeValue> From<V> for Node<V> {
use super::*;
impl<'ast> NodeValue for Expression<'ast> {}
impl<'ast> NodeValue for ExpressionList<'ast> {}
impl<'ast> NodeValue for Assignee<'ast> {}
impl<'ast> NodeValue for Statement<'ast> {}
impl<'ast> NodeValue for SymbolDeclaration<'ast> {}

View file

@ -4,26 +4,20 @@ use std::fmt;
#[derive(Clone, PartialEq)]
pub struct Parameter<'ast> {
pub id: VariableNode<'ast>,
pub private: bool,
pub is_private: bool,
}
impl<'ast> Parameter<'ast> {
pub fn new(v: VariableNode<'ast>, private: bool) -> Self {
Parameter { id: v, private }
}
pub fn public(v: VariableNode<'ast>) -> Self {
Parameter {
id: v,
private: false,
}
pub fn new(v: VariableNode<'ast>, is_private: bool) -> Self {
Parameter { id: v, is_private }
}
pub fn private(v: VariableNode<'ast>) -> Self {
Parameter {
id: v,
private: true,
}
Self::new(v, true)
}
pub fn public(v: VariableNode<'ast>) -> Self {
Self::new(v, false)
}
}
@ -31,7 +25,7 @@ pub type ParameterNode<'ast> = Node<Parameter<'ast>>;
impl<'ast> fmt::Display for Parameter<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let visibility = if self.private { "private " } else { "" };
let visibility = if self.is_private { "private " } else { "" };
write!(
f,
"{}{} {}",
@ -47,7 +41,7 @@ impl<'ast> fmt::Debug for Parameter<'ast> {
write!(
f,
"Parameter(variable: {:?}, private: {:?})",
self.id, self.private
self.id, self.is_private
)
}
}

View file

@ -85,15 +85,15 @@ mod signature {
pub struct UnresolvedSignature<'ast> {
pub generics: Vec<ConstantGenericNode<'ast>>,
pub inputs: Vec<UnresolvedTypeNode<'ast>>,
pub outputs: Vec<UnresolvedTypeNode<'ast>>,
pub output: Option<UnresolvedTypeNode<'ast>>,
}
impl<'ast> fmt::Debug for UnresolvedSignature<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Signature(inputs: {:?}, outputs: {:?})",
self.inputs, self.outputs
"Signature(inputs: {:?}, output: {:?})",
self.inputs, self.output
)
}
}
@ -107,14 +107,10 @@ mod signature {
write!(f, ", ")?;
}
}
write!(f, ") -> (")?;
for (i, t) in self.outputs.iter().enumerate() {
write!(f, "{}", t)?;
if i < self.outputs.len() - 1 {
write!(f, ", ")?;
}
match &self.output {
Some(ty) => write!(f, ") -> {}", ty),
None => write!(f, ")"),
}
write!(f, ")")
}
}
@ -133,8 +129,8 @@ mod signature {
self
}
pub fn outputs(mut self, outputs: Vec<UnresolvedTypeNode<'ast>>) -> Self {
self.outputs = outputs;
pub fn output(mut self, output: UnresolvedTypeNode<'ast>) -> Self {
self.output = Some(output);
self
}
}

View file

@ -6,6 +6,7 @@ use super::Identifier;
#[derive(Clone, PartialEq)]
pub struct Variable<'ast> {
pub is_mutable: bool,
pub id: Identifier<'ast>,
pub _type: UnresolvedTypeNode<'ast>,
}
@ -13,13 +14,26 @@ pub struct Variable<'ast> {
pub type VariableNode<'ast> = Node<Variable<'ast>>;
impl<'ast> Variable<'ast> {
pub fn new<S: Into<&'ast str>>(id: S, t: UnresolvedTypeNode<'ast>) -> Variable<'ast> {
pub fn new<S: Into<&'ast str>>(
id: S,
t: UnresolvedTypeNode<'ast>,
is_mutable: bool,
) -> Variable<'ast> {
Variable {
is_mutable,
id: id.into(),
_type: t,
}
}
pub fn immutable<S: Into<&'ast str>>(id: S, t: UnresolvedTypeNode<'ast>) -> Self {
Self::new(id, t, false)
}
pub fn mutable<S: Into<&'ast str>>(id: S, t: UnresolvedTypeNode<'ast>) -> Self {
Self::new(id, t, true)
}
pub fn get_type(&self) -> &UnresolvedType<'ast> {
&self._type.value
}
@ -33,6 +47,10 @@ impl<'ast> fmt::Display for Variable<'ast> {
impl<'ast> fmt::Debug for Variable<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Variable(type: {:?}, id: {:?})", self._type, self.id,)
write!(
f,
"Variable(type: {:?}, id: {:?}, is_mutable: {:?})",
self._type, self.id, self.is_mutable
)
}
}

View file

@ -5,7 +5,7 @@ impl From<typed_absy::types::ConcreteSignature> for zir::types::Signature {
fn from(s: typed_absy::types::ConcreteSignature) -> zir::types::Signature {
zir::types::Signature {
inputs: s.inputs.into_iter().flat_map(from_type).collect(),
outputs: s.outputs.into_iter().flat_map(from_type).collect(),
outputs: from_type(*s.output),
}
}
}
@ -20,7 +20,7 @@ fn from_type(t: typed_absy::types::ConcreteType) -> Vec<zir::types::Type> {
}
typed_absy::types::ConcreteType::Array(array_type) => {
let inner = from_type(*array_type.ty);
(0..array_type.size).flat_map(|_| inner.clone()).collect()
(0..*array_type.size).flat_map(|_| inner.clone()).collect()
}
typed_absy::types::ConcreteType::Struct(members) => members
.into_iter()

View file

@ -8,11 +8,13 @@ Function calls help make programs clear and modular.
Arguments are passed by value.
Function parameters can be declared as mutable to allow for mutation within the function's body. However, mutable function arguments are still passed by value, so the original value can never be mutated.
```zokrates
{{#include ../../../zokrates_cli/examples/book/side_effects.zok}}
```
Generic paramaters, if any, must be compile-time constants. They are inferred by the compiler if that is possible, but can also be provided explicitly.
Generic parameters, if any, must be compile-time constants. They are inferred by the compiler if that is possible, but can also be provided explicitly.
```zokrates
{{#include ../../../zokrates_cli/examples/book/generic_call.zok}}

View file

@ -18,18 +18,4 @@ The generic parameters can be provided explicitly, especially when they cannot b
```zokrates
{{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}}
```
Functions can return multiple values by providing them as a comma-separated list.
```zokrates
{{#include ../../../zokrates_cli/examples/book/multi_return.zok}}
```
### Variable declaration
When defining a variable as the return value of a function, types are provided when the variable needs to be declared:
```zokrates
{{#include ../../../zokrates_cli/examples/book/multi_def.zok}}
```

View file

@ -8,7 +8,7 @@ You can separate your code into multiple ZoKrates files using `import` statement
The preferred way to import a symbol is by module and name:
```zokrates
from "./path/to/my/module" import MySymbol
from "./path/to/my/module" import MySymbol;
// `MySymbol` is now in scope.
```
@ -16,7 +16,7 @@ from "./path/to/my/module" import MySymbol
To import multiple symbols with a single import statement, separate the symbols names with commas:
```zokrates
from "./path/to/my/module" import MySymbol, MyOtherSymbol
from "./path/to/my/module" import MySymbol, MyOtherSymbol;
```
#### Aliasing
@ -24,7 +24,7 @@ from "./path/to/my/module" import MySymbol, MyOtherSymbol
The `as` keyword enables renaming symbols:
```zokrates
from "./path/to/my/module" import MySymbol as MyAlias
from "./path/to/my/module" import MySymbol as MyAlias;
// `MySymbol` is now in scope under the alias MyAlias.
```
@ -32,11 +32,11 @@ from "./path/to/my/module" import MySymbol as MyAlias
The legacy way to import a symbol is by only specifying a module:
```
import "./path/to/my/module"
import "./path/to/my/module";
```
In this case, the name of the symbol is assumed to be `main` and the alias is assumed to be the module's filename so that the above is equivalent to
```zokrates
from "./path/to/my/module" import main as module
from "./path/to/my/module" import main as module;
// `main` is now in scope under the alias `module`.
```
@ -59,12 +59,12 @@ Constants declared with the `const` keyword are imported by name.
You can import a resource in the same folder directly, like this:
```zokrates
from "./mycode" import foo
from "./mycode" import foo;
```
Imports up the file-system tree are supported:
```zokrates
from "../../../mycode" import foo
from "../../../mycode" import foo;
```
### Absolute Imports

View file

@ -71,8 +71,8 @@ ZoKrates offers a special shorthand syntax to initialize an array with a constan
The following code provides examples for declaration and initialization:
```zokrates
field[3] a = [1, 2, 3] // initialize a field array with field values
bool[13] b = [false; 13] // initialize a bool array with value false
field[3] a = [1, 2, 3]; // initialize a field array with field values
bool[13] b = [false; 13]; // initialize a bool array with value false
```
#### Multidimensional Arrays
@ -95,16 +95,16 @@ ZoKrates provides some syntactic sugar to retrieve subsets of arrays.
The spread operator `...` applied to an array copies the elements of the existing array.
This can be used to conveniently compose new arrays, as shown in the following example:
```
field[3] a = [1, 2, 3]
field[4] c = [...a, 4] // initialize an array copying values from `a`, followed by 4
field[3] a = [1, 2, 3];
field[4] c = [...a, 4]; // initialize an array copying values from `a`, followed by 4
```
##### Slices
An array can also be assigned to by creating a copy of a subset of an existing array.
This operation is called slicing, and the following example shows how to slice in ZoKrates:
```
field[3] a = [1, 2, 3]
field[2] b = a[1..3] // initialize an array copying a slice from `a`
field[3] a = [1, 2, 3];
field[2] b = a[1..3]; // initialize an array copying a slice from `a`
```
### Tuples
@ -132,8 +132,8 @@ A struct definition starts with the `struct` keyword followed by a name. Afterwa
```zokrates
struct Point {
field x
field y
field x;
field y;
}
```

View file

@ -10,6 +10,13 @@ Variables need to be declared to be used. Declaration and definition are always
{{#include ../../../zokrates_cli/examples/book/declaration.zok}}
```
### Mutability
Variables are immutable by default. In order to declare a mutable variable, the `mut` keyword is used.
```zokrates
{{#include ../../../zokrates_cli/examples/book/mutable.zok}}
```
### Shadowing
Shadowing is not allowed.

View file

@ -59,11 +59,9 @@ In this example, the ABI specification is:
"type":"field"
}
],
"outputs":[
{
"type":"field"
}
]
"output": {
"type":"field"
}
}
```

View file

@ -24,7 +24,7 @@ const { initialize } = require('zokrates-js')
## Example
```js
initialize().then((zokratesProvider) => {
const source = "def main(private field a) -> field: return a * a";
const source = "def main(private field a) -> field { return a * a; }";
// compilation
const artifacts = zokratesProvider.compile(source);
@ -88,7 +88,7 @@ Returns: `CompilationArtifacts`
Compilation:
```js
const artifacts = zokratesProvider.compile("def main() -> (): return");
const artifacts = zokratesProvider.compile("def main() { return; }");
```
Compilation with custom options:
@ -99,7 +99,7 @@ const options = {
resolveCallback: (currentLocation, importLocation) => {
console.log(currentLocation + ' is importing ' + importLocation);
return {
source: "def main() -> (): return",
source: "def main() { return; }",
location: importLocation
};
}
@ -135,13 +135,13 @@ Returns: `ComputationResult`
**Example:**
```js
const code = 'def main(private field a) -> (field): return a * a';
const code = 'def main(private field a) -> field { return a * a; }';
const artifacts = zokratesProvider.compile(code);
const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]);
console.log(witness); // Resulting witness which can be used to generate a proof
console.log(output); // Computation output: ["4"]
console.log(output); // Computation output: "4"
```
##### setup(program)

View file

@ -11,5 +11,5 @@ def fill<R, C>(field v) -> matrix<R, C> {
def main(uint32 a, uint32 b) -> (UInt32Array<2>, matrix<2, 4>) {
UInt32Array<2> res = [a, b];
matrix<2, 4> m = fill(1);
return res, m;
return (res, m);
}

View file

@ -12,5 +12,5 @@ def buzz<N>() -> Buzz<N> {
def main(matrix_2x4 m) -> (Buzz<2>, matrix_2x4) {
Buzz<2> b = buzz::<2>();
return b, m;
return (b, m);
}

View file

@ -1,4 +1,4 @@
def sub(field a) -> field {
def sub(field mut a) -> field {
a = a + 3;
return a;
}

View file

@ -1,8 +1,8 @@
def main() -> u32 {
u32[3] a = [1, 2, 3];
u32 c = 0;
u32 mut c = 0;
for u32 i in 0..3 {
c = c + a[i];
}
return c;
}
}

View file

@ -1,8 +1,8 @@
def main() -> (u32[3]) {
def main() -> u32[3] {
u32[3] a = [1, 2, 3];
u32[3] c = [4, 5, 6];
u32[3] mut c = [4, 5, 6];
for u32 i in 0..3 {
c[i] = c[i] + a[i];
}
return c;
}
}

View file

@ -1,11 +1,10 @@
def main(bool[3] a) -> (field[3]) {
def main(bool[3] mut a) -> field[3] {
bool[3] c = [true, true || false, true];
a[1] = true || a[2];
a[2] = a[0];
field[3] result = [0; 3];
field[3] mut result = [0; 3];
for u32 i in 0..3 {
result[i] = a[i] ? 33 : 0;
}
return result;
}

View file

@ -1,5 +1,5 @@
def main(field[2][2][2] cube) -> field {
field res = 0;
field mut res = 0;
for u32 i in 0..2 {
for u32 j in 0..2 {

View file

@ -1,3 +1,3 @@
def main(field value) -> (field[3]) {
def main(field value) -> field[3] {
return [value, value, value];
}

View file

@ -1,5 +1,5 @@
def main(field[10][10][10] a, u32 i, u32 j, u32 k) -> (field[3]) {
def main(field[10][10][10] mut a, u32 i, u32 j, u32 k) -> field[3] {
a[i][j][k] = 42;
field[3][3] b = [[1, 2, 3], [1, 2, 3], [1, 2, 3]];
return b[0];
}
}

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
def foo(field[3] a) -> field {
def foo(field[3] mut a) -> field {
a[1] = 2;
return a[1];
}
@ -7,6 +7,5 @@ def main() -> (field, field) {
field[3] a = [0, 0, 0];
field res = foo(a);
assert(a[1] == 0);
return res, a[1];
}
return (res, a[1]);
}

View file

@ -3,9 +3,9 @@ def foo(field a) -> field {
}
def main(field a) -> (field, field) {
field[2] result = [0, 0];
field[2] mut result = [0, 0];
field r = foo(a);
result[1] = r;
assert(result[1] == r);
return result[1], r;
}
return (result[1], r);
}

View file

@ -2,12 +2,8 @@ def foo() -> u32 {
return 0;
}
def bar() -> (u32, u32) {
return 0, 0;
}
def main(u32[1] a, u32 b) {
def main(u32[1] mut a, (u32,) mut b) {
a[0] = foo();
a[0], b = bar();
b.0 = foo();
return;
}

View file

@ -1,5 +1,5 @@
def main() -> field {
field[3] a = [1, 2, 3]; // initialize a field array with field values
field[3] mut a = [1, 2, 3]; // initialize a field array with field values
a[2] = 4; // set a member to a value
field[4] b = [42; 4]; // initialize an array of 4 values all equal to 42
field[4] c = [...a, 4]; // initialize an array copying values from `a`, followed by 4

View file

@ -1,4 +1,4 @@
def main() -> () {
def main() {
assert(1f + 1f == 2f);
return;
}

View file

@ -1,14 +1,16 @@
def swap(u32 a, u32 b, bool c) -> (u32, u32) {
def swap(u32 a, u32 mut b, bool c) -> (u32, u32) {
u32 a_prime = c ? b : a;
b = c ? a : b;
return a_prime, b;
b = c ? a : b;
return (a_prime, b);
}
def bubblesort<N>(u32[N] a) -> u32[N] {
def bubblesort<N>(u32[N] mut a) -> u32[N] {
for u32 i in 0..(N-1) {
for u32 j in 0..(N-1-i) {
bool need_swap = a[j + 1] < a[j];
a[j], a[j + 1] = swap(a[j], a[j + 1], need_swap);
(u32, u32) swapped = swap(a[j], a[j + 1], need_swap);
a[j] = swapped.0;
a[j + 1] = swapped.1;
}
}
return a;
@ -17,4 +19,3 @@ def bubblesort<N>(u32[N] a) -> u32[N] {
def main(u32[10] a) -> u32[10] {
return bubblesort(a);
}

View file

@ -1,6 +1,6 @@
def main() {
// declare and define `my_variable`
field my_variable = 2;
field mut my_variable = 2;
// redefine `my_variable`
my_variable = 3;
return;

View file

@ -1,6 +1,6 @@
// a function to sum the N first powers of a field element
def sum_powers<N>(field a) -> field {
field res = 0;
field mut res = 0;
for u32 i in 0..N {
res = res + a ** i;
}

View file

@ -1,5 +1,5 @@
def main() -> u32 {
u32 res = 0;
u32 mut res = 0;
for u32 i in 0..4 {
for u32 j in i..5 {
res = res + i;

View file

@ -1,8 +1,8 @@
def main() -> u32 {
u32 a = 0;
u32 mut a = 0;
for u32 i in 0..5 {
a = a + i;
}
// return i <- not allowed
// return i; <- not allowed
return a;
}
}

View file

@ -1,5 +1,5 @@
def foo() -> field {
// return myGlobal <- not allowed
// return myGlobal; <- not allowed
return 42;
}

View file

@ -1,5 +1,5 @@
def sum<N>(field[N] a) -> field {
field res = 0;
field mut res = 0;
for u32 i in 0..N {
res = res + a[i];
}

View file

@ -1,11 +0,0 @@
def foo() -> (field, field) {
return 21, 42;
}
def main() {
// a is declared here
field a = 1;
// b is declared here
a, field b = foo();
return;
}

View file

@ -1,3 +0,0 @@
def main() -> (field, field[3]) {
return 1, [2, 3, 4];
}

View file

@ -7,4 +7,3 @@ def main() -> field {
// allowed access [0..2][0..3]
return a[1][2];
}

View file

@ -0,0 +1,7 @@
def main() {
field a = 42;
// a = 43; <- not allowed, as `a` is immutable
field mut b = 42;
b = 43; // ok
return;
}

View file

@ -1,8 +1,8 @@
def main() -> field {
field a = 2;
// field a = 3 <- not allowed
// field a = 3; <- not allowed
for u32 i in 0..5 {
// field a = 7 <- not allowed
// field a = 7; <- not allowed
}
return a;
}

View file

@ -1,3 +1,3 @@
def main(field a, field b) -> (bool) {
def main(field a, field b) -> bool {
return !(a == b);
}

View file

@ -8,12 +8,12 @@ import "utils/casts/u32_to_bits" as u32_to_bits;
// the remaining preimage bits.
def main(private u32[16] preimage, u32 bitNum) -> (u32[8], bool) {
// Convert the preimage to bits
bool[512] preimageBits = [false; 512];
bool[512] mut preimageBits = [false; 512];
for u32 i in 0..16 {
bool[32] val = u32_to_bits(preimage[i]);
for u32 bit in 0..32 {
preimageBits[i*32 + bit] = val[bit];
}
}
return sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum];
return (sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum]);
}

View file

@ -1,4 +1,4 @@
def incr(field a) -> field {
def incr(field mut a) -> field {
a = a + 1;
return a;
}

View file

@ -3,8 +3,8 @@ struct Point {
field y;
}
def main(field a) -> (Point) {
Point p = Point { x: 1, y: 0 };
def main(field a) -> Point {
Point mut p = Point { x: 1, y: 0 };
p.x = a;
p.y = p.x;
return p;

View file

@ -3,8 +3,7 @@ struct Point {
field y;
}
def main() -> (Point) {
def main() -> Point {
Point p = Point { x: 1, y: 0 };
return p;
}

View file

@ -8,9 +8,8 @@ struct Foo<P> {
bool b;
}
def main() -> (Foo<2>) {
Foo<2>[2] f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true }];
def main() -> Foo<2> {
Foo<2>[2] mut f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true }];
f[0].a.c = [42, 43];
return f[0];
}

View file

@ -1,6 +1,5 @@
def main() -> bool {
(field[2], bool) v = ([1, 2], true);
(field[2], bool) mut v = ([1, 2], true);
v.0 = [42, 43];
return v.1;
}

View file

@ -1,12 +1,12 @@
def foo() -> (field, field[3]) {
return 1, [2, 3, 4];
return (1, [2, 3, 4]);
}
def foo() -> (field, field) {
return 1, 2;
return (1, 2);
}
def main() {
field a, field[3] b = foo();
(field, field[3]) a = foo();
return;
}

View file

@ -1,7 +1,7 @@
// comparison operator example
def main(field x) -> field {
field y = x >= 3 ? 1 : 5;
field z = y <= x ? x**3 : y**3;
def main(field mut x) -> field {
field mut y = x >= 3 ? 1 : 5;
field mut z = y <= x ? x**3 : y**3;
y = x < 3 ? 2 : 6;
z = y > z ? 1 : 2;
x = x == x ? x : y;

View file

@ -1,7 +0,0 @@
def foo<N>() -> field[N] {
return [42; N];
}
def main() -> field[2] {
return foo(); // N is currently not infered to 2 here
}

View file

@ -0,0 +1,11 @@
def bar() -> field[3] {
return [1, 2, 3];
}
def foo<N>() -> field[N] {
return bar();
}
def main() -> field[2] {
return foo();
}

View file

@ -2,6 +2,5 @@ def assert() {
return;
}
def main():
return

View file

@ -0,0 +1,4 @@
def main():
field a = 2
a = 3
return

View file

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

View file

@ -1,6 +1,6 @@
struct Foo {}
struct Bar {}
def main() -> (Foo) {
def main() -> Foo {
return Bar {};
}

View file

@ -1,5 +1,5 @@
def constant() -> u32 {
u32 res = 0;
u32 mut res = 0;
u32 x = 3;
for u32 y in 0..x {
res = res + 1;

View file

@ -1,6 +1,6 @@
def func<N>() -> bool {
u64[N] y = [...[0; N-1], 1]; // the rhs should *not* be reduced to [1] because the spread is not empty
u64 q = 0;
u64 mut q = 0;
for u32 i in 0..N {
q = y[i];

View file

@ -3,7 +3,7 @@ def bound(field x) -> u32 {
}
def main(field a) -> field {
field x = 7;
field mut x = 7;
x = x + 1;
for u32 i in 0..bound(x) + bound(x + 1) {
x = x + a;

View file

@ -16,8 +16,7 @@ def cubeThing(field thing) -> field {
}
def main(u32 index) -> bool {
field thing = getThing(index);
field mut thing = getThing(index);
thing = cubeThing(thing);
return lt(cutoff(), thing);
}

View file

@ -4,7 +4,7 @@ def add(field a, field b) -> field {
}
def main(field a, field b, field c, field d) -> field {
field g = a + b;
field mut g = a + b;
field x = add(a, b);
field y = add(c, d);
g = add(x, g);

View file

@ -2,7 +2,7 @@ def constant() -> field {
return 123123;
}
def add(field a, field b) -> field {
def add(field mut a, field b) -> field {
a = constant();
return a + b;
}

View file

@ -3,7 +3,6 @@ def add(field a,field b) -> field {
}
def main(field a,field b) -> field {
field c = add(a, b);
field mut c = add(a, b);
return c;
}

View file

@ -8,7 +8,7 @@ const u32 DEPTH = 3;
def main(u32[8] root, private u32[8] leaf, private bool[DEPTH] directionSelector, private u32[DEPTH][8] path) -> bool {
// Start from the leaf
u32[8] digest = leaf;
u32[8] mut digest = leaf;
// Loop up the tree
for u32 i in 0..DEPTH {

View file

@ -4,7 +4,7 @@ import "hashes/utils/256bitsDirectionHelper" as multiplex;
const u32 DEPTH = 3;
def select(bool condition, u32[8] left, u32[8] right) -> (u32[8], u32[8]) {
return condition ? right : left, condition ? left : right;
return (condition ? right : left, condition ? left : right);
}
// Merke-Tree inclusion proof for tree depth 4 using sha256
@ -12,13 +12,13 @@ def select(bool condition, u32[8] left, u32[8] right) -> (u32[8], u32[8]) {
def main(u32[8] root, private u32[8] leaf, private bool[DEPTH] directionSelector, private u32[DEPTH][8] path) -> bool {
// Start from the leaf
u32[8] digest = leaf;
u32[8] mut digest = leaf;
// Loop up the tree
for u32 i in 0..DEPTH {
u32[8] left, u32[8] right = select(directionSelector[i], digest, path[i]);
digest = hash(left, right);
}
// Loop up the tree
for u32 i in 0..DEPTH {
(u32[8], u32[8]) s = select(directionSelector[i], digest, path[i]);
digest = hash(s.0, s.1);
}
return digest == root;
}

View file

@ -1,9 +0,0 @@
def foo(field a) -> (field, field, field, field) {
field b = 12 * a;
return a, 2 * a, 5 * b, a * b;
}
def main(field i) {
field x, field y, field z, field t = foo(i);
return;
}

View file

@ -1,8 +0,0 @@
def foo() -> (field, field) {
return 1, 2;
}
def main() -> (field, field) {
field a, field b = foo();
return a + b, b - a;
}

View file

@ -2,8 +2,8 @@ import "utils/casts/u32_to_field" as to_field;
// Binomial Coeffizient, n!/(k!*(n-k)!).
def fac(field x) -> field {
field f = 1;
field counter = 0;
field mut f = 1;
field mut counter = 0;
for u32 i in 1..100 {
f = counter == x ? f : f * to_field(i);
counter = counter == x ? counter : counter + 1;

View file

@ -1,5 +1,5 @@
def main() {
field x = 2**4;
field mut x = 2**4;
assert(x == 16);
x = x**2;
assert(x == 256);
@ -7,7 +7,7 @@ def main() {
assert(y == 27);
field z = y**2;
assert(z == 729);
field a = 5**2;
field mut a = 5**2;
assert(a == 25);
a = a**2;
assert(a == 625);

View file

@ -1,10 +1,10 @@
def main() -> field {
field a = 1 + 2 + 3;
field b = 1 < a ? 3 : a + 3;
field c = b + a == 2 ? 1 : b;
field mut c = b + a == 2 ? 1 : b;
for u32 e in 0..2 {
field g = 4;
c = c + g;
}
return c * a;
}
}

View file

@ -1,9 +1,9 @@
def foo(field a, field b) -> (field, field) {
assert(a == b);
return a, b;
assert(a == b);
return (a, b);
}
def main() -> field {
field a, field b = foo(1, 1);
return a + b;
(field, field) v = foo(1, 1);
return v.0 + v.1;
}

View file

@ -1,9 +1,8 @@
def main(field x) -> field {
field a = x + 5;
field mut a = x + 5;
field b = a + x;
a = 7;
field c = a + b;
a = a + 5;
return a + c;
}

View file

@ -9,7 +9,7 @@ struct Foo {
}
def main() -> Foo {
Foo[2] f = [
Foo[2] mut f = [
Foo {
a: Bar {
c: [0, 0],

View file

@ -26,7 +26,7 @@ def checkNoDuplicates(field a, field b, field c, field d) -> bool {
// returns true if and only if `x` is one of the `4` primes
def validateInput(field x) -> bool {
field res = 1;
field mut res = 1;
for u32 i in 0..4 {
res = res * (x - PRIMES[i]);
@ -39,7 +39,7 @@ def validateInput(field x) -> bool {
def main(field a21, field b11, field b22, field c11, field c22, field d21, private field a11, private field a12, private field a22, private field b12, private field b21, private field c12, private field c21, private field d11, private field d12, private field d22) -> bool {
Grid<4> a = [[a11, a12, b11, b12], [a21, a22, b21, b22], [c11, c12, d11, d12], [c21, c22, d21, d22]];
bool res = true;
bool mut res = true;
// go through the whole grid and check that all elements are valid
for u32 i in 0..4 {

View file

@ -11,7 +11,7 @@
// We use a naive encoding of the values as `[1, 2, 3, 4]` and rely on if-else statements to detect duplicates
def countDuplicates(field e11, field e12, field e21, field e22) -> field {
field duplicates = e11 == e12 ? 1 : 0;
field mut duplicates = e11 == e12 ? 1 : 0;
duplicates = duplicates + e11 == e21 ? 1 : 0;
duplicates = duplicates + e11 == e22 ? 1 : 0;
duplicates = duplicates + e12 == e21 ? 1 : 0;
@ -49,7 +49,7 @@ def main(field a21, field b11, field b22, field c11, field c22, field d21, priva
assert(validateInput(d21));
assert(validateInput(d22));
field duplicates = 0; // globally counts duplicate entries in boxes, rows and columns
field mut duplicates = 0; // globally counts duplicate entries in boxes, rows and columns
// check box correctness

View file

@ -1,4 +1,4 @@
def main((field, field) p, (field, field) q) -> ((field, field)) {
def main((field, field) p, (field, field) q) -> (field, field) {
field a = 42;
field d = 21;

View file

@ -8,12 +8,12 @@ struct Foo {
bool b;
}
def main() -> (((field[2], bool), bool)) {
((field[2], bool), bool)[2] f = [
(([0, 0], false), true),
(([0, 0], false), true)
];
f[0].0.0 = [42, 43];
return f[0];
def main() -> ((field[2], bool), bool) {
((field[2], bool), bool)[2] mut f = [
(([0, 0], false), true),
(([0, 0], false), true)
];
f[0].0.0 = [42, 43];
return f[0];
}

View file

@ -8,7 +8,7 @@ use zokrates_abi::Encode;
use zokrates_ast::ir::{self, ProgEnum};
use zokrates_ast::typed::{
abi::Abi,
types::{ConcreteSignature, ConcreteType},
types::{ConcreteSignature, ConcreteType, GTupleType},
};
use zokrates_field::Field;
@ -104,7 +104,9 @@ fn cli_compute<T: Field, I: Iterator<Item = ir::Statement<T>>>(
}
false => ConcreteSignature::new()
.inputs(vec![ConcreteType::FieldElement; ir_prog.arguments.len()])
.outputs(vec![ConcreteType::FieldElement; ir_prog.return_count]),
.output(ConcreteType::Tuple(GTupleType::new(
vec![ConcreteType::FieldElement; ir_prog.return_count],
))),
};
use zokrates_abi::Inputs;
@ -166,7 +168,7 @@ fn cli_compute<T: Field, I: Iterator<Item = ir::Statement<T>>>(
use zokrates_abi::Decode;
let results_json_value: serde_json::Value =
zokrates_abi::Values::decode(witness.return_values(), signature.outputs).into_serde_json();
zokrates_abi::Value::decode(witness.return_values(), *signature.output).into_serde_json();
if verbose {
println!("\nWitness: \n{}\n", results_json_value);

View file

@ -1,4 +1,4 @@
def main(field[2][2] a) -> field[2][2] {
def main(field[2][2] mut a) -> field[2][2] {
a[1][1] = 42;
return a;
}
}

View file

@ -2,8 +2,8 @@ import "utils/casts/u32_to_field" as to_field;
// Binomial Coeffizient, n!/(k!*(n-k)!).
def fac(field x) -> field {
field f = 1;
field counter = 0;
field mut f = 1;
field mut counter = 0;
for u32 i in 1..100 {
f = counter == x ? f : f * to_field(i);
counter = counter == x ? counter : counter + 1;

View file

@ -1,3 +1,3 @@
def main(private field[3] a, private field b, private field[4] c) -> (field, field[3], field[4]) {
return b, a, c;
return (b, a, c);
}

View file

@ -476,7 +476,7 @@ struct Bar { field a; }
}]
))
}],
outputs: vec![]
output: ConcreteType::Tuple(GTupleType::new(vec![]))
}
);
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
use zokrates_ast::typed::{
folder::*, BlockExpression, BooleanExpression, Conditional, ConditionalExpression,
ConditionalOrExpression, CoreIdentifier, Expr, Identifier, TypedProgram, TypedStatement,
ConditionalOrExpression, CoreIdentifier, Expr, Identifier, Type, TypedProgram, TypedStatement,
Variable,
};
use zokrates_field::Field;
@ -66,7 +66,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConditionRedefiner<'ast, T> {
condition => {
let condition_id = Identifier::from(CoreIdentifier::Condition(self.index));
self.buffer.push(TypedStatement::Definition(
Variable::boolean(condition_id.clone()).into(),
Variable::immutable(condition_id.clone(), Type::Boolean).into(),
condition.into(),
));
self.index += 1;
@ -164,7 +164,7 @@ mod tests {
let expected = vec![
// define condition
TypedStatement::Definition(
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
condition.into(),
),
// rewrite statement
@ -233,11 +233,11 @@ mod tests {
let expected = vec![
// define conditions
TypedStatement::Definition(
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
condition_0.into(),
),
TypedStatement::Definition(
Variable::with_id_and_type(CoreIdentifier::Condition(1), Type::Boolean).into(),
Variable::immutable(CoreIdentifier::Condition(1), Type::Boolean).into(),
condition_1.into(),
),
// rewrite statement
@ -341,7 +341,7 @@ mod tests {
let expected = vec![
// define conditions
TypedStatement::Definition(
Variable::with_id_and_type(CoreIdentifier::Condition(0), Type::Boolean).into(),
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
condition_0.into(),
),
// rewrite statement
@ -356,11 +356,8 @@ mod tests {
FieldElementExpression::Number(Bn128Field::from(1)).into(),
),
TypedStatement::Definition(
Variable::with_id_and_type(
CoreIdentifier::Condition(1),
Type::Boolean,
)
.into(),
Variable::immutable(CoreIdentifier::Condition(1), Type::Boolean)
.into(),
condition_1.into(),
),
],
@ -378,11 +375,8 @@ mod tests {
FieldElementExpression::Number(Bn128Field::from(2)).into(),
),
TypedStatement::Definition(
Variable::with_id_and_type(
CoreIdentifier::Condition(2),
Type::Boolean,
)
.into(),
Variable::immutable(CoreIdentifier::Condition(2), Type::Boolean)
.into(),
condition_2.into(),
),
],

View file

@ -3,8 +3,8 @@ use zokrates_ast::common::FlatEmbed;
use zokrates_ast::typed::TypedProgram;
use zokrates_ast::typed::{
result_folder::ResultFolder,
result_folder::{fold_expression_list_inner, fold_uint_expression_inner},
Constant, TypedExpressionListInner, Types, UBitwidth, UExpressionInner,
result_folder::{fold_statement, fold_uint_expression_inner},
Constant, EmbedCall, TypedStatement, UBitwidth, UExpressionInner,
};
use zokrates_field::Field;
@ -28,6 +28,46 @@ impl fmt::Display for Error {
impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker {
type Error = Error;
fn fold_statement(
&mut self,
s: TypedStatement<'ast, T>,
) -> Result<Vec<TypedStatement<'ast, T>>, Self::Error> {
match s {
TypedStatement::EmbedCallDefinition(assignee, embed_call) => match embed_call {
EmbedCall {
embed: FlatEmbed::BitArrayLe,
..
} => {
let arguments = embed_call
.arguments
.into_iter()
.map(|a| self.fold_expression(a))
.collect::<Result<Vec<_>, _>>()?;
if arguments[1].is_constant() {
Ok(vec![TypedStatement::EmbedCallDefinition(
assignee,
EmbedCall {
embed: FlatEmbed::BitArrayLe,
generics: embed_call.generics,
arguments,
},
)])
} else {
Err(Error(format!(
"Cannot compare to a variable value, found `{}`",
arguments[1]
)))
}
}
embed_call => Ok(vec![TypedStatement::EmbedCallDefinition(
assignee, embed_call,
)]),
},
s => fold_statement(self, s),
}
}
fn fold_uint_expression_inner(
&mut self,
bitwidth: UBitwidth,
@ -63,33 +103,4 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker {
e => fold_uint_expression_inner(self, bitwidth, e),
}
}
fn fold_expression_list_inner(
&mut self,
tys: &Types<'ast, T>,
l: TypedExpressionListInner<'ast, T>,
) -> Result<TypedExpressionListInner<'ast, T>, Error> {
match l {
TypedExpressionListInner::EmbedCall(FlatEmbed::BitArrayLe, generics, arguments) => {
let arguments = arguments
.into_iter()
.map(|a| self.fold_expression(a))
.collect::<Result<Vec<_>, _>>()?;
if arguments[1].is_constant() {
Ok(TypedExpressionListInner::EmbedCall(
FlatEmbed::BitArrayLe,
generics,
arguments,
))
} else {
Err(Error(format!(
"Cannot compare to a variable value, found `{}`",
arguments[1]
)))
}
}
l => fold_expression_list_inner(self, tys, l),
}
}
}

View file

@ -109,7 +109,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantResolver<'ast, T> {
#[cfg(test)]
mod tests {
use super::*;
use zokrates_ast::typed::types::DeclarationSignature;
use zokrates_ast::typed::types::{DeclarationSignature, GTupleType};
use zokrates_ast::typed::{
DeclarationArrayType, DeclarationFunctionKey, DeclarationType, FieldElementExpression,
GType, Identifier, TypedConstant, TypedExpression, TypedFunction, TypedFunctionSymbol,
@ -130,12 +130,12 @@ mod tests {
let const_id = "a";
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![
statements: vec![TypedStatement::Return(
FieldElementExpression::Identifier(Identifier::from(const_id)).into(),
])],
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
};
let program = TypedProgram {
@ -158,7 +158,7 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
),
TypedFunctionSymbol::Here(main),
)
@ -190,13 +190,12 @@ mod tests {
let const_id = CanonicalConstantIdentifier::new("a", "main".into());
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![BooleanExpression::Identifier(
Identifier::from(const_id.clone()),
)
.into()])],
statements: vec![TypedStatement::Return(
BooleanExpression::Identifier(Identifier::from(const_id.clone())).into(),
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::Boolean]),
.output(DeclarationType::Boolean),
};
let program = TypedProgram {
@ -217,7 +216,7 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::Boolean]),
.output(DeclarationType::Boolean),
),
TypedFunctionSymbol::Here(main),
)
@ -249,14 +248,14 @@ mod tests {
let const_id = CanonicalConstantIdentifier::new("a", "main".into());
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![UExpressionInner::Identifier(
Identifier::from(const_id.clone()),
)
.annotate(UBitwidth::B32)
.into()])],
statements: vec![TypedStatement::Return(
UExpressionInner::Identifier(Identifier::from(const_id.clone()))
.annotate(UBitwidth::B32)
.into(),
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::Uint(UBitwidth::B32)]),
.output(DeclarationType::Uint(UBitwidth::B32)),
};
let program = TypedProgram {
@ -279,7 +278,7 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::Uint(UBitwidth::B32)]),
.output(DeclarationType::Uint(UBitwidth::B32)),
),
TypedFunctionSymbol::Here(main),
)
@ -311,24 +310,26 @@ mod tests {
let const_id = CanonicalConstantIdentifier::new("a", "main".into());
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![FieldElementExpression::Add(
FieldElementExpression::select(
ArrayExpressionInner::Identifier(Identifier::from(const_id.clone()))
.annotate(GType::FieldElement, 2u32),
UExpressionInner::Value(0u128).annotate(UBitwidth::B32),
statements: vec![TypedStatement::Return(
FieldElementExpression::Add(
FieldElementExpression::select(
ArrayExpressionInner::Identifier(Identifier::from(const_id.clone()))
.annotate(GType::FieldElement, 2u32),
UExpressionInner::Value(0u128).annotate(UBitwidth::B32),
)
.into(),
FieldElementExpression::select(
ArrayExpressionInner::Identifier(Identifier::from(const_id.clone()))
.annotate(GType::FieldElement, 2u32),
UExpressionInner::Value(1u128).annotate(UBitwidth::B32),
)
.into(),
)
.into(),
FieldElementExpression::select(
ArrayExpressionInner::Identifier(Identifier::from(const_id.clone()))
.annotate(GType::FieldElement, 2u32),
UExpressionInner::Value(1u128).annotate(UBitwidth::B32),
)
.into(),
)
.into()])],
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
};
let program = TypedProgram {
@ -363,7 +364,7 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
),
TypedFunctionSymbol::Here(main),
)
@ -396,12 +397,12 @@ mod tests {
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![
statements: vec![TypedStatement::Return(
FieldElementExpression::Identifier(Identifier::from(const_b_id.clone())).into(),
])],
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
};
let program = TypedProgram {
@ -437,7 +438,7 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
),
TypedFunctionSymbol::Here(main),
)
@ -522,12 +523,17 @@ mod tests {
)
.into(),
TypedFunctionSymbolDeclaration::new(
DeclarationFunctionKey::with_location("foo", "main")
.signature(DeclarationSignature::new().inputs(vec![]).outputs(vec![])),
DeclarationFunctionKey::with_location("foo", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.output(DeclarationType::Tuple(GTupleType::new(vec![]))),
),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![],
statements: vec![],
signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![]),
signature: DeclarationSignature::new()
.inputs(vec![])
.output(DeclarationType::Tuple(GTupleType::new(vec![]))),
}),
)
.into(),
@ -546,19 +552,19 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![
statements: vec![TypedStatement::Return(
FieldElementExpression::Identifier(Identifier::from(
main_const_id.clone(),
))
.into(),
])],
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
}),
)
.into(),
@ -592,19 +598,19 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![
statements: vec![TypedStatement::Return(
FieldElementExpression::Identifier(Identifier::from(
main_const_id.clone(),
))
.into(),
])],
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
}),
)
.into(),
@ -702,12 +708,17 @@ mod tests {
)
.into(),
TypedFunctionSymbolDeclaration::new(
DeclarationFunctionKey::with_location("foo", "main")
.signature(DeclarationSignature::new().inputs(vec![]).outputs(vec![])),
DeclarationFunctionKey::with_location("foo", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.output(DeclarationType::Tuple(GTupleType::new(vec![]))),
),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![],
statements: vec![],
signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![]),
signature: DeclarationSignature::new()
.inputs(vec![])
.output(DeclarationType::Tuple(GTupleType::new(vec![]))),
}),
)
.into(),
@ -748,19 +759,19 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![
statements: vec![TypedStatement::Return(
FieldElementExpression::Identifier(Identifier::from(
main_foo_const_id.clone(),
))
.into(),
])],
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
}),
)
.into(),
@ -823,19 +834,19 @@ mod tests {
DeclarationFunctionKey::with_location("main", "main").signature(
DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![],
statements: vec![TypedStatement::Return(vec![
statements: vec![TypedStatement::Return(
FieldElementExpression::Identifier(Identifier::from(
main_foo_const_id.clone(),
))
.into(),
])],
)],
signature: DeclarationSignature::new()
.inputs(vec![])
.outputs(vec![DeclarationType::FieldElement]),
.output(DeclarationType::FieldElement),
}),
)
.into(),

Some files were not shown because too many files have changed in this diff Show more