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>,
|
imported_modules: &IndexMap<Vec<Symbol>, Program>,
|
||||||
serializer: S,
|
serializer: S,
|
||||||
) -> Result<S::Ok, S::Error> {
|
) -> Result<S::Ok, S::Error> {
|
||||||
let joined: IndexMap<String, Program> = with_session_globals(|s| {
|
let joined: IndexMap<String, Program> =
|
||||||
imported_modules
|
with_session_globals(|s| {
|
||||||
.into_iter()
|
imported_modules
|
||||||
.map(|(package, program)| {
|
.into_iter()
|
||||||
let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::<Vec<_>>();
|
.map(|(package, program)| {
|
||||||
(package.join("."), program.clone())
|
let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::<Vec<_>>();
|
||||||
})
|
(package.join("."), program.clone())
|
||||||
.collect()
|
})
|
||||||
});
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
joined.serialize(serializer)
|
joined.serialize(serializer)
|
||||||
}
|
}
|
||||||
|
@ -66,12 +66,9 @@ pub trait ExpressionReconstructor {
|
|||||||
|
|
||||||
fn reconstruct_associated_constant(&mut self, input: AssociatedConstant) -> (Expression, Self::AdditionalOutput) {
|
fn reconstruct_associated_constant(&mut self, input: AssociatedConstant) -> (Expression, Self::AdditionalOutput) {
|
||||||
(
|
(
|
||||||
Expression::Access(AccessExpression::AssociatedConstant(AssociatedConstant {
|
Expression::Access(AccessExpression::AssociatedConstant(
|
||||||
ty: input.ty,
|
AssociatedConstant { ty: input.ty, name: input.name, span: input.span, id: input.id }
|
||||||
name: input.name,
|
)),
|
||||||
span: input.span,
|
|
||||||
id: input.id,
|
|
||||||
})),
|
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -244,12 +244,9 @@ impl<'a> Compiler<'a> {
|
|||||||
|
|
||||||
/// Runs the destructuring pass.
|
/// Runs the destructuring pass.
|
||||||
pub fn destructuring_pass(&mut self) -> Result<()> {
|
pub fn destructuring_pass(&mut self) -> Result<()> {
|
||||||
self.ast = Destructurer::do_pass((
|
self.ast = Destructurer::do_pass(
|
||||||
std::mem::take(&mut self.ast),
|
(std::mem::take(&mut self.ast), &self.type_table, &self.node_builder, &self.assigner)
|
||||||
&self.type_table,
|
)?;
|
||||||
&self.node_builder,
|
|
||||||
&self.assigner,
|
|
||||||
))?;
|
|
||||||
|
|
||||||
if self.compiler_options.output.destructured_ast {
|
if self.compiler_options.output.destructured_ast {
|
||||||
self.write_ast_to_json("destructured_ast.json")?;
|
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> {
|
fn run_test(&self, test: Test) -> Result<Value, String> {
|
||||||
let buf = BufferEmitter(Rc::default(), Rc::default());
|
let buf = BufferEmitter(Rc::default(), Rc::default());
|
||||||
let handler = Handler::new(Box::new(buf.clone()));
|
let handler = Handler::new(Box::new(buf.clone()));
|
||||||
create_session_if_not_set_then(|_| {
|
create_session_if_not_set_then(
|
||||||
run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string())
|
|_| 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> {
|
fn run_test(&self, test: Test) -> Result<Value, String> {
|
||||||
let buf = BufferEmitter(Rc::default(), Rc::default());
|
let buf = BufferEmitter(Rc::default(), Rc::default());
|
||||||
let handler = Handler::new(Box::new(buf.clone()));
|
let handler = Handler::new(Box::new(buf.clone()));
|
||||||
create_session_if_not_set_then(|_| {
|
create_session_if_not_set_then(
|
||||||
run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string())
|
|_| 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))?;
|
let bytecode = handler.extend_if_error(compile_and_process(&mut parsed))?;
|
||||||
|
|
||||||
// Extract the cases from the test config.
|
// Extract the cases from the test config.
|
||||||
let all_cases = test
|
let all_cases =
|
||||||
.config
|
test.config
|
||||||
.extra
|
.extra
|
||||||
.get("cases")
|
.get("cases")
|
||||||
.expect("An `Execute` config must have a `cases` field.")
|
.expect("An `Execute` config must have a `cases` field.")
|
||||||
.as_mapping()
|
.as_mapping()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Initialize a map for the expected results.
|
// Initialize a map for the expected results.
|
||||||
let mut results = BTreeMap::new();
|
let mut results = BTreeMap::new();
|
||||||
|
@ -237,12 +237,9 @@ impl ParserContext<'_> {
|
|||||||
if self.eat(&Token::As) {
|
if self.eat(&Token::As) {
|
||||||
let (type_, end_span) = self.parse_primitive_type()?;
|
let (type_, end_span) = self.parse_primitive_type()?;
|
||||||
let span = expr.span() + end_span;
|
let span = expr.span() + end_span;
|
||||||
expr = Expression::Cast(CastExpression {
|
expr = Expression::Cast(
|
||||||
expression: Box::new(expr),
|
CastExpression { expression: Box::new(expr), type_, span, id: self.node_builder.next_id() }
|
||||||
type_,
|
);
|
||||||
span,
|
|
||||||
id: self.node_builder.next_id(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
@ -328,12 +325,9 @@ impl ParserContext<'_> {
|
|||||||
|
|
||||||
if let (true, Some(op)) = (args.is_empty(), UnaryOperation::from_symbol(method.name)) {
|
if let (true, Some(op)) = (args.is_empty(), UnaryOperation::from_symbol(method.name)) {
|
||||||
// Found an unary operator and the argument list is empty.
|
// Found an unary operator and the argument list is empty.
|
||||||
Ok(Expression::Unary(UnaryExpression {
|
Ok(Expression::Unary(
|
||||||
span,
|
UnaryExpression { span, op, receiver: Box::new(receiver), id: self.node_builder.next_id() }
|
||||||
op,
|
))
|
||||||
receiver: Box::new(receiver),
|
|
||||||
id: self.node_builder.next_id(),
|
|
||||||
}))
|
|
||||||
} else if let (1, Some(op)) = (args.len(), BinaryOperation::from_symbol(method.name)) {
|
} 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.
|
// Found a binary operator and the argument list contains a single argument.
|
||||||
Ok(Expression::Binary(BinaryExpression {
|
Ok(Expression::Binary(BinaryExpression {
|
||||||
@ -443,12 +437,10 @@ impl ParserContext<'_> {
|
|||||||
if self.check_int() {
|
if self.check_int() {
|
||||||
// Eat a tuple member access.
|
// Eat a tuple member access.
|
||||||
let (index, span) = self.eat_whole_number()?;
|
let (index, span) = self.eat_whole_number()?;
|
||||||
expr = Expression::Access(AccessExpression::Tuple(TupleAccess {
|
expr =
|
||||||
tuple: Box::new(expr),
|
Expression::Access(AccessExpression::Tuple(
|
||||||
index,
|
TupleAccess { tuple: Box::new(expr), index, span, id: self.node_builder.next_id() }
|
||||||
span,
|
))
|
||||||
id: self.node_builder.next_id(),
|
|
||||||
}))
|
|
||||||
} else if self.eat(&Token::Leo) {
|
} else if self.eat(&Token::Leo) {
|
||||||
// Eat an external function call.
|
// Eat an external function call.
|
||||||
self.eat(&Token::Div); // todo: Make `/` a more general token.
|
self.eat(&Token::Div); // todo: Make `/` a more general token.
|
||||||
@ -627,14 +619,15 @@ impl ParserContext<'_> {
|
|||||||
self.expect_identifier()?
|
self.expect_identifier()?
|
||||||
};
|
};
|
||||||
|
|
||||||
let (expression, span) = if self.eat(&Token::Colon) {
|
let (expression, span) =
|
||||||
// Parse individual struct variable declarations.
|
if self.eat(&Token::Colon) {
|
||||||
let expression = self.parse_expression()?;
|
// Parse individual struct variable declarations.
|
||||||
let span = identifier.span + expression.span();
|
let expression = self.parse_expression()?;
|
||||||
(Some(expression), span)
|
let span = identifier.span + expression.span();
|
||||||
} else {
|
(Some(expression), span)
|
||||||
(None, identifier.span)
|
} else {
|
||||||
};
|
(None, identifier.span)
|
||||||
|
};
|
||||||
|
|
||||||
Ok(StructVariableInitializer { identifier, expression, id: self.node_builder.next_id(), 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`.
|
// Literal followed by `group`, e.g., `42group`.
|
||||||
Some(Token::Group) => {
|
Some(Token::Group) => {
|
||||||
assert_no_whitespace("group")?;
|
assert_no_whitespace("group")?;
|
||||||
Expression::Literal(Literal::Group(Box::new(GroupLiteral::Single(
|
Expression::Literal(Literal::Group(Box::new(
|
||||||
value,
|
GroupLiteral::Single(value, full_span, self.node_builder.next_id())
|
||||||
full_span,
|
)))
|
||||||
self.node_builder.next_id(),
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
// Literal followed by `scalar` e.g., `42scalar`.
|
// Literal followed by `scalar` e.g., `42scalar`.
|
||||||
Some(Token::Scalar) => {
|
Some(Token::Scalar) => {
|
||||||
@ -732,11 +723,9 @@ impl ParserContext<'_> {
|
|||||||
Token::Block => {
|
Token::Block => {
|
||||||
Expression::Identifier(Identifier { name: sym::block, span, id: self.node_builder.next_id() })
|
Expression::Identifier(Identifier { name: sym::block, span, id: self.node_builder.next_id() })
|
||||||
}
|
}
|
||||||
t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier {
|
t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(
|
||||||
name: t.keyword_to_symbol().unwrap(),
|
Identifier { name: t.keyword_to_symbol().unwrap(), span, id: self.node_builder.next_id() }
|
||||||
span,
|
),
|
||||||
id: self.node_builder.next_id(),
|
|
||||||
}),
|
|
||||||
token => {
|
token => {
|
||||||
return Err(ParserError::unexpected_str(token, "expression", span).into());
|
return Err(ParserError::unexpected_str(token, "expression", span).into());
|
||||||
}
|
}
|
||||||
|
@ -325,13 +325,9 @@ impl ParserContext<'_> {
|
|||||||
} else {
|
} else {
|
||||||
let type_ = self.parse_type()?.0;
|
let type_ = self.parse_type()?.0;
|
||||||
|
|
||||||
Ok(functions::Input::Internal(FunctionInput {
|
Ok(functions::Input::Internal(
|
||||||
identifier: name,
|
FunctionInput { identifier: name, mode, type_, span: name.span, id: self.node_builder.next_id() }
|
||||||
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))?;
|
let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
|
||||||
|
|
||||||
// Parse return type.
|
// Parse return type.
|
||||||
let output = match self.eat(&Token::Arrow) {
|
let output =
|
||||||
false => vec![],
|
match self.eat(&Token::Arrow) {
|
||||||
true => {
|
false => vec![],
|
||||||
self.disallow_struct_construction = true;
|
true => {
|
||||||
let output = match self.peek_is_left_par() {
|
self.disallow_struct_construction = true;
|
||||||
true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
|
let output = match self.peek_is_left_par() {
|
||||||
false => vec![self.parse_output()?],
|
true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
|
||||||
};
|
false => vec![self.parse_output()?],
|
||||||
self.disallow_struct_construction = false;
|
};
|
||||||
output
|
self.disallow_struct_construction = false;
|
||||||
}
|
output
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Parse the function body.
|
// Parse the function body.
|
||||||
let block = self.parse_block()?;
|
let block = self.parse_block()?;
|
||||||
|
|
||||||
// Parse the `finalize` block if it exists.
|
// Parse the `finalize` block if it exists.
|
||||||
let finalize = match self.eat(&Token::Finalize) {
|
let finalize =
|
||||||
false => None,
|
match self.eat(&Token::Finalize) {
|
||||||
true => {
|
false => None,
|
||||||
// Get starting span.
|
true => {
|
||||||
let start = self.prev_token.span;
|
// Get starting span.
|
||||||
|
let start = self.prev_token.span;
|
||||||
|
|
||||||
// Parse the identifier.
|
// Parse the identifier.
|
||||||
let identifier = self.expect_identifier()?;
|
let identifier = self.expect_identifier()?;
|
||||||
|
|
||||||
// Parse parameters.
|
// Parse parameters.
|
||||||
let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
|
let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
|
||||||
|
|
||||||
// Parse return type.
|
// Parse return type.
|
||||||
let output = match self.eat(&Token::Arrow) {
|
let output = match self.eat(&Token::Arrow) {
|
||||||
false => vec![],
|
false => vec![],
|
||||||
true => {
|
true => {
|
||||||
self.disallow_struct_construction = true;
|
self.disallow_struct_construction = true;
|
||||||
let output = match self.peek_is_left_par() {
|
let output = match self.peek_is_left_par() {
|
||||||
true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
|
true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
|
||||||
false => vec![self.parse_output()?],
|
false => vec![self.parse_output()?],
|
||||||
};
|
};
|
||||||
self.disallow_struct_construction = false;
|
self.disallow_struct_construction = false;
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse the finalize body.
|
// Parse the finalize body.
|
||||||
let block = self.parse_block()?;
|
let block = self.parse_block()?;
|
||||||
let span = start + block.span;
|
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;
|
let span = start + block.span;
|
||||||
Ok((
|
Ok((
|
||||||
|
@ -158,11 +158,9 @@ impl ParserContext<'_> {
|
|||||||
|
|
||||||
// Parse the expression as a statement.
|
// Parse the expression as a statement.
|
||||||
let end = self.expect(&Token::Semicolon)?;
|
let end = self.expect(&Token::Semicolon)?;
|
||||||
Ok(Statement::Expression(ExpressionStatement {
|
Ok(Statement::Expression(
|
||||||
span: place.span() + end,
|
ExpressionStatement { span: place.span() + end, expression: place, id: self.node_builder.next_id() }
|
||||||
expression: place,
|
))
|
||||||
id: self.node_builder.next_id(),
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,45 +269,43 @@ impl ParserContext<'_> {
|
|||||||
let keyword = self.expect(&Token::Console)?;
|
let keyword = self.expect(&Token::Console)?;
|
||||||
self.expect(&Token::Dot)?;
|
self.expect(&Token::Dot)?;
|
||||||
let identifier = self.expect_identifier()?;
|
let identifier = self.expect_identifier()?;
|
||||||
let (span, function) = match identifier.name {
|
let (span, function) =
|
||||||
sym::assert => {
|
match identifier.name {
|
||||||
self.expect(&Token::LeftParen)?;
|
sym::assert => {
|
||||||
let expr = self.parse_expression()?;
|
self.expect(&Token::LeftParen)?;
|
||||||
self.expect(&Token::RightParen)?;
|
let expr = self.parse_expression()?;
|
||||||
(keyword + expr.span(), ConsoleFunction::Assert(expr))
|
self.expect(&Token::RightParen)?;
|
||||||
}
|
(keyword + expr.span(), ConsoleFunction::Assert(expr))
|
||||||
sym::assert_eq => {
|
}
|
||||||
self.expect(&Token::LeftParen)?;
|
sym::assert_eq => {
|
||||||
let left = self.parse_expression()?;
|
self.expect(&Token::LeftParen)?;
|
||||||
self.expect(&Token::Comma)?;
|
let left = self.parse_expression()?;
|
||||||
let right = self.parse_expression()?;
|
self.expect(&Token::Comma)?;
|
||||||
self.expect(&Token::RightParen)?;
|
let right = self.parse_expression()?;
|
||||||
(left.span() + right.span(), ConsoleFunction::AssertEq(left, right))
|
self.expect(&Token::RightParen)?;
|
||||||
}
|
(left.span() + right.span(), ConsoleFunction::AssertEq(left, right))
|
||||||
sym::assert_neq => {
|
}
|
||||||
self.expect(&Token::LeftParen)?;
|
sym::assert_neq => {
|
||||||
let left = self.parse_expression()?;
|
self.expect(&Token::LeftParen)?;
|
||||||
self.expect(&Token::Comma)?;
|
let left = self.parse_expression()?;
|
||||||
let right = self.parse_expression()?;
|
self.expect(&Token::Comma)?;
|
||||||
self.expect(&Token::RightParen)?;
|
let right = self.parse_expression()?;
|
||||||
(left.span() + right.span(), ConsoleFunction::AssertNeq(left, right))
|
self.expect(&Token::RightParen)?;
|
||||||
}
|
(left.span() + right.span(), ConsoleFunction::AssertNeq(left, right))
|
||||||
symbol => {
|
}
|
||||||
// Not sure what it is, assume it's `log`.
|
symbol => {
|
||||||
self.emit_err(ParserError::unexpected_ident(
|
// Not sure what it is, assume it's `log`.
|
||||||
symbol,
|
self.emit_err(
|
||||||
&["assert", "assert_eq", "assert_neq"],
|
ParserError::unexpected_ident(symbol, &["assert", "assert_eq", "assert_neq"], identifier.span)
|
||||||
identifier.span,
|
);
|
||||||
));
|
(
|
||||||
(
|
Default::default(),
|
||||||
Default::default(),
|
ConsoleFunction::Assert(Expression::Err(
|
||||||
ConsoleFunction::Assert(Expression::Err(ErrExpression {
|
ErrExpression { span: Default::default(), id: self.node_builder.next_id() }
|
||||||
span: Default::default(),
|
)),
|
||||||
id: self.node_builder.next_id(),
|
)
|
||||||
})),
|
}
|
||||||
)
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
self.expect(&Token::Semicolon)?;
|
self.expect(&Token::Semicolon)?;
|
||||||
|
|
||||||
Ok(ConsoleStatement { span: keyword + span, function, id: self.node_builder.next_id() })
|
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;
|
let return_type = &self.symbol_table.lookup_fn_symbol(function_name).unwrap().output_type;
|
||||||
match return_type {
|
match return_type {
|
||||||
Type::Unit => {} // Do nothing
|
Type::Unit => {} // Do nothing
|
||||||
Type::Tuple(tuple) => match tuple.length() {
|
Type::Tuple(tuple) => {
|
||||||
0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"),
|
match tuple.length() {
|
||||||
len => {
|
0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"),
|
||||||
for _ in 0..len {
|
len => {
|
||||||
let destination_register = format!("r{}", self.next_register);
|
for _ in 0..len {
|
||||||
destinations.push(destination_register);
|
let destination_register = format!("r{}", self.next_register);
|
||||||
self.next_register += 1;
|
destinations.push(destination_register);
|
||||||
|
self.next_register += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let destination_register = format!("r{}", self.next_register);
|
let destination_register = format!("r{}", self.next_register);
|
||||||
destinations.push(destination_register);
|
destinations.push(destination_register);
|
||||||
|
@ -55,18 +55,19 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_assert(&mut self, input: &'a AssertStatement) -> String {
|
fn visit_assert(&mut self, input: &'a AssertStatement) -> String {
|
||||||
let mut generate_assert_instruction = |name: &str, left: &'a Expression, right: &'a Expression| {
|
let mut generate_assert_instruction =
|
||||||
let (left_operand, left_instructions) = self.visit_expression(left);
|
|name: &str, left: &'a Expression, right: &'a Expression| {
|
||||||
let (right_operand, right_instructions) = self.visit_expression(right);
|
let (left_operand, left_instructions) = self.visit_expression(left);
|
||||||
let assert_instruction = format!(" {name} {left_operand} {right_operand};\n");
|
let (right_operand, right_instructions) = self.visit_expression(right);
|
||||||
|
let assert_instruction = format!(" {name} {left_operand} {right_operand};\n");
|
||||||
|
|
||||||
// Concatenate the instructions.
|
// Concatenate the instructions.
|
||||||
let mut instructions = left_instructions;
|
let mut instructions = left_instructions;
|
||||||
instructions.push_str(&right_instructions);
|
instructions.push_str(&right_instructions);
|
||||||
instructions.push_str(&assert_instruction);
|
instructions.push_str(&assert_instruction);
|
||||||
|
|
||||||
instructions
|
instructions
|
||||||
};
|
};
|
||||||
match &input.variant {
|
match &input.variant {
|
||||||
AssertVariant::Assert(expr) => {
|
AssertVariant::Assert(expr) => {
|
||||||
let (operand, mut instructions) = self.visit_expression(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 {
|
fn visit_return(&mut self, input: &'a ReturnStatement) -> String {
|
||||||
let mut outputs = match input.expression {
|
let mut outputs =
|
||||||
// Skip empty return statements.
|
match input.expression {
|
||||||
Expression::Unit(_) => String::new(),
|
// 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 (operand, mut expression_instructions) = self.visit_expression(&input.expression);
|
||||||
let output = if self.in_finalize {
|
// Get the output type of the function.
|
||||||
// Note that the first unwrap is safe, since `current_function` is set in `visit_function`.
|
let output = if self.in_finalize {
|
||||||
self.current_function.unwrap().finalize.as_ref().unwrap().output.iter()
|
// Note that the first unwrap is safe, since `current_function` is set in `visit_function`.
|
||||||
} else {
|
self.current_function.unwrap().finalize.as_ref().unwrap().output.iter()
|
||||||
// Note that this unwrap is safe, since `current_function` is set in `visit_function`.
|
} else {
|
||||||
self.current_function.unwrap().output.iter()
|
// 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() {
|
// If the operand string is empty, initialize an empty vector.
|
||||||
true => vec![],
|
let operand_strings = match operand.is_empty() {
|
||||||
false => operand.split(' ').collect_vec(),
|
true => vec![],
|
||||||
};
|
false => operand.split(' ').collect_vec(),
|
||||||
let instructions = operand_strings
|
};
|
||||||
.iter()
|
let instructions = operand_strings
|
||||||
.zip_eq(output)
|
.iter()
|
||||||
.map(|(operand, output)| {
|
.zip_eq(output)
|
||||||
match output {
|
.map(|(operand, output)| {
|
||||||
Output::Internal(output) => {
|
match output {
|
||||||
let visibility = if self.is_transition_function {
|
Output::Internal(output) => {
|
||||||
match self.in_finalize {
|
let visibility = if self.is_transition_function {
|
||||||
// If in finalize block, the default visibility is public.
|
match self.in_finalize {
|
||||||
true => match output.mode {
|
// If in finalize block, the default visibility is public.
|
||||||
Mode::None => Mode::Public,
|
true => match output.mode {
|
||||||
mode => mode,
|
Mode::None => Mode::Public,
|
||||||
},
|
mode => mode,
|
||||||
// If not in finalize block, the default visibility is private.
|
},
|
||||||
false => match output.mode {
|
// If not in finalize block, the default visibility is private.
|
||||||
Mode::None => Mode::Private,
|
false => match output.mode {
|
||||||
mode => mode,
|
Mode::None => Mode::Private,
|
||||||
},
|
mode => mode,
|
||||||
}
|
},
|
||||||
} else {
|
}
|
||||||
// Only program functions have visibilities associated with their outputs.
|
} else {
|
||||||
Mode::None
|
// Only program functions have visibilities associated with their outputs.
|
||||||
};
|
Mode::None
|
||||||
format!(
|
};
|
||||||
" output {} as {};\n",
|
format!(
|
||||||
operand,
|
" output {} as {};\n",
|
||||||
self.visit_type_with_visibility(&output.type_, visibility)
|
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!(
|
.join("");
|
||||||
" output {} as {}.aleo/{}.record;\n",
|
|
||||||
operand, output.program_name, output.record,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.join("");
|
|
||||||
|
|
||||||
expression_instructions.push_str(&instructions);
|
expression_instructions.push_str(&instructions);
|
||||||
|
|
||||||
expression_instructions
|
expression_instructions
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize storage for the instructions.
|
// Initialize storage for the instructions.
|
||||||
let mut instructions = String::new();
|
let mut instructions = String::new();
|
||||||
|
@ -55,10 +55,9 @@ impl SymbolTable {
|
|||||||
variant: func.variant,
|
variant: func.variant,
|
||||||
_span: func.span,
|
_span: func.span,
|
||||||
input: func.input.clone(),
|
input: func.input.clone(),
|
||||||
finalize: func.finalize.as_ref().map(|finalize| FinalizeData {
|
finalize: func.finalize.as_ref().map(
|
||||||
input: finalize.input.clone(),
|
|finalize| FinalizeData { input: finalize.input.clone(), output_type: finalize.output_type.clone() }
|
||||||
output_type: finalize.output_type.clone(),
|
),
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,12 +87,13 @@ impl StatementReconstructor for DeadCodeEliminator<'_> {
|
|||||||
self.is_necessary = true;
|
self.is_necessary = true;
|
||||||
|
|
||||||
// Visit the statement.
|
// Visit the statement.
|
||||||
let statement = Statement::Assign(Box::new(AssignStatement {
|
let statement =
|
||||||
place: input.place,
|
Statement::Assign(Box::new(AssignStatement {
|
||||||
value: self.reconstruct_expression(input.value).0,
|
place: input.place,
|
||||||
span: input.span,
|
value: self.reconstruct_expression(input.value).0,
|
||||||
id: input.id,
|
span: input.span,
|
||||||
}));
|
id: input.id,
|
||||||
|
}));
|
||||||
|
|
||||||
// Unset the `is_necessary` flag.
|
// Unset the `is_necessary` flag.
|
||||||
self.is_necessary = false;
|
self.is_necessary = false;
|
||||||
@ -181,14 +182,15 @@ impl StatementReconstructor for DeadCodeEliminator<'_> {
|
|||||||
self.is_necessary = true;
|
self.is_necessary = true;
|
||||||
|
|
||||||
// Visit the statement.
|
// Visit the statement.
|
||||||
let statement = Statement::Return(ReturnStatement {
|
let statement =
|
||||||
expression: self.reconstruct_expression(input.expression).0,
|
Statement::Return(ReturnStatement {
|
||||||
finalize_arguments: input.finalize_arguments.map(|arguments| {
|
expression: self.reconstruct_expression(input.expression).0,
|
||||||
arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect()
|
finalize_arguments: input.finalize_arguments.map(|arguments| {
|
||||||
}),
|
arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect()
|
||||||
span: input.span,
|
}),
|
||||||
id: input.id,
|
span: input.span,
|
||||||
});
|
id: input.id,
|
||||||
|
});
|
||||||
|
|
||||||
// Unset the `is_necessary` flag.
|
// Unset the `is_necessary` flag.
|
||||||
self.is_necessary = false;
|
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.
|
// 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)) => {
|
(Expression::Tuple(lhs_tuple), Expression::Tuple(rhs_tuple)) => {
|
||||||
let statements = lhs_tuple
|
let statements =
|
||||||
.elements
|
lhs_tuple
|
||||||
.into_iter()
|
.elements
|
||||||
.zip_eq(rhs_tuple.elements)
|
.into_iter()
|
||||||
.map(|(lhs, rhs)| {
|
.zip_eq(rhs_tuple.elements)
|
||||||
// Get the type of the rhs.
|
.map(|(lhs, rhs)| {
|
||||||
let type_ = match self.type_table.get(&lhs.id()) {
|
// Get the type of the rhs.
|
||||||
Some(type_) => type_.clone(),
|
let type_ = match self.type_table.get(&lhs.id()) {
|
||||||
None => {
|
Some(type_) => type_.clone(),
|
||||||
unreachable!("Type checking guarantees that the type of the lhs is in the type table.")
|
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 {
|
// Set the type of the lhs.
|
||||||
place: lhs,
|
self.type_table.insert(rhs.id(), type_);
|
||||||
value: rhs,
|
// Return the assign statement.
|
||||||
span: Default::default(),
|
Statement::Assign(Box::new(AssignStatement {
|
||||||
id: self.node_builder.next_id(),
|
place: lhs,
|
||||||
}))
|
value: rhs,
|
||||||
})
|
span: Default::default(),
|
||||||
.collect();
|
id: self.node_builder.next_id(),
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
(Statement::dummy(Default::default(), self.node_builder.next_id()), statements)
|
(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.
|
// 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();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
// Flatten the arguments of the assert statement.
|
// Flatten the arguments of the assert statement.
|
||||||
let assert = AssertStatement {
|
let assert =
|
||||||
span: input.span,
|
AssertStatement {
|
||||||
id: input.id,
|
span: input.span,
|
||||||
variant: match input.variant {
|
id: input.id,
|
||||||
AssertVariant::Assert(expression) => {
|
variant: match input.variant {
|
||||||
let (expression, additional_statements) = self.reconstruct_expression(expression);
|
AssertVariant::Assert(expression) => {
|
||||||
statements.extend(additional_statements);
|
let (expression, additional_statements) = self.reconstruct_expression(expression);
|
||||||
AssertVariant::Assert(expression)
|
statements.extend(additional_statements);
|
||||||
}
|
AssertVariant::Assert(expression)
|
||||||
AssertVariant::AssertEq(left, right) => {
|
}
|
||||||
let (left, additional_statements) = self.reconstruct_expression(left);
|
AssertVariant::AssertEq(left, right) => {
|
||||||
statements.extend(additional_statements);
|
let (left, additional_statements) = self.reconstruct_expression(left);
|
||||||
let (right, additional_statements) = self.reconstruct_expression(right);
|
statements.extend(additional_statements);
|
||||||
statements.extend(additional_statements);
|
let (right, additional_statements) = self.reconstruct_expression(right);
|
||||||
AssertVariant::AssertEq(left, right)
|
statements.extend(additional_statements);
|
||||||
}
|
AssertVariant::AssertEq(left, right)
|
||||||
AssertVariant::AssertNeq(left, right) => {
|
}
|
||||||
let (left, additional_statements) = self.reconstruct_expression(left);
|
AssertVariant::AssertNeq(left, right) => {
|
||||||
statements.extend(additional_statements);
|
let (left, additional_statements) = self.reconstruct_expression(left);
|
||||||
let (right, additional_statements) = self.reconstruct_expression(right);
|
statements.extend(additional_statements);
|
||||||
statements.extend(additional_statements);
|
let (right, additional_statements) = self.reconstruct_expression(right);
|
||||||
AssertVariant::AssertNeq(left, right)
|
statements.extend(additional_statements);
|
||||||
}
|
AssertVariant::AssertNeq(left, right)
|
||||||
},
|
}
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Add the appropriate guards.
|
// Add the appropriate guards.
|
||||||
match self.construct_guard() {
|
match self.construct_guard() {
|
||||||
|
@ -392,68 +392,71 @@ impl<'a> Flattener<'a> {
|
|||||||
// Initialize a vector to accumulate any statements generated.
|
// Initialize a vector to accumulate any statements generated.
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
// For each struct member, construct a new ternary expression.
|
// For each struct member, construct a new ternary expression.
|
||||||
let members = struct_
|
let members =
|
||||||
.members
|
struct_
|
||||||
.iter()
|
.members
|
||||||
.map(|Member { identifier, type_, .. }| {
|
.iter()
|
||||||
// Create an assignment statement for the first access expression.
|
.map(|Member { identifier, type_, .. }| {
|
||||||
let (first, stmt) =
|
// Create an assignment statement for the first access expression.
|
||||||
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Member(MemberAccess {
|
let (first, stmt) = self.unique_simple_assign_statement(Expression::Access(
|
||||||
inner: Box::new(Expression::Identifier(*first)),
|
AccessExpression::Member(MemberAccess {
|
||||||
name: *identifier,
|
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(),
|
span: Default::default(),
|
||||||
id: {
|
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();
|
let id = self.node_builder.next_id();
|
||||||
// Set the type of the node ID.
|
// Set the type of the node ID.
|
||||||
self.type_table.insert(id, type_.clone());
|
self.type_table.insert(id, type_.clone());
|
||||||
id
|
id
|
||||||
},
|
},
|
||||||
})));
|
});
|
||||||
statements.push(stmt);
|
|
||||||
// Create an assignment statement for the second access expression.
|
// Accumulate any statements generated.
|
||||||
let (second, stmt) =
|
statements.extend(stmts);
|
||||||
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Member(MemberAccess {
|
|
||||||
inner: Box::new(Expression::Identifier(*second)),
|
StructVariableInitializer {
|
||||||
name: *identifier,
|
identifier: *identifier,
|
||||||
|
expression: Some(expression),
|
||||||
span: Default::default(),
|
span: Default::default(),
|
||||||
id: {
|
id: self.node_builder.next_id(),
|
||||||
// Create a new node ID for the access expression.
|
}
|
||||||
let id = self.node_builder.next_id();
|
})
|
||||||
// Set the type of the node ID.
|
.collect();
|
||||||
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();
|
|
||||||
|
|
||||||
let (expr, stmts) = self.reconstruct_struct_init(StructExpression {
|
let (expr, stmts) = self.reconstruct_struct_init(StructExpression {
|
||||||
name: struct_.identifier,
|
name: struct_.identifier,
|
||||||
@ -489,65 +492,66 @@ impl<'a> Flattener<'a> {
|
|||||||
// Initialize a vector to accumulate any statements generated.
|
// Initialize a vector to accumulate any statements generated.
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
// For each tuple element, construct a new ternary expression.
|
// For each tuple element, construct a new ternary expression.
|
||||||
let elements = tuple_type
|
let elements =
|
||||||
.elements()
|
tuple_type
|
||||||
.iter()
|
.elements()
|
||||||
.enumerate()
|
.iter()
|
||||||
.map(|(i, type_)| {
|
.enumerate()
|
||||||
// Create an assignment statement for the first access expression.
|
.map(|(i, type_)| {
|
||||||
let (first, stmt) =
|
// Create an assignment statement for the first access expression.
|
||||||
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess {
|
let (first, stmt) =
|
||||||
tuple: Box::new(Expression::Identifier(*first)),
|
self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess {
|
||||||
index: NonNegativeNumber::from(i),
|
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(),
|
span: Default::default(),
|
||||||
id: {
|
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();
|
let id = self.node_builder.next_id();
|
||||||
// Set the type of the node ID.
|
// Set the type of the node ID.
|
||||||
self.type_table.insert(id, type_.clone());
|
self.type_table.insert(id, type_.clone());
|
||||||
id
|
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.
|
// Accumulate any statements generated.
|
||||||
let (expression, stmts) = self.reconstruct_ternary(TernaryExpression {
|
statements.extend(stmts);
|
||||||
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.
|
expression
|
||||||
statements.extend(stmts);
|
})
|
||||||
|
.collect();
|
||||||
expression
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Construct the tuple expression.
|
// Construct the tuple expression.
|
||||||
let tuple = TupleExpression {
|
let tuple = TupleExpression {
|
||||||
|
@ -192,41 +192,42 @@ impl<'a> Unroller<'a> {
|
|||||||
self.type_table.insert(id, input.type_.clone());
|
self.type_table.insert(id, input.type_.clone());
|
||||||
|
|
||||||
// Reconstruct `iteration_count` as a `Literal`.
|
// Reconstruct `iteration_count` as a `Literal`.
|
||||||
let value = match input.type_ {
|
let value =
|
||||||
Type::Integer(IntegerType::I8) => {
|
match input.type_ {
|
||||||
Literal::Integer(IntegerType::I8, iteration_count.to_string(), Default::default(), id)
|
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::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::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::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::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::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::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::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::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)
|
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."
|
_ => 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
|
// Add the loop variable as a constant for the current scope
|
||||||
self.constant_propagation_table
|
self.constant_propagation_table
|
||||||
|
@ -207,12 +207,13 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
|||||||
let (expression, mut statements) = self.consume_expression(*input.expression);
|
let (expression, mut statements) = self.consume_expression(*input.expression);
|
||||||
|
|
||||||
// Construct and accumulate a unique assignment statement storing the result of the cast 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 {
|
let (place, statement) =
|
||||||
expression: Box::new(expression),
|
self.unique_simple_assign_statement(Expression::Cast(CastExpression {
|
||||||
type_: input.type_,
|
expression: Box::new(expression),
|
||||||
span: input.span,
|
type_: input.type_,
|
||||||
id: input.id,
|
span: input.span,
|
||||||
}));
|
id: input.id,
|
||||||
|
}));
|
||||||
statements.push(statement);
|
statements.push(statement);
|
||||||
|
|
||||||
(Expression::Identifier(place), statements)
|
(Expression::Identifier(place), statements)
|
||||||
@ -280,12 +281,13 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct and accumulate a new assignment statement for the struct expression.
|
// Construct and accumulate a new assignment statement for the struct expression.
|
||||||
let (place, statement) = self.unique_simple_assign_statement(Expression::Struct(StructExpression {
|
let (place, statement) =
|
||||||
name: input.name,
|
self.unique_simple_assign_statement(Expression::Struct(StructExpression {
|
||||||
span: input.span,
|
name: input.name,
|
||||||
members: reordered_members,
|
span: input.span,
|
||||||
id: input.id,
|
members: reordered_members,
|
||||||
}));
|
id: input.id,
|
||||||
|
}));
|
||||||
statements.push(statement);
|
statements.push(statement);
|
||||||
|
|
||||||
(Expression::Identifier(place), statements)
|
(Expression::Identifier(place), statements)
|
||||||
@ -375,12 +377,9 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
|||||||
let (receiver, mut statements) = self.consume_expression(*input.receiver);
|
let (receiver, mut statements) = self.consume_expression(*input.receiver);
|
||||||
|
|
||||||
// Construct and accumulate a new assignment statement for the unary expression.
|
// Construct and accumulate a new assignment statement for the unary expression.
|
||||||
let (place, statement) = self.unique_simple_assign_statement(Expression::Unary(UnaryExpression {
|
let (place, statement) = self.unique_simple_assign_statement(Expression::Unary(
|
||||||
op: input.op,
|
UnaryExpression { op: input.op, receiver: Box::new(receiver), span: input.span, id: input.id }
|
||||||
receiver: Box::new(receiver),
|
));
|
||||||
span: input.span,
|
|
||||||
id: input.id,
|
|
||||||
}));
|
|
||||||
statements.push(statement);
|
statements.push(statement);
|
||||||
|
|
||||||
(Expression::Identifier(place), statements)
|
(Expression::Identifier(place), statements)
|
||||||
|
@ -198,13 +198,14 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
|||||||
self.type_table.insert(id, type_);
|
self.type_table.insert(id, type_);
|
||||||
|
|
||||||
// Construct a ternary expression for the phi function.
|
// Construct a ternary expression for the phi function.
|
||||||
let (value, stmts) = self.consume_ternary(TernaryExpression {
|
let (value, stmts) =
|
||||||
condition: Box::new(condition.clone()),
|
self.consume_ternary(TernaryExpression {
|
||||||
if_true,
|
condition: Box::new(condition.clone()),
|
||||||
if_false,
|
if_true,
|
||||||
span: Default::default(),
|
if_false,
|
||||||
id,
|
span: Default::default(),
|
||||||
});
|
id,
|
||||||
|
});
|
||||||
|
|
||||||
statements.extend(stmts);
|
statements.extend(stmts);
|
||||||
|
|
||||||
@ -290,22 +291,17 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct the lhs of the assignment.
|
// Construct the lhs of the assignment.
|
||||||
let place = Expression::Tuple(TupleExpression {
|
let place = Expression::Tuple(
|
||||||
elements,
|
TupleExpression { elements, span: Default::default(), id: self.node_builder.next_id() }
|
||||||
span: Default::default(),
|
);
|
||||||
id: self.node_builder.next_id(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the type of the lhs.
|
// Update the type of the lhs.
|
||||||
self.type_table.insert(place.id(), Type::Tuple(tuple_type_));
|
self.type_table.insert(place.id(), Type::Tuple(tuple_type_));
|
||||||
|
|
||||||
// Create the assignment statement.
|
// Create the assignment statement.
|
||||||
let assignment = Statement::Assign(Box::new(AssignStatement {
|
let assignment = Statement::Assign(
|
||||||
place,
|
Box::new(AssignStatement { place, value, span: definition.span, id: definition.id })
|
||||||
value,
|
);
|
||||||
span: definition.span,
|
|
||||||
id: definition.id,
|
|
||||||
}));
|
|
||||||
|
|
||||||
statements.push(assignment);
|
statements.push(assignment);
|
||||||
}
|
}
|
||||||
@ -401,12 +397,9 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add the simplified return statement to the list of produced statements.
|
// Add the simplified return statement to the list of produced statements.
|
||||||
statements.push(Statement::Return(ReturnStatement {
|
statements.push(Statement::Return(
|
||||||
expression,
|
ReturnStatement { expression, finalize_arguments: finalize_args, span: input.span, id: input.id }
|
||||||
finalize_arguments: finalize_args,
|
));
|
||||||
span: input.span,
|
|
||||||
id: input.id,
|
|
||||||
}));
|
|
||||||
|
|
||||||
statements
|
statements
|
||||||
}
|
}
|
||||||
|
@ -235,10 +235,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
|||||||
self.emit_err(TypeCheckerError::type_should_be(type_, "struct", access.inner.span()));
|
self.emit_err(TypeCheckerError::type_should_be(type_, "struct", access.inner.span()));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.emit_err(TypeCheckerError::could_not_determine_type(
|
self.emit_err(
|
||||||
&access.inner,
|
TypeCheckerError::could_not_determine_type(&access.inner, access.inner.span())
|
||||||
access.inner.span(),
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,11 +287,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
// The array cannot have more than `MAX_ARRAY_ELEMENTS` elements.
|
// The array cannot have more than `MAX_ARRAY_ELEMENTS` elements.
|
||||||
num_elements => {
|
num_elements => {
|
||||||
self.emit_err(TypeCheckerError::array_too_large(
|
self.emit_err(
|
||||||
num_elements,
|
TypeCheckerError::array_too_large(num_elements, Testnet3::MAX_ARRAY_ELEMENTS, input.span())
|
||||||
Testnet3::MAX_ARRAY_ELEMENTS,
|
);
|
||||||
input.span(),
|
|
||||||
));
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -121,18 +121,19 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
|||||||
|
|
||||||
// For records, enforce presence of the `owner: Address` member.
|
// For records, enforce presence of the `owner: Address` member.
|
||||||
if input.is_record {
|
if input.is_record {
|
||||||
let check_has_field =
|
let check_has_field = |need, expected_ty: Type| match input
|
||||||
|need, expected_ty: Type| match input.members.iter().find_map(|Member { identifier, type_, .. }| {
|
.members
|
||||||
(identifier.name == need).then_some((identifier, type_))
|
.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, _)) => {
|
Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type!
|
||||||
self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span()));
|
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()));
|
None => {
|
||||||
}
|
self.emit_err(TypeCheckerError::required_record_variable(need, expected_ty, input.span()));
|
||||||
};
|
}
|
||||||
|
};
|
||||||
check_has_field(sym::owner, Type::Address);
|
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) {
|
let var_type =
|
||||||
match &var.declaration {
|
if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(var_name.name) {
|
||||||
VariableType::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)),
|
match &var.declaration {
|
||||||
VariableType::Input(Mode::Constant) => {
|
VariableType::Const => {
|
||||||
self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span))
|
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())
|
Some(var.type_.clone())
|
||||||
} else {
|
} else {
|
||||||
self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span));
|
self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span));
|
||||||
|
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
if var_type.is_some() {
|
if var_type.is_some() {
|
||||||
self.visit_expression(&input.value, &var_type);
|
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
|
// Enforce that Constant variables have literal expressions on right-hand side
|
||||||
match &input.value {
|
match &input.value {
|
||||||
Expression::Literal(_) => (),
|
Expression::Literal(_) => (),
|
||||||
Expression::Tuple(tuple_expression) => match tuple_expression.elements.len() {
|
Expression::Tuple(tuple_expression) => {
|
||||||
0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."),
|
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(
|
if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) {
|
||||||
input.span,
|
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())),
|
_ => 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> {
|
) -> Option<Type> {
|
||||||
// Check that the number of arguments is correct.
|
// Check that the number of arguments is correct.
|
||||||
if arguments.len() != core_function.num_args() {
|
if arguments.len() != core_function.num_args() {
|
||||||
self.emit_err(TypeCheckerError::incorrect_num_args_to_call(
|
self.emit_err(
|
||||||
core_function.num_args(),
|
TypeCheckerError::incorrect_num_args_to_call(core_function.num_args(), arguments.len(), function_span)
|
||||||
arguments.len(),
|
);
|
||||||
function_span,
|
|
||||||
));
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -982,10 +980,9 @@ impl<'a> TypeChecker<'a> {
|
|||||||
CoreFunction::MappingContains => {
|
CoreFunction::MappingContains => {
|
||||||
// Check that the operation is invoked in a `finalize` block.
|
// Check that the operation is invoked in a `finalize` block.
|
||||||
if !self.is_finalize {
|
if !self.is_finalize {
|
||||||
self.handler.emit_err(TypeCheckerError::invalid_operation_outside_finalize(
|
self.handler.emit_err(
|
||||||
"Mapping::contains",
|
TypeCheckerError::invalid_operation_outside_finalize("Mapping::contains", function_span)
|
||||||
function_span,
|
)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
// Check that the first argument is a mapping.
|
// Check that the first argument is a mapping.
|
||||||
if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) {
|
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.
|
/// Returns a displayable representation of the `span` as a string.
|
||||||
pub fn span_to_string(&self, span: Span) -> String {
|
pub fn span_to_string(&self, span: Span) -> String {
|
||||||
let loc = match self.span_to_location(span) {
|
let loc =
|
||||||
None => return "no-location".to_string(),
|
match self.span_to_location(span) {
|
||||||
Some(l) => l,
|
None => return "no-location".to_string(),
|
||||||
};
|
Some(l) => l,
|
||||||
|
};
|
||||||
|
|
||||||
if loc.line_start == loc.line_stop {
|
if loc.line_start == loc.line_stop {
|
||||||
format!("{}:{}-{}", loc.line_start, loc.col_start, loc.col_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 gap_len = 0;
|
||||||
let mut tail = buf.as_mut_slice();
|
let mut tail = buf.as_mut_slice();
|
||||||
loop {
|
loop {
|
||||||
let idx = match find_crlf(&tail[gap_len..]) {
|
let idx =
|
||||||
None => tail.len(),
|
match find_crlf(&tail[gap_len..]) {
|
||||||
Some(idx) => idx + gap_len,
|
None => tail.len(),
|
||||||
};
|
Some(idx) => idx + gap_len,
|
||||||
|
};
|
||||||
tail.copy_within(gap_len..idx, 0);
|
tail.copy_within(gap_len..idx, 0);
|
||||||
tail = &mut tail[idx - gap_len..];
|
tail = &mut tail[idx - gap_len..];
|
||||||
if tail.len() == gap_len {
|
if tail.len() == gap_len {
|
||||||
|
@ -205,10 +205,11 @@ fn main() -> Result<()> {
|
|||||||
// Parse ABNF to get list of all definitions.
|
// Parse ABNF to get list of all definitions.
|
||||||
// Rust ABNF does not provide support for `%s` (case sensitive strings, part of
|
// Rust ABNF does not provide support for `%s` (case sensitive strings, part of
|
||||||
// the standard); so we need to remove all occurrences before parsing.
|
// the standard); so we need to remove all occurrences before parsing.
|
||||||
let parsed = abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| {
|
let parsed =
|
||||||
eprintln!("{}", &e);
|
abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| {
|
||||||
anyhow::anyhow!(e)
|
eprintln!("{}", &e);
|
||||||
})?;
|
anyhow::anyhow!(e)
|
||||||
|
})?;
|
||||||
|
|
||||||
// Init parser and run it. That's it.
|
// Init parser and run it. That's it.
|
||||||
let mut parser = Processor::new(&grammar, parsed);
|
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> {
|
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {
|
||||||
// If input values are provided, then run the program with those inputs.
|
// If input values are provided, then run the program with those inputs.
|
||||||
// Otherwise, use the input file.
|
// Otherwise, use the input file.
|
||||||
let mut inputs = match self.inputs.is_empty() {
|
let mut inputs =
|
||||||
true => match input {
|
match self.inputs.is_empty() {
|
||||||
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
|
true => match input {
|
||||||
_ => Vec::new(),
|
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
|
||||||
},
|
_ => Vec::new(),
|
||||||
false => self.inputs,
|
},
|
||||||
};
|
false => self.inputs,
|
||||||
|
};
|
||||||
|
|
||||||
// Compose the `execute` command.
|
// Compose the `execute` command.
|
||||||
let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name];
|
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> {
|
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {
|
||||||
// If input values are provided, then run the program with those inputs.
|
// If input values are provided, then run the program with those inputs.
|
||||||
// Otherwise, use the input file.
|
// Otherwise, use the input file.
|
||||||
let mut inputs = match self.inputs.is_empty() {
|
let mut inputs =
|
||||||
true => match input {
|
match self.inputs.is_empty() {
|
||||||
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
|
true => match input {
|
||||||
_ => Vec::new(),
|
(Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits),
|
||||||
},
|
_ => Vec::new(),
|
||||||
false => self.inputs,
|
},
|
||||||
};
|
false => self.inputs,
|
||||||
|
};
|
||||||
|
|
||||||
// Compose the `run` command.
|
// Compose the `run` command.
|
||||||
let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name];
|
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>)> {
|
pub fn read_from<'a>(&self, path: &'a Path) -> Result<(String, Cow<'a, Path>)> {
|
||||||
let path = self.setup_file_path(path);
|
let path = self.setup_file_path(path);
|
||||||
|
|
||||||
let input = fs::read_to_string(&path)
|
let input =
|
||||||
.map_err(|_| PackageError::failed_to_read_input_file(path.clone().into_owned()))?;
|
fs::read_to_string(&path).map_err(|_| PackageError::failed_to_read_input_file(path.clone().into_owned()))?;
|
||||||
Ok((input, path))
|
Ok((input, path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,12 +93,13 @@ impl TestCases {
|
|||||||
let mut path_prefix = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
let mut path_prefix = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
path_prefix.push("../../tests");
|
path_prefix.push("../../tests");
|
||||||
|
|
||||||
let mut new = Self {
|
let mut new =
|
||||||
tests: Vec::new(),
|
Self {
|
||||||
path_prefix,
|
tests: Vec::new(),
|
||||||
expectation_category: expectation_category.to_string(),
|
path_prefix,
|
||||||
fail_categories: Vec::new(),
|
expectation_category: expectation_category.to_string(),
|
||||||
};
|
fail_categories: Vec::new(),
|
||||||
|
};
|
||||||
let tests = new.load_tests(additional_check);
|
let tests = new.load_tests(additional_check);
|
||||||
(new, tests)
|
(new, tests)
|
||||||
}
|
}
|
||||||
@ -188,10 +189,11 @@ pub fn run_tests<T: Runner>(runner: &T, expectation_category: &str) {
|
|||||||
|
|
||||||
let mut outputs = vec![];
|
let mut outputs = vec![];
|
||||||
cases.process_tests(configs, |cases, (path, content, test_name, config)| {
|
cases.process_tests(configs, |cases, (path, content, test_name, config)| {
|
||||||
let namespace = match runner.resolve_namespace(&config.namespace) {
|
let namespace =
|
||||||
Some(ns) => ns,
|
match runner.resolve_namespace(&config.namespace) {
|
||||||
None => return,
|
Some(ns) => ns,
|
||||||
};
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
let (expectation_path, expectations) = cases.load_expectations(path);
|
let (expectation_path, expectations) = cases.load_expectations(path);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user