Merge branch 'master' into feature/515-eliminate-const-vars

This commit is contained in:
Collin Chin 2021-02-17 22:06:12 -08:00 committed by GitHub
commit 9baa9388a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
157 changed files with 3004 additions and 2312 deletions

11
Cargo.lock generated
View File

@ -1289,6 +1289,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"thiserror", "thiserror",
"typed-arena",
"uuid", "uuid",
] ]
@ -3149,6 +3150,12 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "typed-arena"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.12.0" version = "1.12.0"
@ -3442,9 +3449,9 @@ dependencies = [
[[package]] [[package]]
name = "zip" name = "zip"
version = "0.5.9" version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2896475a242c41366941faa27264df2cb935185a92e059a004d0048feb2ac5" checksum = "5a8977234acab718eb2820494b2f96cbb16004c19dddf88b7445b27381450997"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"bzip2", "bzip2",

View File

@ -35,7 +35,7 @@ members = [
"input", "input",
"linter", "linter",
"package", "package",
"state" "state",
] ]
[dependencies.leo-ast] [dependencies.leo-ast]

View File

@ -44,5 +44,8 @@ features = [ "v4", "serde" ]
[dependencies.num-bigint] [dependencies.num-bigint]
version = "0.3" version = "0.3"
[dependencies.typed-arena]
version = "2.0"
[dev-dependencies.criterion] [dev-dependencies.criterion]
version = "0.3" version = "0.3"

View File

