Skip to content

Commit

Permalink
feat: parse binary logic
Browse files Browse the repository at this point in the history
  • Loading branch information
nilslice committed Mar 14, 2022
1 parent e52bea9 commit 2d39659
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 9 deletions.
68 changes: 68 additions & 0 deletions src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,62 @@ impl fmt::Display for ArithmeticOperator {
}
}

#[derive(Clone, Debug, PartialEq)]
pub enum LogicalOperand {
LiteralInteger(i64),
MemoryReference(MemoryReference),
}

impl fmt::Display for LogicalOperand {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
LogicalOperand::LiteralInteger(value) => write!(f, "{}", value),
LogicalOperand::MemoryReference(value) => write!(f, "{}", value),
}
}
}

#[derive(Clone, Debug, PartialEq)]
pub enum LogicalOperator {
Binary(BinaryLogic),
Unary(UnaryLogic),
}

#[derive(Clone, Debug, PartialEq)]
pub enum BinaryLogic {
And,
Or,
Ior,
Xor,
}

#[derive(Clone, Debug, PartialEq)]
pub enum UnaryLogic {
Neg,
Not,
True,
False,
}

impl fmt::Display for LogicalOperator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
LogicalOperator::Binary(logic) => match logic {
BinaryLogic::And => write!(f, "AND"),
BinaryLogic::Or => write!(f, "OR"),
BinaryLogic::Ior => write!(f, "IOR"),
BinaryLogic::Xor => write!(f, "XOR"),
},
LogicalOperator::Unary(logic) => match logic {
UnaryLogic::Neg => write!(f, "NEG"),
UnaryLogic::Not => write!(f, "NOT"),
UnaryLogic::True => write!(f, "TRUE"),
UnaryLogic::False => write!(f, "FALSE"),
},
}
}
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeValue {
String(String),
Expand Down Expand Up @@ -364,6 +420,13 @@ pub struct Arithmetic {
pub source: ArithmeticOperand,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Logic {
pub operator: LogicalOperator,
pub operands: [MemoryReference; 2],
// pub operands: (MemoryReference, LogicalOperand),
}

#[derive(Clone, Debug, PartialEq)]
pub struct Label(pub String);

Expand Down Expand Up @@ -435,6 +498,7 @@ pub enum Instruction {
SwapPhases(SwapPhases),
WaveformDefinition(WaveformDefinition),
Arithmetic(Arithmetic),
Logic(Logic),
Halt,
Label(Label),
Move(Move),
Expand Down Expand Up @@ -481,6 +545,7 @@ impl From<&Instruction> for InstructionRole {
| Instruction::ShiftPhase(_)
| Instruction::SwapPhases(_) => InstructionRole::RFControl,
Instruction::Arithmetic(_)
| Instruction::Logic(_)
| Instruction::Move(_)
| Instruction::Exchange(_)
| Instruction::Load(_)
Expand Down Expand Up @@ -801,6 +866,9 @@ impl fmt::Display for Instruction {
write!(f, "JUMP-WHEN @{} {}", target, condition)
}
Instruction::Label(Label(label)) => write!(f, "LABEL @{}", label),
Instruction::Logic(Logic { operator, operands }) => {
write!(f, "{} {} {}", operator, operands[0], operands[1])
}
}
}
}
Expand Down
23 changes: 21 additions & 2 deletions src/parser/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ use nom::{
use crate::instruction::{
Arithmetic, ArithmeticOperand, ArithmeticOperator, Calibration, Capture, CircuitDefinition,
Declaration, Delay, Exchange, Fence, FrameDefinition, Instruction, Jump, JumpUnless, JumpWhen,
Label, Load, Measurement, Move, Pragma, Pulse, RawCapture, Reset, SetFrequency, SetPhase,
SetScale, ShiftFrequency, ShiftPhase, Store, Waveform, WaveformDefinition,
Label, Load, Logic, LogicalOperator, Measurement, Move, Pragma, Pulse, RawCapture, Reset,
SetFrequency, SetPhase, SetScale, ShiftFrequency, ShiftPhase, Store, Waveform,
WaveformDefinition,
};
use crate::parser::common::parse_variable_qubit;
use crate::parser::instruction::parse_block;
Expand Down Expand Up @@ -57,6 +58,24 @@ pub fn parse_arithmetic(
))
}

