Rename in compiler

This commit is contained in:
Pranav Gaddamadugu 2022-09-30 11:52:06 -07:00
parent 8d12cd6651
commit f51a36aeaf
38 changed files with 371 additions and 408 deletions

View File

@ -20,12 +20,12 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// An access expression to an circuit constant., e.g. `u8::MAX`.
/// An access expression to an struct constant., e.g. `u8::MAX`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AssociatedConstant {
/// The inner circuit type.
/// The inner struct type.
pub ty: Type,
/// The circuit constant that is being accessed.
/// The struct constant that is being accessed.
pub name: Identifier,
/// The span for the entire expression `Foo::bar()`.
pub span: Span,

View File

@ -20,12 +20,12 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// An access expression to an associated function in a circuit, e.g.`Pedersen64::hash()`.
/// An access expression to an associated function in a struct, e.g.`Pedersen64::hash()`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AssociatedFunction {
/// The inner circuit type.
/// The inner struct type.
pub ty: Type,
/// The static circuit member function that is being accessed.
/// The static struct member function that is being accessed.
pub name: Identifier,
/// The arguments passed to the function `name`.
pub args: Vec<Expression>,

View File

@ -20,12 +20,12 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A circuit member access expression `inner.name` to some structure with *named members*.
/// A struct member access expression `inner.name` to some structure with *named members*.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MemberAccess {
/// The inner circuit that is being accessed.
/// The inner struct that is being accessed.
pub inner: Box<Expression>,
/// The name of the circuit member to access.
/// The name of the struct member to access.
pub name: Identifier,
/// The span covering all of `inner.name`.
pub span: Span,

View File

