Clippy + fmt

This commit is contained in:
Pranav Gaddamadugu 2023-11-22 17:34:20 -08:00
parent 1afa68a66e
commit afc953cd0b
28 changed files with 564 additions and 573 deletions

View File

@ -26,15 +26,16 @@ pub fn serialize<S: Serializer>(
imported_modules: &IndexMap<Vec<Symbol>, Program>,
serializer: S,
) -> Result<S::Ok, S::Error> {
let joined: IndexMap<String, Program> = with_session_globals(|s| {
imported_modules
.into_iter()
.map(|(package, program)| {
let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::<Vec<_>>();
(package.join("."), program.clone())
})
.collect()
});
let joined: IndexMap<String, Program> =
with_session_globals(|s| {
imported_modules
.into_iter()
.map(|(package, program)| {
let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::<Vec<_>>();
(package.join("."), program.clone())
})
.collect()
});
joined.serialize(serializer)
}

View File

@ -66,12 +66,9 @@ pub trait ExpressionReconstructor {
fn reconstruct_associated_constant(&mut self, input: AssociatedConstant) -> (Expression, Self::AdditionalOutput) {
(
Expression::Access(AccessExpression::AssociatedConstant(AssociatedConstant {
ty: input.ty,
name: input.name,
span: input.span,
id: input.id,
})),
Expression::Access(AccessExpression::AssociatedConstant(
AssociatedConstant { ty: input.ty, name: input.name, span: input.span, id: input.id }
)),
Default::default(),
)
}

View File

@ -244,12 +244,9 @@ impl<'a> Compiler<'a> {
/// Runs the destructuring pass.
pub fn destructuring_pass(&mut self) -> Result<()> {
self.ast = Destructurer::do_pass((
std::mem::take(&mut self.ast),
&self.type_table,
&self.node_builder,
&self.assigner,
))?;
self.ast = Destructurer::do_pass(
(std::mem::take(&mut self.ast), &self.type_table, &self.node_builder, &self.assigner)
)?;
if self.compiler_options.output.destructured_ast {
self.write_ast_to_json("destructured_ast.json")?;

View File

@ -51,9 +51,9 @@ impl Namespace for CompileNamespace {
fn run_test(&self, test: Test) -> Result<Value, String> {
let buf = BufferEmitter(Rc::default(), Rc::default());
let handler = Handler::new(Box::new(buf.clone()));
create_session_if_not_set_then(|_| {
run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string())
})
create_session_if_not_set_then(
|_| run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string())
)
}
}

View File

@ -58,9 +58,9 @@ impl Namespace for ExecuteNamespace {
fn run_test(&self, test: Test) -> Result<Value, String> {
let buf = BufferEmitter(Rc::default(), Rc::default());
let handler = Handler::new(Box::new(buf.clone()));
create_session_if_not_set_then(|_| {
run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string())
})
create_session_if_not_set_then(
|_| run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string())
)
}
}
@ -125,13 +125,13 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result<Va
let bytecode = handler.extend_if_error(compile_and_process(&mut parsed))?;
// Extract the cases from the test config.
let all_cases = test
.config
.extra
.get("cases")
.expect("An `Execute` config must have a `cases` field.")
.as_mapping()
.unwrap();
let all_cases =
test.config
.extra
.get("cases")
.expect("An `Execute` config must have a `cases` field.")
.as_mapping()
.unwrap();
// Initialize a map for the expected results.
let mut results = BTreeMap::new();

View File

