Merge branch 'master' into array-len-function

This commit is contained in:
damirka 2021-09-13 14:26:38 +03:00
commit 4f41f09ef2
150 changed files with 1186 additions and 553 deletions

View File

@ -1,14 +1,5 @@
name: Leo-ACL2
on:
pull_request:
push:
branches:
- master
- staging
- trying
paths-ignore:
- 'docs/**'
- 'documentation/**'
on: workflow_dispatch
env:
RUST_BACKTRACE: 1
@ -55,7 +46,7 @@ jobs:
cd tmp/tgc/$dir; # enter the directory
./../../../acl2/tgc canonicalization initial_ast.json canonicalization_ast.json canonicalization-theorem.lisp > canonicalization_result.out || canonicalization_errors+=("$dir");
# Disabling Type inference for now
# ./../../../acl2/tgc type-inference canonicalization_ast.json type_inferenced_ast.json type-inference-theorem.lisp > type_inference_result.out || type_inference_errors+=("$dir");
./../../../acl2/tgc type-inference canonicalization_ast.json type_inferenced_ast.json type-inference-theorem.lisp > type_inference_result.out || type_inference_errors+=("$dir");
cd ../../..
done;
@ -68,12 +59,12 @@ jobs:
echo $dir;
done;
echo "Attaching logs:"
for dir in ${canonicalization_errors[@]};
do
cat tmp/tgc/$dir/canonicalization_result.out
cat tmp/tgc/$dir/canonicalization-theorem.lisp
done;
#echo "Attaching logs:"
#for dir in ${canonicalization_errors[@]};
#do
# cat tmp/tgc/$dir/canonicalization_result.out
# cat tmp/tgc/$dir/canonicalization-theorem.lisp
#done;
exit 1
fi
@ -86,11 +77,11 @@ jobs:
echo $dir;
done;
echo "Attaching logs:"
for dir in ${type_inference_errors[@]};
do
cat tmp/tgc/$dir/type_inference_result.out
done;
#echo "Attaching logs:"
#for dir in ${type_inference_errors[@]};
#do
# cat tmp/tgc/$dir/type_inference_result.out
#done;
exit 1
fi

16
Cargo.lock generated
View File

