rustpiet 0.1.1

A Piet interpreter implementation in Rust
Documentation
use interpreter::Interpreter;
use std::io;
use std::io::Write;

pub fn call_op(interpreter: &mut Interpreter, color_value: (i32, i32)) {
    match color_value {
        (0, 1) => push(interpreter),
        (0, 2) => pop(interpreter),
        (1, 0) => add(interpreter),
        (1, 1) => subtract(interpreter),
        (1, 2) => multiply(interpreter),
        (2, 0) => divide(interpreter),
        (2, 1) => modulo(interpreter),
        (2, 2) => not(interpreter),
        (3, 0) => greater(interpreter),
        (3, 1) => pointer(interpreter),
        (3, 2) => switch(interpreter),
        (4, 0) => duplicate(interpreter),
        (4, 1) => roll(interpreter),
        (4, 2) | (5, 0) => input(interpreter),
        (5, 1) => out_number(interpreter),
        (5, 2) => out_char(interpreter),
        _ => (),
    }
}

fn pop_two(interpreter: &mut Interpreter) -> Option<(i32, i32)> {
    let a = match interpreter.stack.pop() {
        Some(n) => n as i32,
        None => return None,
    };

    let b = match interpreter.stack.pop() {
        Some(n) => n as i32,
        None => return None,
    };

    Some((a, b))
}

fn push(interpreter: &mut Interpreter) {
    interpreter.stack.push(interpreter.current_size as i32);
}

fn pop(interpreter: &mut Interpreter) {
    interpreter.stack.pop();
}

fn add(interpreter: &mut Interpreter) {
    if let Some((a, b)) = pop_two(interpreter) {
        interpreter.stack.push(a + b);
    }
}

fn subtract(interpreter: &mut Interpreter) {
    if let Some((a, b)) = pop_two(interpreter) {
        interpreter.stack.push(b - a);
    }
}

fn multiply(interpreter: &mut Interpreter) {
    if let Some((a, b)) = pop_two(interpreter) {
        interpreter.stack.push(a * b);
    }
}

fn divide(interpreter: &mut Interpreter) {
    if let Some((a, b)) = pop_two(interpreter) {
        interpreter.stack.push(b / a);
    }
}

fn modulo(interpreter: &mut Interpreter) {
    if let Some((a, b)) = pop_two(interpreter) {
        interpreter.stack.push(b % a);
    }
}

fn not(interpreter: &mut Interpreter) {
    if let Some(n) = interpreter.stack.pop() {
        if n == 0 {
            interpreter.stack.push(1);
        } else {
            interpreter.stack.push(0);
        }
    }
}

fn greater(interpreter: &mut Interpreter) {
    if let Some((a, b)) = pop_two(interpreter) {
        if b > a {
            interpreter.stack.push(1);
        } else {
            interpreter.stack.push(0);
        }
    }
}

fn pointer(interpreter: &mut Interpreter) {
    if let Some(n) = interpreter.stack.pop() {
        for _ in 1..n.abs() + 1 {
            if n > 0 {
                interpreter.direction_pointer.step();
            } else {
                interpreter.direction_pointer.step_counter();
            }
        }
    }
}

fn switch(interpreter: &mut Interpreter) {
    if let Some(n) = interpreter.stack.pop() {
        for _ in 1..n.abs() + 1 {
            interpreter.codel_chooser.toggle();
        }
    }
}

fn duplicate(interpreter: &mut Interpreter) {
    let x = match interpreter.stack.last() {
        Some(n) => *n,
        None => return (),
    };

    interpreter.stack.push(x);
}

fn roll(interpreter: &mut Interpreter) {
    if let Some((rolls, depth)) = pop_two(interpreter) {
        let neg_depth = interpreter.stack.len() as i32 - depth;

        for _ in 1..rolls.abs() + 1 {
            if rolls > 0 {
                let x = interpreter.stack.pop().unwrap();
                interpreter.stack.insert(neg_depth as usize, x);
            } else {
                let x = interpreter.stack.remove(neg_depth as usize);
                interpreter.stack.push(x);
            }
        }
    }
}

fn input(interpreter: &mut Interpreter) {
    print!("Please type a number: ");

    io::stdout().flush().unwrap();

    let mut value = String::new();

    io::stdin()
        .read_line(&mut value)
        .expect("Failed to read line");

    let value: i32 = value.trim().parse().expect("Please type a number!");

    interpreter.stack.push(value);
}

fn out_number(interpreter: &mut Interpreter) {
    if let Some(n) = interpreter.stack.pop() {
        println!("{}", n);
    }
}

fn out_char(interpreter: &mut Interpreter) {
    if let Some(n) = interpreter.stack.pop() {
        println!("{}", char::from(n as u8));
    }
}