diff --git a/asg/src/context.rs b/asg/src/context.rs index 643ea6f803..ea26be19e8 100644 --- a/asg/src/context.rs +++ b/asg/src/context.rs @@ -68,7 +68,7 @@ impl<'a> AsgContextInner<'a> { #[allow(clippy::mut_from_ref)] pub fn alloc_scope(&'a self, scope: Scope<'a>) -> &'a Scope<'a> { - match self.arena.alloc(ArenaNode::Scope(scope)) { + match self.arena.alloc(ArenaNode::Scope(Box::new(scope))) { ArenaNode::Scope(e) => e, _ => unimplemented!(), } diff --git a/asg/src/node.rs b/asg/src/node.rs index 58b4b7709e..4272c5669a 100644 --- a/asg/src/node.rs +++ b/asg/src/node.rs @@ -44,7 +44,7 @@ pub(super) trait FromAst<'a, T: leo_ast::Node + 'static>: Sized { pub enum ArenaNode<'a> { Expression(Expression<'a>), - Scope(Scope<'a>), + Scope(Box>), Statement(Statement<'a>), Variable(Variable<'a>), Circuit(Circuit<'a>), diff --git a/asg/src/program/mod.rs b/asg/src/program/mod.rs index 868b46e8b3..ebeb75eb7c 100644 --- a/asg/src/program/mod.rs +++ b/asg/src/program/mod.rs @@ -24,7 +24,17 @@ pub use circuit::*; mod function; pub use function::*; -use crate::{ArenaNode, AsgContext, AsgConvertError, ImportResolver, Input, Scope}; +use crate::{ + node::FromAst, + ArenaNode, + AsgContext, + AsgConvertError, + DefinitionStatement, + ImportResolver, + Input, + Scope, + Statement, +}; use leo_ast::{Identifier, PackageAccess, PackageOrPackages, Span}; use indexmap::IndexMap; @@ -48,10 +58,12 @@ pub struct Program<'a> { /// Maps function name => function code block. pub functions: IndexMap>, + /// Maps global constant name => global const code block. + pub global_consts: IndexMap>, + /// Maps circuit name => circuit code block. pub circuits: IndexMap>, - /// Bindings for names and additional program context. pub scope: &'a Scope<'a>, } @@ -168,6 +180,7 @@ impl<'a> Program<'a> { let mut imported_functions: IndexMap> = IndexMap::new(); let mut imported_circuits: IndexMap> = IndexMap::new(); + let mut imported_global_consts: IndexMap> = IndexMap::new(); // Prepare locally relevant scope of imports. for (package, symbol, span) in imported_symbols.into_iter() { @@ -180,12 +193,15 @@ impl<'a> Program<'a> { ImportSymbol::All => { imported_functions.extend(resolved_package.functions.clone().into_iter()); imported_circuits.extend(resolved_package.circuits.clone().into_iter()); + imported_global_consts.extend(resolved_package.global_consts.clone().into_iter()); } ImportSymbol::Direct(name) => { if let Some(function) = resolved_package.functions.get(&name) { imported_functions.insert(name.clone(), *function); } else if let Some(circuit) = resolved_package.circuits.get(&name) { imported_circuits.insert(name.clone(), *circuit); + } else if let Some(global_const) = resolved_package.global_consts.get(&name) { + imported_global_consts.insert(name.clone(), *global_const); } else { return Err(AsgConvertError::unresolved_import( &*format!("{}.{}", pretty_package, name), @@ -198,6 +214,8 @@ impl<'a> Program<'a> { imported_functions.insert(alias.clone(), *function); } else if let Some(circuit) = resolved_package.circuits.get(&name) { imported_circuits.insert(alias.clone(), *circuit); + } else if let Some(global_const) = resolved_package.global_consts.get(&name) { + imported_global_consts.insert(alias.clone(), *global_const); } else { return Err(AsgConvertError::unresolved_import( &*format!("{}.{}", pretty_package, name), @@ -208,17 +226,18 @@ impl<'a> Program<'a> { } } - let import_scope = match context.arena.alloc(ArenaNode::Scope(Scope { + let import_scope = match context.arena.alloc(ArenaNode::Scope(Box::new(Scope { context, id: context.get_id(), parent_scope: Cell::new(None), circuit_self: Cell::new(None), variables: RefCell::new(IndexMap::new()), functions: RefCell::new(imported_functions), + global_consts: RefCell::new(imported_global_consts), circuits: RefCell::new(imported_circuits), function: Cell::new(None), input: Cell::new(None), - })) { + }))) { ArenaNode::Scope(c) => c, _ => unimplemented!(), }; @@ -231,6 +250,7 @@ impl<'a> Program<'a> { circuit_self: Cell::new(None), variables: RefCell::new(IndexMap::new()), functions: RefCell::new(IndexMap::new()), + global_consts: RefCell::new(IndexMap::new()), circuits: RefCell::new(IndexMap::new()), function: Cell::new(None), }); @@ -258,7 +278,29 @@ impl<'a> Program<'a> { scope.functions.borrow_mut().insert(name.name.to_string(), function); } + for (name, global_const) in program.global_consts.iter() { + global_const + .variable_names + .iter() + .for_each(|variable_name| assert!(name.contains(&variable_name.identifier.name.to_string()))); + let gc = <&Statement<'a>>::from_ast(scope, global_const, None)?; + if let Statement::Definition(gc) = gc { + scope.global_consts.borrow_mut().insert(name.clone(), gc); + } + } + // Load concrete definitions. + let mut global_consts = IndexMap::new(); + for (name, global_const) in program.global_consts.iter() { + global_const + .variable_names + .iter() + .for_each(|variable_name| assert!(name.contains(&variable_name.identifier.name.to_string()))); + let asg_global_const = *scope.global_consts.borrow().get(name).unwrap(); + + global_consts.insert(name.clone(), asg_global_const); + } + let mut functions = IndexMap::new(); for (name, function) in program.functions.iter() { assert_eq!(name.name, function.identifier.name); @@ -290,6 +332,7 @@ impl<'a> Program<'a> { id: context.get_id(), name: program.name.clone(), functions, + global_consts, circuits, imported_modules: resolved_packages .into_iter() @@ -340,6 +383,7 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program { let mut all_circuits: IndexMap> = IndexMap::new(); let mut all_functions: IndexMap> = IndexMap::new(); + let mut all_global_consts: IndexMap> = IndexMap::new(); let mut identifiers = InternalIdentifierGenerator { next: 0 }; for (_, program) in all_programs.into_iter() { for (name, circuit) in program.circuits.iter() { @@ -356,6 +400,11 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program { function.name.borrow_mut().name = identifier.clone().into(); all_functions.insert(identifier, *function); } + + for (name, global_const) in program.global_consts.iter() { + let identifier = format!("{}{}", identifiers.next().unwrap(), name); + all_global_consts.insert(identifier, *global_const); + } } leo_ast::Program { @@ -380,6 +429,20 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program { .into_iter() .map(|(_, circuit)| (circuit.name.borrow().clone(), circuit.into())) .collect(), + global_consts: all_global_consts + .into_iter() + .map(|(_, global_const)| { + ( + global_const + .variables + .iter() + .fold("".to_string(), |joined, variable_name| { + format!("{}, {}", joined, variable_name.borrow().name.name) + }), + global_const.into(), + ) + }) + .collect(), } } @@ -399,6 +462,21 @@ impl<'a> Into for &Program<'a> { .iter() .map(|(_, function)| (function.name.borrow().clone(), (*function).into())) .collect(), + global_consts: self + .global_consts + .iter() + .map(|(_, global_const)| { + ( + global_const + .variables + .iter() + .fold("".to_string(), |joined, variable_name| { + format!("{}, {}", joined, variable_name.borrow().name.name) + }), + (*global_const).into(), + ) + }) + .collect(), } } } diff --git a/asg/src/reducer/reconstructing_director.rs b/asg/src/reducer/reconstructing_director.rs index 239f1943c9..080eb1c5db 100644 --- a/asg/src/reducer/reconstructing_director.rs +++ b/asg/src/reducer/reconstructing_director.rs @@ -322,6 +322,12 @@ impl<'a, R: ReconstructingReducerProgram<'a>> ReconstructingDirector<'a, R> { self.reducer.reduce_circuit(input, members) } + pub fn reduce_global_const(&mut self, input: &'a DefinitionStatement<'a>) -> &'a DefinitionStatement<'a> { + let value = self.reduce_expression(input.value.get()); + + self.reducer.reduce_global_const(input, value) + } + pub fn reduce_program(&mut self, input: Program<'a>) -> Program<'a> { let imported_modules = input .imported_modules @@ -339,7 +345,13 @@ impl<'a, R: ReconstructingReducerProgram<'a>> ReconstructingDirector<'a, R> { .map(|(name, c)| (name.clone(), self.reduce_circuit(c))) .collect(); + let global_consts = input + .global_consts + .iter() + .map(|(name, gc)| (name.clone(), self.reduce_global_const(gc))) + .collect(); + self.reducer - .reduce_program(input, imported_modules, functions, circuits) + .reduce_program(input, imported_modules, functions, circuits, global_consts) } } diff --git a/asg/src/reducer/reconstructing_reducer.rs b/asg/src/reducer/reconstructing_reducer.rs index 1441c13a1d..f42a707bc8 100644 --- a/asg/src/reducer/reconstructing_reducer.rs +++ b/asg/src/reducer/reconstructing_reducer.rs @@ -383,12 +383,22 @@ pub trait ReconstructingReducerProgram<'a>: ReconstructingReducerStatement<'a> { input } + fn reduce_global_const( + &mut self, + input: &'a DefinitionStatement<'a>, + value: &'a Expression<'a>, + ) -> &'a DefinitionStatement<'a> { + input.value.set(value); + input + } + fn reduce_program( &mut self, input: Program<'a>, imported_modules: Vec<(String, Program<'a>)>, functions: Vec<(String, &'a Function<'a>)>, circuits: Vec<(String, &'a Circuit<'a>)>, + global_consts: Vec<(String, &'a DefinitionStatement<'a>)>, ) -> Program<'a> { Program { context: input.context, @@ -398,6 +408,7 @@ pub trait ReconstructingReducerProgram<'a>: ReconstructingReducerStatement<'a> { functions: functions.into_iter().collect(), circuits: circuits.into_iter().collect(), scope: input.scope, + global_consts: global_consts.into_iter().collect(), } } } diff --git a/asg/src/reducer/visitor.rs b/asg/src/reducer/visitor.rs index 8a87cf4700..0bd16527bd 100644 --- a/asg/src/reducer/visitor.rs +++ b/asg/src/reducer/visitor.rs @@ -159,6 +159,10 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> { Default::default() } + fn visit_global_const(&mut self, input: &'a DefinitionStatement<'a>) -> VisitResult { + Default::default() + } + fn visit_program(&mut self, input: &Program<'a>) -> VisitResult { Default::default() } diff --git a/asg/src/reducer/visitor_director.rs b/asg/src/reducer/visitor_director.rs index 78cfdd5d94..ee117dffb8 100644 --- a/asg/src/reducer/visitor_director.rs +++ b/asg/src/reducer/visitor_director.rs @@ -424,6 +424,16 @@ impl<'a, R: ProgramVisitor<'a>> VisitorDirector<'a, R> { } } + pub fn visit_global_const(&mut self, input: &'a DefinitionStatement<'a>) -> ConcreteVisitResult { + match self.visitor.visit_global_const(input) { + VisitResult::VisitChildren => { + self.visit_expression(&input.value)?; + Ok(()) + } + x => x.into(), + } + } + pub fn visit_program(&mut self, input: &Program<'a>) -> ConcreteVisitResult { match self.visitor.visit_program(input) { VisitResult::VisitChildren => { @@ -436,6 +446,9 @@ impl<'a, R: ProgramVisitor<'a>> VisitorDirector<'a, R> { for (_, circuit) in input.circuits.iter() { self.visit_circuit(circuit)?; } + for (_, global_const) in input.global_consts.iter() { + self.visit_global_const(global_const)?; + } Ok(()) } x => x.into(), diff --git a/asg/src/scope.rs b/asg/src/scope.rs index fac0d8813c..1c4bcb98ca 100644 --- a/asg/src/scope.rs +++ b/asg/src/scope.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{AsgContext, AsgConvertError, Circuit, Function, Input, Type, Variable}; +use crate::{AsgContext, AsgConvertError, Circuit, DefinitionStatement, Function, Input, Type, Variable}; use indexmap::IndexMap; use std::cell::{Cell, RefCell}; @@ -42,6 +42,9 @@ pub struct Scope<'a> { /// Maps function name => function. pub functions: RefCell>>, + /// Maps global constant name => global const code block. + pub global_consts: RefCell>>, + /// Maps circuit name => circuit. pub circuits: RefCell>>, @@ -161,6 +164,7 @@ impl<'a> Scope<'a> { variables: RefCell::new(IndexMap::new()), functions: RefCell::new(IndexMap::new()), circuits: RefCell::new(IndexMap::new()), + global_consts: RefCell::new(IndexMap::new()), function: Cell::new(None), input: Cell::new(None), }) diff --git a/asg/src/statement/definition.rs b/asg/src/statement/definition.rs index 1502f53244..4d2339a0f7 100644 --- a/asg/src/statement/definition.rs +++ b/asg/src/statement/definition.rs @@ -39,6 +39,22 @@ pub struct DefinitionStatement<'a> { pub value: Cell<&'a Expression<'a>>, } +impl<'a> DefinitionStatement<'a> { + pub fn split(&self) -> Vec<(String, Self)> { + self.variables + .iter() + .map(|variable| { + (variable.borrow().name.name.to_string(), DefinitionStatement { + parent: self.parent.clone(), + span: self.span.clone(), + variables: vec![variable], + value: self.value.clone(), + }) + }) + .collect() + } +} + impl<'a> Node for DefinitionStatement<'a> { fn span(&self) -> Option<&Span> { self.span.as_ref() diff --git a/ast/src/program.rs b/ast/src/program.rs index 41602aac30..23d2d1cbb4 100644 --- a/ast/src/program.rs +++ b/ast/src/program.rs @@ -17,7 +17,7 @@ //! A Leo program consists of import, circuit, and function definitions. //! Each defined type consists of ast statements and expressions. -use crate::{Circuit, Function, FunctionInput, Identifier, ImportStatement}; +use crate::{Circuit, DefinitionStatement, Function, FunctionInput, Identifier, ImportStatement}; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; @@ -30,6 +30,7 @@ pub struct Program { pub expected_input: Vec, pub imports: Vec, pub circuits: IndexMap, + pub global_consts: IndexMap, pub functions: IndexMap, } @@ -66,6 +67,7 @@ impl Program { expected_input: vec![], imports: vec![], circuits: IndexMap::new(), + global_consts: IndexMap::new(), functions: IndexMap::new(), } } diff --git a/ast/src/reducer/reconstructing_director.rs b/ast/src/reducer/reconstructing_director.rs index d3a71e8e56..942eaec3aa 100644 --- a/ast/src/reducer/reconstructing_director.rs +++ b/ast/src/reducer/reconstructing_director.rs @@ -450,8 +450,13 @@ impl ReconstructingDirector { functions.insert(self.reduce_identifier(identifier)?, self.reduce_function(function)?); } + let mut global_consts = IndexMap::new(); + for (name, definition) in program.global_consts.iter() { + global_consts.insert(name.clone(), self.reduce_definition(&definition)?); + } + self.reducer - .reduce_program(program, inputs, imports, circuits, functions) + .reduce_program(program, inputs, imports, circuits, functions, global_consts) } pub fn reduce_function_input_variable( diff --git a/ast/src/reducer/reconstructing_reducer.rs b/ast/src/reducer/reconstructing_reducer.rs index 637bad2869..36c8972728 100644 --- a/ast/src/reducer/reconstructing_reducer.rs +++ b/ast/src/reducer/reconstructing_reducer.rs @@ -398,6 +398,7 @@ pub trait ReconstructingReducer { imports: Vec, circuits: IndexMap, functions: IndexMap, + global_consts: IndexMap, ) -> Result { Ok(Program { name: program.name.clone(), @@ -405,6 +406,7 @@ pub trait ReconstructingReducer { imports, circuits, functions, + global_consts, }) } diff --git a/compiler/src/constraints/constraints.rs b/compiler/src/constraints/constraints.rs index 47649cf5e1..1f444abda2 100644 --- a/compiler/src/constraints/constraints.rs +++ b/compiler/src/constraints/constraints.rs @@ -33,6 +33,10 @@ pub fn generate_constraints<'a, F: PrimeField, G: GroupType, CS: ConstraintSy ) -> Result { let mut resolved_program = ConstrainedProgram::::new(program.clone()); + for (_, global_const) in program.global_consts.iter() { + resolved_program.enforce_definition_statement(cs, global_const)?; + } + let main = { let program = program; program.functions.get("main").cloned() diff --git a/compiler/src/definition/definition.rs b/compiler/src/definition/definition.rs index 5c36b80388..06bff35fd9 100644 --- a/compiler/src/definition/definition.rs +++ b/compiler/src/definition/definition.rs @@ -24,7 +24,6 @@ use snarkvm_fields::PrimeField; impl<'a, F: PrimeField, G: GroupType> ConstrainedProgram<'a, F, G> { pub fn store_definition(&mut self, variable: &Variable, value: ConstrainedValue<'a, F, G>) { let variable = variable.borrow(); - self.store(variable.id, value); } } diff --git a/compiler/src/errors/compiler.rs b/compiler/src/errors/compiler.rs index f0da27c838..a96bf22897 100644 --- a/compiler/src/errors/compiler.rs +++ b/compiler/src/errors/compiler.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::errors::FunctionError; +use crate::errors::{ExpressionError, FunctionError, ImportError, StatementError}; use leo_asg::{AsgConvertError, FormattedError}; use leo_ast::{LeoError, ReducerError}; use leo_input::InputParserError; @@ -31,6 +31,12 @@ pub enum CompilerError { #[error("{}", _0)] AsgPassError(FormattedError), + #[error("{}", _0)] + ExpressionError(#[from] ExpressionError), + + #[error("{}", _0)] + ImportError(#[from] ImportError), + #[error("{}", _0)] InputParserError(#[from] InputParserError), @@ -57,6 +63,9 @@ pub enum CompilerError { #[error("{}", _0)] ReducerError(#[from] ReducerError), + + #[error("{}", _0)] + StatementError(#[from] StatementError), } impl LeoError for CompilerError {} diff --git a/compiler/src/expression/variable_ref/variable_ref.rs b/compiler/src/expression/variable_ref/variable_ref.rs index d2bef6e489..abc07ddf82 100644 --- a/compiler/src/expression/variable_ref/variable_ref.rs +++ b/compiler/src/expression/variable_ref/variable_ref.rs @@ -26,6 +26,7 @@ impl<'a, F: PrimeField, G: GroupType> ConstrainedProgram<'a, F, G> { pub fn evaluate_ref(&mut self, variable_ref: &VariableRef) -> Result, ExpressionError> { // Evaluate the identifier name in the current function scope let variable = variable_ref.variable.borrow(); + let result_value = if let Some(value) = self.get(variable.id) { value.clone() } else { diff --git a/compiler/src/phases/reducing_director.rs b/compiler/src/phases/reducing_director.rs index a654bec9a7..93889b2a73 100644 --- a/compiler/src/phases/reducing_director.rs +++ b/compiler/src/phases/reducing_director.rs @@ -705,12 +705,19 @@ impl CombineAstAsgDirector { functions.insert(ast_ident.clone(), self.reduce_function(ast_function, asg_function)?); } + let mut global_consts = IndexMap::new(); + for ((ast_str, ast_definition), (_asg_str, asg_definition)) in ast.global_consts.iter().zip(&asg.global_consts) + { + global_consts.insert(ast_str.clone(), self.reduce_definition(ast_definition, asg_definition)?); + } + self.ast_reducer.reduce_program( ast, ast.expected_input.clone(), ast.imports.clone(), circuits, functions, + global_consts, ) } diff --git a/compiler/tests/canonicalization/array_expansion.json b/compiler/tests/canonicalization/array_expansion.json index 70371dfaca..4b4f324e0d 100644 --- a/compiler/tests/canonicalization/array_expansion.json +++ b/compiler/tests/canonicalization/array_expansion.json @@ -3,6 +3,7 @@ "expected_input": [], "imports": [], "circuits": {}, + "global_consts": {}, "functions": { "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(a: [group; (2, 1)]) {\\\"}\"}": { "annotations": [], diff --git a/compiler/tests/canonicalization/big_self_in_circuit_replacement.json b/compiler/tests/canonicalization/big_self_in_circuit_replacement.json index a411b9fc05..ac4384991a 100644 --- a/compiler/tests/canonicalization/big_self_in_circuit_replacement.json +++ b/compiler/tests/canonicalization/big_self_in_circuit_replacement.json @@ -126,6 +126,7 @@ ] } }, + "global_consts": {}, "functions": { "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": { "annotations": [], diff --git a/compiler/tests/canonicalization/compound_assignment.json b/compiler/tests/canonicalization/compound_assignment.json index 1a4b5285c6..49ba0bdf78 100644 --- a/compiler/tests/canonicalization/compound_assignment.json +++ b/compiler/tests/canonicalization/compound_assignment.json @@ -2,6 +2,7 @@ "name": "", "expected_input": [], "imports": [], + "global_consts": {}, "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 {\\\"}\"}", diff --git a/compiler/tests/global_consts/global_const_types.leo b/compiler/tests/global_consts/global_const_types.leo new file mode 100644 index 0000000000..8819e55662 --- /dev/null +++ b/compiler/tests/global_consts/global_const_types.leo @@ -0,0 +1,46 @@ +const basic: u32 = 8; +const array: [u8; (3, 2)] = [[0u8; 2]; 3]; +const tuple = (1u32, 2u32); +const (a, b) = (1u32, 2u32); +const simple_group: group = 1group; +const complex_group = (_, 1)group; +const field_test: field = 2; +const use_another_const = basic + 1; +const foo = Foo { width: 10, height: 20 }; +const uno = uno(); + +circuit Foo { + width: u32, + height: u32, +} + +function uno() -> u32 { + return 1u32 +} + +function main() { + // basic test + console.assert(basic == 8u32); + // array test + console.assert(array[0][0] == 0); + console.assert(array[2][1] == 0); + // tuple test + let (x, y) = (1u32, 2u32); + console.assert(x == 1u32); + console.assert(y == 2u32); + // tuple extraction test + console.assert(a == 1u32); + console.assert(b == 2u32); + // group test + console.assert(simple_group == 1group); + console.assert(complex_group == (_, 1)group); + // field test + console.assert(field_test == 2field); + // use another const test + console.assert(use_another_const == 9u32); + // circuit test + console.assert(foo.width == 10u32); + console.assert(foo.height == 20u32); + // function test + console.assert(uno == 1u32); +} \ No newline at end of file diff --git a/compiler/tests/global_consts/mod.rs b/compiler/tests/global_consts/mod.rs new file mode 100644 index 0000000000..dd143bdabe --- /dev/null +++ b/compiler/tests/global_consts/mod.rs @@ -0,0 +1,36 @@ +// 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, expect_compiler_error, parse_program}; + + +#[test] +fn test_global_consts() { + let program_string = include_str!("global_consts.leo"); + + let program = parse_program(program_string).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_modify_global_const() { + let program_string = include_str!("modify_global_const.leo"); + + let program = parse_program(program_string).unwrap(); + + assert!(parse_program(program_string).is_err()); +} \ No newline at end of file diff --git a/compiler/tests/global_consts/modify_global_const.leo b/compiler/tests/global_consts/modify_global_const.leo new file mode 100644 index 0000000000..762baad00a --- /dev/null +++ b/compiler/tests/global_consts/modify_global_const.leo @@ -0,0 +1,6 @@ +const basic: u32 = 8; + +function main() { + // Cannot re-assign! + basic = 2u32; +} \ No newline at end of file diff --git a/compiler/tests/import/alias.leo b/compiler/tests/import/alias.leo index f153b5a128..72b5157a2e 100644 --- a/compiler/tests/import/alias.leo +++ b/compiler/tests/import/alias.leo @@ -1,5 +1,7 @@ import test-import.foo as bar; +import bar.baz.ONE as UNO; function main() { console.assert(bar() == 1u32); -} \ No newline at end of file + console.assert(UNO == 1u8); +} diff --git a/compiler/tests/import/imports/bar/src/baz.leo b/compiler/tests/import/imports/bar/src/baz.leo index 1bb268a84c..25fee7f3e5 100755 --- a/compiler/tests/import/imports/bar/src/baz.leo +++ b/compiler/tests/import/imports/bar/src/baz.leo @@ -4,4 +4,6 @@ circuit Baz { circuit Bazzar { a: u32 -} \ No newline at end of file +} + +const ONE: u8 = 1; \ No newline at end of file diff --git a/compiler/tests/import/many_import.leo b/compiler/tests/import/many_import.leo index 08ae494c4f..06fd7051df 100644 --- a/compiler/tests/import/many_import.leo +++ b/compiler/tests/import/many_import.leo @@ -5,7 +5,7 @@ import test-import.( // local import import bar.( // imports directory import Bar, - baz.(Baz, Bazzar), + baz.(Baz, Bazzar, ONE), bat.bat.Bat, ); @@ -23,4 +23,5 @@ function main() { const car = Car { c: 1u32 }; console.assert(car.c == 1u32); + console.assert(ONE == 1u8); } \ No newline at end of file diff --git a/compiler/tests/import/many_import_star.leo b/compiler/tests/import/many_import_star.leo index 575487a929..5e20fc31aa 100644 --- a/compiler/tests/import/many_import_star.leo +++ b/compiler/tests/import/many_import_star.leo @@ -16,4 +16,5 @@ function main() { const car = Car { c: 1u32 }; console.assert(car.c == 1u32); + console.assert(ONE == 1u8); } \ No newline at end of file diff --git a/compiler/tests/type_inference/basic.json b/compiler/tests/type_inference/basic.json index 6f588d2f3c..3b89375e2a 100644 --- a/compiler/tests/type_inference/basic.json +++ b/compiler/tests/type_inference/basic.json @@ -1,962 +1,1008 @@ { - "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": [ + "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": [] + } + }, + "global_consts": { + "ONE": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"ONE\",\"span\":\"{\\\"line_start\\\":7,\\\"line_stop\\\":7,\\\"col_start\\\":7,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"const ONE = 1u8;\\\"}\"}", + "span": { + "line_start": 7, + "line_stop": 7, + "col_start": 7, + "col_stop": 10, + "path": "", + "content": "const ONE = 1u8;" + } + } + ], + "type_": { + "IntegerType": "U8" + }, + "value": { + "Value": { + "Integer": [ + "U8", + "1", { - "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" + "line_start": 7, + "line_stop": 7, + "col_start": 13, + "col_stop": 16, + "path": "", + "content": "const ONE = 1u8;" + } + ] + } + }, + "span": { + "line_start": 7, + "line_stop": 7, + "col_start": 1, + "col_stop": 16, + "path": "", + "content": "const ONE = 1u8;" + } + } + }, + "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_start": 22, "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, + "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\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": { + "annotations": [], + "identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"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\\\":10,\\\"line_stop\\\":10,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const a = 1u8;\\\"}\"}", + "span": { + "line_start": 10, + "line_stop": 10, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const a = 1u8;" + } + } + ], + "type_": { + "IntegerType": "U8" + }, + "value": { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 10, + "line_stop": 10, + "col_start": 13, + "col_stop": 16, "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;" + ] } + }, + "span": { + "line_start": 10, + "line_stop": 10, + "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, + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"b\",\"span\":\"{\\\"line_start\\\":11,\\\"line_stop\\\":11,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const b = 1field;\\\"}\"}", + "span": { + "line_start": 11, + "line_stop": 11, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const b = 1field;" + } + } + ], + "type_": "Field", + "value": { + "Value": { + "Field": [ + "1", + { + "line_start": 11, + "line_stop": 11, + "col_start": 13, + "col_stop": 19, "path": "", "content": " const b = 1field;" } + ] + } + }, + "span": { + "line_start": 11, + "line_stop": 11, + "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\\\":12,\\\"line_stop\\\":12,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const c = 1group;\\\"}\"}", + "span": { + "line_start": 12, + "line_stop": 12, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const c = 1group;" } - ], - "type_": "Field", - "value": { - "Value": { - "Field": [ + } + ], + "type_": "Group", + "value": { + "Value": { + "Group": { + "Single": [ "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, + "col_stop": 19, "path": "", - "content": " const e = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);" + "content": " const c = 1group;" } ] } - }, - "span": { - "line_start": 12, - "line_stop": 12, - "col_start": 3, - "col_stop": 85, - "path": "", - "content": " const e = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);" } + }, + "span": { + "line_start": 12, + "line_stop": 12, + "col_start": 3, + "col_stop": 19, + "path": "", + "content": " const c = 1group;" } - }, - { - "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();" - } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"d\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const d = (0, 1)group;\\\"}\"}", + "span": { + "line_start": 13, + "line_stop": 13, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const d = (0, 1)group;" } - ], - "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" - }, - [ + ], + "type_": "Group", + "value": { + "Value": { + "Group": { + "Tuple": { + "x": { + "Number": [ + "0", { - "value": "2" + "line_start": 13, + "line_stop": 13, + "col_start": 14, + "col_stop": 15, + "path": "", + "content": " const d = (0, 1)group;" } ] - ] - }, - [ - { - "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": [ + }, + "y": { + "Number": [ + "1", { - "value": "2" + "line_start": 13, + "line_stop": 13, + "col_start": 17, + "col_stop": 18, + "path": "", + "content": " const d = (0, 1)group;" } - ], - "span": { - "line_start": 14, - "line_stop": 14, - "col_start": 13, - "col_stop": 26, - "path": "", - "content": " const g = [0u8; (3, 2)];" - } + ] + }, + "span": { + "line_start": 13, + "line_stop": 13, + "col_start": 14, + "col_stop": 24, + "path": "", + "content": " const d = (0, 1)group;" } - }, - "dimensions": [ - { - "value": "3" - } - ], - "span": { + } + } + } + }, + "span": { + "line_start": 13, + "line_stop": 13, + "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\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const e = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8;\\\"}\"}", + "span": { + "line_start": 14, + "line_stop": 14, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const e = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8;" + } + } + ], + "type_": "Address", + "value": { + "Value": { + "Address": [ + "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8", + { "line_start": 14, "line_stop": 14, "col_start": 13, - "col_stop": 26, + "col_stop": 76, "path": "", - "content": " const g = [0u8; (3, 2)];" + "content": " const e = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8;" } - } - }, - "span": { - "line_start": 14, - "line_stop": 14, - "col_start": 3, - "col_stop": 26, - "path": "", - "content": " const g = [0u8; (3, 2)];" + ] } + }, + "span": { + "line_start": 14, + "line_stop": 14, + "col_start": 3, + "col_stop": 76, + "path": "", + "content": " const e = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8;" } - }, - { - "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];" - } + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"f\",\"span\":\"{\\\"line_start\\\":15,\\\"line_stop\\\":15,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const f = two();\\\"}\"}", + "span": { + "line_start": 15, + "line_stop": 15, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const f = two();" } - ], - "type_": { - "Array": [ - { - "Array": [ + } + ], + "type_": { + "IntegerType": "U8" + }, + "value": { + "Call": { + "function": { + "Identifier": "{\"name\":\"two\",\"span\":\"{\\\"line_start\\\":15,\\\"line_stop\\\":15,\\\"col_start\\\":13,\\\"col_stop\\\":16,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const f = two();\\\"}\"}" + }, + "arguments": [], + "span": { + "line_start": 15, + "line_stop": 15, + "col_start": 13, + "col_stop": 18, + "path": "", + "content": " const f = two();" + } + } + }, + "span": { + "line_start": 15, + "line_stop": 15, + "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\\\":16,\\\"line_stop\\\":16,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const g = [0u8; (3, 2)];\\\"}\"}", + "span": { + "line_start": 16, + "line_stop": 16, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const g = [0u8; (3, 2)];" + } + } + ], + "type_": { + "Array": [ + { + "Array": [ + { + "IntegerType": "U8" + }, + [ { - "IntegerType": "U8" - }, - [ - { - "value": "3" - } - ] + "value": "2" + } ] - }, - [ - { - "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];" + "value": "3" } + ] + ] + }, + "value": { + "ArrayInit": { + "element": { + "ArrayInit": { + "element": { + "Value": { + "Integer": [ + "U8", + "0", + { + "line_start": 16, + "line_stop": 16, + "col_start": 14, + "col_stop": 17, + "path": "", + "content": " const g = [0u8; (3, 2)];" + } + ] + } + }, + "dimensions": [ + { + "value": "2" + } + ], + "span": { + "line_start": 16, + "line_stop": 16, + "col_start": 13, + "col_stop": 26, + "path": "", + "content": " const g = [0u8; (3, 2)];" + } + } + }, + "dimensions": [ + { + "value": "3" + } + ], + "span": { + "line_start": 16, + "line_stop": 16, + "col_start": 13, + "col_stop": 26, + "path": "", + "content": " const g = [0u8; (3, 2)];" } - }, - "span": { - "line_start": 16, - "line_stop": 16, - "col_start": 3, - "col_stop": 28, - "path": "", - "content": " const i = [1u8, 1u8, 1u8];" } + }, + "span": { + "line_start": 16, + "line_stop": 16, + "col_start": 3, + "col_stop": 26, + "path": "", + "content": " const g = [0u8; (3, 2)];" } - }, - { - "Definition": { - "declaration_type": "Const", - "variable_names": [ + } + }, + { + "Definition": { + "declaration_type": "Const", + "variable_names": [ + { + "mutable": false, + "identifier": "{\"name\":\"h\",\"span\":\"{\\\"line_start\\\":17,\\\"line_stop\\\":17,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const h = [[0u8; 3]; 2];\\\"}\"}", + "span": { + "line_start": 17, + "line_stop": 17, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + } + ], + "type_": { + "Array": [ { - "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, + "Array": [ + { + "IntegerType": "U8" + }, + [ + { + "value": "3" + } + ] + ] + }, + [ + { + "value": "2" + } + ] + ] + }, + "value": { + "ArrayInit": { + "element": { + "ArrayInit": { + "element": { + "Value": { + "Integer": [ + "U8", + "0", + { + "line_start": 17, + "line_stop": 17, + "col_start": 15, + "col_stop": 18, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + ] + } + }, + "dimensions": [ + { + "value": "3" + } + ], + "span": { + "line_start": 17, + "line_stop": 17, + "col_start": 14, + "col_stop": 22, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + } + }, + "dimensions": [ + { + "value": "2" + } + ], + "span": { + "line_start": 17, + "line_stop": 17, + "col_start": 13, + "col_stop": 26, + "path": "", + "content": " const h = [[0u8; 3]; 2];" + } + } + }, + "span": { + "line_start": 17, + "line_stop": 17, + "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\\\":18,\\\"line_stop\\\":18,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const i = [1u8, 1u8, 1u8];\\\"}\"}", + "span": { + "line_start": 18, + "line_stop": 18, + "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": 18, + "line_stop": 18, + "col_start": 14, + "col_stop": 17, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + ] + } + } + }, + { + "Expression": { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 18, + "line_stop": 18, + "col_start": 19, + "col_stop": 22, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + ] + } + } + }, + { + "Expression": { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 18, + "line_stop": 18, + "col_start": 24, + "col_stop": 27, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + ] + } + } + } + ], + "span": { + "line_start": 18, + "line_stop": 18, + "col_start": 13, + "col_stop": 28, + "path": "", + "content": " const i = [1u8, 1u8, 1u8];" + } + } + }, + "span": { + "line_start": 18, + "line_stop": 18, + "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\\\":19,\\\"line_stop\\\":19,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const j = true;\\\"}\"}", + "span": { + "line_start": 19, + "line_stop": 19, + "col_start": 9, + "col_stop": 10, + "path": "", + "content": " const j = true;" + } + } + ], + "type_": "Boolean", + "value": { + "Value": { + "Boolean": [ + "true", + { + "line_start": 19, + "line_stop": 19, + "col_start": 13, + "col_stop": 17, "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": 19, + "line_stop": 19, + "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\\\":20,\\\"line_stop\\\":20,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const k = (1u8, 1u8);\\\"}\"}", + "span": { + "line_start": 20, + "line_stop": 20, + "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": 20, + "line_stop": 20, + "col_start": 14, + "col_stop": 17, + "path": "", + "content": " const k = (1u8, 1u8);" + } + ] + } + }, + { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 20, + "line_stop": 20, + "col_start": 19, + "col_stop": 22, + "path": "", + "content": " const k = (1u8, 1u8);" + } + ] + } + } + ], + "span": { + "line_start": 20, + "line_stop": 20, + "col_start": 13, + "col_stop": 23, + "path": "", + "content": " const k = (1u8, 1u8);" + } + } + }, + "span": { + "line_start": 20, + "line_stop": 20, + "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\\\":21,\\\"line_stop\\\":21,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const l = (1u8, 1u8, true);\\\"}\"}", + "span": { + "line_start": 21, + "line_stop": 21, + "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": 21, + "line_stop": 21, + "col_start": 14, + "col_stop": 17, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + ] + } + }, + { + "Value": { + "Integer": [ + "U8", + "1", + { + "line_start": 21, + "line_stop": 21, + "col_start": 19, + "col_stop": 22, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + ] + } + }, + { + "Value": { + "Boolean": [ + "true", + { + "line_start": 21, + "line_stop": 21, + "col_start": 24, + "col_stop": 28, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + ] + } + } + ], + "span": { + "line_start": 21, + "line_stop": 21, + "col_start": 13, + "col_stop": 29, + "path": "", + "content": " const l = (1u8, 1u8, true);" + } + } + }, + "span": { + "line_start": 21, + "line_stop": 21, + "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\\\":22,\\\"line_stop\\\":22,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const m = Foo {};\\\"}\"}", + "span": { + "line_start": 22, + "line_stop": 22, + "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\\\":22,\\\"line_stop\\\":22,\\\"col_start\\\":13,\\\"col_stop\\\":16,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const m = Foo {};\\\"}\"}", + "members": [], + "span": { + "line_start": 22, + "line_stop": 22, + "col_start": 13, + "col_stop": 19, + "path": "", + "content": " const m = Foo {};" + } + } + }, + "span": { + "line_start": 22, + "line_stop": 22, + "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, + "line_start": 9, + "line_stop": 23, + "col_start": 17, "col_stop": 2, "path": "", - "content": "function main() {\n...\n}\n\n\n\n\n\n\n\n\n\n\n\n" + "content": "function main() {\n...\n}" } + }, + "span": { + "line_start": 9, + "line_stop": 23, + "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 index 112d5bb338..af4df0c19f 100644 --- a/compiler/tests/type_inference/basic.leo +++ b/compiler/tests/type_inference/basic.leo @@ -4,6 +4,8 @@ function two() -> u8 { return 2u8; } +const ONE = 1u8; + function main() { const a = 1u8; const b = 1field; diff --git a/compiler/tests/type_inference/for_loop_and_compound.json b/compiler/tests/type_inference/for_loop_and_compound.json index f0079573d1..b8abddd38a 100644 --- a/compiler/tests/type_inference/for_loop_and_compound.json +++ b/compiler/tests/type_inference/for_loop_and_compound.json @@ -3,6 +3,7 @@ "expected_input": [], "imports": [], "circuits": {}, + "global_consts": {}, "functions": { "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": { "annotations": [], diff --git a/grammar/README.md b/grammar/README.md index d89cbb700b..959d593d5f 100644 --- a/grammar/README.md +++ b/grammar/README.md @@ -466,7 +466,7 @@ described above. newline = line-feed / carriage-return / carriage-return line-feed ``` -Go to: _[line-feed](#user-content-line-feed), [carriage-return](#user-content-carriage-return)_; +Go to: _[carriage-return](#user-content-carriage-return), [line-feed](#user-content-line-feed)_; Line terminators form whitespace, along with spaces and horizontal tabs. @@ -476,7 +476,7 @@ Line terminators form whitespace, along with spaces and horizontal tabs. whitespace = space / horizontal-tab / newline ``` -Go to: _[horizontal-tab](#user-content-horizontal-tab), [space](#user-content-space), [newline](#user-content-newline)_; +Go to: _[horizontal-tab](#user-content-horizontal-tab), [newline](#user-content-newline), [space](#user-content-space)_; There are two kinds of comments in Leo, as in other languages. @@ -494,7 +494,7 @@ the ones used in the Java language reference. comment = block-comment / end-of-line-comment ``` -Go to: _[block-comment](#user-content-block-comment), [end-of-line-comment](#user-content-end-of-line-comment)_; +Go to: _[end-of-line-comment](#user-content-end-of-line-comment), [block-comment](#user-content-block-comment)_; @@ -521,7 +521,7 @@ rest-of-block-comment-after-star = "/" / not-star-or-slash rest-of-block-comment ``` -Go to: _[not-star-or-slash](#user-content-not-star-or-slash), [rest-of-block-comment](#user-content-rest-of-block-comment), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star)_; +Go to: _[rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [not-star-or-slash](#user-content-not-star-or-slash), [rest-of-block-comment](#user-content-rest-of-block-comment)_; @@ -764,7 +764,7 @@ atomic-literal = untyped-literal / address-literal ``` -Go to: _[unsigned-literal](#user-content-unsigned-literal), [address-literal](#user-content-address-literal), [field-literal](#user-content-field-literal), [boolean-literal](#user-content-boolean-literal), [untyped-literal](#user-content-untyped-literal), [signed-literal](#user-content-signed-literal), [product-group-literal](#user-content-product-group-literal)_; +Go to: _[signed-literal](#user-content-signed-literal), [untyped-literal](#user-content-untyped-literal), [field-literal](#user-content-field-literal), [product-group-literal](#user-content-product-group-literal), [boolean-literal](#user-content-boolean-literal), [address-literal](#user-content-address-literal), [unsigned-literal](#user-content-unsigned-literal)_; After defining the (mostly) alphanumeric tokens above, @@ -809,7 +809,7 @@ token = keyword / symbol ``` -Go to: _[annotation-name](#user-content-annotation-name), [symbol](#user-content-symbol), [format-string](#user-content-format-string), [identifier](#user-content-identifier), [keyword](#user-content-keyword), [package-name](#user-content-package-name), [atomic-literal](#user-content-atomic-literal)_; +Go to: _[keyword](#user-content-keyword), [atomic-literal](#user-content-atomic-literal), [package-name](#user-content-package-name), [annotation-name](#user-content-annotation-name), [symbol](#user-content-symbol), [format-string](#user-content-format-string), [identifier](#user-content-identifier)_; @@ -845,7 +845,7 @@ signed-type = %s"i8" / %s"i16" / %s"i32" / %s"i64" / %s"i128" integer-type = unsigned-type / signed-type ``` -Go to: _[unsigned-type](#user-content-unsigned-type), [signed-type](#user-content-signed-type)_; +Go to: _[signed-type](#user-content-signed-type), [unsigned-type](#user-content-unsigned-type)_; The integer types, along with the field and group types, @@ -866,7 +866,7 @@ group-type = %s"group" arithmetic-type = integer-type / field-type / group-type ``` -Go to: _[field-type](#user-content-field-type), [integer-type](#user-content-integer-type), [group-type](#user-content-group-type)_; +Go to: _[integer-type](#user-content-integer-type), [field-type](#user-content-field-type), [group-type](#user-content-group-type)_; The arithmetic types, along with the boolean and address types, @@ -887,7 +887,7 @@ address-type = %s"address" scalar-type = boolean-type / arithmetic-type / address-type ``` -Go to: _[arithmetic-type](#user-content-arithmetic-type), [boolean-type](#user-content-boolean-type), [address-type](#user-content-address-type)_; +Go to: _[boolean-type](#user-content-boolean-type), [arithmetic-type](#user-content-arithmetic-type), [address-type](#user-content-address-type)_; Circuit types are denoted by identifiers and the keyword `Self`. @@ -927,7 +927,7 @@ or a tuple of one or more dimensions. array-type = "[" type ";" array-dimensions "]" ``` -Go to: _[type](#user-content-type), [array-dimensions](#user-content-array-dimensions)_; +Go to: _[array-dimensions](#user-content-array-dimensions), [type](#user-content-type)_; @@ -948,7 +948,7 @@ i.e. types whose values contain (sub-)values aggregate-type = tuple-type / array-type / circuit-type ``` -Go to: _[circuit-type](#user-content-circuit-type), [array-type](#user-content-array-type), [tuple-type](#user-content-tuple-type)_; +Go to: _[tuple-type](#user-content-tuple-type), [array-type](#user-content-array-type), [circuit-type](#user-content-circuit-type)_; Scalar and aggregate types form all the types. @@ -994,7 +994,7 @@ A literal is either an atomic one or an affine group literal. literal = atomic-literal / affine-group-literal ``` -Go to: _[atomic-literal](#user-content-atomic-literal), [affine-group-literal](#user-content-affine-group-literal)_; +Go to: _[affine-group-literal](#user-content-affine-group-literal), [atomic-literal](#user-content-atomic-literal)_; The following rule is not directly referenced in the rules for expressions @@ -1036,7 +1036,7 @@ primary-expression = identifier / circuit-expression ``` -Go to: _[tuple-expression](#user-content-tuple-expression), [circuit-expression](#user-content-circuit-expression), [array-expression](#user-content-array-expression), [expression](#user-content-expression), [literal](#user-content-literal), [identifier](#user-content-identifier)_; +Go to: _[expression](#user-content-expression), [tuple-expression](#user-content-tuple-expression), [array-expression](#user-content-array-expression), [literal](#user-content-literal), [circuit-expression](#user-content-circuit-expression), [identifier](#user-content-identifier)_; Tuple expressions construct tuples. @@ -1125,7 +1125,7 @@ circuit-construction = circuit-type "{" "}" ``` -Go to: _[circuit-type](#user-content-circuit-type), [circuit-inline-element](#user-content-circuit-inline-element)_; +Go to: _[circuit-inline-element](#user-content-circuit-inline-element), [circuit-type](#user-content-circuit-type)_; @@ -1133,7 +1133,7 @@ Go to: _[circuit-type](#user-content-circuit-type), [circuit-inline-element](#us circuit-inline-element = identifier ":" expression / identifier ``` -Go to: _[identifier](#user-content-identifier), [expression](#user-content-expression)_; +Go to: _[expression](#user-content-expression), [identifier](#user-content-identifier)_; @@ -1184,7 +1184,7 @@ postfix-expression = primary-expression / postfix-expression "[" [expression] ".." [expression] "]" ``` -Go to: _[function-arguments](#user-content-function-arguments), [identifier](#user-content-identifier), [circuit-type](#user-content-circuit-type), [postfix-expression](#user-content-postfix-expression), [primary-expression](#user-content-primary-expression), [natural](#user-content-natural), [expression](#user-content-expression)_; +Go to: _[expression](#user-content-expression), [primary-expression](#user-content-primary-expression), [identifier](#user-content-identifier), [function-arguments](#user-content-function-arguments), [circuit-type](#user-content-circuit-type), [postfix-expression](#user-content-postfix-expression), [natural](#user-content-natural)_; Unary operators have the highest operator precedence. @@ -1198,7 +1198,7 @@ unary-expression = postfix-expression / "-" unary-expression ``` -Go to: _[postfix-expression](#user-content-postfix-expression), [unary-expression](#user-content-unary-expression)_; +Go to: _[unary-expression](#user-content-unary-expression), [postfix-expression](#user-content-postfix-expression)_; Next in the operator precedence is exponentiation, @@ -1212,7 +1212,7 @@ exponential-expression = unary-expression / unary-expression "**" exponential-expression ``` -Go to: _[exponential-expression](#user-content-exponential-expression), [unary-expression](#user-content-unary-expression)_; +Go to: _[unary-expression](#user-content-unary-expression), [exponential-expression](#user-content-exponential-expression)_; Next in precedence come multiplication and division, both left-associative. @@ -1224,7 +1224,7 @@ multiplicative-expression = exponential-expression / multiplicative-expression "/" exponential-expression ``` -Go to: _[multiplicative-expression](#user-content-multiplicative-expression), [exponential-expression](#user-content-exponential-expression)_; +Go to: _[exponential-expression](#user-content-exponential-expression), [multiplicative-expression](#user-content-multiplicative-expression)_; Then there are addition and subtraction, both left-assocative. @@ -1286,7 +1286,7 @@ disjunctive-expression = conjunctive-expression / disjunctive-expression "||" conjunctive-expression ``` -Go to: _[disjunctive-expression](#user-content-disjunctive-expression), [conjunctive-expression](#user-content-conjunctive-expression)_; +Go to: _[conjunctive-expression](#user-content-conjunctive-expression), [disjunctive-expression](#user-content-disjunctive-expression)_; Finally we have conditional expressions. @@ -1323,7 +1323,8 @@ Blocks are possibly empty sequences of statements surrounded by curly braces. ```abnf statement = expression-statement / return-statement - / variable-definition-statement + / variable-declaration + / constant-declaration / conditional-statement / loop-statement / assignment-statement @@ -1331,7 +1332,7 @@ statement = expression-statement / block ``` -Go to: _[expression-statement](#user-content-expression-statement), [return-statement](#user-content-return-statement), [conditional-statement](#user-content-conditional-statement), [loop-statement](#user-content-loop-statement), [assignment-statement](#user-content-assignment-statement), [variable-definition-statement](#user-content-variable-definition-statement), [console-statement](#user-content-console-statement), [block](#user-content-block)_; +Go to: _[constant-declaration](#user-content-constant-declaration), [variable-declaration](#user-content-variable-declaration), [console-statement](#user-content-console-statement), [block](#user-content-block), [assignment-statement](#user-content-assignment-statement), [return-statement](#user-content-return-statement), [loop-statement](#user-content-loop-statement), [conditional-statement](#user-content-conditional-statement), [expression-statement](#user-content-expression-statement)_; @@ -1366,16 +1367,16 @@ The variables are either a single one or a tuple of two or more; in all cases, there is just one optional type and just one initializing expression. - + ```abnf -variable-definition-statement = ( %s"let" / %s"const" ) - identifier-or-identifiers - [ ":" type ] "=" expression ";" +variable-declaration = %s"let" identifier-or-identifiers [ ":" type ] "=" expression ";" +constant-declaration = %s"const" identifier-or-identifiers [ ":" type ] "=" expression ";" ``` Go to: _[identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type), [expression](#user-content-expression)_; + ```abnf identifier-or-identifiers = identifier @@ -1406,7 +1407,7 @@ conditional-statement = branch / branch %s"else" conditional-statement ``` -Go to: _[branch](#user-content-branch), [block](#user-content-block), [conditional-statement](#user-content-conditional-statement)_; +Go to: _[block](#user-content-block), [branch](#user-content-branch), [conditional-statement](#user-content-conditional-statement)_; A loop statement implicitly defines a loop variable @@ -1418,7 +1419,7 @@ The body is a block. loop-statement = %s"for" identifier %s"in" expression ".." expression block ``` -Go to: _[block](#user-content-block), [identifier](#user-content-identifier), [expression](#user-content-expression)_; +Go to: _[expression](#user-content-expression), [block](#user-content-block), [identifier](#user-content-identifier)_; An assignment statement is straightforward. @@ -1435,7 +1436,7 @@ assignment-operator = "=" / "+=" / "-=" / "*=" / "/=" / "**=" assignment-statement = expression assignment-operator expression ";" ``` -Go to: _[assignment-operator](#user-content-assignment-operator), [expression](#user-content-expression)_; +Go to: _[expression](#user-content-expression), [assignment-operator](#user-content-assignment-operator)_; Console statements start with the `console` keyword, @@ -1521,7 +1522,7 @@ function-declaration = *annotation %s"function" identifier block ``` -Go to: _[type](#user-content-type), [block](#user-content-block), [function-parameters](#user-content-function-parameters), [identifier](#user-content-identifier)_; +Go to: _[block](#user-content-block), [type](#user-content-type), [identifier](#user-content-identifier), [function-parameters](#user-content-function-parameters)_; @@ -1552,7 +1553,7 @@ Go to: _[function-input](#user-content-function-input)_; function-input = [ %s"const" ] identifier ":" type ``` -Go to: _[identifier](#user-content-identifier), [type](#user-content-type)_; +Go to: _[type](#user-content-type), [identifier](#user-content-identifier)_; A circuit member variable declaration consists of an identifier and a type. @@ -1621,7 +1622,7 @@ package-path = "*" / "(" package-path *( "," package-path ) [","] ")" ``` -Go to: _[package-name](#user-content-package-name), [package-path](#user-content-package-path), [identifier](#user-content-identifier)_; +Go to: _[identifier](#user-content-identifier), [package-path](#user-content-package-path), [package-name](#user-content-package-name)_; Finally, we define a file as a sequence of zero or more declarations. @@ -1631,9 +1632,10 @@ Finally, we define a file as a sequence of zero or more declarations. declaration = import-declaration / function-declaration / circuit-declaration + / constant-declaration ``` -Go to: _[function-declaration](#user-content-function-declaration), [import-declaration](#user-content-import-declaration), [circuit-declaration](#user-content-circuit-declaration)_; +Go to: _[function-declaration](#user-content-function-declaration), [import-declaration](#user-content-import-declaration), [circuit-declaration](#user-content-circuit-declaration), [constant-declaration](#user-content-constant-declaration)_; diff --git a/grammar/abnf-grammar.txt b/grammar/abnf-grammar.txt index 847aba2ffa..bf2bbc70bc 100644 --- a/grammar/abnf-grammar.txt +++ b/grammar/abnf-grammar.txt @@ -826,7 +826,8 @@ expression = conditional-expression statement = expression-statement / return-statement - / variable-definition-statement + / variable-declaration + / constant-declaration / conditional-statement / loop-statement / assignment-statement @@ -850,9 +851,9 @@ return-statement = %s"return" expression ";" ; in all cases, there is just one optional type ; and just one initializing expression. -variable-definition-statement = ( %s"let" / %s"const" ) - identifier-or-identifiers - [ ":" type ] "=" expression ";" +variable-declaration = %s"let" identifier-or-identifiers [ ":" type ] "=" expression ";" +constant-declaration = %s"const" identifier-or-identifiers [ ":" type ] "=" expression ";" + identifier-or-identifiers = identifier / "(" identifier 1*( "," identifier ) ")" @@ -972,6 +973,7 @@ package-path = "*" declaration = import-declaration / function-declaration / circuit-declaration + / constant-declaration file = *declaration diff --git a/leo/main.rs b/leo/main.rs index b2af6ba95e..7d92f4f087 100644 --- a/leo/main.rs +++ b/leo/main.rs @@ -358,6 +358,23 @@ mod cli_tests { assert!(run_cmd("leo clean", setup_path).is_ok()); } + #[test] + fn test_import() { + let dir = testdir("test"); + let path = dir.path("test"); + + assert!(run_cmd("leo new import", &Some(path.clone())).is_ok()); + + let import_path = &Some(path.join("import")); + + assert!(run_cmd("leo add no-package/definitely-no", import_path).is_err()); + assert!(run_cmd("leo add justice-league/u8u32", import_path).is_ok()); + assert!(run_cmd("leo remove u8u32", import_path).is_ok()); + assert!(run_cmd("leo add --author justice-league --package u8u32", import_path).is_ok()); + assert!(run_cmd("leo remove u8u32", import_path).is_ok()); + assert!(run_cmd("leo remove u8u32", import_path).is_err()); + } + #[test] fn test_missing_file() { let dir = testdir("test"); diff --git a/parser/src/parser/file.rs b/parser/src/parser/file.rs index ece7ed5825..8dfdfc132a 100644 --- a/parser/src/parser/file.rs +++ b/parser/src/parser/file.rs @@ -28,6 +28,7 @@ impl ParserContext { let mut imports = Vec::new(); let mut circuits = IndexMap::new(); let mut functions = IndexMap::new(); + let mut global_consts = IndexMap::new(); // let mut tests = IndexMap::new(); while self.has_next() { @@ -55,6 +56,10 @@ impl ParserContext { // input_file: None, // }); } + Token::Const => { + let (name, global_const) = self.parse_global_const_declaration()?; + global_consts.insert(name, global_const); + } _ => { return Err(SyntaxError::unexpected( &token.token, @@ -76,6 +81,7 @@ impl ParserContext { imports, circuits, functions, + global_consts, }) } @@ -391,4 +397,20 @@ impl ParserContext { block, })) } + + /// + /// Returns an [`(String, DefinitionStatement)`] AST node if the next tokens represent a global + /// const definition statement and assignment. + /// + pub fn parse_global_const_declaration(&mut self) -> SyntaxResult<(String, DefinitionStatement)> { + let statement = self.parse_definition_statement()?; + let variable_names = statement + .variable_names + .iter() + .map(|variable_name| variable_name.identifier.name.to_string()) + .collect::>() + .join(","); + + Ok((variable_names, statement)) + } } diff --git a/parser/tests/serialization/expected_leo_ast.json b/parser/tests/serialization/expected_leo_ast.json index cb4cff4c8c..b252808c03 100644 --- a/parser/tests/serialization/expected_leo_ast.json +++ b/parser/tests/serialization/expected_leo_ast.json @@ -3,6 +3,7 @@ "expected_input": [], "imports": [], "circuits": {}, + "global_consts": {}, "functions": { "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": { "annotations": [],