@ -237,12 +237,9 @@ impl ParserContext<'_> {
if self.eat(&Token::As) {
let (type_, end_span) = self.parse_primitive_type()?;
let span = expr.span() + end_span;
expr = Expression::Cast(CastExpression {
expression: Box::new(expr),
type_,
span,
id: self.node_builder.next_id(),
});
expr = Expression::Cast(
CastExpression { expression: Box::new(expr), type_, span, id: self.node_builder.next_id() }
);
}
Ok(expr)
@ -328,12 +325,9 @@ impl ParserContext<'_> {
if let (true, Some(op)) = (args.is_empty(), UnaryOperation::from_symbol(method.name)) {
// Found an unary operator and the argument list is empty.
Ok(Expression::Unary(UnaryExpression {
span,
op,
receiver: Box::new(receiver),
id: self.node_builder.next_id(),
}))
Ok(Expression::Unary(
UnaryExpression { span, op, receiver: Box::new(receiver), id: self.node_builder.next_id() }
))
} else if let (1, Some(op)) = (args.len(), BinaryOperation::from_symbol(method.name)) {
// Found a binary operator and the argument list contains a single argument.
Ok(Expression::Binary(BinaryExpression {
@ -443,12 +437,10 @@ impl ParserContext<'_> {
if self.check_int() {
// Eat a tuple member access.
let (index, span) = self.eat_whole_number()?;
expr = Expression::Access(AccessExpression::Tuple(TupleAccess {
tuple: Box::new(expr),
index,
span,
id: self.node_builder.next_id(),
}))
expr =
Expression::Access(AccessExpression::Tuple(
TupleAccess { tuple: Box::new(expr), index, span, id: self.node_builder.next_id() }
))
} else if self.eat(&Token::Leo) {
// Eat an external function call.
self.eat(&Token::Div); // todo: Make `/` a more general token.
@ -627,14 +619,15 @@ impl ParserContext<'_> {
self.expect_identifier()?
};
let (expression, span) = if self.eat(&Token::Colon) {
// Parse individual struct variable declarations.
let expression = self.parse_expression()?;
let span = identifier.span + expression.span();
(Some(expression), span)
} else {
(None, identifier.span)
};
let (expression, span) =
if self.eat(&Token::Colon) {
// Parse individual struct variable declarations.
let expression = self.parse_expression()?;
let span = identifier.span + expression.span();
(Some(expression), span)
} else {
(None, identifier.span)
};
Ok(StructVariableInitializer { identifier, expression, id: self.node_builder.next_id(), span })
}
@ -685,11 +678,9 @@ impl ParserContext<'_> {
// Literal followed by `group`, e.g., `42group`.
Some(Token::Group) => {
assert_no_whitespace("group")?;
Expression::Literal(Literal::Group(Box::new(GroupLiteral::Single(
value,
full_span,
self.node_builder.next_id(),
))))
Expression::Literal(Literal::Group(Box::new(
GroupLiteral::Single(value, full_span, self.node_builder.next_id())
)))
}
// Literal followed by `scalar` e.g., `42scalar`.
Some(Token::Scalar) => {
@ -732,11 +723,9 @@ impl ParserContext<'_> {
Token::Block => {
Expression::Identifier(Identifier { name: sym::block, span, id: self.node_builder.next_id() })
}
t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier {
name: t.keyword_to_symbol().unwrap(),
span,
id: self.node_builder.next_id(),
}),
t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(
Identifier { name: t.keyword_to_symbol().unwrap(), span, id: self.node_builder.next_id() }
),
token => {
return Err(ParserError::unexpected_str(token, "expression", span).into());
}

View File

@ -325,13 +325,9 @@ impl ParserContext<'_> {
} else {
let type_ = self.parse_type()?.0;
Ok(functions::Input::Internal(FunctionInput {
identifier: name,
mode,
type_,
span: name.span,
id: self.node_builder.next_id(),
}))
Ok(functions::Input::Internal(
FunctionInput { identifier: name, mode, type_, span: name.span, id: self.node_builder.next_id() }
))
}
}
@ -420,56 +416,58 @@ impl ParserContext<'_> {
let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
// Parse return type.
let output = match self.eat(&Token::Arrow) {
false => vec![],
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_struct_construction = false;
output
}
};
let output =
match self.eat(&Token::Arrow) {
false => vec![],
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_struct_construction = false;
output
}
};
// Parse the function body.
let block = self.parse_block()?;
// Parse the `finalize` block if it exists.
let finalize = match self.eat(&Token::Finalize) {
false => None,
true => {
// Get starting span.
let start = self.prev_token.span;
let finalize =
match self.eat(&Token::Finalize) {
false => None,
true => {
// Get starting span.
let start = self.prev_token.span;
// Parse the identifier.
let identifier = self.expect_identifier()?;
// Parse the identifier.
let identifier = self.expect_identifier()?;
// Parse parameters.
let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
// Parse parameters.
let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
// Parse return type.
let output = match self.eat(&Token::Arrow) {
false => vec![],
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_struct_construction = false;
output
}
};
// Parse return type.
let output = match self.eat(&Token::Arrow) {
false => vec![],
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_struct_construction = false;
output
}
};
// Parse the finalize body.
let block = self.parse_block()?;
let span = start + block.span;
// Parse the finalize body.
let block = self.parse_block()?;
let span = start + block.span;
Some(Finalize::new(identifier, input, output, block, span, self.node_builder.next_id()))
}
};
Some(Finalize::new(identifier, input, output, block, span, self.node_builder.next_id()))
}
};
let span = start + block.span;
Ok((

View File

@ -158,11 +158,9 @@ impl ParserContext<'_> {
// Parse the expression as a statement.
let end = self.expect(&Token::Semicolon)?;
Ok(Statement::Expression(ExpressionStatement {
span: place.span() + end,
expression: place,
id: self.node_builder.next_id(),
}))
Ok(Statement::Expression(
ExpressionStatement { span: place.span() + end, expression: place, id: self.node_builder.next_id() }
))
}
}
@ -271,45 +269,43 @@ impl ParserContext<'_> {
let keyword = self.expect(&Token::Console)?;
self.expect(&Token::Dot)?;
let identifier = self.expect_identifier()?;
let (span, function) = match identifier.name {
sym::assert => {
self.expect(&Token::LeftParen)?;
let expr = self.parse_expression()?;
self.expect(&Token::RightParen)?;
(keyword + expr.span(), ConsoleFunction::Assert(expr))
}
sym::assert_eq => {
self.expect(&Token::LeftParen)?;
let left = self.parse_expression()?;
self.expect(&Token::Comma)?;
let right = self.parse_expression()?;
self.expect(&Token::RightParen)?;
(left.span() + right.span(), ConsoleFunction::AssertEq(left, right))
}
sym::assert_neq => {
self.expect(&Token::LeftParen)?;
let left = self.parse_expression()?;
self.expect(&Token::Comma)?;
let right = self.parse_expression()?;
self.expect(&Token::RightParen)?;
(left.span() + right.span(), ConsoleFunction::AssertNeq(left, right))
}
symbol => {
// Not sure what it is, assume it's `log`.
self.emit_err(ParserError::unexpected_ident(
symbol,
&["assert", "assert_eq", "assert_neq"],
identifier.span,
));
(
Default::default(),
ConsoleFunction::Assert(Expression::Err(ErrExpression {
span: Default::default(),
id: self.node_builder.next_id(),
})),
)
}
};
let (span, function) =
match identifier.name {
sym::assert => {
self.expect(&Token::LeftParen)?;
let expr = self.parse_expression()?;
self.expect(&Token::RightParen)?;
(keyword + expr.span(), ConsoleFunction::Assert(expr))
}
sym::assert_eq => {
self.expect(&Token::LeftParen)?;
let left = self.parse_expression()?;
self.expect(&Token::Comma)?;
let right = self.parse_expression()?;
self.expect(&Token::RightParen)?;
(left.span() + right.span(), ConsoleFunction::AssertEq(left, right))
}
sym::assert_neq => {
self.expect(&Token::LeftParen)?;
let left = self.parse_expression()?;
self.expect(&Token::Comma)?;
let right = self.parse_expression()?;
self.expect(&Token::RightParen)?;
(left.span() + right.span(), ConsoleFunction::AssertNeq(left, right))
}
symbol => {
// Not sure what it is, assume it's `log`.
self.emit_err(
ParserError::unexpected_ident(symbol, &["assert", "assert_eq", "assert_neq"], identifier.span)
);
(
Default::default(),
ConsoleFunction::Assert(Expression::Err(
ErrExpression { span: Default::default(), id: self.node_builder.next_id() }
)),
)
}
};
self.expect(&Token::Semicolon)?;
Ok(ConsoleStatement { span: keyword + span, function, id: self.node_builder.next_id() })