/// Parse an arithmetic instruction of the form `destination source`.
/// Called using the arithmetic operator itself (such as `ADD`) which should be previously parsed.
pub fn parse_logical_binary(
operator: LogicalOperator,
input: ParserInput,
) -> ParserResult<Instruction> {
let (input, left) = common::parse_memory_reference(input)?; // addr
let (input, right) = common::parse_memory_reference(input)?; // addr

Ok((
input,
Instruction::Logic(Logic {
operator,
operands: [left, right],
}),
))
}

/// Parse the contents of a `DECLARE` instruction.
pub fn parse_declare<'a>(input: ParserInput<'a>) -> ParserResult<'a, Instruction> {
let (input, name) = token!(Identifier(v))(input)?;
Expand Down
98 changes: 92 additions & 6 deletions src/parser/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use nom::{
};

use crate::{
instruction::{ArithmeticOperator, Instruction},
instruction::{ArithmeticOperator, BinaryLogic, Instruction, LogicalOperator},
token,
};

Expand All @@ -43,7 +43,10 @@ pub fn parse_instruction(input: ParserInput) -> ParserResult<Instruction> {
Some((Token::Command(command), remainder)) => {
match command {
Command::Add => command::parse_arithmetic(ArithmeticOperator::Add, remainder),
// Command::And => {}
Command::And => command::parse_logical_binary(
LogicalOperator::Binary(BinaryLogic::And),
remainder,
),
Command::Capture => command::parse_capture(remainder, true),
// Command::Convert => {}
Command::Declare => command::parse_declare(remainder),
Expand All @@ -61,7 +64,10 @@ pub fn parse_instruction(input: ParserInput) -> ParserResult<Instruction> {
// Command::GT => {}
Command::Halt => Ok((remainder, Instruction::Halt)),
// Command::Include => {}
// Command::Ior => {}
Command::Ior => command::parse_logical_binary(
LogicalOperator::Binary(BinaryLogic::Ior),
remainder,
),
Command::Jump => command::parse_jump(remainder),
Command::JumpUnless => command::parse_jump_unless(remainder),
Command::JumpWhen => command::parse_jump_when(remainder),
Expand All @@ -76,6 +82,10 @@ pub fn parse_instruction(input: ParserInput) -> ParserResult<Instruction> {
// Command::Neg => {}
// Command::Nop => {}
// Command::Not => {}
Command::Or => command::parse_logical_binary(
LogicalOperator::Binary(BinaryLogic::Or),
remainder,
),
Command::Pragma => command::parse_pragma(remainder),
Command::Pulse => command::parse_pulse(remainder, true),
Command::RawCapture => command::parse_raw_capture(remainder, true),
Expand All @@ -88,7 +98,10 @@ pub fn parse_instruction(input: ParserInput) -> ParserResult<Instruction> {
Command::Store => command::parse_store(remainder),
Command::Sub => command::parse_arithmetic(ArithmeticOperator::Subtract, remainder),
// Command::Wait => {}
// Command::Xor => {}
Command::Xor => command::parse_logical_binary(
LogicalOperator::Binary(BinaryLogic::Xor),
remainder,
),
_ => Err(nom::Err::Failure(Error {
input: &input[..1],
error: ErrorKind::UnsupportedInstruction,
Expand Down Expand Up @@ -149,8 +162,8 @@ mod tests {
use std::collections::HashMap;

use crate::instruction::{
Label, Reset, SetFrequency, SetPhase, SetScale, ShiftFrequency, ShiftPhase, Waveform,
WaveformDefinition,
BinaryLogic, Label, Logic, LogicalOperator, Reset, SetFrequency, SetPhase, SetScale,
ShiftFrequency, ShiftPhase, Waveform, WaveformDefinition,
};
use crate::parser::lexer::lex;
use crate::{
Expand Down Expand Up @@ -242,6 +255,79 @@ mod tests {
]
);

make_test!(
logic,
parse_instructions,
"AND ro ro[1]\nOR ro ro[1]\nIOR ro[1] ro[2]\nXOR ro[1] ro\nAND ro[1] ro[2]",
vec![
Instruction::Logic(Logic {
operator: LogicalOperator::Binary(BinaryLogic::And),
operands: [
MemoryReference {
name: "ro".to_owned(),
index: 0
},
MemoryReference {
name: "ro".to_owned(),
index: 1
}
]
}),
Instruction::Logic(Logic {
operator: LogicalOperator::Binary(BinaryLogic::Or),
operands: [
MemoryReference {
name: "ro".to_owned(),
index: 0
},
MemoryReference {
name: "ro".to_owned(),
index: 1
}
]
}),
Instruction::Logic(Logic {
operator: LogicalOperator::Binary(BinaryLogic::Ior),
operands: [
MemoryReference {
name: "ro".to_owned(),
index: 1
},
MemoryReference {
name: "ro".to_owned(),
index: 2
}
]
}),
Instruction::Logic(Logic {
operator: LogicalOperator::Binary(BinaryLogic::Xor),
operands: [
MemoryReference {
name: "ro".to_owned(),
index: 1
},
MemoryReference {
name: "ro".to_owned(),
index: 0
}
]
}),
Instruction::Logic(Logic {
operator: LogicalOperator::Binary(BinaryLogic::And),
operands: [
MemoryReference {
name: "ro".to_owned(),
index: 1
},
MemoryReference {
name: "ro".to_owned(),
index: 2
}
]
}),
]
);

make_test!(
capture_instructions,
parse_instructions,
Expand Down
9 changes: 9 additions & 0 deletions src/parser/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ pub enum Command {
Neg,
Nop,
Not,
Or,
Pragma,
Pulse,
RawCapture,
Expand Down Expand Up @@ -196,6 +197,7 @@ fn recognize_command_or_identifier(identifier: String) -> Token {
"DEFGATE" => Token::Command(DefGate),
"ADD" => Token::Command(Add),
"AND" => Token::Command(And),
"OR" => Token::Command(Or),
"CONVERT" => Token::Command(Convert),
"DIV" => Token::Command(Div),
"EQ" => Token::Command(Eq),
Expand Down Expand Up @@ -343,6 +345,13 @@ fn lex_variable(input: &str) -> LexResult {
})(input)
}

// fn lex_logical_binary_op(input: &str) -> LexResult {
// use Token::*;
// alt((
// value()
// ))(input)
// }

#[cfg(test)]
mod tests {
use super::{lex, Command, Operator, Token};
Expand Down
1 change: 1 addition & 0 deletions src/program/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ impl ScheduledProgram {
let instruction_index = Some(index);
match instruction {
Instruction::Arithmetic(_)
| Instruction::Logic(_)
| Instruction::Capture(_)
| Instruction::Delay(_)
| Instruction::Fence(_)
Expand Down
14 changes: 13 additions & 1 deletion src/program/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::collections::HashSet;
use crate::expression::Expression;
use crate::instruction::{
Arithmetic, ArithmeticOperand, Capture, CircuitDefinition, Delay, Exchange, Gate,
GateDefinition, Instruction, Jump, JumpUnless, JumpWhen, Label, Load,
GateDefinition, Instruction, Jump, JumpUnless, JumpWhen, Label, Load, Logic, LogicalOperator,
MeasureCalibrationDefinition, Measurement, MemoryReference, Move, Pulse, RawCapture, SetPhase,
SetScale, ShiftPhase, Store, Vector, WaveformInvocation,
};
Expand Down Expand Up @@ -90,6 +90,18 @@ impl Instruction {
/// Return all memory accesses by the instruction - in expressions, captures, and memory manipulation
pub fn get_memory_accesses(&self) -> MemoryAccesses {
match self {
Instruction::Logic(Logic { operands, operator }) => match operator {
LogicalOperator::Binary(_) => MemoryAccesses {
reads: operands
.iter()
.map(|memref| memref.name.clone())
.collect::<HashSet<String>>(),
..Default::default()
},
LogicalOperator::Unary(logic) => match logic {
_ => todo!("implement memory access for unary logic"),
},
},
Instruction::Arithmetic(Arithmetic {
destination,
source,
Expand Down
1 change: 1 addition & 0 deletions src/program/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ impl Program {
| Instruction::Pragma(_)
| Instruction::WaveformDefinition(_)
| Instruction::Arithmetic(_)
| Instruction::Logic(_)
| Instruction::Halt
| Instruction::Label(_)
| Instruction::Move(_)
Expand Down

0 comments on commit 2d39659

Please sign in to comment.