// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::compiler;
use crate::ddk_bind_constants::{BIND_AUTOBIND, BIND_FLAGS, BIND_PROTOCOL};
use crate::encode_bind_program_v1::{RawCondition, RawInstruction, RawOp};
use crate::errors::UserError;
use crate::instruction::{DeviceProperty, RawAstLocation};
use num_traits::FromPrimitive;
use std::collections::{HashMap, HashSet};
use std::fmt;

#[derive(Debug, Clone, PartialEq)]
pub enum DebuggerError {
    BindFlagsNotSupported,
    InvalidCondition(u32),
    IncorrectCondition,
    InvalidOperation(u32),
    InvalidAstLocation(u32),
    IncorrectAstLocation,
    MissingLabel,
    MissingBindProtocol,
    NoOutcome,
    DuplicateKey(u32),
    InvalidDeprecatedKey(u32),
}

impl fmt::Display for DebuggerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", UserError::from(self.clone()))
    }
}

type DevicePropertyMap = HashMap<u32, u32>;

#[derive(Debug, PartialEq)]
enum DebuggerOutput {
    ConditionStatement { key: u32, condition: RawCondition, success: bool, line: u32 },
    FalseStatement { line: u32 },
    AcceptStatementSuccess { key: u32, value: u32, line: u32 },
    AcceptStatementFailure { key: u32, line: u32 },
    IfCondition { key: u32, condition: RawCondition, success: bool, line: u32 },
}

// TODO(fxb:67441): Support the new bytecode format in the debugger.
pub fn debug(
    instructions: &[RawInstruction<[u32; 3]>],
    properties: &[DeviceProperty],
) -> Result<Option<HashSet<DeviceProperty>>, DebuggerError> {
    let mut debugger = Debugger::new(instructions, properties)?;
    let matched_properties = debugger.evaluate_bind_program()?;
    debugger.log_output()?;
    Ok(matched_properties)
}

struct Debugger<'a> {
    instructions: &'a [RawInstruction<[u32; 3]>],
    properties: DevicePropertyMap,
    output: Vec<DebuggerOutput>,
    deprecated_key_identifiers: HashMap<u32, String>,
}

impl<'a> Debugger<'a> {
    pub fn new(
        instructions: &'a [RawInstruction<[u32; 3]>],
        properties: &[DeviceProperty],
    ) -> Result<Self, DebuggerError> {
        let properties = Debugger::construct_property_map(properties)?;
        let output = Vec::new();
        let deprecated_key_identifiers = compiler::get_deprecated_key_identifiers();
        Ok(Debugger { instructions, properties, output, deprecated_key_identifiers })
    }

    fn construct_property_map(
        properties: &[DeviceProperty],
    ) -> Result<DevicePropertyMap, DebuggerError> {
        let mut property_map = HashMap::new();
        for DeviceProperty { key, value } in properties {
            if property_map.contains_key(key) {
                return Err(DebuggerError::DuplicateKey(*key));
            }
            property_map.insert(*key, *value);
        }
        Ok(property_map)
    }

    fn key_string(&self, key: u32) -> Result<String, DebuggerError> {
        match self.deprecated_key_identifiers.get(&key) {
            Some(identifier) => Ok(format!("`{}` [{:#06x}]", identifier, key)),
            None => Err(DebuggerError::InvalidDeprecatedKey(key)),
        }
    }

    fn get_device_property(&self, key: u32) -> Result<DeviceProperty, DebuggerError> {
        if let Some((key, value)) = self.properties.get_key_value(&key) {
            return Ok(DeviceProperty { key: *key, value: *value });
        }

        // TODO(fxbug.dev/45663): The behavior of setting missing properties to 0 is implemented to be
        // consistent with binding.cc. This behavior should eventually be changed to deal with
        // missing properties in a better way.
        match key {
            BIND_PROTOCOL => Err(DebuggerError::MissingBindProtocol),
            BIND_AUTOBIND => {
                println!(
                    "WARNING: Driver has BI_ABORT_IF_AUTOBIND. \
                    This bind program will fail in autobind contexts."
                );
                // Set autobind = false, since the debugger is always run with a specific driver.
                Ok(DeviceProperty { key: BIND_AUTOBIND, value: 0 })
            }
            _ => {
                println!(
                    "WARNING: Device has no value for {}. The value will be set to 0.",
                    self.key_string(key)?
                );
                Ok(DeviceProperty { key, value: 0 })
            }
        }
    }