@ -25,8 +25,6 @@ use crate::{
Span, Span,
}; };
use std::sync::Arc;
pub struct ReturnPathReducer { pub struct ReturnPathReducer {
pub errors: Vec<(Span, String)>, pub errors: Vec<(Span, String)>,
} }
@ -48,14 +46,14 @@ impl Default for ReturnPathReducer {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
impl MonoidalReducerExpression<BoolAnd> for ReturnPathReducer { impl<'a> MonoidalReducerExpression<'a, BoolAnd> for ReturnPathReducer {
fn reduce_expression(&mut self, input: &Arc<Expression>, value: BoolAnd) -> BoolAnd { fn reduce_expression(&mut self, input: &'a Expression<'a>, value: BoolAnd) -> BoolAnd {
BoolAnd(false) BoolAnd(false)
} }
} }
#[allow(unused_variables)] #[allow(unused_variables)]
impl MonoidalReducerStatement<BoolAnd> for ReturnPathReducer { impl<'a> MonoidalReducerStatement<'a, BoolAnd> for ReturnPathReducer {
fn reduce_assign_access(&mut self, input: &AssignAccess, left: Option<BoolAnd>, right: Option<BoolAnd>) -> BoolAnd { fn reduce_assign_access(&mut self, input: &AssignAccess, left: Option<BoolAnd>, right: Option<BoolAnd>) -> BoolAnd {
BoolAnd(false) BoolAnd(false)
} }
@ -69,7 +67,7 @@ impl MonoidalReducerStatement<BoolAnd> for ReturnPathReducer {
BoolAnd(false) BoolAnd(false)
} else if let Some(index) = statements[..statements.len() - 1].iter().map(|x| x.0).position(|x| x) { } else if let Some(index) = statements[..statements.len() - 1].iter().map(|x| x.0).position(|x| x) {
self.record_error( self.record_error(
input.statements[index].span(), input.statements[index].get().span(),
"dead code due to unconditional early return".to_string(), "dead code due to unconditional early return".to_string(),
); );
BoolAnd(true) BoolAnd(true)

View File

@ -226,7 +226,7 @@ impl ConstInt {
} }
} }
pub fn get_type(&self) -> Type { pub fn get_type<'a>(&self) -> Type<'a> {
Type::Integer(self.get_int_type()) Type::Integer(self.get_int_type())
} }
@ -247,7 +247,7 @@ impl ConstInt {
} }
impl ConstValue { impl ConstValue {
pub fn get_type(&self) -> Option<Type> { pub fn get_type<'a>(&self) -> Option<Type<'a>> {
Some(match self { Some(match self {
ConstValue::Int(i) => i.get_type(), ConstValue::Int(i) => i.get_type(),
ConstValue::Group(_) => Type::Group, ConstValue::Group(_) => Type::Group,

View File

@ -17,56 +17,53 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use leo_ast::IntegerType; use leo_ast::IntegerType;
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct ArrayAccessExpression { pub struct ArrayAccessExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub array: Arc<Expression>, pub array: Cell<&'a Expression<'a>>,
pub index: Arc<Expression>, pub index: Cell<&'a Expression<'a>>,
} }
impl Node for ArrayAccessExpression { impl<'a> Node for ArrayAccessExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for ArrayAccessExpression { impl<'a> ExpressionNode<'a> for ArrayAccessExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.array.set_parent(Arc::downgrade(expr)); self.array.get().set_parent(expr);
self.index.set_parent(Arc::downgrade(expr)); self.index.get().set_parent(expr);
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
match self.array.get_type() { match self.array.get().get_type() {
Some(Type::Array(element, _)) => Some(*element), Some(Type::Array(element, _)) => Some(*element),
_ => None, _ => None,
} }
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
self.array.is_mut_ref() self.array.get().is_mut_ref()
} }
fn const_value(&self) -> Option<ConstValue> { fn const_value(&self) -> Option<ConstValue> {
let mut array = match self.array.const_value()? { let mut array = match self.array.get().const_value()? {
ConstValue::Array(values) => values, ConstValue::Array(values) => values,
_ => return None, _ => return None,
}; };
let const_index = match self.index.const_value()? { let const_index = match self.index.get().const_value()? {
ConstValue::Int(x) => x.to_usize()?, ConstValue::Int(x) => x.to_usize()?,
_ => return None, _ => return None,
}; };
@ -77,17 +74,17 @@ impl ExpressionNode for ArrayAccessExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.array.is_consty() self.array.get().is_consty()
} }
} }
impl FromAst<leo_ast::ArrayAccessExpression> for ArrayAccessExpression { impl<'a> FromAst<'a, leo_ast::ArrayAccessExpression> for ArrayAccessExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::ArrayAccessExpression, value: &leo_ast::ArrayAccessExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<ArrayAccessExpression, AsgConvertError> { ) -> Result<ArrayAccessExpression<'a>, AsgConvertError> {
let array = Arc::<Expression>::from_ast( let array = <&Expression<'a>>::from_ast(
scope, scope,
&*value.array, &*value.array,
Some(PartialType::Array(expected_type.map(Box::new), None)), Some(PartialType::Array(expected_type.map(Box::new), None)),
@ -103,7 +100,7 @@ impl FromAst<leo_ast::ArrayAccessExpression> for ArrayAccessExpression {
} }
} }
let index = Arc::<Expression>::from_ast( let index = <&Expression<'a>>::from_ast(
scope, scope,
&*value.index, &*value.index,
Some(PartialType::Integer(None, Some(IntegerType::U32))), Some(PartialType::Integer(None, Some(IntegerType::U32))),
@ -116,19 +113,19 @@ impl FromAst<leo_ast::ArrayAccessExpression> for ArrayAccessExpression {
} }
Ok(ArrayAccessExpression { Ok(ArrayAccessExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
array, array: Cell::new(array),
index, index: Cell::new(index),
}) })
} }
} }
impl Into<leo_ast::ArrayAccessExpression> for &ArrayAccessExpression { impl<'a> Into<leo_ast::ArrayAccessExpression> for &ArrayAccessExpression<'a> {
fn into(self) -> leo_ast::ArrayAccessExpression { fn into(self) -> leo_ast::ArrayAccessExpression {
leo_ast::ArrayAccessExpression { leo_ast::ArrayAccessExpression {
array: Box::new(self.array.as_ref().into()), array: Box::new(self.array.get().into()),
index: Box::new(self.index.as_ref().into()), index: Box::new(self.index.get().into()),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -16,40 +16,37 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct ArrayInitExpression { pub struct ArrayInitExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub element: Arc<Expression>, pub element: Cell<&'a Expression<'a>>,
pub len: usize, pub len: usize,
} }
impl Node for ArrayInitExpression { impl<'a> Node for ArrayInitExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for ArrayInitExpression { impl<'a> ExpressionNode<'a> for ArrayInitExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.element.set_parent(Arc::downgrade(expr)); self.element.get().set_parent(expr);
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
Some(Type::Array(Box::new(self.element.get_type()?), self.len)) Some(Type::Array(Box::new(self.element.get().get_type()?), self.len))
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
@ -62,16 +59,16 @@ impl ExpressionNode for ArrayInitExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.element.is_consty() self.element.get().is_consty()
} }
} }
impl FromAst<leo_ast::ArrayInitExpression> for ArrayInitExpression { impl<'a> FromAst<'a, leo_ast::ArrayInitExpression> for ArrayInitExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::ArrayInitExpression, value: &leo_ast::ArrayInitExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<ArrayInitExpression, AsgConvertError> { ) -> Result<ArrayInitExpression<'a>, AsgConvertError> {
let (mut expected_item, expected_len) = match expected_type { let (mut expected_item, expected_len) = match expected_type {
Some(PartialType::Array(item, dims)) => (item.map(|x| *x), dims), Some(PartialType::Array(item, dims)) => (item.map(|x| *x), dims),
None => (None, None), None => (None, None),
@ -130,17 +127,19 @@ impl FromAst<leo_ast::ArrayInitExpression> for ArrayInitExpression {
} }
} }
} }
let mut element = Some(Arc::<Expression>::from_ast(scope, &*value.element, expected_item)?); let mut element = Some(<&'a Expression<'a>>::from_ast(scope, &*value.element, expected_item)?);
let mut output = None; let mut output = None;
for dimension in dimensions.iter().rev().copied() { for dimension in dimensions.iter().rev().copied() {
output = Some(ArrayInitExpression { output = Some(ArrayInitExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
element: output element: Cell::new(
.map(Expression::ArrayInit) output
.map(Arc::new) .map(Expression::ArrayInit)
.unwrap_or_else(|| element.take().unwrap()), .map(|expr| &*scope.alloc_expression(expr))
.unwrap_or_else(|| element.take().unwrap()),
),
len: dimension, len: dimension,
}); });
} }
@ -148,10 +147,10 @@ impl FromAst<leo_ast::ArrayInitExpression> for ArrayInitExpression {
} }
} }
impl Into<leo_ast::ArrayInitExpression> for &ArrayInitExpression { impl<'a> Into<leo_ast::ArrayInitExpression> for &ArrayInitExpression<'a> {
fn into(self) -> leo_ast::ArrayInitExpression { fn into(self) -> leo_ast::ArrayInitExpression {
leo_ast::ArrayInitExpression { leo_ast::ArrayInitExpression {
element: Box::new(self.element.as_ref().into()), element: Box::new(self.element.get().into()),
dimensions: leo_ast::ArrayDimensions(vec![leo_ast::PositiveNumber { dimensions: leo_ast::ArrayDimensions(vec![leo_ast::PositiveNumber {
value: self.len.to_string(), value: self.len.to_string(),
}]), }]),

View File

@ -17,25 +17,22 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use leo_ast::SpreadOrExpression; use leo_ast::SpreadOrExpression;
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct ArrayInlineExpression { pub struct ArrayInlineExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub elements: Vec<(Arc<Expression>, bool)>, // bool = if spread pub elements: Vec<(Cell<&'a Expression<'a>>, bool)>, // bool = if spread
} }
impl ArrayInlineExpression { impl<'a> ArrayInlineExpression<'a> {
pub fn expanded_length(&self) -> usize { pub fn expanded_length(&self) -> usize {
self.elements self.elements
.iter() .iter()
.map(|(expr, is_spread)| { .map(|(expr, is_spread)| {
if *is_spread { if *is_spread {
match expr.get_type() { match expr.get().get_type() {
Some(Type::Array(_item, len)) => len, Some(Type::Array(_item, len)) => len,
_ => 0, _ => 0,
} }
@ -47,30 +44,30 @@ impl ArrayInlineExpression {
} }
} }
impl Node for ArrayInlineExpression { impl<'a> Node for ArrayInlineExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for ArrayInlineExpression { impl<'a> ExpressionNode<'a> for ArrayInlineExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.elements.iter().for_each(|(element, _)| { self.elements.iter().for_each(|(element, _)| {
element.set_parent(Arc::downgrade(expr)); element.get().set_parent(expr);
}) })
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
Some(Type::Array( Some(Type::Array(
Box::new(self.elements.first()?.0.get_type()?), Box::new(self.elements.first()?.0.get().get_type()?),
self.expanded_length(), self.expanded_length(),
)) ))
} }
@ -83,28 +80,28 @@ impl ExpressionNode for ArrayInlineExpression {
let mut const_values = vec![]; let mut const_values = vec![];
for (expr, spread) in self.elements.iter() { for (expr, spread) in self.elements.iter() {
if *spread { if *spread {
match expr.const_value()? { match expr.get().const_value()? {
ConstValue::Array(items) => const_values.extend(items), ConstValue::Array(items) => const_values.extend(items),
_ => return None, _ => return None,
} }
} else { } else {
const_values.push(expr.const_value()?); const_values.push(expr.get().const_value()?);
} }
} }
Some(ConstValue::Array(const_values)) Some(ConstValue::Array(const_values))
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.elements.iter().all(|x| x.0.is_consty()) self.elements.iter().all(|x| x.0.get().is_consty())
} }
} }
impl FromAst<leo_ast::ArrayInlineExpression> for ArrayInlineExpression { impl<'a> FromAst<'a, leo_ast::ArrayInlineExpression> for ArrayInlineExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::ArrayInlineExpression, value: &leo_ast::ArrayInlineExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<ArrayInlineExpression, AsgConvertError> { ) -> Result<ArrayInlineExpression<'a>, AsgConvertError> {
let (mut expected_item, expected_len) = match expected_type { let (mut expected_item, expected_len) = match expected_type {
Some(PartialType::Array(item, dims)) => (item.map(|x| *x), dims), Some(PartialType::Array(item, dims)) => (item.map(|x| *x), dims),
None => (None, None), None => (None, None),
@ -119,22 +116,22 @@ impl FromAst<leo_ast::ArrayInlineExpression> for ArrayInlineExpression {
let mut len = 0; let mut len = 0;
let output = ArrayInlineExpression { let output = ArrayInlineExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
elements: value elements: value
.elements .elements
.iter() .iter()
.map(|e| match e { .map(|e| match e {
SpreadOrExpression::Expression(e) => { SpreadOrExpression::Expression(e) => {
let expr = Arc::<Expression>::from_ast(scope, e, expected_item.clone())?; let expr = <&Expression<'a>>::from_ast(scope, e, expected_item.clone())?;
if expected_item.is_none() { if expected_item.is_none() {
expected_item = expr.get_type().map(Type::partial); expected_item = expr.get_type().map(Type::partial);
} }
len += 1; len += 1;
Ok((expr, false)) Ok((Cell::new(expr), false))
} }
SpreadOrExpression::Spread(e) => { SpreadOrExpression::Spread(e) => {
let expr = Arc::<Expression>::from_ast( let expr = <&Expression<'a>>::from_ast(
scope, scope,
e, e,
Some(PartialType::Array(expected_item.clone().map(Box::new), None)), Some(PartialType::Array(expected_item.clone().map(Box::new), None)),
@ -160,7 +157,7 @@ impl FromAst<leo_ast::ArrayInlineExpression> for ArrayInlineExpression {
)); ));
} }
} }
Ok((expr, true)) Ok((Cell::new(expr), true))
} }
}) })
.collect::<Result<Vec<_>, AsgConvertError>>()?, .collect::<Result<Vec<_>, AsgConvertError>>()?,
@ -178,14 +175,14 @@ impl FromAst<leo_ast::ArrayInlineExpression> for ArrayInlineExpression {
} }
} }
impl Into<leo_ast::ArrayInlineExpression> for &ArrayInlineExpression { impl<'a> Into<leo_ast::ArrayInlineExpression> for &ArrayInlineExpression<'a> {
fn into(self) -> leo_ast::ArrayInlineExpression { fn into(self) -> leo_ast::ArrayInlineExpression {
leo_ast::ArrayInlineExpression { leo_ast::ArrayInlineExpression {
elements: self elements: self
.elements .elements
.iter() .iter()
.map(|(element, spread)| { .map(|(element, spread)| {
let element = element.as_ref().into(); let element = element.get().into();
if *spread { if *spread {
SpreadOrExpression::Spread(element) SpreadOrExpression::Spread(element)
} else { } else {

View File

@ -17,57 +17,54 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use leo_ast::IntegerType; use leo_ast::IntegerType;
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct ArrayRangeAccessExpression { pub struct ArrayRangeAccessExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub array: Arc<Expression>, pub array: Cell<&'a Expression<'a>>,
pub left: Option<Arc<Expression>>, pub left: Cell<Option<&'a Expression<'a>>>,
pub right: Option<Arc<Expression>>, pub right: Cell<Option<&'a Expression<'a>>>,
} }
impl Node for ArrayRangeAccessExpression { impl<'a> Node for ArrayRangeAccessExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for ArrayRangeAccessExpression { impl<'a> ExpressionNode<'a> for ArrayRangeAccessExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.array.set_parent(Arc::downgrade(expr)); self.array.get().set_parent(expr);
self.array.enforce_parents(&self.array); self.array.get().enforce_parents(self.array.get());
if let Some(left) = self.left.as_ref() { if let Some(left) = self.left.get() {
left.set_parent(Arc::downgrade(expr)); left.set_parent(expr);
} }
if let Some(right) = self.right.as_ref() { if let Some(right) = self.right.get() {
right.set_parent(Arc::downgrade(expr)); right.set_parent(expr);
} }
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
let (element, array_len) = match self.array.get_type() { let (element, array_len) = match self.array.get().get_type() {
Some(Type::Array(element, len)) => (element, len), Some(Type::Array(element, len)) => (element, len),
_ => return None, _ => return None,
}; };
let const_left = match self.left.as_ref().map(|x| x.const_value()) { let const_left = match self.left.get().map(|x| x.const_value()) {
Some(Some(ConstValue::Int(x))) => x.to_usize()?, Some(Some(ConstValue::Int(x))) => x.to_usize()?,
None => 0, None => 0,
_ => return None, _ => return None,
}; };
let const_right = match self.right.as_ref().map(|x| x.const_value()) { let const_right = match self.right.get().map(|x| x.const_value()) {
Some(Some(ConstValue::Int(x))) => x.to_usize()?, Some(Some(ConstValue::Int(x))) => x.to_usize()?,
None => array_len, None => array_len,
_ => return None, _ => return None,
@ -80,20 +77,20 @@ impl ExpressionNode for ArrayRangeAccessExpression {
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
self.array.is_mut_ref() self.array.get().is_mut_ref()
} }
fn const_value(&self) -> Option<ConstValue> { fn const_value(&self) -> Option<ConstValue> {
let mut array = match self.array.const_value()? { let mut array = match self.array.get().const_value()? {
ConstValue::Array(values) => values, ConstValue::Array(values) => values,
_ => return None, _ => return None,
}; };
let const_left = match self.left.as_ref().map(|x| x.const_value()) { let const_left = match self.left.get().map(|x| x.const_value()) {
Some(Some(ConstValue::Int(x))) => x.to_usize()?, Some(Some(ConstValue::Int(x))) => x.to_usize()?,
None => 0, None => 0,
_ => return None, _ => return None,
}; };
let const_right = match self.right.as_ref().map(|x| x.const_value()) { let const_right = match self.right.get().map(|x| x.const_value()) {
Some(Some(ConstValue::Int(x))) => x.to_usize()?, Some(Some(ConstValue::Int(x))) => x.to_usize()?,
None => array.len(), None => array.len(),
_ => return None, _ => return None,
@ -106,16 +103,16 @@ impl ExpressionNode for ArrayRangeAccessExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.array.is_consty() self.array.get().is_consty()
} }
} }
impl FromAst<leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessExpression { impl<'a> FromAst<'a, leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::ArrayRangeAccessExpression, value: &leo_ast::ArrayRangeAccessExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<ArrayRangeAccessExpression, AsgConvertError> { ) -> Result<ArrayRangeAccessExpression<'a>, AsgConvertError> {
let expected_array = match expected_type { let expected_array = match expected_type {
Some(PartialType::Array(element, _len)) => Some(PartialType::Array(element, None)), Some(PartialType::Array(element, _len)) => Some(PartialType::Array(element, None)),
None => None, None => None,
@ -127,7 +124,7 @@ impl FromAst<leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessExpression
)); ));
} }
}; };
let array = Arc::<Expression>::from_ast(scope, &*value.array, expected_array)?; let array = <&Expression<'a>>::from_ast(scope, &*value.array, expected_array)?;
let array_type = array.get_type(); let array_type = array.get_type();
match array_type { match array_type {
Some(Type::Array(_, _)) => (), Some(Type::Array(_, _)) => (),
@ -143,14 +140,14 @@ impl FromAst<leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessExpression
.left .left
.as_deref() .as_deref()
.map(|left| { .map(|left| {
Arc::<Expression>::from_ast(scope, left, Some(PartialType::Integer(None, Some(IntegerType::U32)))) <&Expression<'a>>::from_ast(scope, left, Some(PartialType::Integer(None, Some(IntegerType::U32))))
}) })
.transpose()?; .transpose()?;
let right = value let right = value
.right .right
.as_deref() .as_deref()
.map(|right| { .map(|right| {
Arc::<Expression>::from_ast(scope, right, Some(PartialType::Integer(None, Some(IntegerType::U32)))) <&Expression<'a>>::from_ast(scope, right, Some(PartialType::Integer(None, Some(IntegerType::U32))))
}) })
.transpose()?; .transpose()?;
@ -169,21 +166,21 @@ impl FromAst<leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessExpression
} }
} }
Ok(ArrayRangeAccessExpression { Ok(ArrayRangeAccessExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
array, array: Cell::new(array),
left, left: Cell::new(left),
right, right: Cell::new(right),
}) })
} }
} }
impl Into<leo_ast::ArrayRangeAccessExpression> for &ArrayRangeAccessExpression { impl<'a> Into<leo_ast::ArrayRangeAccessExpression> for &ArrayRangeAccessExpression<'a> {
fn into(self) -> leo_ast::ArrayRangeAccessExpression { fn into(self) -> leo_ast::ArrayRangeAccessExpression {
leo_ast::ArrayRangeAccessExpression { leo_ast::ArrayRangeAccessExpression {
array: Box::new(self.array.as_ref().into()), array: Box::new(self.array.get().into()),
left: self.left.as_ref().map(|left| Box::new(left.as_ref().into())), left: self.left.get().map(|left| Box::new(left.into())),
right: self.right.as_ref().map(|right| Box::new(right.as_ref().into())), right: self.right.get().map(|right| Box::new(right.into())),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -17,44 +17,41 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
pub use leo_ast::{BinaryOperation, BinaryOperationClass}; pub use leo_ast::{BinaryOperation, BinaryOperationClass};
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct BinaryExpression { pub struct BinaryExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub operation: BinaryOperation, pub operation: BinaryOperation,
pub left: Arc<Expression>, pub left: Cell<&'a Expression<'a>>,
pub right: Arc<Expression>, pub right: Cell<&'a Expression<'a>>,
} }
impl Node for BinaryExpression { impl<'a> Node for BinaryExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for BinaryExpression { impl<'a> ExpressionNode<'a> for BinaryExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.left.set_parent(Arc::downgrade(expr)); self.left.get().set_parent(expr);
self.right.set_parent(Arc::downgrade(expr)); self.right.get().set_parent(expr);
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
match self.operation.class() { match self.operation.class() {
BinaryOperationClass::Boolean => Some(Type::Boolean), BinaryOperationClass::Boolean => Some(Type::Boolean),
BinaryOperationClass::Numeric => self.left.get_type(), BinaryOperationClass::Numeric => self.left.get().get_type(),
} }
} }
@ -64,8 +61,8 @@ impl ExpressionNode for BinaryExpression {
fn const_value(&self) -> Option<ConstValue> { fn const_value(&self) -> Option<ConstValue> {
use BinaryOperation::*; use BinaryOperation::*;
let left = self.left.const_value()?; let left = self.left.get().const_value()?;
let right = self.right.const_value()?; let right = self.right.get().const_value()?;
match (left, right) { match (left, right) {
(ConstValue::Int(left), ConstValue::Int(right)) => Some(match self.operation { (ConstValue::Int(left), ConstValue::Int(right)) => Some(match self.operation {
@ -110,16 +107,16 @@ impl ExpressionNode for BinaryExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.left.is_consty() && self.right.is_consty() self.left.get().is_consty() && self.right.get().is_consty()
} }
} }
impl FromAst<leo_ast::BinaryExpression> for BinaryExpression { impl<'a> FromAst<'a, leo_ast::BinaryExpression> for BinaryExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::BinaryExpression, value: &leo_ast::BinaryExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<BinaryExpression, AsgConvertError> { ) -> Result<BinaryExpression<'a>, AsgConvertError> {
let class = value.op.class(); let class = value.op.class();
let expected_type = match class { let expected_type = match class {
BinaryOperationClass::Boolean => match expected_type { BinaryOperationClass::Boolean => match expected_type {
@ -148,16 +145,16 @@ impl FromAst<leo_ast::BinaryExpression> for BinaryExpression {
}; };
// left // left
let (left, right) = match Arc::<Expression>::from_ast(scope, &*value.left, expected_type.clone()) { let (left, right) = match <&Expression<'a>>::from_ast(scope, &*value.left, expected_type.clone()) {
Ok(left) => { Ok(left) => {
if let Some(left_type) = left.get_type() { if let Some(left_type) = left.get_type() {
let right = Arc::<Expression>::from_ast(scope, &*value.right, Some(left_type.partial()))?; let right = <&Expression<'a>>::from_ast(scope, &*value.right, Some(left_type.partial()))?;
(left, right) (left, right)
} else { } else {
let right = Arc::<Expression>::from_ast(scope, &*value.right, expected_type)?; let right = <&Expression<'a>>::from_ast(scope, &*value.right, expected_type)?;
if let Some(right_type) = right.get_type() { if let Some(right_type) = right.get_type() {
( (
Arc::<Expression>::from_ast(scope, &*value.left, Some(right_type.partial()))?, <&Expression<'a>>::from_ast(scope, &*value.left, Some(right_type.partial()))?,
right, right,
) )
} else { } else {
@ -166,10 +163,10 @@ impl FromAst<leo_ast::BinaryExpression> for BinaryExpression {
} }
} }
Err(e) => { Err(e) => {
let right = Arc::<Expression>::from_ast(scope, &*value.right, expected_type)?; let right = <&Expression<'a>>::from_ast(scope, &*value.right, expected_type)?;
if let Some(right_type) = right.get_type() { if let Some(right_type) = right.get_type() {
( (
Arc::<Expression>::from_ast(scope, &*value.left, Some(right_type.partial()))?, <&Expression<'a>>::from_ast(scope, &*value.left, Some(right_type.partial()))?,
right, right,
) )
} else { } else {
@ -244,21 +241,21 @@ impl FromAst<leo_ast::BinaryExpression> for BinaryExpression {
(_, _) => (), (_, _) => (),
} }
Ok(BinaryExpression { Ok(BinaryExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
operation: value.op.clone(), operation: value.op.clone(),
left, left: Cell::new(left),
right, right: Cell::new(right),
}) })
} }
} }
impl Into<leo_ast::BinaryExpression> for &BinaryExpression { impl<'a> Into<leo_ast::BinaryExpression> for &BinaryExpression<'a> {
fn into(self) -> leo_ast::BinaryExpression { fn into(self) -> leo_ast::BinaryExpression {
leo_ast::BinaryExpression { leo_ast::BinaryExpression {
op: self.operation.clone(), op: self.operation.clone(),
left: Box::new(self.left.as_ref().into()), left: Box::new(self.left.get().into()),
right: Box::new(self.right.as_ref().into()), right: Box::new(self.right.get().into()),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -31,46 +31,43 @@ use crate::{
}; };
pub use leo_ast::{BinaryOperation, Node as AstNode}; pub use leo_ast::{BinaryOperation, Node as AstNode};
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct CallExpression { pub struct CallExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub function: Arc<Function>, pub function: Cell<&'a Function<'a>>,
pub target: Option<Arc<Expression>>, pub target: Cell<Option<&'a Expression<'a>>>,
pub arguments: Vec<Arc<Expression>>, pub arguments: Vec<Cell<&'a Expression<'a>>>,
} }
impl Node for CallExpression { impl<'a> Node for CallExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for CallExpression { impl<'a> ExpressionNode<'a> for CallExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
if let Some(target) = self.target.as_ref() { if let Some(target) = self.target.get() {
target.set_parent(Arc::downgrade(expr)); target.set_parent(expr);
} }
self.arguments.iter().for_each(|element| { self.arguments.iter().for_each(|element| {
element.set_parent(Arc::downgrade(expr)); element.get().set_parent(expr);
}) })
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
Some(self.function.output.clone().into()) Some(self.function.get().output.clone())
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
@ -83,21 +80,20 @@ impl ExpressionNode for CallExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.target.as_ref().map(|x| x.is_consty()).unwrap_or(true) && self.arguments.iter().all(|x| x.is_consty()) self.target.get().map(|x| x.is_consty()).unwrap_or(true) && self.arguments.iter().all(|x| x.get().is_consty())
} }
} }
impl FromAst<leo_ast::CallExpression> for CallExpression { impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::CallExpression, value: &leo_ast::CallExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<CallExpression, AsgConvertError> { ) -> Result<CallExpression<'a>, AsgConvertError> {
let (target, function) = match &*value.function { let (target, function) = match &*value.function {
leo_ast::Expression::Identifier(name) => ( leo_ast::Expression::Identifier(name) => (
None, None,
scope scope
.borrow()
.resolve_function(&name.name) .resolve_function(&name.name)
.ok_or_else(|| AsgConvertError::unresolved_function(&name.name, &name.span))?, .ok_or_else(|| AsgConvertError::unresolved_function(&name.name, &name.span))?,
), ),
@ -106,7 +102,7 @@ impl FromAst<leo_ast::CallExpression> for CallExpression {
name, name,
span, span,
}) => { }) => {
let target = Arc::<Expression>::from_ast(scope, &**ast_circuit, None)?; let target = <&Expression<'a>>::from_ast(scope, &**ast_circuit, None)?;
let circuit = match target.get_type() { let circuit = match target.get_type() {
Some(Type::Circuit(circuit)) => circuit, Some(Type::Circuit(circuit)) => circuit,
type_ => { type_ => {
@ -137,7 +133,7 @@ impl FromAst<leo_ast::CallExpression> for CallExpression {
&span, &span,
)); ));
} }
(Some(target), body.clone()) (Some(target), *body)
} }
CircuitMember::Variable(_) => { CircuitMember::Variable(_) => {
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span)); return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span));
@ -151,7 +147,6 @@ impl FromAst<leo_ast::CallExpression> for CallExpression {
}) => { }) => {
let circuit = if let leo_ast::Expression::Identifier(circuit_name) = &**ast_circuit { let circuit = if let leo_ast::Expression::Identifier(circuit_name) = &**ast_circuit {
scope scope
.borrow()
.resolve_circuit(&circuit_name.name) .resolve_circuit(&circuit_name.name)
.ok_or_else(|| AsgConvertError::unresolved_circuit(&circuit_name.name, &circuit_name.span))? .ok_or_else(|| AsgConvertError::unresolved_circuit(&circuit_name.name, &circuit_name.span))?
} else { } else {
@ -172,7 +167,7 @@ impl FromAst<leo_ast::CallExpression> for CallExpression {
&span, &span,
)); ));
} }
(None, body.clone()) (None, *body)
} }
CircuitMember::Variable(_) => { CircuitMember::Variable(_) => {
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span)); return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span));
@ -186,7 +181,7 @@ impl FromAst<leo_ast::CallExpression> for CallExpression {
} }
}; };
if let Some(expected) = expected_type { if let Some(expected) = expected_type {
let output: Type = function.output.clone().into(); let output: Type = function.output.clone();
if !expected.matches(&output) { if !expected.matches(&output) {
return Err(AsgConvertError::unexpected_type( return Err(AsgConvertError::unexpected_type(
&expected.to_string(), &expected.to_string(),
@ -207,46 +202,45 @@ impl FromAst<leo_ast::CallExpression> for CallExpression {
.arguments .arguments
.iter() .iter()
.zip(function.arguments.iter()) .zip(function.arguments.iter())
.map(|(expr, argument)| { .map(|(expr, (_, argument))| {
let argument = argument.borrow(); let argument = argument.get().borrow();
let converted = let converted = <&Expression<'a>>::from_ast(scope, expr, Some(argument.type_.clone().partial()))?;
Arc::<Expression>::from_ast(scope, expr, Some(argument.type_.clone().strong().partial()))?;
if argument.const_ && !converted.is_consty() { if argument.const_ && !converted.is_consty() {
return Err(AsgConvertError::unexpected_nonconst(&expr.span())); return Err(AsgConvertError::unexpected_nonconst(&expr.span()));
} }
Ok(converted) Ok(Cell::new(converted))
}) })
.collect::<Result<Vec<_>, AsgConvertError>>()?; .collect::<Result<Vec<_>, AsgConvertError>>()?;
Ok(CallExpression { Ok(CallExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
arguments, arguments,
function, function: Cell::new(function),
target, target: Cell::new(target),
}) })
} }
} }
impl Into<leo_ast::CallExpression> for &CallExpression { impl<'a> Into<leo_ast::CallExpression> for &CallExpression<'a> {
fn into(self) -> leo_ast::CallExpression { fn into(self) -> leo_ast::CallExpression {
let target_function = if let Some(target) = &self.target { let target_function = if let Some(target) = self.target.get() {
target.as_ref().into() target.into()
} else { } else {
let circuit = self.function.circuit.borrow().as_ref().map(|x| x.upgrade()).flatten(); let circuit = self.function.get().circuit.get();
if let Some(circuit) = circuit { if let Some(circuit) = circuit {
leo_ast::Expression::CircuitStaticFunctionAccess(leo_ast::CircuitStaticFunctionAccessExpression { leo_ast::Expression::CircuitStaticFunctionAccess(leo_ast::CircuitStaticFunctionAccessExpression {
circuit: Box::new(leo_ast::Expression::Identifier(circuit.name.borrow().clone())), circuit: Box::new(leo_ast::Expression::Identifier(circuit.name.borrow().clone())),
name: self.function.name.borrow().clone(), name: self.function.get().name.borrow().clone(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
}) })
} else { } else {
leo_ast::Expression::Identifier(self.function.name.borrow().clone()) leo_ast::Expression::Identifier(self.function.get().name.borrow().clone())
} }
}; };
leo_ast::CallExpression { leo_ast::CallExpression {
function: Box::new(target_function), function: Box::new(target_function),
arguments: self.arguments.iter().map(|arg| arg.as_ref().into()).collect(), arguments: self.arguments.iter().map(|arg| arg.get().into()).collect(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -18,7 +18,6 @@ use crate::{
AsgConvertError, AsgConvertError,
Circuit, Circuit,
CircuitMember, CircuitMember,
CircuitMemberBody,
ConstValue, ConstValue,
Expression, Expression,
ExpressionNode, ExpressionNode,
@ -31,56 +30,53 @@ use crate::{
Type, Type,
}; };
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct CircuitAccessExpression { pub struct CircuitAccessExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub circuit: Arc<Circuit>, pub circuit: Cell<&'a Circuit<'a>>,
pub target: Option<Arc<Expression>>, pub target: Cell<Option<&'a Expression<'a>>>,
pub member: Identifier, pub member: Identifier,
} }
impl Node for CircuitAccessExpression { impl<'a> Node for CircuitAccessExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for CircuitAccessExpression { impl<'a> ExpressionNode<'a> for CircuitAccessExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
if let Some(target) = self.target.as_ref() { if let Some(target) = self.target.get() {
target.set_parent(Arc::downgrade(expr)); target.set_parent(expr);
} }
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
if self.target.is_none() { if self.target.get().is_none() {
None // function target only for static None // function target only for static
} else { } else {
let members = self.circuit.members.borrow(); let members = self.circuit.get().members.borrow();
let member = members.get(&self.member.name)?; let member = members.get(&self.member.name)?;
match member { match member {
CircuitMember::Variable(type_) => Some(type_.clone().into()), CircuitMember::Variable(type_) => Some(type_.clone()),
CircuitMember::Function(_) => None, CircuitMember::Function(_) => None,
} }
} }
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
if let Some(target) = self.target.as_ref() { if let Some(target) = self.target.get() {
target.is_mut_ref() target.is_mut_ref()
} else { } else {
false false
@ -92,17 +88,17 @@ impl ExpressionNode for CircuitAccessExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.target.as_ref().map(|x| x.is_consty()).unwrap_or(true) self.target.get().map(|x| x.is_consty()).unwrap_or(true)
} }
} }
impl FromAst<leo_ast::CircuitMemberAccessExpression> for CircuitAccessExpression { impl<'a> FromAst<'a, leo_ast::CircuitMemberAccessExpression> for CircuitAccessExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::CircuitMemberAccessExpression, value: &leo_ast::CircuitMemberAccessExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<CircuitAccessExpression, AsgConvertError> { ) -> Result<CircuitAccessExpression<'a>, AsgConvertError> {
let target = Arc::<Expression>::from_ast(scope, &*value.circuit, None)?; let target = <&'a Expression<'a>>::from_ast(scope, &*value.circuit, None)?;
let circuit = match target.get_type() { let circuit = match target.get_type() {
Some(Type::Circuit(circuit)) => circuit, Some(Type::Circuit(circuit)) => circuit,
x => { x => {
@ -119,7 +115,7 @@ impl FromAst<leo_ast::CircuitMemberAccessExpression> for CircuitAccessExpression
if let Some(member) = circuit.members.borrow().get(&value.name.name) { if let Some(member) = circuit.members.borrow().get(&value.name.name) {
if let Some(expected_type) = &expected_type { if let Some(expected_type) = &expected_type {
if let CircuitMember::Variable(type_) = &member { if let CircuitMember::Variable(type_) = &member {
let type_: Type = type_.clone().into(); let type_: Type = type_.clone();
if !expected_type.matches(&type_) { if !expected_type.matches(&type_) {
return Err(AsgConvertError::unexpected_type( return Err(AsgConvertError::unexpected_type(
&expected_type.to_string(), &expected_type.to_string(),
@ -140,15 +136,10 @@ impl FromAst<leo_ast::CircuitMemberAccessExpression> for CircuitAccessExpression
} else if circuit.is_input_pseudo_circuit() { } else if circuit.is_input_pseudo_circuit() {
// add new member to implicit input // add new member to implicit input
if let Some(expected_type) = expected_type.map(PartialType::full).flatten() { if let Some(expected_type) = expected_type.map(PartialType::full).flatten() {
circuit.members.borrow_mut().insert( circuit
value.name.name.clone(), .members
CircuitMember::Variable(expected_type.clone().into()),
);
let body = circuit.body.borrow().upgrade().expect("stale input circuit body");
body.members
.borrow_mut() .borrow_mut()
.insert(value.name.name.clone(), CircuitMemberBody::Variable(expected_type)); .insert(value.name.name.clone(), CircuitMember::Variable(expected_type.clone()));
} else { } else {
return Err(AsgConvertError::input_ref_needs_type( return Err(AsgConvertError::input_ref_needs_type(
&circuit.name.borrow().name, &circuit.name.borrow().name,
@ -165,24 +156,23 @@ impl FromAst<leo_ast::CircuitMemberAccessExpression> for CircuitAccessExpression
} }
Ok(CircuitAccessExpression { Ok(CircuitAccessExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
target: Some(target), target: Cell::new(Some(target)),
circuit, circuit: Cell::new(circuit),
member: value.name.clone(), member: value.name.clone(),
}) })
} }
} }
impl FromAst<leo_ast::CircuitStaticFunctionAccessExpression> for CircuitAccessExpression { impl<'a> FromAst<'a, leo_ast::CircuitStaticFunctionAccessExpression> for CircuitAccessExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &Scope<'a>,
value: &leo_ast::CircuitStaticFunctionAccessExpression, value: &leo_ast::CircuitStaticFunctionAccessExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType>,
) -> Result<CircuitAccessExpression, AsgConvertError> { ) -> Result<CircuitAccessExpression<'a>, AsgConvertError> {
let circuit = match &*value.circuit { let circuit = match &*value.circuit {
leo_ast::Expression::Identifier(name) => scope leo_ast::Expression::Identifier(name) => scope
.borrow()
.resolve_circuit(&name.name) .resolve_circuit(&name.name)
.ok_or_else(|| AsgConvertError::unresolved_circuit(&name.name, &name.span))?, .ok_or_else(|| AsgConvertError::unresolved_circuit(&name.name, &name.span))?,
_ => { _ => {
@ -213,26 +203,28 @@ impl FromAst<leo_ast::CircuitStaticFunctionAccessExpression> for CircuitAccessEx
} }
Ok(CircuitAccessExpression { Ok(CircuitAccessExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
target: None, target: Cell::new(None),
circuit, circuit: Cell::new(circuit),
member: value.name.clone(), member: value.name.clone(),
}) })
} }
} }
impl Into<leo_ast::Expression> for &CircuitAccessExpression { impl<'a> Into<leo_ast::Expression> for &CircuitAccessExpression<'a> {
fn into(self) -> leo_ast::Expression { fn into(self) -> leo_ast::Expression {
if let Some(target) = self.target.as_ref() { if let Some(target) = self.target.get() {
leo_ast::Expression::CircuitMemberAccess(leo_ast::CircuitMemberAccessExpression { leo_ast::Expression::CircuitMemberAccess(leo_ast::CircuitMemberAccessExpression {
circuit: Box::new(target.as_ref().into()), circuit: Box::new(target.into()),
name: self.member.clone(), name: self.member.clone(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
}) })
} else { } else {
leo_ast::Expression::CircuitStaticFunctionAccess(leo_ast::CircuitStaticFunctionAccessExpression { leo_ast::Expression::CircuitStaticFunctionAccess(leo_ast::CircuitStaticFunctionAccessExpression {
circuit: Box::new(leo_ast::Expression::Identifier(self.circuit.name.borrow().clone())), circuit: Box::new(leo_ast::Expression::Identifier(
self.circuit.get().name.borrow().clone(),
)),
name: self.member.clone(), name: self.member.clone(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
}) })

View File

@ -31,42 +31,39 @@ use crate::{
}; };
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct CircuitInitExpression { pub struct CircuitInitExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub circuit: Arc<Circuit>, pub circuit: Cell<&'a Circuit<'a>>,
pub values: Vec<(Identifier, Arc<Expression>)>, pub values: Vec<(Identifier, Cell<&'a Expression<'a>>)>,
} }
impl Node for CircuitInitExpression { impl<'a> Node for CircuitInitExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for CircuitInitExpression { impl<'a> ExpressionNode<'a> for CircuitInitExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.values.iter().for_each(|(_, element)| { self.values.iter().for_each(|(_, element)| {
element.set_parent(Arc::downgrade(expr)); element.get().set_parent(expr);
}) })
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
Some(Type::Circuit(self.circuit.clone())) Some(Type::Circuit(self.circuit.get()))
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
@ -78,18 +75,17 @@ impl ExpressionNode for CircuitInitExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.values.iter().all(|(_, value)| value.is_consty()) self.values.iter().all(|(_, value)| value.get().is_consty())
} }
} }
impl FromAst<leo_ast::CircuitInitExpression> for CircuitInitExpression { impl<'a> FromAst<'a, leo_ast::CircuitInitExpression> for CircuitInitExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::CircuitInitExpression, value: &leo_ast::CircuitInitExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<CircuitInitExpression, AsgConvertError> { ) -> Result<CircuitInitExpression<'a>, AsgConvertError> {
let circuit = scope let circuit = scope
.borrow()
.resolve_circuit(&value.name.name) .resolve_circuit(&value.name.name)
.ok_or_else(|| AsgConvertError::unresolved_circuit(&value.name.name, &value.name.span))?; .ok_or_else(|| AsgConvertError::unresolved_circuit(&value.name.name, &value.name.span))?;
match expected_type { match expected_type {
@ -109,7 +105,7 @@ impl FromAst<leo_ast::CircuitInitExpression> for CircuitInitExpression {
.map(|x| (&x.identifier.name, (&x.identifier, &x.expression))) .map(|x| (&x.identifier.name, (&x.identifier, &x.expression)))
.collect(); .collect();
let mut values: Vec<(Identifier, Arc<Expression>)> = vec![]; let mut values: Vec<(Identifier, Cell<&'a Expression<'a>>)> = vec![];
let mut defined_variables = IndexSet::<String>::new(); let mut defined_variables = IndexSet::<String>::new();
{ {
@ -124,13 +120,13 @@ impl FromAst<leo_ast::CircuitInitExpression> for CircuitInitExpression {
} }
defined_variables.insert(name.clone()); defined_variables.insert(name.clone());
let type_: Type = if let CircuitMember::Variable(type_) = &member { let type_: Type = if let CircuitMember::Variable(type_) = &member {
type_.clone().into() type_.clone()
} else { } else {
continue; continue;
}; };
if let Some((identifier, receiver)) = members.get(&name) { if let Some((identifier, receiver)) = members.get(&name) {
let received = Arc::<Expression>::from_ast(scope, *receiver, Some(type_.partial()))?; let received = <&Expression<'a>>::from_ast(scope, *receiver, Some(type_.partial()))?;
values.push(((*identifier).clone(), received)); values.push(((*identifier).clone(), Cell::new(received)));
} else { } else {
return Err(AsgConvertError::missing_circuit_member( return Err(AsgConvertError::missing_circuit_member(
&circuit.name.borrow().name, &circuit.name.borrow().name,
@ -152,24 +148,24 @@ impl FromAst<leo_ast::CircuitInitExpression> for CircuitInitExpression {
} }
Ok(CircuitInitExpression { Ok(CircuitInitExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
circuit, circuit: Cell::new(circuit),
values, values,
}) })
} }
} }
impl Into<leo_ast::CircuitInitExpression> for &CircuitInitExpression { impl<'a> Into<leo_ast::CircuitInitExpression> for &CircuitInitExpression<'a> {
fn into(self) -> leo_ast::CircuitInitExpression { fn into(self) -> leo_ast::CircuitInitExpression {
leo_ast::CircuitInitExpression { leo_ast::CircuitInitExpression {
name: self.circuit.name.borrow().clone(), name: self.circuit.get().name.borrow().clone(),
members: self members: self
.values .values
.iter() .iter()
.map(|(name, value)| leo_ast::CircuitImpliedVariableDefinition { .map(|(name, value)| leo_ast::CircuitImpliedVariableDefinition {
identifier: name.clone(), identifier: name.clone(),
expression: value.as_ref().into(), expression: value.get().into(),
}) })
.collect(), .collect(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),

View File

@ -29,36 +29,33 @@ use crate::{
Type, Type,
}; };
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct Constant { pub struct Constant<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub value: ConstValue, // should not be compound constants pub value: ConstValue, // should not be compound constants
} }
impl Node for Constant { impl<'a> Node for Constant<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for Constant { impl<'a> ExpressionNode<'a> for Constant<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, _expr: &Arc<Expression>) {} fn enforce_parents(&self, _expr: &'a Expression<'a>) {}
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
self.value.get_type() self.value.get_type()
} }
@ -75,12 +72,12 @@ impl ExpressionNode for Constant {
} }
} }
impl FromAst<leo_ast::ValueExpression> for Constant { impl<'a> FromAst<'a, leo_ast::ValueExpression> for Constant<'a> {
fn from_ast( fn from_ast(
_scope: &Scope, _scope: &'a Scope<'a>,
value: &leo_ast::ValueExpression, value: &leo_ast::ValueExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<Constant, AsgConvertError> { ) -> Result<Constant<'a>, AsgConvertError> {
use leo_ast::ValueExpression::*; use leo_ast::ValueExpression::*;
Ok(match value { Ok(match value {
Address(value, span) => { Address(value, span) => {
@ -95,7 +92,7 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
} }
} }
Constant { Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(span.clone()), span: Some(span.clone()),
value: ConstValue::Address(value.clone()), value: ConstValue::Address(value.clone()),
} }
@ -112,7 +109,7 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
} }
} }
Constant { Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(span.clone()), span: Some(span.clone()),
value: ConstValue::Boolean( value: ConstValue::Boolean(
value value
@ -133,7 +130,7 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
} }
} }
Constant { Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(span.clone()), span: Some(span.clone()),
value: ConstValue::Field(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), value: ConstValue::Field(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?),
} }
@ -150,7 +147,7 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
} }
} }
Constant { Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span().clone()), span: Some(value.span().clone()),
value: ConstValue::Group(match &**value { value: ConstValue::Group(match &**value {
leo_ast::GroupValue::Single(value, _) => GroupValue::Single(value.clone()), leo_ast::GroupValue::Single(value, _) => GroupValue::Single(value.clone()),
@ -164,23 +161,23 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
None => return Err(AsgConvertError::unresolved_type("unknown", span)), None => return Err(AsgConvertError::unresolved_type("unknown", span)),
Some(PartialType::Integer(Some(sub_type), _)) | Some(PartialType::Integer(None, Some(sub_type))) => { Some(PartialType::Integer(Some(sub_type), _)) | Some(PartialType::Integer(None, Some(sub_type))) => {
Constant { Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(span.clone()), span: Some(span.clone()),
value: ConstValue::Int(ConstInt::parse(&sub_type, value, span)?), value: ConstValue::Int(ConstInt::parse(&sub_type, value, span)?),
} }
} }
Some(PartialType::Type(Type::Field)) => Constant { Some(PartialType::Type(Type::Field)) => Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(span.clone()), span: Some(span.clone()),
value: ConstValue::Field(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), value: ConstValue::Field(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?),
}, },
Some(PartialType::Type(Type::Group)) => Constant { Some(PartialType::Type(Type::Group)) => Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(span.clone()), span: Some(span.clone()),
value: ConstValue::Group(GroupValue::Single(value.to_string())), value: ConstValue::Group(GroupValue::Single(value.to_string())),
}, },
Some(PartialType::Type(Type::Address)) => Constant { Some(PartialType::Type(Type::Address)) => Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(span.clone()), span: Some(span.clone()),
value: ConstValue::Address(value.to_string()), value: ConstValue::Address(value.to_string()),
}, },
@ -200,7 +197,7 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
} }
} }
Constant { Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(span.clone()), span: Some(span.clone()),
value: ConstValue::Int(ConstInt::parse(int_type, value, span)?), value: ConstValue::Int(ConstInt::parse(int_type, value, span)?),
} }
@ -209,7 +206,7 @@ impl FromAst<leo_ast::ValueExpression> for Constant {
} }
} }
impl Into<leo_ast::ValueExpression> for &Constant { impl<'a> Into<leo_ast::ValueExpression> for &Constant<'a> {
fn into(self) -> leo_ast::ValueExpression { fn into(self) -> leo_ast::ValueExpression {
match &self.value { match &self.value {
ConstValue::Address(value) => { ConstValue::Address(value) => {

View File

@ -64,31 +64,29 @@ pub use variable_ref::*;
use crate::{AsgConvertError, ConstValue, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, FromAst, Node, PartialType, Scope, Span, Type};
use std::sync::{Arc, Weak}; #[derive(Clone)]
pub enum Expression<'a> {
VariableRef(VariableRef<'a>),
Constant(Constant<'a>),
Binary(BinaryExpression<'a>),
Unary(UnaryExpression<'a>),
Ternary(TernaryExpression<'a>),
#[derive(Debug)] ArrayInline(ArrayInlineExpression<'a>),
pub enum Expression { ArrayInit(ArrayInitExpression<'a>),
VariableRef(VariableRef), ArrayAccess(ArrayAccessExpression<'a>),
Constant(Constant), ArrayRangeAccess(ArrayRangeAccessExpression<'a>),
Binary(BinaryExpression),
Unary(UnaryExpression),
Ternary(TernaryExpression),
ArrayInline(ArrayInlineExpression), TupleInit(TupleInitExpression<'a>),
ArrayInit(ArrayInitExpression), TupleAccess(TupleAccessExpression<'a>),
ArrayAccess(ArrayAccessExpression),
ArrayRangeAccess(ArrayRangeAccessExpression),
TupleInit(TupleInitExpression), CircuitInit(CircuitInitExpression<'a>),
TupleAccess(TupleAccessExpression), CircuitAccess(CircuitAccessExpression<'a>),
CircuitInit(CircuitInitExpression), Call(CallExpression<'a>),
CircuitAccess(CircuitAccessExpression),
Call(CallExpression),
} }
impl Node for Expression { impl<'a> Node for Expression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
use Expression::*; use Expression::*;
match self { match self {
@ -110,19 +108,19 @@ impl Node for Expression {
} }
} }
pub trait ExpressionNode: Node { pub trait ExpressionNode<'a>: Node {
fn set_parent(&self, parent: Weak<Expression>); fn set_parent(&self, parent: &'a Expression<'a>);
fn get_parent(&self) -> Option<Arc<Expression>>; fn get_parent(&self) -> Option<&'a Expression<'a>>;
fn enforce_parents(&self, expr: &Arc<Expression>); fn enforce_parents(&self, expr: &'a Expression<'a>);
fn get_type(&self) -> Option<Type>; fn get_type(&self) -> Option<Type<'a>>;
fn is_mut_ref(&self) -> bool; fn is_mut_ref(&self) -> bool;
fn const_value(&self) -> Option<ConstValue>; // todo: memoize fn const_value(&self) -> Option<ConstValue>; // todo: memoize
fn is_consty(&self) -> bool; fn is_consty(&self) -> bool;
} }
impl ExpressionNode for Expression { impl<'a> ExpressionNode<'a> for Expression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
use Expression::*; use Expression::*;
match self { match self {
VariableRef(x) => x.set_parent(parent), VariableRef(x) => x.set_parent(parent),
@ -142,7 +140,7 @@ impl ExpressionNode for Expression {
} }
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
use Expression::*; use Expression::*;
match self { match self {
VariableRef(x) => x.get_parent(), VariableRef(x) => x.get_parent(),
@ -162,7 +160,7 @@ impl ExpressionNode for Expression {
} }
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
use Expression::*; use Expression::*;
match self { match self {
VariableRef(x) => x.enforce_parents(expr), VariableRef(x) => x.enforce_parents(expr),
@ -182,7 +180,7 @@ impl ExpressionNode for Expression {
} }
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
use Expression::*; use Expression::*;
match self { match self {
VariableRef(x) => x.get_type(), VariableRef(x) => x.get_type(),
@ -263,65 +261,70 @@ impl ExpressionNode for Expression {
} }
} }
impl FromAst<leo_ast::Expression> for Arc<Expression> { impl<'a> FromAst<'a, leo_ast::Expression> for &'a Expression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::Expression, value: &leo_ast::Expression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
use leo_ast::Expression::*; use leo_ast::Expression::*;
let expression = match value { let expression = match value {
Identifier(identifier) => Self::from_ast(scope, identifier, expected_type)?, Identifier(identifier) => Self::from_ast(scope, identifier, expected_type)?,
Value(value) => Arc::new(Constant::from_ast(scope, value, expected_type).map(Expression::Constant)?), Value(value) => {
Binary(binary) => { scope.alloc_expression(Constant::from_ast(scope, value, expected_type).map(Expression::Constant)?)
Arc::new(BinaryExpression::from_ast(scope, binary, expected_type).map(Expression::Binary)?)
} }
Unary(unary) => Arc::new(UnaryExpression::from_ast(scope, unary, expected_type).map(Expression::Unary)?), Binary(binary) => scope
Ternary(conditional) => { .alloc_expression(BinaryExpression::from_ast(scope, binary, expected_type).map(Expression::Binary)?),
Arc::new(TernaryExpression::from_ast(scope, conditional, expected_type).map(Expression::Ternary)?) Unary(unary) => {
scope.alloc_expression(UnaryExpression::from_ast(scope, unary, expected_type).map(Expression::Unary)?)
} }
Ternary(conditional) => scope.alloc_expression(
TernaryExpression::from_ast(scope, conditional, expected_type).map(Expression::Ternary)?,
),
ArrayInline(array_inline) => Arc::new( ArrayInline(array_inline) => scope.alloc_expression(
ArrayInlineExpression::from_ast(scope, array_inline, expected_type).map(Expression::ArrayInline)?, ArrayInlineExpression::from_ast(scope, array_inline, expected_type).map(Expression::ArrayInline)?,
), ),
ArrayInit(array_init) => { ArrayInit(array_init) => scope.alloc_expression(
Arc::new(ArrayInitExpression::from_ast(scope, array_init, expected_type).map(Expression::ArrayInit)?) ArrayInitExpression::from_ast(scope, array_init, expected_type).map(Expression::ArrayInit)?,
} ),
ArrayAccess(array_access) => Arc::new( ArrayAccess(array_access) => scope.alloc_expression(
ArrayAccessExpression::from_ast(scope, array_access, expected_type).map(Expression::ArrayAccess)?, ArrayAccessExpression::from_ast(scope, array_access, expected_type).map(Expression::ArrayAccess)?,
), ),
ArrayRangeAccess(array_range_access) => Arc::new( ArrayRangeAccess(array_range_access) => scope.alloc_expression(
ArrayRangeAccessExpression::from_ast(scope, array_range_access, expected_type) ArrayRangeAccessExpression::from_ast(scope, array_range_access, expected_type)
.map(Expression::ArrayRangeAccess)?, .map(Expression::ArrayRangeAccess)?,
), ),
TupleInit(tuple_init) => { TupleInit(tuple_init) => scope.alloc_expression(
Arc::new(TupleInitExpression::from_ast(scope, tuple_init, expected_type).map(Expression::TupleInit)?) TupleInitExpression::from_ast(scope, tuple_init, expected_type).map(Expression::TupleInit)?,
} ),
TupleAccess(tuple_access) => Arc::new( TupleAccess(tuple_access) => scope.alloc_expression(
TupleAccessExpression::from_ast(scope, tuple_access, expected_type).map(Expression::TupleAccess)?, TupleAccessExpression::from_ast(scope, tuple_access, expected_type).map(Expression::TupleAccess)?,
), ),
CircuitInit(circuit_init) => Arc::new( CircuitInit(circuit_init) => scope.alloc_expression(
CircuitInitExpression::from_ast(scope, circuit_init, expected_type).map(Expression::CircuitInit)?, CircuitInitExpression::from_ast(scope, circuit_init, expected_type).map(Expression::CircuitInit)?,
), ),
CircuitMemberAccess(circuit_member) => Arc::new( CircuitMemberAccess(circuit_member) => scope.alloc_expression(
CircuitAccessExpression::from_ast(scope, circuit_member, expected_type) CircuitAccessExpression::from_ast(scope, circuit_member, expected_type)
.map(Expression::CircuitAccess)?, .map(Expression::CircuitAccess)?,
), ),
CircuitStaticFunctionAccess(circuit_member) => Arc::new( CircuitStaticFunctionAccess(circuit_member) => scope.alloc_expression(
CircuitAccessExpression::from_ast(scope, circuit_member, expected_type) CircuitAccessExpression::from_ast(scope, circuit_member, expected_type)
.map(Expression::CircuitAccess)?, .map(Expression::CircuitAccess)?,
), ),
Call(call) => Arc::new(CallExpression::from_ast(scope, call, expected_type).map(Expression::Call)?), Call(call) => {
scope.alloc_expression(CallExpression::from_ast(scope, call, expected_type).map(Expression::Call)?)
}
}; };
expression.enforce_parents(&expression); expression.enforce_parents(&expression);
Ok(expression) Ok(expression)
} }
} }
impl Into<leo_ast::Expression> for &Expression { impl<'a> Into<leo_ast::Expression> for &Expression<'a> {
fn into(self) -> leo_ast::Expression { fn into(self) -> leo_ast::Expression {
use Expression::*; use Expression::*;
match self { match self {

View File

@ -16,55 +16,52 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct TernaryExpression { pub struct TernaryExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub condition: Arc<Expression>, pub condition: Cell<&'a Expression<'a>>,
pub if_true: Arc<Expression>, pub if_true: Cell<&'a Expression<'a>>,
pub if_false: Arc<Expression>, pub if_false: Cell<&'a Expression<'a>>,
} }
impl Node for TernaryExpression { impl<'a> Node for TernaryExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for TernaryExpression { impl<'a> ExpressionNode<'a> for TernaryExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.condition.set_parent(Arc::downgrade(expr)); self.condition.get().set_parent(expr);
self.if_true.set_parent(Arc::downgrade(expr)); self.if_true.get().set_parent(expr);
self.if_false.set_parent(Arc::downgrade(expr)); self.if_false.get().set_parent(expr);
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
self.if_true.get_type() self.if_true.get().get_type()
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
self.if_true.is_mut_ref() && self.if_false.is_mut_ref() self.if_true.get().is_mut_ref() && self.if_false.get().is_mut_ref()
} }
fn const_value(&self) -> Option<ConstValue> { fn const_value(&self) -> Option<ConstValue> {
if let Some(ConstValue::Boolean(switch)) = self.condition.const_value() { if let Some(ConstValue::Boolean(switch)) = self.condition.get().const_value() {
if switch { if switch {
self.if_true.const_value() self.if_true.get().const_value()
} else { } else {
self.if_false.const_value() self.if_false.get().const_value()
} }
} else { } else {
None None
@ -72,32 +69,40 @@ impl ExpressionNode for TernaryExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.condition.is_consty() && self.if_true.is_consty() && self.if_false.is_consty() self.condition.get().is_consty() && self.if_true.get().is_consty() && self.if_false.get().is_consty()
} }
} }
impl FromAst<leo_ast::TernaryExpression> for TernaryExpression { impl<'a> FromAst<'a, leo_ast::TernaryExpression> for TernaryExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::TernaryExpression, value: &leo_ast::TernaryExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<TernaryExpression, AsgConvertError> { ) -> Result<TernaryExpression<'a>, AsgConvertError> {
Ok(TernaryExpression { Ok(TernaryExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
condition: Arc::<Expression>::from_ast(scope, &*value.condition, Some(Type::Boolean.partial()))?, condition: Cell::new(<&Expression<'a>>::from_ast(
if_true: Arc::<Expression>::from_ast(scope, &*value.if_true, expected_type.clone())?, scope,
if_false: Arc::<Expression>::from_ast(scope, &*value.if_false, expected_type)?, &*value.condition,
Some(Type::Boolean.partial()),
)?),
if_true: Cell::new(<&Expression<'a>>::from_ast(
scope,
&*value.if_true,
expected_type.clone(),
)?),
if_false: Cell::new(<&Expression<'a>>::from_ast(scope, &*value.if_false, expected_type)?),
}) })
} }
} }
impl Into<leo_ast::TernaryExpression> for &TernaryExpression { impl<'a> Into<leo_ast::TernaryExpression> for &TernaryExpression<'a> {
fn into(self) -> leo_ast::TernaryExpression { fn into(self) -> leo_ast::TernaryExpression {
leo_ast::TernaryExpression { leo_ast::TernaryExpression {
condition: Box::new(self.condition.as_ref().into()), condition: Box::new(self.condition.get().into()),
if_true: Box::new(self.if_true.as_ref().into()), if_true: Box::new(self.if_true.get().into()),
if_false: Box::new(self.if_false.as_ref().into()), if_false: Box::new(self.if_false.get().into()),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -16,51 +16,48 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct TupleAccessExpression { pub struct TupleAccessExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub tuple_ref: Arc<Expression>, pub tuple_ref: Cell<&'a Expression<'a>>,
pub index: usize, pub index: usize,
} }
impl Node for TupleAccessExpression { impl<'a> Node for TupleAccessExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for TupleAccessExpression { impl<'a> ExpressionNode<'a> for TupleAccessExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.tuple_ref.set_parent(Arc::downgrade(expr)); self.tuple_ref.get().set_parent(expr);
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
match self.tuple_ref.get_type()? { match self.tuple_ref.get().get_type()? {
Type::Tuple(subtypes) => subtypes.get(self.index).cloned(), Type::Tuple(subtypes) => subtypes.get(self.index).cloned(),
_ => None, _ => None,
} }
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
self.tuple_ref.is_mut_ref() self.tuple_ref.get().is_mut_ref()
} }
fn const_value(&self) -> Option<ConstValue> { fn const_value(&self) -> Option<ConstValue> {
let tuple_const = self.tuple_ref.const_value()?; let tuple_const = self.tuple_ref.get().const_value()?;
match tuple_const { match tuple_const {
ConstValue::Tuple(sub_consts) => sub_consts.get(self.index).cloned(), ConstValue::Tuple(sub_consts) => sub_consts.get(self.index).cloned(),
_ => None, _ => None,
@ -68,16 +65,16 @@ impl ExpressionNode for TupleAccessExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.tuple_ref.is_consty() self.tuple_ref.get().is_consty()
} }
} }
impl FromAst<leo_ast::TupleAccessExpression> for TupleAccessExpression { impl<'a> FromAst<'a, leo_ast::TupleAccessExpression> for TupleAccessExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::TupleAccessExpression, value: &leo_ast::TupleAccessExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<TupleAccessExpression, AsgConvertError> { ) -> Result<TupleAccessExpression<'a>, AsgConvertError> {
let index = value let index = value
.index .index
.value .value
@ -87,7 +84,7 @@ impl FromAst<leo_ast::TupleAccessExpression> for TupleAccessExpression {
let mut expected_tuple = vec![None; index + 1]; let mut expected_tuple = vec![None; index + 1];
expected_tuple[index] = expected_type; expected_tuple[index] = expected_type;
let tuple = Arc::<Expression>::from_ast(scope, &*value.tuple, Some(PartialType::Tuple(expected_tuple)))?; let tuple = <&Expression<'a>>::from_ast(scope, &*value.tuple, Some(PartialType::Tuple(expected_tuple)))?;
let tuple_type = tuple.get_type(); let tuple_type = tuple.get_type();
if let Some(Type::Tuple(_items)) = tuple_type { if let Some(Type::Tuple(_items)) = tuple_type {
} else { } else {
@ -99,18 +96,18 @@ impl FromAst<leo_ast::TupleAccessExpression> for TupleAccessExpression {
} }
Ok(TupleAccessExpression { Ok(TupleAccessExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
tuple_ref: tuple, tuple_ref: Cell::new(tuple),
index, index,
}) })
} }
} }
impl Into<leo_ast::TupleAccessExpression> for &TupleAccessExpression { impl<'a> Into<leo_ast::TupleAccessExpression> for &TupleAccessExpression<'a> {
fn into(self) -> leo_ast::TupleAccessExpression { fn into(self) -> leo_ast::TupleAccessExpression {
leo_ast::TupleAccessExpression { leo_ast::TupleAccessExpression {
tuple: Box::new(self.tuple_ref.as_ref().into()), tuple: Box::new(self.tuple_ref.get().into()),
index: leo_ast::PositiveNumber { index: leo_ast::PositiveNumber {
value: self.index.to_string(), value: self.index.to_string(),
}, },

View File

@ -16,43 +16,40 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct TupleInitExpression { pub struct TupleInitExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub elements: Vec<Arc<Expression>>, pub elements: Vec<Cell<&'a Expression<'a>>>,
} }
impl Node for TupleInitExpression { impl<'a> Node for TupleInitExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for TupleInitExpression { impl<'a> ExpressionNode<'a> for TupleInitExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.elements.iter().for_each(|element| { self.elements.iter().for_each(|element| {
element.set_parent(Arc::downgrade(expr)); element.get().set_parent(expr);
}) })
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
let mut output = vec![]; let mut output = vec![];
for element in self.elements.iter() { for element in self.elements.iter() {
output.push(element.get_type()?); output.push(element.get().get_type()?);
} }
Some(Type::Tuple(output)) Some(Type::Tuple(output))
} }
@ -64,7 +61,7 @@ impl ExpressionNode for TupleInitExpression {
fn const_value(&self) -> Option<ConstValue> { fn const_value(&self) -> Option<ConstValue> {
let mut consts = vec![]; let mut consts = vec![];
for element in self.elements.iter() { for element in self.elements.iter() {
if let Some(const_value) = element.const_value() { if let Some(const_value) = element.get().const_value() {
consts.push(const_value); consts.push(const_value);
} else { } else {
return None; return None;
@ -74,16 +71,16 @@ impl ExpressionNode for TupleInitExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.elements.iter().all(|x| x.is_consty()) self.elements.iter().all(|x| x.get().is_consty())
} }
} }
impl FromAst<leo_ast::TupleInitExpression> for TupleInitExpression { impl<'a> FromAst<'a, leo_ast::TupleInitExpression> for TupleInitExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::TupleInitExpression, value: &leo_ast::TupleInitExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<TupleInitExpression, AsgConvertError> { ) -> Result<TupleInitExpression<'a>, AsgConvertError> {
let tuple_types = match expected_type { let tuple_types = match expected_type {
Some(PartialType::Tuple(sub_types)) => Some(sub_types), Some(PartialType::Tuple(sub_types)) => Some(sub_types),
None => None, None => None,
@ -111,26 +108,27 @@ impl FromAst<leo_ast::TupleInitExpression> for TupleInitExpression {
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, e)| { .map(|(i, e)| {
Arc::<Expression>::from_ast( <&Expression<'a>>::from_ast(
scope, scope,
e, e,
tuple_types.as_ref().map(|x| x.get(i)).flatten().cloned().flatten(), tuple_types.as_ref().map(|x| x.get(i)).flatten().cloned().flatten(),
) )
.map(Cell::new)
}) })
.collect::<Result<Vec<_>, AsgConvertError>>()?; .collect::<Result<Vec<_>, AsgConvertError>>()?;
Ok(TupleInitExpression { Ok(TupleInitExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
elements, elements,
}) })
} }
} }
impl Into<leo_ast::TupleInitExpression> for &TupleInitExpression { impl<'a> Into<leo_ast::TupleInitExpression> for &TupleInitExpression<'a> {
fn into(self) -> leo_ast::TupleInitExpression { fn into(self) -> leo_ast::TupleInitExpression {
leo_ast::TupleInitExpression { leo_ast::TupleInitExpression {
elements: self.elements.iter().map(|e| e.as_ref().into()).collect(), elements: self.elements.iter().map(|e| e.get().into()).collect(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -17,40 +17,37 @@
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
pub use leo_ast::UnaryOperation; pub use leo_ast::UnaryOperation;
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct UnaryExpression { pub struct UnaryExpression<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub operation: UnaryOperation, pub operation: UnaryOperation,
pub inner: Arc<Expression>, pub inner: Cell<&'a Expression<'a>>,
} }
impl Node for UnaryExpression { impl<'a> Node for UnaryExpression<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for UnaryExpression { impl<'a> ExpressionNode<'a> for UnaryExpression<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, expr: &Arc<Expression>) { fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.inner.set_parent(Arc::downgrade(expr)); self.inner.get().set_parent(expr);
} }
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
self.inner.get_type() self.inner.get().get_type()
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
@ -58,7 +55,7 @@ impl ExpressionNode for UnaryExpression {
} }
fn const_value(&self) -> Option<ConstValue> { fn const_value(&self) -> Option<ConstValue> {
if let Some(inner) = self.inner.const_value() { if let Some(inner) = self.inner.get().const_value() {
match self.operation { match self.operation {
UnaryOperation::Not => match inner { UnaryOperation::Not => match inner {
ConstValue::Boolean(value) => Some(ConstValue::Boolean(!value)), ConstValue::Boolean(value) => Some(ConstValue::Boolean(!value)),
@ -79,16 +76,16 @@ impl ExpressionNode for UnaryExpression {
} }
fn is_consty(&self) -> bool { fn is_consty(&self) -> bool {
self.inner.is_consty() self.inner.get().is_consty()
} }
} }
impl FromAst<leo_ast::UnaryExpression> for UnaryExpression { impl<'a> FromAst<'a, leo_ast::UnaryExpression> for UnaryExpression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::UnaryExpression, value: &leo_ast::UnaryExpression,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<UnaryExpression, AsgConvertError> { ) -> Result<UnaryExpression<'a>, AsgConvertError> {
let expected_type = match value.op { let expected_type = match value.op {
UnaryOperation::Not => match expected_type.map(|x| x.full()).flatten() { UnaryOperation::Not => match expected_type.map(|x| x.full()).flatten() {
Some(Type::Boolean) | None => Some(Type::Boolean), Some(Type::Boolean) | None => Some(Type::Boolean),
@ -115,19 +112,23 @@ impl FromAst<leo_ast::UnaryExpression> for UnaryExpression {
}, },
}; };
Ok(UnaryExpression { Ok(UnaryExpression {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
operation: value.op.clone(), operation: value.op.clone(),
inner: Arc::<Expression>::from_ast(scope, &*value.inner, expected_type.map(Into::into))?, inner: Cell::new(<&Expression<'a>>::from_ast(
scope,
&*value.inner,
expected_type.map(Into::into),
)?),
}) })
} }
} }
impl Into<leo_ast::UnaryExpression> for &UnaryExpression { impl<'a> Into<leo_ast::UnaryExpression> for &UnaryExpression<'a> {
fn into(self) -> leo_ast::UnaryExpression { fn into(self) -> leo_ast::UnaryExpression {
leo_ast::UnaryExpression { leo_ast::UnaryExpression {
op: self.operation.clone(), op: self.operation.clone(),
inner: Box::new(self.inner.as_ref().into()), inner: Box::new(self.inner.get().into()),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -31,37 +31,34 @@ use crate::{
Variable, Variable,
}; };
use std::{ use std::cell::Cell;
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct VariableRef { pub struct VariableRef<'a> {
pub parent: RefCell<Option<Weak<Expression>>>, pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub variable: Variable, pub variable: &'a Variable<'a>,
} }
impl Node for VariableRef { impl<'a> Node for VariableRef<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl ExpressionNode for VariableRef { impl<'a> ExpressionNode<'a> for VariableRef<'a> {
fn set_parent(&self, parent: Weak<Expression>) { fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent)); self.parent.replace(Some(parent));
} }
fn get_parent(&self) -> Option<Arc<Expression>> { fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.borrow().as_ref().map(Weak::upgrade).flatten() self.parent.get()
} }
fn enforce_parents(&self, _expr: &Arc<Expression>) {} fn enforce_parents(&self, _expr: &'a Expression<'a>) {}
fn get_type(&self) -> Option<Type> { fn get_type(&self) -> Option<Type<'a>> {
Some(self.variable.borrow().type_.clone().strong()) Some(self.variable.borrow().type_.clone())
} }
fn is_mut_ref(&self) -> bool { fn is_mut_ref(&self) -> bool {
@ -74,24 +71,19 @@ impl ExpressionNode for VariableRef {
if variable.mutable || variable.assignments.len() != 1 { if variable.mutable || variable.assignments.len() != 1 {
return None; return None;
} }
let assignment = variable let assignment = variable.assignments.get(0).unwrap();
.assignments
.get(0)
.unwrap()
.upgrade()
.expect("stale assignment for variable");
match &*assignment { match &*assignment {
Statement::Definition(DefinitionStatement { variables, value, .. }) => { Statement::Definition(DefinitionStatement { variables, value, .. }) => {
if variables.len() == 1 { if variables.len() == 1 {
let defined_variable = variables.get(0).unwrap().borrow(); let defined_variable = variables.get(0).unwrap().borrow();
assert_eq!(variable.id, defined_variable.id); assert_eq!(variable.id, defined_variable.id);
value.const_value() value.get().const_value()
} else { } else {
for defined_variable in variables.iter() { for defined_variable in variables.iter() {
let defined_variable = defined_variable.borrow(); let defined_variable = defined_variable.borrow();
if defined_variable.id == variable.id { if defined_variable.id == variable.id {
return value.const_value(); return value.get().const_value();
} }
} }
panic!("no corresponding tuple variable found during const destructuring (corrupt asg?)"); panic!("no corresponding tuple variable found during const destructuring (corrupt asg?)");
@ -109,12 +101,7 @@ impl ExpressionNode for VariableRef {
if variable.mutable || variable.assignments.len() != 1 { if variable.mutable || variable.assignments.len() != 1 {
return false; return false;
} }
let assignment = variable let assignment = variable.assignments.get(0).unwrap();
.assignments
.get(0)
.unwrap()
.upgrade()
.expect("stale assignment for variable");
match &*assignment { match &*assignment {
Statement::Definition(DefinitionStatement { variables, value, .. }) => { Statement::Definition(DefinitionStatement { variables, value, .. }) => {
@ -122,12 +109,12 @@ impl ExpressionNode for VariableRef {
let defined_variable = variables.get(0).unwrap().borrow(); let defined_variable = variables.get(0).unwrap().borrow();
assert_eq!(variable.id, defined_variable.id); assert_eq!(variable.id, defined_variable.id);
value.is_consty() value.get().is_consty()
} else { } else {
for defined_variable in variables.iter() { for defined_variable in variables.iter() {
let defined_variable = defined_variable.borrow(); let defined_variable = defined_variable.borrow();
if defined_variable.id == variable.id { if defined_variable.id == variable.id {
return value.is_consty(); return value.get().is_consty();
} }
} }
panic!("no corresponding tuple variable found during const destructuring (corrupt asg?)"); panic!("no corresponding tuple variable found during const destructuring (corrupt asg?)");
@ -139,21 +126,21 @@ impl ExpressionNode for VariableRef {
} }
} }
impl FromAst<leo_ast::Identifier> for Arc<Expression> { impl<'a> FromAst<'a, leo_ast::Identifier> for &'a Expression<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::Identifier, value: &leo_ast::Identifier,
expected_type: Option<PartialType>, expected_type: Option<PartialType<'a>>,
) -> Result<Arc<Expression>, AsgConvertError> { ) -> Result<&'a Expression<'a>, AsgConvertError> {
let variable = if value.name == "input" { let variable = if value.name == "input" {
if let Some(function) = scope.borrow().resolve_current_function() { if let Some(function) = scope.resolve_current_function() {
if !function.has_input { if !function.has_input {
return Err(AsgConvertError::unresolved_reference(&value.name, &value.span)); return Err(AsgConvertError::unresolved_reference(&value.name, &value.span));
} }
} else { } else {
return Err(AsgConvertError::unresolved_reference(&value.name, &value.span)); return Err(AsgConvertError::unresolved_reference(&value.name, &value.span));
} }
if let Some(input) = scope.borrow().resolve_input() { if let Some(input) = scope.resolve_input() {
input.container input.container
} else { } else {
return Err(AsgConvertError::InternalError( return Err(AsgConvertError::InternalError(
@ -161,12 +148,12 @@ impl FromAst<leo_ast::Identifier> for Arc<Expression> {
)); ));
} }
} else { } else {
match scope.borrow().resolve_variable(&value.name) { match scope.resolve_variable(&value.name) {
Some(v) => v, Some(v) => v,
None => { None => {
if value.name.starts_with("aleo1") { if value.name.starts_with("aleo1") {
return Ok(Arc::new(Expression::Constant(Constant { return Ok(scope.alloc_expression(Expression::Constant(Constant {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
value: ConstValue::Address(value.name.clone()), value: ConstValue::Address(value.name.clone()),
}))); })));
@ -177,11 +164,11 @@ impl FromAst<leo_ast::Identifier> for Arc<Expression> {
}; };
let variable_ref = VariableRef { let variable_ref = VariableRef {
parent: RefCell::new(None), parent: Cell::new(None),
span: Some(value.span.clone()), span: Some(value.span.clone()),
variable: variable.clone(), variable,
}; };
let expression = Arc::new(Expression::VariableRef(variable_ref)); let expression = scope.alloc_expression(Expression::VariableRef(variable_ref));
if let Some(expected_type) = expected_type { if let Some(expected_type) = expected_type {
let type_ = expression let type_ = expression
@ -197,13 +184,13 @@ impl FromAst<leo_ast::Identifier> for Arc<Expression> {
} }
let mut variable_ref = variable.borrow_mut(); let mut variable_ref = variable.borrow_mut();
variable_ref.references.push(Arc::downgrade(&expression)); variable_ref.references.push(expression);
Ok(expression) Ok(expression)
} }
} }
impl Into<leo_ast::Identifier> for &VariableRef { impl<'a> Into<leo_ast::Identifier> for &VariableRef<'a> {
fn into(self) -> leo_ast::Identifier { fn into(self) -> leo_ast::Identifier {
self.variable.borrow().name.clone() self.variable.borrow().name.clone()
} }

View File

@ -16,56 +16,74 @@
//! Helper methods for resolving imported packages. //! Helper methods for resolving imported packages.
use crate::{AsgConvertError, Program, Span}; use std::marker::PhantomData;
use crate::{AsgContext, AsgConvertError, Program, Span};
use indexmap::IndexMap; use indexmap::IndexMap;
pub trait ImportResolver { pub trait ImportResolver<'a> {
fn resolve_package(&mut self, package_segments: &[&str], span: &Span) -> Result<Option<Program>, AsgConvertError>; fn resolve_package(
&mut self,
context: AsgContext<'a>,
package_segments: &[&str],
span: &Span,
) -> Result<Option<Program<'a>>, AsgConvertError>;
} }
pub struct NullImportResolver; pub struct NullImportResolver;
impl ImportResolver for NullImportResolver { impl<'a> ImportResolver<'a> for NullImportResolver {
fn resolve_package( fn resolve_package(
&mut self, &mut self,
_context: AsgContext<'a>,
_package_segments: &[&str], _package_segments: &[&str],
_span: &Span, _span: &Span,
) -> Result<Option<Program>, AsgConvertError> { ) -> Result<Option<Program<'a>>, AsgConvertError> {
Ok(None) Ok(None)
} }
} }
pub struct CoreImportResolver<'a, T: ImportResolver + 'static>(pub &'a mut T); pub struct CoreImportResolver<'a, 'b, T: ImportResolver<'b>> {
inner: &'a mut T,
lifetime: PhantomData<&'b ()>,
}
impl<'a, T: ImportResolver + 'static> ImportResolver for CoreImportResolver<'a, T> { impl<'a, 'b, T: ImportResolver<'b>> CoreImportResolver<'a, 'b, T> {
fn resolve_package(&mut self, package_segments: &[&str], span: &Span) -> Result<Option<Program>, AsgConvertError> { pub fn new(inner: &'a mut T) -> Self {
if !package_segments.is_empty() && package_segments.get(0).unwrap() == &"core" { CoreImportResolver {
Ok(crate::resolve_core_module(&*package_segments[1..].join("."))?) inner,
} else { lifetime: PhantomData,
self.0.resolve_package(package_segments, span)
} }
} }
} }
pub struct StandardImportResolver; impl<'a, 'b, T: ImportResolver<'b>> ImportResolver<'b> for CoreImportResolver<'a, 'b, T> {
impl ImportResolver for StandardImportResolver {
fn resolve_package( fn resolve_package(
&mut self, &mut self,
_package_segments: &[&str], context: AsgContext<'b>,
_span: &Span, package_segments: &[&str],
) -> Result<Option<Program>, AsgConvertError> { span: &Span,
Ok(None) ) -> Result<Option<Program<'b>>, AsgConvertError> {
if !package_segments.is_empty() && package_segments.get(0).unwrap() == &"core" {
Ok(crate::resolve_core_module(context, &*package_segments[1..].join("."))?)
} else {
self.inner.resolve_package(context, package_segments, span)
}
} }
} }
pub struct MockedImportResolver { pub struct MockedImportResolver<'a> {
pub packages: IndexMap<String, Program>, pub packages: IndexMap<String, Program<'a>>,
} }
impl ImportResolver for MockedImportResolver { impl<'a> ImportResolver<'a> for MockedImportResolver<'a> {
fn resolve_package(&mut self, package_segments: &[&str], _span: &Span) -> Result<Option<Program>, AsgConvertError> { fn resolve_package(
&mut self,
_context: AsgContext<'a>,
package_segments: &[&str],
_span: &Span,
) -> Result<Option<Program<'a>>, AsgConvertError> {
Ok(self.packages.get(&package_segments.join(".")).cloned()) Ok(self.packages.get(&package_segments.join(".")).cloned())
} }
} }

View File

@ -14,23 +14,20 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Circuit, CircuitBody, CircuitMember, CircuitMemberBody, Identifier, Scope, Type, Variable, WeakType}; use crate::{Circuit, CircuitMember, Identifier, Scope, Type, Variable};
use indexmap::IndexMap; use indexmap::IndexMap;
use std::{ use std::cell::RefCell;
cell::RefCell,
sync::{Arc, Weak},
};
/// Stores program input values as asg nodes. /// Stores program input values as ASG nodes.
#[derive(Debug, Clone)] #[derive(Clone, Copy)]
pub struct Input { pub struct Input<'a> {
pub registers: Arc<CircuitBody>, pub registers: &'a Circuit<'a>,
pub state: Arc<CircuitBody>, pub state: &'a Circuit<'a>,
pub state_leaf: Arc<CircuitBody>, pub state_leaf: &'a Circuit<'a>,
pub record: Arc<CircuitBody>, pub record: &'a Circuit<'a>,
pub container_circuit: Arc<CircuitBody>, pub container_circuit: &'a Circuit<'a>,
pub container: Variable, pub container: &'a Variable<'a>,
} }
pub const CONTAINER_PSEUDO_CIRCUIT: &str = "$InputContainer"; pub const CONTAINER_PSEUDO_CIRCUIT: &str = "$InputContainer";
@ -39,95 +36,56 @@ pub const RECORD_PSEUDO_CIRCUIT: &str = "$InputRecord";
pub const STATE_PSEUDO_CIRCUIT: &str = "$InputState"; pub const STATE_PSEUDO_CIRCUIT: &str = "$InputState";
pub const STATE_LEAF_PSEUDO_CIRCUIT: &str = "$InputStateLeaf"; pub const STATE_LEAF_PSEUDO_CIRCUIT: &str = "$InputStateLeaf";
impl Input { impl<'a> Input<'a> {
fn make_header(name: &str) -> Arc<Circuit> { fn make_header(scope: &'a Scope<'a>, name: &str) -> &'a Circuit<'a> {
Arc::new(Circuit { scope.alloc_circuit(Circuit {
id: uuid::Uuid::new_v4(), id: uuid::Uuid::new_v4(),
name: RefCell::new(Identifier::new(name.to_string())), name: RefCell::new(Identifier::new(name.to_string())),
body: RefCell::new(Weak::new()),
members: RefCell::new(IndexMap::new()), members: RefCell::new(IndexMap::new()),
core_mapping: RefCell::new(None), core_mapping: RefCell::new(None),
scope,
span: Default::default(),
}) })
} }
fn make_body(scope: &Scope, circuit: &Arc<Circuit>) -> Arc<CircuitBody> { pub fn new(scope: &'a Scope<'a>) -> Self {
let body = Arc::new(CircuitBody { let input_scope = scope.make_subscope();
scope: scope.clone(), let registers = Self::make_header(input_scope, REGISTERS_PSEUDO_CIRCUIT);
span: None, let record = Self::make_header(input_scope, RECORD_PSEUDO_CIRCUIT);
circuit: circuit.clone(), let state = Self::make_header(input_scope, STATE_PSEUDO_CIRCUIT);
members: RefCell::new(IndexMap::new()), let state_leaf = Self::make_header(input_scope, STATE_LEAF_PSEUDO_CIRCUIT);
});
circuit.body.replace(Arc::downgrade(&body));
body
}
pub fn new(scope: &Scope) -> Self {
let registers = Self::make_header(REGISTERS_PSEUDO_CIRCUIT);
let record = Self::make_header(RECORD_PSEUDO_CIRCUIT);
let state = Self::make_header(STATE_PSEUDO_CIRCUIT);
let state_leaf = Self::make_header(STATE_LEAF_PSEUDO_CIRCUIT);
let mut container_members = IndexMap::new(); let mut container_members = IndexMap::new();
container_members.insert( container_members.insert(
"registers".to_string(), "registers".to_string(),
CircuitMember::Variable(WeakType::Circuit(Arc::downgrade(&registers))), CircuitMember::Variable(Type::Circuit(registers)),
);
container_members.insert(
"record".to_string(),
CircuitMember::Variable(WeakType::Circuit(Arc::downgrade(&record))),
);
container_members.insert(
"state".to_string(),
CircuitMember::Variable(WeakType::Circuit(Arc::downgrade(&state))),
); );
container_members.insert("record".to_string(), CircuitMember::Variable(Type::Circuit(record)));
container_members.insert("state".to_string(), CircuitMember::Variable(Type::Circuit(state)));
container_members.insert( container_members.insert(
"state_leaf".to_string(), "state_leaf".to_string(),
CircuitMember::Variable(WeakType::Circuit(Arc::downgrade(&state_leaf))), CircuitMember::Variable(Type::Circuit(state_leaf)),
); );
let container_circuit = Arc::new(Circuit { let container_circuit = input_scope.alloc_circuit(Circuit {
id: uuid::Uuid::new_v4(), id: uuid::Uuid::new_v4(),
name: RefCell::new(Identifier::new(CONTAINER_PSEUDO_CIRCUIT.to_string())), name: RefCell::new(Identifier::new(CONTAINER_PSEUDO_CIRCUIT.to_string())),
body: RefCell::new(Weak::new()),
members: RefCell::new(container_members), members: RefCell::new(container_members),
core_mapping: RefCell::new(None), core_mapping: RefCell::new(None),
scope: input_scope,
span: Default::default(),
}); });
let registers_body = Self::make_body(scope, &registers);
let record_body = Self::make_body(scope, &record);
let state_body = Self::make_body(scope, &state);
let state_leaf_body = Self::make_body(scope, &state_leaf);
let mut container_body_members = IndexMap::new();
container_body_members.insert(
"registers".to_string(),
CircuitMemberBody::Variable(Type::Circuit(registers)),
);
container_body_members.insert("record".to_string(), CircuitMemberBody::Variable(Type::Circuit(record)));
container_body_members.insert("state".to_string(), CircuitMemberBody::Variable(Type::Circuit(state)));
container_body_members.insert(
"state_leaf".to_string(),
CircuitMemberBody::Variable(Type::Circuit(state_leaf)),
);
let container_circuit_body = Arc::new(CircuitBody {
scope: scope.clone(),
span: None,
circuit: container_circuit.clone(),
members: RefCell::new(container_body_members),
});
container_circuit.body.replace(Arc::downgrade(&container_circuit_body));
Input { Input {
registers: registers_body, registers,
record: record_body, record,
state: state_body, state,
state_leaf: state_leaf_body, state_leaf,
container_circuit: container_circuit_body, container_circuit,
container: Arc::new(RefCell::new(crate::InnerVariable { container: input_scope.alloc_variable(RefCell::new(crate::InnerVariable {
id: uuid::Uuid::new_v4(), id: uuid::Uuid::new_v4(),
name: Identifier::new("input".to_string()), name: Identifier::new("input".to_string()),
type_: Type::Circuit(container_circuit).weak(), type_: Type::Circuit(container_circuit),
mutable: false, mutable: false,
const_: false, const_: false,
declaration: crate::VariableDeclaration::Input, declaration: crate::VariableDeclaration::Input,
@ -138,7 +96,7 @@ impl Input {
} }
} }
impl Circuit { impl<'a> Circuit<'a> {
pub fn is_input_pseudo_circuit(&self) -> bool { pub fn is_input_pseudo_circuit(&self) -> bool {
matches!( matches!(
&*self.name.borrow().name, &*self.name.borrow().name,

View File

@ -65,11 +65,17 @@ pub mod type_;
pub use type_::*; pub use type_::*;
pub mod variable; pub mod variable;
use typed_arena::Arena;
pub use variable::*; pub use variable::*;
pub mod pass;
pub use pass::*;
pub use leo_ast::{Ast, Identifier, Span}; pub use leo_ast::{Ast, Identifier, Span};
use std::{cell::RefCell, path::Path, sync::Arc}; pub type AsgContext<'a> = &'a Arena<ArenaNode<'a>>;
use std::path::Path;
/// The abstract semantic graph (ASG) for a Leo program. /// The abstract semantic graph (ASG) for a Leo program.
/// ///
@ -77,21 +83,27 @@ use std::{cell::RefCell, path::Path, sync::Arc};
/// These data types form a graph that begins from a [`Program`] type node. /// These data types form a graph that begins from a [`Program`] type node.
/// ///
/// A new [`Asg`] can be created from an [`Ast`] generated in the `ast` module. /// A new [`Asg`] can be created from an [`Ast`] generated in the `ast` module.
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct Asg { pub struct Asg<'a> {
asg: Arc<RefCell<InternalProgram>>, context: AsgContext<'a>,
asg: Program<'a>,
} }
impl Asg { impl<'a> Asg<'a> {
/// Creates a new ASG from a given AST and import resolver. /// Creates a new ASG from a given AST and import resolver.
pub fn new<T: ImportResolver + 'static>(ast: &Ast, resolver: &mut T) -> Result<Self, AsgConvertError> { pub fn new<T: ImportResolver<'a>>(
context: AsgContext<'a>,
ast: &Ast,
resolver: &mut T,
) -> Result<Self, AsgConvertError> {
Ok(Self { Ok(Self {
asg: InternalProgram::new(&ast.as_repr(), resolver)?, context,
asg: InternalProgram::new(context, &ast.as_repr(), resolver)?,
}) })
} }
/// Returns the internal program ASG representation. /// Returns the internal program ASG representation.
pub fn as_repr(&self) -> Arc<RefCell<InternalProgram>> { pub fn as_repr(&self) -> Program<'a> {
self.asg.clone() self.asg.clone()
} }
@ -108,10 +120,18 @@ impl Asg {
} }
// TODO (howardwu): Remove this. // TODO (howardwu): Remove this.
pub fn load_asg<T: ImportResolver + 'static>(content: &str, resolver: &mut T) -> Result<Program, AsgConvertError> { pub fn load_asg<'a, T: ImportResolver<'a>>(
context: AsgContext<'a>,
content: &str,
resolver: &mut T,
) -> Result<Program<'a>, AsgConvertError> {
// Parses the Leo file and constructs a grammar ast. // Parses the Leo file and constructs a grammar ast.
let ast = leo_grammar::Grammar::new(&Path::new("input.leo"), content) let ast = leo_grammar::Grammar::new(&Path::new("input.leo"), content)
.map_err(|e| AsgConvertError::InternalError(format!("ast: {:?}", e)))?; .map_err(|e| AsgConvertError::InternalError(format!("ast: {:?}", e)))?;
InternalProgram::new(leo_ast::Ast::new("load_ast", &ast)?.as_repr(), resolver) InternalProgram::new(context, leo_ast::Ast::new("load_ast", &ast)?.as_repr(), resolver)
}
pub fn new_context<'a>() -> Arena<ArenaNode<'a>> {
Arena::new()
} }

View File

@ -14,15 +14,28 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{AsgConvertError, PartialType, Scope, Span}; use crate::{AsgConvertError, Circuit, Expression, Function, PartialType, Scope, Span, Statement, Variable};
/// A node in the abstract semantic graph. /// A node in the abstract semantic graph.
pub trait Node { pub trait Node {
fn span(&self) -> Option<&Span>; fn span(&self) -> Option<&Span>;
} }
pub(super) trait FromAst<T: leo_ast::Node + 'static>: Sized + 'static { pub(super) trait FromAst<'a, T: leo_ast::Node + 'static>: Sized {
// expected_type contract: if present, output expression must be of type expected_type. // expected_type contract: if present, output expression must be of type expected_type.
// type of an element may NEVER be None unless it is functionally a non-expression. (static call targets, function ref call targets are not expressions) // type of an element may NEVER be None unless it is functionally a non-expression. (static call targets, function ref call targets are not expressions)
fn from_ast(scope: &Scope, value: &T, expected_type: Option<PartialType>) -> Result<Self, AsgConvertError>; fn from_ast(
scope: &'a Scope<'a>,
value: &T,
expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError>;
}
pub enum ArenaNode<'a> {
Expression(Expression<'a>),
Scope(Scope<'a>),
Statement(Statement<'a>),
Variable(Variable<'a>),
Circuit(Circuit<'a>),
Function(Function<'a>),
} }

22
asg/src/pass.rs Normal file
View File

@ -0,0 +1,22 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::Program;
pub use leo_ast::Error as FormattedError;
pub trait AsgPass {
fn do_pass(asg: &Program) -> Result<(), FormattedError>;
}

View File

@ -16,15 +16,16 @@
// TODO (protryon): We should merge this with core // TODO (protryon): We should merge this with core
use crate::{AsgConvertError, Program}; use crate::{AsgContext, AsgConvertError, Program};
// TODO (protryon): Make asg deep copy so we can cache resolved core modules // TODO (protryon): Make asg deep copy so we can cache resolved core modules
// TODO (protryon): Figure out how to do headers without bogus returns // TODO (protryon): Figure out how to do headers without bogus returns
pub fn resolve_core_module(module: &str) -> Result<Option<Program>, AsgConvertError> { pub fn resolve_core_module<'a>(context: AsgContext<'a>, module: &str) -> Result<Option<Program<'a>>, AsgConvertError> {
match module { match module {
"unstable.blake2s" => { "unstable.blake2s" => {
let asg = crate::load_asg( let asg = crate::load_asg(
context,
r#" r#"
circuit Blake2s { circuit Blake2s {
function hash(seed: [u8; 32], message: [u8; 32]) -> [u8; 32] { function hash(seed: [u8; 32], message: [u8; 32]) -> [u8; 32] {
@ -34,7 +35,7 @@ pub fn resolve_core_module(module: &str) -> Result<Option<Program>, AsgConvertEr
"#, "#,
&mut crate::NullImportResolver, &mut crate::NullImportResolver,
)?; )?;
asg.borrow().set_core_mapping("blake2s"); asg.set_core_mapping("blake2s");
Ok(Some(asg)) Ok(Some(asg))
} }
_ => Ok(None), _ => Ok(None),

View File

@ -14,37 +14,29 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{AsgConvertError, Function, FunctionBody, Identifier, InnerScope, Node, Scope, Span, Type, WeakType}; use crate::{AsgConvertError, Function, Identifier, Node, Scope, Span, Type};
use indexmap::IndexMap; use indexmap::IndexMap;
use std::{ use std::cell::RefCell;
cell::RefCell,
sync::{Arc, Weak},
};
use uuid::Uuid; use uuid::Uuid;
#[derive(Debug)] #[derive(Clone)]
pub enum CircuitMemberBody { pub enum CircuitMember<'a> {
Variable(Type), Variable(Type<'a>),
Function(Arc<FunctionBody>), Function(&'a Function<'a>),
} }
#[derive(Debug)] #[derive(Clone)]
pub enum CircuitMember { pub struct Circuit<'a> {
Variable(WeakType),
Function(Arc<Function>),
}
#[derive(Debug)]
pub struct Circuit {
pub id: Uuid, pub id: Uuid,
pub name: RefCell<Identifier>, pub name: RefCell<Identifier>,
pub core_mapping: RefCell<Option<String>>, pub core_mapping: RefCell<Option<String>>,
pub body: RefCell<Weak<CircuitBody>>, pub scope: &'a Scope<'a>,
pub members: RefCell<IndexMap<String, CircuitMember>>, pub span: Option<Span>,
pub members: RefCell<IndexMap<String, CircuitMember<'a>>>,
} }
impl PartialEq for Circuit { impl<'a> PartialEq for Circuit<'a> {
fn eq(&self, other: &Circuit) -> bool { fn eq(&self, other: &Circuit) -> bool {
if self.name != other.name { if self.name != other.name {
return false; return false;
@ -52,81 +44,30 @@ impl PartialEq for Circuit {
self.id == other.id self.id == other.id
} }
} }
impl Eq for Circuit {}
#[derive(Debug)] impl<'a> Eq for Circuit<'a> {}
pub struct CircuitBody {
pub scope: Scope,
pub span: Option<Span>,
pub circuit: Arc<Circuit>,
pub members: RefCell<IndexMap<String, CircuitMemberBody>>,
}
impl PartialEq for CircuitBody { impl<'a> Node for Circuit<'a> {
fn eq(&self, other: &CircuitBody) -> bool {
self.circuit == other.circuit
}
}
impl Eq for CircuitBody {}
impl Node for CircuitMemberBody {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
None self.span.as_ref()
} }
} }
impl Circuit { impl<'a> Circuit<'a> {
pub(super) fn init(value: &leo_ast::Circuit) -> Arc<Circuit> { pub(super) fn init(scope: &'a Scope<'a>, value: &leo_ast::Circuit) -> Result<&'a Circuit<'a>, AsgConvertError> {
Arc::new(Circuit { let new_scope = scope.make_subscope();
let circuit = scope.alloc_circuit(Circuit {
id: Uuid::new_v4(), id: Uuid::new_v4(),
name: RefCell::new(value.circuit_name.clone()), name: RefCell::new(value.circuit_name.clone()),
body: RefCell::new(Weak::new()),
members: RefCell::new(IndexMap::new()), members: RefCell::new(IndexMap::new()),
core_mapping: RefCell::new(None), core_mapping: RefCell::new(None),
}) span: Some(value.circuit_name.span.clone()),
} scope: new_scope,
});
pub(super) fn from_ast(self: Arc<Circuit>, scope: &Scope, value: &leo_ast::Circuit) -> Result<(), AsgConvertError> { new_scope.circuit_self.replace(Some(circuit));
let new_scope = InnerScope::make_subscope(scope); // temporary scope for function headers
new_scope.borrow_mut().circuit_self = Some(self.clone());
let mut members = self.members.borrow_mut();
for member in value.members.iter() {
match member {
leo_ast::CircuitMember::CircuitVariable(name, type_) => {
members.insert(
name.name.clone(),
CircuitMember::Variable(new_scope.borrow().resolve_ast_type(type_)?.into()),
);
}
leo_ast::CircuitMember::CircuitFunction(function) => {
let asg_function = Arc::new(Function::from_ast(&new_scope, function)?);
members.insert(function.identifier.name.clone(), CircuitMember::Function(asg_function));
}
}
}
for (_, member) in members.iter() {
if let CircuitMember::Function(func) = member {
func.circuit.borrow_mut().replace(Arc::downgrade(&self));
}
}
Ok(())
}
}
impl CircuitBody {
pub(super) fn from_ast(
scope: &Scope,
value: &leo_ast::Circuit,
circuit: Arc<Circuit>,
) -> Result<CircuitBody, AsgConvertError> {
let mut members = IndexMap::new();
let new_scope = InnerScope::make_subscope(scope);
new_scope.borrow_mut().circuit_self = Some(circuit.clone());
let mut members = circuit.members.borrow_mut();
for member in value.members.iter() { for member in value.members.iter() {
match member { match member {
leo_ast::CircuitMember::CircuitVariable(name, type_) => { leo_ast::CircuitMember::CircuitVariable(name, type_) => {
@ -139,7 +80,7 @@ impl CircuitBody {
} }
members.insert( members.insert(
name.name.clone(), name.name.clone(),
CircuitMemberBody::Variable(new_scope.borrow().resolve_ast_type(type_)?), CircuitMember::Variable(new_scope.resolve_ast_type(type_)?),
); );
} }
leo_ast::CircuitMember::CircuitFunction(function) => { leo_ast::CircuitMember::CircuitFunction(function) => {
@ -150,51 +91,51 @@ impl CircuitBody {
&function.identifier.span, &function.identifier.span,
)); ));
} }
let asg_function = { let asg_function = Function::init(new_scope, function)?;
let circuit_members = circuit.members.borrow(); asg_function.circuit.replace(Some(circuit));
match circuit_members.get(&function.identifier.name).unwrap() { members.insert(function.identifier.name.clone(), CircuitMember::Function(asg_function));
CircuitMember::Function(f) => f.clone(),
_ => unimplemented!(),
}
};
let function_body = Arc::new(FunctionBody::from_ast(&new_scope, function, asg_function.clone())?);
asg_function.body.replace(Arc::downgrade(&function_body));
members.insert(
function.identifier.name.clone(),
CircuitMemberBody::Function(function_body),
);
} }
} }
} }
Ok(CircuitBody { Ok(circuit)
span: Some(value.circuit_name.span.clone()), }
circuit,
members: RefCell::new(members), pub(super) fn fill_from_ast(self: &'a Circuit<'a>, value: &leo_ast::Circuit) -> Result<(), AsgConvertError> {
scope: scope.clone(), for member in value.members.iter() {
}) match member {
leo_ast::CircuitMember::CircuitVariable(..) => {}
leo_ast::CircuitMember::CircuitFunction(function) => {
let asg_function = match *self
.members
.borrow()
.get(&function.identifier.name)
.expect("missing header for defined circuit function")
{
CircuitMember::Function(f) => f,
_ => unimplemented!(),
};
Function::fill_from_ast(asg_function, function)?;
}
}
}
Ok(())
} }
} }
impl Into<leo_ast::Circuit> for &Circuit { impl<'a> Into<leo_ast::Circuit> for &Circuit<'a> {
fn into(self) -> leo_ast::Circuit { fn into(self) -> leo_ast::Circuit {
let members = match self.body.borrow().upgrade() { let members = self
Some(body) => body .members
.members .borrow()
.borrow() .iter()
.iter() .map(|(name, member)| match &member {
.map(|(name, member)| match &member { CircuitMember::Variable(type_) => {
CircuitMemberBody::Variable(type_) => { leo_ast::CircuitMember::CircuitVariable(Identifier::new(name.clone()), type_.into())
leo_ast::CircuitMember::CircuitVariable(Identifier::new(name.clone()), type_.into()) }
} CircuitMember::Function(func) => leo_ast::CircuitMember::CircuitFunction((*func).into()),
CircuitMemberBody::Function(func) => { })
leo_ast::CircuitMember::CircuitFunction(func.function.as_ref().into()) .collect();
}
})
.collect(),
None => vec![],
};
leo_ast::Circuit { leo_ast::Circuit {
circuit_name: self.name.borrow().clone(), circuit_name: self.name.borrow().clone(),
members, members,

View File

@ -20,7 +20,6 @@ use crate::{
Circuit, Circuit,
FromAst, FromAst,
Identifier, Identifier,
InnerScope,
MonoidalDirector, MonoidalDirector,
ReturnPathReducer, ReturnPathReducer,
Scope, Scope,
@ -28,72 +27,58 @@ use crate::{
Statement, Statement,
Type, Type,
Variable, Variable,
WeakType,
}; };
use indexmap::IndexMap;
use leo_ast::FunctionInput; use leo_ast::FunctionInput;
use std::{ use std::cell::{Cell, RefCell};
cell::RefCell,
sync::{Arc, Weak},
};
use uuid::Uuid; use uuid::Uuid;
#[derive(Debug, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub enum FunctionQualifier { pub enum FunctionQualifier {
SelfRef, SelfRef,
MutSelfRef, MutSelfRef,
Static, Static,
} }
#[derive(Debug)] #[derive(Clone)]
pub struct Function { pub struct Function<'a> {
pub id: Uuid, pub id: Uuid,
pub name: RefCell<Identifier>, pub name: RefCell<Identifier>,
pub output: WeakType, pub output: Type<'a>,
pub has_input: bool, pub has_input: bool,
pub arguments: Vec<Variable>, pub arguments: IndexMap<String, Cell<&'a Variable<'a>>>,
pub circuit: RefCell<Option<Weak<Circuit>>>, pub circuit: Cell<Option<&'a Circuit<'a>>>,
pub body: RefCell<Weak<FunctionBody>>, pub span: Option<Span>,
pub body: Cell<Option<&'a Statement<'a>>>,
pub scope: &'a Scope<'a>,
pub qualifier: FunctionQualifier, pub qualifier: FunctionQualifier,
} }
impl PartialEq for Function { impl<'a> PartialEq for Function<'a> {
fn eq(&self, other: &Function) -> bool { fn eq(&self, other: &Function<'a>) -> bool {
if self.name.borrow().name != other.name.borrow().name { if self.name.borrow().name != other.name.borrow().name {
return false; return false;
} }
self.id == other.id self.id == other.id
} }
} }
impl Eq for Function {}
#[derive(Debug)] impl<'a> Eq for Function<'a> {}
pub struct FunctionBody {
pub span: Option<Span>,
pub function: Arc<Function>,
pub body: Arc<Statement>,
pub scope: Scope,
}
impl PartialEq for FunctionBody { impl<'a> Function<'a> {
fn eq(&self, other: &FunctionBody) -> bool { pub(crate) fn init(scope: &'a Scope<'a>, value: &leo_ast::Function) -> Result<&'a Function<'a>, AsgConvertError> {
self.function == other.function let output: Type<'a> = value
}
}
impl Eq for FunctionBody {}
impl Function {
pub(crate) fn from_ast(scope: &Scope, value: &leo_ast::Function) -> Result<Function, AsgConvertError> {
let output: Type = value
.output .output
.as_ref() .as_ref()
.map(|t| scope.borrow().resolve_ast_type(t)) .map(|t| scope.resolve_ast_type(t))
.transpose()? .transpose()?
.unwrap_or_else(|| Type::Tuple(vec![])); .unwrap_or_else(|| Type::Tuple(vec![]));
let mut qualifier = FunctionQualifier::Static; let mut qualifier = FunctionQualifier::Static;
let mut has_input = false; let mut has_input = false;
let new_scope = scope.make_subscope();
let mut arguments = vec![]; let mut arguments = IndexMap::new();
{ {
for input in value.input.iter() { for input in value.input.iter() {
match input { match input {
@ -107,77 +92,74 @@ impl Function {
qualifier = FunctionQualifier::MutSelfRef; qualifier = FunctionQualifier::MutSelfRef;
} }
FunctionInput::Variable(leo_ast::FunctionInputVariable { FunctionInput::Variable(leo_ast::FunctionInputVariable {
identifier,
mutable,
const_,
type_, type_,
span: _span, identifier,
const_,
mutable,
..
}) => { }) => {
let variable = Arc::new(RefCell::new(crate::InnerVariable { let variable = scope.alloc_variable(RefCell::new(crate::InnerVariable {
id: Uuid::new_v4(), id: Uuid::new_v4(),
name: identifier.clone(), name: identifier.clone(),
type_: scope.borrow().resolve_ast_type(&type_)?.weak(), type_: scope.resolve_ast_type(&type_)?,
mutable: *mutable, mutable: *mutable,
const_: *const_, const_: *const_,
declaration: crate::VariableDeclaration::Parameter, declaration: crate::VariableDeclaration::Parameter,
references: vec![], references: vec![],
assignments: vec![], assignments: vec![],
})); }));
arguments.push(variable.clone()); arguments.insert(identifier.name.clone(), Cell::new(&*variable));
} }
} }
} }
} }
if qualifier != FunctionQualifier::Static && scope.borrow().circuit_self.is_none() { if qualifier != FunctionQualifier::Static && scope.circuit_self.get().is_none() {
return Err(AsgConvertError::invalid_self_in_global(&value.span)); return Err(AsgConvertError::invalid_self_in_global(&value.span));
} }
Ok(Function { let function = scope.alloc_function(Function {
id: Uuid::new_v4(), id: Uuid::new_v4(),
name: RefCell::new(value.identifier.clone()), name: RefCell::new(value.identifier.clone()),
output: output.into(), output,
has_input, has_input,
arguments, arguments,
circuit: RefCell::new(None), circuit: Cell::new(None),
body: RefCell::new(Weak::new()), body: Cell::new(None),
qualifier, qualifier,
}) scope: new_scope,
} span: Some(value.span.clone()),
} });
function.scope.function.replace(Some(function));
impl FunctionBody { Ok(function)
pub(super) fn from_ast( }
scope: &Scope,
value: &leo_ast::Function, pub(super) fn fill_from_ast(self: &'a Function<'a>, value: &leo_ast::Function) -> Result<(), AsgConvertError> {
function: Arc<Function>, if self.qualifier != FunctionQualifier::Static {
) -> Result<FunctionBody, AsgConvertError> { let circuit = self.circuit.get();
let new_scope = InnerScope::make_subscope(scope); let self_variable = self.scope.alloc_variable(RefCell::new(crate::InnerVariable {
{ id: Uuid::new_v4(),
let mut scope_borrow = new_scope.borrow_mut(); name: Identifier::new("self".to_string()),
if function.qualifier != FunctionQualifier::Static { type_: Type::Circuit(circuit.as_ref().unwrap()),
let circuit = function.circuit.borrow(); mutable: self.qualifier == FunctionQualifier::MutSelfRef,
let self_variable = Arc::new(RefCell::new(crate::InnerVariable { const_: false,
id: Uuid::new_v4(), declaration: crate::VariableDeclaration::Parameter,
name: Identifier::new("self".to_string()), references: vec![],
type_: WeakType::Circuit(circuit.as_ref().unwrap().clone()), assignments: vec![],
mutable: function.qualifier == FunctionQualifier::MutSelfRef, }));
const_: false, self.scope
declaration: crate::VariableDeclaration::Parameter, .variables
references: vec![], .borrow_mut()
assignments: vec![], .insert("self".to_string(), self_variable);
}));
scope_borrow.variables.insert("self".to_string(), self_variable);
}
scope_borrow.function = Some(function.clone());
for argument in function.arguments.iter() {
let name = argument.borrow().name.name.clone();
scope_borrow.variables.insert(name, argument.clone());
}
} }
let main_block = BlockStatement::from_ast(&new_scope, &value.block, None)?; for (name, argument) in self.arguments.iter() {
self.scope.variables.borrow_mut().insert(name.clone(), argument.get());
}
let main_block = BlockStatement::from_ast(self.scope, &value.block, None)?;
let mut director = MonoidalDirector::new(ReturnPathReducer::new()); let mut director = MonoidalDirector::new(ReturnPathReducer::new());
if !director.reduce_block(&main_block).0 && !function.output.is_unit() { if !director.reduce_block(&main_block).0 && !self.output.is_unit() {
return Err(AsgConvertError::function_missing_return( return Err(AsgConvertError::function_missing_return(
&function.name.borrow().name, &self.name.borrow().name,
&value.span, &value.span,
)); ));
} }
@ -185,47 +167,39 @@ impl FunctionBody {
#[allow(clippy::never_loop)] // TODO @Protryon: How should we return multiple errors? #[allow(clippy::never_loop)] // TODO @Protryon: How should we return multiple errors?
for (span, error) in director.reducer().errors { for (span, error) in director.reducer().errors {
return Err(AsgConvertError::function_return_validation( return Err(AsgConvertError::function_return_validation(
&function.name.borrow().name, &self.name.borrow().name,
&error, &error,
&span, &span,
)); ));
} }
Ok(FunctionBody { self.body
span: Some(value.span.clone()), .replace(Some(self.scope.alloc_statement(Statement::Block(main_block))));
function,
body: Arc::new(Statement::Block(main_block)), Ok(())
scope: new_scope,
})
} }
} }
impl Into<leo_ast::Function> for &Function { impl<'a> Into<leo_ast::Function> for &Function<'a> {
fn into(self) -> leo_ast::Function { fn into(self) -> leo_ast::Function {
let (input, body, span) = match self.body.borrow().upgrade() { let input = self
Some(body) => ( .arguments
body.function .iter()
.arguments .map(|(_, variable)| {
.iter() let variable = variable.get().borrow();
.map(|variable| { leo_ast::FunctionInput::Variable(leo_ast::FunctionInputVariable {
let variable = variable.borrow(); identifier: variable.name.clone(),
leo_ast::FunctionInput::Variable(leo_ast::FunctionInputVariable { mutable: variable.mutable,
identifier: variable.name.clone(), const_: variable.const_,
mutable: variable.mutable, type_: (&variable.type_).into(),
const_: variable.const_, span: Span::default(),
type_: (&variable.type_.clone().strong()).into(), })
span: Span::default(), })
}) .collect();
}) let (body, span) = match self.body.get() {
.collect(), Some(Statement::Block(block)) => (block.into(), block.span.clone().unwrap_or_default()),
match body.body.as_ref() { Some(_) => unimplemented!(),
Statement::Block(block) => block.into(),
_ => unimplemented!(),
},
body.span.clone().unwrap_or_default(),
),
None => ( None => (
vec![],
leo_ast::Block { leo_ast::Block {
statements: vec![], statements: vec![],
span: Default::default(), span: Default::default(),
@ -233,7 +207,7 @@ impl Into<leo_ast::Function> for &Function {
Default::default(), Default::default(),
), ),
}; };
let output: Type = self.output.clone().into(); let output: Type = self.output.clone();
leo_ast::Function { leo_ast::Function {
identifier: self.name.borrow().clone(), identifier: self.name.borrow().clone(),
input, input,

View File

@ -24,16 +24,18 @@ pub use circuit::*;
mod function; mod function;
pub use function::*; pub use function::*;
use crate::{AsgConvertError, ImportResolver, InnerScope, Input, Scope}; use crate::{ArenaNode, AsgContext, AsgConvertError, ImportResolver, Input, Scope};
use leo_ast::{Identifier, PackageAccess, PackageOrPackages, Span}; use leo_ast::{Identifier, PackageAccess, PackageOrPackages, Span};
use indexmap::IndexMap; use indexmap::IndexMap;
use std::{cell::RefCell, sync::Arc}; use std::cell::{Cell, RefCell};
use uuid::Uuid; use uuid::Uuid;
/// Stores the Leo program abstract semantic graph (ASG). /// Stores the Leo program abstract semantic graph (ASG).
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct InternalProgram { pub struct InternalProgram<'a> {
pub context: AsgContext<'a>,
/// The unique id of the program. /// The unique id of the program.
pub id: Uuid, pub id: Uuid,
@ -42,24 +44,25 @@ pub struct InternalProgram {
/// The packages imported by this program. /// The packages imported by this program.
/// these should generally not be accessed directly, but through scoped imports /// these should generally not be accessed directly, but through scoped imports
pub imported_modules: IndexMap<String, Program>, pub imported_modules: IndexMap<String, Program<'a>>,
/// Maps test name => test code block. /// Maps test name => test code block.
pub test_functions: IndexMap<String, (Arc<FunctionBody>, Option<Identifier>)>, // identifier = test input file pub test_functions: IndexMap<String, (&'a Function<'a>, Option<Identifier>)>, // identifier = test input file
/// Maps function name => function code block. /// Maps function name => function code block.
pub functions: IndexMap<String, Arc<FunctionBody>>, pub functions: IndexMap<String, &'a Function<'a>>,
/// Maps circuit name => circuit code block. /// Maps circuit name => circuit code block.
pub circuits: IndexMap<String, Arc<CircuitBody>>, pub circuits: IndexMap<String, &'a Circuit<'a>>,
/// Bindings for names and additional program context. /// Bindings for names and additional program context.
pub scope: Scope, pub scope: &'a Scope<'a>,
} }
pub type Program = Arc<RefCell<InternalProgram>>; pub type Program<'a> = InternalProgram<'a>;
/// Enumerates what names are imported from a package. /// Enumerates what names are imported from a package.
#[derive(Clone)]
enum ImportSymbol { enum ImportSymbol {
/// Import the symbol by name. /// Import the symbol by name.
Direct(String), Direct(String),
@ -124,7 +127,7 @@ fn resolve_import_package_access(
} }
} }
impl InternalProgram { impl<'a> InternalProgram<'a> {
/// Returns a new Leo program ASG from the given Leo program AST and its imports. /// Returns a new Leo program ASG from the given Leo program AST and its imports.
/// ///
/// Stages: /// Stages:
@ -133,10 +136,11 @@ impl InternalProgram {
/// 3. finalize declared functions /// 3. finalize declared functions
/// 4. resolve all asg nodes /// 4. resolve all asg nodes
/// ///
pub fn new<T: ImportResolver + 'static>( pub fn new<T: ImportResolver<'a>>(
arena: AsgContext<'a>,
program: &leo_ast::Program, program: &leo_ast::Program,
import_resolver: &mut T, import_resolver: &mut T,
) -> Result<Program, AsgConvertError> { ) -> Result<Program<'a>, AsgConvertError> {
// Recursively extract imported symbols. // Recursively extract imported symbols.
let mut imported_symbols: Vec<(Vec<String>, ImportSymbol, Span)> = vec![]; let mut imported_symbols: Vec<(Vec<String>, ImportSymbol, Span)> = vec![];
for import in program.imports.iter() { for import in program.imports.iter() {
@ -149,24 +153,27 @@ impl InternalProgram {
deduplicated_imports.insert(package.clone(), span.clone()); deduplicated_imports.insert(package.clone(), span.clone());
} }
let mut wrapped_resolver = crate::CoreImportResolver(import_resolver); let mut wrapped_resolver = crate::CoreImportResolver::new(import_resolver);
// Load imported programs. // Load imported programs.
let mut resolved_packages: IndexMap<Vec<String>, Program> = IndexMap::new(); let mut resolved_packages: IndexMap<Vec<String>, Program> = IndexMap::new();
for (package, span) in deduplicated_imports.iter() { for (package, span) in deduplicated_imports.iter() {
let pretty_package = package.join("."); let pretty_package = package.join(".");
let resolved_package = let resolved_package = match wrapped_resolver.resolve_package(
match wrapped_resolver.resolve_package(&package.iter().map(|x| &**x).collect::<Vec<_>>()[..], span)? { arena,
Some(x) => x, &package.iter().map(|x| &**x).collect::<Vec<_>>()[..],
None => return Err(AsgConvertError::unresolved_import(&*pretty_package, &Span::default())), span,
}; )? {
Some(x) => x,
None => return Err(AsgConvertError::unresolved_import(&*pretty_package, &Span::default())),
};
resolved_packages.insert(package.clone(), resolved_package); resolved_packages.insert(package.clone(), resolved_package);
} }
let mut imported_functions: IndexMap<String, Arc<FunctionBody>> = IndexMap::new(); let mut imported_functions: IndexMap<String, &'a Function<'a>> = IndexMap::new();
let mut imported_circuits: IndexMap<String, Arc<CircuitBody>> = IndexMap::new(); let mut imported_circuits: IndexMap<String, &'a Circuit<'a>> = IndexMap::new();
// Prepare locally relevant scope of imports. // Prepare locally relevant scope of imports.
for (package, symbol, span) in imported_symbols.into_iter() { for (package, symbol, span) in imported_symbols.into_iter() {
@ -175,7 +182,6 @@ impl InternalProgram {
let resolved_package = resolved_packages let resolved_package = resolved_packages
.get(&package) .get(&package)
.expect("could not find preloaded package"); .expect("could not find preloaded package");
let resolved_package = resolved_package.borrow();
match symbol { match symbol {
ImportSymbol::All => { ImportSymbol::All => {
imported_functions.extend(resolved_package.functions.clone().into_iter()); imported_functions.extend(resolved_package.functions.clone().into_iter());
@ -183,9 +189,9 @@ impl InternalProgram {
} }
ImportSymbol::Direct(name) => { ImportSymbol::Direct(name) => {
if let Some(function) = resolved_package.functions.get(&name) { if let Some(function) = resolved_package.functions.get(&name) {
imported_functions.insert(name.clone(), function.clone()); imported_functions.insert(name.clone(), *function);
} else if let Some(function) = resolved_package.circuits.get(&name) { } else if let Some(circuit) = resolved_package.circuits.get(&name) {
imported_circuits.insert(name.clone(), function.clone()); imported_circuits.insert(name.clone(), *circuit);
} else { } else {
return Err(AsgConvertError::unresolved_import( return Err(AsgConvertError::unresolved_import(
&*format!("{}.{}", pretty_package, name), &*format!("{}.{}", pretty_package, name),
@ -195,9 +201,9 @@ impl InternalProgram {
} }
ImportSymbol::Alias(name, alias) => { ImportSymbol::Alias(name, alias) => {
if let Some(function) = resolved_package.functions.get(&name) { if let Some(function) = resolved_package.functions.get(&name) {
imported_functions.insert(alias.clone(), function.clone()); imported_functions.insert(alias.clone(), *function);
} else if let Some(function) = resolved_package.circuits.get(&name) { } else if let Some(circuit) = resolved_package.circuits.get(&name) {
imported_circuits.insert(alias.clone(), function.clone()); imported_circuits.insert(alias.clone(), *circuit);
} else { } else {
return Err(AsgConvertError::unresolved_import( return Err(AsgConvertError::unresolved_import(
&*format!("{}.{}", pretty_package, name), &*format!("{}.{}", pretty_package, name),
@ -208,71 +214,54 @@ impl InternalProgram {
} }
} }
let import_scope = Arc::new(RefCell::new(InnerScope { let import_scope = match arena.alloc(ArenaNode::Scope(Scope {
arena,
id: uuid::Uuid::new_v4(), id: uuid::Uuid::new_v4(),
parent_scope: None, parent_scope: Cell::new(None),
circuit_self: None, circuit_self: Cell::new(None),
variables: IndexMap::new(), variables: RefCell::new(IndexMap::new()),
functions: imported_functions functions: RefCell::new(imported_functions),
.iter() circuits: RefCell::new(imported_circuits),
.map(|(name, func)| (name.clone(), func.function.clone())) function: Cell::new(None),
.collect(), input: Cell::new(None),
circuits: imported_circuits })) {
.iter() ArenaNode::Scope(c) => c,
.map(|(name, circuit)| (name.clone(), circuit.circuit.clone())) _ => unimplemented!(),
.collect(), };
function: None,
input: None, let scope = import_scope.alloc_scope(Scope {
})); arena,
input: Cell::new(Some(Input::new(import_scope))), // we use import_scope to avoid recursive scope ref here
id: uuid::Uuid::new_v4(),
parent_scope: Cell::new(Some(import_scope)),
circuit_self: Cell::new(None),
variables: RefCell::new(IndexMap::new()),
functions: RefCell::new(IndexMap::new()),
circuits: RefCell::new(IndexMap::new()),
function: Cell::new(None),
});
// Prepare header-like scope entries. // Prepare header-like scope entries.
let mut proto_circuits = IndexMap::new();
for (name, circuit) in program.circuits.iter() { for (name, circuit) in program.circuits.iter() {
assert_eq!(name.name, circuit.circuit_name.name); assert_eq!(name.name, circuit.circuit_name.name);
let asg_circuit = Circuit::init(circuit); let asg_circuit = Circuit::init(scope, circuit)?;
proto_circuits.insert(name.name.clone(), asg_circuit); scope.circuits.borrow_mut().insert(name.name.clone(), asg_circuit);
}
let scope = Arc::new(RefCell::new(InnerScope {
input: Some(Input::new(&import_scope)), // we use import_scope to avoid recursive scope ref here
id: uuid::Uuid::new_v4(),
parent_scope: Some(import_scope),
circuit_self: None,
variables: IndexMap::new(),
functions: IndexMap::new(),
circuits: proto_circuits
.iter()
.map(|(name, circuit)| (name.clone(), circuit.clone()))
.collect(),
function: None,
}));
for (name, circuit) in program.circuits.iter() {
assert_eq!(name.name, circuit.circuit_name.name);
let asg_circuit = proto_circuits.get(&name.name).unwrap();
asg_circuit.clone().from_ast(&scope, &circuit)?;
} }
let mut proto_test_functions = IndexMap::new(); let mut proto_test_functions = IndexMap::new();
for (name, test_function) in program.tests.iter() { for (name, test_function) in program.tests.iter() {
assert_eq!(name.name, test_function.function.identifier.name); assert_eq!(name.name, test_function.function.identifier.name);
let function = Arc::new(Function::from_ast(&scope, &test_function.function)?); let function = Function::init(scope, &test_function.function)?;
proto_test_functions.insert(name.name.clone(), function); proto_test_functions.insert(name.name.clone(), function);
} }
let mut proto_functions = IndexMap::new();
for (name, function) in program.functions.iter() { for (name, function) in program.functions.iter() {
assert_eq!(name.name, function.identifier.name); assert_eq!(name.name, function.identifier.name);
let asg_function = Arc::new(Function::from_ast(&scope, function)?); let function = Function::init(scope, function)?;
scope scope.functions.borrow_mut().insert(name.name.clone(), function);
.borrow_mut()
.functions
.insert(name.name.clone(), asg_function.clone());
proto_functions.insert(name.name.clone(), asg_function);
} }
// Load concrete definitions. // Load concrete definitions.
@ -281,38 +270,33 @@ impl InternalProgram {
assert_eq!(name.name, test_function.function.identifier.name); assert_eq!(name.name, test_function.function.identifier.name);
let function = proto_test_functions.get(&name.name).unwrap(); let function = proto_test_functions.get(&name.name).unwrap();
let body = Arc::new(FunctionBody::from_ast( function.fill_from_ast(&test_function.function)?;
&scope,
&test_function.function,
function.clone(),
)?);
function.body.replace(Arc::downgrade(&body));
test_functions.insert(name.name.clone(), (body, test_function.input_file.clone())); test_functions.insert(name.name.clone(), (*function, test_function.input_file.clone()));
} }
let mut functions = IndexMap::new(); let mut functions = IndexMap::new();
for (name, function) in program.functions.iter() { for (name, function) in program.functions.iter() {
assert_eq!(name.name, function.identifier.name); assert_eq!(name.name, function.identifier.name);
let asg_function = proto_functions.get(&name.name).unwrap(); let asg_function = *scope.functions.borrow().get(&name.name).unwrap();
let body = Arc::new(FunctionBody::from_ast(&scope, function, asg_function.clone())?); asg_function.fill_from_ast(function)?;
asg_function.body.replace(Arc::downgrade(&body));
functions.insert(name.name.clone(), body); functions.insert(name.name.clone(), asg_function);
} }
let mut circuits = IndexMap::new(); let mut circuits = IndexMap::new();
for (name, circuit) in program.circuits.iter() { for (name, circuit) in program.circuits.iter() {
assert_eq!(name.name, circuit.circuit_name.name); assert_eq!(name.name, circuit.circuit_name.name);
let asg_circuit = proto_circuits.get(&name.name).unwrap(); let asg_circuit = *scope.circuits.borrow().get(&name.name).unwrap();
let body = Arc::new(CircuitBody::from_ast(&scope, circuit, asg_circuit.clone())?);
asg_circuit.body.replace(Arc::downgrade(&body));
circuits.insert(name.name.clone(), body); asg_circuit.fill_from_ast(circuit)?;
circuits.insert(name.name.clone(), asg_circuit);
} }
Ok(Arc::new(RefCell::new(InternalProgram { Ok(InternalProgram {
context: arena,
id: Uuid::new_v4(), id: Uuid::new_v4(),
name: program.name.clone(), name: program.name.clone(),
test_functions, test_functions,
@ -323,12 +307,12 @@ impl InternalProgram {
.map(|(package, program)| (package.join("."), program)) .map(|(package, program)| (package.join("."), program))
.collect(), .collect(),
scope, scope,
}))) })
} }
pub(crate) fn set_core_mapping(&self, mapping: &str) { pub(crate) fn set_core_mapping(&self, mapping: &str) {
for (_, circuit) in self.circuits.iter() { for (_, circuit) in self.circuits.iter() {
circuit.circuit.core_mapping.replace(Some(mapping.to_string())); circuit.core_mapping.replace(Some(mapping.to_string()));
} }
} }
} }
@ -347,15 +331,15 @@ impl Iterator for InternalIdentifierGenerator {
} }
} }
/// Returns an AST from the given ASG program. /// Returns an AST from the given ASG program.
pub fn reform_ast(program: &Program) -> leo_ast::Program { pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
let mut all_programs: IndexMap<String, Program> = IndexMap::new(); let mut all_programs: IndexMap<String, Program> = IndexMap::new();
let mut program_stack = program.borrow().imported_modules.clone(); let mut program_stack = program.imported_modules.clone();
while let Some((module, program)) = program_stack.pop() { while let Some((module, program)) = program_stack.pop() {
if all_programs.contains_key(&module) { if all_programs.contains_key(&module) {
continue; continue;
} }
all_programs.insert(module, program.clone()); all_programs.insert(module, program.clone());
program_stack.extend(program.borrow().imported_modules.clone()); program_stack.extend(program.imported_modules.clone());
} }
all_programs.insert("".to_string(), program.clone()); all_programs.insert("".to_string(), program.clone());
let core_programs: Vec<_> = all_programs let core_programs: Vec<_> = all_programs
@ -365,16 +349,15 @@ pub fn reform_ast(program: &Program) -> leo_ast::Program {
.collect(); .collect();
all_programs.retain(|module, _| !module.starts_with("core.")); all_programs.retain(|module, _| !module.starts_with("core."));
let mut all_circuits: IndexMap<String, Arc<CircuitBody>> = IndexMap::new(); let mut all_circuits: IndexMap<String, &'a Circuit<'a>> = IndexMap::new();
let mut all_functions: IndexMap<String, Arc<FunctionBody>> = IndexMap::new(); let mut all_functions: IndexMap<String, &'a Function<'a>> = IndexMap::new();
let mut all_test_functions: IndexMap<String, (Arc<FunctionBody>, Option<Identifier>)> = IndexMap::new(); let mut all_test_functions: IndexMap<String, (&'a Function<'a>, Option<Identifier>)> = IndexMap::new();
let mut identifiers = InternalIdentifierGenerator { next: 0 }; let mut identifiers = InternalIdentifierGenerator { next: 0 };
for (_, program) in all_programs.into_iter() { for (_, program) in all_programs.into_iter() {
let program = program.borrow();
for (name, circuit) in program.circuits.iter() { for (name, circuit) in program.circuits.iter() {
let identifier = format!("{}{}", identifiers.next().unwrap(), name); let identifier = format!("{}{}", identifiers.next().unwrap(), name);
circuit.circuit.name.borrow_mut().name = identifier.clone(); circuit.name.borrow_mut().name = identifier.clone();
all_circuits.insert(identifier, circuit.clone()); all_circuits.insert(identifier, *circuit);
} }
for (name, function) in program.functions.iter() { for (name, function) in program.functions.iter() {
let identifier = if name == "main" { let identifier = if name == "main" {
@ -382,12 +365,12 @@ pub fn reform_ast(program: &Program) -> leo_ast::Program {
} else { } else {
format!("{}{}", identifiers.next().unwrap(), name) format!("{}{}", identifiers.next().unwrap(), name)
}; };
function.function.name.borrow_mut().name = identifier.clone(); function.name.borrow_mut().name = identifier.clone();
all_functions.insert(identifier, function.clone()); all_functions.insert(identifier, *function);
} }
for (name, function) in program.test_functions.iter() { for (name, function) in program.test_functions.iter() {
let identifier = format!("{}{}", identifiers.next().unwrap(), name); let identifier = format!("{}{}", identifiers.next().unwrap(), name);
function.0.function.name.borrow_mut().name = identifier.clone(); function.0.name.borrow_mut().name = identifier.clone();
all_test_functions.insert(identifier, function.clone()); all_test_functions.insert(identifier, function.clone());
} }
} }
@ -409,29 +392,24 @@ pub fn reform_ast(program: &Program) -> leo_ast::Program {
tests: all_test_functions tests: all_test_functions
.into_iter() .into_iter()
.map(|(_, (function, ident))| { .map(|(_, (function, ident))| {
(function.function.name.borrow().clone(), leo_ast::TestFunction { (function.name.borrow().clone(), leo_ast::TestFunction {
function: function.function.as_ref().into(), function: function.into(),
input_file: ident, input_file: ident,
}) })
}) })
.collect(), .collect(),
functions: all_functions functions: all_functions
.into_iter() .into_iter()
.map(|(_, function)| { .map(|(_, function)| (function.name.borrow().clone(), function.into()))
(
function.function.name.borrow().clone(),
function.function.as_ref().into(),
)
})
.collect(), .collect(),
circuits: all_circuits circuits: all_circuits
.into_iter() .into_iter()
.map(|(_, circuit)| (circuit.circuit.name.borrow().clone(), circuit.circuit.as_ref().into())) .map(|(_, circuit)| (circuit.name.borrow().clone(), circuit.into()))
.collect(), .collect(),
} }
} }
impl Into<leo_ast::Program> for &InternalProgram { impl<'a> Into<leo_ast::Program> for &InternalProgram<'a> {
fn into(self) -> leo_ast::Program { fn into(self) -> leo_ast::Program {
leo_ast::Program { leo_ast::Program {
name: self.name.clone(), name: self.name.clone(),
@ -440,24 +418,19 @@ impl Into<leo_ast::Program> for &InternalProgram {
circuits: self circuits: self
.circuits .circuits
.iter() .iter()
.map(|(_, circuit)| (circuit.circuit.name.borrow().clone(), circuit.circuit.as_ref().into())) .map(|(_, circuit)| (circuit.name.borrow().clone(), (*circuit).into()))
.collect(), .collect(),
functions: self functions: self
.functions .functions
.iter() .iter()
.map(|(_, function)| { .map(|(_, function)| (function.name.borrow().clone(), (*function).into()))
(
function.function.name.borrow().clone(),
function.function.as_ref().into(),
)
})
.collect(), .collect(),
tests: self tests: self
.test_functions .test_functions
.iter() .iter()
.map(|(_, function)| { .map(|(_, function)| {
(function.0.function.name.borrow().clone(), leo_ast::TestFunction { (function.0.name.borrow().clone(), leo_ast::TestFunction {
function: function.0.function.as_ref().into(), function: function.0.into(),
input_file: function.1.clone(), input_file: function.1.clone(),
}) })
}) })

View File

@ -25,3 +25,9 @@ pub use monoidal_director::*;
mod monoidal_reducer; mod monoidal_reducer;
pub use monoidal_reducer::*; pub use monoidal_reducer::*;
mod visitor;
pub use visitor::*;
mod visitor_director;
pub use visitor_director::*;

View File

@ -17,14 +17,14 @@
use super::*; use super::*;
use crate::{expression::*, program::*, statement::*}; use crate::{expression::*, program::*, statement::*};
use std::{marker::PhantomData, sync::Arc}; use std::marker::PhantomData;
pub struct MonoidalDirector<T: Monoid, R: MonoidalReducerExpression<T>> { pub struct MonoidalDirector<'a, T: Monoid, R: MonoidalReducerExpression<'a, T>> {
reducer: R, reducer: R,
_monoid: PhantomData<T>, _monoid: PhantomData<&'a T>,
} }
impl<T: Monoid, R: MonoidalReducerExpression<T>> MonoidalDirector<T, R> { impl<'a, T: Monoid, R: MonoidalReducerExpression<'a, T>> MonoidalDirector<'a, T, R> {
pub fn new(reducer: R) -> Self { pub fn new(reducer: R) -> Self {
Self { Self {
reducer, reducer,
@ -36,8 +36,8 @@ impl<T: Monoid, R: MonoidalReducerExpression<T>> MonoidalDirector<T, R> {
self.reducer self.reducer
} }
pub fn reduce_expression(&mut self, input: &Arc<Expression>) -> T { pub fn reduce_expression(&mut self, input: &'a Expression<'a>) -> T {
match &**input { let value = match input {
Expression::ArrayAccess(e) => self.reduce_array_access(e), Expression::ArrayAccess(e) => self.reduce_array_access(e),
Expression::ArrayInit(e) => self.reduce_array_init(e), Expression::ArrayInit(e) => self.reduce_array_init(e),
Expression::ArrayInline(e) => self.reduce_array_inline(e), Expression::ArrayInline(e) => self.reduce_array_inline(e),
@ -52,101 +52,115 @@ impl<T: Monoid, R: MonoidalReducerExpression<T>> MonoidalDirector<T, R> {
Expression::TupleInit(e) => self.reduce_tuple_init(e), Expression::TupleInit(e) => self.reduce_tuple_init(e),
Expression::Unary(e) => self.reduce_unary(e), Expression::Unary(e) => self.reduce_unary(e),
Expression::VariableRef(e) => self.reduce_variable_ref(e), Expression::VariableRef(e) => self.reduce_variable_ref(e),
} };
self.reducer.reduce_expression(input, value)
} }
pub fn reduce_array_access(&mut self, input: &ArrayAccessExpression) -> T { pub fn reduce_array_access(&mut self, input: &ArrayAccessExpression<'a>) -> T {
let array = self.reduce_expression(&input.array); let array = self.reduce_expression(input.array.get());
let index = self.reduce_expression(&input.index); let index = self.reduce_expression(input.index.get());
self.reducer.reduce_array_access(input, array, index) self.reducer.reduce_array_access(input, array, index)
} }
pub fn reduce_array_init(&mut self, input: &ArrayInitExpression) -> T { pub fn reduce_array_init(&mut self, input: &ArrayInitExpression<'a>) -> T {
let element = self.reduce_expression(&input.element); let element = self.reduce_expression(input.element.get());
self.reducer.reduce_array_init(input, element) self.reducer.reduce_array_init(input, element)
} }
pub fn reduce_array_inline(&mut self, input: &ArrayInlineExpression) -> T { pub fn reduce_array_inline(&mut self, input: &ArrayInlineExpression<'a>) -> T {
let elements = input.elements.iter().map(|(x, _)| self.reduce_expression(x)).collect(); let elements = input
.elements
.iter()
.map(|(x, _)| self.reduce_expression(x.get()))
.collect();
self.reducer.reduce_array_inline(input, elements) self.reducer.reduce_array_inline(input, elements)
} }
pub fn reduce_array_range_access(&mut self, input: &ArrayRangeAccessExpression) -> T { pub fn reduce_array_range_access(&mut self, input: &ArrayRangeAccessExpression<'a>) -> T {
let array = self.reduce_expression(&input.array); let array = self.reduce_expression(input.array.get());
let left = input.left.as_ref().map(|e| self.reduce_expression(e)); let left = input.left.get().map(|e| self.reduce_expression(e));
let right = input.right.as_ref().map(|e| self.reduce_expression(e)); let right = input.right.get().map(|e| self.reduce_expression(e));
self.reducer.reduce_array_range_access(input, array, left, right) self.reducer.reduce_array_range_access(input, array, left, right)
} }
pub fn reduce_binary(&mut self, input: &BinaryExpression) -> T { pub fn reduce_binary(&mut self, input: &BinaryExpression<'a>) -> T {
let left = self.reduce_expression(&input.left); let left = self.reduce_expression(input.left.get());
let right = self.reduce_expression(&input.right); let right = self.reduce_expression(input.right.get());
self.reducer.reduce_binary(input, left, right) self.reducer.reduce_binary(input, left, right)
} }
pub fn reduce_call(&mut self, input: &CallExpression) -> T { pub fn reduce_call(&mut self, input: &CallExpression<'a>) -> T {
let target = input.target.as_ref().map(|e| self.reduce_expression(e)); let target = input.target.get().map(|e| self.reduce_expression(e));
let arguments = input.arguments.iter().map(|e| self.reduce_expression(e)).collect(); let arguments = input
.arguments
.iter()
.map(|e| self.reduce_expression(e.get()))
.collect();
self.reducer.reduce_call(input, target, arguments) self.reducer.reduce_call(input, target, arguments)
} }
pub fn reduce_circuit_access(&mut self, input: &CircuitAccessExpression) -> T { pub fn reduce_circuit_access(&mut self, input: &CircuitAccessExpression<'a>) -> T {
let target = input.target.as_ref().map(|e| self.reduce_expression(e)); let target = input.target.get().map(|e| self.reduce_expression(e));
self.reducer.reduce_circuit_access(input, target) self.reducer.reduce_circuit_access(input, target)
} }
pub fn reduce_circuit_init(&mut self, input: &CircuitInitExpression) -> T { pub fn reduce_circuit_init(&mut self, input: &CircuitInitExpression<'a>) -> T {
let values = input.values.iter().map(|(_, e)| self.reduce_expression(e)).collect(); let values = input
.values
.iter()
.map(|(_, e)| self.reduce_expression(e.get()))
.collect();
self.reducer.reduce_circuit_init(input, values) self.reducer.reduce_circuit_init(input, values)
} }
pub fn reduce_ternary_expression(&mut self, input: &TernaryExpression) -> T { pub fn reduce_ternary_expression(&mut self, input: &TernaryExpression<'a>) -> T {
let condition = self.reduce_expression(&input.condition); let condition = self.reduce_expression(input.condition.get());
let if_true = self.reduce_expression(&input.if_true); let if_true = self.reduce_expression(input.if_true.get());
let if_false = self.reduce_expression(&input.if_false); let if_false = self.reduce_expression(input.if_false.get());
self.reducer self.reducer
.reduce_ternary_expression(input, condition, if_true, if_false) .reduce_ternary_expression(input, condition, if_true, if_false)
} }
pub fn reduce_constant(&mut self, input: &Constant) -> T { pub fn reduce_constant(&mut self, input: &Constant<'a>) -> T {
self.reducer.reduce_constant(input) self.reducer.reduce_constant(input)
} }
pub fn reduce_tuple_access(&mut self, input: &TupleAccessExpression) -> T { pub fn reduce_tuple_access(&mut self, input: &TupleAccessExpression<'a>) -> T {
let tuple_ref = self.reduce_expression(&input.tuple_ref); let tuple_ref = self.reduce_expression(input.tuple_ref.get());
self.reducer.reduce_tuple_access(input, tuple_ref) self.reducer.reduce_tuple_access(input, tuple_ref)
} }
pub fn reduce_tuple_init(&mut self, input: &TupleInitExpression) -> T { pub fn reduce_tuple_init(&mut self, input: &TupleInitExpression<'a>) -> T {
let values = input.elements.iter().map(|e| self.reduce_expression(e)).collect(); let values = input.elements.iter().map(|e| self.reduce_expression(e.get())).collect();
self.reducer.reduce_tuple_init(input, values) self.reducer.reduce_tuple_init(input, values)
} }
pub fn reduce_unary(&mut self, input: &UnaryExpression) -> T { pub fn reduce_unary(&mut self, input: &UnaryExpression<'a>) -> T {
let inner = self.reduce_expression(&input.inner); let inner = self.reduce_expression(input.inner.get());
self.reducer.reduce_unary(input, inner) self.reducer.reduce_unary(input, inner)
} }
pub fn reduce_variable_ref(&mut self, input: &VariableRef) -> T { pub fn reduce_variable_ref(&mut self, input: &VariableRef<'a>) -> T {
self.reducer.reduce_variable_ref(input) self.reducer.reduce_variable_ref(input)
} }
} }
impl<T: Monoid, R: MonoidalReducerStatement<T>> MonoidalDirector<T, R> { impl<'a, T: Monoid, R: MonoidalReducerStatement<'a, T>> MonoidalDirector<'a, T, R> {
pub fn reduce_statement(&mut self, input: &Arc<Statement>) -> T { pub fn reduce_statement(&mut self, input: &'a Statement<'a>) -> T {
match &**input { let value = match input {
Statement::Assign(s) => self.reduce_assign(s), Statement::Assign(s) => self.reduce_assign(s),
Statement::Block(s) => self.reduce_block(s), Statement::Block(s) => self.reduce_block(s),
Statement::Conditional(s) => self.reduce_conditional_statement(s), Statement::Conditional(s) => self.reduce_conditional_statement(s),
@ -155,57 +169,67 @@ impl<T: Monoid, R: MonoidalReducerStatement<T>> MonoidalDirector<T, R> {
Statement::Expression(s) => self.reduce_expression_statement(s), Statement::Expression(s) => self.reduce_expression_statement(s),
Statement::Iteration(s) => self.reduce_iteration(s), Statement::Iteration(s) => self.reduce_iteration(s),
Statement::Return(s) => self.reduce_return(s), Statement::Return(s) => self.reduce_return(s),
} };
self.reducer.reduce_statement(input, value)
} }
pub fn reduce_assign_access(&mut self, input: &AssignAccess) -> T { pub fn reduce_assign_access(&mut self, input: &AssignAccess<'a>) -> T {
let (left, right) = match input { let (left, right) = match input {
AssignAccess::ArrayRange(left, right) => ( AssignAccess::ArrayRange(left, right) => (
left.as_ref().map(|e| self.reduce_expression(e)), left.get().map(|e| self.reduce_expression(e)),
right.as_ref().map(|e| self.reduce_expression(e)), right.get().map(|e| self.reduce_expression(e)),
), ),
AssignAccess::ArrayIndex(index) => (Some(self.reduce_expression(index)), None), AssignAccess::ArrayIndex(index) => (Some(self.reduce_expression(index.get())), None),
_ => (None, None), _ => (None, None),
}; };
self.reducer.reduce_assign_access(input, left, right) self.reducer.reduce_assign_access(input, left, right)
} }
pub fn reduce_assign(&mut self, input: &AssignStatement) -> T { pub fn reduce_assign(&mut self, input: &AssignStatement<'a>) -> T {
let accesses = input let accesses = input
.target_accesses .target_accesses
.iter() .iter()
.map(|x| self.reduce_assign_access(x)) .map(|x| self.reduce_assign_access(x))
.collect(); .collect();
let value = self.reduce_expression(&input.value); let value = self.reduce_expression(input.value.get());
self.reducer.reduce_assign(input, accesses, value) self.reducer.reduce_assign(input, accesses, value)
} }
pub fn reduce_block(&mut self, input: &BlockStatement) -> T { pub fn reduce_block(&mut self, input: &BlockStatement<'a>) -> T {
let statements = input.statements.iter().map(|x| self.reduce_statement(x)).collect(); let statements = input
.statements
.iter()
.map(|x| self.reduce_statement(x.get()))
.collect();
self.reducer.reduce_block(input, statements) self.reducer.reduce_block(input, statements)
} }
pub fn reduce_conditional_statement(&mut self, input: &ConditionalStatement) -> T { pub fn reduce_conditional_statement(&mut self, input: &ConditionalStatement<'a>) -> T {
let condition = self.reduce_expression(&input.condition); let condition = self.reduce_expression(input.condition.get());
let if_true = self.reduce_statement(&input.result); let if_true = self.reduce_statement(input.result.get());
let if_false = input.next.as_ref().map(|s| self.reduce_statement(s)); let if_false = input.next.get().map(|s| self.reduce_statement(s));
self.reducer self.reducer
.reduce_conditional_statement(input, condition, if_true, if_false) .reduce_conditional_statement(input, condition, if_true, if_false)
} }
pub fn reduce_formatted_string(&mut self, input: &FormattedString) -> T { pub fn reduce_formatted_string(&mut self, input: &FormattedString<'a>) -> T {
let parameters = input.parameters.iter().map(|e| self.reduce_expression(e)).collect(); let parameters = input
.parameters
.iter()
.map(|e| self.reduce_expression(e.get()))
.collect();
self.reducer.reduce_formatted_string(input, parameters) self.reducer.reduce_formatted_string(input, parameters)
} }
pub fn reduce_console(&mut self, input: &ConsoleStatement) -> T { pub fn reduce_console(&mut self, input: &ConsoleStatement<'a>) -> T {
let argument = match &input.function { let argument = match &input.function {
ConsoleFunction::Assert(e) => self.reduce_expression(e), ConsoleFunction::Assert(e) => self.reduce_expression(e.get()),
ConsoleFunction::Debug(f) | ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => { ConsoleFunction::Debug(f) | ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => {
self.reduce_formatted_string(f) self.reduce_formatted_string(f)
} }
@ -214,51 +238,51 @@ impl<T: Monoid, R: MonoidalReducerStatement<T>> MonoidalDirector<T, R> {
self.reducer.reduce_console(input, argument) self.reducer.reduce_console(input, argument)
} }
pub fn reduce_definition(&mut self, input: &DefinitionStatement) -> T { pub fn reduce_definition(&mut self, input: &DefinitionStatement<'a>) -> T {
let value = self.reduce_expression(&input.value); let value = self.reduce_expression(input.value.get());
self.reducer.reduce_definition(input, value) self.reducer.reduce_definition(input, value)
} }
pub fn reduce_expression_statement(&mut self, input: &ExpressionStatement) -> T { pub fn reduce_expression_statement(&mut self, input: &ExpressionStatement<'a>) -> T {
let value = self.reduce_expression(&input.expression); let value = self.reduce_expression(input.expression.get());
self.reducer.reduce_expression_statement(input, value) self.reducer.reduce_expression_statement(input, value)
} }
pub fn reduce_iteration(&mut self, input: &IterationStatement) -> T { pub fn reduce_iteration(&mut self, input: &IterationStatement<'a>) -> T {
let start = self.reduce_expression(&input.start); let start = self.reduce_expression(input.start.get());
let stop = self.reduce_expression(&input.stop); let stop = self.reduce_expression(input.stop.get());
let body = self.reduce_statement(&input.body); let body = self.reduce_statement(input.body.get());
self.reducer.reduce_iteration(input, start, stop, body) self.reducer.reduce_iteration(input, start, stop, body)
} }
pub fn reduce_return(&mut self, input: &ReturnStatement) -> T { pub fn reduce_return(&mut self, input: &ReturnStatement<'a>) -> T {
let value = self.reduce_expression(&input.expression); let value = self.reduce_expression(input.expression.get());
self.reducer.reduce_return(input, value) self.reducer.reduce_return(input, value)
} }
} }
#[allow(dead_code)] #[allow(dead_code)]
impl<T: Monoid, R: MonoidalReducerProgram<T>> MonoidalDirector<T, R> { impl<'a, T: Monoid, R: MonoidalReducerProgram<'a, T>> MonoidalDirector<'a, T, R> {
fn reduce_function(&mut self, input: &Arc<FunctionBody>) -> T { fn reduce_function(&mut self, input: &'a Function<'a>) -> T {
let body = self.reduce_statement(&input.body); let body = input.body.get().map(|s| self.reduce_statement(s)).unwrap_or_default();
self.reducer.reduce_function(input, body) self.reducer.reduce_function(input, body)
} }
fn reduce_circuit_member(&mut self, input: &CircuitMemberBody) -> T { fn reduce_circuit_member(&mut self, input: &CircuitMember<'a>) -> T {
let function = match input { let function = match input {
CircuitMemberBody::Function(f) => Some(self.reduce_function(f)), CircuitMember::Function(f) => Some(self.reduce_function(f)),
_ => None, _ => None,
}; };
self.reducer.reduce_circuit_member(input, function) self.reducer.reduce_circuit_member(input, function)
} }
fn reduce_circuit(&mut self, input: &Arc<CircuitBody>) -> T { fn reduce_circuit(&mut self, input: &'a Circuit<'a>) -> T {
let members = input let members = input
.members .members
.borrow() .borrow()
@ -269,8 +293,7 @@ impl<T: Monoid, R: MonoidalReducerProgram<T>> MonoidalDirector<T, R> {
self.reducer.reduce_circuit(input, members) self.reducer.reduce_circuit(input, members)
} }
fn reduce_program(&mut self, input: &Program) -> T { fn reduce_program(&mut self, input: &Program<'a>) -> T {
let input = input.borrow();
let imported_modules = input let imported_modules = input
.imported_modules .imported_modules
.iter() .iter()

View File

@ -16,29 +16,27 @@
use crate::{expression::*, program::*, statement::*, Monoid}; use crate::{expression::*, program::*, statement::*, Monoid};
use std::sync::Arc;
#[allow(unused_variables)] #[allow(unused_variables)]
pub trait MonoidalReducerExpression<T: Monoid> { pub trait MonoidalReducerExpression<'a, T: Monoid> {
fn reduce_expression(&mut self, input: &Arc<Expression>, value: T) -> T { fn reduce_expression(&mut self, input: &'a Expression<'a>, value: T) -> T {
value value
} }
fn reduce_array_access(&mut self, input: &ArrayAccessExpression, array: T, index: T) -> T { fn reduce_array_access(&mut self, input: &ArrayAccessExpression<'a>, array: T, index: T) -> T {
array.append(index) array.append(index)
} }
fn reduce_array_init(&mut self, input: &ArrayInitExpression, element: T) -> T { fn reduce_array_init(&mut self, input: &ArrayInitExpression<'a>, element: T) -> T {
element element
} }
fn reduce_array_inline(&mut self, input: &ArrayInlineExpression, elements: Vec<T>) -> T { fn reduce_array_inline(&mut self, input: &ArrayInlineExpression<'a>, elements: Vec<T>) -> T {
T::default().append_all(elements.into_iter()) T::default().append_all(elements.into_iter())
} }
fn reduce_array_range_access( fn reduce_array_range_access(
&mut self, &mut self,
input: &ArrayRangeAccessExpression, input: &ArrayRangeAccessExpression<'a>,
array: T, array: T,
left: Option<T>, left: Option<T>,
right: Option<T>, right: Option<T>,
@ -46,69 +44,69 @@ pub trait MonoidalReducerExpression<T: Monoid> {
array.append_option(left).append_option(right) array.append_option(left).append_option(right)
} }
fn reduce_binary(&mut self, input: &BinaryExpression, left: T, right: T) -> T { fn reduce_binary(&mut self, input: &BinaryExpression<'a>, left: T, right: T) -> T {
left.append(right) left.append(right)
} }
fn reduce_call(&mut self, input: &CallExpression, target: Option<T>, arguments: Vec<T>) -> T { fn reduce_call(&mut self, input: &CallExpression<'a>, target: Option<T>, arguments: Vec<T>) -> T {
target.unwrap_or_default().append_all(arguments.into_iter()) target.unwrap_or_default().append_all(arguments.into_iter())
} }
fn reduce_circuit_access(&mut self, input: &CircuitAccessExpression, target: Option<T>) -> T { fn reduce_circuit_access(&mut self, input: &CircuitAccessExpression<'a>, target: Option<T>) -> T {
target.unwrap_or_default() target.unwrap_or_default()
} }
fn reduce_circuit_init(&mut self, input: &CircuitInitExpression, values: Vec<T>) -> T { fn reduce_circuit_init(&mut self, input: &CircuitInitExpression<'a>, values: Vec<T>) -> T {
T::default().append_all(values.into_iter()) T::default().append_all(values.into_iter())
} }
fn reduce_ternary_expression(&mut self, input: &TernaryExpression, condition: T, if_true: T, if_false: T) -> T { fn reduce_ternary_expression(&mut self, input: &TernaryExpression<'a>, condition: T, if_true: T, if_false: T) -> T {
condition.append(if_true).append(if_false) condition.append(if_true).append(if_false)
} }
fn reduce_constant(&mut self, input: &Constant) -> T { fn reduce_constant(&mut self, input: &Constant<'a>) -> T {
T::default() T::default()
} }
fn reduce_tuple_access(&mut self, input: &TupleAccessExpression, tuple_ref: T) -> T { fn reduce_tuple_access(&mut self, input: &TupleAccessExpression<'a>, tuple_ref: T) -> T {
tuple_ref tuple_ref
} }
fn reduce_tuple_init(&mut self, input: &TupleInitExpression, values: Vec<T>) -> T { fn reduce_tuple_init(&mut self, input: &TupleInitExpression<'a>, values: Vec<T>) -> T {
T::default().append_all(values.into_iter()) T::default().append_all(values.into_iter())
} }
fn reduce_unary(&mut self, input: &UnaryExpression, inner: T) -> T { fn reduce_unary(&mut self, input: &UnaryExpression<'a>, inner: T) -> T {
inner inner
} }
fn reduce_variable_ref(&mut self, input: &VariableRef) -> T { fn reduce_variable_ref(&mut self, input: &VariableRef<'a>) -> T {
T::default() T::default()
} }
} }
#[allow(unused_variables)] #[allow(unused_variables)]
pub trait MonoidalReducerStatement<T: Monoid>: MonoidalReducerExpression<T> { pub trait MonoidalReducerStatement<'a, T: Monoid>: MonoidalReducerExpression<'a, T> {
fn reduce_statement(&mut self, input: &Arc<Statement>, value: T) -> T { fn reduce_statement(&mut self, input: &'a Statement<'a>, value: T) -> T {
value value
} }
// left = Some(ArrayIndex.0) always if AssignAccess::ArrayIndex. if member/tuple, always None // left = Some(ArrayIndex.0) always if AssignAccess::ArrayIndex. if member/tuple, always None
fn reduce_assign_access(&mut self, input: &AssignAccess, left: Option<T>, right: Option<T>) -> T { fn reduce_assign_access(&mut self, input: &AssignAccess<'a>, left: Option<T>, right: Option<T>) -> T {
left.unwrap_or_default().append_option(right) left.unwrap_or_default().append_option(right)
} }
fn reduce_assign(&mut self, input: &AssignStatement, accesses: Vec<T>, value: T) -> T { fn reduce_assign(&mut self, input: &AssignStatement<'a>, accesses: Vec<T>, value: T) -> T {
T::default().append_all(accesses.into_iter()).append(value) T::default().append_all(accesses.into_iter()).append(value)
} }
fn reduce_block(&mut self, input: &BlockStatement, statements: Vec<T>) -> T { fn reduce_block(&mut self, input: &BlockStatement<'a>, statements: Vec<T>) -> T {
T::default().append_all(statements.into_iter()) T::default().append_all(statements.into_iter())
} }
fn reduce_conditional_statement( fn reduce_conditional_statement(
&mut self, &mut self,
input: &ConditionalStatement, input: &ConditionalStatement<'a>,
condition: T, condition: T,
if_true: T, if_true: T,
if_false: Option<T>, if_false: Option<T>,
@ -116,42 +114,42 @@ pub trait MonoidalReducerStatement<T: Monoid>: MonoidalReducerExpression<T> {
condition.append(if_true).append_option(if_false) condition.append(if_true).append_option(if_false)
} }
fn reduce_formatted_string(&mut self, input: &FormattedString, parameters: Vec<T>) -> T { fn reduce_formatted_string(&mut self, input: &FormattedString<'a>, parameters: Vec<T>) -> T {
T::default().append_all(parameters.into_iter()) T::default().append_all(parameters.into_iter())
} }
fn reduce_console(&mut self, input: &ConsoleStatement, argument: T) -> T { fn reduce_console(&mut self, input: &ConsoleStatement<'a>, argument: T) -> T {
argument argument
} }
fn reduce_definition(&mut self, input: &DefinitionStatement, value: T) -> T { fn reduce_definition(&mut self, input: &DefinitionStatement<'a>, value: T) -> T {
value value
} }
fn reduce_expression_statement(&mut self, input: &ExpressionStatement, expression: T) -> T { fn reduce_expression_statement(&mut self, input: &ExpressionStatement<'a>, expression: T) -> T {
expression expression
} }
fn reduce_iteration(&mut self, input: &IterationStatement, start: T, stop: T, body: T) -> T { fn reduce_iteration(&mut self, input: &IterationStatement<'a>, start: T, stop: T, body: T) -> T {
start.append(stop).append(body) start.append(stop).append(body)
} }
fn reduce_return(&mut self, input: &ReturnStatement, value: T) -> T { fn reduce_return(&mut self, input: &ReturnStatement<'a>, value: T) -> T {
value value
} }
} }
#[allow(unused_variables)] #[allow(unused_variables)]
pub trait MonoidalReducerProgram<T: Monoid>: MonoidalReducerStatement<T> { pub trait MonoidalReducerProgram<'a, T: Monoid>: MonoidalReducerStatement<'a, T> {
fn reduce_function(&mut self, input: &Arc<FunctionBody>, body: T) -> T { fn reduce_function(&mut self, input: &'a Function<'a>, body: T) -> T {
body body
} }
fn reduce_circuit_member(&mut self, input: &CircuitMemberBody, function: Option<T>) -> T { fn reduce_circuit_member(&mut self, input: &CircuitMember<'a>, function: Option<T>) -> T {
function.unwrap_or_default() function.unwrap_or_default()
} }
fn reduce_circuit(&mut self, input: &Arc<CircuitBody>, members: Vec<T>) -> T { fn reduce_circuit(&mut self, input: &'a Circuit<'a>, members: Vec<T>) -> T {
T::default().append_all(members.into_iter()) T::default().append_all(members.into_iter())
} }

161
asg/src/reducer/visitor.rs Normal file
View File

@ -0,0 +1,161 @@
// 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 std::cell::Cell;
use crate::{expression::*, program::*, statement::*};
pub enum VisitResult {
VisitChildren,
SkipChildren,
Exit,
}
impl Default for VisitResult {
fn default() -> Self {
VisitResult::VisitChildren
}
}
#[allow(unused_variables)]
pub trait ExpressionVisitor<'a> {
fn visit_expression(&mut self, input: &Cell<&'a Expression<'a>>) -> VisitResult {
Default::default()
}
fn visit_array_access(&mut self, input: &ArrayAccessExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_array_init(&mut self, input: &ArrayInitExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_array_inline(&mut self, input: &ArrayInlineExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_array_range_access(&mut self, input: &ArrayRangeAccessExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_binary(&mut self, input: &BinaryExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_call(&mut self, input: &CallExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_circuit_access(&mut self, input: &CircuitAccessExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_circuit_init(&mut self, input: &CircuitInitExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_ternary_expression(&mut self, input: &TernaryExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_constant(&mut self, input: &Constant<'a>) -> VisitResult {
Default::default()
}
fn visit_tuple_access(&mut self, input: &TupleAccessExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_tuple_init(&mut self, input: &TupleInitExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_unary(&mut self, input: &UnaryExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_variable_ref(&mut self, input: &VariableRef<'a>) -> VisitResult {
Default::default()
}
}
#[allow(unused_variables)]
pub trait StatementVisitor<'a>: ExpressionVisitor<'a> {
fn visit_statement(&mut self, input: &Cell<&'a Statement<'a>>) -> VisitResult {
Default::default()
}
// left = Some(ArrayIndex.0) always if AssignAccess::ArrayIndex. if member/tuple, always None
fn visit_assign_access(&mut self, input: &AssignAccess<'a>) -> VisitResult {
Default::default()
}
fn visit_assign(&mut self, input: &AssignStatement<'a>) -> VisitResult {
Default::default()
}
fn visit_block(&mut self, input: &BlockStatement<'a>) -> VisitResult {
Default::default()
}
fn visit_conditional_statement(&mut self, input: &ConditionalStatement<'a>) -> VisitResult {
Default::default()
}
fn visit_formatted_string(&mut self, input: &FormattedString<'a>) -> VisitResult {
Default::default()
}
fn visit_console(&mut self, input: &ConsoleStatement<'a>) -> VisitResult {
Default::default()
}
fn visit_definition(&mut self, input: &DefinitionStatement<'a>) -> VisitResult {
Default::default()
}
fn visit_expression_statement(&mut self, input: &ExpressionStatement<'a>) -> VisitResult {
Default::default()
}
fn visit_iteration(&mut self, input: &IterationStatement<'a>) -> VisitResult {
Default::default()
}
fn visit_return(&mut self, input: &ReturnStatement<'a>) -> VisitResult {
Default::default()
}
}
#[allow(unused_variables)]
pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
fn visit_function(&mut self, input: &'a Function<'a>) -> VisitResult {
Default::default()
}
fn visit_circuit_member(&mut self, input: &CircuitMember<'a>) -> VisitResult {
Default::default()
}
fn visit_circuit(&mut self, input: &'a Circuit<'a>) -> VisitResult {
Default::default()
}
fn visit_program(&mut self, input: &Program<'a>) -> VisitResult {
Default::default()
}
}

View File

@ -0,0 +1,442 @@
// 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 super::*;
use crate::{expression::*, program::*, statement::*};
use std::{cell::Cell, marker::PhantomData};
pub struct VisitorDirector<'a, R: ExpressionVisitor<'a>> {
visitor: R,
lifetime: PhantomData<&'a ()>,
}
pub type ConcreteVisitResult = Result<(), ()>;
impl Into<ConcreteVisitResult> for VisitResult {
fn into(self) -> ConcreteVisitResult {
match self {
VisitResult::VisitChildren => Ok(()),
VisitResult::SkipChildren => Ok(()),
VisitResult::Exit => Err(()),
}
}
}
impl<'a, R: ExpressionVisitor<'a>> VisitorDirector<'a, R> {
pub fn new(visitor: R) -> Self {
Self {
visitor,
lifetime: PhantomData,
}
}
pub fn visitor(self) -> R {
self.visitor
}
pub fn visit_expression(&mut self, input: &Cell<&'a Expression<'a>>) -> ConcreteVisitResult {
match self.visitor.visit_expression(input) {
VisitResult::VisitChildren => match input.get() {
Expression::ArrayAccess(e) => self.visit_array_access(e),
Expression::ArrayInit(e) => self.visit_array_init(e),
Expression::ArrayInline(e) => self.visit_array_inline(e),
Expression::ArrayRangeAccess(e) => self.visit_array_range_access(e),
Expression::Binary(e) => self.visit_binary(e),
Expression::Call(e) => self.visit_call(e),
Expression::CircuitAccess(e) => self.visit_circuit_access(e),
Expression::CircuitInit(e) => self.visit_circuit_init(e),
Expression::Ternary(e) => self.visit_ternary_expression(e),
Expression::Constant(e) => self.visit_constant(e),
Expression::TupleAccess(e) => self.visit_tuple_access(e),
Expression::TupleInit(e) => self.visit_tuple_init(e),
Expression::Unary(e) => self.visit_unary(e),
Expression::VariableRef(e) => self.visit_variable_ref(e),
},
x => x.into(),
}
}
fn visit_opt_expression(&mut self, input: &Cell<Option<&'a Expression<'a>>>) -> ConcreteVisitResult {
let interior = match input.get() {
Some(expr) => Some(Cell::new(expr)),
None => None,
};
if let Some(interior) = interior.as_ref() {
let result = self.visit_expression(interior);
input.replace(Some(interior.get()));
result
} else {
Ok(())
}
}
pub fn visit_array_access(&mut self, input: &ArrayAccessExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_array_access(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.array)?;
self.visit_expression(&input.index)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_array_init(&mut self, input: &ArrayInitExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_array_init(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.element)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_array_inline(&mut self, input: &ArrayInlineExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_array_inline(input) {
VisitResult::VisitChildren => {
for (element, _) in input.elements.iter() {
self.visit_expression(element)?;
}
Ok(())
}
x => x.into(),
}
}
pub fn visit_array_range_access(&mut self, input: &ArrayRangeAccessExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_array_range_access(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.array)?;
self.visit_opt_expression(&input.left)?;
self.visit_opt_expression(&input.right)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_binary(&mut self, input: &BinaryExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_binary(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.left)?;
self.visit_expression(&input.right)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_call(&mut self, input: &CallExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_call(input) {
VisitResult::VisitChildren => {
self.visit_opt_expression(&input.target)?;
for argument in input.arguments.iter() {
self.visit_expression(argument)?;
}
Ok(())
}
x => x.into(),
}
}
pub fn visit_circuit_access(&mut self, input: &CircuitAccessExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_circuit_access(input) {
VisitResult::VisitChildren => {
self.visit_opt_expression(&input.target)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_circuit_init(&mut self, input: &CircuitInitExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_circuit_init(input) {
VisitResult::VisitChildren => {
for (_, argument) in input.values.iter() {
self.visit_expression(argument)?;
}
Ok(())
}
x => x.into(),
}
}
pub fn visit_ternary_expression(&mut self, input: &TernaryExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_ternary_expression(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.condition)?;
self.visit_expression(&input.if_true)?;
self.visit_expression(&input.if_false)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_constant(&mut self, input: &Constant<'a>) -> ConcreteVisitResult {
self.visitor.visit_constant(input).into()
}
pub fn visit_tuple_access(&mut self, input: &TupleAccessExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_tuple_access(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.tuple_ref)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_tuple_init(&mut self, input: &TupleInitExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_tuple_init(input) {
VisitResult::VisitChildren => {
for argument in input.elements.iter() {
self.visit_expression(argument)?;
}
Ok(())
}
x => x.into(),
}
}
pub fn visit_unary(&mut self, input: &UnaryExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_unary(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.inner)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_variable_ref(&mut self, input: &VariableRef<'a>) -> ConcreteVisitResult {
self.visitor.visit_variable_ref(input).into()
}
}
impl<'a, R: StatementVisitor<'a>> VisitorDirector<'a, R> {
pub fn visit_statement(&mut self, input: &Cell<&'a Statement<'a>>) -> ConcreteVisitResult {
match self.visitor.visit_statement(input) {
VisitResult::VisitChildren => match input.get() {
Statement::Assign(s) => self.visit_assign(s),
Statement::Block(s) => self.visit_block(s),
Statement::Conditional(s) => self.visit_conditional_statement(s),
Statement::Console(s) => self.visit_console(s),
Statement::Definition(s) => self.visit_definition(s),
Statement::Expression(s) => self.visit_expression_statement(s),
Statement::Iteration(s) => self.visit_iteration(s),
Statement::Return(s) => self.visit_return(s),
},
x => x.into(),
}
}
fn visit_opt_statement(&mut self, input: &Cell<Option<&'a Statement<'a>>>) -> ConcreteVisitResult {
let interior = match input.get() {
Some(expr) => Some(Cell::new(expr)),
None => None,
};
if let Some(interior) = interior.as_ref() {
let result = self.visit_statement(interior);
input.replace(Some(interior.get()));
result
} else {
Ok(())
}
}
pub fn visit_assign_access(&mut self, input: &AssignAccess<'a>) -> ConcreteVisitResult {
match self.visitor.visit_assign_access(input) {
VisitResult::VisitChildren => {
match input {
AssignAccess::ArrayRange(left, right) => {
self.visit_opt_expression(left)?;
self.visit_opt_expression(right)?;
}
AssignAccess::ArrayIndex(index) => self.visit_expression(index)?,
_ => (),
}
Ok(())
}
x => x.into(),
}
}
pub fn visit_assign(&mut self, input: &AssignStatement<'a>) -> ConcreteVisitResult {
match self.visitor.visit_assign(input) {
VisitResult::VisitChildren => {
for access in input.target_accesses.iter() {
self.visit_assign_access(access)?;
}
self.visit_expression(&input.value)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_block(&mut self, input: &BlockStatement<'a>) -> ConcreteVisitResult {
match self.visitor.visit_block(input) {
VisitResult::VisitChildren => {
for statement in input.statements.iter() {
self.visit_statement(statement)?;
}
Ok(())
}
x => x.into(),
}
}
pub fn visit_conditional_statement(&mut self, input: &ConditionalStatement<'a>) -> ConcreteVisitResult {
match self.visitor.visit_conditional_statement(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.condition)?;
self.visit_statement(&input.result)?;
self.visit_opt_statement(&input.next)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_formatted_string(&mut self, input: &FormattedString<'a>) -> ConcreteVisitResult {
match self.visitor.visit_formatted_string(input) {
VisitResult::VisitChildren => {
for parameter in input.parameters.iter() {
self.visit_expression(parameter)?;
}
Ok(())
}
x => x.into(),
}
}
pub fn visit_console(&mut self, input: &ConsoleStatement<'a>) -> ConcreteVisitResult {
match self.visitor.visit_console(input) {
VisitResult::VisitChildren => {
match &input.function {
ConsoleFunction::Assert(e) => self.visit_expression(e)?,
ConsoleFunction::Debug(f) | ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => {
self.visit_formatted_string(f)?
}
}
Ok(())
}
x => x.into(),
}
}
pub fn visit_definition(&mut self, input: &DefinitionStatement<'a>) -> ConcreteVisitResult {
match self.visitor.visit_definition(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.value)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_expression_statement(&mut self, input: &ExpressionStatement<'a>) -> ConcreteVisitResult {
match self.visitor.visit_expression_statement(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.expression)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_iteration(&mut self, input: &IterationStatement<'a>) -> ConcreteVisitResult {
match self.visitor.visit_iteration(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.start)?;
self.visit_expression(&input.stop)?;
self.visit_statement(&input.body)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_return(&mut self, input: &ReturnStatement<'a>) -> ConcreteVisitResult {
match self.visitor.visit_return(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.expression)?;
Ok(())
}
x => x.into(),
}
}
}
#[allow(dead_code)]
impl<'a, R: ProgramVisitor<'a>> VisitorDirector<'a, R> {
fn visit_function(&mut self, input: &'a Function<'a>) -> ConcreteVisitResult {
match self.visitor.visit_function(input) {
VisitResult::VisitChildren => {
self.visit_opt_statement(&input.body)?;
Ok(())
}
x => x.into(),
}
}
fn visit_circuit_member(&mut self, input: &CircuitMember<'a>) -> ConcreteVisitResult {
match self.visitor.visit_circuit_member(input) {
VisitResult::VisitChildren => {
if let CircuitMember::Function(f) = input {
self.visit_function(f)?;
}
Ok(())
}
x => x.into(),
}
}
fn visit_circuit(&mut self, input: &'a Circuit<'a>) -> ConcreteVisitResult {
match self.visitor.visit_circuit(input) {
VisitResult::VisitChildren => {
for (_, member) in input.members.borrow().iter() {
self.visit_circuit_member(member)?;
}
Ok(())
}
x => x.into(),
}
}
fn visit_program(&mut self, input: &Program<'a>) -> ConcreteVisitResult {
match self.visitor.visit_program(input) {
VisitResult::VisitChildren => {
for (_, import) in input.imported_modules.iter() {
self.visit_program(import)?;
}
for (_, (function, _)) in input.test_functions.iter() {
self.visit_function(function)?;
}
for (_, function) in input.functions.iter() {
self.visit_function(function)?;
}
for (_, circuit) in input.circuits.iter() {
self.visit_circuit(circuit)?;
}
Ok(())
}
x => x.into(),
}
}
}

View File

@ -14,58 +14,98 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{AsgConvertError, Circuit, Function, Input, Type, Variable}; use crate::{ArenaNode, AsgConvertError, Circuit, Expression, Function, Input, Statement, Type, Variable};
use indexmap::IndexMap; use indexmap::IndexMap;
use std::{cell::RefCell, sync::Arc}; use std::cell::{Cell, RefCell};
use typed_arena::Arena;
use uuid::Uuid; use uuid::Uuid;
/// An abstract data type that track the current bindings for variables, functions, and circuits. /// An abstract data type that track the current bindings for variables, functions, and circuits.
#[derive(Debug)] #[derive(Clone)]
pub struct InnerScope { pub struct Scope<'a> {
pub arena: &'a Arena<ArenaNode<'a>>,
/// The unique id of the scope. /// The unique id of the scope.
pub id: Uuid, pub id: Uuid,
/// The parent scope that this scope inherits. /// The parent scope that this scope inherits.
pub parent_scope: Option<Scope>, pub parent_scope: Cell<Option<&'a Scope<'a>>>,
/// The function definition that this scope occurs in. /// The function definition that this scope occurs in.
pub function: Option<Arc<Function>>, pub function: Cell<Option<&'a Function<'a>>>,
/// The circuit definition that this scope occurs in. /// The circuit definition that this scope occurs in.
pub circuit_self: Option<Arc<Circuit>>, pub circuit_self: Cell<Option<&'a Circuit<'a>>>,
/// Maps variable name => variable. /// Maps variable name => variable.
pub variables: IndexMap<String, Variable>, pub variables: RefCell<IndexMap<String, &'a Variable<'a>>>,
/// Maps function name => function. /// Maps function name => function.
pub functions: IndexMap<String, Arc<Function>>, pub functions: RefCell<IndexMap<String, &'a Function<'a>>>,
/// Maps circuit name => circuit. /// Maps circuit name => circuit.
pub circuits: IndexMap<String, Arc<Circuit>>, pub circuits: RefCell<IndexMap<String, &'a Circuit<'a>>>,
/// The main input to the program. /// The main input to the program.
pub input: Option<Input>, pub input: Cell<Option<Input<'a>>>,
} }
pub type Scope = Arc<RefCell<InnerScope>>; #[allow(clippy::mut_from_ref)]
impl<'a> Scope<'a> {
pub fn alloc_expression(&'a self, expr: Expression<'a>) -> &'a mut Expression<'a> {
match self.arena.alloc(ArenaNode::Expression(expr)) {
ArenaNode::Expression(e) => e,
_ => unimplemented!(),
}
}
pub fn alloc_statement(&'a self, statement: Statement<'a>) -> &'a mut Statement<'a> {
match self.arena.alloc(ArenaNode::Statement(statement)) {
ArenaNode::Statement(e) => e,
_ => unimplemented!(),
}
}
pub fn alloc_variable(&'a self, variable: Variable<'a>) -> &'a mut Variable<'a> {
match self.arena.alloc(ArenaNode::Variable(variable)) {
ArenaNode::Variable(e) => e,
_ => unimplemented!(),
}
}
pub fn alloc_scope(&'a self, scope: Scope<'a>) -> &'a mut Scope<'a> {
match self.arena.alloc(ArenaNode::Scope(scope)) {
ArenaNode::Scope(e) => e,
_ => unimplemented!(),
}
}
pub fn alloc_circuit(&'a self, circuit: Circuit<'a>) -> &'a mut Circuit<'a> {
match self.arena.alloc(ArenaNode::Circuit(circuit)) {
ArenaNode::Circuit(e) => e,
_ => unimplemented!(),
}
}
pub fn alloc_function(&'a self, function: Function<'a>) -> &'a mut Function<'a> {
match self.arena.alloc(ArenaNode::Function(function)) {
ArenaNode::Function(e) => e,
_ => unimplemented!(),
}
}
impl InnerScope {
/// ///
/// Returns a reference to the variable corresponding to the name. /// Returns a reference to the variable corresponding to the name.
/// ///
/// If the current scope did not have this name present, then the parent scope is checked. /// If the current scope did not have this name present, then the parent scope is checked.
/// If there is no parent scope, then `None` is returned. /// If there is no parent scope, then `None` is returned.
/// ///
pub fn resolve_variable(&self, name: &str) -> Option<Variable> { pub fn resolve_variable(&self, name: &str) -> Option<&'a Variable<'a>> {
if let Some(resolved) = self.variables.get(name) { if let Some(resolved) = self.variables.borrow().get(name) {
Some(resolved.clone()) Some(*resolved)
} else if let Some(resolved) = self.parent_scope.as_ref() { } else if let Some(scope) = self.parent_scope.get() {
if let Some(resolved) = resolved.borrow().resolve_variable(name) { scope.resolve_variable(name)
Some(resolved)
} else {
None
}
} else { } else {
None None
} }
@ -77,15 +117,11 @@ impl InnerScope {
/// If the current scope did not have a function present, then the parent scope is checked. /// If the current scope did not have a function present, then the parent scope is checked.
/// If there is no parent scope, then `None` is returned. /// If there is no parent scope, then `None` is returned.
/// ///
pub fn resolve_current_function(&self) -> Option<Arc<Function>> { pub fn resolve_current_function(&self) -> Option<&'a Function> {
if let Some(resolved) = self.function.as_ref() { if let Some(resolved) = self.function.get() {
Some(resolved.clone()) Some(resolved)
} else if let Some(resolved) = self.parent_scope.as_ref() { } else if let Some(scope) = self.parent_scope.get() {
if let Some(resolved) = resolved.borrow().resolve_current_function() { scope.resolve_current_function()
Some(resolved)
} else {
None
}
} else { } else {
None None
} }
@ -97,15 +133,11 @@ impl InnerScope {
/// If the current scope did not have an input present, then the parent scope is checked. /// If the current scope did not have an input present, then the parent scope is checked.
/// If there is no parent scope, then `None` is returned. /// If there is no parent scope, then `None` is returned.
/// ///
pub fn resolve_input(&self) -> Option<Input> { pub fn resolve_input(&self) -> Option<Input<'a>> {
if let Some(input) = self.input.as_ref() { if let Some(input) = self.input.get() {
Some(input.clone()) Some(input)
} else if let Some(resolved) = self.parent_scope.as_ref() { } else if let Some(resolved) = self.parent_scope.get() {
if let Some(resolved) = resolved.borrow().resolve_input() { resolved.resolve_input()
Some(resolved)
} else {
None
}
} else { } else {
None None
} }
@ -117,15 +149,11 @@ impl InnerScope {
/// If the current scope did not have this name present, then the parent scope is checked. /// If the current scope did not have this name present, then the parent scope is checked.
/// If there is no parent scope, then `None` is returned. /// If there is no parent scope, then `None` is returned.
/// ///
pub fn resolve_function(&self, name: &str) -> Option<Arc<Function>> { pub fn resolve_function(&self, name: &str) -> Option<&'a Function<'a>> {
if let Some(resolved) = self.functions.get(name) { if let Some(resolved) = self.functions.borrow().get(name) {
Some(resolved.clone()) Some(*resolved)
} else if let Some(resolved) = self.parent_scope.as_ref() { } else if let Some(resolved) = self.parent_scope.get() {
if let Some(resolved) = resolved.borrow().resolve_function(name) { resolved.resolve_function(name)
Some(resolved)
} else {
None
}
} else { } else {
None None
} }
@ -137,17 +165,13 @@ impl InnerScope {
/// If the current scope did not have this name present, then the parent scope is checked. /// If the current scope did not have this name present, then the parent scope is checked.
/// If there is no parent scope, then `None` is returned. /// If there is no parent scope, then `None` is returned.
/// ///
pub fn resolve_circuit(&self, name: &str) -> Option<Arc<Circuit>> { pub fn resolve_circuit(&self, name: &str) -> Option<&'a Circuit<'a>> {
if let Some(resolved) = self.circuits.get(name) { if let Some(resolved) = self.circuits.borrow().get(name) {
Some(resolved.clone()) Some(*resolved)
} else if name == "Self" && self.circuit_self.is_some() { } else if name == "Self" && self.circuit_self.get().is_some() {
self.circuit_self.clone() self.circuit_self.get()
} else if let Some(resolved) = self.parent_scope.as_ref() { } else if let Some(resolved) = self.parent_scope.get() {
if let Some(resolved) = resolved.borrow().resolve_circuit(name) { resolved.resolve_circuit(name)
Some(resolved)
} else {
None
}
} else { } else {
None None
} }
@ -159,15 +183,11 @@ impl InnerScope {
/// If the current scope did not have a circuit self present, then the parent scope is checked. /// If the current scope did not have a circuit self present, then the parent scope is checked.
/// If there is no parent scope, then `None` is returned. /// If there is no parent scope, then `None` is returned.
/// ///
pub fn resolve_circuit_self(&self) -> Option<Arc<Circuit>> { pub fn resolve_circuit_self(&self) -> Option<&'a Circuit<'a>> {
if let Some(resolved) = self.circuit_self.as_ref() { if let Some(resolved) = self.circuit_self.get() {
Some(resolved.clone()) Some(resolved)
} else if let Some(resolved) = self.parent_scope.as_ref() { } else if let Some(resolved) = self.parent_scope.get() {
if let Some(resolved) = resolved.borrow().resolve_circuit_self() { resolved.resolve_circuit_self()
Some(resolved)
} else {
None
}
} else { } else {
None None
} }
@ -176,23 +196,24 @@ impl InnerScope {
/// ///
/// Returns a new scope given a parent scope. /// Returns a new scope given a parent scope.
/// ///
pub fn make_subscope(scope: &Scope) -> Scope { pub fn make_subscope(self: &'a Scope<'a>) -> &'a Scope<'a> {
Arc::new(RefCell::new(InnerScope { self.alloc_scope(Scope::<'a> {
arena: self.arena,
id: Uuid::new_v4(), id: Uuid::new_v4(),
parent_scope: Some(scope.clone()), parent_scope: Cell::new(Some(self)),
circuit_self: None, circuit_self: Cell::new(None),
variables: IndexMap::new(), variables: RefCell::new(IndexMap::new()),
functions: IndexMap::new(), functions: RefCell::new(IndexMap::new()),
circuits: IndexMap::new(), circuits: RefCell::new(IndexMap::new()),
function: None, function: Cell::new(None),
input: None, input: Cell::new(None),
})) })
} }
/// ///
/// Returns the type returned by the current scope. /// Returns the type returned by the current scope.
/// ///
pub fn resolve_ast_type(&self, type_: &leo_ast::Type) -> Result<Type, AsgConvertError> { pub fn resolve_ast_type(&self, type_: &leo_ast::Type) -> Result<Type<'a>, AsgConvertError> {
use leo_ast::Type::*; use leo_ast::Type::*;
Ok(match type_ { Ok(match type_ {
Address => Type::Address, Address => Type::Address,

View File

@ -35,49 +35,49 @@ use crate::{
pub use leo_ast::AssignOperation; pub use leo_ast::AssignOperation;
use leo_ast::AssigneeAccess as AstAssigneeAccess; use leo_ast::AssigneeAccess as AstAssigneeAccess;
use std::sync::{Arc, Weak}; use std::cell::Cell;
#[derive(Debug)] #[derive(Clone)]
pub enum AssignAccess { pub enum AssignAccess<'a> {
ArrayRange(Option<Arc<Expression>>, Option<Arc<Expression>>), ArrayRange(Cell<Option<&'a Expression<'a>>>, Cell<Option<&'a Expression<'a>>>),
ArrayIndex(Arc<Expression>), ArrayIndex(Cell<&'a Expression<'a>>),
Tuple(usize), Tuple(usize),
Member(Identifier), Member(Identifier),
} }
#[derive(Debug)] #[derive(Clone)]
pub struct AssignStatement { pub struct AssignStatement<'a> {
pub parent: Option<Weak<Statement>>, pub parent: Cell<Option<&'a Statement<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub operation: AssignOperation, pub operation: AssignOperation,
pub target_variable: Variable, pub target_variable: Cell<&'a Variable<'a>>,
pub target_accesses: Vec<AssignAccess>, pub target_accesses: Vec<AssignAccess<'a>>,
pub value: Arc<Expression>, pub value: Cell<&'a Expression<'a>>,
} }
impl Node for AssignStatement { impl<'a> Node for AssignStatement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl FromAst<leo_ast::AssignStatement> for Arc<Statement> { impl<'a> FromAst<'a, leo_ast::AssignStatement> for &'a Statement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
statement: &leo_ast::AssignStatement, statement: &leo_ast::AssignStatement,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Arc<Statement>, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
let (name, span) = (&statement.assignee.identifier.name, &statement.assignee.identifier.span); let (name, span) = (&statement.assignee.identifier.name, &statement.assignee.identifier.span);
let variable = if name == "input" { let variable = if name == "input" {
if let Some(function) = scope.borrow().resolve_current_function() { if let Some(function) = scope.resolve_current_function() {
if !function.has_input { if !function.has_input {
return Err(AsgConvertError::unresolved_reference(name, span)); return Err(AsgConvertError::unresolved_reference(name, span));
} }
} else { } else {
return Err(AsgConvertError::unresolved_reference(name, span)); return Err(AsgConvertError::unresolved_reference(name, span));
} }
if let Some(input) = scope.borrow().resolve_input() { if let Some(input) = scope.resolve_input() {
input.container input.container
} else { } else {
return Err(AsgConvertError::InternalError( return Err(AsgConvertError::InternalError(
@ -86,7 +86,6 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
} }
} else { } else {
scope scope
.borrow()
.resolve_variable(&name) .resolve_variable(&name)
.ok_or_else(|| AsgConvertError::unresolved_reference(name, span))? .ok_or_else(|| AsgConvertError::unresolved_reference(name, span))?
}; };
@ -94,7 +93,7 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
if !variable.borrow().mutable { if !variable.borrow().mutable {
return Err(AsgConvertError::immutable_assignment(&name, &statement.span)); return Err(AsgConvertError::immutable_assignment(&name, &statement.span));
} }
let mut target_type: Option<PartialType> = Some(variable.borrow().type_.clone().strong().into()); let mut target_type: Option<PartialType> = Some(variable.borrow().type_.clone().into());
let mut target_accesses = vec![]; let mut target_accesses = vec![];
for access in statement.assignee.accesses.iter() { for access in statement.assignee.accesses.iter() {
@ -104,16 +103,16 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
let left = left let left = left
.as_ref() .as_ref()
.map( .map(
|left: &leo_ast::Expression| -> Result<Arc<Expression>, AsgConvertError> { |left: &leo_ast::Expression| -> Result<&'a Expression<'a>, AsgConvertError> {
Arc::<Expression>::from_ast(scope, left, index_type.clone()) <&Expression<'a>>::from_ast(scope, left, index_type.clone())
}, },
) )
.transpose()?; .transpose()?;
let right = right let right = right
.as_ref() .as_ref()
.map( .map(
|right: &leo_ast::Expression| -> Result<Arc<Expression>, AsgConvertError> { |right: &leo_ast::Expression| -> Result<&'a Expression<'a>, AsgConvertError> {
Arc::<Expression>::from_ast(scope, right, index_type) <&Expression<'a>>::from_ast(scope, right, index_type)
}, },
) )
.transpose()?; .transpose()?;
@ -156,18 +155,18 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
_ => return Err(AsgConvertError::index_into_non_array(&name, &statement.span)), _ => return Err(AsgConvertError::index_into_non_array(&name, &statement.span)),
} }
AssignAccess::ArrayRange(left, right) AssignAccess::ArrayRange(Cell::new(left), Cell::new(right))
} }
AstAssigneeAccess::ArrayIndex(index) => { AstAssigneeAccess::ArrayIndex(index) => {
target_type = match target_type.clone() { target_type = match target_type.clone() {
Some(PartialType::Array(item, _)) => item.map(|x| *x), Some(PartialType::Array(item, _)) => item.map(|x| *x),
_ => return Err(AsgConvertError::index_into_non_array(&name, &statement.span)), _ => return Err(AsgConvertError::index_into_non_array(&name, &statement.span)),
}; };
AssignAccess::ArrayIndex(Arc::<Expression>::from_ast( AssignAccess::ArrayIndex(Cell::new(<&Expression<'a>>::from_ast(
scope, scope,
index, index,
Some(PartialType::Integer(None, Some(IntegerType::U32))), Some(PartialType::Integer(None, Some(IntegerType::U32))),
)?) )?))
} }
AstAssigneeAccess::Tuple(index, _) => { AstAssigneeAccess::Tuple(index, _) => {
let index = index let index = index
@ -203,7 +202,7 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
return Err(AsgConvertError::illegal_function_assign(&name.name, &statement.span)); return Err(AsgConvertError::illegal_function_assign(&name.name, &statement.span));
} }
}; };
Some(x.strong().partial()) Some(x.partial())
} }
_ => { _ => {
return Err(AsgConvertError::index_into_non_tuple( return Err(AsgConvertError::index_into_non_tuple(
@ -216,41 +215,40 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
} }
}); });
} }
let value = Arc::<Expression>::from_ast(scope, &statement.value, target_type)?; let value = <&Expression<'a>>::from_ast(scope, &statement.value, target_type)?;
let statement = Arc::new(Statement::Assign(AssignStatement { let statement = scope.alloc_statement(Statement::Assign(AssignStatement {
parent: None, parent: Cell::new(None),
span: Some(statement.span.clone()), span: Some(statement.span.clone()),
operation: statement.operation.clone(), operation: statement.operation.clone(),
target_variable: variable.clone(), target_variable: Cell::new(variable),
target_accesses, target_accesses,
value, value: Cell::new(value),
})); }));
{ {
let mut variable = variable.borrow_mut(); let mut variable = variable.borrow_mut();
variable.assignments.push(Arc::downgrade(&statement)); variable.assignments.push(statement);
} }
Ok(statement) Ok(statement)
} }
} }
impl Into<leo_ast::AssignStatement> for &AssignStatement { impl<'a> Into<leo_ast::AssignStatement> for &AssignStatement<'a> {
fn into(self) -> leo_ast::AssignStatement { fn into(self) -> leo_ast::AssignStatement {
leo_ast::AssignStatement { leo_ast::AssignStatement {
operation: self.operation.clone(), operation: self.operation.clone(),
assignee: leo_ast::Assignee { assignee: leo_ast::Assignee {
identifier: self.target_variable.borrow().name.clone(), identifier: self.target_variable.get().borrow().name.clone(),
accesses: self accesses: self
.target_accesses .target_accesses
.iter() .iter()
.map(|access| match access { .map(|access| match access {
AssignAccess::ArrayRange(left, right) => AstAssigneeAccess::ArrayRange( AssignAccess::ArrayRange(left, right) => {
left.as_ref().map(|e| e.as_ref().into()), AstAssigneeAccess::ArrayRange(left.get().map(|e| e.into()), right.get().map(|e| e.into()))
right.as_ref().map(|e| e.as_ref().into()), }
), AssignAccess::ArrayIndex(index) => AstAssigneeAccess::ArrayIndex(index.get().into()),
AssignAccess::ArrayIndex(index) => AstAssigneeAccess::ArrayIndex(index.as_ref().into()),
AssignAccess::Tuple(index) => AstAssigneeAccess::Tuple( AssignAccess::Tuple(index) => AstAssigneeAccess::Tuple(
leo_ast::PositiveNumber { leo_ast::PositiveNumber {
value: index.to_string(), value: index.to_string(),
@ -262,7 +260,7 @@ impl Into<leo_ast::AssignStatement> for &AssignStatement {
.collect(), .collect(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
}, },
value: self.value.as_ref().into(), value: self.value.get().into(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -14,38 +14,38 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{AsgConvertError, FromAst, InnerScope, Node, PartialType, Scope, Span, Statement}; use crate::{AsgConvertError, FromAst, Node, PartialType, Scope, Span, Statement};
use std::sync::{Arc, Weak}; use std::cell::Cell;
#[derive(Debug)] #[derive(Clone)]
pub struct BlockStatement { pub struct BlockStatement<'a> {
pub parent: Option<Weak<Statement>>, pub parent: Cell<Option<&'a Statement<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub statements: Vec<Arc<Statement>>, pub statements: Vec<Cell<&'a Statement<'a>>>,
pub scope: Scope, pub scope: &'a Scope<'a>,
} }
impl Node for BlockStatement { impl<'a> Node for BlockStatement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl FromAst<leo_ast::Block> for BlockStatement { impl<'a> FromAst<'a, leo_ast::Block> for BlockStatement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
statement: &leo_ast::Block, statement: &leo_ast::Block,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
let new_scope = InnerScope::make_subscope(scope); let new_scope = scope.make_subscope();
let mut output = vec![]; let mut output = vec![];
for item in statement.statements.iter() { for item in statement.statements.iter() {
output.push(Arc::<Statement>::from_ast(&new_scope, item, None)?); output.push(Cell::new(<&'a Statement<'a>>::from_ast(&new_scope, item, None)?));
} }
Ok(BlockStatement { Ok(BlockStatement {
parent: None, parent: Cell::new(None),
span: Some(statement.span.clone()), span: Some(statement.span.clone()),
statements: output, statements: output,
scope: new_scope, scope: new_scope,
@ -53,14 +53,10 @@ impl FromAst<leo_ast::Block> for BlockStatement {
} }
} }
impl Into<leo_ast::Block> for &BlockStatement { impl<'a> Into<leo_ast::Block> for &BlockStatement<'a> {
fn into(self) -> leo_ast::Block { fn into(self) -> leo_ast::Block {
leo_ast::Block { leo_ast::Block {
statements: self statements: self.statements.iter().map(|statement| statement.get().into()).collect(),
.statements
.iter()
.map(|statement| statement.as_ref().into())
.collect(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -16,31 +16,31 @@
use crate::{AsgConvertError, BlockStatement, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type}; use crate::{AsgConvertError, BlockStatement, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
use std::sync::{Arc, Weak}; use std::cell::Cell;
#[derive(Debug)] #[derive(Clone)]
pub struct ConditionalStatement { pub struct ConditionalStatement<'a> {
pub parent: Option<Weak<Statement>>, pub parent: Cell<Option<&'a Statement<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub condition: Arc<Expression>, pub condition: Cell<&'a Expression<'a>>,
pub result: Arc<Statement>, pub result: Cell<&'a Statement<'a>>,
pub next: Option<Arc<Statement>>, pub next: Cell<Option<&'a Statement<'a>>>,
} }
impl Node for ConditionalStatement { impl<'a> Node for ConditionalStatement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl FromAst<leo_ast::ConditionalStatement> for ConditionalStatement { impl<'a> FromAst<'a, leo_ast::ConditionalStatement> for ConditionalStatement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
statement: &leo_ast::ConditionalStatement, statement: &leo_ast::ConditionalStatement,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
let condition = Arc::<Expression>::from_ast(scope, &statement.condition, Some(Type::Boolean.into()))?; let condition = <&Expression<'a>>::from_ast(scope, &statement.condition, Some(Type::Boolean.into()))?;
let result = Arc::new(Statement::Block(BlockStatement::from_ast( let result = scope.alloc_statement(Statement::Block(BlockStatement::from_ast(
scope, scope,
&statement.block, &statement.block,
None, None,
@ -48,28 +48,30 @@ impl FromAst<leo_ast::ConditionalStatement> for ConditionalStatement {
let next = statement let next = statement
.next .next
.as_deref() .as_deref()
.map(|next| -> Result<Arc<Statement>, AsgConvertError> { Arc::<Statement>::from_ast(scope, next, None) }) .map(|next| -> Result<&'a Statement<'a>, AsgConvertError> {
<&'a Statement<'a>>::from_ast(scope, next, None)
})
.transpose()?; .transpose()?;
Ok(ConditionalStatement { Ok(ConditionalStatement {
parent: None, parent: Cell::new(None),
span: Some(statement.span.clone()), span: Some(statement.span.clone()),
condition, condition: Cell::new(condition),
result, result: Cell::new(result),
next, next: Cell::new(next),
}) })
} }
} }
impl Into<leo_ast::ConditionalStatement> for &ConditionalStatement { impl<'a> Into<leo_ast::ConditionalStatement> for &ConditionalStatement<'a> {
fn into(self) -> leo_ast::ConditionalStatement { fn into(self) -> leo_ast::ConditionalStatement {
leo_ast::ConditionalStatement { leo_ast::ConditionalStatement {
condition: self.condition.as_ref().into(), condition: self.condition.get().into(),
block: match self.result.as_ref() { block: match self.result.get() {
Statement::Block(block) => block.into(), Statement::Block(block) => block.into(),
_ => unimplemented!(), _ => unimplemented!(),
}, },
next: self.next.as_deref().map(|e| Box::new(e.into())), next: self.next.get().as_deref().map(|e| Box::new(e.into())),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -17,43 +17,43 @@
use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type}; use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
use leo_ast::ConsoleFunction as AstConsoleFunction; use leo_ast::ConsoleFunction as AstConsoleFunction;
use std::sync::{Arc, Weak}; use std::cell::Cell;
// TODO (protryon): Refactor to not require/depend on span // TODO (protryon): Refactor to not require/depend on span
#[derive(Debug)] #[derive(Clone)]
pub struct FormattedString { pub struct FormattedString<'a> {
pub string: String, pub string: String,
pub containers: Vec<Span>, pub containers: Vec<Span>,
pub parameters: Vec<Arc<Expression>>, pub parameters: Vec<Cell<&'a Expression<'a>>>,
pub span: Span, pub span: Span,
} }
#[derive(Debug)] #[derive(Clone)]
pub enum ConsoleFunction { pub enum ConsoleFunction<'a> {
Assert(Arc<Expression>), Assert(Cell<&'a Expression<'a>>),
Debug(FormattedString), Debug(FormattedString<'a>),
Error(FormattedString), Error(FormattedString<'a>),
Log(FormattedString), Log(FormattedString<'a>),
} }
#[derive(Debug)] #[derive(Clone)]
pub struct ConsoleStatement { pub struct ConsoleStatement<'a> {
pub parent: Option<Weak<Statement>>, pub parent: Cell<Option<&'a Statement<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub function: ConsoleFunction, pub function: ConsoleFunction<'a>,
} }
impl Node for ConsoleStatement { impl<'a> Node for ConsoleStatement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl FromAst<leo_ast::FormattedString> for FormattedString { impl<'a> FromAst<'a, leo_ast::FormattedString> for FormattedString<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::FormattedString, value: &leo_ast::FormattedString,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
if value.parameters.len() != value.containers.len() { if value.parameters.len() != value.containers.len() {
// + 1 for formatting string as to not confuse user // + 1 for formatting string as to not confuse user
@ -65,7 +65,7 @@ impl FromAst<leo_ast::FormattedString> for FormattedString {
} }
let mut parameters = vec![]; let mut parameters = vec![];
for parameter in value.parameters.iter() { for parameter in value.parameters.iter() {
parameters.push(Arc::<Expression>::from_ast(scope, parameter, None)?); parameters.push(Cell::new(<&Expression<'a>>::from_ast(scope, parameter, None)?));
} }
Ok(FormattedString { Ok(FormattedString {
string: value.string.clone(), string: value.string.clone(),
@ -76,7 +76,7 @@ impl FromAst<leo_ast::FormattedString> for FormattedString {
} }
} }
impl Into<leo_ast::FormattedString> for &FormattedString { impl<'a> Into<leo_ast::FormattedString> for &FormattedString<'a> {
fn into(self) -> leo_ast::FormattedString { fn into(self) -> leo_ast::FormattedString {
leo_ast::FormattedString { leo_ast::FormattedString {
string: self.string.clone(), string: self.string.clone(),
@ -85,27 +85,25 @@ impl Into<leo_ast::FormattedString> for &FormattedString {
.iter() .iter()
.map(|span| leo_ast::FormattedContainer { span: span.clone() }) .map(|span| leo_ast::FormattedContainer { span: span.clone() })
.collect(), .collect(),
parameters: self.parameters.iter().map(|e| e.as_ref().into()).collect(), parameters: self.parameters.iter().map(|e| e.get().into()).collect(),
span: self.span.clone(), span: self.span.clone(),
} }
} }
} }
impl FromAst<leo_ast::ConsoleStatement> for ConsoleStatement { impl<'a> FromAst<'a, leo_ast::ConsoleStatement> for ConsoleStatement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
statement: &leo_ast::ConsoleStatement, statement: &leo_ast::ConsoleStatement,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
Ok(ConsoleStatement { Ok(ConsoleStatement {
parent: None, parent: Cell::new(None),
span: Some(statement.span.clone()), span: Some(statement.span.clone()),
function: match &statement.function { function: match &statement.function {
AstConsoleFunction::Assert(expression) => ConsoleFunction::Assert(Arc::<Expression>::from_ast( AstConsoleFunction::Assert(expression) => ConsoleFunction::Assert(Cell::new(
scope, <&Expression<'a>>::from_ast(scope, expression, Some(Type::Boolean.into()))?,
expression, )),
Some(Type::Boolean.into()),
)?),
AstConsoleFunction::Debug(formatted_string) => { AstConsoleFunction::Debug(formatted_string) => {
ConsoleFunction::Debug(FormattedString::from_ast(scope, formatted_string, None)?) ConsoleFunction::Debug(FormattedString::from_ast(scope, formatted_string, None)?)
} }
@ -120,12 +118,12 @@ impl FromAst<leo_ast::ConsoleStatement> for ConsoleStatement {
} }
} }
impl Into<leo_ast::ConsoleStatement> for &ConsoleStatement { impl<'a> Into<leo_ast::ConsoleStatement> for &ConsoleStatement<'a> {
fn into(self) -> leo_ast::ConsoleStatement { fn into(self) -> leo_ast::ConsoleStatement {
use ConsoleFunction::*; use ConsoleFunction::*;
leo_ast::ConsoleStatement { leo_ast::ConsoleStatement {
function: match &self.function { function: match &self.function {
Assert(e) => AstConsoleFunction::Assert(e.as_ref().into()), Assert(e) => AstConsoleFunction::Assert(e.get().into()),
Debug(formatted_string) => AstConsoleFunction::Debug(formatted_string.into()), Debug(formatted_string) => AstConsoleFunction::Debug(formatted_string.into()),
Error(formatted_string) => AstConsoleFunction::Error(formatted_string.into()), Error(formatted_string) => AstConsoleFunction::Error(formatted_string.into()),
Log(formatted_string) => AstConsoleFunction::Log(formatted_string.into()), Log(formatted_string) => AstConsoleFunction::Log(formatted_string.into()),

View File

@ -28,41 +28,37 @@ use crate::{
Type, Type,
Variable, Variable,
}; };
use leo_ast::{AstError, DeprecatedError}; use leo_ast::{AstError, DeprecatedError};
use std::{ use std::cell::{Cell, RefCell};
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct DefinitionStatement { pub struct DefinitionStatement<'a> {
pub parent: Option<Weak<Statement>>, pub parent: Cell<Option<&'a Statement<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub variables: Vec<Variable>, pub variables: Vec<&'a Variable<'a>>,
pub value: Arc<Expression>, pub value: Cell<&'a Expression<'a>>,
} }
impl Node for DefinitionStatement { impl<'a> Node for DefinitionStatement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl FromAst<leo_ast::DefinitionStatement> for Arc<Statement> { impl<'a> FromAst<'a, leo_ast::DefinitionStatement> for &'a Statement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
statement: &leo_ast::DefinitionStatement, statement: &leo_ast::DefinitionStatement,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Arc<Statement>, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
let type_ = statement let type_ = statement
.type_ .type_
.as_ref() .as_ref()
.map(|x| scope.borrow().resolve_ast_type(&x)) .map(|x| scope.resolve_ast_type(&x))
.transpose()?; .transpose()?;
let value = Arc::<Expression>::from_ast(scope, &statement.value, type_.clone().map(Into::into))?; let value = <&Expression<'a>>::from_ast(scope, &statement.value, type_.clone().map(Into::into))?;
let type_ = type_.or_else(|| value.get_type()); let type_ = type_.or_else(|| value.get_type());
@ -99,13 +95,11 @@ impl FromAst<leo_ast::DefinitionStatement> for Arc<Statement> {
DeprecatedError::const_statement(&statement.span), DeprecatedError::const_statement(&statement.span),
))); )));
} }
variables.push(&*scope.alloc_variable(RefCell::new(InnerVariable {
variables.push(Arc::new(RefCell::new(InnerVariable {
id: uuid::Uuid::new_v4(), id: uuid::Uuid::new_v4(),
name: variable.identifier.clone(), name: variable.identifier.clone(),
type_: type_ type_:
.ok_or_else(|| AsgConvertError::unresolved_type(&variable.identifier.name, &statement.span))? type_.ok_or_else(|| AsgConvertError::unresolved_type(&variable.identifier.name, &statement.span))?,
.weak(),
mutable: variable.mutable, mutable: variable.mutable,
const_: false, const_: false,
declaration: crate::VariableDeclaration::Definition, declaration: crate::VariableDeclaration::Definition,
@ -114,31 +108,29 @@ impl FromAst<leo_ast::DefinitionStatement> for Arc<Statement> {
}))); })));
} }
{ for variable in variables.iter() {
let mut scope_borrow = scope.borrow_mut(); scope
for variable in variables.iter() { .variables
scope_borrow .borrow_mut()
.variables .insert(variable.borrow().name.name.clone(), *variable);
.insert(variable.borrow().name.name.clone(), variable.clone());
}
} }
let statement = Arc::new(Statement::Definition(DefinitionStatement { let statement = scope.alloc_statement(Statement::Definition(DefinitionStatement {
parent: None, parent: Cell::new(None),
span: Some(statement.span.clone()), span: Some(statement.span.clone()),
variables: variables.clone(), variables: variables.clone(),
value, value: Cell::new(value),
})); }));
variables.iter().for_each(|variable| { for variable in variables {
variable.borrow_mut().assignments.push(Arc::downgrade(&statement)); variable.borrow_mut().assignments.push(statement);
}); }
Ok(statement) Ok(statement)
} }
} }
impl Into<leo_ast::DefinitionStatement> for &DefinitionStatement { impl<'a> Into<leo_ast::DefinitionStatement> for &DefinitionStatement<'a> {
fn into(self) -> leo_ast::DefinitionStatement { fn into(self) -> leo_ast::DefinitionStatement {
assert!(!self.variables.is_empty()); assert!(!self.variables.is_empty());
@ -152,7 +144,7 @@ impl Into<leo_ast::DefinitionStatement> for &DefinitionStatement {
span: variable.name.span.clone(), span: variable.name.span.clone(),
}); });
if type_.is_none() { if type_.is_none() {
type_ = Some((&variable.type_.clone().strong()).into()); type_ = Some((&variable.type_.clone()).into());
} }
} }
@ -160,7 +152,7 @@ impl Into<leo_ast::DefinitionStatement> for &DefinitionStatement {
declaration_type: leo_ast::Declare::Let, declaration_type: leo_ast::Declare::Let,
variable_names, variable_names,
type_, type_,
value: self.value.as_ref().into(), value: self.value.get().into(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -16,41 +16,41 @@
use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement}; use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement};
use std::sync::{Arc, Weak}; use std::cell::Cell;
#[derive(Debug)] #[derive(Clone)]
pub struct ExpressionStatement { pub struct ExpressionStatement<'a> {
pub parent: Option<Weak<Statement>>, pub parent: Cell<Option<&'a Statement<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub expression: Arc<Expression>, pub expression: Cell<&'a Expression<'a>>,
} }
impl Node for ExpressionStatement { impl<'a> Node for ExpressionStatement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl FromAst<leo_ast::ExpressionStatement> for ExpressionStatement { impl<'a> FromAst<'a, leo_ast::ExpressionStatement> for ExpressionStatement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
statement: &leo_ast::ExpressionStatement, statement: &leo_ast::ExpressionStatement,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
let expression = Arc::<Expression>::from_ast(scope, &statement.expression, None)?; let expression = <&Expression<'a>>::from_ast(scope, &statement.expression, None)?;
Ok(ExpressionStatement { Ok(ExpressionStatement {
parent: None, parent: Cell::new(None),
span: Some(statement.span.clone()), span: Some(statement.span.clone()),
expression, expression: Cell::new(expression),
}) })
} }
} }
impl Into<leo_ast::ExpressionStatement> for &ExpressionStatement { impl<'a> Into<leo_ast::ExpressionStatement> for &ExpressionStatement<'a> {
fn into(self) -> leo_ast::ExpressionStatement { fn into(self) -> leo_ast::ExpressionStatement {
leo_ast::ExpressionStatement { leo_ast::ExpressionStatement {
expression: self.expression.as_ref().into(), expression: self.expression.get().into(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -30,43 +30,39 @@ use crate::{
Variable, Variable,
}; };
use std::{ use std::cell::{Cell, RefCell};
cell::RefCell,
sync::{Arc, Weak},
};
#[derive(Debug)] #[derive(Clone)]
pub struct IterationStatement { pub struct IterationStatement<'a> {
pub parent: Option<Weak<Statement>>, pub parent: Cell<Option<&'a Statement<'a>>>,
pub span: Option<Span>, pub span: Option<Span>,
pub variable: Variable, pub variable: &'a Variable<'a>,
pub start: Arc<Expression>, pub start: Cell<&'a Expression<'a>>,
pub stop: Arc<Expression>, pub stop: Cell<&'a Expression<'a>>,
pub body: Arc<Statement>, pub body: Cell<&'a Statement<'a>>,
} }
impl Node for IterationStatement { impl<'a> Node for IterationStatement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl FromAst<leo_ast::IterationStatement> for Arc<Statement> { impl<'a> FromAst<'a, leo_ast::IterationStatement> for &'a Statement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
statement: &leo_ast::IterationStatement, statement: &leo_ast::IterationStatement,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Arc<Statement>, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
let expected_index_type = Some(PartialType::Integer(None, Some(IntegerType::U32))); let expected_index_type = Some(PartialType::Integer(None, Some(IntegerType::U32)));
let start = Arc::<Expression>::from_ast(scope, &statement.start, expected_index_type.clone())?; let start = <&Expression<'a>>::from_ast(scope, &statement.start, expected_index_type.clone())?;
let stop = Arc::<Expression>::from_ast(scope, &statement.stop, expected_index_type)?; let stop = <&Expression<'a>>::from_ast(scope, &statement.stop, expected_index_type)?;
let variable = Arc::new(RefCell::new(InnerVariable { let variable = scope.alloc_variable(RefCell::new(InnerVariable {
id: uuid::Uuid::new_v4(), id: uuid::Uuid::new_v4(),
name: statement.variable.clone(), name: statement.variable.clone(),
type_: start type_: start
.get_type() .get_type()
.ok_or_else(|| AsgConvertError::unresolved_type(&statement.variable.name, &statement.span))? .ok_or_else(|| AsgConvertError::unresolved_type(&statement.variable.name, &statement.span))?,
.weak(),
mutable: false, mutable: false,
const_: true, const_: true,
declaration: crate::VariableDeclaration::IterationDefinition, declaration: crate::VariableDeclaration::IterationDefinition,
@ -74,34 +70,34 @@ impl FromAst<leo_ast::IterationStatement> for Arc<Statement> {
assignments: vec![], assignments: vec![],
})); }));
scope scope
.borrow_mut()
.variables .variables
.insert(statement.variable.name.clone(), variable.clone()); .borrow_mut()
.insert(statement.variable.name.clone(), variable);
let statement = Arc::new(Statement::Iteration(IterationStatement { let statement = scope.alloc_statement(Statement::Iteration(IterationStatement {
parent: None, parent: Cell::new(None),
span: Some(statement.span.clone()), span: Some(statement.span.clone()),
variable: variable.clone(), variable,
stop, stop: Cell::new(stop),
start, start: Cell::new(start),
body: Arc::new(Statement::Block(crate::BlockStatement::from_ast( body: Cell::new(scope.alloc_statement(Statement::Block(crate::BlockStatement::from_ast(
scope, scope,
&statement.block, &statement.block,
None, None,
)?)), )?))),
})); }));
variable.borrow_mut().assignments.push(Arc::downgrade(&statement)); variable.borrow_mut().assignments.push(statement);
Ok(statement) Ok(statement)
} }
} }
impl Into<leo_ast::IterationStatement> for &IterationStatement { impl<'a> Into<leo_ast::IterationStatement> for &IterationStatement<'a> {
fn into(self) -> leo_ast::IterationStatement { fn into(self) -> leo_ast::IterationStatement {
leo_ast::IterationStatement { leo_ast::IterationStatement {
variable: self.variable.borrow().name.clone(), variable: self.variable.borrow().name.clone(),
start: self.start.as_ref().into(), start: self.start.get().into(),
stop: self.stop.as_ref().into(), stop: self.stop.get().into(),
block: match self.body.as_ref() { block: match self.body.get() {
Statement::Block(block) => block.into(), Statement::Block(block) => block.into(),
_ => unimplemented!(), _ => unimplemented!(),
}, },

View File

@ -44,21 +44,19 @@ pub use return_::*;
use crate::{AsgConvertError, FromAst, Node, PartialType, Scope, Span}; use crate::{AsgConvertError, FromAst, Node, PartialType, Scope, Span};
use std::sync::Arc; #[derive(Clone)]
pub enum Statement<'a> {
#[derive(Debug)] Return(ReturnStatement<'a>),
pub enum Statement { Definition(DefinitionStatement<'a>),
Return(ReturnStatement), Assign(AssignStatement<'a>),
Definition(DefinitionStatement), Conditional(ConditionalStatement<'a>),
Assign(AssignStatement), Iteration(IterationStatement<'a>),
Conditional(ConditionalStatement), Console(ConsoleStatement<'a>),
Iteration(IterationStatement), Expression(ExpressionStatement<'a>),
Console(ConsoleStatement), Block(BlockStatement<'a>),
Expression(ExpressionStatement),
Block(BlockStatement),
} }
impl Node for Statement { impl<'a> Node for Statement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
use Statement::*; use Statement::*;
match self { match self {
@ -74,31 +72,37 @@ impl Node for Statement {
} }
} }
impl FromAst<leo_ast::Statement> for Arc<Statement> { impl<'a> FromAst<'a, leo_ast::Statement> for &'a Statement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
value: &leo_ast::Statement, value: &leo_ast::Statement,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Arc<Statement>, AsgConvertError> { ) -> Result<&'a Statement<'a>, AsgConvertError> {
use leo_ast::Statement::*; use leo_ast::Statement::*;
Ok(match value { Ok(match value {
Return(statement) => Arc::new(Statement::Return(ReturnStatement::from_ast(scope, statement, None)?)), Return(statement) => {
Definition(statement) => Arc::<Statement>::from_ast(scope, statement, None)?, scope.alloc_statement(Statement::Return(ReturnStatement::from_ast(scope, statement, None)?))
Assign(statement) => Arc::<Statement>::from_ast(scope, statement, None)?, }
Conditional(statement) => Arc::new(Statement::Conditional(ConditionalStatement::from_ast( Definition(statement) => Self::from_ast(scope, statement, None)?,
Assign(statement) => Self::from_ast(scope, statement, None)?,
Conditional(statement) => scope.alloc_statement(Statement::Conditional(ConditionalStatement::from_ast(
scope, statement, None, scope, statement, None,
)?)), )?)),
Iteration(statement) => Arc::<Statement>::from_ast(scope, statement, None)?, Iteration(statement) => Self::from_ast(scope, statement, None)?,
Console(statement) => Arc::new(Statement::Console(ConsoleStatement::from_ast(scope, statement, None)?)), Console(statement) => {
Expression(statement) => Arc::new(Statement::Expression(ExpressionStatement::from_ast( scope.alloc_statement(Statement::Console(ConsoleStatement::from_ast(scope, statement, None)?))
}
Expression(statement) => scope.alloc_statement(Statement::Expression(ExpressionStatement::from_ast(
scope, statement, None, scope, statement, None,
)?)), )?)),
Block(statement) => Arc::new(Statement::Block(BlockStatement::from_ast(scope, statement, None)?)), Block(statement) => {
scope.alloc_statement(Statement::Block(BlockStatement::from_ast(scope, statement, None)?))
}
}) })
} }
} }
impl Into<leo_ast::Statement> for &Statement { impl<'a> Into<leo_ast::Statement> for &Statement<'a> {
fn into(self) -> leo_ast::Statement { fn into(self) -> leo_ast::Statement {
use Statement::*; use Statement::*;
match self { match self {

View File

@ -16,44 +16,46 @@
use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type}; use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
use std::sync::{Arc, Weak}; use std::cell::Cell;
#[derive(Clone)]
#[derive(Debug)] pub struct ReturnStatement<'a> {
pub struct ReturnStatement { pub parent: Cell<Option<&'a Statement<'a>>>,
pub parent: Option<Weak<Statement>>,
pub span: Option<Span>, pub span: Option<Span>,
pub expression: Arc<Expression>, pub expression: Cell<&'a Expression<'a>>,
} }
impl Node for ReturnStatement { impl<'a> Node for ReturnStatement<'a> {
fn span(&self) -> Option<&Span> { fn span(&self) -> Option<&Span> {
self.span.as_ref() self.span.as_ref()
} }
} }
impl FromAst<leo_ast::ReturnStatement> for ReturnStatement { impl<'a> FromAst<'a, leo_ast::ReturnStatement> for ReturnStatement<'a> {
fn from_ast( fn from_ast(
scope: &Scope, scope: &'a Scope<'a>,
statement: &leo_ast::ReturnStatement, statement: &leo_ast::ReturnStatement,
_expected_type: Option<PartialType>, _expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> { ) -> Result<Self, AsgConvertError> {
let return_type: Option<Type> = scope let return_type: Option<Type> = scope
.borrow()
.resolve_current_function() .resolve_current_function()
.map(|x| x.output.clone()) .map(|x| x.output.clone())
.map(Into::into); .map(Into::into);
Ok(ReturnStatement { Ok(ReturnStatement {
parent: None, parent: Cell::new(None),
span: Some(statement.span.clone()), span: Some(statement.span.clone()),
expression: Arc::<Expression>::from_ast(scope, &statement.expression, return_type.map(Into::into))?, expression: Cell::new(<&Expression<'a>>::from_ast(
scope,
&statement.expression,
return_type.map(Into::into),
)?),
}) })
} }
} }
impl Into<leo_ast::ReturnStatement> for &ReturnStatement { impl<'a> Into<leo_ast::ReturnStatement> for &ReturnStatement<'a> {
fn into(self) -> leo_ast::ReturnStatement { fn into(self) -> leo_ast::ReturnStatement {
leo_ast::ReturnStatement { leo_ast::ReturnStatement {
expression: self.expression.as_ref().into(), expression: self.expression.get().into(),
span: self.span.clone().unwrap_or_default(), span: self.span.clone().unwrap_or_default(),
} }
} }

View File

@ -17,14 +17,11 @@
use crate::Circuit; use crate::Circuit;
pub use leo_ast::IntegerType; pub use leo_ast::IntegerType;
use std::{ use std::fmt;
fmt,
sync::{Arc, Weak},
};
/// A type in an ASG. /// A type in an asg.
#[derive(Debug, Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum Type { pub enum Type<'a> {
// Data types // Data types
Address, Address,
Boolean, Boolean,
@ -33,55 +30,21 @@ pub enum Type {
Integer(IntegerType), Integer(IntegerType),
// Data type wrappers // Data type wrappers
Array(Box<Type>, usize), Array(Box<Type<'a>>, usize),
Tuple(Vec<Type>), Tuple(Vec<Type<'a>>),
Circuit(Arc<Circuit>), Circuit(&'a Circuit<'a>),
} }
#[derive(Debug, Clone)] #[derive(Clone, PartialEq)]
pub enum WeakType { pub enum PartialType<'a> {
Type(Type), // circuit not allowed Type(Type<'a>), // non-array or tuple
Circuit(Weak<Circuit>),
}
#[derive(Debug, Clone, PartialEq)]
pub enum PartialType {
Type(Type), // non-array or tuple
Integer(Option<IntegerType>, Option<IntegerType>), // specific, context-specific Integer(Option<IntegerType>, Option<IntegerType>), // specific, context-specific
Array(Option<Box<PartialType>>, Option<usize>), Array(Option<Box<PartialType<'a>>>, Option<usize>),
Tuple(Vec<Option<PartialType>>), Tuple(Vec<Option<PartialType<'a>>>),
} }
impl Into<Type> for WeakType { impl<'a> Into<Option<Type<'a>>> for PartialType<'a> {
fn into(self) -> Type { fn into(self) -> Option<Type<'a>> {
match self {
WeakType::Type(t) => t,
WeakType::Circuit(circuit) => Type::Circuit(circuit.upgrade().unwrap()),
}
}
}
impl WeakType {
pub fn strong(self) -> Type {
self.into()
}
pub fn is_unit(&self) -> bool {
matches!(self, WeakType::Type(Type::Tuple(t)) if t.is_empty())
}
}
impl Into<WeakType> for Type {
fn into(self) -> WeakType {
match self {
Type::Circuit(circuit) => WeakType::Circuit(Arc::downgrade(&circuit)),
t => WeakType::Type(t),
}
}
}
impl Into<Option<Type>> for PartialType {
fn into(self) -> Option<Type> {
match self { match self {
PartialType::Type(t) => Some(t), PartialType::Type(t) => Some(t),
PartialType::Integer(sub_type, contextual_type) => Some(Type::Integer(sub_type.or(contextual_type)?)), PartialType::Integer(sub_type, contextual_type) => Some(Type::Integer(sub_type.or(contextual_type)?)),
@ -96,12 +59,12 @@ impl Into<Option<Type>> for PartialType {
} }
} }
impl PartialType { impl<'a> PartialType<'a> {
pub fn full(self) -> Option<Type> { pub fn full(self) -> Option<Type<'a>> {
self.into() self.into()
} }
pub fn matches(&self, other: &Type) -> bool { pub fn matches(&self, other: &Type<'a>) -> bool {
match (self, other) { match (self, other) {
(PartialType::Type(t), other) => t.is_assignable_from(other), (PartialType::Type(t), other) => t.is_assignable_from(other),
(PartialType::Integer(self_sub_type, _), Type::Integer(sub_type)) => { (PartialType::Integer(self_sub_type, _), Type::Integer(sub_type)) => {
@ -137,8 +100,8 @@ impl PartialType {
} }
} }
impl Into<PartialType> for Type { impl<'a> Into<PartialType<'a>> for Type<'a> {
fn into(self) -> PartialType { fn into(self) -> PartialType<'a> {
match self { match self {
Type::Integer(sub_type) => PartialType::Integer(Some(sub_type), None), Type::Integer(sub_type) => PartialType::Integer(Some(sub_type), None),
Type::Array(element, len) => PartialType::Array(Some(Box::new((*element).into())), Some(len)), Type::Array(element, len) => PartialType::Array(Some(Box::new((*element).into())), Some(len)),
@ -148,16 +111,12 @@ impl Into<PartialType> for Type {
} }
} }
impl Type { impl<'a> Type<'a> {
pub fn is_assignable_from(&self, from: &Type) -> bool { pub fn is_assignable_from(&self, from: &Type<'a>) -> bool {
self == from self == from
} }
pub fn partial(self) -> PartialType { pub fn partial(self) -> PartialType<'a> {
self.into()
}
pub fn weak(self) -> WeakType {
self.into() self.into()
} }
@ -166,7 +125,7 @@ impl Type {
} }
} }
impl fmt::Display for Type { impl<'a> fmt::Display for Type<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Type::Address => write!(f, "address"), Type::Address => write!(f, "address"),
@ -190,7 +149,7 @@ impl fmt::Display for Type {
} }
} }
impl fmt::Display for PartialType { impl<'a> fmt::Display for PartialType<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
PartialType::Type(t) => t.fmt(f), PartialType::Type(t) => t.fmt(f),
@ -230,7 +189,7 @@ impl fmt::Display for PartialType {
} }
} }
impl Into<leo_ast::Type> for &Type { impl<'a> Into<leo_ast::Type> for &Type<'a> {
fn into(self) -> leo_ast::Type { fn into(self) -> leo_ast::Type {
use Type::*; use Type::*;
match self { match self {

View File

@ -14,17 +14,15 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Statement, WeakType}; use std::cell::RefCell;
use crate::{Expression, Statement, Type};
use leo_ast::Identifier; use leo_ast::Identifier;
use std::{
cell::RefCell,
sync::{Arc, Weak},
};
use uuid::Uuid; use uuid::Uuid;
/// Specifies how a program variable was declared. /// Specifies how a program variable was declared.
#[derive(Debug, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub enum VariableDeclaration { pub enum VariableDeclaration {
Definition, Definition,
IterationDefinition, IterationDefinition,
@ -33,17 +31,16 @@ pub enum VariableDeclaration {
} }
/// Stores information on a program variable. /// Stores information on a program variable.
#[derive(Debug)] #[derive(Clone)]
pub struct InnerVariable { pub struct InnerVariable<'a> {
pub id: Uuid, pub id: Uuid,
pub name: Identifier, pub name: Identifier,
pub type_: WeakType, pub type_: Type<'a>,
pub mutable: bool, pub mutable: bool,
pub const_: bool, // only function arguments, const var definitions NOT included pub const_: bool, // only function arguments, const var definitions NOT included
pub declaration: VariableDeclaration, pub declaration: VariableDeclaration,
pub references: Vec<Weak<Expression>>, // all Expression::VariableRef or panic pub references: Vec<&'a Expression<'a>>, // all Expression::VariableRef or panic
pub assignments: Vec<Weak<Statement>>, // all Statement::Assign or panic -- must be 1 if not mutable, or 0 if declaration == input | parameter pub assignments: Vec<&'a Statement<'a>>, // all Statement::Assign or panic -- must be 1 if not mutable, or 0 if declaration == input | parameter
} }
pub type Variable = Arc<RefCell<InnerVariable>>; pub type Variable<'a> = RefCell<InnerVariable<'a>>;
pub type WeakVariable = Weak<RefCell<InnerVariable>>;

View File

@ -14,10 +14,12 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_implicit_invalid() { fn test_implicit_invalid() {
let program_string = include_str!("implicit_invalid.leo"); let program_string = include_str!("implicit_invalid.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
// Expressions // Expressions
@ -21,49 +23,49 @@ use crate::load_asg;
#[test] #[test]
fn test_initializer_fail() { fn test_initializer_fail() {
let program_string = include_str!("initializer_fail.leo"); let program_string = include_str!("initializer_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_input_nested_3x2_fail() { fn test_input_nested_3x2_fail() {
let program_string = include_str!("input_nested_3x2_fail.leo"); let program_string = include_str!("input_nested_3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_input_tuple_3x2_fail() { fn test_input_tuple_3x2_fail() {
let program_string = include_str!("input_tuple_3x2_fail.leo"); let program_string = include_str!("input_tuple_3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_multi_fail_initializer() { fn test_multi_fail_initializer() {
let program_string = include_str!("multi_fail_initializer.leo"); let program_string = include_str!("multi_fail_initializer.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_multi_inline_fail() { fn test_multi_inline_fail() {
let program_string = include_str!("multi_fail_inline.leo"); let program_string = include_str!("multi_fail_inline.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_multi_initializer_fail() { fn test_multi_initializer_fail() {
let program_string = include_str!("multi_initializer_fail.leo"); let program_string = include_str!("multi_initializer_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_nested_3x2_value_fail() { fn test_nested_3x2_value_fail() {
let program_string = include_str!("nested_3x2_value_fail.leo"); let program_string = include_str!("nested_3x2_value_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_tuple_3x2_value_fail() { fn test_tuple_3x2_value_fail() {
let program_string = include_str!("tuple_3x2_value_fail.leo"); let program_string = include_str!("tuple_3x2_value_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
// Array type tests // Array type tests
@ -71,65 +73,65 @@ fn test_tuple_3x2_value_fail() {
#[test] #[test]
fn test_type_fail() { fn test_type_fail() {
let program_string = include_str!("type_fail.leo"); let program_string = include_str!("type_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_nested_value_nested_3x2_fail() { fn test_type_nested_value_nested_3x2_fail() {
let program_string = include_str!("type_nested_value_nested_3x2_fail.leo"); let program_string = include_str!("type_nested_value_nested_3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_nested_value_nested_4x3x2_fail() { fn test_type_nested_value_nested_4x3x2_fail() {
let program_string = include_str!("type_nested_value_nested_4x3x2_fail.leo"); let program_string = include_str!("type_nested_value_nested_4x3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_nested_value_tuple_3x2_fail() { fn test_type_nested_value_tuple_3x2_fail() {
let program_string = include_str!("type_nested_value_tuple_3x2_fail.leo"); let program_string = include_str!("type_nested_value_tuple_3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_nested_value_tuple_4x3x2_fail() { fn test_type_nested_value_tuple_4x3x2_fail() {
let program_string = include_str!("type_nested_value_tuple_4x3x2_fail.leo"); let program_string = include_str!("type_nested_value_tuple_4x3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_nested_3x2_fail() { fn test_type_tuple_value_nested_3x2_fail() {
let program_string = include_str!("type_tuple_value_nested_3x2_fail.leo"); let program_string = include_str!("type_tuple_value_nested_3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_nested_3x2_swap_fail() { fn test_type_tuple_value_nested_3x2_swap_fail() {
let program_string = include_str!("type_tuple_value_nested_3x2_swap_fail.leo"); let program_string = include_str!("type_tuple_value_nested_3x2_swap_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_nested_4x3x2_fail() { fn test_type_tuple_value_nested_4x3x2_fail() {
let program_string = include_str!("type_tuple_value_nested_4x3x2_fail.leo"); let program_string = include_str!("type_tuple_value_nested_4x3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_tuple_3x2_fail() { fn test_type_tuple_value_tuple_3x2_fail() {
let program_string = include_str!("type_tuple_value_tuple_3x2_fail.leo"); let program_string = include_str!("type_tuple_value_tuple_3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_tuple_3x2_swap_fail() { fn test_type_tuple_value_tuple_3x2_swap_fail() {
let program_string = include_str!("type_tuple_value_tuple_3x2_swap_fail.leo"); let program_string = include_str!("type_tuple_value_tuple_3x2_swap_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_tuple_4x3x2_fail() { fn test_type_tuple_value_tuple_4x3x2_fail() {
let program_string = include_str!("type_tuple_value_tuple_4x3x2_fail.leo"); let program_string = include_str!("type_tuple_value_tuple_4x3x2_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -14,22 +14,24 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_not_u32() { fn test_not_u32() {
let program_string = include_str!("not_u32.leo"); let program_string = include_str!("not_u32.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_true_or_u32() { fn test_true_or_u32() {
let program_string = include_str!("true_or_u32.leo"); let program_string = include_str!("true_or_u32.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_true_and_u32() { fn test_true_and_u32() {
let program_string = include_str!("true_and_u32.leo"); let program_string = include_str!("true_and_u32.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
// Expressions // Expressions
@ -21,13 +23,13 @@ use crate::load_asg;
#[test] #[test]
fn test_inline_fail() { fn test_inline_fail() {
let program_string = include_str!("inline_fail.leo"); let program_string = include_str!("inline_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_inline_undefined() { fn test_inline_undefined() {
let program_string = include_str!("inline_undefined.leo"); let program_string = include_str!("inline_undefined.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
// Members // Members
@ -35,19 +37,19 @@ fn test_inline_undefined() {
#[test] #[test]
fn test_member_variable_fail() { fn test_member_variable_fail() {
let program_string = include_str!("member_variable_fail.leo"); let program_string = include_str!("member_variable_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_member_function_fail() { fn test_member_function_fail() {
let program_string = include_str!("member_function_fail.leo"); let program_string = include_str!("member_function_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_member_function_invalid() { fn test_member_function_invalid() {
let program_string = include_str!("member_function_invalid.leo"); let program_string = include_str!("member_function_invalid.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
@ -64,19 +66,19 @@ fn test_mut_member_function_fail() {
console.assert(a.echo(1u32) == 1u32); console.assert(a.echo(1u32) == 1u32);
}"#; }"#;
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_member_static_function_invalid() { fn test_member_static_function_invalid() {
let program_string = include_str!("member_static_function_invalid.leo"); let program_string = include_str!("member_static_function_invalid.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_member_static_function_undefined() { fn test_member_static_function_undefined() {
let program_string = include_str!("member_static_function_undefined.leo"); let program_string = include_str!("member_static_function_undefined.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
// Mutability // Mutability
@ -84,37 +86,37 @@ fn test_member_static_function_undefined() {
#[test] #[test]
fn test_mutate_function_fail() { fn test_mutate_function_fail() {
let program_string = include_str!("mut_function_fail.leo"); let program_string = include_str!("mut_function_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_mutate_self_variable_fail() { fn test_mutate_self_variable_fail() {
let program_string = include_str!("mut_self_variable_fail.leo"); let program_string = include_str!("mut_self_variable_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_mutate_self_function_fail() { fn test_mutate_self_function_fail() {
let program_string = include_str!("mut_self_function_fail.leo"); let program_string = include_str!("mut_self_function_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_mutate_self_static_function_fail() { fn test_mutate_self_static_function_fail() {
let program_string = include_str!("mut_self_static_function_fail.leo"); let program_string = include_str!("mut_self_static_function_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_mutate_static_function_fail() { fn test_mutate_static_function_fail() {
let program_string = include_str!("mut_static_function_fail.leo"); let program_string = include_str!("mut_static_function_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_mutate_variable_fail() { fn test_mutate_variable_fail() {
let program_string = include_str!("mut_variable_fail.leo"); let program_string = include_str!("mut_variable_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
// Self // Self
@ -122,17 +124,17 @@ fn test_mutate_variable_fail() {
#[test] #[test]
fn test_self_fail() { fn test_self_fail() {
let program_string = include_str!("self_fail.leo"); let program_string = include_str!("self_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_self_member_invalid() { fn test_self_member_invalid() {
let program_string = include_str!("self_member_invalid.leo"); let program_string = include_str!("self_member_invalid.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_self_member_undefined() { fn test_self_member_undefined() {
let program_string = include_str!("self_member_undefined.leo"); let program_string = include_str!("self_member_undefined.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -14,28 +14,30 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_log_fail() { fn test_log_fail() {
let program_string = include_str!("log_fail.leo"); let program_string = include_str!("log_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_log_parameter_fail_unknown() { fn test_log_parameter_fail_unknown() {
let program_string = include_str!("log_parameter_fail_unknown.leo"); let program_string = include_str!("log_parameter_fail_unknown.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_log_parameter_fail_empty() { fn test_log_parameter_fail_empty() {
let program_string = include_str!("log_parameter_fail_empty.leo"); let program_string = include_str!("log_parameter_fail_empty.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_log_parameter_fail_none() { fn test_log_parameter_fail_none() {
let program_string = include_str!("log_parameter_fail_empty.leo"); let program_string = include_str!("log_parameter_fail_empty.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -14,28 +14,30 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_core_circuit_invalid() { fn test_core_circuit_invalid() {
let program_string = include_str!("core_package_invalid.leo"); let program_string = include_str!("core_package_invalid.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_core_circuit_star_fail() { fn test_core_circuit_star_fail() {
let program_string = include_str!("core_circuit_star_fail.leo"); let program_string = include_str!("core_circuit_star_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_core_package_invalid() { fn test_core_package_invalid() {
let program_string = include_str!("core_package_invalid.leo"); let program_string = include_str!("core_package_invalid.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_core_unstable_package_invalid() { fn test_core_unstable_package_invalid() {
let program_string = include_str!("core_unstable_package_invalid.leo"); let program_string = include_str!("core_unstable_package_invalid.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -14,42 +14,44 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_multiple_returns_fail() { fn test_multiple_returns_fail() {
let program_string = include_str!("multiple_returns_fail.leo"); let program_string = include_str!("multiple_returns_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_multiple_returns_input_ambiguous() { fn test_multiple_returns_input_ambiguous() {
let program_string = include_str!("multiple_returns_input_ambiguous.leo"); let program_string = include_str!("multiple_returns_input_ambiguous.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_multiple_returns_fail_conditional() { fn test_multiple_returns_fail_conditional() {
let program_string = include_str!("multiple_returns_fail_conditional.leo"); let program_string = include_str!("multiple_returns_fail_conditional.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_scope_fail() { fn test_scope_fail() {
let program_string = include_str!("scope_fail.leo"); let program_string = include_str!("scope_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_undefined() { fn test_undefined() {
let program_string = include_str!("undefined.leo"); let program_string = include_str!("undefined.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_array_input() { fn test_array_input() {
let program_string = include_str!("array_input.leo"); let program_string = include_str!("array_input.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
// Test return multidimensional arrays // Test return multidimensional arrays
@ -57,11 +59,11 @@ fn test_array_input() {
#[test] #[test]
fn test_return_array_nested_fail() { fn test_return_array_nested_fail() {
let program_string = include_str!("return_array_nested_fail.leo"); let program_string = include_str!("return_array_nested_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_return_array_tuple_fail() { fn test_return_array_tuple_fail() {
let program_string = include_str!("return_array_tuple_fail.leo"); let program_string = include_str!("return_array_tuple_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -19,17 +19,17 @@ use crate::load_asg;
#[test] #[test]
fn test_both_sign_high() { fn test_both_sign_high() {
let program_string = include_str!("both_sign_high.leo"); let program_string = include_str!("both_sign_high.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_both_sign_low() { fn test_both_sign_low() {
let program_string = include_str!("both_sign_low.leo"); let program_string = include_str!("both_sign_low.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_both_sign_inferred() { fn test_both_sign_inferred() {
let program_string = include_str!("both_sign_inferred.leo"); let program_string = include_str!("both_sign_inferred.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -16,25 +16,27 @@
macro_rules! test_int { macro_rules! test_int {
($name: ident) => { ($name: ident) => {
use leo_asg::new_context;
pub struct $name {} pub struct $name {}
// we are not doing constant folding here, so asg doesnt catch this // we are not doing constant folding here, so asg doesnt catch this
// impl $name { // impl $name {
// fn test_negate_min_fail() { // fn test_negate_min_fail() {
// let program_string = include_str!("negate_min.leo"); // let program_string = include_str!("negate_min.leo");
// crate::load_asg(program_string).err().unwrap(); // crate::load_asg(&new_context(), program_string).err().unwrap();
// } // }
// } // }
impl super::IntegerTester for $name { impl super::IntegerTester for $name {
fn test_min_fail() { fn test_min_fail() {
let program_string = include_str!("min_fail.leo"); let program_string = include_str!("min_fail.leo");
crate::load_asg(program_string).err().unwrap(); crate::load_asg(&new_context(), program_string).err().unwrap();
} }
fn test_max_fail() { fn test_max_fail() {
let program_string = include_str!("max_fail.leo"); let program_string = include_str!("max_fail.leo");
crate::load_asg(program_string).err().unwrap(); crate::load_asg(&new_context(), program_string).err().unwrap();
} }
} }
}; };

View File

@ -16,17 +16,19 @@
macro_rules! test_uint { macro_rules! test_uint {
($name: ident) => { ($name: ident) => {
use leo_asg::new_context;
pub struct $name {} pub struct $name {}
impl super::IntegerTester for $name { impl super::IntegerTester for $name {
fn test_min_fail() { fn test_min_fail() {
let program_string = include_str!("min_fail.leo"); let program_string = include_str!("min_fail.leo");
crate::load_asg(program_string).err().unwrap(); crate::load_asg(&new_context(), program_string).err().unwrap();
} }
fn test_max_fail() { fn test_max_fail() {
let program_string = include_str!("max_fail.leo"); let program_string = include_str!("max_fail.leo");
crate::load_asg(program_string).err().unwrap(); crate::load_asg(&new_context(), program_string).err().unwrap();
} }
} }
}; };

View File

@ -14,46 +14,54 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_let() { fn test_let() {
let program_string = include_str!("let.leo"); let program_string = include_str!("let.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_const_fail() { fn test_const_fail() {
let program_string = include_str!("const.leo"); let program_string = include_str!("const.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
}
#[test]
fn test_const_mut_fail() {
let program_string = include_str!("const_mut.leo");
load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_array() { fn test_array() {
let program_string = include_str!("array.leo"); let program_string = include_str!("array.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_circuit() { fn test_circuit() {
let program_string = include_str!("circuit.leo"); let program_string = include_str!("circuit.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_circuit_function_mut() { fn test_circuit_function_mut() {
let program_string = include_str!("circuit_function_mut.leo"); let program_string = include_str!("circuit_function_mut.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_circuit_static_function_mut() { fn test_circuit_static_function_mut() {
let program_string = include_str!("circuit_static_function_mut.leo"); let program_string = include_str!("circuit_static_function_mut.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_function_input() { fn test_function_input() {
let program_string = include_str!("function_input.leo"); let program_string = include_str!("function_input.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }

View File

@ -14,12 +14,14 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_num_returns_fail() { fn test_num_returns_fail() {
let program_string = include_str!("num_returns_fail.leo"); let program_string = include_str!("num_returns_fail.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]

View File

@ -26,20 +26,21 @@ mod pass;
const TESTING_FILEPATH: &str = "input.leo"; const TESTING_FILEPATH: &str = "input.leo";
const TESTING_PROGRAM_NAME: &str = "test_program"; const TESTING_PROGRAM_NAME: &str = "test_program";
fn load_asg(program_string: &str) -> Result<Program, AsgConvertError> { fn load_asg<'a>(context: AsgContext<'a>, program_string: &str) -> Result<Program<'a>, AsgConvertError> {
load_asg_imports(program_string, &mut NullImportResolver) load_asg_imports(context, program_string, &mut NullImportResolver)
} }
fn load_asg_imports<T: ImportResolver + 'static>( fn load_asg_imports<'a, T: ImportResolver<'a>>(
context: AsgContext<'a>,
program_string: &str, program_string: &str,
imports: &mut T, imports: &mut T,
) -> Result<Program, AsgConvertError> { ) -> Result<Program<'a>, AsgConvertError> {
let grammar = Grammar::new(Path::new(&TESTING_FILEPATH), program_string)?; let grammar = Grammar::new(Path::new(&TESTING_FILEPATH), program_string)?;
let ast = Ast::new(TESTING_PROGRAM_NAME, &grammar)?; let ast = Ast::new(TESTING_PROGRAM_NAME, &grammar)?;
InternalProgram::new(&ast.as_repr(), imports) InternalProgram::new(context, &ast.as_repr(), imports)
} }
fn mocked_resolver() -> MockedImportResolver { fn mocked_resolver<'a>(_ctx: AsgContext<'a>) -> MockedImportResolver<'a> {
let packages = indexmap::IndexMap::new(); let packages = indexmap::IndexMap::new();
MockedImportResolver { packages } MockedImportResolver { packages }
} }

View File

@ -14,35 +14,37 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_valid() { fn test_valid() {
let program_string = include_str!("valid.leo"); let program_string = include_str!("valid.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_implicit_valid() { fn test_implicit_valid() {
let program_string = include_str!("implicit_valid.leo"); let program_string = include_str!("implicit_valid.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_console_assert_pass() { fn test_console_assert_pass() {
let program_string = include_str!("console_assert_pass.leo"); let program_string = include_str!("console_assert_pass.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_ternary() { fn test_ternary() {
let program_string = include_str!("ternary.leo"); let program_string = include_str!("ternary.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_equal() { fn test_equal() {
let program_string = include_str!("equal.leo"); let program_string = include_str!("equal.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
// Registers // Registers
@ -21,7 +23,7 @@ use crate::load_asg;
#[test] #[test]
fn test_registers() { fn test_registers() {
let program_string = include_str!("registers.leo"); let program_string = include_str!("registers.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Expressions // Expressions
@ -29,173 +31,173 @@ fn test_registers() {
#[test] #[test]
fn test_inline() { fn test_inline() {
let program_string = include_str!("inline.leo"); let program_string = include_str!("inline.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_initializer() { fn test_initializer() {
let program_string = include_str!("initializer.leo"); let program_string = include_str!("initializer.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_initializer_input() { fn test_initializer_input() {
let program_string = include_str!("initializer_input.leo"); let program_string = include_str!("initializer_input.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_nested_3x2() { fn test_input_nested_3x2() {
let program_string = include_str!("input_nested_3x2.leo"); let program_string = include_str!("input_nested_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_tuple_3x2() { fn test_input_tuple_3x2() {
let program_string = include_str!("input_tuple_3x2.leo"); let program_string = include_str!("input_tuple_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_multi_initializer() { fn test_multi_initializer() {
let program_string = include_str!("multi_initializer.leo"); let program_string = include_str!("multi_initializer.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_nested_3x2_value() { fn test_nested_3x2_value() {
let program_string = include_str!("nested_3x2_value.leo"); let program_string = include_str!("nested_3x2_value.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_tuple_3x2_value() { fn test_tuple_3x2_value() {
let program_string = include_str!("tuple_3x2_value.leo"); let program_string = include_str!("tuple_3x2_value.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_spread() { fn test_spread() {
let program_string = include_str!("spread.leo"); let program_string = include_str!("spread.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_slice() { fn test_slice() {
let program_string = include_str!("slice.leo"); let program_string = include_str!("slice.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_index_u8() { fn test_index_u8() {
let program_string = include_str!("index_u8.leo"); let program_string = include_str!("index_u8.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_slice_i8() { fn test_slice_i8() {
let program_string = include_str!("slice_i8.leo"); let program_string = include_str!("slice_i8.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_slice_lower() { fn test_slice_lower() {
let program_string = include_str!("slice_lower.leo"); let program_string = include_str!("slice_lower.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_type_nested_value_nested_3x2() { fn test_type_nested_value_nested_3x2() {
let program_string = include_str!("type_nested_value_nested_3x2.leo"); let program_string = include_str!("type_nested_value_nested_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_type_nested_value_nested_4x3x2() { fn test_type_nested_value_nested_4x3x2() {
let program_string = include_str!("type_nested_value_nested_4x3x2.leo"); let program_string = include_str!("type_nested_value_nested_4x3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_type_nested_value_tuple_3x2() { fn test_type_nested_value_tuple_3x2() {
let program_string = include_str!("type_nested_value_tuple_3x2.leo"); let program_string = include_str!("type_nested_value_tuple_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_type_nested_value_tuple_4x3x2() { fn test_type_nested_value_tuple_4x3x2() {
let program_string = include_str!("type_nested_value_tuple_4x3x2.leo"); let program_string = include_str!("type_nested_value_tuple_4x3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_nested_3x2() { fn test_type_tuple_value_nested_3x2() {
let program_string = include_str!("type_tuple_value_nested_3x2.leo"); let program_string = include_str!("type_tuple_value_nested_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_nested_4x3x2() { fn test_type_tuple_value_nested_4x3x2() {
let program_string = include_str!("type_tuple_value_nested_4x3x2.leo"); let program_string = include_str!("type_tuple_value_nested_4x3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_tuple_3x2() { fn test_type_tuple_value_tuple_3x2() {
let program_string = include_str!("type_tuple_value_tuple_3x2.leo"); let program_string = include_str!("type_tuple_value_tuple_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_type_tuple_value_tuple_4x3x2() { fn test_type_tuple_value_tuple_4x3x2() {
let program_string = include_str!("type_tuple_value_tuple_4x3x2.leo"); let program_string = include_str!("type_tuple_value_tuple_4x3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_type_nested_value_nested_3x2() { fn test_input_type_nested_value_nested_3x2() {
let program_string = include_str!("type_input_3x2.leo"); let program_string = include_str!("type_input_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_type_nested_value_nested_4x3x2() { fn test_input_type_nested_value_nested_4x3x2() {
let program_string = include_str!("type_input_4x3x2.leo"); let program_string = include_str!("type_input_4x3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_type_nested_value_tuple_3x2() { fn test_input_type_nested_value_tuple_3x2() {
let program_string = include_str!("type_input_3x2.leo"); let program_string = include_str!("type_input_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_type_nested_value_tuple_4x3x2() { fn test_input_type_nested_value_tuple_4x3x2() {
let program_string = include_str!("type_input_4x3x2.leo"); let program_string = include_str!("type_input_4x3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_type_tuple_value_nested_3x2() { fn test_input_type_tuple_value_nested_3x2() {
let program_string = include_str!("type_input_3x2.leo"); let program_string = include_str!("type_input_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_type_tuple_value_nested_4x3x2() { fn test_input_type_tuple_value_nested_4x3x2() {
let program_string = include_str!("type_input_4x3x2.leo"); let program_string = include_str!("type_input_4x3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_type_tuple_value_tuple_3x2() { fn test_input_type_tuple_value_tuple_3x2() {
let program_string = include_str!("type_input_3x2.leo"); let program_string = include_str!("type_input_3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_type_tuple_value_tuple_4x3x2() { fn test_input_type_tuple_value_tuple_4x3x2() {
let program_string = include_str!("type_input_4x3x2.leo"); let program_string = include_str!("type_input_4x3x2.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,18 +14,20 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_input_pass() { fn test_input_pass() {
let program_string = include_str!("assert_eq_input.leo"); let program_string = include_str!("assert_eq_input.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_registers() { fn test_registers() {
let program_string = include_str!("output_register.leo"); let program_string = include_str!("output_register.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Boolean not ! // Boolean not !
@ -33,19 +35,19 @@ fn test_registers() {
#[test] #[test]
fn test_not_true() { fn test_not_true() {
let program_string = include_str!("not_true.leo"); let program_string = include_str!("not_true.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_not_false() { fn test_not_false() {
let program_string = include_str!("not_false.leo"); let program_string = include_str!("not_false.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_not_mutable() { fn test_not_mutable() {
let program_string = include_str!("not_mutable.leo"); let program_string = include_str!("not_mutable.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Boolean or || // Boolean or ||
@ -53,19 +55,19 @@ fn test_not_mutable() {
#[test] #[test]
fn test_true_or_true() { fn test_true_or_true() {
let program_string = include_str!("true_or_true.leo"); let program_string = include_str!("true_or_true.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_true_or_false() { fn test_true_or_false() {
let program_string = include_str!("true_or_false.leo"); let program_string = include_str!("true_or_false.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_false_or_false() { fn test_false_or_false() {
let program_string = include_str!("false_or_false.leo"); let program_string = include_str!("false_or_false.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Boolean and && // Boolean and &&
@ -73,19 +75,19 @@ fn test_false_or_false() {
#[test] #[test]
fn test_true_and_true() { fn test_true_and_true() {
let program_string = include_str!("true_and_true.leo"); let program_string = include_str!("true_and_true.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_true_and_false() { fn test_true_and_false() {
let program_string = include_str!("true_and_false.leo"); let program_string = include_str!("true_and_false.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_false_and_false() { fn test_false_and_false() {
let program_string = include_str!("false_and_false.leo"); let program_string = include_str!("false_and_false.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// All // All
@ -93,5 +95,5 @@ fn test_false_and_false() {
#[test] #[test]
fn test_all() { fn test_all() {
let program_string = include_str!("all.leo"); let program_string = include_str!("all.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
// Expressions // Expressions
@ -21,7 +23,7 @@ use crate::load_asg;
#[test] #[test]
fn test_inline() { fn test_inline() {
let program_string = include_str!("inline.leo"); let program_string = include_str!("inline.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Members // Members
@ -29,19 +31,19 @@ fn test_inline() {
#[test] #[test]
fn test_member_variable() { fn test_member_variable() {
let program_string = include_str!("member_variable.leo"); let program_string = include_str!("member_variable.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_member_variable_and_function() { fn test_member_variable_and_function() {
let program_string = include_str!("member_variable_and_function.leo"); let program_string = include_str!("member_variable_and_function.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_member_function() { fn test_member_function() {
let program_string = include_str!("member_function.leo"); let program_string = include_str!("member_function.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
@ -58,25 +60,25 @@ fn test_mut_member_function() {
console.assert(a.echo(1u32) == 1u32); console.assert(a.echo(1u32) == 1u32);
}"#; }"#;
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_member_function_nested() { fn test_member_function_nested() {
let program_string = include_str!("member_function_nested.leo"); let program_string = include_str!("member_function_nested.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_member_static_function() { fn test_member_static_function() {
let program_string = include_str!("member_static_function.leo"); let program_string = include_str!("member_static_function.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_member_static_function_nested() { fn test_member_static_function_nested() {
let program_string = include_str!("member_static_function_nested.leo"); let program_string = include_str!("member_static_function_nested.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Mutability // Mutability
@ -84,19 +86,19 @@ fn test_member_static_function_nested() {
#[test] #[test]
fn test_mutate_self_variable() { fn test_mutate_self_variable() {
let program_string = include_str!("mut_self_variable.leo"); let program_string = include_str!("mut_self_variable.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_mutate_self_variable_conditional() { fn test_mutate_self_variable_conditional() {
let program_string = include_str!("mut_self_variable_conditional.leo"); let program_string = include_str!("mut_self_variable_conditional.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_mutate_variable() { fn test_mutate_variable() {
let program_string = include_str!("mut_variable.leo"); let program_string = include_str!("mut_variable.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Self // Self
@ -104,7 +106,7 @@ fn test_mutate_variable() {
#[test] #[test]
fn test_self_member_pass() { fn test_self_member_pass() {
let program_string = include_str!("self_member.leo"); let program_string = include_str!("self_member.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// All // All
@ -112,13 +114,13 @@ fn test_self_member_pass() {
#[test] #[test]
fn test_pedersen_mock() { fn test_pedersen_mock() {
let program_string = include_str!("pedersen_mock.leo"); let program_string = include_str!("pedersen_mock.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_define_circuit_inside_circuit_function() { fn test_define_circuit_inside_circuit_function() {
let program_string = include_str!("define_circuit_inside_circuit_function.leo"); let program_string = include_str!("define_circuit_inside_circuit_function.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
@ -131,5 +133,5 @@ fn test_circuit_explicit_define() {
let x: One = One {x: 5}; let x: One = One {x: 5};
} }
"#; "#;
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,30 +14,32 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_log() { fn test_log() {
let program_string = include_str!("log.leo"); let program_string = include_str!("log.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_log_parameter() { fn test_log_parameter() {
let program_string = include_str!("log_parameter.leo"); let program_string = include_str!("log_parameter.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_log_parameter_many() { fn test_log_parameter_many() {
let program_string = include_str!("log_parameter_many.leo"); let program_string = include_str!("log_parameter_many.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_log_input() { fn test_log_input() {
let program_string = include_str!("log_input.leo"); let program_string = include_str!("log_input.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Debug // Debug
@ -45,7 +47,7 @@ fn test_log_input() {
#[test] #[test]
fn test_debug() { fn test_debug() {
let program_string = include_str!("debug.leo"); let program_string = include_str!("debug.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Error // Error
@ -53,7 +55,7 @@ fn test_debug() {
#[test] #[test]
fn test_error() { fn test_error() {
let program_string = include_str!("error.leo"); let program_string = include_str!("error.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Assertion // Assertion
@ -61,11 +63,11 @@ fn test_error() {
#[test] #[test]
fn test_assert() { fn test_assert() {
let program_string = include_str!("assert.leo"); let program_string = include_str!("assert.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_conditional_assert() { fn test_conditional_assert() {
let program_string = include_str!("conditional_assert.leo"); let program_string = include_str!("conditional_assert.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,22 +14,24 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_unstable_blake2s() { fn test_unstable_blake2s() {
let program_string = include_str!("unstable_blake2s.leo"); let program_string = include_str!("unstable_blake2s.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_blake2s_input() { fn test_blake2s_input() {
let program_string = include_str!("blake2s_input.leo"); let program_string = include_str!("blake2s_input.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_blake2s_random() { fn test_blake2s_random() {
let program_string = include_str!("blake2s_random.leo"); let program_string = include_str!("blake2s_random.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,17 +14,19 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_out_of_order() { fn test_out_of_order() {
let program_string = include_str!("out_of_order.leo"); let program_string = include_str!("out_of_order.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// #[test] // #[test]
// #[ignore] // #[ignore]
// fn test_out_of_order_with_import() { // fn test_out_of_order_with_import() {
// let program_string = include_str!("out_of_order_with_import.leo"); // let program_string = include_str!("out_of_order_with_import.leo");
// load_asg(program_string).unwrap(); // load_asg(&new_context(), program_string).unwrap();
// } // }

View File

@ -14,18 +14,20 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_negate() { fn test_negate() {
let program_string = include_str!("negate.leo"); let program_string = include_str!("negate.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_add() { fn test_add() {
let program_string = include_str!("add.leo"); let program_string = include_str!("add.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
@ -35,41 +37,41 @@ fn test_add_explicit() {
let c: field = 0field + 1field; let c: field = 0field + 1field;
} }
"#; "#;
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_sub() { fn test_sub() {
let program_string = include_str!("sub.leo"); let program_string = include_str!("sub.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_div() { fn test_div() {
let program_string = include_str!("div.leo"); let program_string = include_str!("div.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_mul() { fn test_mul() {
let program_string = include_str!("mul.leo"); let program_string = include_str!("mul.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_eq() { fn test_eq() {
let program_string = include_str!("eq.leo"); let program_string = include_str!("eq.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_console_assert_pass() { fn test_console_assert_pass() {
let program_string = include_str!("console_assert.leo"); let program_string = include_str!("console_assert.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_ternary() { fn test_ternary() {
let program_string = include_str!("ternary.leo"); let program_string = include_str!("ternary.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
use leo_ast::Ast; use leo_ast::Ast;
use leo_grammar::Grammar; use leo_grammar::Grammar;
@ -23,7 +25,8 @@ use std::path::Path;
#[test] #[test]
fn test_basic() { fn test_basic() {
let program_string = include_str!("./circuits/pedersen_mock.leo"); let program_string = include_str!("./circuits/pedersen_mock.leo");
let asg = load_asg(program_string).unwrap(); let ctx = new_context();
let asg = load_asg(&ctx, program_string).unwrap();
let reformed_ast = leo_asg::reform_ast(&asg); let reformed_ast = leo_asg::reform_ast(&asg);
println!("{}", reformed_ast); println!("{}", reformed_ast);
// panic!(); // panic!();
@ -48,7 +51,8 @@ fn test_function_rename() {
console.assert(total == 20); console.assert(total == 20);
} }
"#; "#;
let asg = load_asg(program_string).unwrap(); let ctx = new_context();
let asg = load_asg(&ctx, program_string).unwrap();
let reformed_ast = leo_asg::reform_ast(&asg); let reformed_ast = leo_asg::reform_ast(&asg);
println!("{}", reformed_ast); println!("{}", reformed_ast);
// panic!(); // panic!();
@ -56,7 +60,8 @@ fn test_function_rename() {
#[test] #[test]
fn test_imports() { fn test_imports() {
let mut imports = crate::mocked_resolver(); let ctx = new_context();
let mut imports = crate::mocked_resolver(&ctx);
let test_import = r#" let test_import = r#"
circuit Point { circuit Point {
x: u32 x: u32
@ -69,7 +74,7 @@ fn test_imports() {
"#; "#;
imports imports
.packages .packages
.insert("test-import".to_string(), load_asg(test_import).unwrap()); .insert("test-import".to_string(), load_asg(&ctx, test_import).unwrap());
let program_string = r#" let program_string = r#"
import test-import.foo; import test-import.foo;
@ -90,7 +95,7 @@ fn test_imports() {
serde_json::to_string(Ast::new("test", &test_grammar).unwrap().as_repr()).unwrap() serde_json::to_string(Ast::new("test", &test_grammar).unwrap().as_repr()).unwrap()
); );
let asg = crate::load_asg_imports(program_string, &mut imports).unwrap(); let asg = crate::load_asg_imports(&ctx, program_string, &mut imports).unwrap();
let reformed_ast = leo_asg::reform_ast(&asg); let reformed_ast = leo_asg::reform_ast(&asg);
println!("{}", serde_json::to_string(&reformed_ast).unwrap()); println!("{}", serde_json::to_string(&reformed_ast).unwrap());
// panic!(); // panic!();

View File

@ -14,18 +14,20 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_empty() { fn test_empty() {
let program_string = include_str!("empty.leo"); let program_string = include_str!("empty.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_iteration() { fn test_iteration() {
let program_string = include_str!("iteration.leo"); let program_string = include_str!("iteration.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
@ -45,7 +47,7 @@ fn test_const_args() {
console.assert(a == 20u32); console.assert(a == 20u32);
} }
"#; "#;
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
@ -66,7 +68,7 @@ fn test_const_args_used() {
console.assert(a == 6u8); console.assert(a == 6u8);
} }
"#; "#;
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
@ -85,61 +87,61 @@ fn test_const_args_fail() {
console.assert(a == 1u8); console.assert(a == 1u8);
} }
"#; "#;
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_iteration_repeated() { fn test_iteration_repeated() {
let program_string = include_str!("iteration_repeated.leo"); let program_string = include_str!("iteration_repeated.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_newlines() { fn test_newlines() {
let program_string = include_str!("newlines.leo"); let program_string = include_str!("newlines.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_multiple_returns() { fn test_multiple_returns() {
let program_string = include_str!("multiple_returns.leo"); let program_string = include_str!("multiple_returns.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_multiple_returns_main() { fn test_multiple_returns_main() {
let program_string = include_str!("multiple_returns_main.leo"); let program_string = include_str!("multiple_returns_main.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_repeated_function_call() { fn test_repeated_function_call() {
let program_string = include_str!("repeated.leo"); let program_string = include_str!("repeated.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_return() { fn test_return() {
let program_string = include_str!("return.leo"); let program_string = include_str!("return.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_undefined() { fn test_undefined() {
let program_string = include_str!("undefined.leo"); let program_string = include_str!("undefined.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
#[test] #[test]
fn test_value_unchanged() { fn test_value_unchanged() {
let program_string = include_str!("value_unchanged.leo"); let program_string = include_str!("value_unchanged.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_array_input() { fn test_array_input() {
let program_string = include_str!("array_input.leo"); let program_string = include_str!("array_input.leo");
load_asg(program_string).err().unwrap(); load_asg(&new_context(), program_string).err().unwrap();
} }
// Test return multidimensional arrays // Test return multidimensional arrays
@ -147,13 +149,13 @@ fn test_array_input() {
#[test] #[test]
fn test_return_array_nested_pass() { fn test_return_array_nested_pass() {
let program_string = include_str!("return_array_nested_pass.leo"); let program_string = include_str!("return_array_nested_pass.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_return_array_tuple_pass() { fn test_return_array_tuple_pass() {
let program_string = include_str!("return_array_tuple_pass.leo"); let program_string = include_str!("return_array_tuple_pass.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Test return tuples // Test return tuples
@ -161,11 +163,11 @@ fn test_return_array_tuple_pass() {
#[test] #[test]
fn test_return_tuple() { fn test_return_tuple() {
let program_string = include_str!("return_tuple.leo"); let program_string = include_str!("return_tuple.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_return_tuple_conditional() { fn test_return_tuple_conditional() {
let program_string = include_str!("return_tuple_conditional.leo"); let program_string = include_str!("return_tuple_conditional.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,12 +14,14 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_one() { fn test_one() {
let program_string = include_str!("one.leo"); let program_string = include_str!("one.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
@ -29,79 +31,79 @@ fn test_implicit() {
let element: group = 0; let element: group = 0;
} }
"#; "#;
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_zero() { fn test_zero() {
let program_string = include_str!("zero.leo"); let program_string = include_str!("zero.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_point() { fn test_point() {
let program_string = include_str!("point.leo"); let program_string = include_str!("point.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_x_sign_high() { fn test_x_sign_high() {
let program_string = include_str!("x_sign_high.leo"); let program_string = include_str!("x_sign_high.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_x_sign_low() { fn test_x_sign_low() {
let program_string = include_str!("x_sign_low.leo"); let program_string = include_str!("x_sign_low.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_x_sign_inferred() { fn test_x_sign_inferred() {
let program_string = include_str!("x_sign_inferred.leo"); let program_string = include_str!("x_sign_inferred.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_y_sign_high() { fn test_y_sign_high() {
let program_string = include_str!("y_sign_high.leo"); let program_string = include_str!("y_sign_high.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_y_sign_low() { fn test_y_sign_low() {
let program_string = include_str!("y_sign_low.leo"); let program_string = include_str!("y_sign_low.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_y_sign_inferred() { fn test_y_sign_inferred() {
let program_string = include_str!("y_sign_inferred.leo"); let program_string = include_str!("y_sign_inferred.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_point_input() { fn test_point_input() {
let program_string = include_str!("point_input.leo"); let program_string = include_str!("point_input.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input() { fn test_input() {
let program_string = include_str!("input.leo"); let program_string = include_str!("input.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_negate() { fn test_negate() {
let program_string = include_str!("negate.leo"); let program_string = include_str!("negate.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_add() { fn test_add() {
let program_string = include_str!("add.leo"); let program_string = include_str!("add.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
@ -111,29 +113,29 @@ fn test_add_explicit() {
let c: group = 0group + 1group; let c: group = 0group + 1group;
} }
"#; "#;
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_sub() { fn test_sub() {
let program_string = include_str!("sub.leo"); let program_string = include_str!("sub.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_console_assert_pass() { fn test_console_assert_pass() {
let program_string = include_str!("assert_eq.leo"); let program_string = include_str!("assert_eq.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_eq() { fn test_eq() {
let program_string = include_str!("eq.leo"); let program_string = include_str!("eq.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_ternary() { fn test_ternary() {
let program_string = include_str!("ternary.leo"); let program_string = include_str!("ternary.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,134 +14,144 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::{load_asg, load_asg_imports, mocked_resolver}; use crate::{load_asg, load_asg_imports, mocked_resolver};
#[test] #[test]
fn test_basic() { fn test_basic() {
let mut imports = mocked_resolver(); let ctx = new_context();
let mut imports = mocked_resolver(&ctx);
imports.packages.insert( imports.packages.insert(
"test-import".to_string(), "test-import".to_string(),
load_asg(include_str!("src/test-import.leo")).unwrap(), load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
); );
let program_string = include_str!("basic.leo"); let program_string = include_str!("basic.leo");
load_asg_imports(program_string, &mut imports).unwrap(); load_asg_imports(&ctx, program_string, &mut imports).unwrap();
} }
#[test] #[test]
fn test_multiple() { fn test_multiple() {
let mut imports = mocked_resolver(); let ctx = new_context();
let mut imports = mocked_resolver(&ctx);
imports.packages.insert( imports.packages.insert(
"test-import".to_string(), "test-import".to_string(),
load_asg(include_str!("src/test-import.leo")).unwrap(), load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
); );
let program_string = include_str!("multiple.leo"); let program_string = include_str!("multiple.leo");
load_asg_imports(program_string, &mut imports).unwrap(); load_asg_imports(&ctx, program_string, &mut imports).unwrap();
} }
#[test] #[test]
fn test_star() { fn test_star() {
let mut imports = mocked_resolver(); let ctx = new_context();
let mut imports = mocked_resolver(&ctx);
imports.packages.insert( imports.packages.insert(
"test-import".to_string(), "test-import".to_string(),
load_asg(include_str!("src/test-import.leo")).unwrap(), load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
); );
let program_string = include_str!("star.leo"); let program_string = include_str!("star.leo");
load_asg_imports(program_string, &mut imports).unwrap(); load_asg_imports(&ctx, program_string, &mut imports).unwrap();
} }
#[test] #[test]
fn test_alias() { fn test_alias() {
let mut imports = mocked_resolver(); let ctx = new_context();
let mut imports = mocked_resolver(&ctx);
imports.packages.insert( imports.packages.insert(
"test-import".to_string(), "test-import".to_string(),
load_asg(include_str!("src/test-import.leo")).unwrap(), load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
); );
let program_string = include_str!("alias.leo"); let program_string = include_str!("alias.leo");
load_asg_imports(program_string, &mut imports).unwrap(); load_asg_imports(&ctx, program_string, &mut imports).unwrap();
} }
// naming tests // naming tests
#[test] #[test]
fn test_name() { fn test_name() {
let mut imports = mocked_resolver(); let ctx = new_context();
let mut imports = mocked_resolver(&ctx);
imports.packages.insert( imports.packages.insert(
"hello-world".to_string(), "hello-world".to_string(),
load_asg(include_str!("src/hello-world.leo")).unwrap(), load_asg(&ctx, include_str!("src/hello-world.leo")).unwrap(),
);
imports.packages.insert(
"a0-f".to_string(),
load_asg(&ctx, include_str!("src/a0-f.leo")).unwrap(),
); );
imports imports
.packages .packages
.insert("a0-f".to_string(), load_asg(include_str!("src/a0-f.leo")).unwrap()); .insert("a-9".to_string(), load_asg(&ctx, include_str!("src/a-9.leo")).unwrap());
imports
.packages
.insert("a-9".to_string(), load_asg(include_str!("src/a-9.leo")).unwrap());
let program_string = include_str!("names.leo"); let program_string = include_str!("names.leo");
load_asg_imports(program_string, &mut imports).unwrap(); load_asg_imports(&ctx, program_string, &mut imports).unwrap();
} }
// more complex tests // more complex tests
#[test] #[test]
fn test_many_import() { fn test_many_import() {
let mut imports = mocked_resolver(); let ctx = new_context();
let mut imports = mocked_resolver(&ctx);
imports.packages.insert( imports.packages.insert(
"test-import".to_string(), "test-import".to_string(),
load_asg(include_str!("src/test-import.leo")).unwrap(), load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"bar".to_string(), "bar".to_string(),
load_asg(include_str!("imports/bar/src/lib.leo")).unwrap(), load_asg(&ctx, include_str!("imports/bar/src/lib.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"bar.baz".to_string(), "bar.baz".to_string(),
load_asg(include_str!("imports/bar/src/baz.leo")).unwrap(), load_asg(&ctx, include_str!("imports/bar/src/baz.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"bar.baz".to_string(), "bar.baz".to_string(),
load_asg(include_str!("imports/bar/src/baz.leo")).unwrap(), load_asg(&ctx, include_str!("imports/bar/src/baz.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"bar.bat.bat".to_string(), "bar.bat.bat".to_string(),
load_asg(include_str!("imports/bar/src/bat/bat.leo")).unwrap(), load_asg(&ctx, include_str!("imports/bar/src/bat/bat.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"car".to_string(), "car".to_string(),
load_asg(include_str!("imports/car/src/lib.leo")).unwrap(), load_asg(&ctx, include_str!("imports/car/src/lib.leo")).unwrap(),
); );
let program_string = include_str!("many_import.leo"); let program_string = include_str!("many_import.leo");
load_asg_imports(program_string, &mut imports).unwrap(); load_asg_imports(&ctx, program_string, &mut imports).unwrap();
} }
#[test] #[test]
fn test_many_import_star() { fn test_many_import_star() {
let mut imports = mocked_resolver(); let ctx = new_context();
let mut imports = mocked_resolver(&ctx);
imports.packages.insert( imports.packages.insert(
"test-import".to_string(), "test-import".to_string(),
load_asg(include_str!("src/test-import.leo")).unwrap(), load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"bar".to_string(), "bar".to_string(),
load_asg(include_str!("imports/bar/src/lib.leo")).unwrap(), load_asg(&ctx, include_str!("imports/bar/src/lib.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"bar.baz".to_string(), "bar.baz".to_string(),
load_asg(include_str!("imports/bar/src/baz.leo")).unwrap(), load_asg(&ctx, include_str!("imports/bar/src/baz.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"bar.baz".to_string(), "bar.baz".to_string(),
load_asg(include_str!("imports/bar/src/baz.leo")).unwrap(), load_asg(&ctx, include_str!("imports/bar/src/baz.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"bar.bat.bat".to_string(), "bar.bat.bat".to_string(),
load_asg(include_str!("imports/bar/src/bat/bat.leo")).unwrap(), load_asg(&ctx, include_str!("imports/bar/src/bat/bat.leo")).unwrap(),
); );
imports.packages.insert( imports.packages.insert(
"car".to_string(), "car".to_string(),
load_asg(include_str!("imports/car/src/lib.leo")).unwrap(), load_asg(&ctx, include_str!("imports/car/src/lib.leo")).unwrap(),
); );
let program_string = include_str!("many_import_star.leo"); let program_string = include_str!("many_import_star.leo");
load_asg_imports(program_string, &mut imports).unwrap(); load_asg_imports(&ctx, program_string, &mut imports).unwrap();
} }

View File

@ -14,16 +14,18 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_input_pass() { fn test_input_pass() {
let program_string = include_str!("main.leo"); let program_string = include_str!("main.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_input_multiple() { fn test_input_multiple() {
let program_string = include_str!("main_multiple.leo"); let program_string = include_str!("main_multiple.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,10 +14,12 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_access() { fn test_access() {
let program_string = include_str!("access.leo"); let program_string = include_str!("access.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,16 +14,18 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_access_state() { fn test_access_state() {
let program_string = include_str!("access_state.leo"); let program_string = include_str!("access_state.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_access_all() { fn test_access_all() {
let program_string = include_str!("access_all.leo"); let program_string = include_str!("access_all.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -16,94 +16,96 @@
macro_rules! test_int { macro_rules! test_int {
($name: ident) => { ($name: ident) => {
use leo_asg::new_context;
pub struct $name {} pub struct $name {}
impl $name { impl $name {
fn test_negate() { fn test_negate() {
let program_string = include_str!("negate.leo"); let program_string = include_str!("negate.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_negate_zero() { fn test_negate_zero() {
let program_string = include_str!("negate_zero.leo"); let program_string = include_str!("negate_zero.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
} }
impl super::IntegerTester for $name { impl super::IntegerTester for $name {
fn test_min() { fn test_min() {
let program_string = include_str!("min.leo"); let program_string = include_str!("min.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_max() { fn test_max() {
let program_string = include_str!("max.leo"); let program_string = include_str!("max.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_add() { fn test_add() {
let program_string = include_str!("add.leo"); let program_string = include_str!("add.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_sub() { fn test_sub() {
let program_string = include_str!("sub.leo"); let program_string = include_str!("sub.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_mul() { fn test_mul() {
let program_string = include_str!("mul.leo"); let program_string = include_str!("mul.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_div() { fn test_div() {
let program_string = include_str!("div.leo"); let program_string = include_str!("div.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_pow() { fn test_pow() {
let program_string = include_str!("pow.leo"); let program_string = include_str!("pow.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_eq() { fn test_eq() {
let program_string = include_str!("eq.leo"); let program_string = include_str!("eq.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_ne() { fn test_ne() {
let program_string = include_str!("ne.leo"); let program_string = include_str!("ne.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_ge() { fn test_ge() {
let program_string = include_str!("ge.leo"); let program_string = include_str!("ge.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_gt() { fn test_gt() {
let program_string = include_str!("gt.leo"); let program_string = include_str!("gt.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_le() { fn test_le() {
let program_string = include_str!("le.leo"); let program_string = include_str!("le.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_lt() { fn test_lt() {
let program_string = include_str!("lt.leo"); let program_string = include_str!("lt.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_console_assert() { fn test_console_assert() {
let program_string = include_str!("console_assert.leo"); let program_string = include_str!("console_assert.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_ternary() { fn test_ternary() {
let program_string = include_str!("ternary.leo"); let program_string = include_str!("ternary.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
} }
}; };

View File

@ -16,82 +16,84 @@
macro_rules! test_uint { macro_rules! test_uint {
($name: ident) => { ($name: ident) => {
use leo_asg::new_context;
pub struct $name {} pub struct $name {}
impl super::IntegerTester for $name { impl super::IntegerTester for $name {
fn test_min() { fn test_min() {
let program_string = include_str!("min.leo"); let program_string = include_str!("min.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_max() { fn test_max() {
let program_string = include_str!("max.leo"); let program_string = include_str!("max.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_add() { fn test_add() {
let program_string = include_str!("add.leo"); let program_string = include_str!("add.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_sub() { fn test_sub() {
let program_string = include_str!("sub.leo"); let program_string = include_str!("sub.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_mul() { fn test_mul() {
let program_string = include_str!("mul.leo"); let program_string = include_str!("mul.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_div() { fn test_div() {
let program_string = include_str!("div.leo"); let program_string = include_str!("div.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_pow() { fn test_pow() {
let program_string = include_str!("pow.leo"); let program_string = include_str!("pow.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_eq() { fn test_eq() {
let program_string = include_str!("eq.leo"); let program_string = include_str!("eq.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_ne() { fn test_ne() {
let program_string = include_str!("ne.leo"); let program_string = include_str!("ne.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_ge() { fn test_ge() {
let program_string = include_str!("ge.leo"); let program_string = include_str!("ge.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_gt() { fn test_gt() {
let program_string = include_str!("gt.leo"); let program_string = include_str!("gt.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_le() { fn test_le() {
let program_string = include_str!("le.leo"); let program_string = include_str!("le.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_lt() { fn test_lt() {
let program_string = include_str!("lt.leo"); let program_string = include_str!("lt.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_console_assert() { fn test_console_assert() {
let program_string = include_str!("console_assert.leo"); let program_string = include_str!("console_assert.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
fn test_ternary() { fn test_ternary() {
let program_string = include_str!("ternary.leo"); let program_string = include_str!("ternary.leo");
crate::load_asg(program_string).unwrap(); crate::load_asg(&new_context(), program_string).unwrap();
} }
} }
}; };

View File

@ -14,58 +14,60 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_let_mut() { fn test_let_mut() {
let program_string = include_str!("let_mut.leo"); let program_string = include_str!("let_mut.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_let_mut_nested() { fn test_let_mut_nested() {
let program_string = include_str!("let_mut_nested.leo"); let program_string = include_str!("let_mut_nested.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_array_mut() { fn test_array_mut() {
let program_string = include_str!("array_mut.leo"); let program_string = include_str!("array_mut.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_array_tuple_mut() { fn test_array_tuple_mut() {
let program_string = include_str!("array_tuple_mut.leo"); let program_string = include_str!("array_tuple_mut.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_array_splice_mut() { fn test_array_splice_mut() {
let program_string = include_str!("array_splice_mut.leo"); let program_string = include_str!("array_splice_mut.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_circuit_mut() { fn test_circuit_mut() {
let program_string = include_str!("circuit_mut.leo"); let program_string = include_str!("circuit_mut.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_circuit_variable_mut() { fn test_circuit_variable_mut() {
let program_string = include_str!("circuit_variable_mut.leo"); let program_string = include_str!("circuit_variable_mut.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_function_input_mut() { fn test_function_input_mut() {
let program_string = include_str!("function_input_mut.leo"); let program_string = include_str!("function_input_mut.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_swap() { fn test_swap() {
let program_string = include_str!("swap.leo"); let program_string = include_str!("swap.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,40 +14,42 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_assert() { fn test_assert() {
let program_string = include_str!("assert.leo"); let program_string = include_str!("assert.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_mutate() { fn test_mutate() {
let program_string = include_str!("mutate.leo"); let program_string = include_str!("mutate.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_for_loop() { fn test_for_loop() {
let program_string = include_str!("for_loop.leo"); let program_string = include_str!("for_loop.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_chain() { fn test_chain() {
let program_string = include_str!("chain.leo"); let program_string = include_str!("chain.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_nested() { fn test_nested() {
let program_string = include_str!("nested.leo"); let program_string = include_str!("nested.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_multiple_returns() { fn test_multiple_returns() {
let program_string = include_str!("multiple_returns.leo"); let program_string = include_str!("multiple_returns.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
pub mod conditional; pub mod conditional;
@ -23,7 +25,7 @@ pub mod conditional;
#[test] #[test]
fn test_ternary_basic() { fn test_ternary_basic() {
let program_string = include_str!("ternary_basic.leo"); let program_string = include_str!("ternary_basic.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
// Iteration for i {start}..{stop} { statements } // Iteration for i {start}..{stop} { statements }
@ -31,11 +33,11 @@ fn test_ternary_basic() {
#[test] #[test]
fn test_iteration_basic() { fn test_iteration_basic() {
let program_string = include_str!("iteration_basic.leo"); let program_string = include_str!("iteration_basic.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_block() { fn test_block() {
let program_string = include_str!("block.leo"); let program_string = include_str!("block.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -14,70 +14,72 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_asg::new_context;
use crate::load_asg; use crate::load_asg;
#[test] #[test]
fn test_tuple_basic() { fn test_tuple_basic() {
let program_string = include_str!("basic.leo"); let program_string = include_str!("basic.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_tuple_access() { fn test_tuple_access() {
let program_string = include_str!("access.leo"); let program_string = include_str!("access.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_tuple_typed() { fn test_tuple_typed() {
let program_string = include_str!("typed.leo"); let program_string = include_str!("typed.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_multiple() { fn test_multiple() {
let program_string = include_str!("multiple.leo"); let program_string = include_str!("multiple.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_multiple_typed() { fn test_multiple_typed() {
let program_string = include_str!("multiple_typed.leo"); let program_string = include_str!("multiple_typed.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_function() { fn test_function() {
let program_string = include_str!("function.leo"); let program_string = include_str!("function.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_function_typed() { fn test_function_typed() {
let program_string = include_str!("function_typed.leo"); let program_string = include_str!("function_typed.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_function_multiple() { fn test_function_multiple() {
let program_string = include_str!("function_multiple.leo"); let program_string = include_str!("function_multiple.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_nested() { fn test_nested() {
let program_string = include_str!("nested.leo"); let program_string = include_str!("nested.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_nested_access() { fn test_nested_access() {
let program_string = include_str!("nested_access.leo"); let program_string = include_str!("nested_access.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }
#[test] #[test]
fn test_nested_typed() { fn test_nested_typed() {
let program_string = include_str!("nested_typed.leo"); let program_string = include_str!("nested_typed.leo");
load_asg(program_string).unwrap(); load_asg(&new_context(), program_string).unwrap();
} }

View File

@ -44,24 +44,36 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
pub use leo_asg::{new_context, AsgContext as Context, AsgContext};
thread_local! {
static THREAD_GLOBAL_CONTEXT: AsgContext<'static> = Box::leak(Box::new(new_context()));
}
/// Conventience function to return a leaked thread-local global context. Should only be used for transient programs (like cli).
pub fn thread_leaked_context() -> AsgContext<'static> {
THREAD_GLOBAL_CONTEXT.with(|f| *f)
}
/// Stores information to compile a Leo program. /// Stores information to compile a Leo program.
#[derive(Clone)] #[derive(Clone)]
pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> { pub struct Compiler<'a, F: Field + PrimeField, G: GroupType<F>> {
program_name: String, program_name: String,
main_file_path: PathBuf, main_file_path: PathBuf,
output_directory: PathBuf, output_directory: PathBuf,
program: Program, program: Program,
program_input: Input, program_input: Input,
asg: Option<Asg>, ctx: AsgContext<'a>,
asg: Option<Asg<'a>>,
_engine: PhantomData<F>, _engine: PhantomData<F>,
_group: PhantomData<G>, _group: PhantomData<G>,
} }
impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
/// ///
/// Returns a new Leo program compiler. /// Returns a new Leo program compiler.
/// ///
pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf) -> Self { pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf, ctx: AsgContext<'a>) -> Self {
Self { Self {
program_name: package_name.clone(), program_name: package_name.clone(),
main_file_path, main_file_path,
@ -69,6 +81,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
program: Program::new(package_name), program: Program::new(package_name),
program_input: Input::new(), program_input: Input::new(),
asg: None, asg: None,
ctx,
_engine: PhantomData, _engine: PhantomData,
_group: PhantomData, _group: PhantomData,
} }
@ -85,8 +98,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
package_name: String, package_name: String,
main_file_path: PathBuf, main_file_path: PathBuf,
output_directory: PathBuf, output_directory: PathBuf,
ctx: AsgContext<'a>,
) -> Result<Self, CompilerError> { ) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name, main_file_path, output_directory); let mut compiler = Self::new(package_name, main_file_path, output_directory, ctx);
compiler.parse_program()?; compiler.parse_program()?;
@ -101,6 +115,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
/// Parses and stores all imported programs. /// Parses and stores all imported programs.
/// Performs type inference checking on the program, imported programs, and program input. /// Performs type inference checking on the program, imported programs, and program input.
/// ///
#[allow(clippy::too_many_arguments)]
pub fn parse_program_with_input( pub fn parse_program_with_input(
package_name: String, package_name: String,
main_file_path: PathBuf, main_file_path: PathBuf,
@ -109,8 +124,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
input_path: &Path, input_path: &Path,
state_string: &str, state_string: &str,
state_path: &Path, state_path: &Path,
ctx: AsgContext<'a>,
) -> Result<Self, CompilerError> { ) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name, main_file_path, output_directory); let mut compiler = Self::new(package_name, main_file_path, output_directory, ctx);
compiler.parse_input(input_string, input_path, state_string, state_path)?; compiler.parse_input(input_string, input_path, state_string, state_path)?;
@ -189,7 +205,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
tracing::debug!("Program parsing complete\n{:#?}", self.program); tracing::debug!("Program parsing complete\n{:#?}", self.program);
// Create a new symbol table from the program, imported_programs, and program_input. // Create a new symbol table from the program, imported_programs, and program_input.
let asg = Asg::new(&core_ast, &mut leo_imports::ImportParser::default())?; let asg = Asg::new(self.ctx, &core_ast, &mut leo_imports::ImportParser::default())?;
tracing::debug!("ASG generation complete"); tracing::debug!("ASG generation complete");
@ -261,7 +277,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
} }
} }
impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<'a, F, G> {
/// ///
/// Synthesizes the circuit with program input. /// Synthesizes the circuit with program input.
/// ///

View File

@ -24,19 +24,18 @@ use crate::{
GroupType, GroupType,
}; };
use leo_asg::{Expression, Span}; use leo_asg::{Expression, Span};
use std::sync::Arc;
use snarkvm_models::{ use snarkvm_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean}, gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
pub fn evaluate_console_assert<CS: ConstraintSystem<F>>( pub fn evaluate_console_assert<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
indicator: &Boolean, indicator: &Boolean,
expression: &Arc<Expression>, expression: &'a Expression<'a>,
span: &Span, span: &Span,
) -> Result<(), ConsoleError> { ) -> Result<(), ConsoleError> {
// Evaluate assert expression // Evaluate assert expression

View File

@ -24,16 +24,21 @@ use snarkvm_models::{
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean}, gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
pub fn evaluate_console_function_call<CS: ConstraintSystem<F>>( pub fn evaluate_console_function_call<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
indicator: &Boolean, indicator: &Boolean,
console: &ConsoleStatement, console: &ConsoleStatement<'a>,
) -> Result<(), ConsoleError> { ) -> Result<(), ConsoleError> {
match &console.function { match &console.function {
ConsoleFunction::Assert(expression) => { ConsoleFunction::Assert(expression) => {
self.evaluate_console_assert(cs, indicator, expression, &console.span.clone().unwrap_or_default())?; self.evaluate_console_assert(
cs,
indicator,
expression.get(),
&console.span.clone().unwrap_or_default(),
)?;
} }
ConsoleFunction::Debug(string) => { ConsoleFunction::Debug(string) => {
let string = self.format(cs, string)?; let string = self.format(cs, string)?;

View File

@ -24,11 +24,11 @@ use snarkvm_models::{
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
pub fn format<CS: ConstraintSystem<F>>( pub fn format<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
formatted: &FormattedString, formatted: &FormattedString<'a>,
) -> Result<String, ConsoleError> { ) -> Result<String, ConsoleError> {
// Check that containers and parameters match // Check that containers and parameters match
if formatted.containers.len() != formatted.parameters.len() { if formatted.containers.len() != formatted.parameters.len() {
@ -50,7 +50,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let mut result = string.to_string(); let mut result = string.to_string();
for parameter in formatted.parameters.iter() { for parameter in formatted.parameters.iter() {
let parameter_value = self.enforce_expression(cs, parameter)?; let parameter_value = self.enforce_expression(cs, parameter.get())?;
result = result.replacen("{}", &parameter_value.to_string(), 1); result = result.replacen("{}", &parameter_value.to_string(), 1);
} }

View File

@ -28,16 +28,16 @@ use snarkvm_models::{
}; };
use std::path::Path; use std::path::Path;
pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>( pub fn generate_constraints<'a, F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS, cs: &mut CS,
asg: &Asg, asg: &Asg<'a>,
input: &Input, input: &Input,
) -> Result<OutputBytes, CompilerError> { ) -> Result<OutputBytes, CompilerError> {
let program = asg.as_repr(); let program = asg.as_repr();
let mut resolved_program = ConstrainedProgram::<F, G>::new(program.clone()); let mut resolved_program = ConstrainedProgram::<F, G>::new(program.clone());
let main = { let main = {
let program = program.borrow(); let program = program;
program.functions.get("main").cloned() program.functions.get("main").cloned()
}; };
@ -50,20 +50,19 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
} }
} }
pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>( pub fn generate_test_constraints<'a, F: Field + PrimeField, G: GroupType<F>>(
asg: &Asg, asg: &Asg<'a>,
input: InputPairs, input: InputPairs,
main_file_path: &Path, main_file_path: &Path,
output_directory: &Path, output_directory: &Path,
) -> Result<(u32, u32), CompilerError> { ) -> Result<(u32, u32), CompilerError> {
let program = asg.as_repr(); let program = asg.as_repr();
let mut resolved_program = ConstrainedProgram::<F, G>::new(program.clone()); let mut resolved_program = ConstrainedProgram::<F, G>::new(program.clone());
let program_name = program.borrow().name.clone(); let program_name = program.name.clone();
// Get default input // Get default input
let default = input.pairs.get(&program_name); let default = input.pairs.get(&program_name);
let program = program.borrow();
let tests = &program.test_functions; let tests = &program.test_functions;
tracing::info!("Running {} tests", tests.len()); tracing::info!("Running {} tests", tests.len());

View File

@ -21,8 +21,8 @@ use leo_asg::Variable;
use snarkvm_models::curves::{Field, PrimeField}; use snarkvm_models::curves::{Field, PrimeField};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
pub fn store_definition(&mut self, variable: &Variable, value: ConstrainedValue<F, G>) { pub fn store_definition(&mut self, variable: &Variable, value: ConstrainedValue<'a, F, G>) {
let variable = variable.borrow(); let variable = variable.borrow();
self.store(variable.id, value); self.store(variable.id, value);

View File

@ -24,12 +24,12 @@ use snarkvm_models::{
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
pub fn enforce_add<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>( pub fn enforce_add<'a, F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS, cs: &mut CS,
left: ConstrainedValue<F, G>, left: ConstrainedValue<'a, F, G>,
right: ConstrainedValue<F, G>, right: ConstrainedValue<'a, F, G>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
match (left, right) { match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => { (ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.add(cs, num_2, span)?)) Ok(ConstrainedValue::Integer(num_1.add(cs, num_2, span)?))

View File

@ -24,12 +24,12 @@ use snarkvm_models::{
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
pub fn enforce_div<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>( pub fn enforce_div<'a, F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS, cs: &mut CS,
left: ConstrainedValue<F, G>, left: ConstrainedValue<'a, F, G>,
right: ConstrainedValue<F, G>, right: ConstrainedValue<'a, F, G>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
match (left, right) { match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => { (ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.div(cs, num_2, span)?)) Ok(ConstrainedValue::Integer(num_1.div(cs, num_2, span)?))

View File

@ -24,12 +24,12 @@ use snarkvm_models::{
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
pub fn enforce_mul<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>( pub fn enforce_mul<'a, F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS, cs: &mut CS,
left: ConstrainedValue<F, G>, left: ConstrainedValue<'a, F, G>,
right: ConstrainedValue<F, G>, right: ConstrainedValue<'a, F, G>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
match (left, right) { match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => { (ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.mul(cs, num_2, span)?)) Ok(ConstrainedValue::Integer(num_1.mul(cs, num_2, span)?))

View File

@ -24,11 +24,11 @@ use snarkvm_models::{
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
pub fn enforce_negate<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>( pub fn enforce_negate<'a, F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS, cs: &mut CS,
value: ConstrainedValue<F, G>, value: ConstrainedValue<'a, F, G>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
match value { match value {
ConstrainedValue::Integer(integer) => Ok(ConstrainedValue::Integer(integer.negate(cs, span)?)), ConstrainedValue::Integer(integer) => Ok(ConstrainedValue::Integer(integer.negate(cs, span)?)),
ConstrainedValue::Field(field) => Ok(ConstrainedValue::Field(field.negate(cs, span)?)), ConstrainedValue::Field(field) => Ok(ConstrainedValue::Field(field.negate(cs, span)?)),

View File

@ -24,12 +24,12 @@ use snarkvm_models::{
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
pub fn enforce_pow<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>( pub fn enforce_pow<'a, F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS, cs: &mut CS,
left: ConstrainedValue<F, G>, left: ConstrainedValue<'a, F, G>,
right: ConstrainedValue<F, G>, right: ConstrainedValue<'a, F, G>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
match (left, right) { match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => { (ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.pow(cs, num_2, span)?)) Ok(ConstrainedValue::Integer(num_1.pow(cs, num_2, span)?))

View File

@ -24,12 +24,12 @@ use snarkvm_models::{
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
pub fn enforce_sub<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>( pub fn enforce_sub<'a, F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS, cs: &mut CS,
left: ConstrainedValue<F, G>, left: ConstrainedValue<'a, F, G>,
right: ConstrainedValue<F, G>, right: ConstrainedValue<'a, F, G>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
match (left, right) { match (left, right) {
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => { (ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
Ok(ConstrainedValue::Integer(num_1.sub(cs, num_2, span)?)) Ok(ConstrainedValue::Integer(num_1.sub(cs, num_2, span)?))

View File

@ -18,22 +18,21 @@
use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_asg::{Expression, Span}; use leo_asg::{Expression, Span};
use std::sync::Arc;
use snarkvm_models::{ use snarkvm_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn enforce_array_access<CS: ConstraintSystem<F>>( pub fn enforce_array_access<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
array: &Arc<Expression>, array: &'a Expression<'a>,
index: &Arc<Expression>, index: &'a Expression<'a>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
let array = match self.enforce_expression(cs, array)? { let array = match self.enforce_expression(cs, array)? {
ConstrainedValue::Array(array) => array, ConstrainedValue::Array(array) => array,
value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())), value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())),
@ -47,21 +46,21 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn enforce_array_range_access<CS: ConstraintSystem<F>>( pub fn enforce_array_range_access<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
array: &Arc<Expression>, array: &'a Expression<'a>,
left: Option<&Arc<Expression>>, left: Option<&'a Expression<'a>>,
right: Option<&Arc<Expression>>, right: Option<&'a Expression<'a>>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
let array = match self.enforce_expression(cs, array)? { let array = match self.enforce_expression(cs, array)? {
ConstrainedValue::Array(array) => array, ConstrainedValue::Array(array) => array,
value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())), value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())),
}; };
let from_resolved = match left.as_deref() { let from_resolved = match left {
Some(from_index) => self.enforce_index(cs, from_index, span)?, Some(from_index) => self.enforce_index(cs, from_index, span)?,
None => 0usize, // Array slice starts at index 0 None => 0usize, // Array slice starts at index 0
}; };
let to_resolved = match right.as_deref() { let to_resolved = match right {
Some(to_index) => self.enforce_index(cs, to_index, span)?, Some(to_index) => self.enforce_index(cs, to_index, span)?,
None => array.len(), // Array slice ends at array length None => array.len(), // Array slice ends at array length
}; };

View File

@ -16,28 +16,29 @@
//! Enforces an array expression in a compiled Leo program. //! Enforces an array expression in a compiled Leo program.
use std::cell::Cell;
use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_asg::{Expression, Span}; use leo_asg::{Expression, Span};
use std::sync::Arc;
use snarkvm_models::{ use snarkvm_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
/// Enforce array expressions /// Enforce array expressions
pub fn enforce_array<CS: ConstraintSystem<F>>( pub fn enforce_array<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
array: &[(Arc<Expression>, bool)], array: &[(Cell<&'a Expression<'a>>, bool)],
span: Span, span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
let expected_dimension = None; let expected_dimension = None;
let mut result = vec![]; let mut result = vec![];
for (element, is_spread) in array.iter() { for (element, is_spread) in array.iter() {
let element_value = self.enforce_expression(cs, element)?; let element_value = self.enforce_expression(cs, element.get())?;
if *is_spread { if *is_spread {
match element_value { match element_value {
ConstrainedValue::Array(array) => result.extend(array), ConstrainedValue::Array(array) => result.extend(array),
@ -66,9 +67,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn enforce_array_initializer<CS: ConstraintSystem<F>>( pub fn enforce_array_initializer<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
element_expression: &Arc<Expression>, element_expression: &'a Expression<'a>,
actual_size: usize, actual_size: usize,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
let mut value = self.enforce_expression(cs, element_expression)?; let mut value = self.enforce_expression(cs, element_expression)?;
// Allocate the array. // Allocate the array.

View File

@ -18,18 +18,17 @@
use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_asg::{Expression, Span}; use leo_asg::{Expression, Span};
use std::sync::Arc;
use snarkvm_models::{ use snarkvm_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
pub(crate) fn enforce_index<CS: ConstraintSystem<F>>( pub(crate) fn enforce_index<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
index: &Arc<Expression>, index: &'a Expression<'a>,
span: &Span, span: &Span,
) -> Result<usize, ExpressionError> { ) -> Result<usize, ExpressionError> {
match self.enforce_expression(cs, index)? { match self.enforce_expression(cs, index)? {

View File

@ -18,23 +18,22 @@
use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_asg::Expression; use leo_asg::Expression;
use std::sync::Arc;
use snarkvm_models::{ use snarkvm_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
type ConstrainedValuePair<T, U> = (ConstrainedValue<T, U>, ConstrainedValue<T, U>); type ConstrainedValuePair<'a, T, U> = (ConstrainedValue<'a, T, U>, ConstrainedValue<'a, T, U>);
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn enforce_binary_expression<CS: ConstraintSystem<F>>( pub fn enforce_binary_expression<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
left: &Arc<Expression>, left: &'a Expression<'a>,
right: &Arc<Expression>, right: &'a Expression<'a>,
) -> Result<ConstrainedValuePair<F, G>, ExpressionError> { ) -> Result<ConstrainedValuePair<'a, F, G>, ExpressionError> {
let resolved_left = self.enforce_expression(cs, left)?; let resolved_left = self.enforce_expression(cs, left)?;
let resolved_right = self.enforce_expression(cs, right)?; let resolved_right = self.enforce_expression(cs, right)?;

View File

@ -24,24 +24,24 @@ use snarkvm_models::{
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn enforce_circuit_access<CS: ConstraintSystem<F>>( pub fn enforce_circuit_access<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
expr: &CircuitAccessExpression, expr: &CircuitAccessExpression<'a>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
if let Some(target) = &expr.target { if let Some(target) = expr.target.get() {
//todo: we can prob pass values by ref here to avoid copying the entire circuit on access //todo: we can prob pass values by ref here to avoid copying the entire circuit on access
let target_value = self.enforce_expression(cs, target)?; let target_value = self.enforce_expression(cs, target)?;
match target_value { match target_value {
ConstrainedValue::CircuitExpression(def, members) => { ConstrainedValue::CircuitExpression(def, members) => {
assert!(def.circuit == expr.circuit); assert!(def == expr.circuit.get());
if let Some(member) = members.into_iter().find(|x| x.0.name == expr.member.name) { if let Some(member) = members.into_iter().find(|x| x.0.name == expr.member.name) {
Ok(member.1) Ok(member.1)
} else { } else {
Err(ExpressionError::undefined_member_access( Err(ExpressionError::undefined_member_access(
expr.circuit.name.borrow().to_string(), expr.circuit.get().name.borrow().to_string(),
expr.member.to_string(), expr.member.to_string(),
expr.member.span.clone(), expr.member.span.clone(),
)) ))

View File

@ -22,26 +22,21 @@ use crate::{
value::{ConstrainedCircuitMember, ConstrainedValue}, value::{ConstrainedCircuitMember, ConstrainedValue},
GroupType, GroupType,
}; };
use leo_asg::{CircuitInitExpression, CircuitMemberBody, Span}; use leo_asg::{CircuitInitExpression, CircuitMember, Span};
use snarkvm_models::{ use snarkvm_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem, gadgets::r1cs::ConstraintSystem,
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
pub fn enforce_circuit<CS: ConstraintSystem<F>>( pub fn enforce_circuit<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
expr: &CircuitInitExpression, expr: &CircuitInitExpression<'a>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
let circuit = expr let circuit = expr.circuit.get();
.circuit
.body
.borrow()
.upgrade()
.expect("circuit init stale circuit ref");
let members = circuit.members.borrow(); let members = circuit.members.borrow();
let mut resolved_members = Vec::with_capacity(members.len()); let mut resolved_members = Vec::with_capacity(members.len());
@ -52,15 +47,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
.get(&name.name) .get(&name.name)
.expect("illegal name in asg circuit init expression"); .expect("illegal name in asg circuit init expression");
match target { match target {
CircuitMemberBody::Variable(_type_) => { CircuitMember::Variable(_type_) => {
let variable_value = self.enforce_expression(cs, inner)?; let variable_value = self.enforce_expression(cs, inner.get())?;
resolved_members.push(ConstrainedCircuitMember(name.clone(), variable_value)); resolved_members.push(ConstrainedCircuitMember(name.clone(), variable_value));
} }
_ => return Err(ExpressionError::expected_circuit_member(name.to_string(), span.clone())), _ => return Err(ExpressionError::expected_circuit_member(name.to_string(), span.clone())),
} }
} }
let value = ConstrainedValue::CircuitExpression(circuit.clone(), resolved_members); let value = ConstrainedValue::CircuitExpression(circuit, resolved_members);
Ok(value) Ok(value)
} }
} }

View File

@ -18,24 +18,23 @@
use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_asg::{Expression, Span}; use leo_asg::{Expression, Span};
use std::sync::Arc;
use snarkvm_models::{ use snarkvm_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::{r1cs::ConstraintSystem, utilities::select::CondSelectGadget}, gadgets::{r1cs::ConstraintSystem, utilities::select::CondSelectGadget},
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
/// Enforce ternary conditional expression /// Enforce ternary conditional expression
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn enforce_conditional_expression<CS: ConstraintSystem<F>>( pub fn enforce_conditional_expression<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
conditional: &Arc<Expression>, conditional: &'a Expression<'a>,
first: &Arc<Expression>, first: &'a Expression<'a>,
second: &Arc<Expression>, second: &'a Expression<'a>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
let conditional_value = match self.enforce_expression(cs, conditional)? { let conditional_value = match self.enforce_expression(cs, conditional)? {
ConstrainedValue::Boolean(resolved) => resolved, ConstrainedValue::Boolean(resolved) => resolved,
value => return Err(ExpressionError::conditional_boolean(value.to_string(), span.to_owned())), value => return Err(ExpressionError::conditional_boolean(value.to_string(), span.to_owned())),

View File

@ -28,21 +28,20 @@ use crate::{
GroupType, GroupType,
}; };
use leo_asg::{expression::*, ConstValue, Expression, Node}; use leo_asg::{expression::*, ConstValue, Expression, Node};
use std::sync::Arc;
use snarkvm_models::{ use snarkvm_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean}, gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
}; };
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<'a, F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
pub(crate) fn enforce_expression<CS: ConstraintSystem<F>>( pub(crate) fn enforce_expression<CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
expression: &Arc<Expression>, expression: &'a Expression<'a>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<'a, F, G>, ExpressionError> {
let span = expression.span().cloned().unwrap_or_default(); let span = expression.span().cloned().unwrap_or_default();
match &**expression { match expression {
// Variables // Variables
Expression::VariableRef(variable_ref) => self.evaluate_ref(variable_ref), Expression::VariableRef(variable_ref) => self.evaluate_ref(variable_ref),
@ -62,7 +61,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Binary(BinaryExpression { Expression::Binary(BinaryExpression {
left, right, operation, .. left, right, operation, ..
}) => { }) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(cs, left, right)?; let (resolved_left, resolved_right) = self.enforce_binary_expression(cs, left.get(), right.get())?;
match operation { match operation {
BinaryOperation::Add => enforce_add(cs, resolved_left, resolved_right, &span), BinaryOperation::Add => enforce_add(cs, resolved_left, resolved_right, &span),
@ -89,10 +88,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Unary operations // Unary operations
Expression::Unary(UnaryExpression { inner, operation, .. }) => match operation { Expression::Unary(UnaryExpression { inner, operation, .. }) => match operation {
UnaryOperation::Negate => { UnaryOperation::Negate => {
let resolved_inner = self.enforce_expression(cs, inner)?; let resolved_inner = self.enforce_expression(cs, inner.get())?;
enforce_negate(cs, resolved_inner, &span) enforce_negate(cs, resolved_inner, &span)
} }
UnaryOperation::Not => Ok(evaluate_not(self.enforce_expression(cs, inner)?, &span)?), UnaryOperation::Not => Ok(evaluate_not(self.enforce_expression(cs, inner.get())?, &span)?),
}, },
Expression::Ternary(TernaryExpression { Expression::Ternary(TernaryExpression {
@ -100,24 +99,26 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
if_true, if_true,
if_false, if_false,
.. ..
}) => self.enforce_conditional_expression(cs, condition, if_true, if_false, &span), }) => self.enforce_conditional_expression(cs, condition.get(), if_true.get(), if_false.get(), &span),
// Arrays // Arrays
Expression::ArrayInline(ArrayInlineExpression { elements, .. }) => self.enforce_array(cs, elements, span), Expression::ArrayInline(ArrayInlineExpression { elements, .. }) => {
self.enforce_array(cs, &elements[..], span)
}
Expression::ArrayInit(ArrayInitExpression { element, len, .. }) => { Expression::ArrayInit(ArrayInitExpression { element, len, .. }) => {
self.enforce_array_initializer(cs, element, *len) self.enforce_array_initializer(cs, element.get(), *len)
} }
Expression::ArrayAccess(ArrayAccessExpression { array, index, .. }) => { Expression::ArrayAccess(ArrayAccessExpression { array, index, .. }) => {
self.enforce_array_access(cs, array, index, &span) self.enforce_array_access(cs, array.get(), index.get(), &span)
} }
Expression::ArrayRangeAccess(ArrayRangeAccessExpression { array, left, right, .. }) => { Expression::ArrayRangeAccess(ArrayRangeAccessExpression { array, left, right, .. }) => {
self.enforce_array_range_access(cs, array, left.as_ref(), right.as_ref(), &span) self.enforce_array_range_access(cs, array.get(), left.get(), right.get(), &span)
} }
// Tuples // Tuples
Expression::TupleInit(TupleInitExpression { elements, .. }) => self.enforce_tuple(cs, elements), Expression::TupleInit(TupleInitExpression { elements, .. }) => self.enforce_tuple(cs, &elements[..]),
Expression::TupleAccess(TupleAccessExpression { tuple_ref, index, .. }) => { Expression::TupleAccess(TupleAccessExpression { tuple_ref, index, .. }) => {
self.enforce_tuple_access(cs, tuple_ref, *index, &span) self.enforce_tuple_access(cs, tuple_ref.get(), *index, &span)
} }
// Circuits // Circuits
@ -131,26 +132,21 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
arguments, arguments,
.. ..
}) => { }) => {
if let Some(circuit) = function if let Some(circuit) = function.get().circuit.get() {
.circuit
.borrow()
.as_ref()
.map(|x| x.upgrade().expect("stale circuit for member function"))
{
let core_mapping = circuit.core_mapping.borrow(); let core_mapping = circuit.core_mapping.borrow();
if let Some(core_mapping) = core_mapping.as_deref() { if let Some(core_mapping) = core_mapping.as_deref() {
let core_circuit = resolve_core_circuit::<F, G>(core_mapping); let core_circuit = resolve_core_circuit::<F, G>(core_mapping);
return self.enforce_core_circuit_call_expression( return self.enforce_core_circuit_call_expression(
cs, cs,
&core_circuit, &core_circuit,
&function, function.get(),
target.as_ref(), target.get(),
arguments, &arguments[..],
&span, &span,
); );
} }
} }
self.enforce_function_call_expression(cs, &function, target.as_ref(), arguments, &span) self.enforce_function_call_expression(cs, function.get(), target.get(), &arguments[..], &span)
} }
} }
} }

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