View File

@ -572,16 +572,18 @@ impl<'a> CodeGenerator<'a> {
let return_type = &self.symbol_table.lookup_fn_symbol(function_name).unwrap().output_type;
match return_type {
Type::Unit => {} // Do nothing
Type::Tuple(tuple) => match tuple.length() {
0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"),
len => {
for _ in 0..len {
let destination_register = format!("r{}", self.next_register);
destinations.push(destination_register);
self.next_register += 1;
Type::Tuple(tuple) => {
match tuple.length() {
0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"),
len => {
for _ in 0..len {
let destination_register = format!("r{}", self.next_register);
destinations.push(destination_register);
self.next_register += 1;
}
}
}
},
}
_ => {
let destination_register = format!("r{}", self.next_register);
destinations.push(destination_register);

View File

@ -55,18 +55,19 @@ impl<'a> CodeGenerator<'a> {
}
fn visit_assert(&mut self, input: &'a AssertStatement) -> String {
let mut generate_assert_instruction = |name: &str, left: &'a Expression, right: &'a Expression| {
let (left_operand, left_instructions) = self.visit_expression(left);
let (right_operand, right_instructions) = self.visit_expression(right);
let assert_instruction = format!(" {name} {left_operand} {right_operand};\n");
let mut generate_assert_instruction =
|name: &str, left: &'a Expression, right: &'a Expression| {
let (left_operand, left_instructions) = self.visit_expression(left);
let (right_operand, right_instructions) = self.visit_expression(right);
let assert_instruction = format!(" {name} {left_operand} {right_operand};\n");
// Concatenate the instructions.
let mut instructions = left_instructions;
instructions.push_str(&right_instructions);
instructions.push_str(&assert_instruction);
// Concatenate the instructions.
let mut instructions = left_instructions;
instructions.push_str(&right_instructions);
instructions.push_str(&assert_instruction);
instructions
};
instructions
};
match &input.variant {
AssertVariant::Assert(expr) => {
let (operand, mut instructions) = self.visit_expression(expr);
@ -81,68 +82,69 @@ impl<'a> CodeGenerator<'a> {
}
fn visit_return(&mut self, input: &'a ReturnStatement) -> String {
let mut outputs = match input.expression {
// Skip empty return statements.
Expression::Unit(_) => String::new(),
_ => {
let (operand, mut expression_instructions) = self.visit_expression(&input.expression);
// Get the output type of the function.
let output = if self.in_finalize {
// Note that the first unwrap is safe, since `current_function` is set in `visit_function`.
self.current_function.unwrap().finalize.as_ref().unwrap().output.iter()
} else {
// Note that this unwrap is safe, since `current_function` is set in `visit_function`.
self.current_function.unwrap().output.iter()
};
// If the operand string is empty, initialize an empty vector.
let operand_strings = match operand.is_empty() {
true => vec![],
false => operand.split(' ').collect_vec(),
};
let instructions = operand_strings
.iter()
.zip_eq(output)
.map(|(operand, output)| {
match output {
Output::Internal(output) => {
let visibility = if self.is_transition_function {
match self.in_finalize {
// If in finalize block, the default visibility is public.
true => match output.mode {
Mode::None => Mode::Public,
mode => mode,
},
// If not in finalize block, the default visibility is private.
false => match output.mode {
Mode::None => Mode::Private,
mode => mode,
},
}
} else {
// Only program functions have visibilities associated with their outputs.
Mode::None
};
format!(
" output {} as {};\n",
operand,
self.visit_type_with_visibility(&output.type_, visibility)
)
let mut outputs =
match input.expression {
// Skip empty return statements.
Expression::Unit(_) => String::new(),
_ => {
let (operand, mut expression_instructions) = self.visit_expression(&input.expression);
// Get the output type of the function.
let output = if self.in_finalize {
// Note that the first unwrap is safe, since `current_function` is set in `visit_function`.
self.current_function.unwrap().finalize.as_ref().unwrap().output.iter()
} else {
// Note that this unwrap is safe, since `current_function` is set in `visit_function`.
self.current_function.unwrap().output.iter()
};
// If the operand string is empty, initialize an empty vector.
let operand_strings = match operand.is_empty() {
true => vec![],
false => operand.split(' ').collect_vec(),
};
let instructions = operand_strings
.iter()
.zip_eq(output)
.map(|(operand, output)| {
match output {
Output::Internal(output) => {
let visibility = if self.is_transition_function {
match self.in_finalize {
// If in finalize block, the default visibility is public.
true => match output.mode {
Mode::None => Mode::Public,
mode => mode,
},
// If not in finalize block, the default visibility is private.
false => match output.mode {
Mode::None => Mode::Private,
mode => mode,
},
}
} else {
// Only program functions have visibilities associated with their outputs.
Mode::None
};
format!(
" output {} as {};\n",
operand,
self.visit_type_with_visibility(&output.type_, visibility)
)
}
Output::External(output) => {
format!(
" output {} as {}.aleo/{}.record;\n",
operand, output.program_name, output.record,
)
}
}
Output::External(output) => {
format!(
" output {} as {}.aleo/{}.record;\n",
operand, output.program_name, output.record,
)
}
}
})
.join("");
})
.join("");
expression_instructions.push_str(&instructions);
expression_instructions.push_str(&instructions);
expression_instructions
}
};
expression_instructions
}
};
// Initialize storage for the instructions.
let mut instructions = String::new();

View File

@ -55,10 +55,9 @@ impl SymbolTable {
variant: func.variant,
_span: func.span,
input: func.input.clone(),
finalize: func.finalize.as_ref().map(|finalize| FinalizeData {
input: finalize.input.clone(),
output_type: finalize.output_type.clone(),
}),
finalize: func.finalize.as_ref().map(
|finalize| FinalizeData { input: finalize.input.clone(), output_type: finalize.output_type.clone() }
),
}
}
}

View File

@ -87,12 +87,13 @@ impl StatementReconstructor for DeadCodeEliminator<'_> {
self.is_necessary = true;
// Visit the statement.
let statement = Statement::Assign(Box::new(AssignStatement {
place: input.place,
value: self.reconstruct_expression(input.value).0,
span: input.span,
id: input.id,
}));
let statement =
Statement::Assign(Box::new(AssignStatement {
place: input.place,
value: self.reconstruct_expression(input.value).0,
span: input.span,
id: input.id,
}));
// Unset the `is_necessary` flag.
self.is_necessary = false;
@ -181,14 +182,15 @@ impl StatementReconstructor for DeadCodeEliminator<'_> {
self.is_necessary = true;
// Visit the statement.
let statement = Statement::Return(ReturnStatement {
expression: self.reconstruct_expression(input.expression).0,
finalize_arguments: input.finalize_arguments.map(|arguments| {
arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect()
}),
span: input.span,
id: input.id,
});
let statement =
Statement::Return(ReturnStatement {
expression: self.reconstruct_expression(input.expression).0,
finalize_arguments: input.finalize_arguments.map(|arguments| {
arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect()
}),
span: input.span,
id: input.id,
});
// Unset the `is_necessary` flag.
self.is_necessary = false;

View File

@ -137,29 +137,32 @@ impl StatementReconstructor for Destructurer<'_> {
),
// If the lhs is a tuple and the rhs is a tuple, create a new assign statement for each tuple element.
(Expression::Tuple(lhs_tuple), Expression::Tuple(rhs_tuple)) => {
let statements = lhs_tuple
.elements
.into_iter()
.zip_eq(rhs_tuple.elements)
.map(|(lhs, rhs)| {
// Get the type of the rhs.
let type_ = match self.type_table.get(&lhs.id()) {
Some(type_) => type_.clone(),
None => {
unreachable!("Type checking guarantees that the type of the lhs is in the type table.")
}
};
// Set the type of the lhs.
self.type_table.insert(rhs.id(), type_);
// Return the assign statement.
Statement::Assign(Box::new(AssignStatement {
place: lhs,
value: rhs,
span: Default::default(),
id: self.node_builder.next_id(),
}))
})
.collect();
let statements =
lhs_tuple
.elements
.into_iter()
.zip_eq(rhs_tuple.elements)
.map(|(lhs, rhs)| {
// Get the type of the rhs.
let type_ = match self.type_table.get(&lhs.id()) {
Some(type_) => type_.clone(),
None => {
unreachable!(
"Type checking guarantees that the type of the lhs is in the type table."
)
}
};
// Set the type of the lhs.
self.type_table.insert(rhs.id(), type_);
// Return the assign statement.
Statement::Assign(Box::new(AssignStatement {
place: lhs,
value: rhs,
span: Default::default(),
id: self.node_builder.next_id(),
}))
})
.collect();
(Statement::dummy(Default::default(), self.node_builder.next_id()), statements)
}
// If the lhs is a tuple and the rhs is an identifier that is a tuple, create a new assign statement for each tuple element.

View File

@ -62,31 +62,32 @@ impl StatementReconstructor for Flattener<'_> {
let mut statements = Vec::new();
// Flatten the arguments of the assert statement.
let assert = AssertStatement {
span: input.span,
id: input.id,
variant: match input.variant {
AssertVariant::Assert(expression) => {
let (expression, additional_statements) = self.reconstruct_expression(expression);
statements.extend(additional_statements);
AssertVariant::Assert(expression)
}
AssertVariant::AssertEq(left, right) => {
let (left, additional_statements) = self.reconstruct_expression(left);
statements.extend(additional_statements);
let (right, additional_statements) = self.reconstruct_expression(right);
statements.extend(additional_statements);
AssertVariant::AssertEq(left, right)
}
AssertVariant::AssertNeq(left, right) => {
let (left, additional_statements) = self.reconstruct_expression(left);
statements.extend(additional_statements);
let (right, additional_statements) = self.reconstruct_expression(right);
statements.extend(additional_statements);
AssertVariant::AssertNeq(left, right)
}
},
};
let assert =
AssertStatement {
span: input.span,
id: input.id,
variant: match input.variant {
AssertVariant::Assert(expression) => {
let (expression, additional_statements) = self.reconstruct_expression(expression);
statements.extend(additional_statements);
AssertVariant::Assert(expression)
}
AssertVariant::AssertEq(left, right) => {
let (left, additional_statements) = self.reconstruct_expression(left);
statements.extend(additional_statements);
let (right, additional_statements) = self.reconstruct_expression(right);
statements.extend(additional_statements);
AssertVariant::AssertEq(left, right)
}
AssertVariant::AssertNeq(left, right) => {
let (left, additional_statements) = self.reconstruct_expression(left);
statements.extend(additional_statements);
let (right, additional_statements) = self.reconstruct_expression(right);
statements.extend(additional_statements);
AssertVariant::AssertNeq(left, right)
}
},
};
// Add the appropriate guards.
match self.construct_guard() {

View File

@ -392,68 +392,71 @@ impl<'a> Flattener<'a> {
// Initialize a vector to accumulate any statements generated.
let mut statements = Vec::new();
// For each struct member, construct a new ternary expression.
let members = struct_
.members
.iter()
.map(|Member { identifier, type_, .. }| {
// Create an assignment statement for the first access expression.
let (first, stmt) =
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Member(MemberAccess {
inner: Box::new(Expression::Identifier(*first)),
name: *identifier,
let members =
struct_
.members
.iter()
.map(|Member { identifier, type_, .. }| {
// Create an assignment statement for the first access expression.
let (first, stmt) = self.unique_simple_assign_statement(Expression::Access(
AccessExpression::Member(MemberAccess {
inner: Box::new(Expression::Identifier(*first)),
name: *identifier,
span: Default::default(),
id: {
// Create a new node ID for the access expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
}),
));
statements.push(stmt);
// Create an assignment statement for the second access expression.
let (second, stmt) = self.unique_simple_assign_statement(Expression::Access(
AccessExpression::Member(MemberAccess {
inner: Box::new(Expression::Identifier(*second)),
name: *identifier,
span: Default::default(),
id: {
// Create a new node ID for the access expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
}),
));
statements.push(stmt);
// Recursively reconstruct the ternary expression.
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: Box::new(condition.clone()),
// Access the member of the first expression.
if_true: Box::new(Expression::Identifier(first)),
// Access the member of the second expression.
if_false: Box::new(Expression::Identifier(second)),
span: Default::default(),
id: {
// Create a new node ID for the access expression.
// Create a new node ID for the ternary expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
})));
statements.push(stmt);
// Create an assignment statement for the second access expression.
let (second, stmt) =
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Member(MemberAccess {
inner: Box::new(Expression::Identifier(*second)),
name: *identifier,
});
// Accumulate any statements generated.
statements.extend(stmts);
StructVariableInitializer {
identifier: *identifier,
expression: Some(expression),
span: Default::default(),
id: {
// Create a new node ID for the access expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
})));
statements.push(stmt);
// Recursively reconstruct the ternary expression.
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: Box::new(condition.clone()),
// Access the member of the first expression.
if_true: Box::new(Expression::Identifier(first)),
// Access the member of the second expression.
if_false: Box::new(Expression::Identifier(second)),
span: Default::default(),
id: {
// Create a new node ID for the ternary expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
});
// Accumulate any statements generated.
statements.extend(stmts);
StructVariableInitializer {
identifier: *identifier,
expression: Some(expression),
span: Default::default(),
id: self.node_builder.next_id(),
}
})
.collect();
id: self.node_builder.next_id(),
}
})
.collect();
let (expr, stmts) = self.reconstruct_struct_init(StructExpression {
name: struct_.identifier,
@ -489,65 +492,66 @@ impl<'a> Flattener<'a> {
// Initialize a vector to accumulate any statements generated.
let mut statements = Vec::new();
// For each tuple element, construct a new ternary expression.
let elements = tuple_type
.elements()
.iter()
.enumerate()
.map(|(i, type_)| {
// Create an assignment statement for the first access expression.
let (first, stmt) =
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess {
tuple: Box::new(Expression::Identifier(*first)),
index: NonNegativeNumber::from(i),
let elements =
tuple_type
.elements()
.iter()
.enumerate()
.map(|(i, type_)| {
// Create an assignment statement for the first access expression.
let (first, stmt) =
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess {
tuple: Box::new(Expression::Identifier(*first)),
index: NonNegativeNumber::from(i),
span: Default::default(),
id: {
// Create a new node ID for the access expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
})));
statements.push(stmt);
// Create an assignment statement for the second access expression.
let (second, stmt) =
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess {
tuple: Box::new(Expression::Identifier(*second)),
index: NonNegativeNumber::from(i),
span: Default::default(),
id: {
// Create a new node ID for the access expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
})));
statements.push(stmt);
// Recursively reconstruct the ternary expression.
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: Box::new(condition.clone()),
// Access the member of the first expression.
if_true: Box::new(Expression::Identifier(first)),
// Access the member of the second expression.
if_false: Box::new(Expression::Identifier(second)),
span: Default::default(),
id: {
// Create a new node ID for the access expression.
// Create a new node ID for the ternary expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
})));
statements.push(stmt);
// Create an assignment statement for the second access expression.
let (second, stmt) =
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess {
tuple: Box::new(Expression::Identifier(*second)),
index: NonNegativeNumber::from(i),
span: Default::default(),
id: {
// Create a new node ID for the access expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
})));
statements.push(stmt);
});
// Recursively reconstruct the ternary expression.
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: Box::new(condition.clone()),
// Access the member of the first expression.
if_true: Box::new(Expression::Identifier(first)),
// Access the member of the second expression.
if_false: Box::new(Expression::Identifier(second)),
span: Default::default(),
id: {
// Create a new node ID for the ternary expression.
let id = self.node_builder.next_id();
// Set the type of the node ID.
self.type_table.insert(id, type_.clone());
id
},
});
// Accumulate any statements generated.
statements.extend(stmts);
// Accumulate any statements generated.
statements.extend(stmts);
expression
})
.collect();
expression
})
.collect();
// Construct the tuple expression.
let tuple = TupleExpression {

View File

@ -192,41 +192,42 @@ impl<'a> Unroller<'a> {
self.type_table.insert(id, input.type_.clone());
// Reconstruct `iteration_count` as a `Literal`.
let value = match input.type_ {
Type::Integer(IntegerType::I8) => {
Literal::Integer(IntegerType::I8, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::I16) => {
Literal::Integer(IntegerType::I16, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::I32) => {
Literal::Integer(IntegerType::I32, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::I64) => {
Literal::Integer(IntegerType::I64, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::I128) => {
Literal::Integer(IntegerType::I128, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U8) => {
Literal::Integer(IntegerType::U8, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U16) => {
Literal::Integer(IntegerType::U16, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U32) => {
Literal::Integer(IntegerType::U32, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U64) => {
Literal::Integer(IntegerType::U64, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U128) => {
Literal::Integer(IntegerType::U128, iteration_count.to_string(), Default::default(), id)
}
_ => unreachable!(
"The iteration variable must be an integer type. This should be enforced by type checking."
),
};
let value =
match input.type_ {
Type::Integer(IntegerType::I8) => {
Literal::Integer(IntegerType::I8, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::I16) => {
Literal::Integer(IntegerType::I16, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::I32) => {
Literal::Integer(IntegerType::I32, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::I64) => {
Literal::Integer(IntegerType::I64, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::I128) => {
Literal::Integer(IntegerType::I128, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U8) => {
Literal::Integer(IntegerType::U8, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U16) => {
Literal::Integer(IntegerType::U16, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U32) => {
Literal::Integer(IntegerType::U32, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U64) => {
Literal::Integer(IntegerType::U64, iteration_count.to_string(), Default::default(), id)
}
Type::Integer(IntegerType::U128) => {
Literal::Integer(IntegerType::U128, iteration_count.to_string(), Default::default(), id)
}
_ => unreachable!(
"The iteration variable must be an integer type. This should be enforced by type checking."
),
};
// Add the loop variable as a constant for the current scope
self.constant_propagation_table

View File

@ -207,12 +207,13 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
let (expression, mut statements) = self.consume_expression(*input.expression);
// Construct and accumulate a unique assignment statement storing the result of the cast expression.
let (place, statement) = self.unique_simple_assign_statement(Expression::Cast(CastExpression {
expression: Box::new(expression),
type_: input.type_,
span: input.span,
id: input.id,
}));
let (place, statement) =
self.unique_simple_assign_statement(Expression::Cast(CastExpression {
expression: Box::new(expression),
type_: input.type_,
span: input.span,
id: input.id,
}));
statements.push(statement);
(Expression::Identifier(place), statements)
@ -280,12 +281,13 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
}
// Construct and accumulate a new assignment statement for the struct expression.
let (place, statement) = self.unique_simple_assign_statement(Expression::Struct(StructExpression {
name: input.name,
span: input.span,
members: reordered_members,
id: input.id,
}));
let (place, statement) =
self.unique_simple_assign_statement(Expression::Struct(StructExpression {
name: input.name,
span: input.span,
members: reordered_members,
id: input.id,
}));
statements.push(statement);
(Expression::Identifier(place), statements)
@ -375,12 +377,9 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
let (receiver, mut statements) = self.consume_expression(*input.receiver);
// Construct and accumulate a new assignment statement for the unary expression.
let (place, statement) = self.unique_simple_assign_statement(Expression::Unary(UnaryExpression {
op: input.op,
receiver: Box::new(receiver),
span: input.span,
id: input.id,
}));
let (place, statement) = self.unique_simple_assign_statement(Expression::Unary(
UnaryExpression { op: input.op, receiver: Box::new(receiver), span: input.span, id: input.id }
));
statements.push(statement);
(Expression::Identifier(place), statements)

View File

@ -198,13 +198,14 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
self.type_table.insert(id, type_);
// Construct a ternary expression for the phi function.
let (value, stmts) = self.consume_ternary(TernaryExpression {
condition: Box::new(condition.clone()),
if_true,
if_false,
span: Default::default(),
id,
});
let (value, stmts) =
self.consume_ternary(TernaryExpression {
condition: Box::new(condition.clone()),
if_true,
if_false,
span: Default::default(),
id,
});
statements.extend(stmts);
@ -290,22 +291,17 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
}
// Construct the lhs of the assignment.
let place = Expression::Tuple(TupleExpression {
elements,
span: Default::default(),
id: self.node_builder.next_id(),
});
let place = Expression::Tuple(
TupleExpression { elements, span: Default::default(), id: self.node_builder.next_id() }
);
// Update the type of the lhs.
self.type_table.insert(place.id(), Type::Tuple(tuple_type_));
// Create the assignment statement.
let assignment = Statement::Assign(Box::new(AssignStatement {
place,
value,
span: definition.span,
id: definition.id,
}));
let assignment = Statement::Assign(
Box::new(AssignStatement { place, value, span: definition.span, id: definition.id })
);
statements.push(assignment);
}
@ -401,12 +397,9 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
});
// Add the simplified return statement to the list of produced statements.
statements.push(Statement::Return(ReturnStatement {
expression,
finalize_arguments: finalize_args,
span: input.span,
id: input.id,
}));
statements.push(Statement::Return(
ReturnStatement { expression, finalize_arguments: finalize_args, span: input.span, id: input.id }
));
statements
}

View File

@ -235,10 +235,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
self.emit_err(TypeCheckerError::type_should_be(type_, "struct", access.inner.span()));
}
None => {
self.emit_err(TypeCheckerError::could_not_determine_type(
&access.inner,
access.inner.span(),
));
self.emit_err(
TypeCheckerError::could_not_determine_type(&access.inner, access.inner.span())
);
}
}
}
@ -288,11 +287,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
}
// The array cannot have more than `MAX_ARRAY_ELEMENTS` elements.
num_elements => {
self.emit_err(TypeCheckerError::array_too_large(
num_elements,
Testnet3::MAX_ARRAY_ELEMENTS,
input.span(),
));
self.emit_err(
TypeCheckerError::array_too_large(num_elements, Testnet3::MAX_ARRAY_ELEMENTS, input.span())
);
None
}
};

View File

@ -121,18 +121,19 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
// For records, enforce presence of the `owner: Address` member.
if input.is_record {
let check_has_field =
|need, expected_ty: Type| match input.members.iter().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((field, _)) => {
self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span()));
}
None => {
self.emit_err(TypeCheckerError::required_record_variable(need, expected_ty, input.span()));
}
};
let check_has_field = |need, expected_ty: Type| match input
.members
.iter()
.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((field, _)) => {
self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span()));
}
None => {
self.emit_err(TypeCheckerError::required_record_variable(need, expected_ty, input.span()));
}
};
check_has_field(sym::owner, Type::Address);
}

View File

@ -68,21 +68,24 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
}
};
let var_type = if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(var_name.name) {
match &var.declaration {
VariableType::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)),
VariableType::Input(Mode::Constant) => {
self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span))
let var_type =
if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(var_name.name) {
match &var.declaration {
VariableType::Const => {
self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span))
}
VariableType::Input(Mode::Constant) => {
self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span))
}
_ => {}
}
_ => {}
}
Some(var.type_.clone())
} else {
self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span));
Some(var.type_.clone())
} else {
self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span));
None
};
None
};
if var_type.is_some() {
self.visit_expression(&input.value, &var_type);
@ -175,16 +178,18 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
// Enforce that Constant variables have literal expressions on right-hand side
match &input.value {
Expression::Literal(_) => (),
Expression::Tuple(tuple_expression) => match tuple_expression.elements.len() {
0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."),
_ => {
if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) {
self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(
input.span,
))
Expression::Tuple(tuple_expression) => {
match tuple_expression.elements.len() {
0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."),
_ => {
if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) {
self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(
input.span,
))
}
}
}
},
}
_ => self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(input.span())),
}