    pub fn evaluate_bind_program(
        &mut self,
    ) -> Result<Option<HashSet<DeviceProperty>>, DebuggerError> {
        let mut instructions = self.instructions.iter();
        let mut matched_properties = HashSet::new();

        while let Some(mut instruction) = instructions.next() {
            let condition = FromPrimitive::from_u32(instruction.condition())
                .ok_or(DebuggerError::InvalidCondition(instruction.condition()))?;
            let operation = FromPrimitive::from_u32(instruction.operation())
                .ok_or(DebuggerError::InvalidOperation(instruction.operation()))?;

            let condition_succeeds = if condition == RawCondition::Always {
                true
            } else {
                let key = instruction.parameter_b();
                if key == BIND_FLAGS {
                    return Err(DebuggerError::BindFlagsNotSupported);
                }

                let device_property = self.get_device_property(key)?;
                matched_properties.insert(device_property);

                match condition {
                    RawCondition::Equal => device_property.value == instruction.value(),
                    RawCondition::NotEqual => device_property.value != instruction.value(),
                    RawCondition::Always => unreachable!(),
                }
            };

            self.output_instruction(instruction, condition_succeeds)?;

            if !condition_succeeds {
                continue;
            }

            match operation {
                RawOp::Abort => return Ok(None),
                RawOp::Match => return Ok(Some(matched_properties)),
                RawOp::Goto => {
                    let label = instruction.parameter_a();
                    while !(FromPrimitive::from_u32(instruction.operation()) == Some(RawOp::Label)
                        && instruction.parameter_a() == label)
                    {
                        instruction = instructions.next().ok_or(DebuggerError::MissingLabel)?;
                    }
                }
                RawOp::Label => (),
            }
        }

        Err(DebuggerError::NoOutcome)
    }

    fn output_instruction(
        &mut self,
        instruction: &RawInstruction<[u32; 3]>,
        condition_succeeds: bool,
    ) -> Result<(), DebuggerError> {
        let condition = FromPrimitive::from_u32(instruction.condition())
            .ok_or(DebuggerError::InvalidCondition(instruction.condition()))?;
        let operation = FromPrimitive::from_u32(instruction.operation())
            .ok_or(DebuggerError::InvalidOperation(instruction.operation()))?;
        let ast_location = FromPrimitive::from_u32(instruction.ast_location())
            .ok_or(DebuggerError::InvalidAstLocation(instruction.ast_location()))?;

        match (operation, condition) {
            (RawOp::Abort, RawCondition::Equal) | (RawOp::Abort, RawCondition::NotEqual) => {
                if ast_location != RawAstLocation::ConditionStatement {
                    return Err(DebuggerError::IncorrectAstLocation);
                }
                // The abort instruction came from a condition statement. An equality condition
                // statement is compiled to AbortIfNotEqual and vice versa, so the condition needs
                // to be flipped. Also, the condition was successful if the instruction doesn't
                // abort, so the `success` value needs to be flipped.
                self.output.push(DebuggerOutput::ConditionStatement {
                    key: instruction.parameter_b(),
                    condition: match condition {
                        RawCondition::Equal => RawCondition::NotEqual,
                        RawCondition::NotEqual => RawCondition::Equal,
                        _ => return Err(DebuggerError::IncorrectCondition),
                    },
                    success: !condition_succeeds,
                    line: instruction.line(),
                });
            }
            (RawOp::Abort, RawCondition::Always) => match ast_location {
                RawAstLocation::AcceptStatementFailure => {
                    // The abort instruction came from the end of an accept statement, meaning that
                    // the accept statement failed.
                    self.output.push(DebuggerOutput::AcceptStatementFailure {
                        key: instruction.extra(),
                        line: instruction.line(),
                    })
                }
                RawAstLocation::FalseStatement => {
                    self.output.push(DebuggerOutput::FalseStatement { line: instruction.line() })
                }
                _ => return Err(DebuggerError::IncorrectAstLocation),
            },
            (RawOp::Goto, RawCondition::Equal) => match ast_location {
                RawAstLocation::AcceptStatementValue => {
                    if condition_succeeds {
                        // The goto instruciton came from one of the values in an accept statement.
                        // The fact that the jump succeeded means that the device had this value, so
                        // the accept statement was satisfied.
                        self.output.push(DebuggerOutput::AcceptStatementSuccess {
                            key: instruction.parameter_b(),
                            value: instruction.value(),
                            line: instruction.line(),
                        });
                    }
                }
                RawAstLocation::IfCondition => {
                    // The goto instruction came from an inequality if statement condition. The
                    // condition was satisfied if the jump doesn't succeed, so the `success` value
                    // needs to be flipped.
                    self.output.push(DebuggerOutput::IfCondition {
                        key: instruction.parameter_b(),
                        condition: RawCondition::NotEqual,
                        success: !condition_succeeds,
                        line: instruction.line(),
                    })
                }
                _ => return Err(DebuggerError::IncorrectAstLocation),
            },
            (RawOp::Goto, RawCondition::NotEqual) => {
                if ast_location != RawAstLocation::IfCondition {
                    return Err(DebuggerError::IncorrectAstLocation);
                }
                // The goto instruction came from an equality if statement condition. The
                // condition was satisfied if the jump doesn't succeed, so the `success` value
                // needs to be flipped.
                self.output.push(DebuggerOutput::IfCondition {
                    key: instruction.parameter_b(),
                    condition: RawCondition::Equal,
                    success: !condition_succeeds,
                    line: instruction.line(),
                });
            }
            _ => (),
        }
        Ok(())
    }

