Skip to content

Commit

Permalink
Allow overriding the number of steps of compile-time execution
Browse files Browse the repository at this point in the history
Should help debugging #28
  • Loading branch information
Wilfred committed Jun 25, 2019
1 parent 485f76c commit 5480840
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 22 deletions.
52 changes: 31 additions & 21 deletions src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#[cfg(test)]
use std::collections::HashMap;
use std::num::Wrapping;
use std::env;

#[cfg(test)]
use quickcheck::quickcheck;
Expand Down Expand Up @@ -51,11 +52,20 @@ pub enum Outcome {
}

/// The maximum number of steps we should execute at compile time.
///
/// It takes around 1 million steps to finish executing bottles.bf at
/// compile time. This is intolerably slow for debug builds of bfc, but
/// instant on a release build.
pub const MAX_STEPS: u64 = 10_000_000;
pub fn max_steps() -> u64 {
// It takes around 1 million steps to finish executing bottles.bf
// at compile time. This is intolerably slow for debug builds of
// bfc, but instant on a release build.
let mut steps = 10_000_000;

match env::var_os("BFC_MAX_STEPS") {
Some(val) => {
steps = val.to_str().unwrap().parse::<u64>().unwrap_or(steps);
},
None => {}
};
steps
}

/// Compile time speculative execution of instructions. We return the
/// final state of the cells, any print side effects, and the point in
Expand Down Expand Up @@ -261,7 +271,7 @@ pub fn execute_with_state<'a>(
#[test]
fn cant_evaluate_inputs() {
let instrs = parse(",.").unwrap();
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand All @@ -277,7 +287,7 @@ fn cant_evaluate_inputs() {
#[test]
fn increment_executed() {
let instrs = parse("+").unwrap();
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand Down Expand Up @@ -322,7 +332,7 @@ fn multiply_move_executed() {
},
];

let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;
assert_eq!(
final_state,
ExecutionState {
Expand All @@ -347,7 +357,7 @@ fn multiply_move_when_current_cell_is_zero() {
position: None,
}];

let (final_state, warning) = execute(&instrs, MAX_STEPS);
let (final_state, warning) = execute(&instrs, max_steps());
assert_eq!(warning, None);
assert_eq!(
final_state,
Expand Down Expand Up @@ -376,7 +386,7 @@ fn multiply_move_wrapping() {
},
];

let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;
assert_eq!(
final_state,
ExecutionState {
Expand Down Expand Up @@ -405,7 +415,7 @@ fn multiply_move_offset_too_high() {
},
];

let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;
let mut expected_cells = vec![Wrapping(0); MAX_CELL_INDEX + 1];
expected_cells[0] = Wrapping(1);
assert_eq!(
Expand Down Expand Up @@ -435,7 +445,7 @@ fn multiply_move_offset_too_low() {
},
];

let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;
assert_eq!(
final_state,
ExecutionState {
Expand All @@ -454,7 +464,7 @@ fn set_executed() {
offset: 0,
position: Some(Position { start: 0, end: 0 }),
}];
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand All @@ -474,7 +484,7 @@ fn set_wraps() {
offset: 0,
position: Some(Position { start: 0, end: 0 }),
}];
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand All @@ -490,7 +500,7 @@ fn set_wraps() {
#[test]
fn decrement_executed() {
let instrs = parse("-").unwrap();
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand All @@ -517,7 +527,7 @@ fn increment_wraps() {
position: Some(Position { start: 0, end: 0 }),
},
];
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand All @@ -533,7 +543,7 @@ fn increment_wraps() {
#[test]
fn ptr_increment_executed() {
let instrs = parse(">").unwrap();
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand All @@ -549,7 +559,7 @@ fn ptr_increment_executed() {
#[test]
fn ptr_out_of_range() {
let instrs = parse("<").unwrap();
let (final_state, warning) = execute(&instrs, MAX_STEPS);
let (final_state, warning) = execute(&instrs, max_steps());

assert_eq!(
final_state,
Expand Down Expand Up @@ -583,7 +593,7 @@ fn limit_to_steps_specified() {
#[test]
fn write_executed() {
let instrs = parse("+.").unwrap();
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand All @@ -599,7 +609,7 @@ fn write_executed() {
#[test]
fn loop_executed() {
let instrs = parse("++[-]").unwrap();
let final_state = execute(&instrs, MAX_STEPS).0;
let final_state = execute(&instrs, max_steps()).0;

assert_eq!(
final_state,
Expand Down Expand Up @@ -802,5 +812,5 @@ fn arithmetic_error_nested_loops() {
// mandlebrot.bf. Previously, if the first element in a loop was
// another loop, we had arithmetic overflow.
let instrs = parse("+[[>>>>>>>>>]+>>>>>>>>>-]").unwrap();
execute(&instrs, MAX_STEPS);
execute(&instrs, max_steps());
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ fn compile_file(matches: &Matches) -> Result<(), String> {
}

let (state, execution_warning) = if opt_level == "2" {
execution::execute(&instrs, execution::MAX_STEPS)
execution::execute(&instrs, execution::max_steps())
} else {
let mut init_state = execution::ExecutionState::initial(&instrs[..]);
// TODO: this will crash on the empty program.
Expand Down

0 comments on commit 5480840

Please sign in to comment.