Skip to content

Commit

Permalink
add register set command
Browse files Browse the repository at this point in the history
  • Loading branch information
chanmix51 committed Apr 11, 2024
1 parent 161ecd3 commit 94a0b0f
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 102 deletions.
38 changes: 13 additions & 25 deletions soft65c02_tester/rules.pest
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,38 @@ sentence = _{ SOI ~ instruction | COMMENT ~ EOI }
instruction = { registers_instruction |
memory_instruction |
run_instruction |
disassemble_instruction |
assert_instruction |
reset_instruction |
marker }

marker = {^"marker" ~ "$$" ~ description ~ "$$" }

reset_instruction = { ^"reset" ~ reset_memory_target | reset_registers_target | reset_all_target }
reset_memory_target = { ^"memory" }
reset_registers_target = { ^"registers" }
reset_all_target = { ^"all" }

registers_instruction = { ^"registers" ~ registers_action }
registers_action = _{ registers_show | registers_flush }
registers_action = _{ registers_set | registers_flush }
registers_flush = { ^"flush" }
registers_show = { ^"show" }
registers_set = { ^"set" ~ register_assignment }

register_assignment = { assignment8 | assignment16 }

assignment8 = _{ register8 ~ "=" ~ value8 }
assignment16 = _{ register16 ~ "=" ~ value16 }

memory_instruction = { ^"memory" ~ memory_action }
memory_action = _{ memory_show | memory_load | memory_write | memory_flush | ^"sub " ~ memory_sub_action }
memory_action = _{ memory_load | memory_write | memory_flush }
memory_flush = { ^"flush" }
memory_show = { ^"show" ~ memory_address ~ size_parameter }
memory_load = { ^"load" ~ memory_address ~ filename }
memory_write = { ^"write" ~ memory_address ~ ^"0x(" ~ bytes ~ ")" }

memory_sub_action = _{ memory_sub_list | memory_sub_add }
memory_sub_list = { ^"list" }
memory_sub_add = { ^"add" ~ memory_address ~ memory_sub_name }
memory_sub_name = { ASCII_ALPHANUMERIC+ }

run_instruction = { ^"run" ~ (memory_address)? ~ (run_until_condition)? }
run_until_condition = { ^"until" ~ boolean_condition }

disassemble_instruction = {
^"disassemble" ~ memory_address ~ size_parameter
| ^"disassemble" ~ size_parameter }

assert_instruction = { ^"assert" ~ boolean_condition ~ "$$" ~ description ~ "$$"}

boolean_condition = { boolean | operation }
boolean_condition = { boolean | comparison }

boolean = { ^"true" | ^"false" }
operation = { operation16 | operation8 }
operation16 = _{ location16 ~ operator ~ value16 }
operation8 = _{ location8 ~ operator ~ value8 }
comparison = { comparison16 | comparison8 }
comparison16 = _{ location16 ~ comparison_operator ~ value16 }
comparison8 = _{ location8 ~ comparison_operator ~ value8 }

location16 = _{ register16 }
location8 = _{ memory_address | register8 }
Expand All @@ -61,7 +49,7 @@ value8 = { "0x" ~ ASCII_HEX_DIGIT{2} | "0b" ~ ASCII_BIN_DIGIT{8} }
bytes = @{ ASCII_HEX_DIGIT{2} ~ ("," ~ ASCII_HEX_DIGIT{2})* }
size_parameter = { ASCII_DIGIT+ }

operator = { ">=" | "<=" | "!=" | "=" | ">" | "<" }
comparison_operator = { ">=" | "<=" | "!=" | "=" | ">" | "<" }
filename = { "\"" ~ filechar+ ~ "\"" }
filechar = _{ ASCII_ALPHANUMERIC | "." | "_" | "/" }
description = { ((!"$$") ~ ANY)* }
84 changes: 39 additions & 45 deletions soft65c02_tester/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::{fs::File, io::Read, path::PathBuf};