View File

@ -387,11 +387,9 @@ impl<'a> TypeChecker<'a> {
) -> Option<Type> {
// Check that the number of arguments is correct.
if arguments.len() != core_function.num_args() {
self.emit_err(TypeCheckerError::incorrect_num_args_to_call(
core_function.num_args(),
arguments.len(),
function_span,
));
self.emit_err(
TypeCheckerError::incorrect_num_args_to_call(core_function.num_args(), arguments.len(), function_span)
);
return None;
}
@ -982,10 +980,9 @@ impl<'a> TypeChecker<'a> {
CoreFunction::MappingContains => {
// Check that the operation is invoked in a `finalize` block.
if !self.is_finalize {
self.handler.emit_err(TypeCheckerError::invalid_operation_outside_finalize(
"Mapping::contains",
function_span,
))
self.handler.emit_err(
TypeCheckerError::invalid_operation_outside_finalize("Mapping::contains", function_span)
)
}
// Check that the first argument is a mapping.
if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) {

View File

@ -99,10 +99,11 @@ impl SourceMap {
/// Returns a displayable representation of the `span` as a string.
pub fn span_to_string(&self, span: Span) -> String {
let loc = match self.span_to_location(span) {
None => return "no-location".to_string(),
Some(l) => l,
};
let loc =
match self.span_to_location(span) {
None => return "no-location".to_string(),
Some(l) => l,
};
if loc.line_start == loc.line_stop {
format!("{}:{}-{}", loc.line_start, loc.col_start, loc.col_stop)
@ -339,10 +340,11 @@ fn normalize_newlines(src: &mut String) {
let mut gap_len = 0;
let mut tail = buf.as_mut_slice();
loop {
let idx = match find_crlf(&tail[gap_len..]) {
None => tail.len(),
Some(idx) => idx + gap_len,
};
let idx =
match find_crlf(&tail[gap_len..]) {
None => tail.len(),
Some(idx) => idx + gap_len,
};
tail.copy_within(gap_len..idx, 0);
tail = &mut tail[idx - gap_len..];
if tail.len() == gap_len {

View File

@ -205,10 +205,11 @@ fn main() -> Result<()> {
// Parse ABNF to get list of all definitions.
// Rust ABNF does not provide support for `%s` (case sensitive strings, part of
// the standard); so we need to remove all occurrences before parsing.
let parsed = abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| {
eprintln!("{}", &e);
anyhow::anyhow!(e)
})?;
let parsed =
abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| {
eprintln!("{}", &e);
anyhow::anyhow!(e)
})?;
// Init parser and run it. That's it.
let mut parser = Processor::new(&grammar, parsed);

View File

@ -54,13 +54,14 @@ impl Command for Execute {
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {
// If input values are provided, then run the program with those inputs.
// Otherwise, use the input file.
let mut inputs = match self.inputs.is_empty() {
true => match input {
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
_ => Vec::new(),
},
false => self.inputs,
};
let mut inputs =
match self.inputs.is_empty() {
true => match input {
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
_ => Vec::new(),
},
false => self.inputs,
};
// Compose the `execute` command.
let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name];

View File

@ -46,13 +46,14 @@ impl Command for Run {
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {
// If input values are provided, then run the program with those inputs.
// Otherwise, use the input file.
let mut inputs = match self.inputs.is_empty() {
true => match input {
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
_ => Vec::new(),
},
false => self.inputs,
};
let mut inputs =
match self.inputs.is_empty() {
true => match input {
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
_ => Vec::new(),
},
false => self.inputs,
};
// Compose the `run` command.
let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name];

View File

@ -56,8 +56,8 @@ impl InputFile {
pub fn read_from<'a>(&self, path: &'a Path) -> Result<(String, Cow<'a, Path>)> {
let path = self.setup_file_path(path);
let input = fs::read_to_string(&path)
.map_err(|_| PackageError::failed_to_read_input_file(path.clone().into_owned()))?;
let input =
fs::read_to_string(&path).map_err(|_| PackageError::failed_to_read_input_file(path.clone().into_owned()))?;
Ok((input, path))
}

View File

@ -93,12 +93,13 @@ impl TestCases {
let mut path_prefix = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path_prefix.push("../../tests");
let mut new = Self {
tests: Vec::new(),
path_prefix,
expectation_category: expectation_category.to_string(),
fail_categories: Vec::new(),
};
let mut new =
Self {
tests: Vec::new(),
path_prefix,
expectation_category: expectation_category.to_string(),
fail_categories: Vec::new(),
};
let tests = new.load_tests(additional_check);
(new, tests)
}
@ -188,10 +189,11 @@ pub fn run_tests<T: Runner>(runner: &T, expectation_category: &str) {
let mut outputs = vec![];
cases.process_tests(configs, |cases, (path, content, test_name, config)| {
let namespace = match runner.resolve_namespace(&config.namespace) {
Some(ns) => ns,
None => return,
};
let namespace =
match runner.resolve_namespace(&config.namespace) {
Some(ns) => ns,
None => return,
};
let (expectation_path, expectations) = cases.load_expectations(path);