mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-29 20:44:52 +03:00
Merge and resolve conflict on generated README.md.
(Since the file is generated, I've simply re-generated it to resolve the conflict.)
This commit is contained in:
commit
ccbf36e6ec
@ -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!(),
|
||||
}
|
||||
|
@ -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<Scope<'a>>),
|
||||
Statement(Statement<'a>),
|
||||
Variable(Variable<'a>),
|
||||
Circuit(Circuit<'a>),
|
||||
|
@ -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<String, &'a Function<'a>>,
|
||||
|
||||
/// Maps global constant name => global const code block.
|
||||
pub global_consts: IndexMap<String, &'a DefinitionStatement<'a>>,
|
||||
|
||||
/// Maps circuit name => circuit code block.
|
||||
pub circuits: IndexMap<String, &'a Circuit<'a>>,
|
||||
|
||||
/// 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<String, &'a Function<'a>> = IndexMap::new();
|
||||
let mut imported_circuits: IndexMap<String, &'a Circuit<'a>> = IndexMap::new();
|
||||
let mut imported_global_consts: IndexMap<String, &'a DefinitionStatement<'a>> = 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<String, &'a Circuit<'a>> = IndexMap::new();
|
||||
let mut all_functions: IndexMap<String, &'a Function<'a>> = IndexMap::new();
|
||||
let mut all_global_consts: IndexMap<String, &'a DefinitionStatement<'a>> = 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<leo_ast::Program> 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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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<IndexMap<String, &'a Function<'a>>>,
|
||||
|
||||
/// Maps global constant name => global const code block.
|
||||
pub global_consts: RefCell<IndexMap<String, &'a DefinitionStatement<'a>>>,
|
||||
|
||||
/// Maps circuit name => circuit.
|
||||
pub circuits: RefCell<IndexMap<String, &'a Circuit<'a>>>,
|
||||
|
||||
@ -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),
|
||||
})
|
||||
|
@ -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()
|
||||
|
@ -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<FunctionInput>,
|
||||
pub imports: Vec<ImportStatement>,
|
||||
pub circuits: IndexMap<Identifier, Circuit>,
|
||||
pub global_consts: IndexMap<String, DefinitionStatement>,
|
||||
pub functions: IndexMap<Identifier, Function>,
|
||||
}
|
||||
|
||||
@ -66,6 +67,7 @@ impl Program {
|
||||
expected_input: vec![],
|
||||
imports: vec![],
|
||||
circuits: IndexMap::new(),
|
||||
global_consts: IndexMap::new(),
|
||||
functions: IndexMap::new(),
|
||||
}
|
||||
}
|
||||
|
@ -450,8 +450,13 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
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(
|
||||
|
@ -398,6 +398,7 @@ pub trait ReconstructingReducer {
|
||||
imports: Vec<ImportStatement>,
|
||||
circuits: IndexMap<Identifier, Circuit>,
|
||||
functions: IndexMap<Identifier, Function>,
|
||||
global_consts: IndexMap<String, DefinitionStatement>,
|
||||
) -> Result<Program, ReducerError> {
|
||||
Ok(Program {
|
||||
name: program.name.clone(),
|
||||
@ -405,6 +406,7 @@ pub trait ReconstructingReducer {
|
||||
imports,
|
||||
circuits,
|
||||
functions,
|
||||
global_consts,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,10 @@ pub fn generate_constraints<'a, F: PrimeField, G: GroupType<F>, CS: ConstraintSy
|
||||
) -> Result<OutputBytes, CompilerError> {
|
||||
let mut resolved_program = ConstrainedProgram::<F, G>::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()
|
||||
|
@ -24,7 +24,6 @@ use snarkvm_fields::PrimeField;
|
||||
impl<'a, F: PrimeField, G: GroupType<F>> 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);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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 {}
|
||||
|
@ -26,6 +26,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||
pub fn evaluate_ref(&mut self, variable_ref: &VariableRef) -> Result<ConstrainedValue<'a, F, G>, 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 {
|
||||
|
@ -705,12 +705,19 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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": [],
|
||||
|
@ -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": [],
|
||||
|
@ -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 {\\\"}\"}",
|
||||
|
46
compiler/tests/global_consts/global_const_types.leo
Normal file
46
compiler/tests/global_consts/global_const_types.leo
Normal file
@ -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);
|
||||
}
|
36
compiler/tests/global_consts/mod.rs
Normal file
36
compiler/tests/global_consts/mod.rs
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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());
|
||||
}
|
6
compiler/tests/global_consts/modify_global_const.leo
Normal file
6
compiler/tests/global_consts/modify_global_const.leo
Normal file
@ -0,0 +1,6 @@
|
||||
const basic: u32 = 8;
|
||||
|
||||
function main() {
|
||||
// Cannot re-assign!
|
||||
basic = 2u32;
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import test-import.foo as bar;
|
||||
import bar.baz.ONE as UNO;
|
||||
|
||||
function main() {
|
||||
console.assert(bar() == 1u32);
|
||||
}
|
||||
console.assert(UNO == 1u8);
|
||||
}
|
||||
|
@ -4,4 +4,6 @@ circuit Baz {
|
||||
|
||||
circuit Bazzar {
|
||||
a: u32
|
||||
}
|
||||
}
|
||||
|
||||
const ONE: u8 = 1;
|
@ -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);
|
||||
}
|
@ -16,4 +16,5 @@ function main() {
|
||||
const car = Car { c: 1u32 };
|
||||
|
||||
console.assert(car.c == 1u32);
|
||||
console.assert(ONE == 1u8);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,8 @@ function two() -> u8 {
|
||||
return 2u8;
|
||||
}
|
||||
|
||||
const ONE = 1u8;
|
||||
|
||||
function main() {
|
||||
const a = 1u8;
|
||||
const b = 1field;
|
||||
|
@ -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": [],
|
||||
|
@ -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)_;
|
||||
|
||||
|
||||
<a name="block-comment"></a>
|
||||
@ -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)_;
|
||||
|
||||
|
||||
<a name="end-of-line-comment"></a>
|
||||
@ -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)_;
|
||||
|
||||
|
||||
<a name="array-dimensions"></a>
|
||||
@ -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)_;
|
||||
|
||||
|
||||
<a name="circuit-inline-element"></a>
|
||||
@ -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)_;
|
||||
|
||||
|
||||
<a name="circuit-expression"></a>
|
||||
@ -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)_;
|
||||
|
||||
|
||||
<a name="block"></a>
|
||||
@ -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.
|
||||
|
||||
<a name="variable-definition-statement"></a>
|
||||
<a name="variable-declaration"></a>
|
||||
```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)_;
|
||||
|
||||
|
||||
|
||||
<a name="identifier-or-identifiers"></a>
|
||||
```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)_;
|
||||
|
||||
|
||||
<a name="function-parameters"></a>
|
||||
@ -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)_;
|
||||
|
||||
|
||||
<a name="file"></a>
|
||||
|
@ -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
|
||||
|
||||
|
17
leo/main.rs
17
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");
|
||||
|
@ -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::<Vec<String>>()
|
||||
.join(",");
|
||||
|
||||
Ok((variable_names, statement))
|
||||
}
|
||||
}
|
||||
|
@ -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": [],
|
||||
|
Loading…
Reference in New Issue
Block a user