add circuit type to ast

This commit is contained in:
collin 2022-06-15 11:32:19 -07:00
parent b2890f393a
commit 3882ec2425
17 changed files with 397 additions and 9 deletions

View File

@ -0,0 +1,39 @@
// Copyright (C) 2019-2022 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::{Expression, Identifier};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A circuit member access expression `inner.name` to some structure with *named members*.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MemberAccess {
/// The structure that the member `name` is being extracted from.
pub inner: Box<Expression>,
/// The name of the member to extract in `inner`.
pub name: Identifier,
/// The span covering all of `inner.name`.
pub span: Span,
}
impl fmt::Display for MemberAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.inner, self.name)
}
}

View File

@ -0,0 +1,21 @@
// Copyright (C) 2019-2022 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/>.
mod member_access;
pub use member_access::*;
mod static_access;
pub use static_access::*;

View File

@ -0,0 +1,41 @@
// Copyright (C) 2019-2022 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::{Expression, Identifier};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// An access expression to a static member, e.g., a constant in a circuit.
/// An example would be `Foo::Const` or `Foo::function` in `Foo::function()`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct StaticAccess {
/// Represents the container for the static member to access.
/// Usually this is a circuit.
pub inner: Box<Expression>,
/// The static member in `inner` that is being accessed.
pub name: Identifier,
/// The span for the entire expression `inner::name`.
pub span: Span,
}
impl fmt::Display for StaticAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}::{}", self.inner, self.name)
}
}

View File

@ -0,0 +1,56 @@
// Copyright (C) 2019-2022 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::{CircuitMember, Identifier};
use serde::{Deserialize, Serialize};
use std::fmt;
/// A circuit type definition, e.g., `circuit Foo { my_field: Bar }`.
/// In some languages these are called `struct`s.
///
/// Type identity is decided by the full path including `circuit_name`,
/// as the record is nominal, not structural.
/// The fields are named so `circuit Foo(u8, u16)` is not allowed.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Circuit {
/// The name of the type in the type system in this module.
pub circuit_name: Identifier,
/// The fields, constant variables, and functions of this structure.
pub members: Vec<CircuitMember>,
}
impl Circuit {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "circuit {} {{ ", self.circuit_name)?;
for field in self.members.iter() {
writeln!(f, " {}", field)?;
}
write!(f, "}}")
}
}
impl fmt::Debug for Circuit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Display for Circuit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}

View File

@ -0,0 +1,63 @@
// Copyright (C) 2019-2022 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::{Expression, Function, Identifier, Type};
use serde::{Deserialize, Serialize};
use std::fmt;
#[allow(clippy::large_enum_variant)]
/// A member of a circuit definition.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CircuitMember {
/// A static constant in a circuit.
/// For example: `const foobar: u8 = 42;`.
CircuitConst(
/// The identifier of the constant.
Identifier,
/// The type the constant has.
Type,
/// The expression representing the constant's value.
/// Checked to be of the type above.
Expression,
),
/// A variable definition in a circuit;
/// For example: `foobar: u8;`.
CircuitVariable(
/// The identifier of the constant.
Identifier,
/// The type the constant has.
Type,
),
/// A function definition in a circuit.
/// For example: `function bar() -> u8 { return 2u8; }`.
CircuitFunction(
/// The function.
Box<Function>,
),
}
impl fmt::Display for CircuitMember {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CircuitMember::CircuitConst(ref identifier, ref type_, ref value) => {
write!(f, "{}: {} = {}", identifier, type_, value)
}
CircuitMember::CircuitVariable(ref identifier, ref type_) => write!(f, "{}: {}", identifier, type_),
CircuitMember::CircuitFunction(ref function) => write!(f, "{}", function),
}
}
}

View File

@ -0,0 +1,21 @@
// Copyright (C) 2019-2022 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/>.
pub mod circuit;
pub use circuit::*;
pub mod circuit_member;
pub use circuit_member::*;

View File

@ -0,0 +1,48 @@
// Copyright (C) 2019-2022 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::access::*;
/// An access expressions, extracting a smaller part out of a whole.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum AccessExpression {
// /// An `array[index]` expression.
// Array(ArrayAccess),
// /// An expression accessing a range of an array.
// ArrayRange(ArrayRangeAccess),
/// An expression accessing a field in a structure, e.g., `circuit_var.field`.
Member(MemberAccess),
// /// Access to a tuple field using its position, e.g., `tuple.1`.
// Tuple(TupleAccess),
/// Access to a member constant or a static function of a circuit.
Static(StaticAccess),
}
impl fmt::Display for AccessExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use AccessExpression::*;
match self {
// Array(access) => access.fmt(f),
// ArrayRange(access) => access.fmt(f),
Member(access) => access.fmt(f),
// Tuple(access) => access.fmt(f),
Static(access) => access.fmt(f),
}
}
}

View File