    fn log_output(&self) -> Result<(), DebuggerError> {
        for output in &self.output {
            match output {
                DebuggerOutput::ConditionStatement { key, condition, success, line } => {
                    self.log_condition_statement(*key, *condition, *success, *line)?;
                }
                DebuggerOutput::FalseStatement { line } => self.log_false_statement(*line),
                DebuggerOutput::AcceptStatementSuccess { key, value, line } => {
                    self.log_accept_statement_success(*key, *value, *line)?
                }
                DebuggerOutput::AcceptStatementFailure { key, line } => {
                    self.log_accept_statement_failure(*key, *line)?
                }
                DebuggerOutput::IfCondition { key, condition, success, line } => {
                    self.log_if_condition(*key, *condition, *success, *line)?;
                }
            }
        }
        Ok(())
    }

    fn log_condition_statement(
        &self,
        key: u32,
        condition: RawCondition,
        success: bool,
        line: u32,
    ) -> Result<(), DebuggerError> {
        let outcome_string = if success { "succeeded" } else { "failed" };
        println!("Line {}: Condition statement {}.", line, outcome_string);

        if condition_needs_actual_value(success, condition)? {
            println!("\t{}", self.actual_value_string(key)?)
        }

        Ok(())
    }

    fn log_false_statement(&self, line: u32) {
        println!("Line {}: False statement reached.", line);
    }

    fn log_accept_statement_success(
        &self,
        key: u32,
        value: u32,
        line: u32,
    ) -> Result<(), DebuggerError> {
        println!(
            "Line {}: Accept statement succeeded.\n\tThe value of {} was {:#010x}.",
            line,
            self.key_string(key)?,
            value
        );

        Ok(())
    }

    fn log_accept_statement_failure(&self, key: u32, line: u32) -> Result<(), DebuggerError> {
        println!("Line {}: Accept statement failed.\n\t{}", line, self.actual_value_string(key)?);
        Ok(())
    }

    fn log_if_condition(
        &self,
        key: u32,
        condition: RawCondition,
        success: bool,
        line: u32,
    ) -> Result<(), DebuggerError> {
        let outcome_string = if success { "succeeded" } else { "failed" };
        println!("Line {}: If statement condition {}.", line, outcome_string);

        if condition_needs_actual_value(success, condition)? {
            println!("\t{}", self.actual_value_string(key)?)
        }

        Ok(())
    }

