Ver Fonte

initial commit

Nicolas Winkler há 6 anos atrás
commit
034c38d2c5
12 ficheiros alterados com 176 adições e 0 exclusões
  1. 2 0
      .gitignore
  2. 4 0
      Cargo.lock
  3. 7 0
      Cargo.toml
  4. BIN
      src/.interpret.rs.swp
  5. BIN
      src/.ir.rs.swp
  6. BIN
      src/.lowering.rs.swp
  7. BIN
      src/.main.rs.swp
  8. BIN
      src/.parser.rs.swp
  9. 51 0
      src/interpret.rs
  10. 16 0
      src/ir.rs
  11. 20 0
      src/main.rs
  12. 76 0
      src/parser.rs

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+/target
+**/*.rs.bk

+ 4 - 0
Cargo.lock

@@ -0,0 +1,4 @@
+[[package]]
+name = "zombie"
+version = "0.1.0"
+

+ 7 - 0
Cargo.toml

@@ -0,0 +1,7 @@
+[package]
+name = "zombie"
+version = "0.1.0"
+authors = ["Nicolas Winkler <nicolas.winkler@gmx.ch>"]
+edition = "2018"
+
+[dependencies]

BIN
src/.interpret.rs.swp


BIN
src/.ir.rs.swp


BIN
src/.lowering.rs.swp


BIN
src/.main.rs.swp


BIN
src/.parser.rs.swp


+ 51 - 0
src/interpret.rs

@@ -0,0 +1,51 @@
+use super::ir::Instruction;
+use std::io::Read;
+use std::io::Write;
+use std::io;
+
+struct Data {
+    memory: Vec<u8>,
+    ptr: i64,
+}
+
+pub fn run(instructions: &Vec<Instruction>) {
+    let len = 1024;
+    let mut data = Data {
+        memory: vec![0; len],
+        ptr: 0,
+    };
+
+    run_instrs(instructions, &mut data);
+}
+
+fn run_instrs(instructions: &Vec<Instruction>, data: &mut Data) {
+    let len = data.memory.len();
+    for inst in instructions {
+        match inst {
+            Instruction::Add{ offset, value } => {
+                let cell = &mut data.memory[(data.ptr + offset) as usize % len];
+                *cell = cell.wrapping_add(*value as u8);
+            },
+            Instruction::MovePtr(offset) => {
+                data.ptr = data.ptr.wrapping_add(*offset);
+            },
+            Instruction::Loop(instrs) => {
+                while data.memory[data.ptr as usize % len] != 0 {
+                    run_instrs(instrs, data);
+                }
+            },
+            Instruction::Read(offset) => {
+                let cell = &mut data.memory[(data.ptr + offset) as usize % len];
+                *cell = io::stdin().bytes().next().unwrap_or(Ok(0)).unwrap_or_default();
+            },
+            Instruction::Write(offset) => {
+                let cell = data.memory[(data.ptr + offset) as usize % len];
+                io::stdout().write(&[cell]).unwrap();
+                io::stdout().flush().unwrap();
+            }
+            _ => {}
+        }
+    }
+}
+
+

+ 16 - 0
src/ir.rs

@@ -0,0 +1,16 @@
+
+use std::collections::BTreeMap;
+
+pub enum Instruction {
+    Add{ offset: i64, value: i64 },
+    LinearLoop{ offset: i64, increment: i64, factors: BTreeMap<i64, i64> },
+    MovePtr(i64),
+    Loop(Vec<Instruction>),
+    Read(i64),
+    Write(i64)
+}
+
+
+
+
+

+ 20 - 0
src/main.rs

@@ -0,0 +1,20 @@
+use std::io::{self, Read};
+
+pub mod ir;
+pub mod parser;
+pub mod interpret;
+
+fn main() -> io::Result<()> {
+    let mut buffer = String::new();
+    io::stdin().read_to_string(&mut buffer)?;
+
+    let insts = parser::parse(&buffer);
+    if let Ok(insts) = insts {
+        interpret::run(&insts);
+    }
+    else if let Err(msg) = insts {
+        println!("error parsing: {}", msg);
+    }
+
+    Ok(())
+}

+ 76 - 0
src/parser.rs

@@ -0,0 +1,76 @@
+use std::collections::BTreeMap;
+use super::ir;
+
+pub fn parse(code: &str) -> Result<Vec<ir::Instruction>, &str> {
+    let mut ptr: i64 = 0;
+    let mut add_map: BTreeMap<i64, i64> = BTreeMap::new();
+    let mut instruction_stack: Vec<Vec<ir::Instruction>> = Vec::new();
+    let mut instructions: Vec<ir::Instruction> = Vec::new();
+
+    let implement = |add_map: &mut BTreeMap<i64, i64>, instructions: &mut Vec<ir::Instruction>, ptr: &mut i64| {
+        for (&offset, &value) in add_map.iter() {
+            instructions.push(ir::Instruction::Add{ value, offset });
+        }
+        add_map.clear();
+        if *ptr != 0 {
+            instructions.push(ir::Instruction::MovePtr(*ptr));
+            *ptr = 0;
+        }
+    };
+
+    for c in code.chars() {
+        match c {
+            '+' => {
+                match add_map.get_mut(&ptr) {
+                    Some(entry) => { *entry = entry.wrapping_add(1); },
+                    None => { add_map.insert(ptr, 1); }
+                }
+            },
+            '-' => {
+                match add_map.get_mut(&ptr) {
+                    Some(entry) => { *entry = entry.wrapping_sub(1); },
+                    None => { add_map.insert(ptr, -1); }
+                }
+            },
+            '>' => { ptr += 1; },
+            '<' => { ptr -= 1; },
+            '.' => {
+                implement(&mut add_map, &mut instructions, &mut ptr);
+                instructions.push(ir::Instruction::Write(ptr));
+            },
+            ',' => {
+                implement(&mut add_map, &mut instructions, &mut ptr);
+                instructions.push(ir::Instruction::Read(ptr));
+            },
+            '[' => {
+                implement(&mut add_map, &mut instructions, &mut ptr);
+                instruction_stack.push(instructions);
+                instructions = Vec::new();
+            },
+            ']' => {
+                implement(&mut add_map, &mut instructions, &mut ptr);
+                let top = instruction_stack.pop();
+                if let Some(mut inst) = top {
+                    inst.push(ir::Instruction::Loop(instructions));
+                    instructions = inst;
+                }
+                else {
+                    // error, too many ']'
+                    return Err("found ']' without matching '['");
+                }
+            },
+
+            _ => {}
+        }
+    }
+
+    if instruction_stack.len() > 0 {
+        return Err("found '[' without matching ']'");
+    }
+
+    Ok(instructions)
+}
+
+
+
+