mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 13:56:58 +03:00
Make parser compatible with new assembly AST
This commit is contained in:
parent
3d95d67d78
commit
73c761149f
@ -24,11 +24,14 @@ pub trait InstructionReconstructor {
|
||||
// TODO: Remove the associated type if it is not needed.
|
||||
type AdditionalOutput: Default;
|
||||
|
||||
fn reconstruct_literal(&mut self, input: LiteralExpression) -> (LiteralExpression, Self::AdditionalOutput) {
|
||||
fn reconstruct_instruction_literal(
|
||||
&mut self,
|
||||
input: LiteralExpression,
|
||||
) -> (LiteralExpression, Self::AdditionalOutput) {
|
||||
(input, Default::default())
|
||||
}
|
||||
|
||||
fn reconstruct_identifier(&mut self, input: Identifier) -> (Identifier, Self::AdditionalOutput) {
|
||||
fn reconstruct_instruction_identifier(&mut self, input: Identifier) -> (Identifier, Self::AdditionalOutput) {
|
||||
(input, Default::default())
|
||||
}
|
||||
|
||||
@ -36,11 +39,11 @@ pub trait InstructionReconstructor {
|
||||
match input {
|
||||
Operand::Invalid => (Operand::Invalid, Default::default()),
|
||||
Operand::Identifier(operand) => (
|
||||
Operand::Identifier(self.reconstruct_identifier(operand).0),
|
||||
Operand::Identifier(self.reconstruct_instruction_identifier(operand).0),
|
||||
Default::default(),
|
||||
),
|
||||
Operand::Literal(operand) => (
|
||||
Operand::Literal(self.reconstruct_literal(operand).0),
|
||||
Operand::Literal(self.reconstruct_instruction_literal(operand).0),
|
||||
Default::default(),
|
||||
),
|
||||
}
|
||||
@ -71,7 +74,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::Add(Add {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -83,7 +86,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::And(And {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -95,7 +98,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::Div(Div {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -107,7 +110,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::GreaterThan(GreaterThan {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -122,7 +125,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::GreaterThanOrEqual(GreaterThanOrEqual {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -134,7 +137,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::IsEqual(IsEqual {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -146,7 +149,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::IsNotEqual(IsNotEqual {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -158,7 +161,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::LessThan(LessThan {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -173,7 +176,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::LessThanOrEqual(LessThanOrEqual {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -185,7 +188,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::Mul(Mul {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -200,7 +203,7 @@ pub trait InstructionReconstructor {
|
||||
(
|
||||
Instruction::Not(Not {
|
||||
operand: self.reconstruct_operand(input.operand).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -212,7 +215,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::Or(Or {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -224,7 +227,7 @@ pub trait InstructionReconstructor {
|
||||
Instruction::Sub(Sub {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -237,7 +240,7 @@ pub trait InstructionReconstructor {
|
||||
first: self.reconstruct_operand(input.first).0,
|
||||
second: self.reconstruct_operand(input.second).0,
|
||||
third: self.reconstruct_operand(input.third).0,
|
||||
destination: self.reconstruct_identifier(input.destination).0,
|
||||
destination: self.reconstruct_instruction_identifier(input.destination).0,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
|
@ -25,7 +25,7 @@ pub trait InstructionVisitor<'a> {
|
||||
type AdditionalInput: Default;
|
||||
type Output: Default;
|
||||
|
||||
fn visit_literal(
|
||||
fn visit_instruction_literal(
|
||||
&mut self,
|
||||
_input: &'a LiteralExpression,
|
||||
_additional_input: &Self::AdditionalInput,
|
||||
@ -33,7 +33,11 @@ pub trait InstructionVisitor<'a> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_identifier(&mut self, _input: &'a Identifier, _additional_input: &Self::AdditionalInput) -> Self::Output {
|
||||
fn visit_instruction_identifier(
|
||||
&mut self,
|
||||
_input: &'a Identifier,
|
||||
_additional_input: &Self::AdditionalInput,
|
||||
) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
@ -44,8 +48,8 @@ pub trait InstructionVisitor<'a> {
|
||||
fn visit_operand(&mut self, input: &'a Operand, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
match input {
|
||||
Operand::Invalid => self.visit_invalid_operand(additional),
|
||||
Operand::Identifier(operand) => self.visit_identifier(operand, additional),
|
||||
Operand::Literal(operand) => self.visit_literal(operand, additional),
|
||||
Operand::Identifier(operand) => self.visit_instruction_identifier(operand, additional),
|
||||
Operand::Literal(operand) => self.visit_instruction_literal(operand, additional),
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,21 +76,21 @@ pub trait InstructionVisitor<'a> {
|
||||
fn visit_add_instruction(&mut self, input: &'a Add, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_and_instruction(&mut self, input: &'a And, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_div_instruction(&mut self, input: &'a Div, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
@ -97,7 +101,7 @@ pub trait InstructionVisitor<'a> {
|
||||
) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
@ -108,14 +112,14 @@ pub trait InstructionVisitor<'a> {
|
||||
) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_is_equal_instruction(&mut self, input: &'a IsEqual, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
@ -126,14 +130,14 @@ pub trait InstructionVisitor<'a> {
|
||||
) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_less_than_instruction(&mut self, input: &'a LessThan, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
@ -144,14 +148,14 @@ pub trait InstructionVisitor<'a> {
|
||||
) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_mul_instruction(&mut self, input: &'a Mul, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
@ -161,21 +165,21 @@ pub trait InstructionVisitor<'a> {
|
||||
|
||||
fn visit_not_instruction(&mut self, input: &'a Not, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.operand, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_or_instruction(&mut self, input: &'a Or, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_sub_instruction(&mut self, input: &'a Sub, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
@ -183,7 +187,7 @@ pub trait InstructionVisitor<'a> {
|
||||
self.visit_operand(&input.first, additional);
|
||||
self.visit_operand(&input.second, additional);
|
||||
self.visit_operand(&input.third, additional);
|
||||
self.visit_identifier(&input.destination, additional);
|
||||
self.visit_instruction_identifier(&input.destination, additional);
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -19,75 +19,265 @@
|
||||
// TODO: If snarkVM instructions are used directly, then we should directly use the associated instruction parsers.
|
||||
|
||||
use crate::{ParserContext, Token};
|
||||
use std::process::id;
|
||||
|
||||
use leo_ast::{Expression, Instruction, Node, Opcode, Operand};
|
||||
use leo_ast::{
|
||||
Add, And, Div, Expression, GreaterThan, GreaterThanOrEqual, Instruction, IsEqual, IsNotEqual, LessThan,
|
||||
LessThanOrEqual, Mul, Node, Nop, Not, Operand, Or, Sub, Ternary,
|
||||
};
|
||||
use leo_errors::{ParserError, Result};
|
||||
use leo_span::Symbol;
|
||||
use leo_span::Span;
|
||||
|
||||
// TODO: Note that this design is a prototype.
|
||||
impl ParserContext<'_> {
|
||||
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.
|
||||
let opcode_identifer = self.expect_ident()?;
|
||||
let opcode = match &*opcode_identifer.name.as_str() {
|
||||
"add" => Opcode::Add,
|
||||
"and" => Opcode::And,
|
||||
"div" => Opcode::Div,
|
||||
"gt" => Opcode::GreaterThan,
|
||||
"gte" => Opcode::GreaterThanOrEqual,
|
||||
"eq" => Opcode::IsEqual,
|
||||
"neq" => Opcode::IsNotEqual,
|
||||
"lt" => Opcode::LessThan,
|
||||
"lte" => Opcode::LessThanOrEqual,
|
||||
"mul" => Opcode::Mul,
|
||||
"not" => Opcode::Not,
|
||||
"or" => Opcode::Or,
|
||||
"sub" => Opcode::Sub,
|
||||
"ter" => Opcode::Ternary,
|
||||
let identifier = self.expect_ident()?;
|
||||
match &*identifier.name.as_str() {
|
||||
"add" => self.parse_add_instruction(identifier.span),
|
||||
"and" => self.parse_and_instruction(identifier.span),
|
||||
"div" => self.parse_div_instruction(identifier.span),
|
||||
"gt" => self.parse_greater_than_instruction(identifier.span),
|
||||
"gte" => self.parse_greater_than_or_equal_instruction(identifier.span),
|
||||
"eq" => self.parse_equal_instruction(identifier.span),
|
||||
"neq" => self.parse_not_equal_instruction(identifier.span),
|
||||
"lt" => self.parse_less_than_instruction(identifier.span),
|
||||
"lte" => self.parse_less_than_or_equal_instruction(identifier.span),
|
||||
"mul" => self.parse_mul_instruction(identifier.span),
|
||||
"not" => self.parse_not_instruction(identifier.span),
|
||||
"or" => self.parse_or_instruction(identifier.span),
|
||||
"sub" => self.parse_sub_instruction(identifier.span),
|
||||
"ter" => self.parse_ternary_instruction(identifier.span),
|
||||
_ => {
|
||||
self.emit_err(ParserError::invalid_opcode_in_assembly_instruction(
|
||||
opcode_identifer.span,
|
||||
));
|
||||
Opcode::Invalid
|
||||
self.emit_err(ParserError::invalid_opcode_in_assembly_instruction(identifier.span));
|
||||
// TODO: Do we need to eat tokens here?
|
||||
Ok(Instruction::Nop(Nop { span: identifier.span }))
|
||||
}
|
||||
};
|
||||
|
||||
// Parse arguments.
|
||||
let mut operands = Vec::new();
|
||||
while !self.check(&Token::Semicolon) {
|
||||
let expression = self.parse_expression()?;
|
||||
match expression {
|
||||
Expression::Identifier(identifier) => match &*identifier.name.as_str() {
|
||||
"into" => break,
|
||||
_ => operands.push(Operand::Identifier(identifier)),
|
||||
},
|
||||
Expression::Literal(literal) => operands.push(Operand::Literal(literal)),
|
||||
Expression::Access(..)
|
||||
| Expression::Binary(..)
|
||||
| Expression::Call(..)
|
||||
| Expression::CircuitInit(..)
|
||||
| Expression::Err(..)
|
||||
| Expression::Ternary(..)
|
||||
| Expression::Unary(..) => {
|
||||
self.emit_err(ParserError::invalid_operand_in_assembly_instruction(expression.span()));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// If the next token is the `into` keyword, then we need to parse destinations.
|
||||
let mut destinations = Vec::new();
|
||||
while !self.check(&Token::Semicolon) {
|
||||
destinations.push(self.expect_ident()?)
|
||||
// TODO: Consider a macro to simplify boilerplate code.
|
||||
|
||||
pub fn parse_add_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::Add(Add {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_and_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::And(And {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_div_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::Div(Div {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_greater_than_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::GreaterThan(GreaterThan {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_greater_than_or_equal_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::GreaterThanOrEqual(GreaterThanOrEqual {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_equal_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::IsEqual(IsEqual {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_not_equal_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::IsNotEqual(IsNotEqual {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_less_than_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::LessThan(LessThan {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_less_than_or_equal_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::LessThanOrEqual(LessThanOrEqual {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_mul_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::Mul(Mul {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_not_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let operand = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::Not(Not {
|
||||
operand,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_or_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::Or(Or {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_sub_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::Sub(Sub {
|
||||
first,
|
||||
second,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_ternary_instruction(&mut self, start: Span) -> Result<Instruction> {
|
||||
let first = self.parse_operand()?;
|
||||
let second = self.parse_operand()?;
|
||||
let third = self.parse_operand()?;
|
||||
self.expect_into()?;
|
||||
let destination = self.expect_ident()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Instruction::Ternary(Ternary {
|
||||
first,
|
||||
second,
|
||||
third,
|
||||
destination,
|
||||
span: start + destination.span,
|
||||
}))
|
||||
}
|
||||
|
||||
// TODO: Better error handling.
|
||||
// Separate tokens and symbols for assembly block.
|
||||
pub fn expect_into(&mut self) -> Result<()> {
|
||||
let identifier = self.expect_ident()?;
|
||||
match &*identifier.name.as_str() {
|
||||
"into" => Ok(()),
|
||||
string => Err(ParserError::unexpected(string, "into", identifier.span).into()),
|
||||
}
|
||||
}
|
||||
|
||||
let end_span = self.expect(&Token::Semicolon)?;
|
||||
|
||||
Ok(Instruction {
|
||||
opcode,
|
||||
operands,
|
||||
destinations,
|
||||
span: opcode_identifer.span + end_span,
|
||||
})
|
||||
pub fn parse_operand(&mut self) -> Result<Operand> {
|
||||
let expression = self.parse_expression()?;
|
||||
match expression {
|
||||
Expression::Identifier(identifier) => Ok(Operand::Identifier(identifier)),
|
||||
Expression::Literal(literal) => Ok(Operand::Literal(literal)),
|
||||
Expression::Access(..)
|
||||
| Expression::Binary(..)
|
||||
| Expression::Call(..)
|
||||
| Expression::CircuitInit(..)
|
||||
| Expression::Err(..)
|
||||
| Expression::Ternary(..)
|
||||
| Expression::Unary(..) => {
|
||||
self.emit_err(ParserError::invalid_operand_in_assembly_instruction(expression.span()));
|
||||
Ok(Operand::Invalid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user