    fn actual_value_string(&self, key: u32) -> Result<String, DebuggerError> {
        let value = self.properties.get(&key);

        Ok(match value {
            Some(value) => {
                format!("Actual value of {} was {:#010x}.", self.key_string(key)?, value)
            }
            None => format!("Device had no value for {}.", self.key_string(key)?),
        })
    }
}

fn condition_needs_actual_value(
    success: bool,
    condition: RawCondition,
) -> Result<bool, DebuggerError> {
    match condition {
        RawCondition::Equal => Ok(!success),
        RawCondition::NotEqual => Ok(success),
        RawCondition::Always => Err(DebuggerError::IncorrectCondition),
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::bind_program::{Condition, ConditionOp, Statement};
    use crate::compiler::{self, BindProgramEncodeError, Symbol, SymbolTable};
    use crate::encode_bind_program_v1::{encode_instruction, to_raw_instruction};
    use crate::instruction::{self, Instruction};
    use crate::make_identifier;
    use crate::parser_common::{CompoundIdentifier, Span, Value};

    fn compile_to_raw(
        statements: Vec<Statement>,
        symbol_table: SymbolTable,
    ) -> Vec<RawInstruction<[u32; 3]>> {
        compiler::compile_statements(statements, symbol_table, false)
            .unwrap()
            .instructions
            .into_iter()
            .map(|symbolic| encode_instruction(symbolic.to_instruction()))
            .collect::<Result<Vec<_>, BindProgramEncodeError>>()
            .unwrap()
    }

    fn span_with_line(line: u32) -> Span<'static> {
        let mut span = Span::new();
        span.line = line;
        span
    }

    #[test]
    fn autobind() {
        // Autobind is false (BIND_AUTOBIND has the value 0).
        let instructions = vec![
            to_raw_instruction(Instruction::Match(instruction::Condition::Equal(
                Symbol::NumberValue(BIND_AUTOBIND.into()),
                Symbol::NumberValue(0),
            )))
            .unwrap(),
            to_raw_instruction(Instruction::Abort(instruction::Condition::Always)).unwrap(),
        ];
        let properties = Vec::new();
        assert_eq!(
            debug(&instructions, &properties),
            Ok(Some(
                vec![DeviceProperty { key: 0x0002, value: 0 },].into_iter().collect::<HashSet<_>>()
            ))
        );
    }

    #[test]
    fn bind_flags_not_supported() {
        let instructions =
            vec![to_raw_instruction(Instruction::Abort(instruction::Condition::Equal(
                Symbol::NumberValue(BIND_FLAGS.into()),
                Symbol::NumberValue(0),
            )))
            .unwrap()];
        let properties = Vec::new();
        assert_eq!(debug(&instructions, &properties), Err(DebuggerError::BindFlagsNotSupported));
    }

    #[test]
    fn missing_bind_protocol() {
        let instructions =
            vec![to_raw_instruction(Instruction::Abort(instruction::Condition::Equal(
                Symbol::NumberValue(BIND_PROTOCOL.into()),
                Symbol::NumberValue(5),
            )))
            .unwrap()];
        let properties = Vec::new();
        assert_eq!(debug(&instructions, &properties), Err(DebuggerError::MissingBindProtocol));
    }

    #[test]
    fn duplicate_key() {
        let instructions = Vec::new();
        let properties = vec![
            DeviceProperty { key: 0x0100, value: 42 },
            DeviceProperty { key: 0x0100, value: 5 },
        ];
        assert_eq!(debug(&instructions, &properties), Err(DebuggerError::DuplicateKey(0x0100)));
    }

    #[test]
    fn default_value_zero() {
        // When the device doesn't have the property, its value is set to 0.
        let statements = vec![Statement::ConditionStatement {
            span: Span::new(),
            condition: Condition {
                span: Span::new(),
                lhs: make_identifier!("abc"),
                op: ConditionOp::Equals,
                rhs: Value::NumericLiteral(0),
            },
        }];
        let mut symbol_table = HashMap::new();
        symbol_table.insert(make_identifier!("abc"), Symbol::DeprecatedKey(0x0100));
        let raw_instructions = compile_to_raw(statements, symbol_table);
        let properties = Vec::new();
        assert_eq!(
            debug(&raw_instructions, &properties),
            Ok(Some(
                vec![DeviceProperty { key: 0x0100, value: 0 },].into_iter().collect::<HashSet<_>>()
            ))
        );
    }

    mod condition_equals {
        use super::*;

        fn condition_equals_instructions() -> Vec<RawInstruction<[u32; 3]>> {
            let statements = vec![Statement::ConditionStatement {
                span: span_with_line(7),
                condition: Condition {
                    span: span_with_line(7),
                    lhs: make_identifier!("abc"),
                    op: ConditionOp::Equals,
                    rhs: Value::NumericLiteral(42),
                },
            }];
            let mut symbol_table = HashMap::new();
            symbol_table.insert(make_identifier!("abc"), Symbol::DeprecatedKey(0x0100));
            compile_to_raw(statements, symbol_table)
        }

        #[test]
        fn correct_value() {
            // Binds when the device has the correct value for the property.
            let raw_instructions = condition_equals_instructions();
            let properties = vec![DeviceProperty { key: 0x0100, value: 42 }];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert_eq!(
                debugger.evaluate_bind_program().unwrap(),
                Some(
                    vec![DeviceProperty { key: 0x0100, value: 42 }]
                        .into_iter()
                        .collect::<HashSet<_>>()
                )
            );
            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::ConditionStatement {
                    key: 0x0100,
                    condition: RawCondition::Equal,
                    success: true,
                    line: 7
                }]
            );
        }

        #[test]
        fn wrong_value() {
            // Doesn't bind when the device has the wrong value for the property.
            let raw_instructions = condition_equals_instructions();
            let properties = vec![DeviceProperty { key: 0x0100, value: 5 }];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::ConditionStatement {
                    key: 0x0100,
                    condition: RawCondition::Equal,
                    success: false,
                    line: 7
                }]
            );
        }

        #[test]
        fn missing_value() {
            // Doesn't bind when the property is not present in the device.
            let raw_instructions = condition_equals_instructions();
            let properties = Vec::new();
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::ConditionStatement {
                    key: 0x0100,
                    condition: RawCondition::Equal,
                    success: false,
                    line: 7
                }]
            );
        }
    }

    mod condition_not_equals {
        use super::*;

        fn condition_not_equals_instructions() -> Vec<RawInstruction<[u32; 3]>> {
            let statements = vec![Statement::ConditionStatement {
                span: span_with_line(7),
                condition: Condition {
                    span: span_with_line(7),
                    lhs: make_identifier!("abc"),
                    op: ConditionOp::NotEquals,
                    rhs: Value::NumericLiteral(42),
                },
            }];
            let mut symbol_table = HashMap::new();
            symbol_table.insert(make_identifier!("abc"), Symbol::DeprecatedKey(0x0100));
            compile_to_raw(statements, symbol_table)
        }

        #[test]
        fn different_value() {
            // Binds when the device has a different value for the property.
            let raw_instructions = condition_not_equals_instructions();
            let properties = vec![DeviceProperty { key: 0x0100, value: 5 }];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert_eq!(
                debugger.evaluate_bind_program().unwrap(),
                Some(
                    vec![DeviceProperty { key: 0x0100, value: 5 }]
                        .into_iter()
                        .collect::<HashSet<_>>()
                )
            );
            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::ConditionStatement {
                    key: 0x0100,
                    condition: RawCondition::NotEqual,
                    success: true,
                    line: 7
                }]
            );
        }

        #[test]
        fn missing_value() {
            // Binds when the property is not present in the device.
            let raw_instructions = condition_not_equals_instructions();
            let properties = Vec::new();
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert_eq!(
                debugger.evaluate_bind_program().unwrap(),
                Some(
                    vec![DeviceProperty { key: 0x0100, value: 0 }]
                        .into_iter()
                        .collect::<HashSet<_>>()
                )
            );
            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::ConditionStatement {
                    key: 0x0100,
                    condition: RawCondition::NotEqual,
                    success: true,
                    line: 7
                }]
            );
        }

        #[test]
        fn same_value() {
            // Doesn't bind when the device has the property in the condition statement.
            let raw_instructions = condition_not_equals_instructions();
            let properties = vec![DeviceProperty { key: 0x0100, value: 42 }];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::ConditionStatement {
                    key: 0x0100,
                    condition: RawCondition::NotEqual,
                    success: false,
                    line: 7
                }]
            );
        }
    }

    mod accept {
        use super::*;

        fn accept_instructions() -> Vec<RawInstruction<[u32; 3]>> {
            let statements = vec![Statement::Accept {
                span: span_with_line(7),
                identifier: make_identifier!("abc"),
                values: vec![Value::NumericLiteral(42), Value::NumericLiteral(314)],
            }];
            let mut symbol_table = HashMap::new();
            symbol_table.insert(make_identifier!("abc"), Symbol::DeprecatedKey(0x0100));

            compile_to_raw(statements, symbol_table)
        }

        #[test]
        fn accepted_value() {
            // Binds when the device has one of the accepted values for the property.
            let raw_instructions = accept_instructions();
            let properties = vec![DeviceProperty { key: 0x0100, value: 42 }];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert_eq!(
                debugger.evaluate_bind_program().unwrap(),
                Some(
                    vec![DeviceProperty { key: 0x0100, value: 42 }]
                        .into_iter()
                        .collect::<HashSet<_>>()
                )
            );

            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::AcceptStatementSuccess { key: 0x0100, value: 42, line: 7 }]
            );
        }

        #[test]
        fn different_value() {
            // Doesn't bind when the device has a different value for the property.
            let raw_instructions = accept_instructions();
            let properties = vec![DeviceProperty { key: 0x0100, value: 5 }];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::AcceptStatementFailure { key: 0x0100, line: 7 }]
            );
        }

        #[test]
        fn missing_value() {
            // Doesn't bind when the device is missing the property.
            let raw_instructions = accept_instructions();
            let properties = Vec::new();
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![DebuggerOutput::AcceptStatementFailure { key: 0x0100, line: 7 }]
            );
        }
    }

    mod if_else {
        use super::*;

        fn if_else_instructions() -> Vec<RawInstruction<[u32; 3]>> {
            /*
            if abc == 1 {
                xyz == 1;
            } else if abc == 2{
                xyz == 2;
            } else {
                xyz == 3;
            }
            */

            let condition1 = Condition {
                span: span_with_line(1),
                lhs: make_identifier!("abc"),
                op: ConditionOp::Equals,
                rhs: Value::NumericLiteral(1),
            };
            let statement1 = Statement::ConditionStatement {
                span: span_with_line(2),
                condition: Condition {
                    span: span_with_line(2),
                    lhs: make_identifier!("xyz"),
                    op: ConditionOp::Equals,
                    rhs: Value::NumericLiteral(1),
                },
            };
            let condition2 = Condition {
                span: span_with_line(3),
                lhs: make_identifier!("abc"),
                op: ConditionOp::Equals,
                rhs: Value::NumericLiteral(2),
            };
            let statement2 = Statement::ConditionStatement {
                span: span_with_line(4),
                condition: Condition {
                    span: span_with_line(1),
                    lhs: make_identifier!("xyz"),
                    op: ConditionOp::Equals,
                    rhs: Value::NumericLiteral(2),
                },
            };
            let statement3 = Statement::ConditionStatement {
                span: span_with_line(6),
                condition: Condition {
                    span: span_with_line(6),
                    lhs: make_identifier!("xyz"),
                    op: ConditionOp::Equals,
                    rhs: Value::NumericLiteral(3),
                },
            };

            let statements = vec![Statement::If {
                span: span_with_line(1),
                blocks: vec![
                    (condition1.clone(), vec![statement1.clone()]),
                    (condition2.clone(), vec![statement2.clone()]),
                ],
                else_block: vec![statement3.clone()],
            }];
            let mut symbol_table = HashMap::new();
            symbol_table.insert(make_identifier!("abc"), Symbol::DeprecatedKey(0x0100));
            symbol_table.insert(make_identifier!("xyz"), Symbol::DeprecatedKey(0x0200));

            compile_to_raw(statements, symbol_table)
        }

        #[test]
        fn if_clause_satisfied() {
            // Binds when the if clause is satisfied.
            let raw_instructions = if_else_instructions();
            let properties = vec![
                DeviceProperty { key: 0x0100, value: 1 },
                DeviceProperty { key: 0x0200, value: 1 },
            ];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert_eq!(
                debugger.evaluate_bind_program().unwrap(),
                Some(
                    vec![
                        DeviceProperty { key: 0x0100, value: 1 },
                        DeviceProperty { key: 0x0200, value: 1 }
                    ]
                    .into_iter()
                    .collect::<HashSet<_>>()
                )
            );
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: true,
                        line: 1
                    },
                    DebuggerOutput::ConditionStatement {
                        key: 0x0200,
                        condition: RawCondition::Equal,
                        success: true,
                        line: 2
                    }
                ]
            );
        }

        #[test]
        fn if_else_clause_satisfied() {
            // Binds when the if else clause is satisfied.
            let raw_instructions = if_else_instructions();
            let properties = vec![
                DeviceProperty { key: 0x0100, value: 2 },
                DeviceProperty { key: 0x0200, value: 2 },
            ];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert_eq!(
                debugger.evaluate_bind_program().unwrap(),
                Some(
                    vec![
                        DeviceProperty { key: 0x0100, value: 2 },
                        DeviceProperty { key: 0x0200, value: 2 },
                    ]
                    .into_iter()
                    .collect::<HashSet<_>>()
                )
            );
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 1
                    },
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: true,
                        line: 3
                    },
                    DebuggerOutput::ConditionStatement {
                        key: 0x0200,
                        condition: RawCondition::Equal,
                        success: true,
                        line: 4
                    }
                ]
            );
        }

        #[test]
        fn else_clause_satisfied() {
            // Binds when the else clause is satisfied.
            let raw_instructions = if_else_instructions();
            let properties = vec![DeviceProperty { key: 0x0200, value: 3 }];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert_eq!(
                debugger.evaluate_bind_program().unwrap(),
                Some(
                    vec![
                        DeviceProperty { key: 0x0200, value: 3 },
                        DeviceProperty { key: 0x0100, value: 0 },
                    ]
                    .into_iter()
                    .collect::<HashSet<_>>()
                )
            );
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 1
                    },
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 3
                    },
                    DebuggerOutput::ConditionStatement {
                        key: 0x0200,
                        condition: RawCondition::Equal,
                        success: true,
                        line: 6
                    }
                ]
            );
        }

        #[test]
        fn incorrect_values() {
            // Doesn't bind when the device has incorrect values for the properties.
            let raw_instructions = if_else_instructions();
            let properties = vec![
                DeviceProperty { key: 0x0100, value: 42 },
                DeviceProperty { key: 0x0200, value: 42 },
            ];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 1
                    },
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 3
                    },
                    DebuggerOutput::ConditionStatement {
                        key: 0x0200,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 6
                    }
                ]
            );
        }

        #[test]
        fn missing_values() {
            // Doesn't bind when the properties are missing in the device.
            let raw_instructions = if_else_instructions();
            let properties = Vec::new();
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 1
                    },
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 3
                    },
                    DebuggerOutput::ConditionStatement {
                        key: 0x0200,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 6
                    }
                ]
            );
        }
    }

    mod abort {
        use super::*;

        fn abort_instructions() -> Vec<RawInstruction<[u32; 3]>> {
            let statements = vec![Statement::False { span: span_with_line(8) }];
            let mut symbol_table = HashMap::new();
            symbol_table.insert(make_identifier!("abc"), Symbol::DeprecatedKey(0x0100));

            compile_to_raw(statements, symbol_table)
        }

        #[test]
        fn aborts() {
            // Doesn't bind when false statement is present.
            let raw_instructions = abort_instructions();
            let properties = vec![
                DeviceProperty { key: 0x0100, value: 42 },
                DeviceProperty { key: 0x0200, value: 1 },
            ];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(debugger.output, vec![DebuggerOutput::FalseStatement { line: 8 },]);
        }
    }

    mod full_program {
        use super::*;

        fn full_program_instructions() -> Vec<RawInstruction<[u32; 3]>> {
            /*
            if abc == 42 {
                false;
            } else {
                accept xyz {1, 2};
                pqr != 5;
            }
            */

            let condition = Condition {
                span: span_with_line(1),
                lhs: make_identifier!("abc"),
                op: ConditionOp::Equals,
                rhs: Value::NumericLiteral(42),
            };
            let false_statement = Statement::False { span: span_with_line(2) };
            let accept_statement = Statement::Accept {
                span: span_with_line(4),
                identifier: make_identifier!("xyz"),
                values: vec![Value::NumericLiteral(1), Value::NumericLiteral(2)],
            };
            let condition_statement = Statement::ConditionStatement {
                span: span_with_line(5),
                condition: Condition {
                    span: span_with_line(5),
                    lhs: make_identifier!("pqr"),
                    op: ConditionOp::NotEquals,
                    rhs: Value::NumericLiteral(5),
                },
            };

            let statements = vec![Statement::If {
                span: span_with_line(1),
                blocks: vec![(condition, vec![false_statement])],
                else_block: vec![accept_statement, condition_statement],
            }];
            let mut symbol_table = HashMap::new();
            symbol_table.insert(make_identifier!("abc"), Symbol::DeprecatedKey(0x0100));
            symbol_table.insert(make_identifier!("xyz"), Symbol::DeprecatedKey(0x0200));
            symbol_table.insert(make_identifier!("pqr"), Symbol::DeprecatedKey(0x0300));

            compile_to_raw(statements, symbol_table)
        }

        #[test]
        fn if_condition_satisfied() {
            // Aborts because if condition is true.
            let raw_instructions = full_program_instructions();
            let properties = vec![DeviceProperty { key: 0x0100, value: 42 }];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: true,
                        line: 1
                    },
                    DebuggerOutput::FalseStatement { line: 2 },
                ]
            );
        }

        #[test]
        fn else_block_satisfied() {
            // Binds because all statements inside else block are satisfied.
            let raw_instructions = full_program_instructions();
            let properties = vec![
                DeviceProperty { key: 0x0100, value: 43 },
                DeviceProperty { key: 0x0200, value: 1 },
            ];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert_eq!(
                debugger.evaluate_bind_program().unwrap(),
                Some(
                    vec![
                        DeviceProperty { key: 0x0100, value: 43 },
                        DeviceProperty { key: 0x0200, value: 1 },
                        DeviceProperty { key: 0x0300, value: 0 },
                    ]
                    .into_iter()
                    .collect::<HashSet<_>>()
                )
            );
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 1
                    },
                    DebuggerOutput::AcceptStatementSuccess { key: 0x0200, value: 1, line: 4 },
                    DebuggerOutput::ConditionStatement {
                        key: 0x0300,
                        condition: RawCondition::NotEqual,
                        success: true,
                        line: 5
                    },
                ]
            );
        }

        #[test]
        fn accept_statement_not_satisfied() {
            // Doesn't bind because accept statement is not satisfied.
            let raw_instructions = full_program_instructions();
            let properties = vec![
                DeviceProperty { key: 0x0100, value: 43 },
                DeviceProperty { key: 0x0200, value: 3 },
            ];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 1
                    },
                    DebuggerOutput::AcceptStatementFailure { key: 0x0200, line: 4 },
                ]
            );
        }

        #[test]
        fn condition_statement_not_satisfied() {
            // Doesn't bind because condition statement is not satisfied.
            let raw_instructions = full_program_instructions();
            let properties = vec![
                DeviceProperty { key: 0x0100, value: 43 },
                DeviceProperty { key: 0x0200, value: 1 },
                DeviceProperty { key: 0x0300, value: 5 },
            ];
            let mut debugger = Debugger::new(&raw_instructions, &properties).unwrap();
            assert!(debugger.evaluate_bind_program().unwrap().is_none());
            assert_eq!(
                debugger.output,
                vec![
                    DebuggerOutput::IfCondition {
                        key: 0x0100,
                        condition: RawCondition::Equal,
                        success: false,
                        line: 1
                    },
                    DebuggerOutput::AcceptStatementSuccess { key: 0x0200, value: 1, line: 4 },
                    DebuggerOutput::ConditionStatement {
                        key: 0x0300,
                        condition: RawCondition::NotEqual,
                        success: false,
                        line: 5
                    },
                ]
            );
        }
    }
}