@ -0,0 +1,64 @@
// Copyright (C) 2019-2022 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::*;
/// An initializer for a single field / variable of a circuit initializer expression.
/// That is, in `Foo { bar: 42, baz }`, this is either `bar: 42`, or `baz`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CircuitVariableInitializer {
/// The name of the field / variable to be initialized.
pub identifier: Identifier,
/// The expression to initialize the field with.
/// When `None`, a binding, in scope, with the name will be used instead.
pub expression: Option<Expression>,
}
impl fmt::Display for CircuitVariableInitializer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(expr) = &self.expression {
write!(f, "{}: {}", self.identifier, expr)
} else {
write!(f, "{}", self.identifier)
}
}
}
/// A circuit initialization expression, e.g., `Foo { bar: 42, baz }`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CircuitInitExpression {
/// The name of the structure type to initialize.
pub name: Identifier,
/// Initializer expressions for each of the fields in the circuit.
///
/// N.B. Any functions or member constants in the circuit definition
/// are excluded from this list.
pub members: Vec<CircuitVariableInitializer>,
/// A span from `name` to `}`.
pub span: Span,
}
impl fmt::Display for CircuitInitExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {{", self.name)?;
for member in self.members.iter() {
write!(f, "{}", member)?;
write!(f, ", ")?;
}
write!(f, "}}")
}
}
crate::simple_node_impl!(CircuitInitExpression);

View File

@ -20,19 +20,31 @@ use leo_span::Span;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
mod access;
pub use access::*;
mod binary; mod binary;
pub use binary::*; pub use binary::*;
mod unary;
pub use unary::*;
mod ternary;
pub use ternary::*;
mod value;
pub use value::*;
mod call; mod call;
pub use call::*; pub use call::*;
mod circuit_init;
pub use circuit_init::*;
mod err; mod err;
pub use err::*; pub use err::*;
mod ternary;
pub use ternary::*;
mod unary;
pub use unary::*;
mod value;
pub use value::*;
/// Expression that evaluates to a value. /// Expression that evaluates to a value.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Expression { pub enum Expression {

View File

@ -21,12 +21,17 @@
//! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`Ast`]. //! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`Ast`].
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
pub mod access;
pub use self::access::*;
pub mod circuits;
pub use self::circuits::*;
pub mod common; pub mod common;
pub use self::common::*; pub use self::common::*;
pub mod expression; pub mod expressions;
pub use self::expression::*; pub use self::expressions::*;
pub mod functions; pub mod functions;
pub use self::functions::*; pub use self::functions::*;

View File

@ -39,6 +39,8 @@ pub enum Type {
IntegerType(IntegerType), IntegerType(IntegerType),
/// A reference to a built in type. /// A reference to a built in type.
Identifier(Identifier), Identifier(Identifier),
/// The `Self` type, allowed within `circuit` definitions.
SelfType,
/// Placeholder for a type that could not be resolved or was not well-formed. /// Placeholder for a type that could not be resolved or was not well-formed.
/// Will eventually lead to a compile error. /// Will eventually lead to a compile error.
@ -46,6 +48,20 @@ pub enum Type {
} }
impl Type { impl Type {
///
/// Returns `true` if the self `Type` is the `SelfType`.
///
pub fn is_self(&self) -> bool {
matches!(self, Type::SelfType)
}
///
/// Returns `true` if the self `Type` is a `Circuit`.
///
pub fn is_circuit(&self) -> bool {
matches!(self, Type::Identifier(_))
}
/// ///
/// Returns `true` if the self `Type` is equal to the other `Type`. /// Returns `true` if the self `Type` is equal to the other `Type`.
/// ///
@ -58,7 +74,8 @@ impl Type {
| (Type::Field, Type::Field) | (Type::Field, Type::Field)
| (Type::Group, Type::Group) | (Type::Group, Type::Group)
| (Type::Scalar, Type::Scalar) | (Type::Scalar, Type::Scalar)
| (Type::String, Type::String) => true, | (Type::String, Type::String)
| (Type::SelfType, Type::SelfType) => true,
(Type::IntegerType(left), Type::IntegerType(right)) => left.eq(right), (Type::IntegerType(left), Type::IntegerType(right)) => left.eq(right),
(Type::Identifier(left), Type::Identifier(right)) => left.eq(right), (Type::Identifier(left), Type::Identifier(right)) => left.eq(right),
_ => false, _ => false,
@ -75,6 +92,7 @@ impl fmt::Display for Type {
Type::Group => write!(f, "group"), Type::Group => write!(f, "group"),
Type::Scalar => write!(f, "scalar"), Type::Scalar => write!(f, "scalar"),
Type::String => write!(f, "string"), Type::String => write!(f, "string"),
Type::SelfType => write!(f, "SelfType"),
Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type), Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type),
Type::Identifier(ref variable) => write!(f, "circuit {}", variable), Type::Identifier(ref variable) => write!(f, "circuit {}", variable),
Type::Err => write!(f, "error"), Type::Err => write!(f, "error"),