Skip to content

Commit

Permalink
Merge #598 #620
Browse files Browse the repository at this point in the history
598: [Feature] 374 circuit self access r=collinc97 a=gluax

Feature resolves #374. At the grammar level the following syntax is no longer allowed on self:
```
self[0];
self();
```

Syntax that is allowed at the grammar level is:
```
console.log("b: {}", self::b);
console.log("hmm: {}",self::hmm());
self.hello();
console.log("access: {}", self.a);
```

Note that these changes are only at the grammar level only.

620: Feature/254 strengthen import rules r=collinc97 a=gluax

Grammar changes are a bit different than what was suggested in the original feature request #254. However, it should be logically equivalent and I think makes more sense on the rust side.

Closes #254 

Co-authored-by: gluaxspeed <jonathan.t.pavlik@gmail.com>
Co-authored-by: Howard Wu <9260812+howardwu@users.noreply.github.com>
  • Loading branch information
3 people committed Feb 11, 2021
3 parents 8d20b75 + 5fe61da + f02845a commit dee4f34
Show file tree
Hide file tree
Showing 30 changed files with 591 additions and 46 deletions.
38 changes: 26 additions & 12 deletions asg/src/program/mod.rs
Expand Up @@ -25,7 +25,7 @@ mod function;
pub use function::*;

use crate::{AsgConvertError, ImportResolver, InnerScope, Input, Scope};
use leo_ast::{Identifier, Package, PackageAccess, Span};
use leo_ast::{Identifier, PackageAccess, PackageOrPackages, Span};