@ -27,11 +27,11 @@ pub enum AccessExpression {
// Array(ArrayAccess),
// /// An expression accessing a range of an array.
// ArrayRange(ArrayRangeAccess),
/// Access to an associated variable of a circuit e.g `u8::MAX`.
/// Access to an associated variable of a struct e.g `u8::MAX`.
AssociatedConstant(AssociatedConstant),
/// Access to an associated function of a circuit e.g `Pedersen64::hash()`.
/// Access to an associated function of a struct e.g `Pedersen64::hash()`.
AssociatedFunction(AssociatedFunction),
/// An expression accessing a field in a structure, e.g., `circuit_var.field`.
/// An expression accessing a field in a structure, e.g., `struct_var.field`.
Member(MemberAccess),
/// Access to a tuple field using its position, e.g., `tuple.1`.
Tuple(TupleAccess),

View File

@ -29,8 +29,8 @@ pub use binary::*;
mod call;
pub use call::*;
mod circuit_init;
pub use circuit_init::*;
mod struct_init;
pub use struct_init::*;
mod err;
pub use err::*;
@ -50,14 +50,14 @@ pub use literal::*;
/// Expression that evaluates to a value.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Expression {
/// A circuit access expression, e.g., `Foo.bar`.
/// A struct access expression, e.g., `Foo.bar`.
Access(AccessExpression),
/// A binary expression, e.g., `42 + 24`.
Binary(BinaryExpression),
/// A call expression, e.g., `my_fun(args)`.
Call(CallExpression),
/// An expression constructing a circuit like `Foo { bar: 42, baz }`.
Circuit(CircuitExpression),
/// An expression constructing a struct like `Foo { bar: 42, baz }`.
Struct(StructExpression),
/// An expression of type "error".
/// Will result in a compile error eventually.
Err(ErrExpression),
@ -80,7 +80,7 @@ impl Node for Expression {
Access(n) => n.span(),
Binary(n) => n.span(),
Call(n) => n.span(),
Circuit(n) => n.span(),
Struct(n) => n.span(),
Err(n) => n.span(),
Identifier(n) => n.span(),
Literal(n) => n.span(),
@ -96,7 +96,7 @@ impl Node for Expression {
Access(n) => n.set_span(span),
Binary(n) => n.set_span(span),
Call(n) => n.set_span(span),
Circuit(n) => n.set_span(span),
Struct(n) => n.set_span(span),
Identifier(n) => n.set_span(span),
Literal(n) => n.set_span(span),
Err(n) => n.set_span(span),
@ -114,7 +114,7 @@ impl fmt::Display for Expression {
Access(n) => n.fmt(f),
Binary(n) => n.fmt(f),
Call(n) => n.fmt(f),
Circuit(n) => n.fmt(f),
Struct(n) => n.fmt(f),
Err(n) => n.fmt(f),
Identifier(n) => n.fmt(f),
Literal(n) => n.fmt(f),

View File

@ -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::{normalize_json_value, remove_key_from_json, Circuit, Expression, Type};
use crate::{normalize_json_value, remove_key_from_json, Struct, Expression, Type};
use super::*;
use leo_errors::{AstError, Result};
@ -41,7 +41,7 @@ pub struct InputAst {
impl InputAst {
/// Returns all values of the input AST for execution with `leo run`.
pub fn program_inputs(&self, program_name: &str, circuits: IndexMap<Symbol, Circuit>) -> Vec<String> {
pub fn program_inputs(&self, program_name: &str, structs: IndexMap<Symbol, Struct>) -> Vec<String> {
self.sections
.iter()
.filter(|section| section.name() == program_name)
@ -49,18 +49,18 @@ impl InputAst {
section.definitions.iter().map(|definition| match &definition.type_ {
// Handle case where the input may be record.
Type::Identifier(identifier) => {
match circuits.get(&identifier.name) {
match structs.get(&identifier.name) {
// TODO: Better error handling.
None => panic!(
"Input error: A circuit or record declaration does not exist for {}.",
"Input error: A struct or record declaration does not exist for {}.",
identifier.name
),
Some(circuit) => match circuit.is_record {
Some(struct_) => match struct_.is_record {
false => definition.value.to_string(),
true => match &definition.value {
// Print out the record interface with visibility.
Expression::Circuit(circuit_expression) => circuit_expression.to_record_string(),
_ => panic!("Input error: Expected a circuit expression."),
Expression::Struct(struct_expression) => struct_expression.to_record_string(),
_ => panic!("Input error: Expected a struct expression."),
},
},
}

View File

@ -27,8 +27,8 @@ extern crate core;
pub mod access;
pub use self::access::*;
pub mod circuit;
pub use self::circuit::*;
pub mod r#struct;
pub use self::r#struct::*;
pub mod common;
pub use self::common::*;

View File

@ -28,7 +28,7 @@ pub trait ExpressionConsumer {
Expression::Access(access) => self.consume_access(access),
Expression::Binary(binary) => self.consume_binary(binary),
Expression::Call(call) => self.consume_call(call),
Expression::Circuit(circuit) => self.consume_circuit_init(circuit),
Expression::Struct(struct_) => self.consume_struct_init(struct_),
Expression::Err(err) => self.consume_err(err),
Expression::Identifier(identifier) => self.consume_identifier(identifier),
Expression::Literal(value) => self.consume_literal(value),
@ -44,7 +44,7 @@ pub trait ExpressionConsumer {
fn consume_call(&mut self, _input: CallExpression) -> Self::Output;
fn consume_circuit_init(&mut self, _input: CircuitExpression) -> Self::Output;
fn consume_struct_init(&mut self, _input: StructExpression) -> Self::Output;
fn consume_err(&mut self, _input: ErrExpression) -> Self::Output {
unreachable!("`ErrExpression`s should not be in the AST at this phase of compilation.")
@ -108,11 +108,11 @@ pub trait FunctionConsumer {
fn consume_function(&mut self, input: Function) -> Self::Output;
}
/// A Consumer trait for circuits in the AST.
pub trait CircuitConsumer {
/// A Consumer trait for structs in the AST.
pub trait StructConsumer {
type Output;
fn consume_circuit(&mut self, input: Circuit) -> Self::Output;
fn consume_struct(&mut self, input: Struct) -> Self::Output;
}
/// A Consumer trait for imported programs in the AST.

View File

@ -29,7 +29,7 @@ pub trait ExpressionReconstructor {
Expression::Access(access) => self.reconstruct_access(access),
Expression::Binary(binary) => self.reconstruct_binary(binary),
Expression::Call(call) => self.reconstruct_call(call),
Expression::Circuit(circuit) => self.reconstruct_circuit_init(circuit),
Expression::Struct(struct_) => self.reconstruct_struct_init(struct_),
Expression::Err(err) => self.reconstruct_err(err),
Expression::Identifier(identifier) => self.reconstruct_identifier(identifier),
Expression::Literal(value) => self.reconstruct_literal(value),
@ -98,8 +98,8 @@ pub trait ExpressionReconstructor {
)
}
fn reconstruct_circuit_init(&mut self, input: CircuitExpression) -> (Expression, Self::AdditionalOutput) {
(Expression::Circuit(input), Default::default())
fn reconstruct_struct_init(&mut self, input: StructExpression) -> (Expression, Self::AdditionalOutput) {
(Expression::Struct(input), Default::default())
}
fn reconstruct_err(&mut self, _input: ErrExpression) -> (Expression, Self::AdditionalOutput) {
@ -330,10 +330,10 @@ pub trait ProgramReconstructor: StatementReconstructor {
.into_iter()
.map(|(i, f)| (i, self.reconstruct_function(f)))
.collect(),
circuits: input
.circuits
structs: input
.structs
.into_iter()
.map(|(i, c)| (i, self.reconstruct_circuit(c)))
.map(|(i, c)| (i, self.reconstruct_struct(c)))
.collect(),
}
}
@ -358,7 +358,7 @@ pub trait ProgramReconstructor: StatementReconstructor {
}
}
fn reconstruct_circuit(&mut self, input: Circuit) -> Circuit {
fn reconstruct_struct(&mut self, input: Struct) -> Struct {
input
}

View File

@ -30,7 +30,7 @@ pub trait ExpressionVisitor<'a> {
Expression::Access(access) => self.visit_access(access, additional),
Expression::Binary(binary) => self.visit_binary(binary, additional),
Expression::Call(call) => self.visit_call(call, additional),
Expression::Circuit(circuit) => self.visit_circuit_init(circuit, additional),
Expression::Struct(struct_) => self.visit_struct_init(struct_, additional),
Expression::Err(err) => self.visit_err(err, additional),
Expression::Identifier(identifier) => self.visit_identifier(identifier, additional),
Expression::Literal(literal) => self.visit_literal(literal, additional),
@ -72,9 +72,9 @@ pub trait ExpressionVisitor<'a> {
Default::default()
}
fn visit_circuit_init(
fn visit_struct_init(
&mut self,
_input: &'a CircuitExpression,
_input: &'a StructExpression,
_additional: &Self::AdditionalInput,
) -> Self::Output {
Default::default()
@ -200,9 +200,9 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
input.imports.values().for_each(|import| self.visit_import(import));
input
.circuits
.structs
.values()
.for_each(|function| self.visit_circuit(function));
.for_each(|function| self.visit_struct(function));
input.mappings.values().for_each(|mapping| self.visit_mapping(mapping));
@ -216,7 +216,7 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
self.visit_program(input)
}
fn visit_circuit(&mut self, _input: &'a Circuit) {}
fn visit_struct(&mut self, _input: &'a Struct) {}
fn visit_mapping(&mut self, _input: &'a Mapping) {}

View File

@ -14,10 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! A Leo program consists of import, circuit, and function definitions.
//! A Leo program consists of import, struct, and function definitions.
//! Each defined type consists of ast statements and expressions.
use crate::{Circuit, Function, FunctionInput, Identifier, Mapping};
use crate::{Struct, Function, FunctionInput, Identifier, Mapping};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
@ -35,8 +35,8 @@ pub struct Program {
pub expected_input: Vec<FunctionInput>,
/// A map from import names to import definitions.
pub imports: IndexMap<Identifier, Program>,
/// A map from circuit names to circuit definitions.
pub circuits: IndexMap<Identifier, Circuit>,
/// A map from struct names to struct definitions.
pub structs: IndexMap<Identifier, Struct>,
/// A map from mapping names to mapping definitions.
pub mappings: IndexMap<Identifier, Mapping>,
/// A map from function names to function definitions.
@ -48,8 +48,8 @@ impl fmt::Display for Program {
for (id, _import) in self.imports.iter() {
writeln!(f, "import {}.leo;", id)?;
}
for (_, circuit) in self.circuits.iter() {
circuit.fmt(f)?;
for (_, struct_) in self.structs.iter() {
struct_.fmt(f)?;
writeln!(f,)?;
}
for (_, mapping) in self.mappings.iter() {
@ -73,7 +73,7 @@ impl Default for Program {
network: String::new(),
expected_input: vec![],
imports: IndexMap::new(),
circuits: IndexMap::new(),
structs: IndexMap::new(),
mappings: IndexMap::new(),
functions: IndexMap::new(),
}

View File

@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod circuit_member;
pub use circuit_member::*;
pub mod member;
pub use member::*;
use crate::{Identifier, Node};
use leo_span::{Span, Symbol};
@ -23,49 +23,49 @@ use leo_span::{Span, Symbol};
use serde::{Deserialize, Serialize};
use std::fmt;
/// A circuit type definition, e.g., `circuit Foo { my_field: Bar }`.
/// A struct type definition, e.g., `struct Foo { my_field: Bar }`.
/// In some languages these are called `struct`s.
///
/// Type identity is decided by the full path including `circuit_name`,
/// Type identity is decided by the full path including `struct_name`,
/// as the record is nominal, not structural.
/// The fields are named so `circuit Foo(u8, u16)` is not allowed.
/// The fields are named so `struct Foo(u8, u16)` is not allowed.
#[derive(Clone, Serialize, Deserialize)]
pub struct Circuit {
pub struct Struct {
/// The name of the type in the type system in this module.
pub identifier: Identifier,
/// The fields, constant variables, and functions of this structure.
pub members: Vec<CircuitMember>,
pub members: Vec<Member>,
/// Was this a `record Foo { ... }`?
/// If so, it wasn't a circuit.
/// If so, it wasn't a struct.
pub is_record: bool,
/// The entire span of the circuit definition.
/// The entire span of the struct definition.
pub span: Span,
}
impl PartialEq for Circuit {
impl PartialEq for Struct {
fn eq(&self, other: &Self) -> bool {
self.identifier == other.identifier
}
}
impl Eq for Circuit {}
impl Eq for Struct {}
impl Circuit {
/// Returns the circuit name as a Symbol.
impl Struct {
/// Returns the struct name as a Symbol.
pub fn name(&self) -> Symbol {
self.identifier.name
}
}
impl fmt::Debug for Circuit {
impl fmt::Debug for Struct {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}
impl fmt::Display for Circuit {
impl fmt::Display for Struct {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(if self.is_record { "record" } else { "circuit" })?;
f.write_str(if self.is_record { "record" } else { "struct" })?;
writeln!(f, " {} {{ ", self.identifier)?;
for field in self.members.iter() {
writeln!(f, " {}", field)?;
@ -74,4 +74,4 @@ impl fmt::Display for Circuit {
}
}
crate::simple_node_impl!(Circuit);
crate::simple_node_impl!(Struct);

View File

@ -183,7 +183,7 @@ pub enum Value {
Input(Type, Identifier),
Address(String, Span),
Boolean(bool, Span),
Circuit(Identifier, IndexMap<Symbol, Value>),
Struct(Identifier, IndexMap<Symbol, Value>),
Field(String, Span),
Group(Box<GroupLiteral>),
I8(i8, Span),
@ -728,7 +728,7 @@ impl Display for Value {
match self {
Input(type_, ident) => write!(f, "input var {}: {type_}", ident.name),
Address(val, _) => write!(f, "{val}"),
Circuit(val, _) => write!(f, "{}", val.name),
Struct(val, _) => write!(f, "{}", val.name),
Boolean(val, _) => write!(f, "{val}"),
Field(val, _) => write!(f, "{val}"),
Group(val) => write!(f, "{val}"),
@ -845,7 +845,7 @@ impl From<&Value> for Type {
Input(type_, _) => type_.clone(),
Address(_, _) => Type::Address,
Boolean(_, _) => Type::Boolean,
Circuit(ident, _) => Type::Identifier(*ident),
Struct(ident, _) => Type::Identifier(*ident),
Field(_, _) => Type::Field,
Group(_) => Type::Group,
I8(_, _) => Type::Integer(IntegerType::I8),
@ -899,7 +899,7 @@ impl From<Value> for Literal {
Input(_, _) => todo!("We need to test if this is hittable"),
Address(v, span) => Literal::Address(v, span),
Boolean(v, span) => Literal::Boolean(v, span),
Circuit(_ident, _values) => todo!("We need to test if this is hittable"),
Struct(_ident, _values) => todo!("We need to test if this is hittable"),
Field(v, span) => Literal::Field(v, span),
Group(v) => Literal::Group(v),
I8(v, span) => Literal::Integer(IntegerType::I8, v.to_string(), span),

View File

@ -48,9 +48,9 @@ pub enum CoreInstruction {
}
impl CoreInstruction {
/// Returns a `CoreInstruction` from the given circuit and method symbols.
pub fn from_symbols(circuit: Symbol, function: Symbol) -> Option<Self> {
Some(match (circuit, function) {
/// Returns a `CoreInstruction` from the given module and method symbols.
pub fn from_symbols(module: Symbol, function: Symbol) -> Option<Self> {
Some(match (module, function) {
(sym::BHP256, sym::commit) => Self::BHP256Commit,
(sym::BHP256, sym::hash) => Self::BHP256Hash,
(sym::BHP512, sym::commit) => Self::BHP512Commit,
@ -161,7 +161,7 @@ impl CoreInstruction {
}
}
/// A core function of a core circuit, e.g. `hash` or `commit`
/// A core function of a core struct, e.g. `hash` or `commit`
/// Provides required type information to the type checker.
trait CoreFunction {
const NUM_ARGS: usize;

View File

@ -37,8 +37,8 @@ pub(crate) struct ParserContext<'a> {
/// The previous token, i.e., if `p.tokens = ['3', *, '4']`,
/// then after two `p.bump()`s, we'll have `p.token = '*'` and `p.prev_token = '3'`.
pub(crate) prev_token: SpannedToken,
/// true if parsing an expression for if and loop statements -- means circuit inits are not legal
pub(crate) disallow_circuit_construction: bool,
/// true if parsing an expression for if and loop statements -- means struct inits are not legal
pub(crate) disallow_struct_construction: bool,
/// true if parsing an identifier inside an input file.
pub(crate) allow_identifier_underscores: bool,
}
@ -60,7 +60,7 @@ impl<'a> ParserContext<'a> {
let token = SpannedToken::dummy();
let mut p = Self {
handler,
disallow_circuit_construction: false,
disallow_struct_construction: false,
allow_identifier_underscores: false,
prev_token: token.clone(),
token,

View File

@ -38,25 +38,25 @@ const INT_TYPES: &[Token] = &[
impl ParserContext<'_> {
/// Returns an [`Expression`] AST node if the next token is an expression.
/// Includes circuit init expressions.
/// Includes struct init expressions.
pub(crate) fn parse_expression(&mut self) -> Result<Expression> {
// Store current parser state.
let prior_fuzzy_state = self.disallow_circuit_construction;
let prior_fuzzy_state = self.disallow_struct_construction;
// Allow circuit init expressions.
self.disallow_circuit_construction = false;
// Allow struct init expressions.
self.disallow_struct_construction = false;
// Parse expression.
let result = self.parse_conditional_expression();
// Restore prior parser state.
self.disallow_circuit_construction = prior_fuzzy_state;
self.disallow_struct_construction = prior_fuzzy_state;
result
}
/// Returns an [`Expression`] AST node if the next tokens represent
/// a ternary expression. May or may not include circuit init expressions.
/// a ternary expression. May or may not include struct init expressions.
///
/// Otherwise, tries to parse the next token using [`parse_boolean_or_expression`].
pub(super) fn parse_conditional_expression(&mut self) -> Result<Expression> {
@ -307,15 +307,15 @@ impl ParserContext<'_> {
/// Returns an [`Expression`] AST node if the next tokens represent a
/// static access expression.
fn parse_associated_access_expression(&mut self, circuit_name: Expression) -> Result<Expression> {
// Parse circuit name expression into circuit type.
let circuit_type = if let Expression::Identifier(ident) = circuit_name {
fn parse_associated_access_expression(&mut self, module_name: Expression) -> Result<Expression> {
// Parse struct name expression into struct type.
let type_ = if let Expression::Identifier(ident) = module_name {
Type::Identifier(ident)
} else {
return Err(ParserError::invalid_associated_access(&circuit_name, circuit_name.span()).into());
return Err(ParserError::invalid_associated_access(&module_name, module_name.span()).into());
};
// Parse the circuit member name (can be variable or function name).
// Parse the struct member name (can be variable or function name).
let member_name = self.expect_identifier()?;
// Check if there are arguments.
@ -323,18 +323,18 @@ impl ParserContext<'_> {
// Parse the arguments
let (args, _, end) = self.parse_expr_tuple()?;
// Return the circuit function.
// Return the struct function.
AccessExpression::AssociatedFunction(AssociatedFunction {
span: circuit_name.span() + end,
ty: circuit_type,
span: module_name.span() + end,
ty: type_,
name: member_name,
args,
})
} else {
// Return the circuit constant.
// Return the struct constant.
AccessExpression::AssociatedConstant(AssociatedConstant {
span: circuit_name.span() + member_name.span(),
ty: circuit_type,
span: module_name.span() + member_name.span(),
ty: type_,
name: member_name,
})
}))
@ -346,7 +346,7 @@ impl ParserContext<'_> {
}
/// Returns an [`Expression`] AST node if the next tokens represent an
/// array access, circuit member access, function call, or static function call expression.
/// array access, struct member access, function call, or static function call expression.
///
/// Otherwise, tries to parse the next token using [`parse_primary_expression`].
fn parse_postfix_expression(&mut self) -> Result<Expression> {
@ -387,7 +387,7 @@ impl ParserContext<'_> {
// Eat a method call on a type
expr = self.parse_method_call_expression(expr, name)?
} else {
// Eat a circuit member access.
// Eat a struct member access.
expr = Expression::Access(AccessExpression::Member(MemberAccess {
span: expr.span(),
inner: Box::new(expr),
@ -396,7 +396,7 @@ impl ParserContext<'_> {
}
}
} else if self.eat(&Token::DoubleColon) {
// Eat a core circuit constant or core circuit function call.
// Eat a core struct constant or core struct function call.
expr = self.parse_associated_access_expression(expr)?;
} else if self.check(&Token::LeftParen) {
// Parse a function call that's by itself.
@ -494,9 +494,9 @@ impl ParserContext<'_> {
Some(Ok(gt))
}
fn parse_circuit_member(&mut self) -> Result<CircuitVariableInitializer> {
fn parse_struct_member(&mut self) -> Result<StructVariableInitializer> {
let identifier = if self.allow_identifier_underscores && self.eat(&Token::Underscore) {
// Allow `_nonce` for circuit records.
// Allow `_nonce` for struct records.
let identifier_without_underscore = self.expect_identifier()?;
Identifier::new(Symbol::intern(&format!("_{}", identifier_without_underscore.name)))
} else {
@ -504,24 +504,24 @@ impl ParserContext<'_> {
};
let expression = if self.eat(&Token::Colon) {
// Parse individual circuit variable declarations.
// Parse individual struct variable declarations.
Some(self.parse_expression()?)
} else {
None
};
Ok(CircuitVariableInitializer { identifier, expression })
Ok(StructVariableInitializer { identifier, expression })
}
/// Returns an [`Expression`] AST node if the next tokens represent a
/// circuit initialization expression.
/// struct initialization expression.
/// let foo = Foo { x: 1u8 };
pub fn parse_circuit_init_expression(&mut self, identifier: Identifier) -> Result<Expression> {
pub fn parse_struct_init_expression(&mut self, identifier: Identifier) -> Result<Expression> {
let (members, _, end) = self.parse_list(Delimiter::Brace, Some(Token::Comma), |p| {
p.parse_circuit_member().map(Some)
p.parse_struct_member().map(Some)
})?;
Ok(Expression::Circuit(CircuitExpression {
Ok(Expression::Struct(StructExpression {
span: identifier.span + end,
name: identifier,
members,
@ -584,10 +584,10 @@ impl ParserContext<'_> {
Token::StaticString(value) => Expression::Literal(Literal::String(value, span)),
Token::Identifier(name) => {
let ident = Identifier { name, span };
if !self.disallow_circuit_construction && self.check(&Token::LeftCurly) {
// Parse circuit and records inits as circuit expressions.
// Enforce circuit or record type later at type checking.
self.parse_circuit_init_expression(ident)?
if !self.disallow_struct_construction && self.check(&Token::LeftCurly) {
// Parse struct and records inits as struct expressions.
// Enforce struct or record type later at type checking.
self.parse_struct_init_expression(ident)?
} else {
Expression::Identifier(ident)
}

View File

@ -28,7 +28,7 @@ impl ParserContext<'_> {
pub fn parse_program(&mut self) -> Result<Program> {
let mut imports = IndexMap::new();
let mut functions = IndexMap::new();
let mut circuits = IndexMap::new();
let mut structs = IndexMap::new();
let mut mappings = IndexMap::new();
// TODO: Condense logic
@ -38,9 +38,10 @@ impl ParserContext<'_> {
let (id, import) = self.parse_import()?;
imports.insert(id, import);
}
Token::Circuit | Token::Record => {
let (id, circuit) = self.parse_circuit()?;
circuits.insert(id, circuit);
// TODO: Error for circuit token
Token::Struct | Token::Record => {
let (id, struct_) = self.parse_struct()?;
structs.insert(id, struct_);
}
Token::Mapping => {
let (id, mapping) = self.parse_mapping()?;
@ -68,7 +69,7 @@ impl ParserContext<'_> {
expected_input: Vec::new(),
imports,
functions,
circuits,
structs,
mappings,
})
}
@ -76,7 +77,7 @@ impl ParserContext<'_> {
fn unexpected_item(token: &SpannedToken) -> ParserError {
ParserError::unexpected(
&token.token,
[Token::Function, Token::Circuit, Token::Identifier(sym::test)]
[Token::Function, Token::Struct, Token::Identifier(sym::test)]
.iter()
.map(|x| format!("'{}'", x))
.collect::<Vec<_>>()
@ -131,40 +132,30 @@ impl ParserContext<'_> {
Ok((import_name, program_ast.into_repr()))
}
/// Returns a [`Vec<CircuitMember>`] AST node if the next tokens represent a circuit member variable
/// or circuit member function or circuit member constant.
fn parse_circuit_members(&mut self) -> Result<(Vec<CircuitMember>, Span)> {
/// Returns a [`Vec<Member>`] AST node if the next tokens represent a struct member.
fn parse_struct_members(&mut self) -> Result<(Vec<Member>, Span)> {
let mut members = Vec::new();
let (mut semi_colons, mut commas) = (false, false);
while !self.check(&Token::RightCurly) {
members.push(if self.peek_is_function() {
// function
self.parse_member_function_declaration()?
} else if self.eat(&Token::Static) {
// static const
self.parse_const_member_variable_declaration()?
} else {
// variable
let variable = self.parse_member_variable_declaration()?;
let variable = self.parse_member_variable_declaration()?;
if self.eat(&Token::Semicolon) {
if commas {
self.emit_err(ParserError::mixed_commas_and_semicolons(self.token.span));
}
semi_colons = true;
if self.eat(&Token::Semicolon) {
if commas {
self.emit_err(ParserError::mixed_commas_and_semicolons(self.token.span));
}
semi_colons = true;
}
if self.eat(&Token::Comma) {
if semi_colons {
self.emit_err(ParserError::mixed_commas_and_semicolons(self.token.span));
}
commas = true;
if self.eat(&Token::Comma) {
if semi_colons {
self.emit_err(ParserError::mixed_commas_and_semicolons(self.token.span));
}
commas = true;
}
variable
});
members.push(variable);
}
let span = self.expect(&Token::RightCurly)?;
@ -180,57 +171,27 @@ impl ParserContext<'_> {
Ok((name, type_))
}
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member static constant.
fn parse_const_member_variable_declaration(&mut self) -> Result<CircuitMember> {
self.expect(&Token::Static)?;
self.expect(&Token::Const)?;
// `IDENT: TYPE = EXPR`:
let (_name, _type_) = self.parse_typed_ident()?;
self.expect(&Token::Assign)?;
let expr = self.parse_expression()?;
self.expect(&Token::Semicolon)?;
// CAUTION: function members are unstable for testnet3.
Err(ParserError::circuit_constants_unstable(expr.span()).into())
// Ok(CircuitMember::CircuitConst(name, type_, expr))
}
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member variable.
fn parse_member_variable_declaration(&mut self) -> Result<CircuitMember> {
/// Returns a [`Member`] AST node if the next tokens represent a struct member variable.
fn parse_member_variable_declaration(&mut self) -> Result<Member> {
let (name, type_) = self.parse_typed_ident()?;
Ok(CircuitMember::CircuitVariable(name, type_))
Ok(Member::StructVariable(name, type_))
}
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member function.
fn parse_member_function_declaration(&mut self) -> Result<CircuitMember> {
if self.peek_is_function() {
// CAUTION: function members are unstable for testnet3.
let function = self.parse_function()?;
Err(ParserError::circuit_functions_unstable(function.1.span()).into())
// Ok(CircuitMember::CircuitFunction(Box::new(function.1)))
} else {
Err(Self::unexpected_item(&self.token).into())
}
}
/// Parses a circuit or record definition, e.g., `circuit Foo { ... }` or `record Foo { ... }`.
pub(super) fn parse_circuit(&mut self) -> Result<(Identifier, Circuit)> {
/// Parses a struct or record definition, e.g., `struct Foo { ... }` or `record Foo { ... }`.
pub(super) fn parse_struct(&mut self) -> Result<(Identifier, Struct)> {
let is_record = matches!(&self.token.token, Token::Record);
let start = self.expect_any(&[Token::Circuit, Token::Record])?;
let circuit_name = self.expect_identifier()?;
let start = self.expect_any(&[Token::Struct, Token::Record])?;
let struct_name = self.expect_identifier()?;
self.expect(&Token::LeftCurly)?;
let (members, end) = self.parse_circuit_members()?;
let (members, end) = self.parse_struct_members()?;
Ok((
circuit_name,
Circuit {
identifier: circuit_name,
struct_name,
Struct {
identifier: struct_name,
members,
is_record,
span: start + end,
@ -414,12 +375,12 @@ impl ParserContext<'_> {
let output = match self.eat(&Token::Arrow) {
false => vec![],
true => {
self.disallow_circuit_construction = true;
self.disallow_struct_construction = true;
let output = match self.peek_is_left_par() {
true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
false => vec![self.parse_output()?],
};
self.disallow_circuit_construction = false;
self.disallow_struct_construction = false;
output
}
};
@ -444,12 +405,12 @@ impl ParserContext<'_> {
let output = match self.eat(&Token::Arrow) {
false => vec![],
true => {
self.disallow_circuit_construction = true;
self.disallow_struct_construction = true;
let output = match self.peek_is_left_par() {
true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
false => vec![self.parse_output()?],
};
self.disallow_circuit_construction = false;
self.disallow_struct_construction = false;
output
}
};

View File

@ -177,9 +177,9 @@ impl ParserContext<'_> {
/// Returns a [`ConditionalStatement`] AST node if the next tokens represent a conditional statement.
fn parse_conditional_statement(&mut self) -> Result<ConditionalStatement> {
let start = self.expect(&Token::If)?;
self.disallow_circuit_construction = true;
self.disallow_struct_construction = true;
let expr = self.parse_conditional_expression()?;
self.disallow_circuit_construction = false;
self.disallow_struct_construction = false;
let body = self.parse_block()?;
let next = if self.eat(&Token::Else) {
let s = self.parse_statement()?;
@ -210,9 +210,9 @@ impl ParserContext<'_> {
// Parse iteration range.
let start = self.parse_expression()?;
self.expect(&Token::DotDot)?;
self.disallow_circuit_construction = true;
self.disallow_struct_construction = true;
let stop = self.parse_conditional_expression()?;
self.disallow_circuit_construction = false;
self.disallow_struct_construction = false;
let block = self.parse_block()?;

View File

@ -396,7 +396,6 @@ impl Token {
"address" => Token::Address,
"async" => Token::Async,
"bool" => Token::Bool,
"circuit" => Token::Circuit,
"console" => Token::Console,
"const" => Token::Const,
"constant" => Token::Constant,
@ -426,6 +425,7 @@ impl Token {
"scalar" => Token::Scalar,
"self" => Token::SelfLower,
"string" => Token::String,
"struct" => Token::Struct,
"true" => Token::True,
"u8" => Token::U8,
"u16" => Token::U16,

View File

@ -107,6 +107,7 @@ mod tests {
scalar
self
string
struct
test
true
u128
@ -158,7 +159,7 @@ mod tests {
assert_eq!(
output,
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" test_ident 12345 address async bool const else false field finalize for function group i128 i64 i32 i16 i8 if in input let mut return scalar self string test true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> => _ . .. / : ; < <= = == > >= [ ] { { } } || ? @ // test
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" test_ident 12345 address async bool const else false field finalize for function group i128 i64 i32 i16 i8 if in input let mut return scalar self string struct test true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> => _ . .. / : ; < <= = == > >= [ ] { { } } || ? @ // test
/* test */ // "#
);
});

View File

@ -131,6 +131,7 @@ pub enum Token {
Return,
SelfLower,
Static,
Struct,
// For imports.
Leo,
@ -146,7 +147,6 @@ pub const KEYWORD_TOKENS: &[Token] = &[
Token::Address,
Token::Async,
Token::Bool,
Token::Circuit,
Token::Console,
Token::Const,
Token::Constant,
@ -176,6 +176,7 @@ pub const KEYWORD_TOKENS: &[Token] = &[
Token::Scalar,
Token::Static,
Token::String,
Token::Struct,
Token::True,
Token::U8,
Token::U16,
@ -196,7 +197,6 @@ impl Token {
Token::Address => sym::address,
Token::Async => sym::Async,
Token::Bool => sym::bool,
Token::Circuit => sym::circuit,
Token::Console => sym::console,
Token::Const => sym::Const,
Token::Constant => sym::Constant,
@ -227,6 +227,7 @@ impl Token {
Token::SelfLower => sym::SelfLower,
Token::Static => sym::Static,
Token::String => sym::string,
Token::Struct => sym::Struct,
Token::True => sym::True,
Token::U8 => sym::u8,
Token::U16 => sym::u16,
@ -323,7 +324,6 @@ impl fmt::Display for Token {
Record => write!(f, "record"),
Async => write!(f, "async"),
Circuit => write!(f, "circuit"),
Console => write!(f, "console"),
Const => write!(f, "const"),
Constant => write!(f, "constant"),
@ -342,6 +342,7 @@ impl fmt::Display for Token {
Public => write!(f, "public"),
Return => write!(f, "return"),
Static => write!(f, "static"),
Struct => write!(f, "struct"),
Leo => write!(f, "leo"),
Eof => write!(f, "<eof>"),
}

View File

@ -16,7 +16,7 @@
use crate::CodeGenerator;
use leo_ast::{
AccessExpression, AssociatedFunction, BinaryExpression, BinaryOperation, CallExpression, CircuitExpression,
AccessExpression, AssociatedFunction, BinaryExpression, BinaryOperation, CallExpression, StructExpression,
ErrExpression, Expression, Identifier, Literal, MemberAccess, TernaryExpression, TupleExpression, Type,
UnaryExpression, UnaryOperation,
};
@ -34,7 +34,7 @@ impl<'a> CodeGenerator<'a> {
Expression::Access(expr) => self.visit_access(expr),
Expression::Binary(expr) => self.visit_binary(expr),
Expression::Call(expr) => self.visit_call(expr),
Expression::Circuit(expr) => self.visit_circuit_init(expr),
Expression::Struct(expr) => self.visit_struct_init(expr),
Expression::Err(expr) => self.visit_err(expr),
Expression::Identifier(expr) => self.visit_identifier(expr),
Expression::Literal(expr) => self.visit_value(expr),
@ -160,8 +160,8 @@ impl<'a> CodeGenerator<'a> {
(destination_register, instructions)
}
fn visit_circuit_init(&mut self, input: &'a CircuitExpression) -> (String, String) {
// Lookup circuit or record.
fn visit_struct_init(&mut self, input: &'a StructExpression) -> (String, String) {
// Lookup struct or record.
let name = if let Some((is_record, type_)) = self.composite_mapping.get(&input.name.name) {
if *is_record {
// record.private;
@ -176,9 +176,9 @@ impl<'a> CodeGenerator<'a> {
// Initialize instruction builder strings.
let mut instructions = String::new();
let mut circuit_init_instruction = String::from(" cast ");
let mut struct_init_instruction = String::from(" cast ");
// Visit each circuit member and accumulate instructions from expressions.
// Visit each struct member and accumulate instructions from expressions.
for member in input.members.iter() {
let operand = if let Some(expr) = member.expression.as_ref() {
// Visit variable expression.
@ -194,21 +194,21 @@ impl<'a> CodeGenerator<'a> {
ident_operand
};
// Push operand name to circuit init instruction.
write!(circuit_init_instruction, "{} ", operand).expect("failed to write to string");
// Push operand name to struct init instruction.
write!(struct_init_instruction, "{} ", operand).expect("failed to write to string");
}
// Push destination register to circuit init instruction.
// Push destination register to struct init instruction.
let destination_register = format!("r{}", self.next_register);
writeln!(
circuit_init_instruction,
struct_init_instruction,
"into {dest} as {name};",
dest = destination_register,
name = name,
)
.expect("failed to write to string");
instructions.push_str(&circuit_init_instruction);
instructions.push_str(&struct_init_instruction);
// Increment the register counter.
self.next_register += 1;
@ -217,8 +217,8 @@ impl<'a> CodeGenerator<'a> {
}
fn visit_member_access(&mut self, input: &'a MemberAccess) -> (String, String) {
let (inner_circuit, _inner_instructions) = self.visit_expression(&input.inner);
let member_access_instruction = format!("{}.{}", inner_circuit, input.name);
let (inner_struct, _inner_instructions) = self.visit_expression(&input.inner);
let member_access_instruction = format!("{}.{}", inner_struct, input.name);
(member_access_instruction, String::new())
}
@ -237,10 +237,10 @@ impl<'a> CodeGenerator<'a> {
sym::Poseidon2 => "psd2",
sym::Poseidon4 => "psd4",
sym::Poseidon8 => "psd8",
_ => unreachable!("All core circuit function calls should be known at this time."),
_ => unreachable!("All core function calls should be known at this time."),
}
} else {
unreachable!("All core circuits should be known at this time.")
unreachable!("All core function should be known at this time.")
};
// Construct associated function call.

View File

@ -16,7 +16,7 @@
use crate::CodeGenerator;
use leo_ast::{functions, Circuit, CircuitMember, Function, Identifier, Mapping, Mode, Program, Type};
use leo_ast::{functions, Struct, Member, Function, Identifier, Mapping, Mode, Program, Type};
use indexmap::IndexMap;
use itertools::Itertools;
@ -49,12 +49,12 @@ impl<'a> CodeGenerator<'a> {
// Newline separator.
program_string.push('\n');
// Visit each `Circuit` or `Record` in the Leo AST and produce a Aleo interface instruction.
// Visit each `Struct` or `Record` in the Leo AST and produce a Aleo interface instruction.
program_string.push_str(
&input
.circuits
.structs
.values()
.map(|circuit| self.visit_circuit_or_record(circuit))
.map(|struct_| self.visit_struct_or_record(struct_))
.join("\n"),
);
@ -114,25 +114,25 @@ impl<'a> CodeGenerator<'a> {
format!("import {}.aleo;", import_name)
}
fn visit_circuit_or_record(&mut self, circuit: &'a Circuit) -> String {
if circuit.is_record {
self.visit_record(circuit)
fn visit_struct_or_record(&mut self, struct_: &'a Struct) -> String {
if struct_.is_record {
self.visit_record(struct_)
} else {
self.visit_circuit(circuit)
self.visit_struct(struct_)
}
}
fn visit_circuit(&mut self, circuit: &'a Circuit) -> String {
fn visit_struct(&mut self, struct_: &'a Struct) -> String {
// Add private symbol to composite types.
self.composite_mapping
.insert(&circuit.identifier.name, (false, String::from("private"))); // todo: private by default here.
.insert(&struct_.identifier.name, (false, String::from("private"))); // todo: private by default here.
let mut output_string = format!("interface {}:\n", circuit.identifier); // todo: check if this is safe from name conflicts.
let mut output_string = format!("interface {}:\n", struct_.identifier); // todo: check if this is safe from name conflicts.
// Construct and append the record variables.
for var in circuit.members.iter() {
for var in struct_.members.iter() {
let (name, type_) = match var {
CircuitMember::CircuitVariable(name, type_) => (name, type_),
Member::StructVariable(name, type_) => (name, type_),
};
writeln!(output_string, " {} as {};", name, type_,).expect("failed to write to string");
@ -141,7 +141,7 @@ impl<'a> CodeGenerator<'a> {
output_string
}
fn visit_record(&mut self, record: &'a Circuit) -> String {
fn visit_record(&mut self, record: &'a Struct) -> String {
// Add record symbol to composite types.
let mut output_string = String::from("record");
self.composite_mapping
@ -151,7 +151,7 @@ impl<'a> CodeGenerator<'a> {
// Construct and append the record variables.
for var in record.members.iter() {
let (name, type_) = match var {
CircuitMember::CircuitVariable(name, type_) => (name, type_),
Member::StructVariable(name, type_) => (name, type_),
};
writeln!(
@ -270,12 +270,12 @@ impl<'a> CodeGenerator<'a> {
Type::Mapping(_) | Type::Tuple(_) => unreachable!("Mappings cannot contain mappings or tuples."),
Type::Identifier(identifier) => {
// Lookup the type in the composite mapping.
// Note that this unwrap is safe since all circuit and records have been added to the composite mapping.
// Note that this unwrap is safe since all struct and records have been added to the composite mapping.
let (is_record, _) = self.composite_mapping.get(&identifier.name).unwrap();
match is_record {
// If the type is a record, then declare the type as is.
true => format!("{}.record", identifier),
// If the type is a circuit, then add the public modifier.
// If the type is a struct, then add the public modifier.
false => format!("{}.public", identifier),
}
}

View File

@ -18,7 +18,7 @@ use crate::Flattener;
use itertools::Itertools;
use leo_ast::{
AccessExpression, CircuitExpression, CircuitMember, CircuitVariableInitializer, Expression,
AccessExpression, StructExpression, Member, StructVariableInitializer, Expression,
ExpressionReconstructor, MemberAccess, Statement, TernaryExpression, TupleExpression,
};
@ -27,7 +27,7 @@ use leo_ast::{
impl ExpressionReconstructor for Flattener<'_> {
type AdditionalOutput = Vec<Statement>;
/// Reconstructs ternary expressions over tuples and circuits, accumulating any statements that are generated.
/// Reconstructs ternary expressions over tuples and structs, accumulating any statements that are generated.
/// This is necessary because Aleo instructions does not support ternary expressions over composite data types.
/// For example, the ternary expression `cond ? (a, b) : (c, d)` is flattened into the following:
/// ```leo
@ -35,7 +35,7 @@ impl ExpressionReconstructor for Flattener<'_> {
/// let var$1 = cond ? b : d;
/// (var$0, var$1)
/// ```
/// For circuits, the ternary expression `cond ? a : b`, where `a` and `b` are both circuits `Foo { bar: u8, baz: u8 }`, is flattened into the following:
/// For structs, the ternary expression `cond ? a : b`, where `a` and `b` are both structs `Foo { bar: u8, baz: u8 }`, is flattened into the following:
/// ```leo
/// let var$0 = cond ? a.bar : b.bar;
/// let var$1 = cond ? a.baz : b.baz;
@ -85,31 +85,31 @@ impl ExpressionReconstructor for Flattener<'_> {
});
(tuple, statements)
}
// If both expressions are access expressions which themselves are circuits, construct ternary expression for nested circuit member.
// If both expressions are access expressions which themselves are structs, construct ternary expression for nested struct member.
(
Expression::Access(AccessExpression::Member(first)),
Expression::Access(AccessExpression::Member(second)),
) => {
// Lookup the circuit symbols associated with the expressions.
// Lookup the struct symbols associated with the expressions.
// TODO: Remove clones
let first_circuit_symbol =
self.lookup_circuit_symbol(&Expression::Access(AccessExpression::Member(first.clone())));
let second_circuit_symbol =
self.lookup_circuit_symbol(&Expression::Access(AccessExpression::Member(second.clone())));
let first_struct_symbol =
self.lookup_struct_symbol(&Expression::Access(AccessExpression::Member(first.clone())));
let second_struct_symbol =
self.lookup_struct_symbol(&Expression::Access(AccessExpression::Member(second.clone())));
match (first_circuit_symbol, second_circuit_symbol) {
(Some(first_circuit_symbol), Some(second_circuit_symbol)) => {
let first_member_circuit = self.symbol_table.lookup_circuit(first_circuit_symbol).unwrap();
let second_member_circuit = self.symbol_table.lookup_circuit(second_circuit_symbol).unwrap();
match (first_struct_symbol, second_struct_symbol) {
(Some(first_struct_symbol), Some(second_struct_symbol)) => {
let first_member_struct = self.symbol_table.lookup_struct(first_struct_symbol).unwrap();
let second_member_struct = self.symbol_table.lookup_struct(second_struct_symbol).unwrap();
// Note that type checking guarantees that both expressions have the same same type. This is a sanity check.
assert_eq!(first_member_circuit, second_member_circuit);
assert_eq!(first_member_struct, second_member_struct);
// For each circuit member, construct a new ternary expression.
let members = first_member_circuit
// For each struct member, construct a new ternary expression.
let members = first_member_struct
.members
.iter()
.map(|CircuitMember::CircuitVariable(id, _)| {
// Construct a new ternary expression for the circuit member.
.map(|Member::StructVariable(id, _)| {
// Construct a new ternary expression for the struct member.
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: input.condition.clone(),
if_true: Box::new(Expression::Access(AccessExpression::Member(MemberAccess {
@ -128,19 +128,19 @@ impl ExpressionReconstructor for Flattener<'_> {
// Accumulate any statements generated.
statements.extend(stmts);
// Create and accumulate an intermediate assignment statement for the ternary expression corresponding to the circuit member.
// Create and accumulate an intermediate assignment statement for the ternary expression corresponding to the struct member.
let (identifier, statement) = self.unique_simple_assign_statement(expression);
statements.push(statement);
CircuitVariableInitializer {
StructVariableInitializer {
identifier: *id,
expression: Some(Expression::Identifier(identifier)),
}
})
.collect();
let (expr, stmts) = self.reconstruct_circuit_init(CircuitExpression {
name: first_member_circuit.identifier,
let (expr, stmts) = self.reconstruct_struct_init(StructExpression {
name: first_member_struct.identifier,
members,
span: Default::default(),
});
@ -148,12 +148,12 @@ impl ExpressionReconstructor for Flattener<'_> {
// Accumulate any statements generated.
statements.extend(stmts);
// Create a new assignment statement for the circuit expression.
// Create a new assignment statement for the struct expression.
let (identifier, statement) = self.unique_simple_assign_statement(expr);
// Mark the lhs of the assignment as a circuit.
self.circuits
.insert(identifier.name, first_member_circuit.identifier.name);
// Mark the lhs of the assignment as a struct.
self.structs
.insert(identifier.name, first_member_struct.identifier.name);
statements.push(statement);
@ -185,27 +185,27 @@ impl ExpressionReconstructor for Flattener<'_> {
}
}
}
// If both expressions are identifiers which are circuits, construct ternary expression for each of the members and a circuit expression for the result.
// If both expressions are identifiers which are structs, construct ternary expression for each of the members and a struct expression for the result.
(Expression::Identifier(first), Expression::Identifier(second))
if self.circuits.contains_key(&first.name) && self.circuits.contains_key(&second.name) =>
if self.structs.contains_key(&first.name) && self.structs.contains_key(&second.name) =>
{
let first_circuit = self
let first_struct = self
.symbol_table
.lookup_circuit(*self.circuits.get(&first.name).unwrap())
.lookup_struct(*self.structs.get(&first.name).unwrap())
.unwrap();
let second_circuit = self
let second_struct = self
.symbol_table
.lookup_circuit(*self.circuits.get(&second.name).unwrap())
.lookup_struct(*self.structs.get(&second.name).unwrap())
.unwrap();
// Note that type checking guarantees that both expressions have the same same type. This is a sanity check.
assert_eq!(first_circuit, second_circuit);
assert_eq!(first_struct, second_struct);
// For each circuit member, construct a new ternary expression.
let members = first_circuit
// For each struct member, construct a new ternary expression.
let members = first_struct
.members
.iter()
.map(|CircuitMember::CircuitVariable(id, _)| {
// Construct a new ternary expression for the circuit member.
.map(|Member::StructVariable(id, _)| {
// Construct a new ternary expression for the struct member.
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: input.condition.clone(),
if_true: Box::new(Expression::Access(AccessExpression::Member(MemberAccess {
@ -224,19 +224,19 @@ impl ExpressionReconstructor for Flattener<'_> {
// Accumulate any statements generated.
statements.extend(stmts);
// Create and accumulate an intermediate assignment statement for the ternary expression corresponding to the circuit member.
// Create and accumulate an intermediate assignment statement for the ternary expression corresponding to the struct member.
let (identifier, statement) = self.unique_simple_assign_statement(expression);
statements.push(statement);
CircuitVariableInitializer {
StructVariableInitializer {
identifier: *id,
expression: Some(Expression::Identifier(identifier)),
}
})
.collect();
let (expr, stmts) = self.reconstruct_circuit_init(CircuitExpression {
name: first_circuit.identifier,
let (expr, stmts) = self.reconstruct_struct_init(StructExpression {
name: first_struct.identifier,
members,
span: Default::default(),
});
@ -244,11 +244,11 @@ impl ExpressionReconstructor for Flattener<'_> {
// Accumulate any statements generated.
statements.extend(stmts);
// Create a new assignment statement for the circuit expression.
// Create a new assignment statement for the struct expression.
let (identifier, statement) = self.unique_simple_assign_statement(expr);
// Mark the lhs of the assignment as a circuit.
self.circuits.insert(identifier.name, first_circuit.identifier.name);
// Mark the lhs of the assignment as a struct.
self.structs.insert(identifier.name, first_struct.identifier.name);
statements.push(statement);

View File

@ -27,11 +27,11 @@ impl ProgramReconstructor for Flattener<'_> {
// First, flatten the finalize block. This allows us to initialize self.finalizes correctly.
// Note that this is safe since the finalize block is independent of the function body.
let finalize = function.finalize.map(|finalize| {
// Initialize `self.circuits` with the finalize's input as necessary.
self.circuits = Default::default();
// Initialize `self.structs` with the finalize's input as necessary.
self.structs = Default::default();
for input in &finalize.input {
if let Type::Identifier(circuit_name) = input.type_() {
self.circuits.insert(input.identifier().name, circuit_name.name);
if let Type::Identifier(struct_name) = input.type_() {
self.structs.insert(input.identifier().name, struct_name.name);
}
}
@ -68,11 +68,11 @@ impl ProgramReconstructor for Flattener<'_> {
}
});
// Initialize `self.circuits` with the function's input as necessary.
self.circuits = Default::default();
// Initialize `self.structs` with the function's input as necessary.
self.structs = Default::default();
for input in &function.input {
if let Type::Identifier(circuit_name) = input.type_() {
self.circuits.insert(input.identifier().name, circuit_name.name);
if let Type::Identifier(struct_name) = input.type_() {
self.structs.insert(input.identifier().name, struct_name.name);
}
}

View File

@ -24,8 +24,8 @@ use leo_ast::{
impl StatementReconstructor for Flattener<'_> {
/// Flattens an assign statement, if necessary.
/// Marks variables as circuits as necessary.
/// Note that new statements are only produced if the right hand side is a ternary expression over circuits.
/// Marks variables as structs as necessary.
/// Note that new statements are only produced if the right hand side is a ternary expression over structs.
/// Otherwise, the statement is returned as is.
fn reconstruct_assign(&mut self, assign: AssignStatement) -> (Statement, Self::AdditionalOutput) {
let lhs = match assign.place {
@ -40,8 +40,8 @@ impl StatementReconstructor for Flattener<'_> {
value => (value, Default::default()),
};
// Update the `self.circuits` if the rhs is a circuit.
self.update_circuits(&lhs, &value);
// Update the `self.structs` if the rhs is a struct.
self.update_structs(&lhs, &value);
(
Statement::Assign(Box::new(AssignStatement {

View File

@ -17,7 +17,7 @@
use crate::{Assigner, SymbolTable};
use leo_ast::{
AccessExpression, CircuitMember, Expression, ExpressionReconstructor, Identifier, Statement, TernaryExpression,
AccessExpression, Member, Expression, ExpressionReconstructor, Identifier, Statement, TernaryExpression,
Type,
};
use leo_span::Symbol;
@ -26,12 +26,12 @@ use indexmap::IndexMap;
pub struct Flattener<'a> {
/// The symbol table associated with the program.
/// This table is used to lookup circuit definitions, when they are folded.
/// This table is used to lookup struct definitions, when they are folded.
pub(crate) symbol_table: &'a SymbolTable,
/// An struct used to construct (unique) assignment statements.
pub(crate) assigner: Assigner,
/// The set of variables that are circuits.
pub(crate) circuits: IndexMap<Symbol, Symbol>,
/// The set of variables that are structs.
pub(crate) structs: IndexMap<Symbol, Symbol>,
/// A stack of condition `Expression`s visited up to the current point in the AST.
pub(crate) condition_stack: Vec<Expression>,
/// A list containing tuples of guards and expressions associated `ReturnStatement`s.
@ -51,7 +51,7 @@ impl<'a> Flattener<'a> {
Self {
symbol_table,
assigner,
circuits: IndexMap::new(),
structs: IndexMap::new(),
condition_stack: Vec::new(),
returns: Vec::new(),
finalizes: Vec::new(),
@ -119,15 +119,15 @@ impl<'a> Flattener<'a> {
(expression, statements)
}
/// Looks up the name of the circuit associated with an identifier or access expression, if it exists.
pub(crate) fn lookup_circuit_symbol(&self, expression: &Expression) -> Option<Symbol> {
/// Looks up the name of the struct associated with an identifier or access expression, if it exists.
pub(crate) fn lookup_struct_symbol(&self, expression: &Expression) -> Option<Symbol> {
match expression {
Expression::Identifier(identifier) => self.circuits.get(&identifier.name).copied(),
Expression::Identifier(identifier) => self.structs.get(&identifier.name).copied(),
Expression::Access(AccessExpression::Member(access)) => {
// The inner expression of an access expression is either an identifier or another access expression.
let name = self.lookup_circuit_symbol(&access.inner).unwrap();
let circuit = self.symbol_table.lookup_circuit(name).unwrap();
let CircuitMember::CircuitVariable(_, member_type) = circuit
let name = self.lookup_struct_symbol(&access.inner).unwrap();
let struct_ = self.symbol_table.lookup_struct(name).unwrap();
let Member::StructVariable(_, member_type) = struct_
.members
.iter()
.find(|member| member.name() == access.name.name)
@ -141,38 +141,38 @@ impl<'a> Flattener<'a> {
}
}
/// Updates `self.circuits` for new assignment statements.
/// Updates `self.structs` for new assignment statements.
/// Expects the left hand side of the assignment to be an identifier.
pub(crate) fn update_circuits(&mut self, lhs: &Identifier, rhs: &Expression) {
pub(crate) fn update_structs(&mut self, lhs: &Identifier, rhs: &Expression) {
match rhs {
Expression::Circuit(rhs) => {
self.circuits.insert(lhs.name, rhs.name.name);
Expression::Struct(rhs) => {
self.structs.insert(lhs.name, rhs.name.name);
}
// If the rhs of the assignment is an identifier that is a circuit, add it to `self.circuits`.
Expression::Identifier(rhs) if self.circuits.contains_key(&rhs.name) => {
// If the rhs of the assignment is an identifier that is a struct, add it to `self.structs`.
Expression::Identifier(rhs) if self.structs.contains_key(&rhs.name) => {
// Note that this unwrap is safe because we just checked that the key exists.
self.circuits.insert(lhs.name, *self.circuits.get(&rhs.name).unwrap());
self.structs.insert(lhs.name, *self.structs.get(&rhs.name).unwrap());
}
// Otherwise, do nothing.
_ => (),
}
}
/// A wrapper around `assigner.unique_simple_assign_statement` that updates `self.circuits`.
/// A wrapper around `assigner.unique_simple_assign_statement` that updates `self.structs`.
pub(crate) fn unique_simple_assign_statement(&mut self, expr: Expression) -> (Identifier, Statement) {
let (place, statement) = self.assigner.unique_simple_assign_statement(expr);
match &statement {
Statement::Assign(assign) => {
self.update_circuits(&place, &assign.value);
self.update_structs(&place, &assign.value);
}
_ => unreachable!("`assigner.unique_simple_assign_statement` always returns an assignment statement."),
}
(place, statement)
}
/// A wrapper around `assigner.simple_assign_statement` that updates `self.circuits`.
/// A wrapper around `assigner.simple_assign_statement` that updates `self.structs`.
pub(crate) fn simple_assign_statement(&mut self, lhs: Identifier, rhs: Expression) -> Statement {
self.update_circuits(&lhs, &rhs);
self.update_structs(&lhs, &rhs);
self.assigner.simple_assign_statement(lhs, rhs)
}
}

View File

@ -17,8 +17,8 @@
use crate::StaticSingleAssigner;
use leo_ast::{
AccessExpression, AssociatedFunction, BinaryExpression, CallExpression, CircuitExpression,
CircuitVariableInitializer, Expression, ExpressionConsumer, Identifier, Literal, MemberAccess, Statement,
AccessExpression, AssociatedFunction, BinaryExpression, CallExpression, StructExpression,
StructVariableInitializer, Expression, ExpressionConsumer, Identifier, Literal, MemberAccess, Statement,
TernaryExpression, TupleAccess, TupleExpression, UnaryExpression,
};
use leo_span::sym;
@ -141,8 +141,8 @@ impl ExpressionConsumer for StaticSingleAssigner {
(Expression::Identifier(place), statements)
}
/// Consumes a circuit initialization expression with renamed variables, accumulating any statements that are generated.
fn consume_circuit_init(&mut self, input: CircuitExpression) -> Self::Output {
/// Consumes a struct initialization expression with renamed variables, accumulating any statements that are generated.
fn consume_struct_init(&mut self, input: StructExpression) -> Self::Output {
let mut statements = Vec::new();
// Process the members, accumulating any statements produced.
@ -151,10 +151,10 @@ impl ExpressionConsumer for StaticSingleAssigner {
.into_iter()
.map(|arg| {
let (expression, mut stmts) = match &arg.expression.is_some() {
// If the expression is None, then `arg` is a `CircuitVariableInitializer` of the form `<id>,`.
// If the expression is None, then `arg` is a `StructVariableInitializer` of the form `<id>,`.
// In this case, we must consume the identifier and produce an initializer of the form `<id>: <renamed_id>`.
false => self.consume_identifier(arg.identifier),
// If expression is `Some(..)`, then `arg is a `CircuitVariableInitializer` of the form `<id>: <expr>,`.
// If expression is `Some(..)`, then `arg is a `StructVariableInitializer` of the form `<id>: <expr>,`.
// In this case, we must consume the expression.
true => self.consume_expression(arg.expression.unwrap()),
};
@ -162,17 +162,17 @@ impl ExpressionConsumer for StaticSingleAssigner {
statements.append(&mut stmts);
// Return the new member.
CircuitVariableInitializer {
StructVariableInitializer {
identifier: arg.identifier,
expression: Some(expression),
}
})
.collect();
// Construct and accumulate a new assignment statement for the circuit expression.
// Construct and accumulate a new assignment statement for the struct expression.
let (place, statement) = self
.assigner
.unique_simple_assign_statement(Expression::Circuit(CircuitExpression {
.unique_simple_assign_statement(Expression::Struct(StructExpression {
name: input.name,
span: input.span,
members,

View File

@ -102,7 +102,7 @@ impl ProgramConsumer for StaticSingleAssigner {
.into_iter()
.map(|(i, f)| (i, self.consume_function(f)))
.collect(),
circuits: input.circuits,
structs: input.structs,
mappings: input.mappings,
}
}

View File

@ -20,7 +20,7 @@ use leo_errors::emitter::Handler;
use crate::{SymbolTable, VariableSymbol, VariableType};
/// A compiler pass during which the `SymbolTable` is created.
/// Note that this pass only creates the initial entries for functions and circuits.
/// Note that this pass only creates the initial entries for functions, structs, and records.
/// The table is populated further during the type checking pass.
pub struct CreateSymbolTable<'a> {
/// The `SymbolTable` constructed by this compiler pass.
@ -50,8 +50,8 @@ impl<'a> ProgramVisitor<'a> for CreateSymbolTable<'a> {
self.visit_program(input)
}
fn visit_circuit(&mut self, input: &'a Circuit) {
if let Err(err) = self.symbol_table.insert_circuit(input.name(), input) {
fn visit_struct(&mut self, input: &'a Struct) {
if let Err(err) = self.symbol_table.insert_struct(input.name(), input) {
self.handler.emit_err(err);
}
}

View File

@ -16,7 +16,7 @@
use std::cell::RefCell;
use leo_ast::{Circuit, Function};
use leo_ast::{Struct, Function};
use leo_errors::{AstError, Result};
use leo_span::{Span, Symbol};
@ -32,9 +32,9 @@ pub struct SymbolTable {
/// Functions represents the name of each function mapped to the AST's function definition.
/// This field is populated at a first pass.
pub functions: IndexMap<Symbol, FunctionSymbol>,
/// Maps circuit names to circuit definitions.
/// Maps struct names to struct definitions.
/// This field is populated at a first pass.
pub circuits: IndexMap<Symbol, Circuit>,
pub structs: IndexMap<Symbol, Struct>,
/// The variables defined in a scope.
/// This field is populated as necessary.
pub(crate) variables: IndexMap<Symbol, VariableSymbol>,
@ -52,10 +52,10 @@ impl SymbolTable {
Err(AstError::shadowed_variable(symbol, span).into())
} else if self.functions.contains_key(&symbol) {
Err(AstError::shadowed_function(symbol, span).into())
} else if let Some(existing) = self.circuits.get(&symbol) {
} else if let Some(existing) = self.structs.get(&symbol) {
match existing.is_record {
true => Err(AstError::shadowed_record(symbol, span).into()),
false => Err(AstError::shadowed_circuit(symbol, span).into()),
false => Err(AstError::shadowed_struct(symbol, span).into()),
}
} else if let Some(parent) = self.parent.as_ref() {
parent.check_shadowing(symbol, span)
@ -81,10 +81,10 @@ impl SymbolTable {
Ok(())
}
/// Inserts a circuit into the symbol table.
pub fn insert_circuit(&mut self, symbol: Symbol, insert: &Circuit) -> Result<()> {
/// Inserts a struct into the symbol table.
pub fn insert_struct(&mut self, symbol: Symbol, insert: &Struct) -> Result<()> {
self.check_shadowing(symbol, insert.span)?;
self.circuits.insert(symbol, insert.clone());
self.structs.insert(symbol, insert.clone());
Ok(())
}
@ -112,12 +112,12 @@ impl SymbolTable {
}
}
/// Attempts to lookup a circuit in the symbol table.
pub fn lookup_circuit(&self, symbol: Symbol) -> Option<&Circuit> {
if let Some(circ) = self.circuits.get(&symbol) {
Some(circ)
/// Attempts to lookup a struct in the symbol table.
pub fn lookup_struct(&self, symbol: Symbol) -> Option<&Struct> {
if let Some(struct_) = self.structs.get(&symbol) {
Some(struct_)
} else if let Some(parent) = self.parent.as_ref() {
parent.lookup_circuit(symbol)
parent.lookup_struct(symbol)
} else {
None
}

View File

@ -47,8 +47,8 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
fn visit_access(&mut self, input: &'a AccessExpression, expected: &Self::AdditionalInput) -> Self::Output {
match input {
AccessExpression::AssociatedFunction(access) => {
// Check core circuit name and function.
if let Some(core_instruction) = self.check_core_circuit_call(&access.ty, &access.name) {
// Check core struct name and function.
if let Some(core_instruction) = self.check_core_function_call(&access.ty, &access.name) {
// Check num input arguments.
if core_instruction.num_args() != access.args.len() {
// TODO: Better error messages.
@ -88,7 +88,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
// Check return type.
return Some(self.assert_and_return_type(core_instruction.return_type(), expected, access.span()));
} else {
self.emit_err(TypeCheckerError::invalid_core_circuit_call(access, access.span()));
self.emit_err(TypeCheckerError::invalid_core_function_call(access, access.span()));
}
}
AccessExpression::Tuple(access) => {
@ -121,7 +121,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
self.emit_err(TypeCheckerError::type_should_be(type_, "tuple", access.span()));
}
}
self.emit_err(TypeCheckerError::invalid_core_circuit_call(access, access.span()));
self.emit_err(TypeCheckerError::invalid_core_function_call(access, access.span()));
}
}
AccessExpression::Member(access) => {
@ -134,25 +134,25 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
}
},
_ => {
// Check that the type of `inner` in `inner.name` is a circuit.
// Check that the type of `inner` in `inner.name` is a struct.
match self.visit_expression(&access.inner, &None) {
Some(Type::Identifier(identifier)) => {
// Retrieve the circuit definition associated with `identifier`.
let circ = self.symbol_table.borrow().lookup_circuit(identifier.name).cloned();
if let Some(circ) = circ {
// Check that `access.name` is a member of the circuit.
match circ
// Retrieve the struct definition associated with `identifier`.
let struct_ = self.symbol_table.borrow().lookup_struct(identifier.name).cloned();
if let Some(struct_) = struct_ {
// Check that `access.name` is a member of the struct.
match struct_
.members
.iter()
.find(|circuit_member| circuit_member.name() == access.name.name)
.find(|member| member.name() == access.name.name)
{
// Case where `access.name` is a member of the circuit.
Some(CircuitMember::CircuitVariable(_, type_)) => return Some(type_.clone()),
// Case where `access.name` is not a member of the circuit.
// Case where `access.name` is a member of the struct.
Some(Member::StructVariable(_, type_)) => return Some(type_.clone()),
// Case where `access.name` is not a member of the struct.
None => {
self.emit_err(TypeCheckerError::invalid_circuit_variable(
self.emit_err(TypeCheckerError::invalid_struct_variable(
access.name,
&circ,
&struct_,
access.name.span(),
));
}
@ -162,7 +162,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
}
}
Some(type_) => {
self.emit_err(TypeCheckerError::type_should_be(type_, "circuit", access.inner.span()));
self.emit_err(TypeCheckerError::type_should_be(type_, "struct", access.inner.span()));
}
None => {
self.emit_err(TypeCheckerError::could_not_determine_type(
@ -470,33 +470,33 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
}
}
fn visit_circuit_init(&mut self, input: &'a CircuitExpression, additional: &Self::AdditionalInput) -> Self::Output {
let circ = self.symbol_table.borrow().lookup_circuit(input.name.name).cloned();
if let Some(circ) = circ {
// Check circuit type name.
let ret = self.check_expected_circuit(circ.identifier, additional, input.name.span());
fn visit_struct_init(&mut self, input: &'a StructExpression, additional: &Self::AdditionalInput) -> Self::Output {
let struct_ = self.symbol_table.borrow().lookup_struct(input.name.name).cloned();
if let Some(struct_) = struct_ {
// Check struct type name.
let ret = self.check_expected_struct(struct_.identifier, additional, input.name.span());
// Check number of circuit members.
if circ.members.len() != input.members.len() {
self.emit_err(TypeCheckerError::incorrect_num_circuit_members(
circ.members.len(),
// Check number of struct members.
if struct_.members.len() != input.members.len() {
self.emit_err(TypeCheckerError::incorrect_num_struct_members(
struct_.members.len(),
input.members.len(),
input.span(),
));
}
// Check circuit member types.
circ.members
// Check struct member types.
struct_.members
.iter()
.for_each(|CircuitMember::CircuitVariable(name, ty)| {
// Lookup circuit variable name.
.for_each(|Member::StructVariable(name, ty)| {
// Lookup struct variable name.
if let Some(actual) = input.members.iter().find(|member| member.identifier.name == name.name) {
if let Some(expr) = &actual.expression {
self.visit_expression(expr, &Some(ty.clone()));
}
} else {
self.emit_err(TypeCheckerError::missing_circuit_member(
circ.identifier,
self.emit_err(TypeCheckerError::missing_struct_member(
struct_.identifier,
name,
input.span(),
));
@ -506,7 +506,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
Some(ret)
} else {
self.emit_err(TypeCheckerError::unknown_sym(
"circuit",
"struct",
input.name.name,
input.name.span(),
));

View File

@ -26,13 +26,13 @@ use std::collections::HashSet;
// TODO: Generally, cleanup tyc logic.
impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
fn visit_circuit(&mut self, input: &'a Circuit) {
// Check for conflicting circuit/record member names.
fn visit_struct(&mut self, input: &'a Struct) {
// Check for conflicting struct/record member names.
let mut used = HashSet::new();
if !input
.members
.iter()
.all(|CircuitMember::CircuitVariable(ident, type_)| {
.all(|Member::StructVariable(ident, type_)| {
// TODO: Better spans.
// Check that the member types are valid.
self.assert_type_is_valid(input.span, type_);
@ -42,7 +42,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
self.emit_err(if input.is_record {
TypeCheckerError::duplicate_record_variable(input.name(), input.span())
} else {
TypeCheckerError::duplicate_circuit_member(input.name(), input.span())
TypeCheckerError::duplicate_struct_member(input.name(), input.span())
});
}
@ -51,7 +51,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
let check_has_field = |need, expected_ty: Type| match input
.members
.iter()
.find_map(|CircuitMember::CircuitVariable(v, t)| (v.name == need).then_some((v, t)))
.find_map(|Member::StructVariable(v, t)| (v.name == need).then_some((v, t)))
{
Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type!
Some((field, _)) => {
@ -73,7 +73,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
check_has_field(sym::gates, Type::Integer(IntegerType::U64));
}
for CircuitMember::CircuitVariable(v, type_) in input.members.iter() {
for Member::StructVariable(v, type_) in input.members.iter() {
// Ensure there are no tuple typed members.
self.assert_not_tuple(v.span, type_);
// Ensure that there are no record members.

View File

@ -322,35 +322,35 @@ impl<'a> TypeChecker<'a> {
)
}
/// Emits an error if the `circuit` is not a core library circuit.
/// Emits an error if the `function` is not supported by the circuit.
pub(crate) fn check_core_circuit_call(&self, circuit: &Type, function: &Identifier) -> Option<CoreInstruction> {
if let Type::Identifier(ident) = circuit {
// Lookup core circuit
/// Emits an error if the `struct` is not a core library struct.
/// Emits an error if the `function` is not supported by the struct.
pub(crate) fn check_core_function_call(&self, struct_: &Type, function: &Identifier) -> Option<CoreInstruction> {
if let Type::Identifier(ident) = struct_ {
// Lookup core struct
match CoreInstruction::from_symbols(ident.name, function.name) {
None => {
// Not a core library circuit.
self.emit_err(TypeCheckerError::invalid_core_instruction(
// Not a core library struct.
self.emit_err(TypeCheckerError::invalid_core_function(
ident.name,
function.name,
ident.span(),
));
}
Some(core_circuit) => return Some(core_circuit),
Some(core_instruction) => return Some(core_instruction),
}
}
None
}
/// Returns the `circuit` type and emits an error if the `expected` type does not match.
pub(crate) fn check_expected_circuit(&mut self, circuit: Identifier, expected: &Option<Type>, span: Span) -> Type {
/// Returns the `struct` type and emits an error if the `expected` type does not match.
pub(crate) fn check_expected_struct(&mut self, struct_: Identifier, expected: &Option<Type>, span: Span) -> Type {
if let Some(Type::Identifier(expected)) = expected {
if !circuit.matches(expected) {
self.emit_err(TypeCheckerError::type_should_be(circuit.name, expected.name, span));
if !struct_.matches(expected) {
self.emit_err(TypeCheckerError::type_should_be(struct_.name, expected.name, span));
}
}
Type::Identifier(circuit)
Type::Identifier(struct_)
}
/// Emits an error if the type is a tuple.
@ -360,17 +360,17 @@ impl<'a> TypeChecker<'a> {
}
}
/// Emits an error if the circuit member is a record type.
/// Emits an error if the struct member is a record type.
pub(crate) fn assert_member_is_not_record(&self, span: Span, parent: Symbol, type_: &Type) {
match type_ {
Type::Identifier(identifier)
if self
.symbol_table
.borrow()
.lookup_circuit(identifier.name)
.map_or(false, |circuit| circuit.is_record) =>
.lookup_struct(identifier.name)
.map_or(false, |struct_| struct_.is_record) =>
{
self.emit_err(TypeCheckerError::circuit_or_record_cannot_contain_record(
self.emit_err(TypeCheckerError::struct_or_record_cannot_contain_record(
parent,
identifier.name,
span,
@ -389,7 +389,7 @@ impl<'a> TypeChecker<'a> {
pub(crate) fn assert_type_is_valid(&self, span: Span, type_: &Type) {
match type_ {
// Check that the named composite type has been defined.
Type::Identifier(identifier) if self.symbol_table.borrow().lookup_circuit(identifier.name).is_none() => {
Type::Identifier(identifier) if self.symbol_table.borrow().lookup_struct(identifier.name).is_none() => {
self.emit_err(TypeCheckerError::undefined_type(identifier.name, span));
}
// Check that the constituent types of the tuple are valid.

View File

@ -138,7 +138,7 @@ symbols! {
sub_wrapped,
xor,
// core circuits
// core functions
BHP256,
BHP512,
BHP768,

View File

@ -17,7 +17,7 @@
use crate::commands::ALEO_CLI_COMMAND;
use crate::{commands::Command, context::Context};
use leo_ast::Circuit;
use leo_ast::Struct;
use leo_compiler::{Compiler, InputAst, OutputOptions};
use leo_errors::{CliError, CompilerError, PackageError, Result};
use leo_package::source::{SourceDirectory, MAIN_FILENAME};
@ -90,7 +90,7 @@ pub struct Build {
impl Command for Build {
type Input = ();
type Output = (Option<InputAst>, IndexMap<Symbol, Circuit>);
type Output = (Option<InputAst>, IndexMap<Symbol, Struct>);
fn log_span(&self) -> Span {
tracing::span!(tracing::Level::INFO, "Leo")
@ -119,12 +119,12 @@ impl Command for Build {
// Fetch paths to all .leo files in the source directory.
let source_files = SourceDirectory::files(&package_path)?;
// Store all circuits declarations made in the source files.
let mut circuits = IndexMap::new();
// Store all struct declarations made in the source files.
let mut structs = IndexMap::new();
// Compile all .leo files into .aleo files.
for file_path in source_files.into_iter() {
circuits.extend(compile_leo_file(
structs.extend(compile_leo_file(
file_path,
&package_path,
&package_name,
@ -144,7 +144,7 @@ impl Command for Build {
// Compile all .leo files into .aleo files.
for file_path in import_files.into_iter() {
circuits.extend(compile_leo_file(
structs.extend(compile_leo_file(
file_path,
&package_path,
&package_name,
@ -188,7 +188,7 @@ impl Command for Build {
// Log the result of the build
tracing::info!("{}", result);
Ok((input_ast, circuits))
Ok((input_ast, structs))
}
}
@ -200,7 +200,7 @@ fn compile_leo_file(
build: &Path,
handler: &Handler,
options: BuildOptions,
) -> Result<IndexMap<Symbol, Circuit>> {
) -> Result<IndexMap<Symbol, Struct>> {
// Construct the Leo file name with extension `foo.leo`.
let file_name = file_path
.file_name()
@ -279,5 +279,5 @@ fn compile_leo_file(
// Log the build as successful.
tracing::info!("Compiled '{}' into Aleo instructions", file_name,);
Ok(symbol_table.circuits)
Ok(symbol_table.structs)
}

View File

@ -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/>.
//! The serialized circuit output file.
//! The serialized struct output file.
use crate::outputs::OUTPUTS_DIRECTORY_NAME;
use leo_errors::{PackageError, Result};
@ -69,7 +69,7 @@ impl SnapshotFile {
path.exists()
}
/// Reads the serialized circuit from the given file path if it exists.
/// Reads the serialized struct from the given file path if it exists.
pub fn read_from(&self, path: &Path) -> Result<String> {
let path = self.snapshot_file_path(path);
@ -79,7 +79,7 @@ impl SnapshotFile {
Ok(result)
}
/// Removes the serialized circuit at the given path if it exists. Returns `true` on success,
/// Removes the serialized struct at the given path if it exists. Returns `true` on success,
/// `false` if the file doesn't exist, and `Error` if the file system fails during operation.
pub fn remove(&self, path: &Path) -> Result<bool> {
let path = self.snapshot_file_path(path);

View File

@ -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/>.
//! The serialized circuit output file.
//! The serialized struct output file.
use crate::outputs::OUTPUTS_DIRECTORY_NAME;
use leo_errors::{PackageError, Result};
@ -48,7 +48,7 @@ impl CircuitFile {
path.exists()
}
/// Reads the serialized circuit from the given file path if it exists.
/// Reads the serialized struct from the given file path if it exists.
pub fn read_from(&self, path: &Path) -> Result<String> {
let path = self.setup_file_path(path);
@ -57,7 +57,7 @@ impl CircuitFile {
Ok(string)
}
/// Writes the given serialized circuit to a file.
/// Writes the given serialized struct to a file.
pub fn write_to(&self, path: &Path, circuit: String) -> Result<()> {
let path = self.setup_file_path(path);
let mut file = File::create(&path).map_err(PackageError::io_error_circuit_file)?;
@ -67,7 +67,7 @@ impl CircuitFile {
Ok(())
}
/// Removes the serialized circuit at the given path if it exists. Returns `true` on success,
/// Removes the serialized struct at the given path if it exists. Returns `true` on success,
/// `false` if the file doesn't exist, and `Error` if the file system fails during operation.
pub fn remove(&self, path: &Path) -> Result<bool> {
let path = self.setup_file_path(path);