mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 13:56:58 +03:00
Clean up AssemblyBlock parser, fix errors
This commit is contained in:
parent
73c761149f
commit
1036113be9
@ -498,7 +498,7 @@ impl ParserContext<'_> {
|
|||||||
/// - self
|
/// - self
|
||||||
///
|
///
|
||||||
/// Returns an expression error if the token cannot be matched.
|
/// Returns an expression error if the token cannot be matched.
|
||||||
fn parse_primary_expression(&mut self) -> Result<Expression> {
|
pub fn parse_primary_expression(&mut self) -> Result<Expression> {
|
||||||
if let Token::LeftParen = self.token.token {
|
if let Token::LeftParen = self.token.token {
|
||||||
return self.parse_tuple_expression();
|
return self.parse_tuple_expression();
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,9 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// TODO: Consider designing a separate Parser for instructions. This would improve modularity at the
|
// TODO: We currently rely on the Leo tokenizer and parser to parse the assembly block.
|
||||||
// cost of building/managing the new parser.
|
// Consider designing a separate Parser for instructions.
|
||||||
|
// This would improve modularity, reduce the likelihood of errors, improve error handling, at the cost of building, linking, and managing the new parser.
|
||||||
// TODO: If snarkVM instructions are used directly, then we should directly use the associated instruction parsers.
|
// TODO: If snarkVM instructions are used directly, then we should directly use the associated instruction parsers.
|
||||||
|
|
||||||
use crate::{ParserContext, Token};
|
use crate::{ParserContext, Token};
|
||||||
@ -25,31 +26,40 @@ use leo_ast::{
|
|||||||
LessThanOrEqual, Mul, Node, Nop, Not, Operand, Or, Sub, Ternary,
|
LessThanOrEqual, Mul, Node, Nop, Not, Operand, Or, Sub, Ternary,
|
||||||
};
|
};
|
||||||
use leo_errors::{ParserError, Result};
|
use leo_errors::{ParserError, Result};
|
||||||
use leo_span::Span;
|
use leo_span::{sym, Span};
|
||||||
|
|
||||||
// TODO: Note that this design is a prototype.
|
|
||||||
impl ParserContext<'_> {
|
impl ParserContext<'_> {
|
||||||
pub fn parse_instruction(&mut self) -> Result<Instruction> {
|
pub fn parse_instruction(&mut self) -> Result<Instruction> {
|
||||||
// Parse the opcode. Since we are using the Leo tokenizer, the opcode will be tokenized as an identifier.
|
// Parse the opcode. Since we are using the Leo tokenizer, the opcode will be tokenized as an identifier.
|
||||||
let identifier = self.expect_ident()?;
|
let identifier = self.expect_ident()?;
|
||||||
match &*identifier.name.as_str() {
|
match identifier.name {
|
||||||
"add" => self.parse_add_instruction(identifier.span),
|
sym::add => self.parse_add_instruction(identifier.span),
|
||||||
"and" => self.parse_and_instruction(identifier.span),
|
sym::and => self.parse_and_instruction(identifier.span),
|
||||||
"div" => self.parse_div_instruction(identifier.span),
|
sym::div => self.parse_div_instruction(identifier.span),
|
||||||
"gt" => self.parse_greater_than_instruction(identifier.span),
|
sym::gt => self.parse_greater_than_instruction(identifier.span),
|
||||||
"gte" => self.parse_greater_than_or_equal_instruction(identifier.span),
|
sym::gte => self.parse_greater_than_or_equal_instruction(identifier.span),
|
||||||
"eq" => self.parse_equal_instruction(identifier.span),
|
sym::eq => self.parse_equal_instruction(identifier.span),
|
||||||
"neq" => self.parse_not_equal_instruction(identifier.span),
|
sym::neq => self.parse_not_equal_instruction(identifier.span),
|
||||||
"lt" => self.parse_less_than_instruction(identifier.span),
|
sym::lt => self.parse_less_than_instruction(identifier.span),
|
||||||
"lte" => self.parse_less_than_or_equal_instruction(identifier.span),
|
sym::lte => self.parse_less_than_or_equal_instruction(identifier.span),
|
||||||
"mul" => self.parse_mul_instruction(identifier.span),
|
sym::mul => self.parse_mul_instruction(identifier.span),
|
||||||
"not" => self.parse_not_instruction(identifier.span),
|
sym::not => self.parse_not_instruction(identifier.span),
|
||||||
"or" => self.parse_or_instruction(identifier.span),
|
sym::or => self.parse_or_instruction(identifier.span),
|
||||||
"sub" => self.parse_sub_instruction(identifier.span),
|
sym::sub => self.parse_sub_instruction(identifier.span),
|
||||||
"ter" => self.parse_ternary_instruction(identifier.span),
|
sym::ter => self.parse_ternary_instruction(identifier.span),
|
||||||
_ => {
|
_ => {
|
||||||
self.emit_err(ParserError::invalid_opcode_in_assembly_instruction(identifier.span));
|
self.emit_err(ParserError::invalid_opcode_in_assembly_instruction(identifier.span));
|
||||||
// TODO: Do we need to eat tokens here?
|
// Attempt to recover the parser by eating tokens until we find a semi-colon or closing bracket.
|
||||||
|
while !(self.check(&Token::Eof) || self.check(&Token::RightCurly) || self.check(&Token::Semicolon)) {
|
||||||
|
self.bump();
|
||||||
|
}
|
||||||
|
if let Ok(span) = self.expect(&Token::Eof) {
|
||||||
|
self.emit_err(ParserError::unexpected_eof(span));
|
||||||
|
} else if let Ok(span) = self.expect(&Token::RightCurly) {
|
||||||
|
self.emit_err(ParserError::unexpected_end_of_assembly_block(span));
|
||||||
|
} else {
|
||||||
|
self.expect(&Token::Semicolon)?;
|
||||||
|
}
|
||||||
Ok(Instruction::Nop(Nop { span: identifier.span }))
|
Ok(Instruction::Nop(Nop { span: identifier.span }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,18 +263,16 @@ impl ParserContext<'_> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Better error handling.
|
|
||||||
// Separate tokens and symbols for assembly block.
|
|
||||||
pub fn expect_into(&mut self) -> Result<()> {
|
pub fn expect_into(&mut self) -> Result<()> {
|
||||||
let identifier = self.expect_ident()?;
|
let identifier = self.expect_ident()?;
|
||||||
match &*identifier.name.as_str() {
|
match identifier.name {
|
||||||
"into" => Ok(()),
|
sym::into => Ok(()),
|
||||||
string => Err(ParserError::unexpected(string, "into", identifier.span).into()),
|
symbol => Err(ParserError::unexpected(symbol.as_str(), "`into`", identifier.span).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_operand(&mut self) -> Result<Operand> {
|
pub fn parse_operand(&mut self) -> Result<Operand> {
|
||||||
let expression = self.parse_expression()?;
|
let expression = self.parse_primary_expression()?;
|
||||||
match expression {
|
match expression {
|
||||||
Expression::Identifier(identifier) => Ok(Operand::Identifier(identifier)),
|
Expression::Identifier(identifier) => Ok(Operand::Identifier(identifier)),
|
||||||
Expression::Literal(literal) => Ok(Operand::Literal(literal)),
|
Expression::Literal(literal) => Ok(Operand::Literal(literal)),
|
||||||
|
@ -426,4 +426,12 @@ create_messages!(
|
|||||||
msg: format!("Invalid operand in assembly block. Operands must be `Identifier`s or `LiteralExpressions`."),
|
msg: format!("Invalid operand in assembly block. Operands must be `Identifier`s or `LiteralExpressions`."),
|
||||||
help: None,
|
help: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For when the parser encountered an unexpected end of assembly block.
|
||||||
|
@formatted
|
||||||
|
unexpected_end_of_assembly_block {
|
||||||
|
args: (),
|
||||||
|
msg: "Unexpected end of assembly block.",
|
||||||
|
help: None,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
@ -137,6 +137,9 @@ symbols! {
|
|||||||
sub_wrapped,
|
sub_wrapped,
|
||||||
xor,
|
xor,
|
||||||
|
|
||||||
|
// ternary operators
|
||||||
|
ter,
|
||||||
|
|
||||||
// core circuits
|
// core circuits
|
||||||
BHP256,
|
BHP256,
|
||||||
BHP512,
|
BHP512,
|
||||||
@ -221,6 +224,9 @@ symbols! {
|
|||||||
state_leaf,
|
state_leaf,
|
||||||
public,
|
public,
|
||||||
private,
|
private,
|
||||||
|
|
||||||
|
// Assembly specific symbols
|
||||||
|
into,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An interned string.
|
/// An interned string.
|
||||||
|
@ -14,81 +14,67 @@ outputs:
|
|||||||
hi: 11
|
hi: 11
|
||||||
- AssemblyBlock:
|
- AssemblyBlock:
|
||||||
instructions:
|
instructions:
|
||||||
- opcode: Add
|
- Add:
|
||||||
operands:
|
first:
|
||||||
- Identifier: "{\"name\":\"r1\",\"span\":\"{\\\"lo\\\":15,\\\"hi\\\":17}\"}"
|
Identifier: "{\"name\":\"r1\",\"span\":\"{\\\"lo\\\":15,\\\"hi\\\":17}\"}"
|
||||||
- Identifier: "{\"name\":\"r2\",\"span\":\"{\\\"lo\\\":18,\\\"hi\\\":20}\"}"
|
second:
|
||||||
destinations:
|
Identifier: "{\"name\":\"r2\",\"span\":\"{\\\"lo\\\":18,\\\"hi\\\":20}\"}"
|
||||||
- "{\"name\":\"r3\",\"span\":\"{\\\"lo\\\":26,\\\"hi\\\":28}\"}"
|
destination: "{\"name\":\"r3\",\"span\":\"{\\\"lo\\\":26,\\\"hi\\\":28}\"}"
|
||||||
span:
|
span:
|
||||||
lo: 11
|
lo: 11
|
||||||
hi: 29
|
hi: 28
|
||||||
span:
|
span:
|
||||||
lo: 0
|
lo: 0
|
||||||
hi: 31
|
hi: 31
|
||||||
- AssemblyBlock:
|
- AssemblyBlock:
|
||||||
instructions:
|
instructions:
|
||||||
- opcode: Add
|
- Add:
|
||||||
operands:
|
first:
|
||||||
- Identifier: "{\"name\":\"r1\",\"span\":\"{\\\"lo\\\":15,\\\"hi\\\":17}\"}"
|
Identifier: "{\"name\":\"r1\",\"span\":\"{\\\"lo\\\":15,\\\"hi\\\":17}\"}"
|
||||||
- Identifier: "{\"name\":\"r2\",\"span\":\"{\\\"lo\\\":18,\\\"hi\\\":20}\"}"
|
second:
|
||||||
- Identifier: "{\"name\":\"thisistreatedasanidentifier\",\"span\":\"{\\\"lo\\\":21,\\\"hi\\\":48}\"}"
|
Identifier: "{\"name\":\"r2\",\"span\":\"{\\\"lo\\\":18,\\\"hi\\\":20}\"}"
|
||||||
- Identifier: "{\"name\":\"r3\",\"span\":\"{\\\"lo\\\":49,\\\"hi\\\":51}\"}"
|
destination: "{\"name\":\"r3\",\"span\":\"{\\\"lo\\\":26,\\\"hi\\\":28}\"}"
|
||||||
destinations: []
|
span:
|
||||||
span:
|
lo: 11
|
||||||
lo: 11
|
hi: 28
|
||||||
hi: 52
|
- IsEqual:
|
||||||
span:
|
first:
|
||||||
lo: 0
|
Identifier: "{\"name\":\"r3\",\"span\":\"{\\\"lo\\\":33,\\\"hi\\\":35}\"}"
|
||||||
hi: 54
|
second:
|
||||||
- AssemblyBlock:
|
Literal:
|
||||||
instructions:
|
|
||||||
- opcode: Add
|
|
||||||
operands:
|
|
||||||
- Identifier: "{\"name\":\"r1\",\"span\":\"{\\\"lo\\\":15,\\\"hi\\\":17}\"}"
|
|
||||||
- Identifier: "{\"name\":\"r2\",\"span\":\"{\\\"lo\\\":18,\\\"hi\\\":20}\"}"
|
|
||||||
destinations:
|
|
||||||
- "{\"name\":\"r3\",\"span\":\"{\\\"lo\\\":26,\\\"hi\\\":28}\"}"
|
|
||||||
span:
|
|
||||||
lo: 11
|
|
||||||
hi: 29
|
|
||||||
- opcode: IsEqual
|
|
||||||
operands:
|
|
||||||
- Identifier: "{\"name\":\"r3\",\"span\":\"{\\\"lo\\\":33,\\\"hi\\\":35}\"}"
|
|
||||||
- Literal:
|
|
||||||
Integer:
|
Integer:
|
||||||
- U8
|
- U8
|
||||||
- "0"
|
- "0"
|
||||||
- span:
|
- span:
|
||||||
lo: 36
|
lo: 36
|
||||||
hi: 39
|
hi: 39
|
||||||
destinations:
|
destination: "{\"name\":\"r4\",\"span\":\"{\\\"lo\\\":45,\\\"hi\\\":47}\"}"
|
||||||
- "{\"name\":\"r4\",\"span\":\"{\\\"lo\\\":45,\\\"hi\\\":47}\"}"
|
span:
|
||||||
span:
|
lo: 30
|
||||||
lo: 30
|
hi: 47
|
||||||
hi: 48
|
- Ternary:
|
||||||
- opcode: Ternary
|
first:
|
||||||
operands:
|
Identifier: "{\"name\":\"r4\",\"span\":\"{\\\"lo\\\":53,\\\"hi\\\":55}\"}"
|
||||||
- Identifier: "{\"name\":\"r4\",\"span\":\"{\\\"lo\\\":53,\\\"hi\\\":55}\"}"
|
second:
|
||||||
- Literal:
|
Literal:
|
||||||
Integer:
|
Integer:
|
||||||
- U8
|
- U8
|
||||||
- "1"
|
- "1"
|
||||||
- span:
|
- span:
|
||||||
lo: 56
|
lo: 56
|
||||||
hi: 59
|
hi: 59
|
||||||
- Literal:
|
third:
|
||||||
|
Literal:
|
||||||
Integer:
|
Integer:
|
||||||
- U8
|
- U8
|
||||||
- "2"
|
- "2"
|
||||||
- span:
|
- span:
|
||||||
lo: 60
|
lo: 60
|
||||||
hi: 63
|
hi: 63
|
||||||
destinations:
|
destination: "{\"name\":\"r5\",\"span\":\"{\\\"lo\\\":69,\\\"hi\\\":71}\"}"
|
||||||
- "{\"name\":\"r5\",\"span\":\"{\\\"lo\\\":69,\\\"hi\\\":71}\"}"
|
span:
|
||||||
span:
|
lo: 49
|
||||||
lo: 49
|
hi: 71
|
||||||
hi: 72
|
|
||||||
span:
|
span:
|
||||||
lo: 0
|
lo: 0
|
||||||
hi: 74
|
hi: 74
|
||||||
|
@ -6,6 +6,7 @@ outputs:
|
|||||||
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ']'\n --> test:1:10\n |\n 1 | assembly{]\n | ^"
|
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ']'\n --> test:1:10\n |\n 1 | assembly{]\n | ^"
|
||||||
- "Error [EPAR0370005]: expected { -- got '['\n --> test:1:9\n |\n 1 | assembly[]\n | ^"
|
- "Error [EPAR0370005]: expected { -- got '['\n --> test:1:9\n |\n 1 | assembly[]\n | ^"
|
||||||
- "Error [EPAR0370005]: expected ; -- got '<eof>'\n --> test:1:11\n |\n 1 | assembli {}\n | ^"
|
- "Error [EPAR0370005]: expected ; -- got '<eof>'\n --> test:1:11\n |\n 1 | assembli {}\n | ^"
|
||||||
- "Error [EPAR0370009]: unexpected string: expected 'ident', got '}'\n --> test:3:1\n |\n 3 | }\n | ^"
|
- "Error [EPAR0370005]: expected ; -- got '}'\n --> test:3:1\n |\n 3 | }\n | ^"
|
||||||
- "Error [EPAR0370047]: Invalid opcode in assembly block.\n --> test:2:1\n |\n 2 | thisopcodedoesnotexist r1 r2 into r3;\n | ^^^^^^^^^^^^^^^^^^^^^^"
|
- "Error [EPAR0370047]: Invalid opcode in assembly block.\n --> test:2:1\n |\n 2 | thisopcodedoesnotexist r1 r2 into r3;\n | ^^^^^^^^^^^^^^^^^^^^^^"
|
||||||
- "Error [EPAR0370048]: Invalid operand in assembly block. Operands must be `Identifier`s or `LiteralExpressions`.\n --> test:2:5\n |\n 2 | add r1 (1u8 + 2u8) into r3;\n | ^^^^^^^^^^^^^^"
|
- "Error [EPAR0370005]: expected `into` -- got 'thishouldbeinto'\n --> test:2:11\n |\n 2 | add r1 r2 thishouldbeinto r3;\n | ^^^^^^^^^^^^^^^"
|
||||||
|
- "Error [EPAR0370048]: Invalid operand in assembly block. Operands must be `Identifier`s or `LiteralExpressions`.\n --> test:2:9\n |\n 2 | add r1 (1u8 + 2u8) into r3;\n | ^^^^^^^^^"
|
||||||
|
@ -11,9 +11,6 @@ assembly {
|
|||||||
add r1 r2 into r3;
|
add r1 r2 into r3;
|
||||||
}
|
}
|
||||||
|
|
||||||
assembly {
|
|
||||||
add r1 r2 thisistreatedasanidentifier r3;
|
|
||||||
}
|
|
||||||
|
|
||||||
assembly {
|
assembly {
|
||||||
add r1 r2 into r3;
|
add r1 r2 into r3;
|
||||||
|
@ -19,6 +19,10 @@ assembly {
|
|||||||
thisopcodedoesnotexist r1 r2 into r3;
|
thisopcodedoesnotexist r1 r2 into r3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assembly {
|
||||||
|
add r1 r2 thishouldbeinto r3;
|
||||||
|
}
|
||||||
|
|
||||||
assembly {
|
assembly {
|
||||||
add r1 (1u8 + 2u8) into r3;
|
add r1 (1u8 + 2u8) into r3;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user