use indexmap::IndexMap;
use std::{cell::RefCell, sync::Arc};
Expand Down Expand Up @@ -74,24 +74,37 @@ enum ImportSymbol {
fn resolve_import_package(
output: &mut Vec<(Vec<String>, ImportSymbol, Span)>,
mut package_segments: Vec<String>,
package: &Package,
package_or_packages: &PackageOrPackages,
) {
package_segments.push(package.name.name.clone());

resolve_import_package_access(output, package_segments, &package.access);
match package_or_packages {
PackageOrPackages::Package(package) => {
package_segments.push(package.name.name.clone());
resolve_import_package_access(output, package_segments, &package.access);
}
PackageOrPackages::Packages(packages) => {
package_segments.push(packages.name.name.clone());
for access in packages.accesses.clone() {
resolve_import_package_access(output, package_segments.clone(), &access);
}
}
}
}

fn resolve_import_package_access(
output: &mut Vec<(Vec<String>, ImportSymbol, Span)>,
package_segments: Vec<String>,
mut package_segments: Vec<String>,
package: &PackageAccess,
) {
match package {
PackageAccess::Star(span) => {
output.push((package_segments, ImportSymbol::All, span.clone()));
}
PackageAccess::SubPackage(subpackage) => {
resolve_import_package(output, package_segments, &*subpackage);
resolve_import_package(
output,
package_segments,
&PackageOrPackages::Package(*(*subpackage).clone()),
);
}
PackageAccess::Symbol(symbol) => {
let span = symbol.symbol.span.clone();
Expand All @@ -102,8 +115,9 @@ fn resolve_import_package_access(
};
output.push((package_segments, symbol, span));
}
PackageAccess::Multiple(subaccesses) => {
for subaccess in subaccesses.iter() {
PackageAccess::Multiple(packages) => {
package_segments.push(packages.name.name.clone());
for subaccess in packages.accesses.iter() {
resolve_import_package_access(output, package_segments.clone(), &subaccess);
}
}
Expand All @@ -126,7 +140,7 @@ impl InternalProgram {
// Recursively extract imported symbols.
let mut imported_symbols: Vec<(Vec<String>, ImportSymbol, Span)> = vec![];
for import in program.imports.iter() {
resolve_import_package(&mut imported_symbols, vec![], &import.package);
resolve_import_package(&mut imported_symbols, vec![], &import.package_or_packages);
}

// Create package list.
Expand Down Expand Up @@ -383,11 +397,11 @@ pub fn reform_ast(program: &Program) -> leo_ast::Program {
imports: core_programs
.iter()
.map(|(module, _)| leo_ast::ImportStatement {
package: leo_ast::Package {
package_or_packages: leo_ast::PackageOrPackages::Package(leo_ast::Package {
name: Identifier::new(module.clone()),
access: leo_ast::PackageAccess::Star(Span::default()),
span: Default::default(),
},
}),
span: Span::default(),
})
.collect(),
Expand Down
4 changes: 4 additions & 0 deletions asg/tests/pass/import/imports/bar/src/baz.leo
@@ -1,3 +1,7 @@
circuit Baz {
z: u32
}

circuit Bazzar {
a: u32
}
3 changes: 2 additions & 1 deletion asg/tests/pass/import/many_import.leo
Expand Up @@ -5,7 +5,7 @@ import test-import.( // local import

import bar.( // imports directory import
Bar,
baz.Baz,
baz.(Baz, Bazzar),
bat.bat.Bat,
);

Expand All @@ -17,6 +17,7 @@ function main() {

const bar = Bar { r: 1u32 };
const baz = Baz { z: 1u32 };
const bazzar = Bazzar { a: 1u32 };
const bat = Bat { t: 1u32 };

const car = Car { c: 1u32 };
Expand Down
2 changes: 1 addition & 1 deletion ast/src/common/identifier.rs
Expand Up @@ -129,7 +129,7 @@ impl<'ast> From<AnnotationArgument<'ast>> for Identifier {
impl<'ast> From<KeywordOrIdentifier<'ast>> for Identifier {
fn from(name: KeywordOrIdentifier<'ast>) -> Self {
match name {
KeywordOrIdentifier::SelfKeywordOrIdentifier(keyword) => Identifier::from(keyword),
KeywordOrIdentifier::Identifier(keyword) => Identifier::from(keyword),
KeywordOrIdentifier::SelfType(self_type) => Identifier::from(self_type),
KeywordOrIdentifier::Input(keyword) => Identifier::from(keyword),
}
Expand Down
84 changes: 83 additions & 1 deletion ast/src/expression/mod.rs
Expand Up @@ -25,7 +25,7 @@ use crate::{
SpreadOrExpression,
};
use leo_grammar::{
access::{Access, AssigneeAccess},
access::{Access, AssigneeAccess, SelfAccess},
common::{Assignee, Identifier as GrammarIdentifier, RangeOrExpression as GrammarRangeOrExpression},
expressions::{
ArrayInitializerExpression,
Expand All @@ -34,6 +34,7 @@ use leo_grammar::{
CircuitInlineExpression,
Expression as GrammarExpression,
PostfixExpression,
SelfPostfixExpression,
TernaryExpression as GrammarTernaryExpression,
UnaryExpression as GrammarUnaryExpression,
},
Expand Down Expand Up @@ -254,6 +255,86 @@ impl<'ast> From<PostfixExpression<'ast>> for Expression {
}
}

impl<'ast> From<SelfPostfixExpression<'ast>> for Expression {
fn from(expression: SelfPostfixExpression<'ast>) -> Self {
let variable = Expression::Identifier(Identifier::from(expression.name));

// Handle self expression access.
let self_expression = match expression.self_access {
// Handle circuit member accesses
SelfAccess::Object(circuit_object) => Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
circuit: Box::new(variable),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
}),

// Handle static access
SelfAccess::StaticObject(circuit_object) => {
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
circuit: Box::new(variable),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
})
}
};
// ast::SelfPostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions
// are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here

// we start with the id, and we fold the array of accesses by wrapping the current value
expression
.accesses
.into_iter()
.fold(self_expression, |acc, access| match access {
// Handle array accesses
Access::Array(array) => match array.expression {
GrammarRangeOrExpression::Expression(expression) => {
Expression::ArrayAccess(ArrayAccessExpression {
array: Box::new(acc),
index: Box::new(Expression::from(expression)),
span: Span::from(array.span),
})
}
GrammarRangeOrExpression::Range(range) => {
Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
array: Box::new(acc),
left: range.from.map(Expression::from).map(Box::new),
right: range.to.map(Expression::from).map(Box::new),
span: Span::from(array.span),
})
}
},

// Handle tuple access
Access::Tuple(tuple) => Expression::TupleAccess(TupleAccessExpression {
tuple: Box::new(acc),
index: PositiveNumber::from(tuple.number),
span: Span::from(tuple.span),
}),

// Handle function calls
Access::Call(function) => Expression::Call(CallExpression {
function: Box::new(acc),
arguments: function.expressions.into_iter().map(Expression::from).collect(),
span: Span::from(function.span),
}),

// Handle circuit member accesses
Access::Object(circuit_object) => Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
circuit: Box::new(acc),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
}),
Access::StaticObject(circuit_object) => {
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
circuit: Box::new(acc),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
})
}
})
}
}

impl<'ast> From<GrammarExpression<'ast>> for Expression {
fn from(expression: GrammarExpression<'ast>) -> Self {
match expression {
Expand All @@ -267,6 +348,7 @@ impl<'ast> From<GrammarExpression<'ast>> for Expression {
GrammarExpression::Tuple(expression) => Expression::from(expression),
GrammarExpression::CircuitInline(expression) => Expression::from(expression),
GrammarExpression::Postfix(expression) => Expression::from(expression),
GrammarExpression::SelfPostfix(expression) => Expression::from(expression),
}
}
}
Expand Down
13 changes: 8 additions & 5 deletions ast/src/imports/import.rs
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.

use crate::{Package, Span};
use crate::{PackageOrPackages, Span};
use leo_grammar::imports::Import as GrammarImport;

use serde::{Deserialize, Serialize};
Expand All @@ -23,7 +23,7 @@ use std::fmt;
/// Represents an import statement in a Leo program.
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct ImportStatement {
pub package: Package,
pub package_or_packages: PackageOrPackages,
pub span: Span,
}

Expand All @@ -32,22 +32,25 @@ impl ImportStatement {
/// Returns the the package file name of the self import statement.
///
pub fn get_file_name(&self) -> &str {
&self.package.name.name
match self.package_or_packages {
PackageOrPackages::Package(ref package) => &package.name.name,
PackageOrPackages::Packages(ref packages) => &packages.name.name,
}
}
}

impl<'ast> From<GrammarImport<'ast>> for ImportStatement {
fn from(import: GrammarImport<'ast>) -> Self {
ImportStatement {
package: Package::from(import.package),
package_or_packages: PackageOrPackages::from(import.package_or_packages),
span: Span::from(import.span),
}
}
}

impl ImportStatement {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "import {};", self.package)
write!(f, "import {};", self.package_or_packages)
}
}

Expand Down
6 changes: 6 additions & 0 deletions ast/src/imports/mod.rs
Expand Up @@ -23,5 +23,11 @@ pub use import_symbol::*;
pub mod package;
pub use package::*;

pub mod packages;
pub use packages::*;

pub mod package_or_packages;
pub use package_or_packages::*;

pub mod package_access;
pub use package_access::*;
14 changes: 6 additions & 8 deletions ast/src/imports/package_access.rs
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.

use crate::{ImportSymbol, Package, Span};
use crate::{ImportSymbol, Package, Packages, Span};
use leo_grammar::imports::PackageAccess as GrammarPackageAccess;

use serde::{Deserialize, Serialize};
Expand All @@ -25,7 +25,7 @@ pub enum PackageAccess {
Star(Span),
SubPackage(Box<Package>),
Symbol(ImportSymbol),
Multiple(Vec<PackageAccess>),
Multiple(Packages),
}

impl<'ast> From<GrammarPackageAccess<'ast>> for PackageAccess {
Expand All @@ -34,9 +34,7 @@ impl<'ast> From<GrammarPackageAccess<'ast>> for PackageAccess {
GrammarPackageAccess::Star(star) => PackageAccess::Star(Span::from(star.span)),
GrammarPackageAccess::SubPackage(package) => PackageAccess::SubPackage(Box::new(Package::from(*package))),
GrammarPackageAccess::Symbol(symbol) => PackageAccess::Symbol(ImportSymbol::from(symbol)),
GrammarPackageAccess::Multiple(accesses) => {
PackageAccess::Multiple(accesses.into_iter().map(PackageAccess::from).collect())
}
GrammarPackageAccess::Multiple(packages) => PackageAccess::Multiple(Packages::from(packages)),
}
}
}
Expand All @@ -47,11 +45,11 @@ impl PackageAccess {
PackageAccess::Star(ref _span) => write!(f, "*"),
PackageAccess::SubPackage(ref package) => write!(f, "{}", package),
PackageAccess::Symbol(ref symbol) => write!(f, "{}", symbol),
PackageAccess::Multiple(ref accesses) => {
PackageAccess::Multiple(ref packages) => {
write!(f, "(")?;
for (i, access) in accesses.iter().enumerate() {
for (i, access) in packages.accesses.iter().enumerate() {
write!(f, "{}", access)?;
if i < accesses.len() - 1 {
if i < packages.accesses.len() - 1 {
write!(f, ", ")?;
}
}
Expand Down

0 comments on commit dee4f34

Please sign in to comment.