mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 23:23:50 +03:00
Clippy + fmt
This commit is contained in:
parent
1afa68a66e
commit
afc953cd0b
@ -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)
|
||||
}
|
||||
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
@ -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")?;
|
||||
|
@ -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())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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((
|
||||
|
@ -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() })
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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() }
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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())),
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
@ -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];
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user