merge latest abnf branch

This commit is contained in:
gluax 2021-03-30 19:38:37 -04:00
commit 34f0f1519a
81 changed files with 1278 additions and 1146 deletions

139
Cargo.lock generated
View File

@ -2,6 +2,25 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "abnf"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "020babd9b431b239cffff9eb1e49d8cad5f3581674d3938540801e633a3b5f69"
dependencies = [
"abnf-core",
"nom 6.1.2",
]
[[package]]
name = "abnf-core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b514944cb7199c4201f54406bc58676a3e4f37d40bf8e3dbe30652ca82e3ddb4"
dependencies = [
"nom 6.1.2",
]
[[package]]
name = "addr2line"
version = "0.14.1"
@ -157,6 +176,18 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bitvec"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "blake2"
version = "0.9.1"
@ -290,7 +321,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
dependencies = [
"nom",
"nom 5.1.2",
]
[[package]]
@ -787,6 +818,22 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "funty"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "futf"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b"
dependencies = [
"mac",
"new_debug_unreachable",
]
[[package]]
name = "futures-channel"
version = "0.3.13"
@ -1192,6 +1239,14 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "leo-abnf"
version = "1.2.3"
dependencies = [
"abnf",
"anyhow",
]
[[package]]
name = "leo-asg"
version = "1.2.3"
@ -1203,6 +1258,7 @@ dependencies = [
"num-bigint",
"serde",
"serde_json",
"tendril",
"thiserror",
"typed-arena",
]
@ -1225,6 +1281,7 @@ dependencies = [
"pest",
"serde",
"serde_json",
"tendril",
"thiserror",
]
@ -1351,6 +1408,7 @@ dependencies = [
"leo-ast",
"serde",
"serde_json",
"tendril",
"thiserror",
"tracing",
]
@ -1386,6 +1444,19 @@ dependencies = [
"snarkvm-r1cs",
]
[[package]]
name = "lexical-core"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
dependencies = [
"arrayvec",
"bitflags",
"cfg-if 1.0.0",
"ryu",
"static_assertions",
]
[[package]]
name = "libc"
version = "0.2.89"
@ -1444,6 +1515,12 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "mac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "maplit"
version = "1.0.2"
@ -1610,6 +1687,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "nias"
version = "0.5.0"
@ -1626,6 +1709,19 @@ dependencies = [
"version_check",
]
[[package]]
name = "nom"
version = "6.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
dependencies = [
"bitvec",
"funty",
"lexical-core",
"memchr",
"version_check",
]
[[package]]
name = "notify"
version = "4.0.15"
@ -2011,6 +2107,12 @@ dependencies = [
"proc-macro2 1.0.24",
]
[[package]]
name = "radium"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "rand"
version = "0.8.3"
@ -2675,6 +2777,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.8.0"
@ -2745,6 +2853,12 @@ dependencies = [
"unicode-xid 0.2.1",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
version = "3.2.0"
@ -2759,6 +2873,17 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "tendril"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33"
dependencies = [
"futf",
"mac",
"utf-8",
]
[[package]]
name = "termcolor"
version = "1.1.2"
@ -3077,6 +3202,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "utf-8"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
[[package]]
name = "vcpkg"
version = "0.2.11"
@ -3283,6 +3414,12 @@ dependencies = [
"winapi-build",
]
[[package]]
name = "wyz"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
[[package]]
name = "zip"
version = "0.5.10"

View File

@ -29,6 +29,7 @@ members = [
"asg",
"ast",
"compiler",
"grammar",
"imports",
"input",
"linter",

View File

@ -43,5 +43,8 @@ version = "0.4"
[dependencies.typed-arena]
version = "2.0"
[dependencies.tendril]
version = "0.4"
[dev-dependencies.criterion]
version = "0.3"

View File

@ -18,6 +18,7 @@ use crate::{AsgConvertError, IntegerType, Span, Type};
use num_bigint::BigInt;
use std::{convert::TryInto, fmt};
use tendril::StrTendril;
/// Constant integer values in a program.
#[derive(Clone, Debug, PartialEq)]
@ -38,7 +39,7 @@ pub enum ConstInt {
#[derive(Clone, Debug, PartialEq)]
pub enum GroupCoordinate {
/// Explicit field element number string.
Number(String),
Number(StrTendril),
/// Attempt to recover with a sign high bit.
SignHigh,
@ -87,7 +88,7 @@ impl Into<leo_ast::GroupCoordinate> for &GroupCoordinate {
#[derive(Clone, Debug, PartialEq)]
pub enum GroupValue {
Single(String),
Single(StrTendril),
Tuple(GroupCoordinate, GroupCoordinate),
}
@ -106,7 +107,7 @@ pub enum ConstValue {
Int(ConstInt),
Group(GroupValue),
Field(BigInt),
Address(String),
Address(StrTendril),
Boolean(bool),
// compounds

View File

@ -35,25 +35,7 @@ pub enum AsgConvertError {
SyntaxError(#[from] SyntaxError),
}
impl LeoError for AsgConvertError {
fn get_path(&self) -> Option<&str> {
match self {
AsgConvertError::Error(error) => error.get_path(),
AsgConvertError::SyntaxError(error) => error.get_path(),
AsgConvertError::ImportError(error) => error.get_path(),
AsgConvertError::InternalError(_) => None,
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
AsgConvertError::Error(error) => error.set_path(path, contents),
AsgConvertError::SyntaxError(error) => error.set_path(path, contents),
AsgConvertError::ImportError(error) => error.set_path(path, contents),
AsgConvertError::InternalError(_) => {}
}
}
}
impl LeoError for AsgConvertError {}
impl AsgConvertError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -152,7 +152,7 @@ impl<'a> Into<leo_ast::ArrayInitExpression> for &ArrayInitExpression<'a> {
leo_ast::ArrayInitExpression {
element: Box::new(self.element.get().into()),
dimensions: leo_ast::ArrayDimensions(vec![leo_ast::PositiveNumber {
value: self.len.to_string(),
value: self.len.to_string().into(),
}]),
span: self.span.clone().unwrap_or_default(),
}

View File

@ -116,7 +116,7 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
let circuit_name = circuit.name.borrow().name.clone();
let member = circuit.members.borrow();
let member = member
.get(&name.name)
.get(name.name.as_ref())
.ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, span))?;
match member {
CircuitMember::Function(body) => {
@ -156,7 +156,7 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
let member = circuit.members.borrow();
let member = member
.get(&name.name)
.get(name.name.as_ref())
.ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, span))?;
match member {
CircuitMember::Function(body) => {

View File

@ -67,7 +67,7 @@ impl<'a> ExpressionNode<'a> for CircuitAccessExpression<'a> {
None // function target only for static
} else {
let members = self.circuit.get().members.borrow();
let member = members.get(&self.member.name)?;
let member = members.get(self.member.name.as_ref())?;
match member {
CircuitMember::Variable(type_) => Some(type_.clone()),
CircuitMember::Function(_) => None,
@ -112,7 +112,7 @@ impl<'a> FromAst<'a, leo_ast::CircuitMemberAccessExpression> for CircuitAccessEx
// scoping refcell reference
let found_member = {
if let Some(member) = circuit.members.borrow().get(&value.name.name) {
if let Some(member) = circuit.members.borrow().get(value.name.name.as_ref()) {
if let Some(expected_type) = &expected_type {
if let CircuitMember::Variable(type_) = &member {
let type_: Type = type_.clone();
@ -136,10 +136,10 @@ impl<'a> FromAst<'a, leo_ast::CircuitMemberAccessExpression> for CircuitAccessEx
} else if circuit.is_input_pseudo_circuit() {
// add new member to implicit input
if let Some(expected_type) = expected_type.map(PartialType::full).flatten() {
circuit
.members
.borrow_mut()
.insert(value.name.name.clone(), CircuitMember::Variable(expected_type.clone()));
circuit.members.borrow_mut().insert(
value.name.name.to_string(),
CircuitMember::Variable(expected_type.clone()),
);
} else {
return Err(AsgConvertError::input_ref_needs_type(
&circuit.name.borrow().name,
@ -192,7 +192,7 @@ impl<'a> FromAst<'a, leo_ast::CircuitStaticFunctionAccessExpression> for Circuit
));
}
if let Some(CircuitMember::Function(_)) = circuit.members.borrow().get(&value.name.name) {
if let Some(CircuitMember::Function(_)) = circuit.members.borrow().get(value.name.name.as_ref()) {
// okay
} else {
return Err(AsgConvertError::unresolved_circuit_member(

View File

@ -99,10 +99,10 @@ impl<'a> FromAst<'a, leo_ast::CircuitInitExpression> for CircuitInitExpression<'
));
}
}
let members: IndexMap<&String, (&Identifier, Option<&leo_ast::Expression>)> = value
let members: IndexMap<&str, (&Identifier, Option<&leo_ast::Expression>)> = value
.members
.iter()
.map(|x| (&x.identifier.name, (&x.identifier, x.expression.as_ref())))
.map(|x| (x.identifier.name.as_ref(), (&x.identifier, x.expression.as_ref())))
.collect();
let mut values: Vec<(Identifier, Cell<&'a Expression<'a>>)> = vec![];
@ -124,7 +124,7 @@ impl<'a> FromAst<'a, leo_ast::CircuitInitExpression> for CircuitInitExpression<'
} else {
continue;
};
if let Some((identifier, receiver)) = members.get(&name) {
if let Some((identifier, receiver)) = members.get(&**name) {
let received = if let Some(receiver) = *receiver {
<&Expression<'a>>::from_ast(scope, receiver, Some(type_.partial()))?
} else {

View File

@ -174,12 +174,12 @@ impl<'a> FromAst<'a, leo_ast::ValueExpression> for Constant<'a> {
Some(PartialType::Type(Type::Group)) => Constant {
parent: Cell::new(None),
span: Some(span.clone()),
value: ConstValue::Group(GroupValue::Single(value.to_string())),
value: ConstValue::Group(GroupValue::Single(value.clone())),
},
Some(PartialType::Type(Type::Address)) => Constant {
parent: Cell::new(None),
span: Some(span.clone()),
value: ConstValue::Address(value.to_string()),
value: ConstValue::Address(value.clone()),
},
Some(x) => return Err(AsgConvertError::unexpected_type(&x.to_string(), Some("unknown"), span)),
},
@ -213,10 +213,10 @@ impl<'a> Into<leo_ast::ValueExpression> for &Constant<'a> {
leo_ast::ValueExpression::Address(value.clone(), self.span.clone().unwrap_or_default())
}
ConstValue::Boolean(value) => {
leo_ast::ValueExpression::Boolean(value.to_string(), self.span.clone().unwrap_or_default())
leo_ast::ValueExpression::Boolean(value.to_string().into(), self.span.clone().unwrap_or_default())
}
ConstValue::Field(value) => {
leo_ast::ValueExpression::Field(value.to_string(), self.span.clone().unwrap_or_default())
leo_ast::ValueExpression::Field(value.to_string().into(), self.span.clone().unwrap_or_default())
}
ConstValue::Group(value) => leo_ast::ValueExpression::Group(Box::new(match value {
GroupValue::Single(single) => {
@ -230,7 +230,7 @@ impl<'a> Into<leo_ast::ValueExpression> for &Constant<'a> {
})),
ConstValue::Int(int) => leo_ast::ValueExpression::Integer(
int.get_int_type(),
int.raw_value(),
int.raw_value().into(),
self.span.clone().unwrap_or_default(),
),
ConstValue::Tuple(_) => unimplemented!(),

View File

@ -109,7 +109,7 @@ impl<'a> Into<leo_ast::TupleAccessExpression> for &TupleAccessExpression<'a> {
leo_ast::TupleAccessExpression {
tuple: Box::new(self.tuple_ref.get().into()),
index: leo_ast::PositiveNumber {
value: self.index.to_string(),
value: self.index.to_string().into(),
},
span: self.span.clone().unwrap_or_default(),
}

View File

@ -136,7 +136,7 @@ impl<'a> FromAst<'a, leo_ast::Identifier> for &'a Expression<'a> {
value: &leo_ast::Identifier,
expected_type: Option<PartialType<'a>>,
) -> Result<&'a Expression<'a>, AsgConvertError> {
let variable = if value.name == "input" {
let variable = if value.name.as_ref() == "input" {
if let Some(function) = scope.resolve_current_function() {
if !function.has_input {
return Err(AsgConvertError::unresolved_reference(&value.name, &value.span));

View File

@ -40,7 +40,7 @@ impl<'a> Input<'a> {
fn make_header(scope: &'a Scope<'a>, name: &str) -> &'a Circuit<'a> {
scope.context.alloc_circuit(Circuit {
id: scope.context.get_id(),
name: RefCell::new(Identifier::new(name.to_string())),
name: RefCell::new(Identifier::new(name.into())),
members: RefCell::new(IndexMap::new()),
core_mapping: RefCell::new(None),
scope,
@ -69,7 +69,7 @@ impl<'a> Input<'a> {
let container_circuit = input_scope.context.alloc_circuit(Circuit {
id: scope.context.get_id(),
name: RefCell::new(Identifier::new(CONTAINER_PSEUDO_CIRCUIT.to_string())),
name: RefCell::new(Identifier::new(CONTAINER_PSEUDO_CIRCUIT.into())),
members: RefCell::new(container_members),
core_mapping: RefCell::new(None),
scope: input_scope,
@ -84,7 +84,7 @@ impl<'a> Input<'a> {
container_circuit,
container: input_scope.context.alloc_variable(RefCell::new(crate::InnerVariable {
id: scope.context.get_id(),
name: Identifier::new("input".to_string()),
name: Identifier::new("input".into()),
type_: Type::Circuit(container_circuit),
mutable: false,
const_: false,

View File

@ -69,7 +69,7 @@ impl<'a> Circuit<'a> {
let mut members = circuit.members.borrow_mut();
for member in value.members.iter() {
if let leo_ast::CircuitMember::CircuitVariable(name, type_) = member {
if members.contains_key(&name.name) {
if members.contains_key(name.name.as_ref()) {
return Err(AsgConvertError::redefined_circuit_member(
&value.circuit_name.name,
&name.name,
@ -77,7 +77,7 @@ impl<'a> Circuit<'a> {
));
}
members.insert(
name.name.clone(),
name.name.to_string(),
CircuitMember::Variable(new_scope.resolve_ast_type(type_)?),
);
}
@ -93,13 +93,13 @@ impl<'a> Circuit<'a> {
let new_scope = scope.make_subscope();
let circuits = scope.circuits.borrow();
let circuit = circuits.get(&value.circuit_name.name).unwrap();
let circuit = circuits.get(value.circuit_name.name.as_ref()).unwrap();
new_scope.circuit_self.replace(Some(circuit));
let mut members = circuit.members.borrow_mut();
for member in value.members.iter() {
if let leo_ast::CircuitMember::CircuitFunction(function) = member {
if members.contains_key(&function.identifier.name) {
if members.contains_key(function.identifier.name.as_ref()) {
return Err(AsgConvertError::redefined_circuit_member(
&value.circuit_name.name,
&function.identifier.name,
@ -111,7 +111,10 @@ impl<'a> Circuit<'a> {
if asg_function.is_test() {
return Err(AsgConvertError::circuit_test_function(&function.identifier.span));
}
members.insert(function.identifier.name.clone(), CircuitMember::Function(asg_function));
members.insert(
function.identifier.name.to_string(),
CircuitMember::Function(asg_function),
);
}
}
@ -126,7 +129,7 @@ impl<'a> Circuit<'a> {
let asg_function = match *self
.members
.borrow()
.get(&function.identifier.name)
.get(function.identifier.name.as_ref())
.expect("missing header for defined circuit function")
{
CircuitMember::Function(f) => f,
@ -148,7 +151,7 @@ impl<'a> Into<leo_ast::Circuit> for &Circuit<'a> {
.iter()
.map(|(name, member)| match &member {
CircuitMember::Variable(type_) => {
leo_ast::CircuitMember::CircuitVariable(Identifier::new(name.clone()), type_.into())
leo_ast::CircuitMember::CircuitVariable(Identifier::new((&**name).into()), type_.into())
}
CircuitMember::Function(func) => leo_ast::CircuitMember::CircuitFunction((*func).into()),
})

View File

@ -113,7 +113,7 @@ impl<'a> Function<'a> {
references: vec![],
assignments: vec![],
}));
arguments.insert(identifier.name.clone(), Cell::new(&*variable));
arguments.insert(identifier.name.to_string(), Cell::new(&*variable));
}
}
}
@ -144,7 +144,7 @@ impl<'a> Function<'a> {
let circuit = self.circuit.get();
let self_variable = self.scope.context.alloc_variable(RefCell::new(crate::InnerVariable {
id: self.scope.context.get_id(),
name: Identifier::new("self".to_string()),
name: Identifier::new("self".into()),
type_: Type::Circuit(circuit.as_ref().unwrap()),
mutable: self.qualifier == FunctionQualifier::MutSelfRef,
const_: false,
@ -186,7 +186,7 @@ impl<'a> Function<'a> {
}
pub fn is_test(&self) -> bool {
self.annotations.iter().any(|x| x.name.name == "test")
self.annotations.iter().any(|x| x.name.name.as_ref() == "test")
}
}

View File

@ -89,11 +89,11 @@ fn resolve_import_package(
) {
match package_or_packages {
PackageOrPackages::Package(package) => {
package_segments.push(package.name.name.clone());
package_segments.push(package.name.name.to_string());
resolve_import_package_access(output, package_segments, &package.access);
}
PackageOrPackages::Packages(packages) => {
package_segments.push(packages.name.name.clone());
package_segments.push(packages.name.name.to_string());
for access in packages.accesses.clone() {
resolve_import_package_access(output, package_segments.clone(), &access);
}
@ -120,14 +120,14 @@ fn resolve_import_package_access(
PackageAccess::Symbol(symbol) => {
let span = symbol.symbol.span.clone();
let symbol = if let Some(alias) = symbol.alias.as_ref() {
ImportSymbol::Alias(symbol.symbol.name.clone(), alias.name.clone())
ImportSymbol::Alias(symbol.symbol.name.to_string(), alias.name.to_string())
} else {
ImportSymbol::Direct(symbol.symbol.name.clone())
ImportSymbol::Direct(symbol.symbol.name.to_string())
};
output.push((package_segments, symbol, span));
}
PackageAccess::Multiple(packages) => {
package_segments.push(packages.name.name.clone());
package_segments.push(packages.name.name.to_string());
for subaccess in packages.accesses.iter() {
resolve_import_package_access(output, package_segments.clone(), &subaccess);
}
@ -258,7 +258,7 @@ impl<'a> Program<'a> {
assert_eq!(name.name, circuit.circuit_name.name);
let asg_circuit = Circuit::init(scope, circuit)?;
scope.circuits.borrow_mut().insert(name.name.clone(), asg_circuit);
scope.circuits.borrow_mut().insert(name.name.to_string(), asg_circuit);
}
// Second pass for circuit members.
@ -266,21 +266,21 @@ impl<'a> Program<'a> {
assert_eq!(name.name, circuit.circuit_name.name);
let asg_circuit = Circuit::init_member(scope, circuit)?;
scope.circuits.borrow_mut().insert(name.name.clone(), asg_circuit);
scope.circuits.borrow_mut().insert(name.name.to_string(), asg_circuit);
}
for (name, function) in program.functions.iter() {
assert_eq!(name.name, function.identifier.name);
let function = Function::init(scope, function)?;
scope.functions.borrow_mut().insert(name.name.clone(), function);
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)));
.for_each(|variable_name| assert!(name.contains(&variable_name.identifier.name.to_string())));
let gc = <&Statement<'a>>::from_ast(scope, global_const, None)?;
if let Statement::Definition(gc) = gc {
scope.global_consts.borrow_mut().insert(name.clone(), gc);
@ -293,7 +293,7 @@ impl<'a> Program<'a> {
global_const
.variable_names
.iter()
.for_each(|variable_name| assert!(name.contains(&variable_name.identifier.name)));
.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);
@ -302,21 +302,21 @@ impl<'a> Program<'a> {
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).unwrap();
let asg_function = *scope.functions.borrow().get(name.name.as_ref()).unwrap();
asg_function.fill_from_ast(function)?;
functions.insert(name.name.clone(), asg_function);
functions.insert(name.name.to_string(), 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).unwrap();
let asg_circuit = *scope.circuits.borrow().get(name.name.as_ref()).unwrap();
asg_circuit.fill_from_ast(circuit)?;
circuits.insert(name.name.clone(), asg_circuit);
circuits.insert(name.name.to_string(), asg_circuit);
}
Ok(Program {
@ -380,7 +380,7 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
for (_, program) in all_programs.into_iter() {
for (name, circuit) in program.circuits.iter() {
let identifier = format!("{}{}", identifiers.next().unwrap(), name);
circuit.name.borrow_mut().name = identifier.clone();
circuit.name.borrow_mut().name = identifier.clone().into();
all_circuits.insert(identifier, *circuit);
}
for (name, function) in program.functions.iter() {
@ -389,7 +389,7 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
} else {
format!("{}{}", identifiers.next().unwrap(), name)
};
function.name.borrow_mut().name = identifier.clone();
function.name.borrow_mut().name = identifier.clone().into();
all_functions.insert(identifier, *function);
}
@ -405,7 +405,7 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
.iter()
.map(|(module, _)| leo_ast::ImportStatement {
package_or_packages: leo_ast::PackageOrPackages::Package(leo_ast::Package {
name: Identifier::new(module.clone()),
name: Identifier::new(module.clone().into()),
access: leo_ast::PackageAccess::Star(Span::default()),
span: Default::default(),
}),

View File

@ -198,7 +198,7 @@ impl<'a> Scope<'a> {
.map(|x| self.resolve_ast_type(x))
.collect::<Result<Vec<_>, AsgConvertError>>()?,
),
Circuit(name) if name.name == "Self" => Type::Circuit(
Circuit(name) if name.name.as_ref() == "Self" => Type::Circuit(
self.resolve_circuit_self()
.ok_or_else(|| AsgConvertError::unresolved_circuit(&name.name, &name.span))?,
),

View File

@ -69,7 +69,7 @@ impl<'a> FromAst<'a, leo_ast::AssignStatement> for &'a Statement<'a> {
) -> Result<Self, AsgConvertError> {
let (name, span) = (&statement.assignee.identifier.name, &statement.assignee.identifier.span);
let variable = if name == "input" {
let variable = if name.as_ref() == "input" {
if let Some(function) = scope.resolve_current_function() {
if !function.has_input {
return Err(AsgConvertError::unresolved_reference(name, &span));
@ -188,7 +188,7 @@ impl<'a> FromAst<'a, leo_ast::AssignStatement> for &'a Statement<'a> {
let circuit = circuit;
let members = circuit.members.borrow();
let member = members.get(&name.name).ok_or_else(|| {
let member = members.get(name.name.as_ref()).ok_or_else(|| {
AsgConvertError::unresolved_circuit_member(
&circuit.name.borrow().name,
&name.name,
@ -251,7 +251,7 @@ impl<'a> Into<leo_ast::AssignStatement> for &AssignStatement<'a> {
AssignAccess::ArrayIndex(index) => AstAssigneeAccess::ArrayIndex(index.get().into()),
AssignAccess::Tuple(index) => AstAssigneeAccess::Tuple(
leo_ast::PositiveNumber {
value: index.to_string(),
value: index.to_string().into(),
},
self.span.clone().unwrap_or_default(),
),

View File

@ -44,7 +44,7 @@ impl<'a> DefinitionStatement<'a> {
self.variables
.iter()
.map(|variable| {
(variable.borrow().name.name.clone(), DefinitionStatement {
(variable.borrow().name.name.to_string(), DefinitionStatement {
parent: self.parent.clone(),
span: self.span.clone(),
variables: vec![variable],
@ -122,7 +122,7 @@ impl<'a> FromAst<'a, leo_ast::DefinitionStatement> for &'a Statement<'a> {
scope
.variables
.borrow_mut()
.insert(variable.borrow().name.name.clone(), *variable);
.insert(variable.borrow().name.name.to_string(), *variable);
}
let statement = scope

View File

@ -85,7 +85,7 @@ impl<'a> FromAst<'a, leo_ast::IterationStatement> for &'a Statement<'a> {
scope
.variables
.borrow_mut()
.insert(statement.variable.name.clone(), variable);
.insert(statement.variable.name.to_string(), variable);
let statement = scope.context.alloc_statement(Statement::Iteration(IterationStatement {
parent: Cell::new(None),

View File

@ -204,7 +204,9 @@ impl<'a> Into<leo_ast::Type> for &Type<'a> {
Integer(int_type) => leo_ast::Type::IntegerType(int_type.clone()),
Array(type_, len) => leo_ast::Type::Array(
Box::new(type_.as_ref().into()),
leo_ast::ArrayDimensions(vec![leo_ast::PositiveNumber { value: len.to_string() }]),
leo_ast::ArrayDimensions(vec![leo_ast::PositiveNumber {
value: len.to_string().into(),
}]),
),
Tuple(subtypes) => leo_ast::Type::Tuple(subtypes.iter().map(Into::into).collect()),
Circuit(circuit) => leo_ast::Type::Circuit(circuit.name.borrow().clone()),

View File

@ -41,6 +41,9 @@ version = "1.0"
[dependencies.thiserror]
version = "1.0"
[dependencies.tendril]
version = "0.4"
[dev-dependencies.criterion]
version = "0.3"

View File

@ -17,10 +17,12 @@
use crate::{Identifier, Span};
use serde::{Deserialize, Serialize};
use tendril::StrTendril;
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Annotation {
pub span: Span,
pub name: Identifier,
pub arguments: Vec<String>,
#[serde(with = "crate::common::vec_tendril_json")]
pub arguments: Vec<StrTendril>,
}

View File

@ -32,7 +32,7 @@ impl ArrayDimensions {
///
pub fn push_usize(&mut self, number: usize) {
let positive_number = PositiveNumber {
value: number.to_string(),
value: number.to_string().into(),
};
self.0.push(positive_number)

View File

@ -16,6 +16,7 @@
use crate::Span;
use leo_input::common::Identifier as InputIdentifier;
use tendril::StrTendril;
use crate::Node;
use serde::{
@ -41,7 +42,7 @@ use std::{
/// to reflect the new struct instantiation.
#[derive(Clone)]
pub struct Identifier {
pub name: String,
pub name: StrTendril,
pub span: Span,
}
@ -56,7 +57,7 @@ impl Node for Identifier {
}
impl Identifier {
pub fn new(name: String) -> Self {
pub fn new(name: StrTendril) -> Self {
Self {
name,
span: Span::default(),
@ -65,24 +66,16 @@ impl Identifier {
pub fn new_with_span(name: &str, span: Span) -> Self {
Self {
name: name.to_owned(),
name: name.into(),
span,
}
}
pub fn is_self_type(&self) -> bool {
self.name == "Self"
}
pub fn is_self(&self) -> bool {
self.is_self_type() || self.name == "self"
}
}
impl<'ast> From<InputIdentifier<'ast>> for Identifier {
fn from(identifier: InputIdentifier<'ast>) -> Self {
Self {
name: identifier.value,
name: identifier.value.into(),
span: Span::from(identifier.span),
}
}
@ -123,7 +116,7 @@ impl Serialize for Identifier {
// Load the struct elements into a BTreeMap (to preserve serialized ordering of keys).
let mut key: BTreeMap<String, String> = BTreeMap::new();
key.insert("name".to_string(), self.name.clone());
key.insert("name".to_string(), self.name.to_string());
key.insert("span".to_string(), to_json_string(&self.span)?);
// Convert the serialized object into a string for use as a key.
@ -164,7 +157,10 @@ impl<'de> Deserialize<'de> for Identifier {
None => return Err(E::custom("missing 'span' in serialized Identifier struct")),
};
Ok(Identifier { name, span })
Ok(Identifier {
name: name.into(),
span,
})
}
}

View File

@ -40,3 +40,7 @@ pub use span::*;
pub mod spread_or_expression;
pub use spread_or_expression::*;
pub mod tendril_json;
pub mod vec_tendril_json;

View File

@ -18,11 +18,13 @@ use leo_input::values::PositiveNumber as InputPositiveNumber;
use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
/// A number string guaranteed to be positive by the pest grammar.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
pub struct PositiveNumber {
pub value: String,
#[serde(with = "crate::common::tendril_json")]
pub value: StrTendril,
}
impl PositiveNumber {
@ -30,14 +32,16 @@ impl PositiveNumber {
/// Returns `true` if this number is zero.
///
pub fn is_zero(&self) -> bool {
self.value.eq("0")
self.value.as_ref().eq("0")
}
}
/// Create a new [`PositiveNumber`] from an [`InputPositiveNumber`] in a Leo input file.
impl<'ast> From<InputPositiveNumber<'ast>> for PositiveNumber {
fn from(array: InputPositiveNumber<'ast>) -> Self {
Self { value: array.value }
Self {
value: array.value.into(),
}
}
}

View File

@ -14,9 +14,10 @@
// 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 std::{fmt, rc::Rc};
use std::{fmt, sync::Arc};
use serde::{Deserialize, Serialize};
use tendril::StrTendril;
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct Span {
@ -24,7 +25,9 @@ pub struct Span {
pub line_stop: usize,
pub col_start: usize,
pub col_stop: usize,
pub path: Rc<String>,
pub path: Arc<String>,
#[serde(with = "crate::common::tendril_json")]
pub content: StrTendril,
}
impl fmt::Display for Span {
@ -51,7 +54,8 @@ impl<'ast> From<pest::Span<'ast>> for Span {
line_stop: end.0,
col_start: start.1,
col_stop: end.1,
path: Rc::new(String::new()),
path: Arc::new(String::new()),
content: span.as_str().into(),
}
}
}
@ -76,22 +80,40 @@ impl std::ops::Add for Span {
col_start: self.col_start.min(other.col_start),
col_stop: self.col_stop.max(other.col_stop),
path: self.path,
}
} else if self.line_start < other.line_stop {
Span {
line_start: self.line_start,
line_stop: other.line_stop,
col_start: self.col_start,
col_stop: other.col_stop,
path: self.path,
content: self.content,
}
} else {
Span {
line_start: other.line_start,
line_stop: self.line_stop,
col_start: other.col_start,
col_stop: self.col_stop,
path: self.path,
let mut new_content = vec![];
let self_lines = self.content.lines().collect::<Vec<_>>();
let other_lines = other.content.lines().collect::<Vec<_>>();
for line in self.line_start.min(other.line_start)..self.line_stop.max(other.line_stop) + 1 {
if line >= self.line_start && line <= self.line_stop {
new_content.push(self_lines.get(line - self.line_start).copied().unwrap_or_default());
} else if line >= other.line_start && line <= other.line_stop {
new_content.push(other_lines.get(line - other.line_start).copied().unwrap_or_default());
} else if new_content.last().map(|x| *x != "...").unwrap_or(true) {
new_content.push("...");
}
}
let new_content = new_content.join("\n").into();
if self.line_start < other.line_stop {
Span {
line_start: self.line_start,
line_stop: other.line_stop,
col_start: self.col_start,
col_stop: other.col_stop,
path: self.path,
content: new_content,
}
} else {
Span {
line_start: other.line_start,
line_stop: self.line_stop,
col_start: other.col_start,
col_stop: self.col_stop,
path: self.path,
content: new_content,
}
}
}
}

View File

@ -0,0 +1,26 @@
// 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 serde::{Deserialize, Deserializer, Serializer};
use tendril::StrTendril;
pub fn serialize<S: Serializer>(tendril: &StrTendril, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&tendril[..])
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<StrTendril, D::Error> {
Ok(String::deserialize(deserializer)?.into())
}

View File

@ -0,0 +1,34 @@
// 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 serde::{Deserialize, Deserializer, Serialize, Serializer};
use tendril::StrTendril;
#[allow(clippy::ptr_arg)]
pub fn serialize<S: Serializer>(tendril: &Vec<StrTendril>, serializer: S) -> Result<S::Ok, S::Error> {
tendril
.iter()
.map(|x| x.as_ref())
.collect::<Vec<_>>()
.serialize(serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<StrTendril>, D::Error> {
Ok(Vec::<String>::deserialize(deserializer)?
.into_iter()
.map(|x| x.into())
.collect())
}

View File

@ -16,12 +16,12 @@
use crate::{LeoError, Span};
use std::fmt;
use std::{fmt, sync::Arc};
pub const INDENT: &str = " ";
/// Formatted compiler error type
/// --> file.leo 2:8
/// --> file.leo: 2:8
/// |
/// 2 | let a = x;
/// | ^
@ -29,60 +29,30 @@ pub const INDENT: &str = " ";
/// = undefined value `x`
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct FormattedError {
/// File path where error occurred
pub path: Option<String>,
/// Line start number
pub line_start: usize,
/// Line end number
pub line_stop: usize,
/// Starting column
pub start: usize,
/// Ending column
pub end: usize,
/// Text of errored lines
pub text: Option<Vec<String>>,
/// Error explanation
pub col_start: usize,
pub col_stop: usize,
pub path: Arc<String>,
pub content: String,
pub message: String,
}
impl FormattedError {
pub fn new_from_span(message: String, span: &Span) -> Self {
Self {
path: None,
line_start: span.line_start,
line_stop: span.line_stop,
start: span.col_start,
end: span.col_stop,
text: None,
col_start: span.col_start,
col_stop: span.col_stop,
path: span.path.clone(),
content: span.content.to_string(),
message,
}
}
}
impl LeoError for FormattedError {
fn set_path(&mut self, path: &str, content: &[String]) {
self.path = Some(path.to_string());
if self.line_stop - 1 > content.len() {
self.text = Some(vec!["corrupt file".to_string()]);
return;
}
assert!(self.line_stop >= self.line_start);
// if self.line_stop == self.line_start {
// self.text = Some(vec![content[self.line_start - 1][self.start - 1..self.end - 1].to_string()]);
// } else {
self.text = Some(
content[self.line_start - 1..self.line_stop]
.iter()
.map(|x| x.to_string())
.collect(),
);
// }
}
fn get_path(&self) -> Option<&str> {
self.path.as_deref()
}
}
impl LeoError for FormattedError {}
fn underline(mut start: usize, mut end: usize) -> String {
if start > end {
@ -105,29 +75,26 @@ fn underline(mut start: usize, mut end: usize) -> String {
impl fmt::Display for FormattedError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let path = self.path.as_ref().map(|path| format!("{}:", path)).unwrap_or_default();
let underline = underline(self.start - 1, self.end - 1);
let underline = underline(self.col_start - 1, self.col_stop - 1);
write!(
f,
"{indent }--> {path} {line_start}:{start}\n\
"{indent }--> {path}: {line_start}:{start}\n\
{indent } |\n",
indent = INDENT,
path = path,
path = &*self.path,
line_start = self.line_start,
start = self.start,
start = self.col_start,
)?;
if let Some(lines) = &self.text {
for (line_no, line) in lines.iter().enumerate() {
writeln!(
f,
"{line_no:width$} | {text}",
width = INDENT.len(),
line_no = self.line_start + line_no,
text = line,
)?;
}
for (line_no, line) in self.content.lines().enumerate() {
writeln!(
f,
"{line_no:width$} | {text}",
width = INDENT.len(),
line_no = self.line_start + line_no,
text = line,
)?;
}
write!(
@ -151,12 +118,12 @@ impl std::error::Error for FormattedError {
#[test]
fn test_error() {
let err = FormattedError {
path: Some("file.leo".to_string()),
path: std::sync::Arc::new("file.leo".to_string()),
line_start: 2,
line_stop: 2,
start: 8,
end: 9,
text: Some(vec!["let a = x;".to_string()]),
col_start: 8,
col_stop: 9,
content: "let a = x;".into(),
message: "undefined value `x`".to_string(),
};

View File

@ -17,8 +17,4 @@
pub mod error;
pub use error::*;
pub trait LeoError {
fn get_path(&self) -> Option<&str>;
fn set_path(&mut self, path: &str, contents: &[String]);
}
pub trait LeoError {}

View File

@ -14,18 +14,24 @@
// 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 tendril::StrTendril;
use super::*;
use crate::GroupTuple;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ValueExpression {
// todo: deserialize values here
Address(String, Span),
Boolean(String, Span),
Field(String, Span),
Address(#[serde(with = "crate::common::tendril_json")] StrTendril, Span),
Boolean(#[serde(with = "crate::common::tendril_json")] StrTendril, Span),
Field(#[serde(with = "crate::common::tendril_json")] StrTendril, Span),
Group(Box<GroupValue>),
Implicit(String, Span),
Integer(IntegerType, String, Span),
Implicit(#[serde(with = "crate::common::tendril_json")] StrTendril, Span),
Integer(
IntegerType,
#[serde(with = "crate::common::tendril_json")] StrTendril,
Span,
),
}
impl fmt::Display for ValueExpression {

View File

@ -25,10 +25,11 @@ use leo_input::values::{
use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum GroupCoordinate {
Number(String, Span),
Number(#[serde(with = "crate::common::tendril_json")] StrTendril, Span),
SignHigh,
SignLow,
Inferred,
@ -61,7 +62,7 @@ impl<'ast> From<InputNumberValue<'ast>> for GroupCoordinate {
let value = number.to_string();
let span = Span::from(number.span().clone());
GroupCoordinate::Number(value, span)
GroupCoordinate::Number(value.into(), span)
}
}

View File

@ -23,10 +23,11 @@ use leo_input::values::{
use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum GroupValue {
Single(String, Span),
Single(#[serde(with = "crate::common::tendril_json")] StrTendril, Span),
Tuple(GroupTuple),
}
@ -51,7 +52,7 @@ impl<'ast> From<InputGroupValue<'ast>> for GroupValue {
let span = Span::from(ast_group.span);
match ast_group.value {
InputGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span),
InputGroupRepresentation::Single(number) => GroupValue::Single(number.to_string().into(), span),
InputGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)),
}
}

View File

@ -51,7 +51,7 @@ impl ImportSymbol {
pub fn star(span: &Span) -> Self {
Self {
symbol: Identifier {
name: "*".to_string(),
name: "*".into(),
span: span.clone(),
},
alias: None,
@ -60,6 +60,6 @@ impl ImportSymbol {
}
pub fn is_star(&self) -> bool {
self.symbol.name.eq("*")
self.symbol.name.as_ref().eq("*")
}
}

View File

@ -96,13 +96,13 @@ impl Input {
/// Returns the main function input value with the given `name`.
#[allow(clippy::ptr_arg)]
pub fn get(&self, name: &String) -> Option<Option<InputValue>> {
pub fn get(&self, name: &str) -> Option<Option<InputValue>> {
self.program_input.get(name)
}
/// Returns the constant input value with the given `name`.
#[allow(clippy::ptr_arg)]
pub fn get_constant(&self, name: &String) -> Option<Option<InputValue>> {
pub fn get_constant(&self, name: &str) -> Option<Option<InputValue>> {
self.program_input.get_constant(name)
}

View File

@ -74,12 +74,12 @@ impl ProgramInput {
/// Returns the main function input value with the given `name`
#[allow(clippy::ptr_arg)]
pub fn get(&self, name: &String) -> Option<Option<InputValue>> {
pub fn get(&self, name: &str) -> Option<Option<InputValue>> {
self.main.get(name)
}
#[allow(clippy::ptr_arg)]
pub fn get_constant(&self, name: &String) -> Option<Option<InputValue>> {
pub fn get_constant(&self, name: &str) -> Option<Option<InputValue>> {
self.constants.get(name)
}

View File

@ -171,7 +171,7 @@ impl Canonicalizer {
Expression::CircuitInit(circuit_init) => {
let mut name = circuit_init.name.clone();
if name.name == *"Self" {
if name.name.as_ref() == "Self" {
name = self.circuit_name.as_ref().unwrap().clone();
}

View File

@ -18,10 +18,11 @@ use crate::{Expression, Node, Span};
use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum FormattedStringPart {
Const(String),
Const(#[serde(with = "crate::common::tendril_json")] StrTendril),
Container,
}

View File

@ -24,10 +24,9 @@ use crate::{
OutputBytes,
OutputFile,
};
use indexmap::IndexMap;
pub use leo_asg::{new_context, AsgContext as Context, AsgContext};
use leo_asg::{Asg, AsgPass, FormattedError, Program as AsgProgram};
use leo_ast::{Input, LeoError, MainInput, Program as AstProgram};
use leo_ast::{Input, MainInput, Program as AstProgram};
use leo_input::LeoInputParser;
use leo_package::inputs::InputPairs;
use leo_parser::parse_ast;
@ -39,11 +38,9 @@ use snarkvm_r1cs::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
use sha2::{Digest, Sha256};
use std::{
cell::RefCell,
fs,
marker::PhantomData,
path::{Path, PathBuf},
rc::Rc,
};
thread_local! {
@ -68,7 +65,6 @@ pub struct Compiler<'a, F: PrimeField, G: GroupType<F>> {
program_input: Input,
context: AsgContext<'a>,
asg: Option<AsgProgram<'a>>,
file_contents: RefCell<IndexMap<String, Rc<Vec<String>>>>,
options: CompilerOptions,
_engine: PhantomData<F>,
_group: PhantomData<G>,
@ -93,7 +89,6 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
asg: None,
context,
options: CompilerOptions::default(),
file_contents: RefCell::new(IndexMap::new()),
_engine: PhantomData,
_group: PhantomData,
}
@ -200,20 +195,6 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
Ok(())
}
fn resolve_content(&self, path: &str) -> Result<Rc<Vec<String>>, CompilerError> {
let mut file_contents = self.file_contents.borrow_mut();
if file_contents.contains_key(path) {
// using this pattern because of mutable reference in branch below
Ok(file_contents.get(path).unwrap().clone())
} else {
let content = fs::read_to_string(path).map_err(|e| CompilerError::FileReadError(PathBuf::from(path), e))?;
let content = Rc::new(content.lines().map(|x| x.to_string()).collect::<Vec<String>>());
file_contents.insert(path.to_string(), content);
Ok(file_contents.get(path).unwrap().clone())
}
}
///
/// Parses and stores the main program file, constructs a syntax tree, and generates a program.
///
@ -224,31 +205,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
let content = fs::read_to_string(&self.main_file_path)
.map_err(|e| CompilerError::FileReadError(self.main_file_path.clone(), e))?;
self.parse_program_from_string(&content).map_err(|mut error| {
// Return a formatted error with file path and code text.
let path = match error.get_path().map(|x| x.to_string()) {
// Get the file path if it exists
Some(path) => path,
// If a file path does not exist, then insert the main file path.
None => match self.main_file_path.clone().into_os_string().into_string() {
Err(e) => return CompilerError::FileStringError(e),
Ok(path) => path,
},
};
// Resolve the code text using the file path.
let content = match self.resolve_content(&path) {
Err(e) => return e,
Ok(x) => x,
};
// Update the formatted error.
error.set_path(&path, &content[..]);
error
})
self.parse_program_from_string(&content)
}
///
@ -257,11 +214,6 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
///
pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<(), CompilerError> {
// Use the parser to construct the abstract syntax tree (ast).
let lines = program_string.lines().map(|x| x.to_string()).collect();
self.file_contents.borrow_mut().insert(
self.main_file_path.to_str().map(|x| x.to_string()).unwrap_or_default(),
Rc::new(lines),
);
let mut ast = parse_ast(self.main_file_path.to_str().unwrap_or_default(), program_string)?;
// Preform compiler optimization via canonicalizing AST if its enabled.
@ -313,28 +265,14 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
/// Synthesizes the circuit with program input to verify correctness.
///
pub fn compile_constraints<CS: ConstraintSystem<F>>(&self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
generate_constraints::<F, G, CS>(cs, &self.asg.as_ref().unwrap(), &self.program_input).map_err(|mut error| {
if let Some(path) = error.get_path().map(|x| x.to_string()) {
let content = match self.resolve_content(&path) {
Err(e) => return e,
Ok(x) => x,
};
error.set_path(&path, &content[..]);
}
error
})
generate_constraints::<F, G, CS>(cs, &self.asg.as_ref().unwrap(), &self.program_input)
}
///
/// Synthesizes the circuit for test functions with program input.
///
pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(u32, u32), CompilerError> {
generate_test_constraints::<F, G>(
&self.asg.as_ref().unwrap(),
input_pairs,
&self.main_file_path,
&self.output_directory,
)
generate_test_constraints::<F, G>(&self.asg.as_ref().unwrap(), input_pairs, &self.output_directory)
}
///

View File

@ -18,7 +18,7 @@
use crate::{errors::CompilerError, ConstrainedProgram, GroupType, OutputBytes, OutputFile};
use leo_asg::Program;
use leo_ast::{Input, LeoError};
use leo_ast::Input;
use leo_input::LeoInputParser;
use leo_package::inputs::InputPairs;
@ -54,7 +54,6 @@ pub fn generate_constraints<'a, F: PrimeField, G: GroupType<F>, CS: ConstraintSy
pub fn generate_test_constraints<'a, F: PrimeField, G: GroupType<F>>(
program: &Program<'a>,
input: InputPairs,
main_file_path: &Path,
output_directory: &Path,
) -> Result<(u32, u32), CompilerError> {
let mut resolved_program = ConstrainedProgram::<F, G>::new(program.clone());
@ -82,7 +81,7 @@ pub fn generate_test_constraints<'a, F: PrimeField, G: GroupType<F>>(
let input_file = function
.annotations
.iter()
.find(|x| x.name.name == "test")
.find(|x| x.name.name.as_ref() == "test")
.unwrap()
.arguments
.get(0);
@ -91,11 +90,11 @@ pub fn generate_test_constraints<'a, F: PrimeField, G: GroupType<F>>(
Some(file_id) => {
let file_name = file_id.clone();
output_file_name = file_name.clone();
output_file_name = file_name.to_string();
match input.pairs.get(&file_name) {
match input.pairs.get(file_name.as_ref()) {
Some(pair) => pair.to_owned(),
None => return Err(CompilerError::InvalidTestContext(file_name)),
None => return Err(CompilerError::InvalidTestContext(file_name.to_string())),
}
}
None => default.ok_or(CompilerError::NoTestInput)?,
@ -139,8 +138,7 @@ pub fn generate_test_constraints<'a, F: PrimeField, G: GroupType<F>>(
}
(false, _) => {
// Set file location of error
let mut error = result.unwrap_err();
error.set_path(main_file_path.to_str().unwrap_or_default(), &[]);
let error = result.unwrap_err();
tracing::error!("{} failed due to error\n\n{}\n", full_test_name, error);

View File

@ -88,30 +88,4 @@ pub enum CompilerError {
StatementError(#[from] StatementError),
}
impl LeoError for CompilerError {
fn get_path(&self) -> Option<&str> {
match self {
CompilerError::SyntaxError(error) => error.get_path(),
CompilerError::ImportError(error) => error.get_path(),
CompilerError::ImportParserError(error) => error.get_path(),
CompilerError::InputParserError(error) => error.get_path(),
CompilerError::FunctionError(error) => error.get_path(),
CompilerError::OutputStringError(error) => error.get_path(),
CompilerError::AsgConvertError(error) => error.get_path(),
_ => None,
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
CompilerError::SyntaxError(error) => error.set_path(path, contents),
CompilerError::ImportError(error) => error.set_path(path, contents),
CompilerError::ImportParserError(error) => error.set_path(path, contents),
CompilerError::InputParserError(error) => error.set_path(path, contents),
CompilerError::FunctionError(error) => error.set_path(path, contents),
CompilerError::OutputStringError(error) => error.set_path(path, contents),
CompilerError::AsgConvertError(error) => error.set_path(path, contents),
_ => {}
}
}
}
impl LeoError for CompilerError {}

View File

@ -26,21 +26,7 @@ pub enum ConsoleError {
Expression(#[from] ExpressionError),
}
impl LeoError for ConsoleError {
fn get_path(&self) -> Option<&str> {
match self {
ConsoleError::Error(error) => error.get_path(),
ConsoleError::Expression(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ConsoleError::Error(error) => error.set_path(path, contents),
ConsoleError::Expression(error) => error.set_path(path, contents),
}
}
}
impl LeoError for ConsoleError {}
impl ConsoleError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -45,33 +45,7 @@ pub enum ExpressionError {
ValueError(#[from] ValueError),
}
impl LeoError for ExpressionError {
fn get_path(&self) -> Option<&str> {
match self {
ExpressionError::AddressError(error) => error.get_path(),
ExpressionError::BooleanError(error) => error.get_path(),
ExpressionError::Error(error) => error.get_path(),
ExpressionError::FieldError(error) => error.get_path(),
ExpressionError::FunctionError(error) => error.get_path(),
ExpressionError::GroupError(error) => error.get_path(),
ExpressionError::IntegerError(error) => error.get_path(),
ExpressionError::ValueError(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ExpressionError::AddressError(error) => error.set_path(path, contents),
ExpressionError::BooleanError(error) => error.set_path(path, contents),
ExpressionError::Error(error) => error.set_path(path, contents),
ExpressionError::FieldError(error) => error.set_path(path, contents),
ExpressionError::FunctionError(error) => error.set_path(path, contents),
ExpressionError::GroupError(error) => error.set_path(path, contents),
ExpressionError::IntegerError(error) => error.set_path(path, contents),
ExpressionError::ValueError(error) => error.set_path(path, contents),
}
}
}
impl LeoError for ExpressionError {}
impl ExpressionError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -64,39 +64,7 @@ pub enum FunctionError {
ImportASGError(#[from] AsgConvertError),
}
impl LeoError for FunctionError {
fn get_path(&self) -> Option<&str> {
match self {
FunctionError::AddressError(error) => error.get_path(),
FunctionError::BooleanError(error) => error.get_path(),
FunctionError::ExpressionError(error) => error.get_path(),
FunctionError::Error(error) => error.get_path(),
FunctionError::FieldError(error) => error.get_path(),
FunctionError::GroupError(error) => error.get_path(),
FunctionError::IntegerError(error) => error.get_path(),
FunctionError::OutputStringError(error) => error.get_path(),
FunctionError::StatementError(error) => error.get_path(),
FunctionError::ValueError(error) => error.get_path(),
FunctionError::ImportASGError(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
FunctionError::AddressError(error) => error.set_path(path, contents),
FunctionError::BooleanError(error) => error.set_path(path, contents),
FunctionError::ExpressionError(error) => error.set_path(path, contents),
FunctionError::Error(error) => error.set_path(path, contents),
FunctionError::FieldError(error) => error.set_path(path, contents),
FunctionError::GroupError(error) => error.set_path(path, contents),
FunctionError::IntegerError(error) => error.set_path(path, contents),
FunctionError::OutputStringError(error) => error.set_path(path, contents),
FunctionError::StatementError(error) => error.set_path(path, contents),
FunctionError::ValueError(error) => error.set_path(path, contents),
FunctionError::ImportASGError(error) => error.set_path(path, contents),
}
}
}
impl LeoError for FunctionError {}
impl FunctionError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -22,19 +22,7 @@ pub enum ImportError {
Error(#[from] FormattedError),
}
impl LeoError for ImportError {
fn get_path(&self) -> Option<&str> {
match self {
ImportError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ImportError::Error(error) => error.set_path(path, contents),
}
}
}
impl LeoError for ImportError {}
impl ImportError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -30,23 +30,7 @@ pub enum OutputBytesError {
AsgConvertError(#[from] AsgConvertError),
}
impl LeoError for OutputBytesError {
fn get_path(&self) -> Option<&str> {
match self {
OutputBytesError::Error(error) => error.get_path(),
OutputBytesError::ValueError(error) => error.get_path(),
OutputBytesError::AsgConvertError(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
OutputBytesError::Error(error) => error.set_path(path, contents),
OutputBytesError::ValueError(error) => error.set_path(path, contents),
OutputBytesError::AsgConvertError(error) => error.set_path(path, contents),
}
}
}
impl LeoError for OutputBytesError {}
impl OutputBytesError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -42,31 +42,7 @@ pub enum StatementError {
ValueError(#[from] ValueError),
}
impl LeoError for StatementError {
fn get_path(&self) -> Option<&str> {
match self {
StatementError::AddressError(error) => error.get_path(),
StatementError::BooleanError(error) => error.get_path(),
StatementError::Error(error) => error.get_path(),
StatementError::ExpressionError(error) => error.get_path(),
StatementError::IntegerError(error) => error.get_path(),
StatementError::MacroError(error) => error.get_path(),
StatementError::ValueError(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
StatementError::AddressError(error) => error.set_path(path, contents),
StatementError::BooleanError(error) => error.set_path(path, contents),
StatementError::Error(error) => error.set_path(path, contents),
StatementError::ExpressionError(error) => error.set_path(path, contents),
StatementError::IntegerError(error) => error.set_path(path, contents),
StatementError::MacroError(error) => error.set_path(path, contents),
StatementError::ValueError(error) => error.set_path(path, contents),
}
}
}
impl LeoError for StatementError {}
impl StatementError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -24,19 +24,7 @@ pub enum AddressError {
Error(#[from] FormattedError),
}
impl LeoError for AddressError {
fn get_path(&self) -> Option<&str> {
match self {
AddressError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
AddressError::Error(error) => error.set_path(path, contents),
}
}
}
impl LeoError for AddressError {}
impl AddressError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -23,19 +23,7 @@ pub enum BooleanError {
Error(#[from] FormattedError),
}
impl LeoError for BooleanError {
fn get_path(&self) -> Option<&str> {
match self {
BooleanError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
BooleanError::Error(error) => error.set_path(path, contents),
}
}
}
impl LeoError for BooleanError {}
impl BooleanError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -23,19 +23,7 @@ pub enum FieldError {
Error(#[from] FormattedError),
}
impl LeoError for FieldError {
fn get_path(&self) -> Option<&str> {
match self {
FieldError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
FieldError::Error(error) => error.set_path(path, contents),
}
}
}
impl LeoError for FieldError {}
impl FieldError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -23,19 +23,7 @@ pub enum GroupError {
Error(#[from] FormattedError),
}
impl LeoError for GroupError {
fn get_path(&self) -> Option<&str> {
match self {
GroupError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
GroupError::Error(error) => error.set_path(path, contents),
}
}
}
impl LeoError for GroupError {}
impl GroupError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -25,19 +25,7 @@ pub enum IntegerError {
Error(#[from] FormattedError),
}
impl LeoError for IntegerError {
fn get_path(&self) -> Option<&str> {
match self {
IntegerError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
IntegerError::Error(error) => error.set_path(path, contents),
}
}
}
impl LeoError for IntegerError {}
impl IntegerError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -38,29 +38,7 @@ pub enum ValueError {
IntegerError(#[from] IntegerError),
}
impl LeoError for ValueError {
fn get_path(&self) -> Option<&str> {
match self {
ValueError::AddressError(error) => error.get_path(),
ValueError::BooleanError(error) => error.get_path(),
ValueError::Error(error) => error.get_path(),
ValueError::FieldError(error) => error.get_path(),
ValueError::GroupError(error) => error.get_path(),
ValueError::IntegerError(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ValueError::AddressError(error) => error.set_path(path, contents),
ValueError::BooleanError(error) => error.set_path(path, contents),
ValueError::Error(error) => error.set_path(path, contents),
ValueError::FieldError(error) => error.set_path(path, contents),
ValueError::GroupError(error) => error.set_path(path, contents),
ValueError::IntegerError(error) => error.set_path(path, contents),
}
}
}
impl LeoError for ValueError {}
impl ValueError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -42,7 +42,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
// type checking is already done in asg
for (name, inner) in expr.values.iter() {
let target = members
.get(&name.name)
.get(name.name.as_ref())
.expect("illegal name in asg circuit init expression");
match target {
CircuitMember::Variable(_type_) => {

View File

@ -41,7 +41,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
span: &Span,
) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
Ok(match value {
ConstValue::Address(value) => ConstrainedValue::Address(Address::constant(value.clone(), span)?),
ConstValue::Address(value) => ConstrainedValue::Address(Address::constant(value.to_string(), span)?),
ConstValue::Boolean(value) => ConstrainedValue::Boolean(Boolean::Constant(*value)),
ConstValue::Field(value) => ConstrainedValue::Field(FieldType::constant(value.to_string(), span)?),
ConstValue::Group(value) => ConstrainedValue::Group(G::constant(value, span)?),

View File

@ -38,19 +38,19 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
// Create an identifier for each input variable
let registers_name = Identifier {
name: REGISTERS_VARIABLE_NAME.to_string(),
name: REGISTERS_VARIABLE_NAME.into(),
span: span.clone(),
};
let record_name = Identifier {
name: RECORD_VARIABLE_NAME.to_string(),
name: RECORD_VARIABLE_NAME.into(),
span: span.clone(),
};
let state_name = Identifier {
name: STATE_VARIABLE_NAME.to_string(),
name: STATE_VARIABLE_NAME.into(),
span: span.clone(),
};
let state_leaf_name = Identifier {
name: STATE_LEAF_VARIABLE_NAME.to_string(),
name: STATE_LEAF_VARIABLE_NAME.into(),
span: span.clone(),
};
@ -73,7 +73,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
let mut members = Vec::with_capacity(sections.len());
for (name, values) in sections {
let sub_circuit = match expected_type.members.borrow().get(&name.name) {
let sub_circuit = match expected_type.members.borrow().get(name.name.as_ref()) {
Some(CircuitMember::Variable(Type::Circuit(circuit))) => *circuit,
_ => panic!("illegal input type definition from asg"),
};

View File

@ -36,7 +36,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
// Allocate each section definition as a circuit member value
for (parameter, option) in section.into_iter() {
let section_members = expected_type.members.borrow();
let expected_type = match section_members.get(&parameter.variable.name) {
let expected_type = match section_members.get(parameter.variable.name.as_ref()) {
Some(CircuitMember::Variable(inner)) => inner,
_ => continue, // present, but unused
};

View File

@ -62,11 +62,15 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
let input_variable = input_variable.get().borrow();
let name = input_variable.name.name.clone();
let input_value = match (input_variable.const_, input.get(&name), input.get_constant(&name)) {
let input_value = match (
input_variable.const_,
input.get(&name),
input.get_constant(name.as_ref()),
) {
// If variable is in both [main] and [constants] sections - error.
(_, Some(_), Some(_)) => {
return Err(FunctionError::double_input_declaration(
name.clone(),
name.to_string(),
&function.span.clone().unwrap_or_default(),
));
}
@ -89,21 +93,21 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
// Function argument is const, input is not.
(true, Some(_), None) => {
return Err(FunctionError::expected_const_input(
name.clone(),
name.to_string(),
&function.span.clone().unwrap_or_default(),
));
}
// Input is const, function argument is not.
(false, None, Some(_)) => {
return Err(FunctionError::expected_non_const_input(
name.clone(),
name.to_string(),
&function.span.clone().unwrap_or_default(),
));
}
// When not found - Error out.
(_, _, _) => {
return Err(FunctionError::input_not_found(
name.clone(),
name.to_string(),
&function.span.clone().unwrap_or_default(),
));
}

View File

@ -56,7 +56,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> CoreCircuit<'a, F, G> for Blake2s {
mut arguments: Vec<ConstrainedValue<'a, F, G>>,
) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
assert_eq!(arguments.len(), 2); // asg enforced
assert!(function.name.borrow().name == "hash"); // asg enforced
assert!(function.name.borrow().name.as_ref() == "hash"); // asg enforced
assert!(target.is_none()); // asg enforced
let input = unwrap_argument(arguments.remove(1));
let seed = unwrap_argument(arguments.remove(0));

View File

@ -19,11 +19,13 @@ use snarkvm_gadgets::traits::utilities::{
int::{Int128, Int16, Int32, Int64, Int8},
uint::{UInt128, UInt16, UInt32, UInt64, UInt8},
};
use std::fmt::Debug;
use std::{convert::TryInto, fmt::Debug};
pub trait IntegerTrait: Sized + Clone + Debug {
fn get_value(&self) -> Option<String>;
fn get_index(&self) -> Option<usize>;
fn get_bits(&self) -> Vec<Boolean>;
}
@ -34,6 +36,10 @@ macro_rules! integer_trait_impl {
self.value.map(|num| num.to_string())
}
fn get_index(&self) -> Option<usize> {
self.value.map(|num| num.try_into().ok()).flatten()
}
fn get_bits(&self) -> Vec<Boolean> {
self.bits.clone()
}

View File

@ -5,15 +5,15 @@
"circuits": {},
"global_consts": {},
"functions": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\"}\"}": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(a: [group; (2, 1)]) {\\\"}\"}": {
"annotations": [],
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\"}\"}",
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(a: [group; (2, 1)]) {\\\"}\"}",
"input": [
{
"Variable": {
"identifier": "{\"name\":\"a\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":15,\\\"col_stop\\\":16,\\\"path\\\":\\\"\\\"}\"}",
"identifier": "{\"name\":\"a\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":15,\\\"col_stop\\\":16,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(a: [group; (2, 1)]) {\\\"}\"}",
"const_": false,
"mutable": false,
"mutable": true,
"type_": {
"Array": [
{
@ -38,7 +38,8 @@
"line_stop": 1,
"col_start": 15,
"col_stop": 16,
"path": ""
"path": "",
"content": "function main(a: [group; (2, 1)]) {"
}
}
}
@ -53,14 +54,15 @@
"declaration_type": "Let",
"variable_names": [
{
"mutable": false,
"identifier": "{\"name\":\"b\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\"}\"}",
"mutable": true,
"identifier": "{\"name\":\"b\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let b = [true; (6, 5, 4, 3, 2)];\\\"}\"}",
"span": {
"line_start": 2,
"line_stop": 2,
"col_start": 7,
"col_stop": 8,
"path": ""
"path": "",
"content": " let b = [true; (6, 5, 4, 3, 2)];"
}
}
],
@ -84,7 +86,8 @@
"line_stop": 2,
"col_start": 12,
"col_stop": 16,
"path": ""
"path": "",
"content": " let b = [true; (6, 5, 4, 3, 2)];"
}
]
}
@ -99,7 +102,8 @@
"line_stop": 2,
"col_start": 11,
"col_stop": 34,
"path": ""
"path": "",
"content": " let b = [true; (6, 5, 4, 3, 2)];"
}
}
},
@ -113,7 +117,8 @@
"line_stop": 2,
"col_start": 11,
"col_stop": 34,
"path": ""
"path": "",
"content": " let b = [true; (6, 5, 4, 3, 2)];"
}
}
},
@ -127,7 +132,8 @@
"line_stop": 2,
"col_start": 11,
"col_stop": 34,
"path": ""
"path": "",
"content": " let b = [true; (6, 5, 4, 3, 2)];"
}
}
},
@ -141,7 +147,8 @@
"line_stop": 2,
"col_start": 11,
"col_stop": 34,
"path": ""
"path": "",
"content": " let b = [true; (6, 5, 4, 3, 2)];"
}
}
},
@ -155,7 +162,8 @@
"line_stop": 2,
"col_start": 11,
"col_stop": 34,
"path": ""
"path": "",
"content": " let b = [true; (6, 5, 4, 3, 2)];"
}
}
},
@ -164,7 +172,8 @@
"line_stop": 2,
"col_start": 3,
"col_stop": 34,
"path": ""
"path": "",
"content": " let b = [true; (6, 5, 4, 3, 2)];"
}
}
},
@ -173,14 +182,15 @@
"declaration_type": "Let",
"variable_names": [
{
"mutable": false,
"identifier": "{\"name\":\"c\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\"}\"}",
"mutable": true,
"identifier": "{\"name\":\"c\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let c: [u32; (1, 2)] = [0u32; (1, 2)];\\\"}\"}",
"span": {
"line_start": 3,
"line_stop": 3,
"col_start": 7,
"col_stop": 8,
"path": ""
"path": "",
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
}
}
],
@ -219,7 +229,8 @@
"line_stop": 3,
"col_start": 27,
"col_stop": 31,
"path": ""
"path": "",
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
}
]
}
@ -234,7 +245,8 @@
"line_stop": 3,
"col_start": 26,
"col_stop": 40,
"path": ""
"path": "",
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
}
}
},
@ -248,7 +260,8 @@
"line_stop": 3,
"col_start": 26,
"col_stop": 40,
"path": ""
"path": "",
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
}
}
},
@ -257,7 +270,8 @@
"line_stop": 3,
"col_start": 3,
"col_stop": 40,
"path": ""
"path": "",
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
}
}
},
@ -266,14 +280,15 @@
"declaration_type": "Let",
"variable_names": [
{
"mutable": false,
"identifier": "{\"name\":\"d\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\"}\"}",
"mutable": true,
"identifier": "{\"name\":\"d\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let d = [0i8; (1)];\\\"}\"}",
"span": {
"line_start": 4,
"line_stop": 4,
"col_start": 7,
"col_stop": 8,
"path": ""
"path": "",
"content": " let d = [0i8; (1)];"
}
}
],
@ -290,7 +305,8 @@
"line_stop": 4,
"col_start": 12,
"col_stop": 15,
"path": ""
"path": "",
"content": " let d = [0i8; (1)];"
}
]
}
@ -305,7 +321,8 @@
"line_stop": 4,
"col_start": 11,
"col_stop": 21,
"path": ""
"path": "",
"content": " let d = [0i8; (1)];"
}
}
},
@ -314,26 +331,29 @@
"line_stop": 4,
"col_start": 3,
"col_stop": 21,
"path": ""
"path": "",
"content": " let d = [0i8; (1)];"
}
}
}
],
"span": {
"line_start": 1,
"line_stop": 5,
"line_stop": 7,
"col_start": 35,
"col_stop": 2,
"path": ""
"path": "",
"content": "function main(a: [group; (2, 1)]) {\n...\n}"
}
},
"span": {
"line_start": 1,
"line_stop": 5,
"line_stop": 7,
"col_start": 1,
"col_stop": 2,
"path": ""
"path": "",
"content": "function main(a: [group; (2, 1)]) {\n...\n}\n\n\n\n"
}
}
}
}
}

View File

@ -1,207 +1,219 @@
{
"name": "",
"expected_input": [],
"imports": [],
"circuits": {
"{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\"}\"}": {
"circuit_name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\"}\"}",
"members": [
{
"CircuitVariable": [
"{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\"}\"}",
{
"IntegerType": "U32"
}
]
},
{
"CircuitFunction": {
"annotations": [],
"identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\"}\"}",
"input": [],
"output": {
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\"}\"}"
},
"block": {
"statements": [
{
"Definition": {
"declaration_type": "Let",
"variable_names": [
{
"mutable": false,
"identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\"}\"}",
"span": {
"line_start": 5,
"line_stop": 5,
"col_start": 9,
"col_stop": 12,
"path": ""
}
"name": "",
"expected_input": [],
"imports": [],
"circuits": {
"{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}": {
"circuit_name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}",
"members": [
{
"CircuitVariable": [
"{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x: u32\\\"}\"}",
{
"IntegerType": "U32"
}
]
},
{
"CircuitFunction": {
"annotations": [],
"identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function new() -> Self {\\\"}\"}",
"input": [],
"output": {
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}"
},
"block": {
"statements": [
{
"Definition": {
"declaration_type": "Let",
"variable_names": [
{
"mutable": true,
"identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let new: Self = Self {\\\"}\"}",
"span": {
"line_start": 5,
"line_stop": 5,
"col_start": 9,
"col_stop": 12,
"path": "",
"content": " let new: Self = Self {"
}
],
"type_": {
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\"}\"}"
},
"value": {
"CircuitInit": {
"name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\"}\"}",
"members": [
{
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\"}\"}",
"expression": {
"Value": {
"Integer": [
"U32",
"1",
{
"line_start": 6,
"line_stop": 6,
"col_start": 10,
"col_stop": 14,
"path": ""
}
]
}
}
],
"type_": {
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}"
},
"value": {
"CircuitInit": {
"name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}",
"members": [
{
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x: 1u32\\\"}\"}",
"expression": {
"Value": {
"Integer": [
"U32",
"1",
{
"line_start": 6,
"line_stop": 6,
"col_start": 10,
"col_stop": 14,
"path": "",
"content": " x: 1u32"
}
]
}
}
],
"span": {
"line_start": 5,
"line_stop": 7,
"col_start": 21,
"col_stop": 6,
"path": ""
}
}
},
"span": {
"line_start": 5,
"line_stop": 7,
"col_start": 5,
"col_stop": 6,
"path": ""
}
}
},
{
"Return": {
"expression": {
"Identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\"}\"}"
},
"span": {
"line_start": 9,
"line_stop": 9,
"col_start": 5,
"col_stop": 15,
"path": ""
}
}
}
],
"span": {
"line_start": 4,
"line_stop": 10,
"col_start": 26,
"col_stop": 4,
"path": ""
}
},
"span": {
"line_start": 4,
"line_stop": 10,
"col_start": 3,
"col_stop": 4,
"path": ""
}
}
}
]
}
},
"global_consts": {},
"functions": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\"}\"}": {
"annotations": [],
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\"}\"}",
"input": [],
"output": {
"Tuple": []
},
"block": {
"statements": [
{
"Definition": {
"declaration_type": "Let",
"variable_names": [
{
"mutable": false,
"identifier": "{\"name\":\"foo\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":7,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\"}\"}",
"span": {
"line_start": 14,
"line_stop": 14,
"col_start": 7,
"col_stop": 10,
"path": ""
}
}
],
"type_": {
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\"}\"}"
},
"value": {
"Call": {
"function": {
"CircuitStaticFunctionAccess": {
"circuit": {
"Identifier": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":18,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\"}\"}"
},
"name": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":23,\\\"col_stop\\\":26,\\\"path\\\":\\\"\\\"}\"}",
],
"span": {
"line_start": 14,
"line_stop": 14,
"col_start": 18,
"col_stop": 26,
"path": ""
"line_start": 5,
"line_stop": 7,
"col_start": 21,
"col_stop": 6,
"path": "",
"content": " let new: Self = Self {\n...\n };"
}
}
},
"arguments": [],
"span": {
"line_start": 14,
"line_stop": 14,
"col_start": 18,
"col_stop": 28,
"path": ""
"line_start": 5,
"line_stop": 7,
"col_start": 5,
"col_stop": 6,
"path": "",
"content": " let new: Self = Self {\n...\n };"
}
}
},
"span": {
"line_start": 14,
"line_stop": 14,
"col_start": 3,
"col_stop": 28,
"path": ""
{
"Return": {
"expression": {
"Identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return new\\\"}\"}"
},
"span": {
"line_start": 9,
"line_stop": 9,
"col_start": 5,
"col_stop": 15,
"path": "",
"content": " return new"
}
}
}
],
"span": {
"line_start": 4,
"line_stop": 10,
"col_start": 26,
"col_stop": 4,
"path": "",
"content": " function new() -> Self {\n...\n }"
}
},
"span": {
"line_start": 4,
"line_stop": 10,
"col_start": 3,
"col_stop": 4,
"path": "",
"content": " function new() -> Self {\n...\n }\n\n\n\n"
}
}
}
]
}
},
"global_consts": {},
"functions": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": {
"annotations": [],
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}",
"input": [],
"output": {
"Tuple": []
},
"block": {
"statements": [
{
"Definition": {
"declaration_type": "Let",
"variable_names": [
{
"mutable": true,
"identifier": "{\"name\":\"foo\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":7,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let foo: Foo = Foo::new();\\\"}\"}",
"span": {
"line_start": 14,
"line_stop": 14,
"col_start": 7,
"col_stop": 10,
"path": "",
"content": " let foo: Foo = Foo::new();"
}
}
],
"type_": {
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let foo: Foo = Foo::new();\\\"}\"}"
},
"value": {
"Call": {
"function": {
"CircuitStaticFunctionAccess": {
"circuit": {
"Identifier": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":18,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let foo: Foo = Foo::new();\\\"}\"}"
},
"name": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":23,\\\"col_stop\\\":26,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let foo: Foo = Foo::new();\\\"}\"}",
"span": {
"line_start": 14,
"line_stop": 14,
"col_start": 18,
"col_stop": 26,
"path": "",
"content": " let foo: Foo = Foo::new();"
}
}
},
"arguments": [],
"span": {
"line_start": 14,
"line_stop": 14,
"col_start": 18,
"col_stop": 28,
"path": "",
"content": " let foo: Foo = Foo::new();"
}
}
},
"span": {
"line_start": 14,
"line_stop": 14,
"col_start": 3,
"col_stop": 28,
"path": "",
"content": " let foo: Foo = Foo::new();"
}
}
],
"span": {
"line_start": 13,
"line_stop": 15,
"col_start": 17,
"col_stop": 2,
"path": ""
}
},
],
"span": {
"line_start": 13,
"line_stop": 15,
"col_start": 1,
"col_start": 17,
"col_stop": 2,
"path": ""
"path": "",
"content": "function main() {\n...\n}"
}
},
"span": {
"line_start": 13,
"line_stop": 15,
"col_start": 1,
"col_stop": 2,
"path": "",
"content": "function main() {\n...\n}"
}
}
}
}

View File

@ -1,129 +1,137 @@
{
"name": "",
"expected_input": [],
"imports": [],
"circuits": {},
"global_consts": {},
"functions": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\"}\"}": {
"annotations": [],
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\"}\"}",
"input": [],
"output": {
"Tuple": []
},
"block": {
"statements": [
{
"Definition": {
"declaration_type": "Let",
"variable_names": [
{
"mutable": true,
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":11,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\"}\"}",
"span": {
"name": "",
"expected_input": [],
"imports": [],
"circuits": {},
"global_consts": {},
"functions": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": {
"annotations": [],
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}",
"input": [],
"output": {
"Tuple": []
},
"block": {
"statements": [
{
"Definition": {
"declaration_type": "Let",
"variable_names": [
{
"mutable": true,
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let x = 10u32;\\\"}\"}",
"span": {
"line_start": 2,
"line_stop": 2,
"col_start": 7,
"col_stop": 8,
"path": "",
"content": " let x = 10u32;"
}
}
],
"type_": null,
"value": {
"Value": {
"Integer": [
"U32",
"10",
{
"line_start": 2,
"line_stop": 2,
"col_start": 7,
"col_stop": 12,
"path": ""
"col_start": 11,
"col_stop": 16,
"path": "",
"content": " let x = 10u32;"
}
}
],
"type_": null,
"value": {
"Value": {
"Integer": [
"U32",
"10",
{
"line_start": 2,
"line_stop": 2,
"col_start": 15,
"col_stop": 20,
"path": ""
}
]
}
},
"span": {
"line_start": 2,
"line_stop": 2,
"col_start": 3,
"col_stop": 20,
"path": ""
]
}
},
"span": {
"line_start": 2,
"line_stop": 2,
"col_start": 3,
"col_stop": 16,
"path": "",
"content": " let x = 10u32;"
}
},
{
"Assign": {
"operation": "Assign",
"assignee": {
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\"}\"}",
"accesses": [],
"span": {
"line_start": 3,
"line_stop": 3,
"col_start": 3,
"col_stop": 4,
"path": ""
}
},
"value": {
"Binary": {
"left": {
"Identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\"}\"}"
},
"right": {
"Value": {
"Implicit": [
"20",
{
"line_start": 3,
"line_stop": 3,
"col_start": 8,
"col_stop": 10,
"path": ""
}
]
}
},
"op": "Add",
"span": {
"line_start": 3,
"line_stop": 3,
"col_start": 3,
"col_stop": 10,
"path": ""
}
}
},
}
},
{
"Assign": {
"operation": "Assign",
"assignee": {
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x += 20;\\\"}\"}",
"accesses": [],
"span": {
"line_start": 3,
"line_stop": 3,
"col_start": 3,
"col_stop": 10,
"path": ""
"col_stop": 4,
"path": "",
"content": " x += 20;"
}
},
"value": {
"Binary": {
"left": {
"Identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x += 20;\\\"}\"}"
},
"right": {
"Value": {
"Implicit": [
"20",
{
"line_start": 3,
"line_stop": 3,
"col_start": 8,
"col_stop": 10,
"path": "",
"content": " x += 20;"
}
]
}
},
"op": "Add",
"span": {
"line_start": 3,
"line_stop": 3,
"col_start": 3,
"col_stop": 10,
"path": "",
"content": " x += 20;"
}
}
},
"span": {
"line_start": 3,
"line_stop": 3,
"col_start": 3,
"col_stop": 10,
"path": "",
"content": " x += 20;"
}
}
],
"span": {
"line_start": 1,
"line_stop": 4,
"col_start": 17,
"col_stop": 2,
"path": ""
}
},
],
"span": {
"line_start": 1,
"line_stop": 4,
"col_start": 1,
"col_start": 17,
"col_stop": 2,
"path": ""
"path": "",
"content": "function main() {\n...\n}"
}
},
"span": {
"line_start": 1,
"line_stop": 4,
"col_start": 1,
"col_stop": 2,
"path": "",
"content": "function main() {\n...\n}\n"
}
}
}
}

18
grammar/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "leo-abnf"
version = "1.2.3"
authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "ABNF to Markdown converter"
edition = "2018"
keywords = [
"aleo",
"cryptography",
"leo",
"programming-language",
"zero-knowledge",
"leo-abnf"
]
[dependencies]
abnf = "0.10.0"
anyhow = "1.0"

224
grammar/src/main.rs Normal file
View File

@ -0,0 +1,224 @@
// 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/>.
// ABNF PARSING RULES
//
// Header:
// ```abnf
// ; Introduction
// ; -------------
// ```
//
// Code block in docs (note double whitespace after colon):
// ```abnf
// ; code
// ; code
//```
//
// Rule:
// ```abnf
// address = "address"
// ```
//
// Line:
// ``` abnf
// ;;;;;;;;;
// ```
//
use abnf::types::{Node, Rule};
use anyhow::Result;
use std::collections::{HashMap, HashSet};
/// Processor's scope. Used when code block or definition starts or ends.
#[derive(Debug, Clone)]
enum Scope {
Free,
Code,
Definition(Rule),
}
/// Transforms abnf file into Markdown.
#[derive(Debug, Clone)]
struct Processor<'a> {
rules: HashMap<String, Rule>,
grammar: &'a str,
scope: Scope,
line: u32,
out: String,
}
impl<'a> Processor<'a> {
fn new(grammar: &'a str, abnf: Vec<Rule>) -> Processor<'a> {
// we need a hashmap to pull rules easily
let rules: HashMap<String, Rule> = abnf.into_iter().map(|rule| (rule.name().to_string(), rule)).collect();
Processor {
grammar,
line: 0,
out: String::new(),
rules,
scope: Scope::Free,
}
}
/// Main function for this struct.
/// Goes through each line and transforms it into proper markdown.
fn process(&mut self) -> Result<()> {
let mut lines = self.grammar.lines();
let mut prev = "";
while let Some(line) = lines.next() {
self.line += 1;
// code block in comment (not highlighted as abnf)
if line.starts_with("; ") {
self.enter_scope(Scope::Code)?;
self.append_str(&line[3..]);
// just comment. end of code block
} else if line.starts_with("; ") {
self.enter_scope(Scope::Free)?;
self.append_str(&line[2..]);
// horizontal rule - section separator
} else if line.starts_with(";;;;;;;;;;") {
self.enter_scope(Scope::Free)?;
self.append_str("\n--------\n");
// empty line in comment. end of code block
} else if line.starts_with(";") {
self.enter_scope(Scope::Free)?;
self.append_str("\n\n");
// just empty line. end of doc, start of definition
} else if line.len() == 0 {
self.enter_scope(Scope::Free)?;
self.append_str("");
// definition (may be multiline)
} else {
// if there's an equality sign and previous line was empty
if line.contains("=") && prev.len() == 0 {
let (def, _) = line.split_at(line.find("=").unwrap());
let def = def.trim();
// try to find rule matching definition or fail
let rule = self.rules.get(&def.to_string()).map(|rule| rule.clone()).unwrap();
self.enter_scope(Scope::Definition(rule))?;
}
self.append_str(line);
}
prev = line;
}
Ok(())
}
/// Append new line into output, add newline character.
fn append_str(&mut self, line: &str) {
self.out.push_str(line);
self.out.push_str("\n");
}
/// Enter new scope (definition or code block). Allows customizing
/// pre and post lines for each scope entered or exited.
fn enter_scope(&mut self, new_scope: Scope) -> Result<()> {
match (&self.scope, &new_scope) {
// exchange scopes between Free and Code
(Scope::Free, Scope::Code) => self.append_str("```"),
(Scope::Code, Scope::Free) => self.append_str("```"),
// exchange scopes between Free and Definition
(Scope::Free, Scope::Definition(rule)) => {
self.append_str(&format!("<a name=\"{}\"></a>", rule.name()));
self.append_str("```abnf");
}
(Scope::Definition(rule), Scope::Free) => {
let mut rules: Vec<String> = Vec::new();
parse_abnf_node(rule.node(), &mut rules);
// 1. leave only unique keys
// 2. map each rule into a link
// 3. join results as a list
// Note: GitHub only allows custom tags with 'user-content-' prefix
let keys = rules
.into_iter()
.collect::<HashSet<_>>()
.into_iter()
.map(|tag| format!("[{}](#user-content-{})", &tag, tag))
.collect::<Vec<String>>()
.join(", ");
self.append_str("```");
if keys.len() > 0 {
self.append_str(&format!("\nGo to: _{}_;\n", keys));
}
}
(_, _) => (),
};
self.scope = new_scope;
Ok(())
}
}
/// Recursively parse ABNF Node and fill sum vec with found rule names.
fn parse_abnf_node(node: &Node, sum: &mut Vec<String>) {
match node {
// these two are just vectors of rules
Node::Alternation(vec) | Node::Concatenation(vec) => {
for node in vec {
parse_abnf_node(node, sum);
}
}
Node::Group(node) | Node::Optional(node) => parse_abnf_node(node.as_ref(), sum),
// push rulename if it is known
Node::Rulename(name) => sum.push(name.clone()),
// do nothing for other nodes
_ => (),
}
}
fn main() -> Result<()> {
// Take Leo ABNF grammar file.
let grammar = include_str!("../abnf-grammar.txt");
// A. Coglio's proposal for %s syntax for case-sensitive statements has not been implemented
// in this library, so we need to remove all occurrences of %s in the grammar file.
// Link to this proposal: https://www.kestrel.edu/people/coglio/vstte18.pdf
let grammar = &str::replace(grammar, "%s", "");
// Parse ABNF to get list of all definitions.
let parsed = abnf::rulelist(grammar).map_err(|e| {
eprintln!("{}", &e);
anyhow::anyhow!(e)
})?;
// Init parser and run it. That's it.
let mut parser = Processor::new(grammar, parsed);
parser.process()?;
// Print result of conversion to STDOUT.
println!("{}", parser.out);
Ok(())
}

View File

@ -33,25 +33,7 @@ pub enum ImportParserError {
AsgConvertError(#[from] AsgConvertError),
}
impl LeoError for ImportParserError {
fn get_path(&self) -> Option<&str> {
match self {
ImportParserError::Error(error) => error.get_path(),
ImportParserError::SyntaxError(error) => error.get_path(),
ImportParserError::AsgConvertError(error) => error.get_path(),
ImportParserError::DeprecatedError(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ImportParserError::Error(error) => error.set_path(path, contents),
ImportParserError::SyntaxError(error) => error.set_path(path, contents),
ImportParserError::AsgConvertError(error) => error.set_path(path, contents),
ImportParserError::DeprecatedError(error) => error.set_path(path, contents),
}
}
}
impl LeoError for ImportParserError {}
impl Into<AsgConvertError> for ImportParserError {
fn into(self) -> AsgConvertError {

View File

@ -48,6 +48,9 @@ version = "0.3"
[dependencies.indexmap]
version = "1.6"
[dependencies.tendril]
version = "0.4"
[features]
default = [ ]
ci_skip = [ ]

View File

@ -28,19 +28,7 @@ impl DeprecatedError {
}
}
impl LeoError for DeprecatedError {
fn get_path(&self) -> Option<&str> {
match self {
DeprecatedError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
DeprecatedError::Error(error) => error.set_path(path, contents),
}
}
}
impl LeoError for DeprecatedError {}
impl DeprecatedError {
pub fn mut_function_input(mut span: Span) -> Self {

View File

@ -30,23 +30,7 @@ pub enum SyntaxError {
DeprecatedError(#[from] DeprecatedError),
}
impl LeoError for SyntaxError {
fn get_path(&self) -> Option<&str> {
match self {
SyntaxError::Error(error) => error.get_path(),
SyntaxError::TokenError(error) => error.get_path(),
SyntaxError::DeprecatedError(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
SyntaxError::Error(error) => error.set_path(path, contents),
SyntaxError::TokenError(error) => error.set_path(path, contents),
SyntaxError::DeprecatedError(error) => error.set_path(path, contents),
}
}
}
impl LeoError for SyntaxError {}
impl SyntaxError {
fn new_from_span(message: String, span: &Span) -> Self {
@ -112,4 +96,8 @@ impl SyntaxError {
span,
)
}
pub fn illegal_self_const(span: &Span) -> Self {
Self::new_from_span("cannot have const self".to_string(), span)
}
}

View File

@ -22,19 +22,7 @@ pub enum TokenError {
Error(#[from] FormattedError),
}
impl LeoError for TokenError {
fn get_path(&self) -> Option<&str> {
match self {
TokenError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
TokenError::Error(error) => error.set_path(path, contents),
}
}
}
impl LeoError for TokenError {}
impl TokenError {
fn new_from_span(message: String, span: &Span) -> Self {

View File

@ -18,6 +18,7 @@ use std::unimplemented;
use crate::{tokenizer::*, SyntaxError, SyntaxResult, Token, KEYWORD_TOKENS};
use leo_ast::*;
use tendril::format_tendril;
/// Stores a program in tokenized format plus additional context.
/// May be converted into a [`Program`] AST by parsing all tokens.
@ -149,7 +150,7 @@ impl ParserContext {
span,
}) => {
*i -= 1;
GroupCoordinate::Number(format!("-{}", value), span.clone())
GroupCoordinate::Number(format_tendril!("-{}", value), span.clone())
}
_ => GroupCoordinate::SignLow,
},
@ -280,7 +281,7 @@ impl ParserContext {
pub fn expect_loose_identifier(&mut self) -> SyntaxResult<Identifier> {
if let Some(token) = self.eat_any(KEYWORD_TOKENS) {
return Ok(Identifier {
name: token.token.to_string(),
name: token.token.to_string().into(),
span: token.span,
});
}
@ -302,10 +303,6 @@ impl ParserContext {
span,
} = token
{
// if name.starts_with('_') {
// return Err(SyntaxError::invalid_ident_name(&name, &name[1..name.len()], &span));
// }
Ok(Identifier { name, span })
} else {
unimplemented!()

View File

@ -14,6 +14,8 @@
// 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 tendril::format_tendril;
use super::*;
const INT_TYPES: &[Token] = &[
@ -309,8 +311,7 @@ impl ParserContext {
/// Otherwise, tries to parse the next token using [`parse_cast_expression`].
///
pub fn parse_exponential_expression(&mut self) -> SyntaxResult<Expression> {
let mut exprs = vec![];
exprs.push(self.parse_cast_expression()?);
let mut exprs = vec![self.parse_cast_expression()?];
while self.eat(Token::Exp).is_some() {
exprs.push(self.parse_cast_expression()?);
}
@ -368,10 +369,17 @@ impl ParserContext {
// hack for const signed integer overflow issues
if matches!(operation, UnaryOperation::Negate) {
if let Expression::Value(ValueExpression::Integer(type_, value, span)) = inner {
inner = Expression::Value(ValueExpression::Integer(type_, format!("-{}", value), &op.span + &span));
inner = Expression::Value(ValueExpression::Integer(
type_,
format_tendril!("-{}", value),
&op.span + &span,
));
continue;
} else if let Expression::Value(ValueExpression::Implicit(value, span)) = inner {
inner = Expression::Value(ValueExpression::Implicit(format!("-{}", value), &op.span + &span));
inner = Expression::Value(ValueExpression::Implicit(
format_tendril!("-{}", value),
&op.span + &span,
));
continue;
}
}
@ -665,8 +673,8 @@ impl ParserContext {
None => Expression::Value(ValueExpression::Implicit(value, span)),
}
}
Token::True => Expression::Value(ValueExpression::Boolean("true".to_string(), span)),
Token::False => Expression::Value(ValueExpression::Boolean("false".to_string(), span)),
Token::True => Expression::Value(ValueExpression::Boolean("true".into(), span)),
Token::False => Expression::Value(ValueExpression::Boolean("false".into(), span)),
Token::AddressLit(value) => Expression::Value(ValueExpression::Address(value, span)),
Token::Address => {
self.expect(Token::LeftParen)?;
@ -696,7 +704,7 @@ impl ParserContext {
}
Token::BigSelf => {
let ident = Identifier {
name: token.to_string(),
name: token.to_string().into(),
span,
};
if !self.fuzzy_struct_state && self.peek()?.token == Token::LeftCurly {
@ -707,7 +715,7 @@ impl ParserContext {
}
Token::Input | Token::LittleSelf => {
let ident = Identifier {
name: token.to_string(),
name: token.to_string().into(),
span,
};
Expression::Identifier(ident)

View File

@ -14,6 +14,8 @@
// 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 tendril::format_tendril;
use crate::KEYWORD_TOKENS;
use super::*;
@ -43,7 +45,7 @@ impl ParserContext {
let (id, function) = self.parse_function_declaration()?;
functions.insert(id, function);
}
Token::Ident(ident) if ident == "test" => {
Token::Ident(ident) if ident.as_ref() == "test" => {
return Err(SyntaxError::DeprecatedError(DeprecatedError::test_function(
&token.span,
)));
@ -65,7 +67,7 @@ impl ParserContext {
Token::Import,
Token::Circuit,
Token::Function,
Token::Ident("test".to_string()),
Token::Ident("test".into()),
Token::At,
],
&token.span,
@ -89,7 +91,7 @@ impl ParserContext {
pub fn parse_annotation(&mut self) -> SyntaxResult<Annotation> {
let start = self.expect(Token::At)?;
let name = self.expect_ident()?;
if name.name == "context" {
if name.name.as_ref() == "context" {
return Err(SyntaxError::DeprecatedError(DeprecatedError::context_annotation(
&name.span,
)));
@ -200,25 +202,24 @@ impl ParserContext {
match &self.peek()?.token {
Token::Minus => {
let span = self.expect(Token::Minus)?;
base.name += "-";
base.span = base.span + span;
let next = self.expect_loose_identifier()?;
base.name += &next.name;
base.name = format_tendril!("{}-{}", base.name, next.name);
base.span = base.span + next.span;
}
Token::Int(_) => {
let (num, span) = self.eat_int().unwrap();
base.name += &num.value;
base.name = format_tendril!("{}{}", base.name, num.value);
base.span = base.span + span;
}
Token::Ident(_) => {
let next = self.expect_ident()?;
base.name += &next.name;
base.name = format_tendril!("{}{}", base.name, next.name);
base.span = base.span + next.span;
}
x if KEYWORD_TOKENS.contains(&x) => {
let next = self.expect_loose_identifier()?;
base.name += &next.name;
base.name = format_tendril!("{}{}", base.name, next.name);
base.span = base.span + next.span;
}
_ => break,
@ -226,7 +227,7 @@ impl ParserContext {
}
// Return an error if the package name contains a keyword.
if let Some(token) = KEYWORD_TOKENS.iter().find(|x| x.to_string() == base.name) {
if let Some(token) = KEYWORD_TOKENS.iter().find(|x| x.to_string() == base.name.as_ref()) {
return Err(SyntaxError::unexpected_str(token, "package name", &base.span));
}
@ -325,7 +326,7 @@ impl ParserContext {
if let Some(token) = self.eat(Token::Input) {
return Ok(FunctionInput::InputKeyword(InputKeyword {
identifier: Identifier {
name: token.token.to_string(),
name: token.token.to_string().into(),
span: token.span,
},
}));
@ -334,22 +335,25 @@ impl ParserContext {
let mutable = self.eat(Token::Mut);
let mut name = if let Some(token) = self.eat(Token::LittleSelf) {
Identifier {
name: token.token.to_string(),
name: token.token.to_string().into(),
span: token.span,
}
} else {
self.expect_ident()?
};
if name.name == "self" {
if name.name.as_ref() == "self" {
if let Some(mutable) = &mutable {
// Handle `mut self`.
name.span = &mutable.span + &name.span;
name.name = "mut self".to_string();
name.name = "mut self".to_string().into();
return Ok(FunctionInput::MutSelfKeyword(MutSelfKeyword { identifier: name }));
} else if let Some(const_) = &const_ {
// Handle `const self`.
name.span = &const_.span + &name.span;
name.name = "const self".to_string();
name.name = "const self".to_string().into();
return Ok(FunctionInput::ConstSelfKeyword(ConstSelfKeyword { identifier: name }));
}
// Handle `self`.
return Ok(FunctionInput::SelfKeyword(SelfKeyword { identifier: name }));
}
@ -416,7 +420,7 @@ impl ParserContext {
let variable_names = statement
.variable_names
.iter()
.map(|variable_name| variable_name.identifier.name.clone())
.map(|variable_name| variable_name.identifier.name.to_string())
.collect::<Vec<String>>()
.join(",");

View File

@ -37,16 +37,7 @@ pub type SyntaxResult<T> = Result<T, SyntaxError>;
/// Creates a new program from a given file path and source code text.
pub fn parse(path: &str, source: &str) -> SyntaxResult<Program> {
let mut tokens = ParserContext::new(crate::tokenize(path, source)?);
let mut tokens = ParserContext::new(crate::tokenize(path, source.into())?);
match tokens.parse_program() {
Ok(x) => Ok(x),
Err(mut e) => {
e.set_path(
path,
&source.lines().map(|x| x.to_string()).collect::<Vec<String>>()[..],
);
Err(e)
}
}
tokens.parse_program()
}

View File

@ -17,34 +17,35 @@
use crate::tokenizer::{FormattedStringPart, Token};
use leo_ast::Span;
use serde::{Deserialize, Serialize};
use tendril::StrTendril;
use std::fmt;
///
/// Returns a reference to bytes from the given input if the given string is equal to the bytes,
/// otherwise returns [`None`].
/// Returns the length of the given `wanted` string if the string can be eaten, otherwise returns [`None`].
/// A string can be eaten if its bytes are at the front of the given `input` array.
///
fn eat<'a>(input: &'a [u8], wanted: &str) -> Option<&'a [u8]> {
fn eat(input: &[u8], wanted: &str) -> Option<usize> {
let wanted = wanted.as_bytes();
if input.len() < wanted.len() {
return None;
}
if &input[0..wanted.len()] == wanted {
return Some(&input[wanted.len()..]);
return Some(wanted.len());
}
None
}
///
/// Returns a reference to the bytes of an identifier and the remaining bytes from the given input.
/// Returns [`None`] if the bytes do not represent an identifier.
/// Returns a new `StrTendril` string if an identifier can be eaten, otherwise returns [`None`].
/// An identifier can be eaten if its bytes are at the front of the given `input_tendril` string.
///
fn eat_identifier(input: &[u8]) -> Option<(&[u8], &[u8])> {
if input.is_empty() {
fn eat_identifier(input_tendril: &StrTendril) -> Option<StrTendril> {
if input_tendril.is_empty() {
return None;
}
let input = input_tendril[..].as_bytes();
if !input[0].is_ascii_alphabetic() {
// Allow _ at start.
return None;
}
@ -55,20 +56,21 @@ fn eat_identifier(input: &[u8]) -> Option<(&[u8], &[u8])> {
}
i += 1;
}
Some((&input[0..i], &input[i..]))
Some(input_tendril.subtendril(0, i as u32))
}
impl Token {
///
/// Returns a reference to the remaining bytes and the bytes of a number from the given input.
/// Returns [`None`] if the bytes do not represent a number.
/// Returns a tuple: [(integer length, integer token)] if an integer can be eaten, otherwise returns [`None`].
/// An integer can be eaten if its bytes are at the front of the given `input_tendril` string.
///
fn gobble_int(input: &[u8]) -> (&[u8], Option<Token>) {
if input.is_empty() {
return (input, None);
fn eat_integer(input_tendril: &StrTendril) -> (usize, Option<Token>) {
if input_tendril.is_empty() {
return (0, None);
}
let input = input_tendril[..].as_bytes();
if !input[0].is_ascii_digit() {
return (input, None);
return (0, None);
}
let mut i = 1;
let mut is_hex = false;
@ -88,22 +90,20 @@ impl Token {
i += 1;
}
(
&input[i..],
Some(Token::Int(String::from_utf8(input[0..i].to_vec()).unwrap_or_default())),
)
(i, Some(Token::Int(input_tendril.subtendril(0, i as u32))))
}
///
/// Returns a reference to the remaining bytes and the bytes of a [`Token`] from the given input.
/// Returns [`None`] if the bytes do not represent a token.
/// Returns a tuple: [(token length, token)] if the next token can be eaten, otherwise returns [`None`].
/// The next token can be eaten if the bytes at the front of the given `input_tendril` string can be scanned into a token.
///
pub(crate) fn gobble(input: &[u8]) -> (&[u8], Option<Token>) {
if input.is_empty() {
return (input, None);
pub(crate) fn eat(input_tendril: StrTendril) -> (usize, Option<Token>) {
if input_tendril.is_empty() {
return (0, None);
}
let input = input_tendril[..].as_bytes();
match input[0] {
x if x.is_ascii_whitespace() => return (&input[1..], None),
x if x.is_ascii_whitespace() => return (1, None),
b'"' => {
let mut i = 1;
let mut in_escape = false;
@ -126,7 +126,7 @@ impl Token {
}
if start < i {
segments.push(FormattedStringPart::Const(
String::from_utf8_lossy(&input[start..i]).to_string(),
input_tendril.subtendril(start as u32, (i - start) as u32),
));
}
segments.push(FormattedStringPart::Container);
@ -140,191 +140,176 @@ impl Token {
i += 1;
}
if i == input.len() {
return (input, None);
return (0, None);
}
if start < i {
segments.push(FormattedStringPart::Const(
String::from_utf8_lossy(&input[start..i]).to_string(),
input_tendril.subtendril(start as u32, (i - start) as u32),
));
}
return (&input[(i + 1)..], Some(Token::FormattedString(segments)));
return (i + 1, Some(Token::FormattedString(segments)));
}
x if x.is_ascii_digit() => {
return Self::gobble_int(input);
return Self::eat_integer(&input_tendril);
}
b'!' => {
if let Some(input) = eat(input, "!=") {
return (input, Some(Token::NotEq));
if let Some(len) = eat(input, "!=") {
return (len, Some(Token::NotEq));
}
return (&input[1..], Some(Token::Not));
return (1, Some(Token::Not));
}
b'?' => {
return (&input[1..], Some(Token::Question));
return (1, Some(Token::Question));
}
b'&' => {
if let Some(input) = eat(input, "&&") {
// if let Some(input) = eat(input, "=") {
// return (input, Some(Token::AndEq));
if let Some(len) = eat(input, "&&") {
// if let Some(inner_len) = eat(&input[len..], "=") {
// return (len + inner_len, Some(Token::AndEq));
// }
return (input, Some(Token::And));
return (len, Some(Token::And));
}
// else if let Some(input) = eat(input, "&=") {
// return (input, Some(Token::BitAndEq));
// else if let Some(len) = eat(input, "&=") {
// return (len, Some(Token::BitAndEq));
// }
// return (&input[1..], Some(Token::BitAnd));
// return (1, Some(Token::BitAnd));
}
b'(' => return (&input[1..], Some(Token::LeftParen)),
b')' => return (&input[1..], Some(Token::RightParen)),
b'(' => return (1, Some(Token::LeftParen)),
b')' => return (1, Some(Token::RightParen)),
b'_' => return (1, Some(Token::Underscore)),
b'*' => {
if let Some(input) = eat(input, "**") {
if let Some(input) = eat(input, "=") {
return (input, Some(Token::ExpEq));
if let Some(len) = eat(input, "**") {
if let Some(inner_len) = eat(&input[len..], "=") {
return (len + inner_len, Some(Token::ExpEq));
}
return (input, Some(Token::Exp));
} else if let Some(input) = eat(input, "*=") {
return (input, Some(Token::MulEq));
return (len, Some(Token::Exp));
} else if let Some(len) = eat(input, "*=") {
return (len, Some(Token::MulEq));
}
return (&input[1..], Some(Token::Mul));
return (1, Some(Token::Mul));
}
b'+' => {
if let Some(input) = eat(input, "+=") {
return (input, Some(Token::AddEq));
if let Some(len) = eat(input, "+=") {
return (len, Some(Token::AddEq));
}
return (&input[1..], Some(Token::Add));
return (1, Some(Token::Add));
}
b',' => return (&input[1..], Some(Token::Comma)),
b',' => return (1, Some(Token::Comma)),
b'-' => {
if let Some(input) = eat(input, "->") {
return (input, Some(Token::Arrow));
} else if let Some(input) = eat(input, "-=") {
return (input, Some(Token::MinusEq));
if let Some(len) = eat(input, "->") {
return (len, Some(Token::Arrow));
} else if let Some(len) = eat(input, "-=") {
return (len, Some(Token::MinusEq));
}
return (&input[1..], Some(Token::Minus));
return (1, Some(Token::Minus));
}
b'.' => {
if let Some(input) = eat(input, "...") {
return (input, Some(Token::DotDotDot));
} else if let Some(input) = eat(input, "..") {
return (input, Some(Token::DotDot));
if let Some(len) = eat(input, "...") {
return (len, Some(Token::DotDotDot));
} else if let Some(len) = eat(input, "..") {
return (len, Some(Token::DotDot));
}
return (&input[1..], Some(Token::Dot));
return (1, Some(Token::Dot));
}
b'/' => {
if eat(input, "//").is_some() {
let eol = input.iter().position(|x| *x == b'\n');
let (input, comment) = if let Some(eol) = eol {
(&input[(eol + 1)..], &input[..eol])
} else {
(&input[input.len()..input.len()], input)
};
return (
input,
Some(Token::CommentLine(String::from_utf8_lossy(comment).to_string())),
);
let len = if let Some(eol) = eol { eol + 1 } else { input.len() };
return (len, Some(Token::CommentLine(input_tendril.subtendril(0, len as u32))));
} else if eat(input, "/*").is_some() {
if input.is_empty() {
return (input, None);
return (0, None);
}
let eol = input.windows(2).skip(2).position(|x| x[0] == b'*' && x[1] == b'/');
let (input, comment) = if let Some(eol) = eol {
(&input[(eol + 4)..], &input[..eol + 4])
} else {
(&input[input.len()..input.len()], input)
};
return (
input,
Some(Token::CommentBlock(String::from_utf8_lossy(comment).to_string())),
);
} else if let Some(input) = eat(input, "/=") {
return (input, Some(Token::DivEq));
let len = if let Some(eol) = eol { eol + 4 } else { input.len() };
return (len, Some(Token::CommentBlock(input_tendril.subtendril(0, len as u32))));
} else if let Some(len) = eat(input, "/=") {
return (len, Some(Token::DivEq));
}
return (&input[1..], Some(Token::Div));
return (1, Some(Token::Div));
}
b':' => {
if let Some(input) = eat(input, "::") {
return (input, Some(Token::DoubleColon));
if let Some(len) = eat(input, "::") {
return (len, Some(Token::DoubleColon));
} else {
return (&input[1..], Some(Token::Colon));
return (1, Some(Token::Colon));
}
}
b';' => return (&input[1..], Some(Token::Semicolon)),
b';' => return (1, Some(Token::Semicolon)),
b'<' => {
if let Some(input) = eat(input, "<=") {
return (input, Some(Token::LtEq));
if let Some(len) = eat(input, "<=") {
return (len, Some(Token::LtEq));
}
// else if let Some(input) = eat(input, "<<") {
// if let Some(input) = eat(input, "=") {
// return (input, Some(Token::ShlEq));
// else if let Some(len) = eat(input, "<<") {
// if let Some(inner_len) = eat(&input[len..], "=") {
// return (len + inner_len, Some(Token::ShlEq));
// }
// return (input, Some(Token::Shl));
// return (len, Some(Token::Shl));
// }
return (&input[1..], Some(Token::Lt));
return (1, Some(Token::Lt));
}
b'>' => {
if let Some(input) = eat(input, ">=") {
return (input, Some(Token::GtEq));
if let Some(len) = eat(input, ">=") {
return (len, Some(Token::GtEq));
}
// else if let Some(input) = eat(input, ">>") {
// if let Some(input) = eat(input, "=") {
// return (input, Some(Token::ShrEq));
// } else if let Some(input) = eat(input, ">") {
// if let Some(input) = eat(input, "=") {
// return (input, Some(Token::ShrSignedEq));
// else if let Some(len) = eat(input, ">>") {
// if let Some(inner_len) = eat(&input[len..], "=") {
// return (len + inner_len, Some(Token::ShrEq));
// } else if let Some(inner_len) = eat(&input[len..], ">") {
// if let Some(eq_len) = eat(&input[len + inner_len..], "=") {
// return (len + inner_len + eq_len, Some(Token::ShrSignedEq));
// }
// return (input, Some(Token::ShrSigned));
// return (len + inner_len, Some(Token::ShrSigned));
// }
// return (input, Some(Token::Shr));
// return (len, Some(Token::Shr));
// }
return (&input[1..], Some(Token::Gt));
return (1, Some(Token::Gt));
}
b'=' => {
if let Some(input) = eat(input, "==") {
return (input, Some(Token::Eq));
if let Some(len) = eat(input, "==") {
return (len, Some(Token::Eq));
}
return (&input[1..], Some(Token::Assign));
return (1, Some(Token::Assign));
}
b'_' => return (&input[1..], Some(Token::Underscore)),
b'@' => return (&input[1..], Some(Token::At)),
b'[' => return (&input[1..], Some(Token::LeftSquare)),
b']' => return (&input[1..], Some(Token::RightSquare)),
b'{' => return (&input[1..], Some(Token::LeftCurly)),
b'}' => return (&input[1..], Some(Token::RightCurly)),
b'@' => return (1, Some(Token::At)),
b'[' => return (1, Some(Token::LeftSquare)),
b']' => return (1, Some(Token::RightSquare)),
b'{' => return (1, Some(Token::LeftCurly)),
b'}' => return (1, Some(Token::RightCurly)),
b'|' => {
if let Some(input) = eat(input, "||") {
// if let Some(input) = eat(input, "=") {
// return (input, Some(Token::OrEq));
if let Some(len) = eat(input, "||") {
// if let Some(inner_len) = eat(&input[len..], "=") {
// return (len + inner_len, Some(Token::OrEq));
// }
return (input, Some(Token::Or));
return (len, Some(Token::Or));
}
// else if let Some(input) = eat(input, "|=") {
// return (input, Some(Token::BitOrEq));
// else if let Some(len) = eat(input, "|=") {
// return (len, Some(Token::BitOrEq));
// }
// return (&input[1..], Some(Token::BitOr));
// return (1, Some(Token::BitOr));
}
// b'^' => {
// if let Some(input) = eat(input, "^=") {
// return (input, Some(Token::BitXorEq));
// if let Some(len) = eat(input, "^=") {
// return (len, Some(Token::BitXorEq));
// }
// return (&input[1..], Some(Token::BitXor));
// return (1, Some(Token::BitXor));
// }
// b'~' => return (&input[1..], Some(Token::BitNot)),
// b'~' => return (1, Some(Token::BitNot)),
// b'%' => {
// if let Some(input) = eat(input, "%=") {
// return (input, Some(Token::ModEq));
// if let Some(len) = eat(input, "%=") {
// return (len, Some(Token::ModEq));
// }
// return (&input[1..], Some(Token::Mod));
// return (1, Some(Token::Mod));
// }
_ => (),
}
if let Some((ident, input)) = eat_identifier(input) {
let ident = String::from_utf8_lossy(ident).to_string();
if let Some(ident) = eat_identifier(&input_tendril) {
return (
input,
ident.len(),
Some(match &*ident {
x if x.starts_with("aleo1")
&& x.chars().skip(5).all(|x| x.is_ascii_lowercase() || x.is_ascii_digit()) =>
{
Token::AddressLit(x.to_string())
Token::AddressLit(ident)
}
"address" => Token::Address,
"as" => Token::As,
@ -365,7 +350,7 @@ impl Token {
);
}
(input, None)
(0, None)
}
}

View File

@ -20,6 +20,8 @@
//! separated by whitespace.
pub(crate) mod token;
use std::sync::Arc;
pub(crate) use self::token::*;
pub(crate) mod lexer;
@ -27,31 +29,33 @@ pub(crate) use self::lexer::*;
use crate::TokenError;
use leo_ast::Span;
use std::rc::Rc;
use tendril::StrTendril;
/// Creates a new vector of spanned tokens from a given file path and source code text.
pub(crate) fn tokenize(path: &str, source: &str) -> Result<Vec<SpannedToken>, TokenError> {
let path = Rc::new(path.to_string());
let mut input = source.as_bytes();
let mut tokens = Vec::new();
pub(crate) fn tokenize(path: &str, input: StrTendril) -> Result<Vec<SpannedToken>, TokenError> {
let path = Arc::new(path.to_string());
let mut tokens = vec![];
let mut index = 0usize;
let mut line_no = 1usize;
let mut line_start = 0usize;
while !input.is_empty() {
match Token::gobble(input) {
(output, Some(token)) => {
while input.len() > index {
match Token::eat(input.subtendril(index as u32, (input.len() - index) as u32)) {
(token_len, Some(token)) => {
let mut span = Span {
line_start: line_no,
line_stop: line_no,
col_start: index - line_start + 1,
col_stop: index - line_start + (input.len() - output.len()) + 1,
col_stop: index - line_start + token_len + 1,
path: path.clone(),
content: input.subtendril(
line_start as u32,
input[line_start..].find('\n').unwrap_or(input.len() - line_start) as u32,
),
};
match &token {
Token::CommentLine(_) => {
line_no += 1;
line_start = index + (input.len() - output.len());
line_start = index + token_len;
}
Token::CommentBlock(block) => {
let line_ct = block.chars().filter(|x| *x == '\n').count();
@ -59,7 +63,7 @@ pub(crate) fn tokenize(path: &str, source: &str) -> Result<Vec<SpannedToken>, To
if line_ct > 0 {
let last_line_index = block.rfind('\n').unwrap();
line_start = index + last_line_index + 1;
span.col_stop = index + (input.len() - output.len()) - line_start + 1;
span.col_stop = index + token_len - line_start + 1;
}
span.line_stop = line_no;
}
@ -71,30 +75,29 @@ pub(crate) fn tokenize(path: &str, source: &str) -> Result<Vec<SpannedToken>, To
_ => (),
}
tokens.push(SpannedToken { token, span });
index += input.len() - output.len();
input = output;
index += token_len;
}
(output, None) => {
if output.is_empty() {
(token_len, None) => {
if token_len == 0 && index == input.len() {
break;
} else if output.len() == input.len() {
return Err(TokenError::unexpected_token(
&String::from_utf8_lossy(&[input[0]]),
&Span {
line_start: line_no,
line_stop: line_no,
col_start: index - line_start + 1,
col_stop: index - line_start + 2,
path,
},
));
} else if token_len == 0 {
return Err(TokenError::unexpected_token(&input[index..index + 1], &Span {
line_start: line_no,
line_stop: line_no,
col_start: index - line_start + 1,
col_stop: index - line_start + 2,
path,
content: input.subtendril(
line_start as u32,
input[line_start..].find('\n').unwrap_or_else(|| input.len()) as u32,
),
}));
}
index += input.len() - output.len();
if input[0] == b'\n' {
if input.as_bytes()[index] == b'\n' {
line_no += 1;
line_start = index;
line_start = index + token_len;
}
input = output;
index += token_len;
}
}
}
@ -214,19 +217,19 @@ mod tests {
?
// test
/* test */
//"#,
//"#
.into(),
)
.unwrap();
let mut output = String::new();
for SpannedToken { token, .. } in tokens.iter() {
output += &format!("{} ", &token.to_string());
output += &format!("{} ", token.to_string());
}
// & &= | |= ^ ^= ~ << <<= >> >>= >>> >>>= % %= ||= &&=
assert_eq!(
output,
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8 test_ident 12345 address as bool circuit const else false field for function group i128 i64 i32 i16 i8 if import in input let mut return static string test true u128 u64 u32 u16 u8 self Self console ! != && ( ) * ** **= *= + += , - -= -> _ . .. ... / /= : :: ; < <= = == > >= @ [ ] { { } } || ? // test
/* test */ //
"#
/* test */ // "#
);
}
@ -242,7 +245,7 @@ mod tests {
test */
test
"#;
let tokens = tokenize("test_path", raw).unwrap();
let tokens = tokenize("test_path", raw.into()).unwrap();
let mut line_indicies = vec![0];
for (i, c) in raw.chars().enumerate() {
if c == '\n' {

View File

@ -16,11 +16,12 @@
use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
/// Parts of a formatted string for logging to the console.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum FormattedStringPart {
Const(String),
Const(#[serde(with = "leo_ast::common::tendril_json")] StrTendril),
Container,
}
@ -38,14 +39,14 @@ impl fmt::Display for FormattedStringPart {
pub enum Token {
// Lexical Grammar
// Literals
CommentLine(String),
CommentBlock(String),
CommentLine(#[serde(with = "leo_ast::common::tendril_json")] StrTendril),
CommentBlock(#[serde(with = "leo_ast::common::tendril_json")] StrTendril),
FormattedString(Vec<FormattedStringPart>),
Ident(String),
Int(String),
Ident(#[serde(with = "leo_ast::common::tendril_json")] StrTendril),
Int(#[serde(with = "leo_ast::common::tendril_json")] StrTendril),
True,
False,
AddressLit(String),
AddressLit(#[serde(with = "leo_ast::common::tendril_json")] StrTendril),
At,
@ -198,7 +199,7 @@ impl fmt::Display for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Token::*;
match self {
CommentLine(s) => writeln!(f, "{}", s),
CommentLine(s) => write!(f, "{}", s),
CommentBlock(s) => write!(f, "{}", s),
FormattedString(parts) => {
// todo escapes

View File

@ -5,9 +5,9 @@
"circuits": {},
"global_consts": {},
"functions": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"test\\\"}\"}": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": {
"annotations": [],
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"test\\\"}\"}",
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"function main() {\\\"}\"}",
"input": [],
"output": null,
"block": {
@ -25,7 +25,8 @@
"line_stop": 2,
"col_start": 12,
"col_stop": 13,
"path": "test"
"path": "test",
"content": " return 1 + 1"
}
]
}
@ -39,7 +40,8 @@
"line_stop": 2,
"col_start": 16,
"col_stop": 17,
"path": "test"
"path": "test",
"content": " return 1 + 1"
}
]
}
@ -50,7 +52,8 @@
"line_stop": 2,
"col_start": 12,
"col_stop": 17,
"path": "test"
"path": "test",
"content": " return 1 + 1"
}
}
},
@ -59,7 +62,8 @@
"line_stop": 2,
"col_start": 5,
"col_stop": 17,
"path": "test"
"path": "test",
"content": " return 1 + 1"
}
}
}
@ -69,7 +73,8 @@
"line_stop": 3,
"col_start": 17,
"col_stop": 2,
"path": "test"
"path": "test",
"content": "function main() {\n...\n}"
}
},
"span": {
@ -77,7 +82,8 @@
"line_stop": 3,
"col_start": 1,
"col_stop": 2,
"path": "test"
"path": "test",
"content": "function main() {\n...\n}"
}
}
}

View File

@ -27,7 +27,7 @@ pub fn find_input(
) -> Result<InputValue, InputValueError> {
let matched_parameter = parameters
.iter()
.find(|(parameter, _value)| parameter.variable.name == name);
.find(|(parameter, _value)| parameter.variable.name.as_ref() == name);
match matched_parameter {
Some((_, Some(value))) => Ok(value.clone()),