Some cleanup

This commit is contained in:
Pranav Gaddamadugu 2022-09-30 12:19:40 -07:00
parent c551179b42
commit eb8366badc
9 changed files with 40 additions and 34 deletions

View File

@ -60,6 +60,7 @@ impl ParserContext<'_> {
let (id, function) = self.parse_function()?; let (id, function) = self.parse_function()?;
functions.insert(id, function); functions.insert(id, function);
} }
Token::Circuit => return Err(ParserError::circuit_is_deprecated(self.token.span).into()),
_ => return Err(Self::unexpected_item(&self.token).into()), _ => return Err(Self::unexpected_item(&self.token).into()),
} }
} }
@ -173,9 +174,9 @@ impl ParserContext<'_> {
/// Returns a [`Member`] AST node if the next tokens represent a struct member variable. /// Returns a [`Member`] AST node if the next tokens represent a struct member variable.
fn parse_member_variable_declaration(&mut self) -> Result<Member> { fn parse_member_variable_declaration(&mut self) -> Result<Member> {
let (name, type_) = self.parse_typed_ident()?; let (identifier, type_) = self.parse_typed_ident()?;
Ok(Member::StructVariable(name, type_)) Ok(Member { identifier, type_ })
} }
/// Parses a struct or record definition, e.g., `struct Foo { ... }` or `record Foo { ... }`. /// Parses a struct or record definition, e.g., `struct Foo { ... }` or `record Foo { ... }`.

View File