use soft65c02_lib::{execute_step, AddressableIO, LogLine, Memory, Registers};

use crate::{until_condition::BooleanExpression, AppResult};
use crate::{
until_condition::{Assignment, BooleanExpression},
AppResult,
};

#[derive(Debug)]
pub enum OutputToken {
Expand Down Expand Up @@ -92,13 +95,23 @@ impl Command for RunCommand {
#[derive(Debug)]
pub enum RegisterCommand {
Flush,
Set { assignment: Assignment },
}

impl Command for RegisterCommand {
fn execute(&self, registers: &mut Registers, _memory: &mut Memory) -> AppResult<OutputToken> {
registers.initialize(0x0000);
fn execute(&self, registers: &mut Registers, memory: &mut Memory) -> AppResult<OutputToken> {
let outputs = match self {
Self::Flush => {
registers.initialize(0x0000);

vec!["registers flushed".to_string()]
}
Self::Set { assignment } => assignment.execute(registers, memory)?,
};

Ok(OutputToken::Setup(vec!["registers flushed".to_string()]))
let token = OutputToken::Setup(outputs);

Ok(token)
}
}

Expand Down Expand Up @@ -190,7 +203,7 @@ mod assert_command_tests {
mod run_command_tests {
use soft65c02_lib::AddressableIO;

use crate::until_condition::Source;
use crate::until_condition::{RegisterSource, Source};

use super::*;

Expand Down Expand Up @@ -225,7 +238,10 @@ mod run_command_tests {
#[test]
fn run_with_condition() {
let command = RunCommand {
stop_condition: BooleanExpression::StrictlyGreater(Source::RegisterX, Source::Value(0)),
stop_condition: BooleanExpression::StrictlyGreater(
Source::Register(RegisterSource::RegisterX),
Source::Value(0),
),
start_address: Some(0x1234),
};
let mut registers = Registers::new_initialized(0x1000);
Expand Down Expand Up @@ -253,6 +269,8 @@ mod run_command_tests {

#[cfg(test)]
mod register_command_tests {
use crate::until_condition::{RegisterSource, Source};

use super::*;

#[test]
Expand All @@ -265,6 +283,20 @@ mod register_command_tests {
assert!(matches!(token, OutputToken::Setup(s) if s[0] == *"registers flushed"));
assert_eq!(0x0000, registers.command_pointer);
}

#[test]
fn test_set() {
let command = RegisterCommand::Set {
assignment: Assignment::new(Source::Value(0xff), RegisterSource::RegisterX),
};
let mut registers = Registers::new_initialized(0xffff);
let mut memory = Memory::new_with_ram();
let token = command.execute(&mut registers, &mut memory).unwrap();

eprintln!("token => {token:?}");
assert!(matches!(token, OutputToken::Setup(s) if s[0] == *"register X set to 0xff"));
assert_eq!(0xff, registers.register_x);
}
}

#[cfg(test)]
Expand All @@ -282,7 +314,7 @@ mod memory_command_tests {
let token = command.execute(&mut registers, &mut memory).unwrap();

assert_eq!(vec![0x00, 0x00, 0x00], memory.read(0x000, 3).unwrap());
assert!(matches!(token, OutputToken::Setup(s) if s.len() == 0));
assert!(matches!(token, OutputToken::Setup(s) if s.is_empty()));
}

#[test]
Expand Down Expand Up @@ -351,41 +383,3 @@ mod memory_command_tests {
assert!(matches!(token, OutputToken::Setup(s) if s[0].contains(&expected)));
}
}

#[cfg(test)]
mod cli_command_tests {
use crate::CliCommandParser;

use super::*;

#[test]
fn test_assertion() {
let mut registers = Registers::new(0x0000);
let mut memory = Memory::new_with_ram();

let token = CliCommandParser::from("assert #0x0000 = 0x00 $$The first byte is zero$$")
.unwrap()
.execute(&mut registers, &mut memory)
.unwrap();

assert!(
matches!(token, OutputToken::Assertion { success, description } if success && description == *"The first byte is zero")
);
}

#[test]
fn test_bad_assertion() {
let mut registers = Registers::new(0x0000);
let mut memory = Memory::new_with_ram();

let token =
CliCommandParser::from("assert #0x0000 = 0x01 $$The first byte is one, really?$$")
.unwrap()
.execute(&mut registers, &mut memory)
.unwrap();

assert!(
matches!(token, OutputToken::Assertion { success, description } if !success && description == *"The first byte is one, really?")
);
}
}
27 changes: 16 additions & 11 deletions soft65c02_tester/src/pest_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use pest_derive::Parser;

use crate::{
commands::*,
until_condition::{BooleanExpression, Source},
until_condition::{BooleanExpression, RegisterSource, Source},
AppResult,
};

Expand Down Expand Up @@ -178,6 +178,8 @@ impl RunCommandParser {

#[cfg(test)]
mod run_command_parser_tests {
use crate::until_condition::RegisterSource;

use super::*;

#[test]
Expand Down Expand Up @@ -211,7 +213,7 @@ mod run_command_parser_tests {
let command = RunCommandParser::from_pairs(parser.next().unwrap().into_inner()).unwrap();

if let BooleanExpression::StrictlyGreater(lt, rt) = command.stop_condition {
assert!(matches!(lt, Source::Accumulator));
assert!(matches!(lt, Source::Register(RegisterSource::Accumulator)));
assert!(matches!(rt, Source::Value(data) if data == 0x12));
} else {
panic!(
Expand Down Expand Up @@ -418,14 +420,14 @@ pub fn parse_boolean_condition(mut nodes: Pairs<Rule>) -> AppResult<BooleanExpre
let node = nodes.next().unwrap();
let expression = match node.as_rule() {
Rule::boolean => BooleanExpression::Value(node.as_str() == "true"),
Rule::operation => parse_operation(node.into_inner())?,
Rule::comparison => parse_comparison(node.into_inner())?,
smt => panic!("unknown node type '{smt:?}'. Is the Pest grammar up to date?"),
};

Ok(expression)
}

fn parse_operation(mut nodes: Pairs<Rule>) -> AppResult<BooleanExpression> {
fn parse_comparison(mut nodes: Pairs<Rule>) -> AppResult<BooleanExpression> {
let node = nodes.next().unwrap();
let lh = match node.as_rule() {
Rule::register8 | Rule::register16 => parse_source_register(&node),
Expand Down Expand Up @@ -456,12 +458,12 @@ fn parse_operation(mut nodes: Pairs<Rule>) -> AppResult<BooleanExpression> {

fn parse_source_register(node: &Pair<Rule>) -> Source {
match node.as_str() {
"A" => Source::Accumulator,
"X" => Source::RegisterX,
"Y" => Source::RegisterY,
"S" => Source::RegisterS,
"SP" => Source::RegisterSP,
"CP" => Source::RegisterCP,
"A" => Source::Register(RegisterSource::Accumulator),
"X" => Source::Register(RegisterSource::RegisterX),
"Y" => Source::Register(RegisterSource::RegisterY),
"S" => Source::Register(RegisterSource::Status),
"SP" => Source::Register(RegisterSource::StackPointer),
"CP" => Source::Register(RegisterSource::CommandPointer),
v => panic!("unknown register type '{:?}'.", v),
}
}
Expand Down Expand Up @@ -502,7 +504,10 @@ mod tests {

assert!(matches!(
output,
BooleanExpression::Different(Source::Accumulator, Source::Value(0xff))
BooleanExpression::Different(
Source::Register(RegisterSource::Accumulator),
Source::Value(0xff)
)
));
}

Expand Down
Loading

0 comments on commit 94a0b0f

Please sign in to comment.