@ -76,9 +76,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.43"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf"
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
[[package]]
name = "arrayvec"
@ -88,9 +88,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "assert_cmd"
version = "2.0.0"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54f002ce7d0c5e809ebb02be78fd503aeed4a511fd0fcaff6e6914cbdabbfa33"
checksum = "b800c4403e8105d959595e1f88119e78bc12bc874c4336973658b648a746ba93"
dependencies = [
"bstr",
"doc-comment",
@ -2427,9 +2427,9 @@ dependencies = [
[[package]]
name = "serde_yaml"
version = "0.8.20"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad104641f3c958dab30eb3010e834c2622d1f3f4c530fef1dee20ad9485f3c09"
checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af"
dependencies = [
"dtoa",
"indexmap",
@ -2451,9 +2451,9 @@ dependencies = [
[[package]]
name = "sha2"
version = "0.9.6"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9204c41a1597a8c5af23c82d1c921cb01ec0a4c59e07a9c7306062829a3903f3"
checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa"
dependencies = [
"block-buffer 0.9.0",
"cfg-if 1.0.0",

View File

@ -169,7 +169,7 @@ version = "0.12.1"
version = "0.11.2"
[dev-dependencies.assert_cmd]
version = "2.0.0"
version = "2.0.1"
[dev-dependencies.test_dir]
version = "0.1.0"

View File

@ -74,7 +74,7 @@ impl<'a> FromAst<'a, leo_ast::ArrayInitExpression> for ArrayInitExpression<'a> {
Some(PartialType::Array(item, dims)) => (item.map(|x| *x), dims),
None => (None, None),
Some(type_) => {
return Err(AsgError::unexpected_type(type_, "array", &value.span).into());
return Err(AsgError::unexpected_type("array", type_, &value.span).into());
}
};
let dimensions = value

View File

@ -110,7 +110,7 @@ impl<'a> FromAst<'a, leo_ast::ArrayInlineExpression> for ArrayInlineExpression<'
Some(PartialType::Type(Type::ArrayWithoutSize(item))) => (Some(item.partial()), None),
None => (None, None),
Some(type_) => {
return Err(AsgError::unexpected_type(type_, "array", &value.span).into());
return Err(AsgError::unexpected_type("array", type_, &value.span).into());
}
};

View File

@ -108,7 +108,7 @@ impl<'a> FromAst<'a, leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessEx
Some(PartialType::Array(element, len)) => (Some(PartialType::Array(element, None)), len),
None => (None, None),
Some(x) => {
return Err(AsgError::unexpected_type(x, "array", &value.span).into());
return Err(AsgError::unexpected_type("array", x, &value.span).into());
}
};
let array = <&Expression<'a>>::from_ast(scope, &*value.array, expected_array)?;

View File

@ -123,7 +123,7 @@ impl<'a> FromAst<'a, leo_ast::BinaryExpression> for BinaryExpression<'a> {
BinaryOperationClass::Boolean => match expected_type {
Some(PartialType::Type(Type::Boolean)) | None => None,
Some(x) => {
return Err(AsgError::unexpected_type(x, Type::Boolean, &value.span).into());
return Err(AsgError::unexpected_type(Type::Boolean, x, &value.span).into());
}
},
BinaryOperationClass::Numeric => match expected_type {
@ -131,7 +131,7 @@ impl<'a> FromAst<'a, leo_ast::BinaryExpression> for BinaryExpression<'a> {
Some(x @ PartialType::Type(Type::Field)) => Some(x),
Some(x @ PartialType::Type(Type::Group)) => Some(x),
Some(x) => {
return Err(AsgError::unexpected_type(x, "integer, field, or group", &value.span).into());
return Err(AsgError::unexpected_type("integer, field, or group", x, &value.span).into());
}
None => None,
},
@ -192,14 +192,16 @@ impl<'a> FromAst<'a, leo_ast::BinaryExpression> for BinaryExpression<'a> {
BinaryOperation::And | BinaryOperation::Or => match left_type {
Some(Type::Boolean) | None => (),
Some(x) => {
return Err(AsgError::unexpected_type(x, Type::Boolean, &value.span).into());
return Err(AsgError::unexpected_type(Type::Boolean, x, &value.span).into());
}
},
BinaryOperation::Eq | BinaryOperation::Ne => (), // all types allowed
_ => match left_type {
op => match left_type {
Some(Type::Integer(_)) | None => (),
Some(x) => {
return Err(AsgError::unexpected_type(x, "integer", &value.span).into());
return Err(
AsgError::operator_allowed_only_for_type(op.as_ref(), "integer", x, &value.span).into(),
);
}
},
},

View File

@ -172,7 +172,7 @@ impl<'a> FromAst<'a, leo_ast::CircuitStaticFunctionAccessExpression> for Circuit
};
if let Some(expected_type) = expected_type {
return Err(AsgError::unexpected_type(expected_type, "none", &value.span).into());
return Err(AsgError::unexpected_type("none", expected_type, &value.span).into());
}
if let Some(CircuitMember::Function(_)) = circuit.members.borrow().get(value.name.name.as_ref()) {

View File

@ -90,7 +90,7 @@ impl<'a> FromAst<'a, leo_ast::TupleAccessExpression> for TupleAccessExpression<'
if let Some(Type::Tuple(_items)) = tuple_type {
} else {
return Err(AsgError::unexpected_type(
"a tuple",
"tuple",
tuple_type
.map(|x| x.to_string())
.unwrap_or_else(|| "unknown".to_string()),

View File

@ -95,7 +95,7 @@ impl<'a> FromAst<'a, leo_ast::UnaryExpression> for UnaryExpression<'a> {
UnaryOperation::Not => match expected_type.map(|x| x.full()).flatten() {
Some(Type::Boolean) | None => Some(Type::Boolean),
Some(type_) => {
return Err(AsgError::unexpected_type(type_, Type::Boolean, &value.span).into());
return Err(AsgError::unexpected_type(Type::Boolean, type_, &value.span).into());
}
},
UnaryOperation::Negate => match expected_type.map(|x| x.full()).flatten() {
@ -104,14 +104,14 @@ impl<'a> FromAst<'a, leo_ast::UnaryExpression> for UnaryExpression<'a> {
Some(Type::Field) => Some(Type::Field),
None => None,
Some(type_) => {
return Err(AsgError::unexpected_type(type_, "integer, group, field", &value.span).into());
return Err(AsgError::unexpected_type("integer, group, field", type_, &value.span).into());
}
},
UnaryOperation::BitNot => match expected_type.map(|x| x.full()).flatten() {
Some(type_ @ Type::Integer(_)) => Some(type_),
None => None,
Some(type_) => {
return Err(AsgError::unexpected_type(type_, "integer", &value.span).into());
return Err(AsgError::unexpected_type("integer", type_, &value.span).into());
}
},
};

View File

@ -132,6 +132,11 @@ impl<'a> FromAst<'a, leo_ast::Identifier> for &'a Expression<'a> {
} else {
return Err(AsgError::illegal_input_variable_reference(&value.span).into());
}
} else if let Some(gc) = scope.resolve_global_const(&value.name) {
gc.variables
.iter()
.find(|&&v| v.borrow().name.name == value.name)
.unwrap()
} else {
match scope.resolve_variable(&value.name) {
Some(v) => v,

View File

@ -141,9 +141,13 @@ impl<'a> Function<'a> {
.insert("self".to_string(), self_variable);
}
for (name, argument) in self.arguments.iter() {
/* if self.scope.resolve_alias(name).is_some() {
return Err(AsgError::cannot_shadow_name("function input", name, "alias", &argument.get().borrow().name.span).into());
} */
if self.scope.resolve_global_const(name).is_some() {
return Err(AsgError::function_input_cannot_shadow_global_const(
name,
&argument.get().borrow().name.span,
)
.into());
}
self.scope.variables.borrow_mut().insert(name.clone(), argument.get());
}

View File

@ -130,6 +130,29 @@ fn resolve_import_package_access(
}
}
/// Checks whether a given string is found in any other global namespaces.
/// If it is found it returns an error.
fn check_top_level_namespaces<'a>(
name: &str,
span: &Span,
aliases: &IndexMap<String, &'a Alias<'a>>,
functions: &IndexMap<String, &'a Function<'a>>,
circuits: &IndexMap<String, &'a Circuit<'a>>,
global_consts: &IndexMap<String, &'a DefinitionStatement<'a>>,
) -> Result<()> {
if aliases.contains_key(name) {
Err(AsgError::duplicate_alias_definition(name, span).into())
} else if global_consts.contains_key(name) {
Err(AsgError::duplicate_global_const_definition(name, span).into())
} else if functions.contains_key(name) {
Err(AsgError::duplicate_function_definition(name, span).into())
} else if circuits.contains_key(name) {
Err(AsgError::duplicate_circuit_definition(name, span).into())
} else {
Ok(())
}
}
impl<'a> Program<'a> {
/// Returns a new Leo program ASG from the given Leo program AST and its imports.
///
@ -264,44 +287,40 @@ 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())));
for (names, global_const) in program.global_consts.iter() {
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);
if let Statement::Definition(def) = gc {
let name = names
.iter()
.enumerate()
.map(|(i, name)| {
assert_eq!(name.name, def.variables.get(i).unwrap().borrow().name.name);
name.name.to_string()
})
.collect::<Vec<String>>()
.join(",");
scope.global_consts.borrow_mut().insert(name, def);
}
}
// Load concrete definitions.
let mut aliases = IndexMap::new();
let mut functions = IndexMap::new();
let mut circuits = IndexMap::new();
let mut global_consts = IndexMap::new();
for (name, alias) in program.aliases.iter() {
assert_eq!(name.name, alias.name.name);
let asg_alias = *scope.aliases.borrow().get(name.name.as_ref()).unwrap();
let name = name.name.to_string();
if aliases.contains_key(&name) {
return Err(AsgError::duplicate_alias_definition(name, &alias.span).into());
}
check_top_level_namespaces(&name, &alias.span, &aliases, &functions, &circuits, &global_consts)?;
aliases.insert(name, asg_alias);
}
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);
let asg_function = *scope.functions.borrow().get(name.name.as_ref()).unwrap();
@ -310,21 +329,50 @@ impl<'a> Program<'a> {
let name = name.name.to_string();
if functions.contains_key(&name) {
return Err(AsgError::duplicate_function_definition(name, &function.span).into());
}
check_top_level_namespaces(&name, &function.span, &aliases, &functions, &circuits, &global_consts)?;
functions.insert(name, asg_function);
}
let mut circuits = IndexMap::new();
for (name, circuit) in program.circuits.iter() {
assert_eq!(name.name, circuit.circuit_name.name);
let asg_circuit = *scope.circuits.borrow().get(name.name.as_ref()).unwrap();
asg_circuit.fill_from_ast(circuit)?;
circuits.insert(name.name.to_string(), asg_circuit);
let name = name.name.to_string();
check_top_level_namespaces(
&name,
&circuit.circuit_name.span,
&aliases,
&functions,
&circuits,
&global_consts,
)?;
circuits.insert(name, asg_circuit);
}
for (names, global_const) in program.global_consts.iter() {
let name = names
.iter()
.map(|name| name.name.to_string())
.collect::<Vec<String>>()
.join(",");
let asg_global_const = *scope.global_consts.borrow().get(&name).unwrap();
check_top_level_namespaces(
&name,
&global_const.span,
&aliases,
&functions,
&circuits,
&global_consts,
)?;
global_consts.insert(name.clone(), asg_global_const);
}
Ok(Program {

View File

@ -151,6 +151,22 @@ impl<'a> Scope<'a> {
}
}
///
/// Returns a reference to the global const definition statement corresponding to the name.
///
/// If the current scope did not have this name present, then the parent scope is checked.
/// If there is no parent scope, then `None` is returned.
///
pub fn resolve_global_const(&self, name: &str) -> Option<&'a DefinitionStatement<'a>> {
if let Some(resolved) = self.global_consts.borrow().get(name) {
Some(*resolved)
} else if let Some(resolved) = self.parent_scope.get() {
resolved.resolve_global_const(name)
} else {
None
}
}
///
/// Returns a new scope given a parent scope.
///
@ -205,7 +221,7 @@ impl<'a> Scope<'a> {
.collect::<Result<Vec<_>>>()?,
),
SelfType => return Err(AsgError::unexpected_big_self(span).into()),
CircuitOrAlias(name) => {
Identifier(name) => {
if let Some(circuit) = self.resolve_circuit(&name.name) {
Type::Circuit(circuit)
} else if let Some(alias) = self.resolve_alias(&name.name) {

View File

@ -110,10 +110,18 @@ impl<'a> FromAst<'a, leo_ast::DefinitionStatement> for &'a Statement<'a> {
}
for (variable, type_) in statement.variable_names.iter().zip(output_types.into_iter()) {
/* let name = variable.identifier.name.as_ref();
if scope.resolve_alias(name).is_some() {
return Err(AsgError::cannot_shadow_name("function input", name, "alias", &variable.identifier.span).into());
} */
let name = variable.identifier.name.as_ref();
if scope.resolve_global_const(name).is_some() {
return Err(
AsgError::function_variable_cannot_shadow_global_const(name, &variable.identifier.span).into(),
);
} else if scope.resolve_variable(name).is_some() {
return Err(AsgError::function_variable_cannot_shadow_other_function_variable(
name,
&variable.identifier.span,
)
.into());
}
variables.push(&*scope.context.alloc_variable(RefCell::new(InnerVariable {
id: scope.context.get_id(),

View File

@ -227,7 +227,7 @@ impl<'a> Into<leo_ast::Type> for &Type<'a> {
),
ArrayWithoutSize(type_) => leo_ast::Type::Array(Box::new(type_.as_ref().into()), None),
Tuple(subtypes) => leo_ast::Type::Tuple(subtypes.iter().map(Into::into).collect()),
Circuit(circuit) => leo_ast::Type::CircuitOrAlias(circuit.name.borrow().clone()),
Circuit(circuit) => leo_ast::Type::Identifier(circuit.name.borrow().clone()),
}
}
}

View File

@ -116,7 +116,7 @@ impl Canonicalizer {
fn canonicalize_self_type(&self, type_option: Option<&Type>) -> Option<Type> {
match type_option {
Some(type_) => match type_ {
Type::SelfType => Some(Type::CircuitOrAlias(self.circuit_name.as_ref().unwrap().clone())),
Type::SelfType => Some(Type::Identifier(self.circuit_name.as_ref().unwrap().clone())),
Type::Array(type_, dimensions) => Some(Type::Array(
Box::new(self.canonicalize_self_type(Some(type_)).unwrap()),
dimensions.clone(),
@ -470,15 +470,15 @@ impl Canonicalizer {
fn canonicalize_function_input(&mut self, input: &FunctionInput) -> FunctionInput {
if let FunctionInput::Variable(variable) = input {
if variable.type_.is_self() {
return FunctionInput::Variable(FunctionInputVariable {
identifier: variable.identifier.clone(),
const_: variable.const_,
mutable: variable.mutable,
type_: Type::CircuitOrAlias(self.circuit_name.as_ref().unwrap().clone()),
span: variable.span.clone(),
});
}
let type_ = self.canonicalize_self_type(Some(&variable.type_)).unwrap();
return FunctionInput::Variable(FunctionInputVariable {
identifier: variable.identifier.clone(),
const_: variable.const_,
mutable: variable.mutable,
type_,
span: variable.span.clone(),
});
}
input.clone()

View File

@ -21,25 +21,42 @@ use leo_errors::{AstError, Result, Span};
use indexmap::IndexMap;
pub struct Importer<T>
where
T: ImportResolver,
{
import_resolver: T,
}
pub struct Importer {}
impl<T> Importer<T>
where
T: ImportResolver,
{
pub fn new(import_resolver: T) -> Self {
Self { import_resolver }
}
impl Importer {
pub fn do_pass<T>(program: Program, importer: &mut T) -> Result<Ast>
where
T: ImportResolver,
{
let mut imported_symbols: Vec<(Vec<String>, ImportSymbol, Span)> = vec![];
for import_statement in program.import_statements.iter() {
resolve_import_package(&mut imported_symbols, vec![], &import_statement.package_or_packages);
}
pub fn do_pass(ast: Program, importer: T) -> Result<Ast> {
Ok(Ast::new(
ReconstructingDirector::new(Importer::new(importer)).reduce_program(&ast)?,
))
let mut deduplicated_imports: IndexMap<Vec<String>, Span> = IndexMap::new();
for (package, _symbol, span) in imported_symbols.iter() {
deduplicated_imports.insert(package.clone(), span.clone());
}
let mut wrapped_resolver = CoreImportResolver::new(importer);
let mut resolved_packages: IndexMap<Vec<String>, Program> = IndexMap::new();
for (package, span) in deduplicated_imports {
let pretty_package = package.join(".");
let resolved_package =
match wrapped_resolver.resolve_package(&package.iter().map(|x| &**x).collect::<Vec<_>>()[..], &span)? {
Some(x) => x,
None => return Err(AstError::unresolved_import(pretty_package, &span).into()),
};
resolved_packages.insert(package.clone(), resolved_package);
}
let mut ast = program;
ast.imports = resolved_packages;
Ok(Ast::new(ast))
}
}
@ -108,66 +125,3 @@ fn resolve_import_package_access(
}
}
}
impl<T> ReconstructingReducer for Importer<T>
where
T: ImportResolver,
{
fn in_circuit(&self) -> bool {
false
}
fn swap_in_circuit(&mut self) {}
fn reduce_program(
&mut self,
program: &Program,
expected_input: Vec<FunctionInput>,
import_statements: Vec<ImportStatement>,
empty_imports: IndexMap<Vec<String>, Program>,
aliases: IndexMap<Identifier, Alias>,
circuits: IndexMap<Identifier, Circuit>,
functions: IndexMap<Identifier, Function>,
global_consts: IndexMap<String, DefinitionStatement>,
) -> Result<Program> {
if !empty_imports.is_empty() {
return Err(AstError::injected_programs(empty_imports.len()).into());
}
let mut imported_symbols: Vec<(Vec<String>, ImportSymbol, Span)> = vec![];
for import_statement in import_statements.iter() {
resolve_import_package(&mut imported_symbols, vec![], &import_statement.package_or_packages);
}
let mut deduplicated_imports: IndexMap<Vec<String>, Span> = IndexMap::new();
for (package, _symbol, span) in imported_symbols.iter() {
deduplicated_imports.insert(package.clone(), span.clone());
}
let mut wrapped_resolver = CoreImportResolver::new(&mut self.import_resolver);
let mut resolved_packages: IndexMap<Vec<String>, Program> = IndexMap::new();
for (package, span) in deduplicated_imports {
let pretty_package = package.join(".");
let resolved_package =
match wrapped_resolver.resolve_package(&package.iter().map(|x| &**x).collect::<Vec<_>>()[..], &span)? {
Some(x) => x,
None => return Err(AstError::unresolved_import(pretty_package, &span).into()),
};
resolved_packages.insert(package.clone(), resolved_package);
}
Ok(Program {
name: program.name.clone(),
expected_input,
import_statements,
imports: resolved_packages,
aliases,
circuits,
functions,
global_consts,
})
}
}

View File

@ -0,0 +1,57 @@
// 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::{DefinitionStatement, Identifier};
use indexmap::IndexMap;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[allow(clippy::ptr_arg)]
pub fn serialize<S: Serializer>(
global_consts: &IndexMap<Vec<Identifier>, DefinitionStatement>,
serializer: S,
) -> Result<S::Ok, S::Error> {
let joined: IndexMap<String, DefinitionStatement> = global_consts
.into_iter()
.map(|(idents, program)| {
(
idents.iter().map(|i| i.name.to_string()).collect::<Vec<_>>().join(","),
program.clone(),
)
})
.collect();
joined.serialize(serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<IndexMap<Vec<Identifier>, DefinitionStatement>, D::Error> {
Ok(IndexMap::<String, DefinitionStatement>::deserialize(deserializer)?
.into_iter()
.map(|(name, program)| {
(
name.split(',')
.map(|ident_name| Identifier {
name: ident_name.into(),
span: Default::default(),
})
.collect::<Vec<Identifier>>(),
program,
)
})
.collect())
}

View File

@ -20,6 +20,8 @@ pub use array_dimensions::*;
pub mod const_self_keyword;
pub use const_self_keyword::*;
pub mod global_consts_json;
pub mod identifier;
pub use identifier::*;

View File

@ -33,7 +33,8 @@ pub struct Program {
pub imports: IndexMap<Vec<String>, Program>,
pub aliases: IndexMap<Identifier, Alias>,
pub circuits: IndexMap<Identifier, Circuit>,
pub global_consts: IndexMap<String, DefinitionStatement>,
#[serde(with = "crate::common::global_consts_json")]
pub global_consts: IndexMap<Vec<Identifier>, DefinitionStatement>,
pub functions: IndexMap<Identifier, Function>,
}

View File

@ -41,7 +41,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
Type::Tuple(reduced_types)
}
Type::CircuitOrAlias(identifier) => Type::CircuitOrAlias(self.reduce_identifier(identifier)?),
Type::Identifier(identifier) => Type::Identifier(self.reduce_identifier(identifier)?),
_ => type_.clone(),
};

View File

@ -387,7 +387,7 @@ pub trait ReconstructingReducer {
aliases: IndexMap<Identifier, Alias>,
circuits: IndexMap<Identifier, Circuit>,
functions: IndexMap<Identifier, Function>,
global_consts: IndexMap<String, DefinitionStatement>,
global_consts: IndexMap<Vec<Identifier>, DefinitionStatement>,
) -> Result<Program> {
Ok(Program {
name: program.name.clone(),

View File

@ -37,7 +37,7 @@ pub enum Type {
#[serde(serialize_with = "serialize_array")]
Array(Box<Type>, Option<ArrayDimensions>),
Tuple(Vec<Type>),
CircuitOrAlias(Identifier),
Identifier(Identifier), // ex Circuit or Alias
SelfType,
}
@ -53,7 +53,7 @@ impl Type {
/// Returns `true` if the self `Type` is a `Circuit`.
///
pub fn is_circuit(&self) -> bool {
matches!(self, Type::CircuitOrAlias(_))
matches!(self, Type::Identifier(_))
}
///
@ -69,7 +69,7 @@ impl Type {
(Type::Field, Type::Field) => true,
(Type::Group, Type::Group) => true,
(Type::IntegerType(left), Type::IntegerType(right)) => left.eq(right),
(Type::CircuitOrAlias(left), Type::CircuitOrAlias(right)) => left.eq(right),
(Type::Identifier(left), Type::Identifier(right)) => left.eq(right),
(Type::SelfType, Type::SelfType) => true,
(Type::Array(left_type, left_dim), Type::Array(right_type, right_dim)) => {
// Convert array dimensions to owned.
@ -161,7 +161,7 @@ impl fmt::Display for Type {
Type::Field => write!(f, "field"),
Type::Group => write!(f, "group"),
Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type),
Type::CircuitOrAlias(ref variable) => write!(f, "circuit {}", variable),
Type::Identifier(ref variable) => write!(f, "circuit {}", variable),
Type::SelfType => write!(f, "SelfType"),
Type::Array(ref array, ref dimensions) => {
if let Some(dimensions) = dimensions {

View File

@ -251,7 +251,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
// Preform import resolution.
ast = leo_ast_passes::Importer::do_pass(
ast.into_repr(),
ImportParser::new(self.main_file_path.clone(), self.imports_map.clone()),
&mut ImportParser::new(self.main_file_path.clone(), self.imports_map.clone()),
)?;
if self.ast_snapshot_options.imports_resolved {

View File

@ -266,7 +266,7 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
asg: &AsgCircuitAccessExpression,
) -> Result<CircuitMemberAccessExpression> {
let type_ = if self.options.type_inference_enabled() {
Some(leo_ast::Type::CircuitOrAlias(asg.circuit.get().name.borrow().clone()))
Some(leo_ast::Type::Identifier(asg.circuit.get().name.borrow().clone()))
} else {
None
};

View File

@ -2,15 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Pratyush Mishra
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status
@ -18,7 +11,7 @@ FINAL
# Summary
This proposal aims to improve the import management system in Leo programs to
make program environment more reproducible, predictable and compatible. To achieve
make program environment more reproducible, predictable and compatible. To achieve
that we suggest few changes to Leo CLI and Manifest:
- add a "dependencies" section to Leo Manifest and add a command to pull those dependencies;
@ -29,19 +22,19 @@ that we suggest few changes to Leo CLI and Manifest:
# Motivation
The current design of imports does not provide any guarantees on what's stored
in program imports and published with the program to Aleo Package Manager.
The current design of imports does not provide any guarantees on what's stored
in program imports and published with the program to Aleo Package Manager.
When a dependency is "added," it is stored inside imports folder, and it is possible
to manually edit and/or add packages in this folder.
Also, imports are stored under the package name which makes it impossible to import
two different packages with the same name.
two different packages with the same name.
Another important detail in the scope of this proposal is that in future Leo
programs will have the ability to be run with different proving systems
and curves, possibly creating incompatibility between programs written
programs will have the ability to be run with different proving systems
and curves, possibly creating incompatibility between programs written
for different proving systems or curves. To make a foundation for these features,
imports need to be managed with include/exclude lists for allowed (compatible)
imports need to be managed with include/exclude lists for allowed (compatible)
proving systems and curves.
# Design
@ -67,7 +60,7 @@ curve = "Bls12_377"
proving_system = "Groth16"
```
These fields are meant to be used to determine whether imported program is
These fields are meant to be used to determine whether imported program is
compatible to the original when support for different curves and proving systems
is added.
@ -88,7 +81,7 @@ version = "1.0"
### Parameters description
`name` field sets the name of the dependency in Leo code. That way we allow
`name` field sets the name of the dependency in Leo code. That way we allow
developer to resolve collisions in import names manually. So, for example,
if a developer is adding `howard/silly-sudoku` package to his program, he
might define its in-code name as `sudoku` and import it with that name:
@ -97,13 +90,13 @@ might define its in-code name as `sudoku` and import it with that name:
import sudoku;
```
`package`, `author` and `version` are package name, package author and
version respectively. They are already used as arguments in `leo add`
`package`, `author` and `version` are package name, package author and
version respectively. They are already used as arguments in `leo add`
command, so these fields are already understood by the Leo developers.
## Leo CLI
## Leo CLI
To support updated Manifest new command should be added to Leo CLI.
To support updated Manifest new command should be added to Leo CLI.
```bash
# pull imports
@ -113,11 +106,11 @@ leo fetch
## Imports Restructurization
One of the goals of proposed changes is to allow importing packages with the
same name but different authors. This has to be solved not only on the
language level but also on the level of storing program imports.
same name but different authors. This has to be solved not only on the
language level but also on the level of storing program imports.
We suggest using set of all 3 possible program identifiers for import
folder name: `author-package@version`. Later it can be extended to
folder name: `author-package@version`. Later it can be extended to
include hash for version, but having the inital set already solves name
collisions.
@ -140,7 +133,7 @@ leo-program
This change would also affect the way imports are being processed on the ASG
level, and we'd need to add an imports map as an argument to the Leo compiler.
The Leo Manifest's dependencies sections needs to be parsed and passed as
The Leo Manifest's dependencies sections needs to be parsed and passed as
a hashmap to the compiler:
```
@ -184,7 +177,7 @@ The format described here allows the Leo binary to form an imports map which can
passed to the compiler.
It is important to note that Leo.lock file is created only when a package has dependencies.
For programs with no dependencies, a lock file is not required and not created.
For programs with no dependencies, a lock file is not required and not created.
## Recursive Dependencies
@ -208,12 +201,12 @@ It also introduces the danger of having recursive dependencies, this problem is
# Effect on Ecosystem
Proposed improvement provides safety inside Leo programs and should not affect
ecosystem except for the tools which use Leo directly (such as Aleo Studio).
ecosystem except for the tools which use Leo directly (such as Aleo Studio).
It is possible that some of the proposed features will open new features on Aleo PM.
It is possible that some of the proposed features will open new features on Aleo PM.
# Alternatives
Another approach to the stated cases is to keep everything as we have now but change
the way programs are imported and stored and make names unique. Also, current
implementation provides some guarantees on import stablitity and consistency.
the way programs are imported and stored and make names unique. Also, current
implementation provides some guarantees on import stablitity and consistency.

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status
@ -67,7 +60,7 @@ function bubble_sort(a: [u32; 10]) -> [u32; 10] {
Having a countdown loop in the examples above could improve readability and
usability of the language by making it more natural to the developer.
However, if we imagined this example using a countdown loop, we would see that
However, if we imagined this example using a countdown loop, we would see that
it wouldn't be possible to count to 0; because the first bound of the range is
inclusive and the second is exclusive, and loops ranges must use only unsigned integers.
@ -75,19 +68,19 @@ inclusive and the second is exclusive, and loops ranges must use only unsigned i
// loop goes 0,1,2,3,4,5,6,7,8
for i in 0..9 { /* ... */ }
// loop goes 9,8,7,6,5,4,3,2,1
// loop goes 9,8,7,6,5,4,3,2,1
for i in 9..0 { /* ... */ }
```
Hence direct implementation of the coundown loop ranges would create asymmetry (1)
and would not allow loops to count down to 0 (2). To implement coundown loops and
and would not allow loops to count down to 0 (2). To implement coundown loops and
solve these two problems we suggest adding an inclusive range bounds.
# Design
## Coundown loops
Countdown ranges do not need any changes to the existing syntax. However their
Countdown ranges do not need any changes to the existing syntax. However their
functionality needs to be implemented in the compiler.
```ts
@ -96,9 +89,9 @@ for i in 5..0 {}
## Inclusive ranges
To solve loop asymmetry and to improve loop ranges in general we suggest adding
inclusive range operator to Leo. Inclusive range would extend the second bound
of the loop making it inclusive (instead of default - exclusive)
To solve loop asymmetry and to improve loop ranges in general we suggest adding
inclusive range operator to Leo. Inclusive range would extend the second bound
of the loop making it inclusive (instead of default - exclusive)
therefore allowing countdown loops to reach 0 value.
```ts

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status

View File

@ -2,37 +2,25 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status
DRAFT
# Summary
## Summary
This RFC proposes a framework for making certain (top-level) declarations (e.g. type aliases)
available in every Leo program without the need to explicitly write those declarations.
These may be hardwired into the language, or provided by standard libraries/packages;
in the latter case, the libraries may be either implicitly imported or required to be explicitly imported.
This RFC proposes a framework for making certain (top-level) declarations (e.g. type aliases) available in every Leo program without the need to write those declarations explicitly. These may be hardwired into the language or provided by standard libraries/packages; in the latter case, the libraries may be implicitly imported or required to be explicitly imported.
# Motivation
## Motivation
It is common for programming languages to provide predefined types, functions, etc.
that can be readily used in programs.
The initial motivation for this in Leo was to have a type alias `string` for character arrays of unspecified sizes
(array types of unspecified sizes and type aliases are discussed in separate RFCs),
but the feature is clearly more general.
that can be readily used in programs. The initial motivation for this in Leo was to have a type alias `string` for character arrays of unspecified sizes (array types of unspecified sizes and type aliases are discussed in separate RFCs), but the feature is clearly more general.
# Design
## Design
Leo supports five kinds of top-level declarations:
Leo supports four kinds of top-level declarations:
- Import declarations.
- Function declarations.
- Circuit type declarations.
@ -41,42 +29,32 @@ Leo supports four kinds of top-level declarations:
Leaving import declarations aside for the moment since they are "meta" in some sense
(as they bring in names of entities declared elsewhere),
it may make sense for any of the four kinds of declarations above to have built-in instances,
i.e. we could have some built-in functions, circuit types, global constants, and type aliases.
This is why this RFC talks of built-in declarations, more broadly than just built-in type aliases that inspired it.
it may make sense for any of the four kinds of declarations above to have built-in instances, i.e., we could have some built-in functions, circuit types, global constants, and type aliases. These features are why this RFC talks of built-in declarations, more broadly than just built-in type aliases that inspired it.
The built-in status of the envisioned declarations could be achieved in slightly different ways:
1. Their names could be simply available in any program,
without any explicit declaration found anywhere for them.
2. They could be declared in some core library files explicitly,
and be available in any program without needing to be explicitly import them,
like `java.lang.String` in Java or `std::Option` in Rust.
3. They could be declared in some core library files explicitly,
and be available only in programs that explicitly import them.
The built-in status of the envisioned declarations will be done through explicitly declared core library files. Then these core library files must be explicitly imported. This way helps avoid unnecessary code bloat in the compilation, and any user asked for AST snapshots.
From a user's perspective, there is not a lot of difference between cases 1 and 2 above:
in both cases, the names are available; the only difference is that in case 2 the user can see the declaration somewhere.
Also note that case 2 could be seen as having an implicit (i.e. built-in) import of the library/libraries in question.
Again, imports are "meta" in this context, and what counts are really the other kinds of declarations.
In cases 2 and 3, a related but somewhat independent issue is whether those declarations have Leo definitions or not.
The Leo library already includes functions like the one for BLAKE2s that are not defined in Leo,
but rather "natively" in Rust/R1CS.
# Drawbacks
## Drawbacks
This does not seem to bring any drawbacks.
# Effect on Ecosystem
## Effect on Ecosystem
This may interact with libraries and packages in some way,
if we go with case 2 or 3 above.
But it should be not much different from regular libraries/packages.
This change may interact with libraries and packages in some way.
But it should not be much different from standard libraries/packages.
# Alternatives
## Alternatives
The 'Design' section above currently discusses a few alternatives,
rather than prescribing a defined approach.
When consensus is reached on one of the alternatives discussed there,
the others will be moved to this section.
Some alternative approaches are:
1. Their names could be simply available in any program,
without any explicit declaration found anywhere for them.
2. They could be declared in some core library files explicitly
and be available in any program without explicitly importing them,
like `java.lang.String` in Java or `std::Option` in Rust.
From a user's perspective, there is not a lot of difference between cases 1 and 2 above:
in both cases, the names are available; the only difference is that in case 2, the user can see the declaration somewhere.
Also, note that case 2 could be seen as having an implicit (i.e., built-in) import of the library/libraries in question. Again, imports are "meta" in this context, and what counts are the other kinds of declarations.
In cases 2 and the decided upon design choice, a related but somewhat independent issue is whether those declarations have Leo definitions or not. The Leo library already includes functions like BLAKE2s that are not defined in Leo but rather "natively" in Rust/R1CS though some of this may be subject to change for native definitions(see the separate RFC on those).

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status

View File

@ -2,14 +2,7 @@
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
The Aleo Team.
## Status
@ -52,7 +45,7 @@ postfix-expression = primary-expression
/ identifier function-arguments
/ postfix-expression "." identifier function-arguments
/ named-type "::" identifier function-arguments ; this used to be a circuit-type
/ named-type "::" identifier ; this is new to allow static members on
/ named-type "::" identifier ; this is new to allow static members on
/ postfix-expression "[" expression "]"
/ postfix-expression "[" [expression] ".." [expression] "]"
```

View File

@ -420,6 +420,14 @@ create_errors!(
help: None,
}
/// For when a user defines an circuit with the same name twice.
@formatted
duplicate_circuit_definition {
args: (name: impl Display),
msg: format!("a circuit named \"{}\" already exists in this scope", name),
help: None,
}
/// For when a user defines a function input with the same name twice.
@formatted
duplicate_function_input_definition {
@ -436,11 +444,34 @@ create_errors!(
help: None,
}
/// For when a named identifier is being shadowed.
/// For when a function input shadows a global const.
@formatted
cannot_shadow_name {
args: (type_: impl Display, name: impl Display, location: impl Display),
msg: format!("a {} cannot be named `{}` as a {} with that name already exists in this scope", type_, name, location),
function_input_cannot_shadow_global_const {
args: (name: impl Display),
msg: format!("a function input cannot be named `{}` as a global const with that name already exists in this scope", name),
help: None,
}
/// For when a variable definition shadows a global const.
@formatted
function_variable_cannot_shadow_global_const {
args: (name: impl Display),
msg: format!("a variable cannot be named `{}` as a global const with that name already exists in this scope", name),
help: None,
}
/// For when a variable definition shadows a function input.
@formatted
function_variable_cannot_shadow_other_function_variable {
args: (name: impl Display),
msg: format!("a variable cannot be named `{}` as a function input or variable with that name already exists in this scope", name),
help: None,
}
@formatted
operator_allowed_only_for_type {
args: (operator: impl Display, type_: impl Display, received: impl Display),
msg: format!("operator '{}' is only allowed for type '{}', received: '{}'", operator, type_, received),
help: None,
}
);

View File

@ -6,3 +6,7 @@ license = "LICENSE-MIT"
[remote]
author = "aleo"
[target]
curve = "bls12_377"
proving_system = "groth16"

1
examples/linear-regression/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
outputs/

View File

@ -0,0 +1,12 @@
[project]
name = "linear-regression"
version = "0.1.0"
description = "The linear-regression package"
license = "MIT"
[remote]
author = "aleo"
[target]
curve = "bls12_377"
proving_system = "groth16"

View File

@ -0,0 +1,20 @@
# linear-regression
## Build Guide
To compile this Leo program, run:
```bash
leo build
```
To test this Leo program, run:
```bash
leo test
```
## Development
To output the number of constraints, run:
```bash
leo build -d
```

View File

@ -0,0 +1,7 @@
// The program input for light-cuddly-cyan-polo/src/main.leo
[main]
x: i32 = 1i32;
y: i32 = 2i32;
[registers]
r0: [i32; 2] = [1i32, 2i32];

View File

@ -0,0 +1,26 @@
// The program state for linear-regression/src/main.leo
[[public]]
[state]
leaf_index: u32 = 0;
root: [u8; 32] = [0; 32];
[[private]]
[record]
serial_number: [u8; 64] = [0; 64];
commitment: [u8; 32] = [0; 32];
owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9;
is_dummy: bool = false;
value: u64 = 0;
payload: [u8; 32] = [0; 32];
birth_program_id: [u8; 48] = [0; 48];
death_program_id: [u8; 48] = [0; 48];
serial_number_nonce: [u8; 32] = [0; 32];
commitment_randomness: [u8; 32] = [0; 32];
[state_leaf]
path: [u8; 128] = [0; 128];
memo: [u8; 32] = [0; 32];
network_id: u8 = 0;
leaf_randomness: [u8; 32] = [0; 32];

View File

@ -0,0 +1,65 @@
circuit Point {
x: i32,
y: i32,
function new(x: i32, y: i32) -> Self {
return Self { x, y };
}
}
circuit LinearRegression {
points: [Point; 5],
// Instantiates a linear regression circuit.
function new(points: [Point; 5]) -> Self {
return Self { points };
}
// Return the slope of the linear regression.
function slope(self) -> i32 {
let num_points = 5i32;
// Calculate the sums.
let x_sum = 0i32;
let y_sum = 0i32;
let xy_sum = 0i32;
let x2_sum = 0i32;
for i in 0..5 {
x_sum += self.points[i].x;
y_sum += self.points[i].y;
xy_sum += self.points[i].x * self.points[i].y;
x2_sum += self.points[i].x * self.points[i].x;
}
let numerator = (num_points * xy_sum) - (x_sum * y_sum);
let denominator = (num_points * x2_sum) - (x_sum * x_sum);
let slope = numerator / denominator;
return slope;
}
// Return the offset of the linear regression.
function offset(self, slope: i32) -> i32 {
let num_points = 5i32;
// Calculate the sum.
let x_sum = 0i32;
let y_sum = 0i32;
for i in 0..5 {
x_sum += self.points[i].x;
y_sum += self.points[i].y;
}
return (y_sum - slope * x_sum) / num_points;
}
}
function main (x: i32, y: i32) -> [i32; 2] {
let points: [Point; 5] = [
Point{x: x + 1, y: y + 1},
Point{x: x + 2, y: y + 2},
Point{x: x + 3, y: y + 3},
Point{x: x + 4, y: y + 4},
Point{x: x + 5, y: y + 5}
];
let reg = LinearRegression::new(points);
let slope = reg.slope();
let offset = reg.offset(slope);
return [slope, offset];
}

1
examples/palindrome/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
outputs/

View File

@ -0,0 +1,15 @@
[project]
name = "palindrome"
version = "0.1.0"
description = "The palindrome package"
license = "MIT"
[remote]
author = "aleo"
[target]
curve = "bls12_377"
proving_system = "groth16"
[dependencies]
# none

View File

@ -0,0 +1,20 @@
# palindrome
## Build Guide
To compile this Leo program, run:
```bash
leo build
```
To test this Leo program, run:
```bash
leo test
```
## Development
To output the number of constraints, run:
```bash
leo build -d
```

View File

@ -0,0 +1,5 @@
[main]
str: [char; 20] = "borrow or rob "; // char array can be defined as a string
[registers]
r0: bool = false;

View File

@ -0,0 +1,26 @@
// The program state for palindrome/src/main.leo
[[public]]
[state]
leaf_index: u32 = 0;
root: [u8; 32] = [0; 32];
[[private]]
[record]
serial_number: [u8; 64] = [0; 64];
commitment: [u8; 32] = [0; 32];
owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9;
is_dummy: bool = false;
value: u64 = 0;
payload: [u8; 32] = [0; 32];
birth_program_id: [u8; 48] = [0; 48];
death_program_id: [u8; 48] = [0; 48];
serial_number_nonce: [u8; 32] = [0; 32];
commitment_randomness: [u8; 32] = [0; 32];
[state_leaf]
path: [u8; 128] = [0; 128];
memo: [u8; 32] = [0; 32];
network_id: u8 = 0;
leaf_randomness: [u8; 32] = [0; 32];

View File

@ -0,0 +1,59 @@
// This Program takes in any 20-byte low register string and tells
// whether a string is a palindrome ignoring any spaces.
function main(str: [char; 20]) -> bool {
return is_palindrome(str);
}
function is_palindrome(str: [char; 20]) -> bool {
const str_len = 20u32; // saving const for convenience
// By default we assume that input is a palindrome.
let result = true;
let processed = 0u8;
for start in 0..(str_len / 2) {
let start_sym = str[start];
if start_sym != ' ' {
let skipped = 0u8;
let end_empty = 0u8;
let end_sym = ' ';
for end in (str_len - 1)..start {
if str[end] != ' ' && skipped == processed && end_sym == ' ' {
end_sym = str[end];
} else {
end_empty = end_empty + 1;
if str[end] != ' ' {
skipped = skipped + 1;
}
}
}
// If there are symbols left to the right from the start.
if end_sym != ' ' {
console.log("Comparing: {} ? {}", start_sym, end_sym);
if result {
result = (start_sym == end_sym);
}
processed = processed + 1;
}
}
}
console.log("Result is: {}", result);
return result;
}
@test
function test_is_palindrome() {
console.assert(is_palindrome("a b a "));
console.assert(is_palindrome("😀😀😀😀😀 😀😀😀😀😀"));
console.assert(is_palindrome("borrow or rob "));
console.assert(is_palindrome("bbbb aaaa aaaa bbbb"));
console.assert(is_palindrome("aaaaaaaaaaaaaaaaaaaa"));
console.assert(is_palindrome("taco cat "));
}

View File

@ -6,3 +6,7 @@ license = "LICENSE-MIT"
[remote]
author = "aleo"
[target]
curve = "bls12_377"
proving_system = "groth16"

View File

@ -6,3 +6,7 @@ license = "MIT"
[remote]
author = "howard"
[target]
curve = "bls12_377"
proving_system = "groth16"

View File

@ -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), [newline](#user-content-newline), [space](#user-content-space)_;
Go to: _[newline](#user-content-newline), [space](#user-content-space), [horizontal-tab](#user-content-horizontal-tab)_;
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: _[end-of-line-comment](#user-content-end-of-line-comment), [block-comment](#user-content-block-comment)_;
Go to: _[block-comment](#user-content-block-comment), [end-of-line-comment](#user-content-end-of-line-comment)_;
<a name="block-comment"></a>
@ -511,7 +511,7 @@ rest-of-block-comment = "*" rest-of-block-comment-after-star
/ not-star rest-of-block-comment
```
Go to: _[not-star](#user-content-not-star), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [rest-of-block-comment](#user-content-rest-of-block-comment)_;
Go to: _[rest-of-block-comment](#user-content-rest-of-block-comment), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [not-star](#user-content-not-star)_;
<a name="rest-of-block-comment-after-star"></a>
@ -590,7 +590,7 @@ lowercase-letter = %x61-7A ; a-z
letter = uppercase-letter / lowercase-letter
```
Go to: _[uppercase-letter](#user-content-uppercase-letter), [lowercase-letter](#user-content-lowercase-letter)_;
Go to: _[lowercase-letter](#user-content-lowercase-letter), [uppercase-letter](#user-content-uppercase-letter)_;
The following rules defines (ASCII) decimal, octal, and hexadecimal digits.
@ -774,7 +774,7 @@ character-literal-element = not-single-quote-or-backslash
/ unicode-character-escape
```
Go to: _[unicode-character-escape](#user-content-unicode-character-escape), [simple-character-escape](#user-content-simple-character-escape), [not-single-quote-or-backslash](#user-content-not-single-quote-or-backslash), [ascii-character-escape](#user-content-ascii-character-escape)_;
Go to: _[ascii-character-escape](#user-content-ascii-character-escape), [simple-character-escape](#user-content-simple-character-escape), [unicode-character-escape](#user-content-unicode-character-escape), [not-single-quote-or-backslash](#user-content-not-single-quote-or-backslash)_;
<a name="single-quote-escape"></a>
@ -829,7 +829,7 @@ simple-character-escape = single-quote-escape
/ null-character-escape
```
Go to: _[line-feed-escape](#user-content-line-feed-escape), [single-quote-escape](#user-content-single-quote-escape), [double-quote-escape](#user-content-double-quote-escape), [carriage-return-escape](#user-content-carriage-return-escape), [null-character-escape](#user-content-null-character-escape), [horizontal-tab-escape](#user-content-horizontal-tab-escape), [backslash-escape](#user-content-backslash-escape)_;
Go to: _[line-feed-escape](#user-content-line-feed-escape), [carriage-return-escape](#user-content-carriage-return-escape), [double-quote-escape](#user-content-double-quote-escape), [backslash-escape](#user-content-backslash-escape), [null-character-escape](#user-content-null-character-escape), [single-quote-escape](#user-content-single-quote-escape), [horizontal-tab-escape](#user-content-horizontal-tab-escape)_;
<a name="ascii-character-escape"></a>
@ -865,7 +865,7 @@ string-literal-element = not-double-quote-or-backslash
/ unicode-character-escape
```
Go to: _[unicode-character-escape](#user-content-unicode-character-escape), [simple-character-escape](#user-content-simple-character-escape), [not-double-quote-or-backslash](#user-content-not-double-quote-or-backslash), [ascii-character-escape](#user-content-ascii-character-escape)_;
Go to: _[simple-character-escape](#user-content-simple-character-escape), [unicode-character-escape](#user-content-unicode-character-escape), [not-double-quote-or-backslash](#user-content-not-double-quote-or-backslash), [ascii-character-escape](#user-content-ascii-character-escape)_;
The ones above are all the atomic literals
@ -885,7 +885,7 @@ atomic-literal = untyped-literal
/ string-literal
```
Go to: _[field-literal](#user-content-field-literal), [boolean-literal](#user-content-boolean-literal), [address-literal](#user-content-address-literal), [signed-literal](#user-content-signed-literal), [character-literal](#user-content-character-literal), [string-literal](#user-content-string-literal), [unsigned-literal](#user-content-unsigned-literal), [product-group-literal](#user-content-product-group-literal), [untyped-literal](#user-content-untyped-literal)_;
Go to: _[character-literal](#user-content-character-literal), [unsigned-literal](#user-content-unsigned-literal), [signed-literal](#user-content-signed-literal), [address-literal](#user-content-address-literal), [field-literal](#user-content-field-literal), [untyped-literal](#user-content-untyped-literal), [product-group-literal](#user-content-product-group-literal), [string-literal](#user-content-string-literal), [boolean-literal](#user-content-boolean-literal)_;
After defining the (mostly) alphanumeric tokens above,
@ -929,7 +929,7 @@ token = keyword
/ symbol
```
Go to: _[identifier](#user-content-identifier), [atomic-literal](#user-content-atomic-literal), [package-name](#user-content-package-name), [annotation-name](#user-content-annotation-name), [symbol](#user-content-symbol), [keyword](#user-content-keyword)_;
Go to: _[identifier](#user-content-identifier), [annotation-name](#user-content-annotation-name), [package-name](#user-content-package-name), [keyword](#user-content-keyword), [symbol](#user-content-symbol), [atomic-literal](#user-content-atomic-literal)_;
Tokens, comments, and whitespace are lexemes, i.e. lexical units.
@ -939,7 +939,7 @@ Tokens, comments, and whitespace are lexemes, i.e. lexical units.
lexeme = token / comment / whitespace
```
Go to: _[token](#user-content-token), [comment](#user-content-comment), [whitespace](#user-content-whitespace)_;
Go to: _[token](#user-content-token), [whitespace](#user-content-whitespace), [comment](#user-content-comment)_;
@ -996,7 +996,7 @@ group-type = %s"group"
arithmetic-type = integer-type / field-type / group-type
```
Go to: _[integer-type](#user-content-integer-type), [group-type](#user-content-group-type), [field-type](#user-content-field-type)_;
Go to: _[field-type](#user-content-field-type), [group-type](#user-content-group-type), [integer-type](#user-content-integer-type)_;
The arithmetic types, along with the boolean, address, and character types,
@ -1022,24 +1022,7 @@ character-type = %s"char"
scalar-type = boolean-type / arithmetic-type / address-type / character-type
```
Go to: _[character-type](#user-content-character-type), [boolean-type](#user-content-boolean-type), [address-type](#user-content-address-type), [arithmetic-type](#user-content-arithmetic-type)_;
Circuit types are denoted by identifiers and the keyword `Self`.
The latter is only allowed inside a circuit definition,
to denote the circuit being defined.
<a name="self-type"></a>
```abnf
self-type = %s"Self"
```
<a name="circuit-or-alias-type"></a>
```abnf
circuit-or-alias-type = identifier / self-type
```
Go to: _[self-type](#user-content-self-type), [identifier](#user-content-identifier)_;
Go to: _[boolean-type](#user-content-boolean-type), [arithmetic-type](#user-content-arithmetic-type), [character-type](#user-content-character-type), [address-type](#user-content-address-type)_;
A tuple type consists of zero, two, or more component types.
@ -1056,32 +1039,68 @@ An array type consists of an element type
and an indication of dimensions.
There is either a single dimension,
or a tuple of one or more dimensions.
Each dimension is either a natural or is unspecified.
<a name="array-type"></a>
```abnf
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>
<a name="array-dimension"></a>
```abnf
array-dimensions = natural
/ "(" natural *( "," natural ) ")"
array-dimension = natural / "_"
```
Go to: _[natural](#user-content-natural)_;
Scalar and the remaining types form all the types.
<a name="array-dimensions"></a>
```abnf
array-dimensions = array-dimension
/ "(" array-dimension *( "," array-dimension ) ")"
```
Go to: _[array-dimension](#user-content-array-dimension)_;
The keyword `Self` denotes the enclosing circuit type.
It is only allowed inside a circuit type declaration.
<a name="self-type"></a>
```abnf
self-type = %s"Self"
```
Circuit types are denoted by identifiers and by `Self`.
Identifiers may also be type aliases;
syntactically (i.e. without a semantic analysis),
they cannot be distinguished from circuit types.
Scalar types, tuple types, array types,
identifiers (which may be circuit types or type aliases),
and the `Self` type
form all the types.
<a name="type"></a>
```abnf
type = scalar-type / tuple-type / array-type / circuit-or-alias-type
type = scalar-type / tuple-type / array-type / identifier / self-type
```
Go to: _[circuit-or-alias-type](#user-content-circuit-or-alias-type), [tuple-type](#user-content-tuple-type), [array-type](#user-content-array-type), [scalar-type](#user-content-scalar-type)_;
Go to: _[array-type](#user-content-array-type), [scalar-type](#user-content-scalar-type), [tuple-type](#user-content-tuple-type), [identifier](#user-content-identifier), [self-type](#user-content-self-type)_;
It is convenient to introduce a rule for types that are
either identifiers or `Self`, as this is used in other rules.
<a name="identifier-or-self-type"></a>
```abnf
identifier-or-self-type = identifier / self-type
```
Go to: _[self-type](#user-content-self-type), [identifier](#user-content-identifier)_;
The lexical grammar given earlier defines product group literals.
@ -1117,7 +1136,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
@ -1130,7 +1149,7 @@ a group literal is either a product group literal or an affine group literal.
group-literal = product-group-literal / affine-group-literal
```
Go to: _[affine-group-literal](#user-content-affine-group-literal), [product-group-literal](#user-content-product-group-literal)_;
Go to: _[product-group-literal](#user-content-product-group-literal), [affine-group-literal](#user-content-affine-group-literal)_;
As often done in grammatical language syntax specifications,
@ -1159,7 +1178,7 @@ primary-expression = identifier
/ circuit-expression
```
Go to: _[identifier](#user-content-identifier), [literal](#user-content-literal), [expression](#user-content-expression), [tuple-expression](#user-content-tuple-expression), [array-expression](#user-content-array-expression), [circuit-expression](#user-content-circuit-expression)_;
Go to: _[tuple-expression](#user-content-tuple-expression), [array-expression](#user-content-array-expression), [identifier](#user-content-identifier), [literal](#user-content-literal), [expression](#user-content-expression), [circuit-expression](#user-content-circuit-expression)_;
Tuple expressions construct tuples.
@ -1220,7 +1239,7 @@ Go to: _[expression](#user-content-expression), [array-dimensions](#user-content
array-construction = array-inline-construction / array-repeat-construction
```
Go to: _[array-repeat-construction](#user-content-array-repeat-construction), [array-inline-construction](#user-content-array-inline-construction)_;
Go to: _[array-inline-construction](#user-content-array-inline-construction), [array-repeat-construction](#user-content-array-repeat-construction)_;
<a name="array-expression"></a>
@ -1242,13 +1261,13 @@ so they are syntactically identical but semantically different.
<a name="circuit-construction"></a>
```abnf
circuit-construction = circuit-or-alias-type "{"
circuit-construction = identifier-or-self-type "{"
circuit-inline-element
*( "," circuit-inline-element ) [ "," ]
"}"
```
Go to: _[circuit-inline-element](#user-content-circuit-inline-element), [circuit-or-alias-type](#user-content-circuit-or-alias-type)_;
Go to: _[identifier-or-self-type](#user-content-identifier-or-self-type), [circuit-inline-element](#user-content-circuit-inline-element)_;
<a name="circuit-inline-element"></a>
@ -1302,12 +1321,12 @@ postfix-expression = primary-expression
/ postfix-expression "." identifier
/ identifier function-arguments
/ postfix-expression "." identifier function-arguments
/ circuit-or-alias-type "::" identifier function-arguments
/ identifier-or-self-type "::" identifier function-arguments
/ postfix-expression "[" expression "]"
/ postfix-expression "[" [expression] ".." [expression] "]"
```
Go to: _[identifier](#user-content-identifier), [postfix-expression](#user-content-postfix-expression), [function-arguments](#user-content-function-arguments), [circuit-or-alias-type](#user-content-circuit-or-alias-type), [primary-expression](#user-content-primary-expression), [natural](#user-content-natural), [expression](#user-content-expression)_;
Go to: _[function-arguments](#user-content-function-arguments), [primary-expression](#user-content-primary-expression), [expression](#user-content-expression), [postfix-expression](#user-content-postfix-expression), [identifier](#user-content-identifier), [natural](#user-content-natural), [identifier-or-self-type](#user-content-identifier-or-self-type)_;
Unary operators have the highest operator precedence.
@ -1335,7 +1354,7 @@ exponential-expression = unary-expression
/ unary-expression "**" exponential-expression
```
Go to: _[unary-expression](#user-content-unary-expression), [exponential-expression](#user-content-exponential-expression)_;
Go to: _[exponential-expression](#user-content-exponential-expression), [unary-expression](#user-content-unary-expression)_;
Next in precedence come multiplication and division, both left-associative.
@ -1347,7 +1366,7 @@ multiplicative-expression = exponential-expression
/ multiplicative-expression "/" exponential-expression
```
Go to: _[exponential-expression](#user-content-exponential-expression), [multiplicative-expression](#user-content-multiplicative-expression)_;
Go to: _[multiplicative-expression](#user-content-multiplicative-expression), [exponential-expression](#user-content-exponential-expression)_;
Then there are addition and subtraction, both left-assocative.
@ -1359,7 +1378,7 @@ additive-expression = multiplicative-expression
/ additive-expression "-" multiplicative-expression
```
Go to: _[multiplicative-expression](#user-content-multiplicative-expression), [additive-expression](#user-content-additive-expression)_;
Go to: _[additive-expression](#user-content-additive-expression), [multiplicative-expression](#user-content-multiplicative-expression)_;
Next in the precedence order are ordering relations.
@ -1398,7 +1417,7 @@ conjunctive-expression = equality-expression
/ conjunctive-expression "&&" equality-expression
```
Go to: _[conjunctive-expression](#user-content-conjunctive-expression), [equality-expression](#user-content-equality-expression)_;
Go to: _[equality-expression](#user-content-equality-expression), [conjunctive-expression](#user-content-conjunctive-expression)_;
Next come disjunctive expressions, left-associative.
@ -1409,7 +1428,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.
@ -1422,7 +1441,7 @@ conditional-expression = disjunctive-expression
":" conditional-expression
```
Go to: _[disjunctive-expression](#user-content-disjunctive-expression), [expression](#user-content-expression), [conditional-expression](#user-content-conditional-expression)_;
Go to: _[expression](#user-content-expression), [disjunctive-expression](#user-content-disjunctive-expression), [conditional-expression](#user-content-conditional-expression)_;
Those above are all the expressions.
@ -1455,7 +1474,7 @@ statement = expression-statement
/ block
```
Go to: _[assignment-statement](#user-content-assignment-statement), [expression-statement](#user-content-expression-statement), [loop-statement](#user-content-loop-statement), [return-statement](#user-content-return-statement), [console-statement](#user-content-console-statement), [variable-declaration](#user-content-variable-declaration), [conditional-statement](#user-content-conditional-statement), [block](#user-content-block), [constant-declaration](#user-content-constant-declaration)_;
Go to: _[loop-statement](#user-content-loop-statement), [expression-statement](#user-content-expression-statement), [console-statement](#user-content-console-statement), [block](#user-content-block), [return-statement](#user-content-return-statement), [variable-declaration](#user-content-variable-declaration), [constant-declaration](#user-content-constant-declaration), [assignment-statement](#user-content-assignment-statement), [conditional-statement](#user-content-conditional-statement)_;
<a name="block"></a>
@ -1498,7 +1517,7 @@ variable-declaration = %s"let" identifier-or-identifiers [ ":" type ]
"=" expression ";"
```
Go to: _[expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type)_;
Go to: _[identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type), [expression](#user-content-expression)_;
<a name="constant-declaration"></a>
@ -1507,7 +1526,7 @@ 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)_;
Go to: _[expression](#user-content-expression), [type](#user-content-type), [identifier-or-identifiers](#user-content-identifier-or-identifiers)_;
<a name="identifier-or-identifiers"></a>
@ -1540,7 +1559,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), [conditional-statement](#user-content-conditional-statement), [branch](#user-content-branch)_;
A loop statement implicitly defines a loop variable
@ -1549,10 +1568,11 @@ The body is a block.
<a name="loop-statement"></a>
```abnf
loop-statement = %s"for" identifier %s"in" expression ".." [ "=" ] expression 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), [identifier](#user-content-identifier), [block](#user-content-block)_;
An assignment statement is straightforward.
@ -1625,7 +1645,7 @@ Go to: _[string-literal](#user-content-string-literal)_;
print-call = print-function print-arguments
```
Go to: _[print-function](#user-content-print-function), [print-arguments](#user-content-print-arguments)_;
Go to: _[print-arguments](#user-content-print-arguments), [print-function](#user-content-print-function)_;
An annotation consists of an annotation name (which starts with `@`)
@ -1638,7 +1658,7 @@ annotation = annotation-name
[ "(" identifier *( "," identifier ) ")" ]
```
Go to: _[identifier](#user-content-identifier), [annotation-name](#user-content-annotation-name)_;
Go to: _[annotation-name](#user-content-annotation-name), [identifier](#user-content-identifier)_;
A function declaration defines a function.
@ -1655,7 +1675,7 @@ function-declaration = *annotation %s"function" identifier
block
```
Go to: _[block](#user-content-block), [type](#user-content-type), [identifier](#user-content-identifier), [function-parameters](#user-content-function-parameters)_;
Go to: _[identifier](#user-content-identifier), [type](#user-content-type), [block](#user-content-block), [function-parameters](#user-content-function-parameters)_;
<a name="function-parameters"></a>
@ -1665,7 +1685,7 @@ function-parameters = self-parameter
/ function-inputs
```
Go to: _[self-parameter](#user-content-self-parameter), [function-inputs](#user-content-function-inputs)_;
Go to: _[function-inputs](#user-content-function-inputs), [self-parameter](#user-content-self-parameter)_;
<a name="self-parameter"></a>
@ -1756,7 +1776,7 @@ by using an explicit package name before the package path.
import-declaration = %s"import" package-name "." package-path ";"
```
Go to: _[package-path](#user-content-package-path), [package-name](#user-content-package-name)_;
Go to: _[package-name](#user-content-package-name), [package-path](#user-content-package-path)_;
<a name="package-path"></a>
@ -1767,19 +1787,17 @@ package-path = "*"
/ "(" package-path *( "," package-path ) [","] ")"
```
Go to: _[package-name](#user-content-package-name), [identifier](#user-content-identifier), [package-path](#user-content-package-path)_;
Go to: _[package-path](#user-content-package-path), [identifier](#user-content-identifier), [package-name](#user-content-package-name)_;
A type declaration consists of the `type` keyword
followed by an identifier and a type that the alias
would refer to.
A type alias declaration defines an identifier to stand for a type.
<a name="type-alias-declaration"></a>
```abnf
type-alias-declaration = %s"type" identifier "=" type ";"
```
Go to: _[type](#user-content-type), [identifier](#user-content-identifier)_;
Go to: _[identifier](#user-content-identifier), [type](#user-content-type)_;
Finally, we define a file as a sequence of zero or more declarations.
@ -1795,7 +1813,7 @@ declaration = import-declaration
/ type-alias-declaration
```
Go to: _[import-declaration](#user-content-import-declaration), [circuit-declaration](#user-content-circuit-declaration), [constant-declaration](#user-content-constant-declaration), [type-alias-declaration](#user-content-type-alias-declaration), [function-declaration](#user-content-function-declaration)_;
Go to: _[circuit-declaration](#user-content-circuit-declaration), [import-declaration](#user-content-import-declaration), [function-declaration](#user-content-function-declaration), [constant-declaration](#user-content-constant-declaration), [type-alias-declaration](#user-content-type-alias-declaration)_;
<a name="file"></a>

View File

@ -659,14 +659,6 @@ character-type = %s"char"
scalar-type = boolean-type / arithmetic-type / address-type / character-type
; Circuit types are denoted by identifiers and the keyword `Self`.
; The latter is only allowed inside a circuit definition,
; to denote the circuit being defined.
self-type = %s"Self"
circuit-or-alias-type = identifier / self-type
; A tuple type consists of zero, two, or more component types.
tuple-type = "(" [ type 1*( "," type ) ] ")"
@ -675,6 +667,7 @@ tuple-type = "(" [ type 1*( "," type ) ] ")"
; and an indication of dimensions.
; There is either a single dimension,
; or a tuple of one or more dimensions.
; Each dimension is either a natural or is unspecified.
array-type = "[" type ";" array-dimensions "]"
@ -683,9 +676,27 @@ array-dimension = natural / "_"
array-dimensions = array-dimension
/ "(" array-dimension *( "," array-dimension ) ")"
; Scalar and the remaining types form all the types.
; The keyword `Self` denotes the enclosing circuit type.
; It is only allowed inside a circuit type declaration.
type = scalar-type / tuple-type / array-type / circuit-or-alias-type
self-type = %s"Self"
; Circuit types are denoted by identifiers and by `Self`.
; Identifiers may also be type aliases;
; syntactically (i.e. without a semantic analysis),
; they cannot be distinguished from circuit types.
; Scalar types, tuple types, array types,
; identifiers (which may be circuit types or type aliases),
; and the `Self` type
; form all the types.
type = scalar-type / tuple-type / array-type / identifier / self-type
; It is convenient to introduce a rule for types that are
; either identifiers or `Self`, as this is used in other rules.
identifier-or-self-type = identifier / self-type
; The lexical grammar given earlier defines product group literals.
; The other kind of group literal is a pair of integer coordinates,
@ -771,7 +782,7 @@ array-expression = array-construction
; while the right one denotes an expression (a variable),
; so they are syntactically identical but semantically different.
circuit-construction = circuit-or-alias-type "{"
circuit-construction = identifier-or-self-type "{"
circuit-inline-element
*( "," circuit-inline-element ) [ "," ]
"}"
@ -807,7 +818,7 @@ postfix-expression = primary-expression
/ postfix-expression "." identifier
/ identifier function-arguments
/ postfix-expression "." identifier function-arguments
/ circuit-or-alias-type "::" identifier function-arguments
/ identifier-or-self-type "::" identifier function-arguments
/ postfix-expression "[" expression "]"
/ postfix-expression "[" [expression] ".." [expression] "]"
@ -937,7 +948,8 @@ conditional-statement = branch
; that goes from a starting value (inclusive) to an ending value (exclusive).
; The body is a block.
loop-statement = %s"for" identifier %s"in" expression ".." [ "=" ] expression block
loop-statement = %s"for" identifier %s"in" expression ".." [ "=" ] expression
block
; An assignment statement is straightforward.
; Based on the operator, the assignment may be simple (i.e. `=`)
@ -1049,9 +1061,7 @@ package-path = "*"
/ package-name "." package-path
/ "(" package-path *( "," package-path ) [","] ")"
; A type declaration consists of the `type` keyword
; followed by an identifier and a type that the alias
; would refer to.
; A type alias declaration defines an identifier to stand for a type.
type-alias-declaration = %s"type" identifier "=" type ";"

View File

@ -35,7 +35,10 @@ impl ImportParser {
return self.parse_package(package.path(), remaining_segments, span);
}
Self::parse_import_file(package, span)
let program = Self::parse_import_file(package, span)?;
let ast = leo_ast_passes::Importer::do_pass(program, self)?.into_repr();
Ok(ast)
}
///

View File

@ -507,14 +507,13 @@ impl ParserContext {
/// 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) -> Result<(String, DefinitionStatement)> {
pub fn parse_global_const_declaration(&mut self) -> Result<(Vec<Identifier>, 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(",");
.map(|variable_name| variable_name.identifier.clone())
.collect::<Vec<Identifier>>();
Ok((variable_names, statement))
}

View File

@ -91,7 +91,7 @@ impl ParserContext {
(Type::SelfType, token.span)
} else if let Some(ident) = self.eat_identifier() {
let span = ident.span.clone();
(Type::CircuitOrAlias(ident), span)
(Type::Identifier(ident), span)
} else if let Some(token) = self.eat(Token::LeftParen) {
let mut types = Vec::new();
let end_span;

View File

@ -143,7 +143,7 @@ fn generate_asts(path: PathBuf, text: &str) -> Result<(String, String, String, S
let mut ast = leo_parser::parse_ast(path.clone().into_os_string().into_string().unwrap(), text)?;
let initial = ast.to_json_string()?;
ast = leo_ast_passes::Importer::do_pass(ast.into_repr(), ImportParser::new(path, Default::default()))?;
ast = leo_ast_passes::Importer::do_pass(ast.into_repr(), &mut ImportParser::new(path, Default::default()))?;
let imports_resolved = ast.to_json_string()?;
ast = leo_ast_passes::Canonicalizer::do_pass(ast.into_repr())?;

View File

@ -0,0 +1,17 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
type Int = u32;
circuit Int {
x: u8;
}
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,14 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
type int = u32;
function int() {}
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,14 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
type int = u32;
const int = 8u8;
function main(y: bool) -> bool {
return y;
}

View File

@ -1,9 +0,0 @@
/*
namespace: Compile
expectation: Fail
input_file: input/dummy.in
*/
function main(y: bool) {
return (10u8.len() == 10u32) == y;
}

View File

@ -20,7 +20,7 @@ circuit Foo {
y[Self {x: 0}.x] += 2;
}
function func() {
function func(a: [Self; 3], y: (Self)) {
const x: Self = Foo {x: Self {x: 1}.x};
}

View File

@ -0,0 +1,16 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
circuit Int {
x: u8;
}
type Int = u32;
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,16 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
circuit Foo {
x: u8;
}
function Foo() {}
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,16 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
circuit Foo {
x: u8;
}
const Foo = 8u8;
function main(y: bool) -> bool {
return y;
}

View File

@ -5,10 +5,12 @@ input_file: input/dummy.in
*/
function main() {
function main(y: bool) -> bool {
console.log("{}", 1u8);
return y;
}
function main() {
function main(y: bool) -> bool {
console.log("{}", 2u8);
return y;
}

View File

@ -0,0 +1,14 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
function int() {}
type int = u32;
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,16 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
function Foo() {}
circuit Foo {
x: u8;
}
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,14 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
function foo() {}
const foo = 8u8;
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,13 @@
/*
namespace: Compile
expectation: Fail
input_file: input/dummy.in
*/
const hi = 1u32;
function tester(hi: u8) {}
function main (y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,13 @@
/*
namespace: Compile
expectation: Fail
input_file: input/dummy.in
*/
function tester(hi: u8) {
const hi = 1u8;
}
function main (y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,13 @@
/*
namespace: Compile
expectation: Fail
input_file: input/dummy.in
*/
function tester(hi: u8) {
const hi = 2u8;
}
function main (y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,14 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
const int = 8u8;
type int = u32;
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,16 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
const Foo = 8u8;
circuit Foo {
x: u8;
}
function main(y: bool) -> bool {
return y;
}

View File

@ -0,0 +1,14 @@
/*
namespace: Compile
expectation: Fail
input_file:
- inputs/dummy.in
*/
const two = 2u8;
function two() {}
function main(y: bool) -> bool {
return y;
}

View File

@ -19,7 +19,7 @@ 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();
const one = uno();
const character = 'a';
const hello = "Hello, World!";
@ -49,7 +49,7 @@ function main(a: u32) -> bool {
&& use_another_const == 9u32 // use another const test
&& foo.width == 10u32 // circuit test
&& foo.height == 20u32
&& uno == 1u32 // function test
&& one == 1u32 // function test
&& character == 'a' // char test
&& hello == "Hello, World!";
}

View File

@ -0,0 +1,6 @@
[main]
y: bool = true;
x: bool = false;
[registers]
r0: bool = true;

View File

@ -11,6 +11,8 @@ function main(y: bool) -> bool {
const a = Point { x: 1u32, y: 0u32 };
const hello_alias: char5 = "hello";
const hello = "hello";
const eight = 8u8;
const fab = fab_gen();
return( (foo() == 1u32) && hello_alias == hello) == y;
return( (foo() == 1u32) && hello_alias == hello && EIGHT == eight) == y;
}

View File

@ -8,3 +8,11 @@ function foo() -> u32 {
}
type char5 = [char; 5];
const EIGHT = 8u8;
import nested.c-d.Fab;
function fab_gen() -> Fab {
return Fab { x: 3 };
}

View File

@ -1,3 +1,7 @@
circuit Fab {
x: u8;
}
function cd() -> bool {
return true;
}

View File

@ -5,7 +5,7 @@ input_file: inputs/true_true.in
*/
function main(a: (bool, bool)) -> (bool, bool) {
const a = (true, false);
const b = (true, false);
return (a.0, a.1);
return (b.0, b.1);
}

View File

@ -5,7 +5,7 @@ input_file: inputs/true_true.in
*/
function main(a: (bool, bool)) -> (bool, bool) {
let a = (a.0 ? false : true, a.1 ? false : true);
let b = (a.0 ? false : true, a.1 ? false : true);
return (a.0, a.1);
return (b.0, b.1);
}

View File

@ -5,7 +5,7 @@ input_file: inputs/true_true.in
*/
function main(a: (bool, bool)) -> (bool, bool) {
let (a, b) = (a.0 ? false : true, a.1 ? false : true);
let (b, c) = (a.0 ? false : true, a.1 ? false : true);
return (b, a);
return (c, b);
}

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- "Error [EASG0373044]: a alias named \"Int\" already exists in this scope\n --> compiler-test:6:9\n |\n 6 | circuit Int {\n | ^^^"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- "Error [EASG0373044]: a alias named \"int\" already exists in this scope\n --> compiler-test:5:1\n |\n 5 | function int() {}\n | ^^^^^^^^^^^^^^^^^"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- "Error [EASG0373044]: a alias named \"int\" already exists in this scope\n --> compiler-test:5:1\n |\n 5 | const int = 8u8;\n | ^^^^^^^^^^^^^^^"

View File

@ -16,7 +16,7 @@ outputs:
r0:
type: bool
value: "true"
initial_ast: a4a3b4b30742544a6dae3d76794504173c1cc64f217bd3feda033ce51512a670
imports_resolved_ast: a4a3b4b30742544a6dae3d76794504173c1cc64f217bd3feda033ce51512a670
canonicalized_ast: a4a3b4b30742544a6dae3d76794504173c1cc64f217bd3feda033ce51512a670
initial_ast: 6349e2684562bad873bcf643e01eeb02039295bd41e2df77f1fefc7bb3f2d3bb
imports_resolved_ast: 6349e2684562bad873bcf643e01eeb02039295bd41e2df77f1fefc7bb3f2d3bb
canonicalized_ast: 6349e2684562bad873bcf643e01eeb02039295bd41e2df77f1fefc7bb3f2d3bb
type_inferenced_ast: 508686ddeb2f8fad60d9ad58639b5a761e6c5f5b61e105803eb8a98d8065a2ad

View File

@ -16,7 +16,7 @@ outputs:
r0:
type: bool
value: "true"
initial_ast: d83b33119db295fa2ed7795c8e17d4073cabba5e90e9438cd53f3a9a77585f19
imports_resolved_ast: d83b33119db295fa2ed7795c8e17d4073cabba5e90e9438cd53f3a9a77585f19
canonicalized_ast: d83b33119db295fa2ed7795c8e17d4073cabba5e90e9438cd53f3a9a77585f19
type_inferenced_ast: 77be8ec74bc15f2a45e8bf29e7973bc0c721008fe5508dcc6d02b91aae3d84ee
initial_ast: 9f78c996da10363fb594947ca29fef29e35a7032761ce87f69f3ae454650d47e
imports_resolved_ast: 9f78c996da10363fb594947ca29fef29e35a7032761ce87f69f3ae454650d47e
canonicalized_ast: 9f78c996da10363fb594947ca29fef29e35a7032761ce87f69f3ae454650d47e
type_inferenced_ast: 103314a18ce6036da1ab4cc32c025b694cf799492460ab9553dfbd5232544a89

View File

@ -16,7 +16,7 @@ outputs:
r0:
type: bool
value: "true"
initial_ast: d9b0b6772317f0e2d1042dba26c19b4eb71a7e902c643cbeb0a4f62630f0f1bc
imports_resolved_ast: d9b0b6772317f0e2d1042dba26c19b4eb71a7e902c643cbeb0a4f62630f0f1bc
canonicalized_ast: d9b0b6772317f0e2d1042dba26c19b4eb71a7e902c643cbeb0a4f62630f0f1bc
type_inferenced_ast: e384fbed9e161b04c6c9e85f45788e5047385f289ef89d20fdacee00a8fb3e5c
initial_ast: ee817c17e6bef3b458e14d3a81c087ed6a75c4554bc70b62466e8d8e43ff1b5e
imports_resolved_ast: ee817c17e6bef3b458e14d3a81c087ed6a75c4554bc70b62466e8d8e43ff1b5e
canonicalized_ast: ee817c17e6bef3b458e14d3a81c087ed6a75c4554bc70b62466e8d8e43ff1b5e
type_inferenced_ast: b15c7e773ebb56e339f750401241e38aab4ab8950c20a70acc293afc1b91d917

View File

@ -16,7 +16,7 @@ outputs:
r0:
type: bool
value: "true"
initial_ast: 7feac3e33e75789d3b532a7cc857f324cd7abed380d578791803b3162edcfdec
imports_resolved_ast: 7feac3e33e75789d3b532a7cc857f324cd7abed380d578791803b3162edcfdec
canonicalized_ast: 7feac3e33e75789d3b532a7cc857f324cd7abed380d578791803b3162edcfdec
initial_ast: 8d5ed3110bc3a61ddee37408133fcc1f77209b65bb83d230729203009e093f40
imports_resolved_ast: 8d5ed3110bc3a61ddee37408133fcc1f77209b65bb83d230729203009e093f40
canonicalized_ast: 8d5ed3110bc3a61ddee37408133fcc1f77209b65bb83d230729203009e093f40
type_inferenced_ast: bc54ad21e90ab297b40ff570dfc379cbca61fdc9e20bd6899f4b964f726954b0

View File

@ -16,7 +16,7 @@ outputs:
r0:
type: bool
value: "true"
initial_ast: 671704ed30a8c68ebffe2a58ff4799f626badf975d2d0dded3b06f5264e5c0db
imports_resolved_ast: 671704ed30a8c68ebffe2a58ff4799f626badf975d2d0dded3b06f5264e5c0db
canonicalized_ast: 671704ed30a8c68ebffe2a58ff4799f626badf975d2d0dded3b06f5264e5c0db
type_inferenced_ast: eb525f7c227207a1037b96838d2f0cf597968c14117b3fae30564f3cd5a3a27b
initial_ast: f7b2eb89c51644dc8596988bcc66fbfe471489887c6f46b78ca417746c7ef442
imports_resolved_ast: f7b2eb89c51644dc8596988bcc66fbfe471489887c6f46b78ca417746c7ef442
canonicalized_ast: f7b2eb89c51644dc8596988bcc66fbfe471489887c6f46b78ca417746c7ef442
type_inferenced_ast: f24ef5063928ee7998b53e5e66064c56c01bd99d55b736309d3a1d11ff2fec05

View File

@ -16,7 +16,7 @@ outputs:
r0:
type: bool
value: "true"
initial_ast: cd2e85ff29ee11d30e73dbba0a612223a8a26dff125069ad7ac05697fd4c9829
imports_resolved_ast: cd2e85ff29ee11d30e73dbba0a612223a8a26dff125069ad7ac05697fd4c9829
canonicalized_ast: cd2e85ff29ee11d30e73dbba0a612223a8a26dff125069ad7ac05697fd4c9829
initial_ast: 66ead06ceac4fea6a24fe071a955986722a53975fa98d2ad2909a83fa8ba8525
imports_resolved_ast: 66ead06ceac4fea6a24fe071a955986722a53975fa98d2ad2909a83fa8ba8525
canonicalized_ast: 66ead06ceac4fea6a24fe071a955986722a53975fa98d2ad2909a83fa8ba8525
type_inferenced_ast: 1e73226b2cbbd5c7a36ffe70b778e0e544976d2e09a1f0ba3f2b486d1b604d58

View File

@ -19,4 +19,4 @@ outputs:
initial_ast: 843884ddf198fe566cea0f8e84a2902f720d6211c9d8bad98299eea4da846870
imports_resolved_ast: 843884ddf198fe566cea0f8e84a2902f720d6211c9d8bad98299eea4da846870
canonicalized_ast: c30721e60523bc31af9a9bf342d9b89bf92a26e3886394cc0c1a574560715bdf
type_inferenced_ast: c37f209961a9acff1d942af1e4a9a332123676f2bc581ca94604314f9d738a1e
type_inferenced_ast: baed608da257be0625cd54a796c2f89e9aec8b1ff60f23c7657a0c4fc260e1d1

View File

@ -25,4 +25,4 @@ outputs:
initial_ast: 4e74124bc410534941ef9b79ffb64656d14e145b5a79fbd14419c1aef2f0ef69
imports_resolved_ast: 4e74124bc410534941ef9b79ffb64656d14e145b5a79fbd14419c1aef2f0ef69
canonicalized_ast: 4e74124bc410534941ef9b79ffb64656d14e145b5a79fbd14419c1aef2f0ef69
type_inferenced_ast: f5cb6326028b3cf9187889be6ac5ed5bd095a570d45ae63c7285a09366fc6803
type_inferenced_ast: de80815f88fb65efa62ce7f5fa23c6fc4f1bbdf601954e94c1212c4eabbee1cb

View File

@ -16,7 +16,7 @@ outputs:
r0:
type: bool
value: "true"
initial_ast: 1695abb58931812bfe65ffdb967c9e8e36abbab771bfd8a20e289e3e1b102b5a
imports_resolved_ast: 1695abb58931812bfe65ffdb967c9e8e36abbab771bfd8a20e289e3e1b102b5a
canonicalized_ast: 637eaabe62c318b0c9f9d6d26936c11aa8804022866ce356e14dc02e29a34251
type_inferenced_ast: 1540899195a176d1b1d0e1d886a671f07f063dd10fea15f853e67ffcfc0ae9ce
initial_ast: 0e8ea2eb2de2ad93883ced129ab7c42674fd476d94ede483f5ea042f8386b730
imports_resolved_ast: 0e8ea2eb2de2ad93883ced129ab7c42674fd476d94ede483f5ea042f8386b730
canonicalized_ast: 529ba1d5564ef0c1752343e3e6e8b181f13bec0620c4ecbe23080ef4a080cb2b
type_inferenced_ast: b4d3305f7179dfc2a7a330e538a41e3cdf51f12e4a6545cd57ff9a2e5a9d1db0

View File

@ -103,4 +103,4 @@ outputs:
initial_ast: 0c2aeb5b47fc21f5aded4e3aebcdf55eb98c10c6b51a2a6dcb98490a96da0c97
imports_resolved_ast: 0c2aeb5b47fc21f5aded4e3aebcdf55eb98c10c6b51a2a6dcb98490a96da0c97
canonicalized_ast: 0c2aeb5b47fc21f5aded4e3aebcdf55eb98c10c6b51a2a6dcb98490a96da0c97
type_inferenced_ast: 84977d828c2988392d85d4156d34d168a3265aca3c3516b3ddb974d3d9eee2dc
type_inferenced_ast: e9c5fc64aad2390305671ffbe316eee04d5fca7a6f09dcc8c8a69c38db8b3a62

View File

@ -16,7 +16,7 @@ outputs:
r0:
type: bool
value: "true"
initial_ast: 8ccdbe000ca6a2ae3b7cf8601d5b6a922106181fe3f1b8aede16c5661a816b93
imports_resolved_ast: 8ccdbe000ca6a2ae3b7cf8601d5b6a922106181fe3f1b8aede16c5661a816b93
canonicalized_ast: 551e7de9ff8d1391a435861819576c9ac1a0ff93818c7a907830be890e27311f
type_inferenced_ast: b83403b86ddd7a10d070a4537a95ac03075e292d3004cdb667564b630dcae805
initial_ast: ec52d3b3e69bef6d104f2dcfa9e713a728d7b0e15439c9da3b521b6cbfe719d4
imports_resolved_ast: ec52d3b3e69bef6d104f2dcfa9e713a728d7b0e15439c9da3b521b6cbfe719d4
canonicalized_ast: c85604dd75a964f7a6cfc0dddbeeeccf28a7c43915b944740528a0ff6230db78
type_inferenced_ast: 258670051ac595a600362cb5a6793fb5ba9361cd914f7483057ad66204fc1b36

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- "Error [EASG0373044]: a alias named \"Int\" already exists in this scope\n --> compiler-test:3:9\n |\n 3 | circuit Int {\n | ^^^"

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