From 61e791c67146c264e8d81c44464be7fe96100747 Mon Sep 17 00:00:00 2001 From: gluax Date: Tue, 13 Apr 2021 11:52:01 -0400 Subject: [PATCH] type inference tests --- ast/src/errors/combiner.rs | 12 + ast/src/lib.rs | 2 +- ast/src/reducer/canonicalization.rs | 9 +- compiler/tests/mod.rs | 1 + compiler/tests/type_inference/basic.json | 962 ++++++++++++++++++ compiler/tests/type_inference/basic.leo | 21 + .../type_inference/for_loop_and_compound.json | 242 +++++ .../type_inference/for_loop_and_compound.leo | 7 + compiler/tests/type_inference/mod.rs | 115 +++ 9 files changed, 1366 insertions(+), 5 deletions(-) create mode 100644 compiler/tests/type_inference/basic.json create mode 100644 compiler/tests/type_inference/basic.leo create mode 100644 compiler/tests/type_inference/for_loop_and_compound.json create mode 100644 compiler/tests/type_inference/for_loop_and_compound.leo create mode 100644 compiler/tests/type_inference/mod.rs diff --git a/ast/src/errors/combiner.rs b/ast/src/errors/combiner.rs index 8ad146d1cd..7c8aa72375 100644 --- a/ast/src/errors/combiner.rs +++ b/ast/src/errors/combiner.rs @@ -34,4 +34,16 @@ impl CombinerError { Self::new_from_span(message, span) } + + pub fn illegal_compound_array_access(span: &Span) -> Self { + let message = "Illegal compound assignement with array range".to_string(); + + Self::new_from_span(message, span) + } + + pub fn illegal_compound_operation(span: &Span) -> Self { + let message = "Illegal compound assignment operator =".to_string(); + + Self::new_from_span(message, span) + } } diff --git a/ast/src/lib.rs b/ast/src/lib.rs index 4601a74959..7fab42c3be 100644 --- a/ast/src/lib.rs +++ b/ast/src/lib.rs @@ -71,7 +71,7 @@ pub use node::*; /// These data types form a tree that begins from a [`Program`] type root. /// /// A new [`Ast`] can be created from a [`Grammar`] generated by the pest parser in the `grammar` module. -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Ast { ast: Program, } diff --git a/ast/src/reducer/canonicalization.rs b/ast/src/reducer/canonicalization.rs index 65ccc2ba83..8c27232b47 100644 --- a/ast/src/reducer/canonicalization.rs +++ b/ast/src/reducer/canonicalization.rs @@ -69,7 +69,7 @@ impl Canonicalizer { span: span.clone(), })); } - _ => unimplemented!(), // No reason for someone to compute ArrayRanges. + _ => return Err(ReducerError::from(CombinerError::illegal_compound_array_access(&span))), } } @@ -79,9 +79,10 @@ impl Canonicalizer { pub fn compound_operation_converstion( &mut self, operation: &AssignOperation, + span: &Span, ) -> Result { match operation { - AssignOperation::Assign => unimplemented!(), // Impossible + AssignOperation::Assign => Err(ReducerError::from(CombinerError::illegal_compound_operation(&span))), AssignOperation::Add => Ok(BinaryOperation::Add), AssignOperation::Sub => Ok(BinaryOperation::Sub), AssignOperation::Mul => Ok(BinaryOperation::Mul), @@ -549,7 +550,7 @@ impl ReconstructingReducer for Canonicalizer { &assign.span, )?; let right = Box::new(Expression::Binary(binary_expr)); - let op = self.compound_operation_converstion(&assign.operation)?; + let op = self.compound_operation_converstion(&assign.operation, &assign.span)?; let new_value = Expression::Binary(BinaryExpression { left, @@ -572,7 +573,7 @@ impl ReconstructingReducer for Canonicalizer { &assign.span, )?; let right = Box::new(Expression::Value(value_expr)); - let op = self.compound_operation_converstion(&assign.operation)?; + let op = self.compound_operation_converstion(&assign.operation, &assign.span)?; let new_value = Expression::Binary(BinaryExpression { left, diff --git a/compiler/tests/mod.rs b/compiler/tests/mod.rs index 96069ffe54..3065734e61 100644 --- a/compiler/tests/mod.rs +++ b/compiler/tests/mod.rs @@ -37,6 +37,7 @@ pub mod mutability; pub mod statements; pub mod syntax; pub mod tuples; +pub mod type_inference; use leo_asg::{new_alloc_context, new_context, AsgContext}; use leo_ast::{InputValue, MainInput}; diff --git a/compiler/tests/type_inference/basic.json b/compiler/tests/type_inference/basic.json new file mode 100644 index 0000000000..6f588d2f3c --- /dev/null +++ b/compiler/tests/type_inference/basic.json @@ -0,0 +1,962 @@ +{ + "name": "", + "expected_input": [], + "imports": [], + "circuits": { + "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {}\\\"}\"}": { + "circuit_name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {}\\\"}\"}", + "members": [] + } + }, + "functions": { + "{\"name\":\"two\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":10,\\\"col_stop\\\":13,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function two() -> u8 {\\\"}\"}": { + "annotations": [], + "identifier": "{\"name\":\"two\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":10,\\\"col_stop\\\":13,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function two() -> u8 {\\\"}\"}", + "input": [], + "output": { + "IntegerType": "U8" + }, + "block": { + "statements": [ + { + "Return": { + "expression": { + "Value": { + "Integer": [ + "U8", + "2", + { + "line_start": 4, + "line_stop": 4, + "col_start": 10, + "col_stop": 13, + "path": "", + "content": " return 2u8" + } + ] + } + }, + "span": { + "line_start": 4, + "line_stop": 4, + "col_start": 3, + "col_stop": 13, + "path": "", + "content": " return 2u8" + } + } + } + ], + "span": { + "line_start": 3, + "line_stop": 5, + "col_start": 22, + "col_stop": 2, + "path": "", + "content": "function two() -> u8 {\n...\n}" + } + }, + "span": { + "line_start": 3, + "line_stop": 5, + "col_start": 1, + "col_stop": 2, + "path": "", + "content": "function two() -> u8 {\n...\n}" + } + }, + "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":7,\\\"line_stop\\\":7,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": { + "annotations": [], + "identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":7,\\\"line_stop\\\":7,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}", + "input": [], + "output": { + "Tuple": [] + }, + "block": { + "statements": [ + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"a\",\"span\":\"{\\\"line_start\\\":8,\\\"line_stop\\\":8,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const a = 1u8;\\\"}\"}", + "span": { + "line_start": 8, + "line_stop": 8, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const a = 1u8;" + } + } + ], + "type_": { + "IntegerType": "U8" + }, + "value": { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 8, + "line_stop": 8, + "col_start": 13, + "col_stop": 16, + "path": "", + "content": " const a = 1u8;" + } + ] + } + }, + "span": { + "line_start": 8, + "line_stop": 8, + "col_start": 3, + "col_stop": 16, + "path": "", + "content": " const a = 1u8;" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"b\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const b = 1field;\\\"}\"}", + "span": { + "line_start": 9, + "line_stop": 9, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const b = 1field;" + } + } + ], + "type_": "Field", + "value": { + "Value": { + "Field": [ + "1", + { + "line_start": 9, + "line_stop": 9, + "col_start": 13, + "col_stop": 19, + "path": "", + "content": " const b = 1field;" + } + ] + } + }, + "span": { + "line_start": 9, + "line_stop": 9, + "col_start": 3, + "col_stop": 19, + "path": "", + "content": " const b = 1field;" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"c\",\"span\":\"{\\\"line_start\\\":10,\\\"line_stop\\\":10,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const c = 1group;\\\"}\"}", + "span": { + "line_start": 10, + "line_stop": 10, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const c = 1group;" + } + } + ], + "type_": "Group", + "value": { + "Value": { + "Group": { + "Single": [ + "1", + { + "line_start": 10, + "line_stop": 10, + "col_start": 13, + "col_stop": 19, + "path": "", + "content": " const c = 1group;" + } + ] + } + } + }, + "span": { + "line_start": 10, + "line_stop": 10, + "col_start": 3, + "col_stop": 19, + "path": "", + "content": " const c = 1group;" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"d\",\"span\":\"{\\\"line_start\\\":11,\\\"line_stop\\\":11,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const d = (0, 1)group;\\\"}\"}", + "span": { + "line_start": 11, + "line_stop": 11, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const d = (0, 1)group;" + } + } + ], + "type_": "Group", + "value": { + "Value": { + "Group": { + "Tuple": { + "x": { + "Number": [ + "0", + { + "line_start": 11, + "line_stop": 11, + "col_start": 14, + "col_stop": 15, + "path": "", + "content": " const d = (0, 1)group;" + } + ] + }, + "y": { + "Number": [ + "1", + { + "line_start": 11, + "line_stop": 11, + "col_start": 17, + "col_stop": 18, + "path": "", + "content": " const d = (0, 1)group;" + } + ] + }, + "span": { + "line_start": 11, + "line_stop": 11, + "col_start": 14, + "col_stop": 24, + "path": "", + "content": " const d = (0, 1)group;" + } + } + } + } + }, + "span": { + "line_start": 11, + "line_stop": 11, + "col_start": 3, + "col_stop": 24, + "path": "", + "content": " const d = (0, 1)group;" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"e\",\"span\":\"{\\\"line_start\\\":12,\\\"line_stop\\\":12,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const e = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);\\\"}\"}", + "span": { + "line_start": 12, + "line_stop": 12, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const e = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);" + } + } + ], + "type_": "Address", + "value": { + "Value": { + "Address": [ + "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8", + { + "line_start": 12, + "line_stop": 12, + "col_start": 13, + "col_stop": 85, + "path": "", + "content": " const e = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);" + } + ] + } + }, + "span": { + "line_start": 12, + "line_stop": 12, + "col_start": 3, + "col_stop": 85, + "path": "", + "content": " const e = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"f\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const f = two();\\\"}\"}", + "span": { + "line_start": 13, + "line_stop": 13, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const f = two();" + } + } + ], + "type_": { + "IntegerType": "U8" + }, + "value": { + "Call": { + "function": { + "Identifier": "{\"name\":\"two\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":13,\\\"col_stop\\\":16,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const f = two();\\\"}\"}" + }, + "arguments": [], + "span": { + "line_start": 13, + "line_stop": 13, + "col_start": 13, + "col_stop": 18, + "path": "", + "content": " const f = two();" + } + } + }, + "span": { + "line_start": 13, + "line_stop": 13, + "col_start": 3, + "col_stop": 18, + "path": "", + "content": " const f = two();" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"g\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const g = [0u8; (3, 2)];\\\"}\"}", + "span": { + "line_start": 14, + "line_stop": 14, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const g = [0u8; (3, 2)];" + } + } + ], + "type_": { + "Array": [ + { + "Array": [ + { + "IntegerType": "U8" + }, + [ + { + "value": "2" + } + ] + ] + }, + [ + { + "value": "3" + } + ] + ] + }, + "value": { + "ArrayInit": { + "element": { + "ArrayInit": { + "element": { + "Value": { + "Integer": [ + "U8", + "0", + { + "line_start": 14, + "line_stop": 14, + "col_start": 14, + "col_stop": 17, + "path": "", + "content": " const g = [0u8; (3, 2)];" + } + ] + } + }, + "dimensions": [ + { + "value": "2" + } + ], + "span": { + "line_start": 14, + "line_stop": 14, + "col_start": 13, + "col_stop": 26, + "path": "", + "content": " const g = [0u8; (3, 2)];" + } + } + }, + "dimensions": [ + { + "value": "3" + } + ], + "span": { + "line_start": 14, + "line_stop": 14, + "col_start": 13, + "col_stop": 26, + "path": "", + "content": " const g = [0u8; (3, 2)];" + } + } + }, + "span": { + "line_start": 14, + "line_stop": 14, + "col_start": 3, + "col_stop": 26, + "path": "", + "content": " const g = [0u8; (3, 2)];" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"h\",\"span\":\"{\\\"line_start\\\":15,\\\"line_stop\\\":15,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const h = [[0u8; 3]; 2];\\\"}\"}", + "span": { + "line_start": 15, + "line_stop": 15, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + } + ], + "type_": { + "Array": [ + { + "Array": [ + { + "IntegerType": "U8" + }, + [ + { + "value": "3" + } + ] + ] + }, + [ + { + "value": "2" + } + ] + ] + }, + "value": { + "ArrayInit": { + "element": { + "ArrayInit": { + "element": { + "Value": { + "Integer": [ + "U8", + "0", + { + "line_start": 15, + "line_stop": 15, + "col_start": 15, + "col_stop": 18, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + ] + } + }, + "dimensions": [ + { + "value": "3" + } + ], + "span": { + "line_start": 15, + "line_stop": 15, + "col_start": 14, + "col_stop": 22, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + } + }, + "dimensions": [ + { + "value": "2" + } + ], + "span": { + "line_start": 15, + "line_stop": 15, + "col_start": 13, + "col_stop": 26, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + } + }, + "span": { + "line_start": 15, + "line_stop": 15, + "col_start": 3, + "col_stop": 26, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"i\",\"span\":\"{\\\"line_start\\\":16,\\\"line_stop\\\":16,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const i = [1u8, 1u8, 1u8];\\\"}\"}", + "span": { + "line_start": 16, + "line_stop": 16, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + } + ], + "type_": { + "Array": [ + { + "IntegerType": "U8" + }, + [ + { + "value": "3" + } + ] + ] + }, + "value": { + "ArrayInline": { + "elements": [ + { + "Expression": { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 16, + "line_stop": 16, + "col_start": 14, + "col_stop": 17, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + ] + } + } + }, + { + "Expression": { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 16, + "line_stop": 16, + "col_start": 19, + "col_stop": 22, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + ] + } + } + }, + { + "Expression": { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 16, + "line_stop": 16, + "col_start": 24, + "col_stop": 27, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + ] + } + } + } + ], + "span": { + "line_start": 16, + "line_stop": 16, + "col_start": 13, + "col_stop": 28, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + } + }, + "span": { + "line_start": 16, + "line_stop": 16, + "col_start": 3, + "col_stop": 28, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"j\",\"span\":\"{\\\"line_start\\\":17,\\\"line_stop\\\":17,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const j = true;\\\"}\"}", + "span": { + "line_start": 17, + "line_stop": 17, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const j = true;" + } + } + ], + "type_": "Boolean", + "value": { + "Value": { + "Boolean": [ + "true", + { + "line_start": 17, + "line_stop": 17, + "col_start": 13, + "col_stop": 17, + "path": "", + "content": " const j = true;" + } + ] + } + }, + "span": { + "line_start": 17, + "line_stop": 17, + "col_start": 3, + "col_stop": 17, + "path": "", + "content": " const j = true;" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"k\",\"span\":\"{\\\"line_start\\\":18,\\\"line_stop\\\":18,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const k = (1u8, 1u8);\\\"}\"}", + "span": { + "line_start": 18, + "line_stop": 18, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const k = (1u8, 1u8);" + } + } + ], + "type_": { + "Tuple": [ + { + "IntegerType": "U8" + }, + { + "IntegerType": "U8" + } + ] + }, + "value": { + "TupleInit": { + "elements": [ + { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 18, + "line_stop": 18, + "col_start": 14, + "col_stop": 17, + "path": "", + "content": " const k = (1u8, 1u8);" + } + ] + } + }, + { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 18, + "line_stop": 18, + "col_start": 19, + "col_stop": 22, + "path": "", + "content": " const k = (1u8, 1u8);" + } + ] + } + } + ], + "span": { + "line_start": 18, + "line_stop": 18, + "col_start": 13, + "col_stop": 23, + "path": "", + "content": " const k = (1u8, 1u8);" + } + } + }, + "span": { + "line_start": 18, + "line_stop": 18, + "col_start": 3, + "col_stop": 23, + "path": "", + "content": " const k = (1u8, 1u8);" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"l\",\"span\":\"{\\\"line_start\\\":19,\\\"line_stop\\\":19,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const l = (1u8, 1u8, true);\\\"}\"}", + "span": { + "line_start": 19, + "line_stop": 19, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + } + ], + "type_": { + "Tuple": [ + { + "IntegerType": "U8" + }, + { + "IntegerType": "U8" + }, + "Boolean" + ] + }, + "value": { + "TupleInit": { + "elements": [ + { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 19, + "line_stop": 19, + "col_start": 14, + "col_stop": 17, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + ] + } + }, + { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 19, + "line_stop": 19, + "col_start": 19, + "col_stop": 22, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + ] + } + }, + { + "Value": { + "Boolean": [ + "true", + { + "line_start": 19, + "line_stop": 19, + "col_start": 24, + "col_stop": 28, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + ] + } + } + ], + "span": { + "line_start": 19, + "line_stop": 19, + "col_start": 13, + "col_stop": 29, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + } + }, + "span": { + "line_start": 19, + "line_stop": 19, + "col_start": 3, + "col_stop": 29, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"m\",\"span\":\"{\\\"line_start\\\":20,\\\"line_stop\\\":20,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const m = Foo {};\\\"}\"}", + "span": { + "line_start": 20, + "line_stop": 20, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const m = Foo {};" + } + } + ], + "type_": { + "Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {}\\\"}\"}" + }, + "value": { + "CircuitInit": { + "name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":20,\\\"line_stop\\\":20,\\\"col_start\\\":13,\\\"col_stop\\\":16,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const m = Foo {};\\\"}\"}", + "members": [], + "span": { + "line_start": 20, + "line_stop": 20, + "col_start": 13, + "col_stop": 19, + "path": "", + "content": " const m = Foo {};" + } + } + }, + "span": { + "line_start": 20, + "line_stop": 20, + "col_start": 3, + "col_stop": 19, + "path": "", + "content": " const m = Foo {};" + } + } + } + ], + "span": { + "line_start": 7, + "line_stop": 21, + "col_start": 17, + "col_stop": 2, + "path": "", + "content": "function main() {\n...\n}" + } + }, + "span": { + "line_start": 7, + "line_stop": 21, + "col_start": 1, + "col_stop": 2, + "path": "", + "content": "function main() {\n...\n}\n\n\n\n\n\n\n\n\n\n\n\n" + } + } + } + } \ No newline at end of file diff --git a/compiler/tests/type_inference/basic.leo b/compiler/tests/type_inference/basic.leo new file mode 100644 index 0000000000..c83c7df815 --- /dev/null +++ b/compiler/tests/type_inference/basic.leo @@ -0,0 +1,21 @@ +circuit Foo {} + +function two() -> u8 { + return 2u8 +} + +function main() { + const a = 1u8; + const b = 1field; + const c = 1group; + const d = (0, 1)group; + const e = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8); + const f = two(); + const g = [0u8; (3, 2)]; + const h = [[0u8; 3]; 2]; + const i = [1u8, 1u8, 1u8]; + const j = true; + const k = (1u8, 1u8); + const l = (1u8, 1u8, true); + const m = Foo {}; +} \ No newline at end of file diff --git a/compiler/tests/type_inference/for_loop_and_compound.json b/compiler/tests/type_inference/for_loop_and_compound.json new file mode 100644 index 0000000000..f0079573d1 --- /dev/null +++ b/compiler/tests/type_inference/for_loop_and_compound.json @@ -0,0 +1,242 @@ +{ + "name": "", + "expected_input": [], + "imports": [], + "circuits": {}, + "functions": { + "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": { + "annotations": [], + "identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}", + "input": [], + "output": { + "Tuple": [] + }, + "block": { + "statements": [ + { + "Definition": { + "declaration_type": "Let", + "variable_names": [ + { + "mutable": true, + "identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let x = 10u16;\\\"}\"}", + "span": { + "line_start": 2, + "line_stop": 2, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " let x = 10u16;" + } + } + ], + "type_": { + "IntegerType": "U16" + }, + "value": { + "Value": { + "Integer": [ + "U16", + "10", + { + "line_start": 2, + "line_stop": 2, + "col_start": 13, + "col_stop": 18, + "path": "", + "content": " let x = 10u16;" + } + ] + } + }, + "span": { + "line_start": 2, + "line_stop": 2, + "col_start": 5, + "col_stop": 18, + "path": "", + "content": " let x = 10u16;" + } + } + }, + { + "Iteration": { + "variable": "{\"name\":\"i\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" for i in 0..3 {\\\"}\"}", + "start": { + "Value": { + "Integer": [ + "U32", + "0", + { + "line_start": 3, + "line_stop": 3, + "col_start": 14, + "col_stop": 15, + "path": "", + "content": " for i in 0..3 {" + } + ] + } + }, + "stop": { + "Value": { + "Integer": [ + "U32", + "3", + { + "line_start": 3, + "line_stop": 3, + "col_start": 17, + "col_stop": 18, + "path": "", + "content": " for i in 0..3 {" + } + ] + } + }, + "block": { + "statements": [ + { + "Assign": { + "operation": "Assign", + "assignee": { + "identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x -= 1;\\\"}\"}", + "accesses": [], + "span": { + "line_start": 4, + "line_stop": 4, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " x -= 1;" + } + }, + "value": { + "Binary": { + "left": { + "Identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x -= 1;\\\"}\"}" + }, + "right": { + "Value": { + "Integer": [ + "U16", + "1", + { + "line_start": 4, + "line_stop": 4, + "col_start": 14, + "col_stop": 15, + "path": "", + "content": " x -= 1;" + } + ] + } + }, + "op": "Sub", + "span": { + "line_start": 4, + "line_stop": 4, + "col_start": 9, + "col_stop": 15, + "path": "", + "content": " x -= 1;" + } + } + }, + "span": { + "line_start": 4, + "line_stop": 4, + "col_start": 9, + "col_stop": 15, + "path": "", + "content": " x -= 1;" + } + } + } + ], + "span": { + "line_start": 3, + "line_stop": 5, + "col_start": 19, + "col_stop": 6, + "path": "", + "content": " for i in 0..3 {\n...\n }" + } + }, + "span": { + "line_start": 3, + "line_stop": 5, + "col_start": 5, + "col_stop": 6, + "path": "", + "content": " for i in 0..3 {\n...\n }" + } + } + }, + { + "Console": { + "function": { + "Assert": { + "Binary": { + "left": { + "Identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":20,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" console.assert(x == 7u16);\\\"}\"}" + }, + "right": { + "Value": { + "Integer": [ + "U16", + "7", + { + "line_start": 6, + "line_stop": 6, + "col_start": 25, + "col_stop": 29, + "path": "", + "content": " console.assert(x == 7u16);" + } + ] + } + }, + "op": "Eq", + "span": { + "line_start": 6, + "line_stop": 6, + "col_start": 20, + "col_stop": 29, + "path": "", + "content": " console.assert(x == 7u16);" + } + } + } + }, + "span": { + "line_start": 6, + "line_stop": 6, + "col_start": 5, + "col_stop": 29, + "path": "", + "content": " console.assert(x == 7u16);" + } + } + } + ], + "span": { + "line_start": 1, + "line_stop": 7, + "col_start": 17, + "col_stop": 2, + "path": "", + "content": "function main() {\n...\n}" + } + }, + "span": { + "line_start": 1, + "line_stop": 7, + "col_start": 1, + "col_stop": 2, + "path": "", + "content": "function main() {\n...\n}\n\n\n\n" + } + } + } + } \ No newline at end of file diff --git a/compiler/tests/type_inference/for_loop_and_compound.leo b/compiler/tests/type_inference/for_loop_and_compound.leo new file mode 100644 index 0000000000..92c27ff24b --- /dev/null +++ b/compiler/tests/type_inference/for_loop_and_compound.leo @@ -0,0 +1,7 @@ +function main() { + let x = 10u16; + for i in 0..3 { + x -= 1; + } + console.assert(x == 7u16); +} \ No newline at end of file diff --git a/compiler/tests/type_inference/mod.rs b/compiler/tests/type_inference/mod.rs new file mode 100644 index 0000000000..0e505442c7 --- /dev/null +++ b/compiler/tests/type_inference/mod.rs @@ -0,0 +1,115 @@ +// Copyright (C) 2019-2021 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{assert_satisfied, parse_program}; +#[allow(unused)] +use leo_asg::{new_context, Asg, AsgContext}; +use leo_ast::{Ast, ReconstructingReducer}; +use leo_compiler::{CombineAstAsgDirector, CompilerOptions}; +use leo_imports::ImportParser; +use leo_parser::parser; + +thread_local! { + static THREAD_GLOBAL_CONTEXT: AsgContext<'static> = { + let leaked = Box::leak(Box::new(leo_asg::new_alloc_context())); + leo_asg::new_context(leaked) + } +} + +pub fn thread_leaked_context() -> AsgContext<'static> { + THREAD_GLOBAL_CONTEXT.with(|f| *f) +} + +struct TypeInferenceCombiner { + in_circuit: bool, +} + +impl ReconstructingReducer for TypeInferenceCombiner { + fn in_circuit(&self) -> bool { + self.in_circuit + } + + fn swap_in_circuit(&mut self) { + self.in_circuit = !self.in_circuit; + } +} + +impl Default for TypeInferenceCombiner { + fn default() -> Self { + Self { in_circuit: false } + } +} + +pub fn parse_program_ast(file_string: &str) -> Ast { + const TEST_PROGRAM_PATH: &str = ""; + let test_program_file_path = std::path::PathBuf::from(TEST_PROGRAM_PATH); + + let mut ast = Ast::new( + parser::parse(test_program_file_path.to_str().expect("unwrap fail"), &file_string) + .expect("Failed to parse file."), + ); + ast.canonicalize().expect("Failed to canonicalize program."); + + let program = ast.clone().into_repr(); + let asg = Asg::new(thread_leaked_context(), &program, &mut ImportParser::default()) + .expect("Failed to create ASG from AST"); + + let new_ast = Ast::new( + CombineAstAsgDirector::new(TypeInferenceCombiner::default(), CompilerOptions::default()) + .reduce_program(&ast.clone().into_repr(), &asg.into_repr()) + .expect("Failed to convert ASG to AST"), + ); + + new_ast +} + +#[test] +fn test_basic() { + // Check program is valid. + let program_string = include_str!("basic.leo"); + let program = parse_program(program_string).unwrap(); + assert_satisfied(program); + + // Check we get expected ast. + let ast = parse_program_ast(program_string); + let expected_json = include_str!("basic.json"); + let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json."); + + assert_eq!(expected_ast, ast); +} + +#[test] +fn test_for_loop_and_compound() { + // Check program is valid. + let program_string = include_str!("for_loop_and_compound.leo"); + let program = parse_program(program_string).unwrap(); + assert_satisfied(program); + + // Check we get expected ast. + let ast = parse_program_ast(program_string); + let expected_json = include_str!("for_loop_and_compound.json"); + let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json."); + + assert_eq!(expected_ast, ast); +} + +// #[test] +// fn test_big_self_outside_circuit_fail() { +// // Check program is invalid. +// let program_string = include_str!("big_self_outside_circuit_fail.leo"); +// let program = parse_program(program_string); +// assert!(program.is_err()); +// }