~jpl8/piet_interpreter

360bad4485f88eb1a4314ab894d79129fb6dedc3 — jpl 3 years ago 57afb7e
add duplicate, roll, and utf8 to unicode
2 files changed, 109 insertions(+), 0 deletions(-)

M src/interpreter/interpreter_tests.rs
M src/interpreter/mod.rs
M src/interpreter/interpreter_tests.rs => src/interpreter/interpreter_tests.rs +21 -0
@@ 306,3 306,24 @@ fn pointer_works() {
    assert_eq!(popped, 3);

}

#[test]
#[ignore]
fn switch_works() { }

#[test]
#[ignore]
fn roll_works() { }

#[test]
fn get_utf8_char() {
    let buffer = "€";
    assert_eq!(Interpreter::get_utf8_char(&buffer), [0xE2, 0x82, 0xAC]);
}

#[test]
fn utf8_to_unicode() {
    let bytes = [0xE2, 0x82, 0xAC]; // €
    assert_eq!(Interpreter::utf8_to_unicode(&bytes), 0x20AC);

}

M src/interpreter/mod.rs => src/interpreter/mod.rs +88 -0
@@ 186,6 186,56 @@ impl Interpreter {

                }

                Op::Switch => {
                    if let Some(val) = self.stack.pop() {
                        for _ in 0..(val.abs()) {
                            let new_dir = self.head().codel_chooser().toggle();
                            self.head_as_mut().set_codel_chooser(new_dir);
                        }
                    }
                    Ok(())

                }

                Op::Duplicate => {
                    if let Some(val) = self.stack.pop() {
                        self.stack.push(val);
                        self.stack.push(val);
                    }
                    Ok(())
                }

                Op::Roll => {
                    if self.stack.len() < 3 {
                        return Err(Error::new(ErrorKind::InvalidInput, "Not enough values on stack!"));
                    }

                    let first_pop  = self.stack.pop().unwrap();
                    let second_pop = self.stack.pop().unwrap();
                    if second_pop < 0 {
                            // depth is negative -> ignore
                            return Ok(());
                        }

                    if first_pop < 0 {
                       for _ in 0..(first_pop.abs()) {
                           let front = self.stack.remove(0);
                           self.stack.insert(second_pop as usize, front);
                       }
                    }
                    else { 
                        for _ in 0..first_pop {
                            let third_pop  = self.stack.pop().unwrap();
                            self.stack.insert(self.stack.len() - second_pop as usize, third_pop);
                        }
                    }
                    Ok(())
 
                }

                // Op::InNum => {

                // }

                _ => {Ok(())}



@@ 269,6 319,44 @@ impl Interpreter {
    
    }

    fn get_utf8_char(buffer: &str) -> &[u8] { 

        let bytes = buffer.as_bytes();
        let num_bytes = bytes[0].reverse_bits().trailing_ones() as usize;


        return &bytes[..num_bytes];


    }

    fn utf8_to_unicode(bytes: &[u8]) -> isize { 
        let num_bytes = bytes[0].reverse_bits().trailing_ones() as usize;

        let mut code_point: Vec<&str> = vec!();
        let byte_strs: Vec<String> = bytes.iter().map(|byte| format!("{:b}", byte)).collect();
        let header_str = &byte_strs[0];
        code_point.push(&header_str[num_bytes+1..]);

        for i in 1..num_bytes {
            code_point.push(&byte_strs[i][2..]);
        }

        
        let mut code_point_num: isize = 0;
        let mut multiplier = 1;

        for bit in code_point.join("").chars().rev() {
            code_point_num += (bit.to_digit(2).unwrap() as isize) * multiplier;
            multiplier *= 2;

        }

        code_point_num

    }


}