mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-31 22:23:57 +03:00
Merge branch 'master' into array-len-function
This commit is contained in:
commit
4f41f09ef2
35
.github/workflows/acl2.yml
vendored
35
.github/workflows/acl2.yml
vendored
@ -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
16
Cargo.lock
generated
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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)?;
|
||||
|
@ -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(),
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -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()) {
|
||||
|
@ -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()),
|
||||
|
@ -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());
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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(),
|
||||
|
@ -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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
57
ast/src/common/global_consts_json.rs
Normal file
57
ast/src/common/global_consts_json.rs
Normal 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())
|
||||
}
|
@ -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::*;
|
||||
|
||||
|
@ -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>,
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
};
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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] "]"
|
||||
```
|
||||
|
@ -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,
|
||||
}
|
||||
);
|
||||
|
@ -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
1
examples/linear-regression/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
outputs/
|
12
examples/linear-regression/Leo.toml
Normal file
12
examples/linear-regression/Leo.toml
Normal 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"
|
20
examples/linear-regression/README.md
Normal file
20
examples/linear-regression/README.md
Normal 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
|
||||
```
|
7
examples/linear-regression/inputs/linear-regression.in
Normal file
7
examples/linear-regression/inputs/linear-regression.in
Normal 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];
|
26
examples/linear-regression/inputs/linear-regression.state
Normal file
26
examples/linear-regression/inputs/linear-regression.state
Normal 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];
|
65
examples/linear-regression/src/main.leo
Normal file
65
examples/linear-regression/src/main.leo
Normal 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
1
examples/palindrome/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
outputs/
|
15
examples/palindrome/Leo.toml
Normal file
15
examples/palindrome/Leo.toml
Normal 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
|
20
examples/palindrome/README.md
Normal file
20
examples/palindrome/README.md
Normal 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
|
||||
```
|
5
examples/palindrome/inputs/palindrome.in
Normal file
5
examples/palindrome/inputs/palindrome.in
Normal file
@ -0,0 +1,5 @@
|
||||
[main]
|
||||
str: [char; 20] = "borrow or rob "; // char array can be defined as a string
|
||||
|
||||
[registers]
|
||||
r0: bool = false;
|
26
examples/palindrome/inputs/palindrome.state
Normal file
26
examples/palindrome/inputs/palindrome.state
Normal 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];
|
59
examples/palindrome/src/main.leo
Normal file
59
examples/palindrome/src/main.leo
Normal 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 "));
|
||||
}
|
@ -6,3 +6,7 @@ license = "LICENSE-MIT"
|
||||
|
||||
[remote]
|
||||
author = "aleo"
|
||||
|
||||
[target]
|
||||
curve = "bls12_377"
|
||||
proving_system = "groth16"
|
||||
|
@ -6,3 +6,7 @@ license = "MIT"
|
||||
|
||||
[remote]
|
||||
author = "howard"
|
||||
|
||||
[target]
|
||||
curve = "bls12_377"
|
||||
proving_system = "groth16"
|
||||
|
@ -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>
|
||||
|
@ -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 ";"
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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())?;
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
input_file: input/dummy.in
|
||||
*/
|
||||
|
||||
function main(y: bool) {
|
||||
return (10u8.len() == 10u32) == y;
|
||||
}
|
@ -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};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
13
tests/compiler/function/shadow_global_const_var_fail.leo
Normal file
13
tests/compiler/function/shadow_global_const_var_fail.leo
Normal 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;
|
||||
}
|
13
tests/compiler/function/shadow_parameter_fail.leo
Normal file
13
tests/compiler/function/shadow_parameter_fail.leo
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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!";
|
||||
}
|
||||
|
6
tests/compiler/global_consts/inputs/dummy.in
Normal file
6
tests/compiler/global_consts/inputs/dummy.in
Normal file
@ -0,0 +1,6 @@
|
||||
[main]
|
||||
y: bool = true;
|
||||
x: bool = false;
|
||||
|
||||
[registers]
|
||||
r0: bool = true;
|
@ -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;
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
circuit Fab {
|
||||
x: u8;
|
||||
}
|
||||
|
||||
function cd() -> bool {
|
||||
return true;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 | ^^^"
|
@ -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 | ^^^^^^^^^^^^^^^^^"
|
@ -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 | ^^^^^^^^^^^^^^^"
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -19,4 +19,4 @@ outputs:
|
||||
initial_ast: 843884ddf198fe566cea0f8e84a2902f720d6211c9d8bad98299eea4da846870
|
||||
imports_resolved_ast: 843884ddf198fe566cea0f8e84a2902f720d6211c9d8bad98299eea4da846870
|
||||
canonicalized_ast: c30721e60523bc31af9a9bf342d9b89bf92a26e3886394cc0c1a574560715bdf
|
||||
type_inferenced_ast: c37f209961a9acff1d942af1e4a9a332123676f2bc581ca94604314f9d738a1e
|
||||
type_inferenced_ast: baed608da257be0625cd54a796c2f89e9aec8b1ff60f23c7657a0c4fc260e1d1
|
||||
|
@ -25,4 +25,4 @@ outputs:
|
||||
initial_ast: 4e74124bc410534941ef9b79ffb64656d14e145b5a79fbd14419c1aef2f0ef69
|
||||
imports_resolved_ast: 4e74124bc410534941ef9b79ffb64656d14e145b5a79fbd14419c1aef2f0ef69
|
||||
canonicalized_ast: 4e74124bc410534941ef9b79ffb64656d14e145b5a79fbd14419c1aef2f0ef69
|
||||
type_inferenced_ast: f5cb6326028b3cf9187889be6ac5ed5bd095a570d45ae63c7285a09366fc6803
|
||||
type_inferenced_ast: de80815f88fb65efa62ce7f5fa23c6fc4f1bbdf601954e94c1212c4eabbee1cb
|
||||
|
@ -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
|
||||
|
@ -103,4 +103,4 @@ outputs:
|
||||
initial_ast: 0c2aeb5b47fc21f5aded4e3aebcdf55eb98c10c6b51a2a6dcb98490a96da0c97
|
||||
imports_resolved_ast: 0c2aeb5b47fc21f5aded4e3aebcdf55eb98c10c6b51a2a6dcb98490a96da0c97
|
||||
canonicalized_ast: 0c2aeb5b47fc21f5aded4e3aebcdf55eb98c10c6b51a2a6dcb98490a96da0c97
|
||||
type_inferenced_ast: 84977d828c2988392d85d4156d34d168a3265aca3c3516b3ddb974d3d9eee2dc
|
||||
type_inferenced_ast: e9c5fc64aad2390305671ffbe316eee04d5fca7a6f09dcc8c8a69c38db8b3a62
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user