From ffb7cab142f771c2191c441b4f0b5477093ae2b4 Mon Sep 17 00:00:00 2001 From: gluax Date: Mon, 3 May 2021 15:32:11 -0400 Subject: [PATCH 1/3] bug fix 905, make sure values are constant when assign is constant --- asg/src/error/mod.rs | 10 ++++++++++ asg/src/statement/definition.rs | 11 +++++++++++ asg/tests/pass/address/ternary.leo | 2 +- asg/tests/pass/boolean/not_mutable.leo | 2 +- asg/tests/pass/circuits/pedersen_mock.leo | 6 +++--- asg/tests/pass/core/blake2s_random.leo | 2 +- asg/tests/pass/field/ternary.leo | 2 +- asg/tests/pass/group/point_input.leo | 2 +- asg/tests/pass/group/ternary.leo | 2 +- asg/tests/pass/integers/i128/ternary.leo | 2 +- asg/tests/pass/integers/i16/ternary.leo | 2 +- asg/tests/pass/integers/i32/ternary.leo | 2 +- asg/tests/pass/integers/i64/ternary.leo | 2 +- asg/tests/pass/integers/i8/ternary.leo | 2 +- asg/tests/pass/integers/u128/ternary.leo | 2 +- asg/tests/pass/integers/u16/ternary.leo | 2 +- asg/tests/pass/integers/u32/ternary.leo | 2 +- asg/tests/pass/integers/u64/ternary.leo | 2 +- asg/tests/pass/integers/u8/ternary.leo | 2 +- asg/tests/pass/mutability/let_mut_nested.leo | 2 +- asg/tests/pass/mutability/swap.leo | 4 ++-- asg/tests/pass/statements/conditional/for_loop.leo | 2 +- asg/tests/pass/statements/ternary_basic.leo | 4 ++-- compiler/tests/address/ternary.leo | 2 +- compiler/tests/boolean/not_mutable.leo | 2 +- compiler/tests/circuits/pedersen_mock.leo | 6 +++--- .../core/packages/unstable/blake2s/blake2s_random.leo | 2 +- compiler/tests/integers/i128/ternary.leo | 2 +- compiler/tests/integers/i16/ternary.leo | 2 +- compiler/tests/integers/i32/ternary.leo | 2 +- compiler/tests/integers/i64/ternary.leo | 2 +- compiler/tests/integers/i8/ternary.leo | 2 +- compiler/tests/integers/u128/ternary.leo | 2 +- compiler/tests/integers/u16/ternary.leo | 2 +- compiler/tests/integers/u32/ternary.leo | 2 +- compiler/tests/integers/u64/ternary.leo | 2 +- compiler/tests/integers/u8/ternary.leo | 2 +- compiler/tests/mutability/let_mut_nested.leo | 2 +- compiler/tests/mutability/swap.leo | 4 ++-- compiler/tests/statements/conditional/for_loop.leo | 2 +- compiler/tests/statements/mod.rs | 8 ++++++++ compiler/tests/statements/ternary_basic.leo | 4 ++-- .../statements/ternary_non_const_conditional_fail.leo | 4 ++++ 43 files changed, 80 insertions(+), 47 deletions(-) create mode 100644 compiler/tests/statements/ternary_non_const_conditional_fail.leo diff --git a/asg/src/error/mod.rs b/asg/src/error/mod.rs index 7ee1eb62cf..7e2170b2d3 100644 --- a/asg/src/error/mod.rs +++ b/asg/src/error/mod.rs @@ -172,6 +172,16 @@ impl AsgConvertError { ) } + pub fn invalid_const_assign(name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "failed to create const variable(s) '{}' with non constant values.", + name + ), + span, + ) + } + pub fn duplicate_function_definition(name: &str, span: &Span) -> Self { Self::new_from_span( format!("a function named \"{}\" already exists in this scope", name), diff --git a/asg/src/statement/definition.rs b/asg/src/statement/definition.rs index 4d2339a0f7..4e2ce3cd83 100644 --- a/asg/src/statement/definition.rs +++ b/asg/src/statement/definition.rs @@ -75,6 +75,17 @@ impl<'a> FromAst<'a, leo_ast::DefinitionStatement> for &'a Statement<'a> { let value = <&Expression<'a>>::from_ast(scope, &statement.value, type_.clone().map(Into::into))?; + if matches!(statement.declaration_type, leo_ast::Declare::Const) && !value.is_consty() { + let var_names = statement + .variable_names + .iter() + .map(ToString::to_string) + .collect::>() + .join(" ,"); + + return Err(AsgConvertError::invalid_const_assign(&var_names, &statement.span)); + } + let type_ = type_.or_else(|| value.get_type()); let mut output_types = vec![]; diff --git a/asg/tests/pass/address/ternary.leo b/asg/tests/pass/address/ternary.leo index f29e13ab5d..65a8eea1e7 100644 --- a/asg/tests/pass/address/ternary.leo +++ b/asg/tests/pass/address/ternary.leo @@ -2,7 +2,7 @@ function main(s: bool, c: address) { const a = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; const b = aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r; - const r = s? a: b; + let r = s ? a: b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/boolean/not_mutable.leo b/asg/tests/pass/boolean/not_mutable.leo index c621647ff9..92588434e4 100644 --- a/asg/tests/pass/boolean/not_mutable.leo +++ b/asg/tests/pass/boolean/not_mutable.leo @@ -1,4 +1,4 @@ function main () { - let b = false; + const b = false; const a = !b; } \ No newline at end of file diff --git a/asg/tests/pass/circuits/pedersen_mock.leo b/asg/tests/pass/circuits/pedersen_mock.leo index 0fc6752f2f..7f2dc12180 100644 --- a/asg/tests/pass/circuits/pedersen_mock.leo +++ b/asg/tests/pass/circuits/pedersen_mock.leo @@ -1,14 +1,14 @@ circuit PedersenHash { parameters: [u32; 512] - function new(parameters: [u32; 512]) -> Self { + function new(const parameters: [u32; 512]) -> Self { return Self { parameters: parameters }; } - function hash(self, bits: [bool; 512]) -> u32 { + function hash(self, const bits: [bool; 512]) -> u32 { let digest: u32 = 0; for i in 0..512 { - const base = bits[i] ? self.parameters[i] : 0u32; + let base = bits[i] ? self.parameters[i] : 0u32; digest += base; } return digest; diff --git a/asg/tests/pass/core/blake2s_random.leo b/asg/tests/pass/core/blake2s_random.leo index c9592fcbf8..72aef44932 100644 --- a/asg/tests/pass/core/blake2s_random.leo +++ b/asg/tests/pass/core/blake2s_random.leo @@ -1,7 +1,7 @@ import core.unstable.blake2s.Blake2s; function main(seed: [u8; 32], message: [u8; 32], expected: [u8; 32]) { - const actual = Blake2s::hash(seed, message); + let actual = Blake2s::hash(seed, message); console.assert(expected == actual); } diff --git a/asg/tests/pass/field/ternary.leo b/asg/tests/pass/field/ternary.leo index 05cb161b46..f193ad82a3 100644 --- a/asg/tests/pass/field/ternary.leo +++ b/asg/tests/pass/field/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: field, b: field, c: field) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/group/point_input.leo b/asg/tests/pass/group/point_input.leo index a3a8e63bd3..68d8c458a3 100644 --- a/asg/tests/pass/group/point_input.leo +++ b/asg/tests/pass/group/point_input.leo @@ -1,3 +1,3 @@ function main(a: group) { - const b = a; + let b = a; } \ No newline at end of file diff --git a/asg/tests/pass/group/ternary.leo b/asg/tests/pass/group/ternary.leo index 97fba1f5b6..fb69b74521 100644 --- a/asg/tests/pass/group/ternary.leo +++ b/asg/tests/pass/group/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: group, b: group, c: group) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/ternary.leo b/asg/tests/pass/integers/i128/ternary.leo index 3783463b22..a923c428e6 100644 --- a/asg/tests/pass/integers/i128/ternary.leo +++ b/asg/tests/pass/integers/i128/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i128, b: i128, c: i128) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/ternary.leo b/asg/tests/pass/integers/i16/ternary.leo index d66c73cb93..4586b87bb4 100644 --- a/asg/tests/pass/integers/i16/ternary.leo +++ b/asg/tests/pass/integers/i16/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i16, b: i16, c: i16) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/ternary.leo b/asg/tests/pass/integers/i32/ternary.leo index 790769d62f..7927c2998b 100644 --- a/asg/tests/pass/integers/i32/ternary.leo +++ b/asg/tests/pass/integers/i32/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i32, b: i32, c: i32) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/ternary.leo b/asg/tests/pass/integers/i64/ternary.leo index df63b3ad6a..1a2d03a77f 100644 --- a/asg/tests/pass/integers/i64/ternary.leo +++ b/asg/tests/pass/integers/i64/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i64, b: i64, c: i64) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/ternary.leo b/asg/tests/pass/integers/i8/ternary.leo index 0956a9cd39..e1ec1943c9 100644 --- a/asg/tests/pass/integers/i8/ternary.leo +++ b/asg/tests/pass/integers/i8/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i8, b: i8, c: i8) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/ternary.leo b/asg/tests/pass/integers/u128/ternary.leo index 99a6b997e0..22e2e67058 100644 --- a/asg/tests/pass/integers/u128/ternary.leo +++ b/asg/tests/pass/integers/u128/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u128, b: u128, c: u128) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/ternary.leo b/asg/tests/pass/integers/u16/ternary.leo index d6131f9f4f..11d836570d 100644 --- a/asg/tests/pass/integers/u16/ternary.leo +++ b/asg/tests/pass/integers/u16/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u16, b: u16, c: u16) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/ternary.leo b/asg/tests/pass/integers/u32/ternary.leo index f32ffc29fe..3c96a7236c 100644 --- a/asg/tests/pass/integers/u32/ternary.leo +++ b/asg/tests/pass/integers/u32/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u32, b: u32, c: u32) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/ternary.leo b/asg/tests/pass/integers/u64/ternary.leo index 4427cd0466..4c4ddd8e0c 100644 --- a/asg/tests/pass/integers/u64/ternary.leo +++ b/asg/tests/pass/integers/u64/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u64, b: u64, c: u64) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/ternary.leo b/asg/tests/pass/integers/u8/ternary.leo index 5123a511cd..1b436aa054 100644 --- a/asg/tests/pass/integers/u8/ternary.leo +++ b/asg/tests/pass/integers/u8/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u8, b: u8, c: u8) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/asg/tests/pass/mutability/let_mut_nested.leo b/asg/tests/pass/mutability/let_mut_nested.leo index 93236ef4c6..ace4bfb8b4 100644 --- a/asg/tests/pass/mutability/let_mut_nested.leo +++ b/asg/tests/pass/mutability/let_mut_nested.leo @@ -1,5 +1,5 @@ function main () { let x = 2u8; let y = x; - const z = y / 2u8; + let z = y / 2u8; } \ No newline at end of file diff --git a/asg/tests/pass/mutability/swap.leo b/asg/tests/pass/mutability/swap.leo index d0d663ea1a..05fb661085 100644 --- a/asg/tests/pass/mutability/swap.leo +++ b/asg/tests/pass/mutability/swap.leo @@ -1,6 +1,6 @@ // Swap two elements of an array. function swap(a: [u32; 2], const i: u32, const j: u32) -> [u32; 2] { - const t = a[i]; + let t = a[i]; a[i] = a[j]; a[j] = t; return a; @@ -11,7 +11,7 @@ function main() { const expected: [u32; 2] = [1, 0]; // Do swap. - const actual = swap(arr, 0, 1); + let actual = swap(arr, 0, 1); // Check result. for i in 0..2 { diff --git a/asg/tests/pass/statements/conditional/for_loop.leo b/asg/tests/pass/statements/conditional/for_loop.leo index db307f3c36..79df649236 100644 --- a/asg/tests/pass/statements/conditional/for_loop.leo +++ b/asg/tests/pass/statements/conditional/for_loop.leo @@ -7,7 +7,7 @@ function main(a: bool) { } } - const r: u32 = a ? 6 : 0; + let r: u32 = a ? 6 : 0; console.assert(r == b); } diff --git a/asg/tests/pass/statements/ternary_basic.leo b/asg/tests/pass/statements/ternary_basic.leo index 38359004a9..675b681fa9 100644 --- a/asg/tests/pass/statements/ternary_basic.leo +++ b/asg/tests/pass/statements/ternary_basic.leo @@ -1,5 +1,5 @@ function main(a: bool, b: bool) { - const c = a ? true : false; + let c = a ? true : false; - const d = c == b; + let d = c == b; } \ No newline at end of file diff --git a/compiler/tests/address/ternary.leo b/compiler/tests/address/ternary.leo index f29e13ab5d..65a8eea1e7 100644 --- a/compiler/tests/address/ternary.leo +++ b/compiler/tests/address/ternary.leo @@ -2,7 +2,7 @@ function main(s: bool, c: address) { const a = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; const b = aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r; - const r = s? a: b; + let r = s ? a: b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/boolean/not_mutable.leo b/compiler/tests/boolean/not_mutable.leo index c621647ff9..92588434e4 100644 --- a/compiler/tests/boolean/not_mutable.leo +++ b/compiler/tests/boolean/not_mutable.leo @@ -1,4 +1,4 @@ function main () { - let b = false; + const b = false; const a = !b; } \ No newline at end of file diff --git a/compiler/tests/circuits/pedersen_mock.leo b/compiler/tests/circuits/pedersen_mock.leo index 0fc6752f2f..7f2dc12180 100644 --- a/compiler/tests/circuits/pedersen_mock.leo +++ b/compiler/tests/circuits/pedersen_mock.leo @@ -1,14 +1,14 @@ circuit PedersenHash { parameters: [u32; 512] - function new(parameters: [u32; 512]) -> Self { + function new(const parameters: [u32; 512]) -> Self { return Self { parameters: parameters }; } - function hash(self, bits: [bool; 512]) -> u32 { + function hash(self, const bits: [bool; 512]) -> u32 { let digest: u32 = 0; for i in 0..512 { - const base = bits[i] ? self.parameters[i] : 0u32; + let base = bits[i] ? self.parameters[i] : 0u32; digest += base; } return digest; diff --git a/compiler/tests/core/packages/unstable/blake2s/blake2s_random.leo b/compiler/tests/core/packages/unstable/blake2s/blake2s_random.leo index c9592fcbf8..72aef44932 100644 --- a/compiler/tests/core/packages/unstable/blake2s/blake2s_random.leo +++ b/compiler/tests/core/packages/unstable/blake2s/blake2s_random.leo @@ -1,7 +1,7 @@ import core.unstable.blake2s.Blake2s; function main(seed: [u8; 32], message: [u8; 32], expected: [u8; 32]) { - const actual = Blake2s::hash(seed, message); + let actual = Blake2s::hash(seed, message); console.assert(expected == actual); } diff --git a/compiler/tests/integers/i128/ternary.leo b/compiler/tests/integers/i128/ternary.leo index 3783463b22..a923c428e6 100644 --- a/compiler/tests/integers/i128/ternary.leo +++ b/compiler/tests/integers/i128/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i128, b: i128, c: i128) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/ternary.leo b/compiler/tests/integers/i16/ternary.leo index d66c73cb93..4586b87bb4 100644 --- a/compiler/tests/integers/i16/ternary.leo +++ b/compiler/tests/integers/i16/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i16, b: i16, c: i16) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/ternary.leo b/compiler/tests/integers/i32/ternary.leo index 790769d62f..7927c2998b 100644 --- a/compiler/tests/integers/i32/ternary.leo +++ b/compiler/tests/integers/i32/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i32, b: i32, c: i32) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/ternary.leo b/compiler/tests/integers/i64/ternary.leo index df63b3ad6a..1a2d03a77f 100644 --- a/compiler/tests/integers/i64/ternary.leo +++ b/compiler/tests/integers/i64/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i64, b: i64, c: i64) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/ternary.leo b/compiler/tests/integers/i8/ternary.leo index 0956a9cd39..e1ec1943c9 100644 --- a/compiler/tests/integers/i8/ternary.leo +++ b/compiler/tests/integers/i8/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: i8, b: i8, c: i8) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/ternary.leo b/compiler/tests/integers/u128/ternary.leo index 99a6b997e0..22e2e67058 100644 --- a/compiler/tests/integers/u128/ternary.leo +++ b/compiler/tests/integers/u128/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u128, b: u128, c: u128) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/ternary.leo b/compiler/tests/integers/u16/ternary.leo index d6131f9f4f..11d836570d 100644 --- a/compiler/tests/integers/u16/ternary.leo +++ b/compiler/tests/integers/u16/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u16, b: u16, c: u16) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/ternary.leo b/compiler/tests/integers/u32/ternary.leo index f32ffc29fe..3c96a7236c 100644 --- a/compiler/tests/integers/u32/ternary.leo +++ b/compiler/tests/integers/u32/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u32, b: u32, c: u32) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/ternary.leo b/compiler/tests/integers/u64/ternary.leo index 4427cd0466..4c4ddd8e0c 100644 --- a/compiler/tests/integers/u64/ternary.leo +++ b/compiler/tests/integers/u64/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u64, b: u64, c: u64) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/ternary.leo b/compiler/tests/integers/u8/ternary.leo index 5123a511cd..1b436aa054 100644 --- a/compiler/tests/integers/u8/ternary.leo +++ b/compiler/tests/integers/u8/ternary.leo @@ -1,5 +1,5 @@ function main(s: bool, a: u8, b: u8, c: u8) { - const r = s ? a : b; + let r = s ? a : b; console.assert(r == c); } \ No newline at end of file diff --git a/compiler/tests/mutability/let_mut_nested.leo b/compiler/tests/mutability/let_mut_nested.leo index 93236ef4c6..ace4bfb8b4 100644 --- a/compiler/tests/mutability/let_mut_nested.leo +++ b/compiler/tests/mutability/let_mut_nested.leo @@ -1,5 +1,5 @@ function main () { let x = 2u8; let y = x; - const z = y / 2u8; + let z = y / 2u8; } \ No newline at end of file diff --git a/compiler/tests/mutability/swap.leo b/compiler/tests/mutability/swap.leo index d0d663ea1a..05fb661085 100644 --- a/compiler/tests/mutability/swap.leo +++ b/compiler/tests/mutability/swap.leo @@ -1,6 +1,6 @@ // Swap two elements of an array. function swap(a: [u32; 2], const i: u32, const j: u32) -> [u32; 2] { - const t = a[i]; + let t = a[i]; a[i] = a[j]; a[j] = t; return a; @@ -11,7 +11,7 @@ function main() { const expected: [u32; 2] = [1, 0]; // Do swap. - const actual = swap(arr, 0, 1); + let actual = swap(arr, 0, 1); // Check result. for i in 0..2 { diff --git a/compiler/tests/statements/conditional/for_loop.leo b/compiler/tests/statements/conditional/for_loop.leo index db307f3c36..79df649236 100644 --- a/compiler/tests/statements/conditional/for_loop.leo +++ b/compiler/tests/statements/conditional/for_loop.leo @@ -7,7 +7,7 @@ function main(a: bool) { } } - const r: u32 = a ? 6 : 0; + let r: u32 = a ? 6 : 0; console.assert(r == b); } diff --git a/compiler/tests/statements/mod.rs b/compiler/tests/statements/mod.rs index d9be9023c3..847df96083 100644 --- a/compiler/tests/statements/mod.rs +++ b/compiler/tests/statements/mod.rs @@ -47,6 +47,14 @@ fn test_ternary_basic() { assert_satisfied(program); } +#[test] +fn test_ternary_non_const_conditional_fail() { + let program_string = include_str!("ternary_non_const_conditional_fail.leo"); + let error = parse_program(program_string).err().unwrap(); + + expect_asg_error(error); +} + // Iteration for i {start}..{stop} { statements } #[test] diff --git a/compiler/tests/statements/ternary_basic.leo b/compiler/tests/statements/ternary_basic.leo index 38359004a9..675b681fa9 100644 --- a/compiler/tests/statements/ternary_basic.leo +++ b/compiler/tests/statements/ternary_basic.leo @@ -1,5 +1,5 @@ function main(a: bool, b: bool) { - const c = a ? true : false; + let c = a ? true : false; - const d = c == b; + let d = c == b; } \ No newline at end of file diff --git a/compiler/tests/statements/ternary_non_const_conditional_fail.leo b/compiler/tests/statements/ternary_non_const_conditional_fail.leo new file mode 100644 index 0000000000..a46fc84a7b --- /dev/null +++ b/compiler/tests/statements/ternary_non_const_conditional_fail.leo @@ -0,0 +1,4 @@ +function main() { + let x = 3u8; + const y = x > 2u8? 1u8 : 2u8; +} \ No newline at end of file From e7f88a9849944ecf17414bebbd0ecedfed5682ff Mon Sep 17 00:00:00 2001 From: Eric McCarthy Date: Tue, 4 May 2021 12:10:07 -0700 Subject: [PATCH 2/3] add mention of Javascript and Rust --- docs/rfc/001-initial-strings.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/rfc/001-initial-strings.md b/docs/rfc/001-initial-strings.md index abd0a3ad1d..874615154e 100644 --- a/docs/rfc/001-initial-strings.md +++ b/docs/rfc/001-initial-strings.md @@ -84,15 +84,16 @@ We allow other backslash escapes for commonly used characters that are not otherwise easily denoted, namely _[TODO: Decide which other escapes we want to allow, e.g. `'\n'`.]_ We also allow Unicode escapes of the form `'\u{X}'`, -where `X` is a sequence of one or more hex digits +where `X` is a sequence of one to six hex digits (both uppercase and lowercase letters are allowed) -whose value must be between 0 and 10FFFFh. +whose value must be between 0 and 10FFFF, inclusive. Note that the literal character is assembled by the compiler---for creating literals there is no need for the circuit to know which codepoints are disallowed. _[TODO: Do we want a different notation for Unicode escapes? Note that the `{` `}` delimiters are motivated by the fact that there may be a varying number of hex digits in this notation.]_ +This notation is supported by both Javascript and Rust. _[TODO: Which (initial) built-in or library operations do we want to provide for `char` values?]_ From 2818d1404fc365ec17daf0adc07d48799a07ea5e Mon Sep 17 00:00:00 2001 From: gluax Date: Wed, 5 May 2021 14:11:19 -0400 Subject: [PATCH 3/3] some todos --- docs/rfc/001-initial-strings.md | 70 ++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/docs/rfc/001-initial-strings.md b/docs/rfc/001-initial-strings.md index abd0a3ad1d..27e1e0d55b 100644 --- a/docs/rfc/001-initial-strings.md +++ b/docs/rfc/001-initial-strings.md @@ -21,7 +21,7 @@ DRAFT The purpose of this proposal is to provide initial support for strings in Leo. Since strings are sequences of characters, the proposal inextricably also involves characters. -This proposal is described as 'initial' +This proposal is described as 'initial,' because it provides some basic features that we may extend in the future; the initial features should be sufficiently simple and conservative that they should not limit the design of the future features. @@ -61,7 +61,7 @@ with a discussion of possible future extensions. ## Characters -We add a new scalar type `char` for characters. +We add a new scalar type, `char` for characters. In accord with Leo's strong typing, this new type is separate from all the other scalar types. @@ -76,19 +76,26 @@ there is no notion of Unicode encoding (e.g. UTF-8) that applies here. We add a new kind of literals for characters, consisting of single characters or escapes, surrounded by single quotes. -Any single Unicode character except single quote is allowed, +Any single Unicode character except a single quote is allowed, e.g. `'a'`, `'*'`, and `'"'`. -Single quotes must be escaped with backslash, i.e. `'\''`; +Single quotes must be escaped with a backslash, i.e. `'\''`; backslashes must be escaped as well, i.e. `'\\'` We allow other backslash escapes for commonly used characters that are not otherwise easily denoted, namely _[TODO: Decide which other escapes we want to allow, e.g. `'\n'`.]_ +* `\n` +* `\r` +* `\t` +* `\0` +* `\'` +* `\"` + We also allow Unicode escapes of the form `'\u{X}'`, where `X` is a sequence of one or more hex digits (both uppercase and lowercase letters are allowed) whose value must be between 0 and 10FFFFh. Note that the literal character is assembled by the compiler---for -creating literals there is no need for the circuit to know +creating literals, there is no need for the circuit to know which codepoints are disallowed. _[TODO: Do we want a different notation for Unicode escapes? Note that the `{` `}` delimiters are motivated by the fact that @@ -96,11 +103,20 @@ there may be a varying number of hex digits in this notation.]_ _[TODO: Which (initial) built-in or library operations do we want to provide for `char` values?]_ +- [ ] is_alphabetic - Returns `true` if the `char` has the `Alphabetic` property. +- [ ] is_ascii - Returns `true` if the `char` is in the `ASCII` range. +- [ ] is_ascii_alphabetic - Returns `true` if the `char` is in the `ASCII Alphabetic` range. +- [ ] is_lowercase - Returns `true` if the `char` has the `Lowercase` property. +- [ ] is_numeric - Returns `true` if the `char` has one of the general categories for numbers. +- [ ] is_uppercase - Returns `true` if the `char` has the `Uppercase` property. +- [ ] is_whitespace - Returns `true` if the `char` has the `White_Space` property. +- [ ] to_digit - Converts the `char` to the given `radix` format. + ## Strings In this initial design proposal, we do not introduce any new type for strings. -Instead, we rely on the fact that Leo already has arrays, +Instead, we rely on the fact that Leo already has arrays and that arrays of characters can be regarded as strings. Existing array operations, such as element and range access, apply to these strings without the need of language extensions. @@ -112,7 +128,7 @@ surrounded by double quotes; this is just syntactic sugar. Any single Unicode character except double quote is allowed, e.g. `""`, `"Aleo"`, `"it's"`, and `"x + y"`. -Double quotes must be escaped with backslash, e.g. `"say \"hi\""`; +Double quotes must be escaped with a backslash, e.g. `"say \"hi\""`; backslashes must be escaped as well, e.g. `"c:\\dir"`. We allow the same backslash escapes allowed for character literals (see the section on characters above). @@ -120,9 +136,9 @@ _[TODO: There is a difference in the treatment of single and double quotes: the former are allowed in string literals but not character literals, while the latter are allowed in character literals but not string literals; this asymmetry is also present in Java. -However, for simplicity we may want to symmetrically disallow +However, for simplicity, we may want to symmetrically disallow both single and double quotes in both character and string literals.]_ -We also allow the same Unicode escapes allowed in character literals, +We also allow the same Unicode escapes allowed in character literals (described in the section on characters above). In any case, the type of a string literal is `[char; N]`, where `N` is the length of the string measured in characters, @@ -131,7 +147,7 @@ Note that there is no notion of Unicode encoding (e.g. UTF-8) that applies to string literals. The rationale for not introducing a new type for strings initially, -and instead piggyback on the existing array types and operations, +and instead, piggyback on the existing array types and operations, is twofold. First, it is an economical design that lets us reuse the existing array machinery, @@ -141,21 +157,27 @@ and at the R1CS compilation level Second, it leaves the door open to providing, in a future design iteration, a richer type for strings, -as disccused in the section about future extensions below. +as discussed in the section about future extensions below. _[TODO: Which (initial) built-in or library operations do we want to provide for `[char; N]` values that are not already available with the existing array operations?]_ -* `u8` to `[char; 2]` hexstring, .., `u128` to `[char; 32]` hexstring -* field element to `[char; 64]` hexstring. (Application can test leading zeros and slice them out if it needs to return, say, a 40-hex-digit string) -* _[TODO: more?]_ +- [ ] `u8` to `[char; 2]` hexstring, .., `u128` to `[char; 32]` hexstring +- [ ] field element to `[char; 64]` hexstring. (Application can test leading zeros and slice them out if it needs to return, say, a 40-hex-digit string) +- [ ] len - Returns the length of the `string`. +- [ ] is_empty - Returns `true` if the `string` is empty. +- [ ] pop - Pops a `char` to the `string`. +- [ ] push - Pushes a `char` to the `string`. +- [ ] append - Appends a `string` to the `string`. +- [ ] clear - Empties the `string`. +- [ ] _[TODO: more?]_ ## Input and Output of Literal Characters and Strings Since UTF-8 is a standard encoding, it would make sense for the literal characters and strings in the `.in` file to be automatically converted to UTF-32 by the Leo compiler. -However, the size of a string can be confusing, since multiple +However, the size of a string can be confusing since multiple Unicode code points can be composed into a single glyph which then appears to be a single character. If a parameter of type `[char; 10]` [if that is the syntax we decide on] is passed a literal string @@ -169,16 +191,16 @@ usable exclusively as first arguments of console print calls. This proposal eliminates this very specific notion, which is subsumed by the string literals described above. In other words, a console print call -will simply take a string literal as first argument, +will take a string literal as the first argument, which will be interpreted as a format string according to the semantics of console print calls. The internal UTF-32 string will be translated to UTF-8 for output. ## Compilation to R1CS -So far the discussion has been independent from R1CS +So far, the discussion has been independent from R1CS (except for a brief reference when discussing the rationale behind the design). -This is intentional, because the syntax and semantics of Leo +This is intentional because the syntax and semantics of Leo should be understandable independently from the compilation of Leo to R1CS. However, compilation to R1CS is a critical consideration that affects the design of Leo. @@ -206,10 +228,10 @@ suitable array inline construction expressions. ## Future Extensions As alluded to in the section about design above, -for now we are avoiding the introduction of a string type, +for now, we are avoiding the introduction of a string type, isomorphic to but separate from character arrays, because we may want to introduce later a more flexible type of strings, -in particular one that supports resizing. +in particular, one that supports resizing. This may be realized via a built-in or library circuit type that includes a character array and a fill index. This may be a special case of a built-in or library circuit type @@ -240,7 +262,7 @@ to/from common formats, e.g. UTF-8. # Alternatives We could avoid the new `char` type altogether, -and instead rely on the existing `u32` to represent Unicode code points, +and instead, rely on the existing `u32` to represent Unicode code points, and provide character-oriented operations on `u32` values. (Note that both `u8` and `u16` are too small for 10FFFFh, and that signed integer types include negative integers @@ -254,7 +276,7 @@ All in all, introducing a new type for characters is consistent with Leo's strong typing approach. Furthermore, for compilation to R1CS, `u32`, even if restricted to the number of bits needed for Unicode code points, -is less efficient than the field representation described earlier, +is less efficient than the field representation described earlier because `u32` requires a field element for each bit. Instead of representing strings as character arrays, @@ -264,9 +286,9 @@ These strings would be isomorphic to, but distinct form, character arrays. However, for compilation to R1CS, it would be necessary to perform the same kind of known-size analysis on strings that is already performed on arrays, -possibly necessitating to include a size as part of the type, i.e. `string(N)`, +possibly necessitating to include size as part of the type, i.e. `string(N)`, which is obviously isomorphic to `[char; N]`. -Thus, using character arrays avoids the duplication. +Thus, using character arrays avoids duplication. Furthermore, as noted in the section on future extensions, this leaves the door open to introducing a future type `string` for resizable strings.