@ -396,6 +396,7 @@ impl Token {
"address" => Token::Address, "address" => Token::Address,
"async" => Token::Async, "async" => Token::Async,
"bool" => Token::Bool, "bool" => Token::Bool,
"circuit" => Token::Circuit,
"console" => Token::Console, "console" => Token::Console,
"const" => Token::Const, "const" => Token::Const,
"constant" => Token::Constant, "constant" => Token::Constant,

View File

@ -324,6 +324,7 @@ impl fmt::Display for Token {
Record => write!(f, "record"), Record => write!(f, "record"),
Async => write!(f, "async"), Async => write!(f, "async"),
Circuit => write!(f, "circuit"),
Console => write!(f, "console"), Console => write!(f, "console"),
Const => write!(f, "const"), Const => write!(f, "const"),
Constant => write!(f, "constant"), Constant => write!(f, "constant"),

View File

@ -16,7 +16,7 @@
use crate::CodeGenerator; use crate::CodeGenerator;
use leo_ast::{functions, Function, Identifier, Mapping, Member, Mode, Program, Struct, Type}; use leo_ast::{functions, Function, Identifier, Mapping, Mode, Program, Struct, Type};
use indexmap::IndexMap; use indexmap::IndexMap;
use itertools::Itertools; use itertools::Itertools;
@ -131,11 +131,7 @@ impl<'a> CodeGenerator<'a> {
// Construct and append the record variables. // Construct and append the record variables.
for var in struct_.members.iter() { for var in struct_.members.iter() {
let (name, type_) = match var { writeln!(output_string, " {} as {};", var.identifier, var.type_,).expect("failed to write to string");
Member::StructVariable(name, type_) => (name, type_),
};
writeln!(output_string, " {} as {};", name, type_,).expect("failed to write to string");
} }
output_string output_string
@ -150,14 +146,10 @@ impl<'a> CodeGenerator<'a> {
// Construct and append the record variables. // Construct and append the record variables.
for var in record.members.iter() { for var in record.members.iter() {
let (name, type_) = match var {
Member::StructVariable(name, type_) => (name, type_),
};
writeln!( writeln!(
output_string, output_string,
" {} as {}.private;", // todo: CAUTION private record variables only. " {} as {}.private;", // todo: CAUTION private record variables only.
name, type_, var.identifier, var.type_,
) )
.expect("failed to write to string"); .expect("failed to write to string");
} }

View File

@ -108,18 +108,18 @@ impl ExpressionReconstructor for Flattener<'_> {
let members = first_member_struct let members = first_member_struct
.members .members
.iter() .iter()
.map(|Member::StructVariable(id, _)| { .map(|Member { identifier, .. }| {
// Construct a new ternary expression for the struct member. // Construct a new ternary expression for the struct member.
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: input.condition.clone(), condition: input.condition.clone(),
if_true: Box::new(Expression::Access(AccessExpression::Member(MemberAccess { if_true: Box::new(Expression::Access(AccessExpression::Member(MemberAccess {
inner: Box::new(Expression::Access(AccessExpression::Member(first.clone()))), inner: Box::new(Expression::Access(AccessExpression::Member(first.clone()))),
name: *id, name: *identifier,
span: Default::default(), span: Default::default(),
}))), }))),
if_false: Box::new(Expression::Access(AccessExpression::Member(MemberAccess { if_false: Box::new(Expression::Access(AccessExpression::Member(MemberAccess {
inner: Box::new(Expression::Access(AccessExpression::Member(second.clone()))), inner: Box::new(Expression::Access(AccessExpression::Member(second.clone()))),
name: *id, name: *identifier,
span: Default::default(), span: Default::default(),
}))), }))),
span: Default::default(), span: Default::default(),
@ -133,7 +133,7 @@ impl ExpressionReconstructor for Flattener<'_> {
statements.push(statement); statements.push(statement);
StructVariableInitializer { StructVariableInitializer {
identifier: *id, identifier,
expression: Some(Expression::Identifier(identifier)), expression: Some(Expression::Identifier(identifier)),
} }
}) })
@ -204,18 +204,18 @@ impl ExpressionReconstructor for Flattener<'_> {
let members = first_struct let members = first_struct
.members .members
.iter() .iter()
.map(|Member::StructVariable(id, _)| { .map(|Member { identifier, .. }| {
// Construct a new ternary expression for the struct member. // Construct a new ternary expression for the struct member.
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: input.condition.clone(), condition: input.condition.clone(),
if_true: Box::new(Expression::Access(AccessExpression::Member(MemberAccess { if_true: Box::new(Expression::Access(AccessExpression::Member(MemberAccess {
inner: Box::new(Expression::Identifier(first)), inner: Box::new(Expression::Identifier(first)),
name: *id, name: *identifier,
span: Default::default(), span: Default::default(),
}))), }))),
if_false: Box::new(Expression::Access(AccessExpression::Member(MemberAccess { if_false: Box::new(Expression::Access(AccessExpression::Member(MemberAccess {
inner: Box::new(Expression::Identifier(second)), inner: Box::new(Expression::Identifier(second)),
name: *id, name: *identifier,
span: Default::default(), span: Default::default(),
}))), }))),
span: Default::default(), span: Default::default(),
@ -229,7 +229,7 @@ impl ExpressionReconstructor for Flattener<'_> {
statements.push(statement); statements.push(statement);
StructVariableInitializer { StructVariableInitializer {
identifier: *id, identifier,
expression: Some(Expression::Identifier(identifier)), expression: Some(Expression::Identifier(identifier)),
} }
}) })

View File

@ -126,12 +126,12 @@ impl<'a> Flattener<'a> {
// The inner expression of an access expression is either an identifier or another access expression. // The inner expression of an access expression is either an identifier or another access expression.
let name = self.lookup_struct_symbol(&access.inner).unwrap(); let name = self.lookup_struct_symbol(&access.inner).unwrap();
let struct_ = self.symbol_table.lookup_struct(name).unwrap(); let struct_ = self.symbol_table.lookup_struct(name).unwrap();
let Member::StructVariable(_, member_type) = struct_ let Member { type_, .. } = struct_
.members .members
.iter() .iter()
.find(|member| member.name() == access.name.name) .find(|member| member.name() == access.name.name)
.unwrap(); .unwrap();
match member_type { match type_ {
Type::Identifier(identifier) => Some(identifier.name), Type::Identifier(identifier) => Some(identifier.name),
_ => None, _ => None,
} }

View File

@ -143,7 +143,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
// Check that `access.name` is a member of the struct. // Check that `access.name` is a member of the struct.
match struct_.members.iter().find(|member| member.name() == access.name.name) { match struct_.members.iter().find(|member| member.name() == access.name.name) {
// Case where `access.name` is a member of the struct. // Case where `access.name` is a member of the struct.
Some(Member::StructVariable(_, type_)) => return Some(type_.clone()), Some(Member { type_, .. }) => return Some(type_.clone()),
// Case where `access.name` is not a member of the struct. // Case where `access.name` is not a member of the struct.
None => { None => {
self.emit_err(TypeCheckerError::invalid_struct_variable( self.emit_err(TypeCheckerError::invalid_struct_variable(
@ -482,16 +482,20 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
} }
// Check struct member types. // Check struct member types.
struct_.members.iter().for_each(|Member::StructVariable(name, ty)| { struct_.members.iter().for_each(|Member { identifier, type_ }| {
// Lookup struct variable name. // Lookup struct variable name.
if let Some(actual) = input.members.iter().find(|member| member.identifier.name == name.name) { if let Some(actual) = input
.members
.iter()
.find(|member| member.identifier.name == identifier.name)
{
if let Some(expr) = &actual.expression { if let Some(expr) = &actual.expression {
self.visit_expression(expr, &Some(ty.clone())); self.visit_expression(expr, &Some(type_.clone()));
} }
} else { } else {
self.emit_err(TypeCheckerError::missing_struct_member( self.emit_err(TypeCheckerError::missing_struct_member(
struct_.identifier, struct_.identifier,
name, identifier,
input.span(), input.span(),
)); ));
}; };

View File

@ -29,11 +29,11 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
fn visit_struct(&mut self, input: &'a Struct) { fn visit_struct(&mut self, input: &'a Struct) {
// Check for conflicting struct/record member names. // Check for conflicting struct/record member names.
let mut used = HashSet::new(); let mut used = HashSet::new();
if !input.members.iter().all(|Member::StructVariable(ident, type_)| { if !input.members.iter().all(|Member { identifier, type_ }| {
// TODO: Better spans. // TODO: Better spans.
// Check that the member types are valid. // Check that the member types are valid.
self.assert_type_is_valid(input.span, type_); self.assert_type_is_valid(input.span, type_);
used.insert(ident.name) used.insert(identifier.name)
}) { }) {
self.emit_err(if input.is_record { self.emit_err(if input.is_record {
TypeCheckerError::duplicate_record_variable(input.name(), input.span()) TypeCheckerError::duplicate_record_variable(input.name(), input.span())
@ -47,7 +47,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
let check_has_field = |need, expected_ty: Type| match input let check_has_field = |need, expected_ty: Type| match input
.members .members
.iter() .iter()
.find_map(|Member::StructVariable(v, t)| (v.name == need).then_some((v, t))) .find_map(|Member { identifier, type_ }| (identifier.name == need).then_some((identifier, type_)))
{ {
Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type! Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type!
Some((field, _)) => { Some((field, _)) => {
@ -69,11 +69,11 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
check_has_field(sym::gates, Type::Integer(IntegerType::U64)); check_has_field(sym::gates, Type::Integer(IntegerType::U64));
} }
for Member::StructVariable(v, type_) in input.members.iter() { for Member { identifier, type_ } in input.members.iter() {
// Ensure there are no tuple typed members. // Ensure there are no tuple typed members.
self.assert_not_tuple(v.span, type_); self.assert_not_tuple(identifier.span, type_);
// Ensure that there are no record members. // Ensure that there are no record members.
self.assert_member_is_not_record(v.span, input.identifier.name, type_); self.assert_member_is_not_record(identifier.span, input.identifier.name, type_);
} }
} }

View File

@ -251,4 +251,11 @@ create_messages!(
msg: "A finalize statement must be preceded by the `async` keyword.", msg: "A finalize statement must be preceded by the `async` keyword.",
help: Some("Add the `async` keyword before the `finalize` keyword.".to_string()), help: Some("Add the `async` keyword before the `finalize` keyword.".to_string()),
} }
@formatted
circuit_is_deprecated {
args: (),
msg: "The keyword `circuit` is deprecated.",
help: Some("Use `struct` instead.".to_string()),
}
); );