소스 검색

improving interpreter

Nicolas Winkler 4 년 전
부모
커밋
17001efdec
3개의 변경된 파일230개의 추가작업 그리고 48개의 파일을 삭제
  1. 172 15
      src/interpret.rs
  2. 55 31
      src/main.rs
  3. 3 2
      src/options.rs

+ 172 - 15
src/interpret.rs

@@ -1,26 +1,134 @@
 use super::ir::Instruction;
+use super::options;
+use super::options::Options;
 use std::io::Read;
 use std::io::Write;
 use std::io;
 use std::ops::{Add, Mul, Sub};
 use std::num::Wrapping;
 
-struct Data<T: Add + Mul + Sub + Eq + From<i64>> {
+
+trait FromNum {
+    fn from(n: i64) -> Self;
+}
+trait CellWrite {
+    fn write<S: Write>(&self, s: &mut S);
+}
+trait CellRead {
+    fn read<R: Read>(&mut self, r: &mut R);
+}
+
+impl FromNum for Wrapping<u8> {
+    fn from(n: i64) -> Self { Wrapping(n as u8) }
+}
+impl CellWrite for Wrapping<u8> {
+    fn write<S: Write>(&self, s: &mut S) {
+        s.write(&[self.0]).unwrap();
+        s.flush().unwrap();
+    }
+}
+impl CellRead for Wrapping<u8> {
+    fn read<R: Read>(&mut self, r: &mut R) {
+        let mut bytes: [u8; 1] = [0];
+        if r.read(&mut bytes).is_ok() {
+            *self = Wrapping(bytes[0]);
+        }
+        else {
+            *self = Wrapping(0);
+        }
+    }
+}
+
+
+impl FromNum for Wrapping<u16> {
+    fn from(n: i64) -> Self { Wrapping(n as u16) }
+}
+impl CellWrite for Wrapping<u16> {
+    fn write<S: Write>(&self, s: &mut S) {
+        write!(s, "{}", self.0);
+        s.flush().unwrap();
+    }
+}
+impl CellRead for Wrapping<u16> {
+    fn read<R: Read>(&mut self, r: &mut R) {
+        let mut bytes: [u8; 1] = [0];
+        if r.read(&mut bytes).is_ok() {
+            *self = Wrapping(bytes[0] as _);
+        }
+        else {
+            *self = Wrapping(0);
+        }
+    }
+}
+
+impl FromNum for i64 {
+    fn from(n: i64) -> Self { n as _ }
+}
+impl CellWrite for i64 {
+    fn write<S: Write>(&self, s: &mut S) {
+        s.write(&[*self as u8]).unwrap();
+        s.flush().unwrap();
+    }
+}
+impl CellRead for i64 {
+    fn read<R: Read>(&mut self, r: &mut R) {
+        let mut bytes: [u8; 1] = [0];
+        if r.read(&mut bytes).is_ok() {
+            *self = bytes[0] as _;
+        }
+        else {
+            *self = 0;
+        }
+    }
+}
+
+
+
+
+
+
+
+struct Data<T> {
     memory: Vec<T>,
     ptr: i64,
 }
 
-pub fn run(instructions: &Vec<Instruction>) {
-    let len = 1024;
-    let mut data = Data<Wrapping<u8>> {
-        memory: vec![0; len],
-        ptr: 0,
-    };
-
-    run_instrs(instructions, &mut data);
+pub fn run(instructions: &Vec<Instruction>, opts: &Options) {
+    if opts.cell_size == options::CellSize::Bits(8) {
+        let mut data = Data::<Wrapping<u8>> {
+            memory: vec![Wrapping(0); opts.memory_size as usize],
+            ptr: 0,
+        };
+        run_with_funcs(instructions, &mut data, &|a, b| a + b, &|a, b| a * b);
+    }
+    else if opts.cell_size == options::CellSize::Bits(16) {
+        let mut data = Data::<Wrapping<u16>> {
+            memory: vec![Wrapping(0); opts.memory_size as usize],
+            ptr: 0,
+        };
+        run_with_funcs(instructions, &mut data, &|a, b| a + b, &|a, b| a * b);
+    }
+    else {
+        match opts.cell_size {
+            options::CellSize::Modular(n) => {
+                let n = n as i64;
+                let mut data = Data::<i64> {
+                    memory: vec![0; opts.memory_size as usize],
+                    ptr: 0,
+                };
+                run_with_funcs(instructions, &mut data, &|a, b| (a + b) % n, &|a, b| (a * b) % n);
+            },
+            _ => {}
+        }
+    }
 }
 
-fn run_instrs<T: Add + Mul + Sub + Eq + From<i64>>(instructions: &Vec<Instruction>, data: &mut Data<T>) {
+
+fn run_instrs<T>(instructions: &Vec<Instruction>, data: &mut Data<T>)
+where
+T: Add<Output=T> + Sub<Output=T> + Mul<Output=T>,
+T: Copy + Eq + CellWrite + CellRead + FromNum
+{
     let len = data.memory.len();
     for inst in instructions {
         match inst {
@@ -43,20 +151,69 @@ fn run_instrs<T: Add + Mul + Sub + Eq + From<i64>>(instructions: &Vec<Instructio
             },
             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();
+                cell.read(&mut io::stdin());
+            },
+            Instruction::Write(offset) => {
+                let cell = data.memory[(data.ptr + offset) as usize % len];
+                cell.write(&mut io::stdout());
+            },
+            Instruction::LinearLoop{ offset: glob_offset, factors } => {
+                //assert_eq!(factors.get(&0), Some(&-1));
+                let multiplicator = data.memory[((data.ptr + glob_offset) as usize) % len];
+                for (offset, value) in factors {
+                    let cell = &mut data.memory[(data.ptr + offset + glob_offset) as usize % len];
+                    *cell = *cell + (multiplicator * T::from(*value));
+                }
+                data.memory[((data.ptr + glob_offset) as usize) % len] = T::from(0);
+            },
+        }
+    }
+}
+
+
+fn run_with_funcs<T>(instructions: &Vec<Instruction>,
+                 data: &mut Data<T>,
+                 add: &dyn Fn(T, T) -> T,
+                 mul: &dyn Fn(T, T) -> T)
+where
+T: Copy + Eq + CellWrite + CellRead + FromNum
+{
+    let len = data.memory.len();
+    for inst in instructions {
+        match inst {
+            Instruction::Nop => {},
+            Instruction::Add{ offset, value } => {
+                let cell = &mut data.memory[(data.ptr + offset) as usize % len];
+                *cell = add(*cell, T::from(*value));
+            },
+            Instruction::Set{ offset, value } => {
+                let cell = &mut data.memory[(data.ptr + offset) as usize % len];
+                *cell = T::from(*value);
+            },
+            Instruction::MovePtr(offset) => {
+                data.ptr = data.ptr.wrapping_add(*offset);
+            },
+            Instruction::Loop(instrs) => {
+                while data.memory[data.ptr as usize % len] != T::from(0) {
+                    run_with_funcs(instrs, data, add, mul);
+                }
+            },
+            Instruction::Read(offset) => {
+                let cell = &mut data.memory[(data.ptr + offset) as usize % len];
+                cell.read(&mut io::stdin());
             },
             Instruction::Write(offset) => {
                 let cell = data.memory[(data.ptr + offset) as usize % len];
-                io::stdout().write(&[cell]).unwrap();
-                io::stdout().flush().unwrap();
+                cell.write(&mut io::stdout());
             },
             Instruction::LinearLoop{ offset: glob_offset, factors } => {
-                assert_eq!(factors.get(&0), Some(&-1));
+                //assert_eq!(factors.get(&0), Some(&-1));
                 let multiplicator = data.memory[((data.ptr + glob_offset) as usize) % len];
                 for (offset, value) in factors {
                     let cell = &mut data.memory[(data.ptr + offset + glob_offset) as usize % len];
-                    *cell = cell + (multiplicator * (*value as _));
+                    *cell = add(*cell, mul(multiplicator, T::from(*value)));
                 }
+                data.memory[((data.ptr + glob_offset) as usize) % len] = T::from(0);
             },
         }
     }

+ 55 - 31
src/main.rs

@@ -34,6 +34,10 @@ fn main() -> io::Result<()> {
         .arg(Arg::with_name("input")
                 .takes_value(true)
                 .help("Input file"))
+        .arg(Arg::with_name("interpret")
+                .long("interpret")
+                .short("i")
+                .help("No JIT, run only simple interpreter"))
         .arg(Arg::with_name("transpile")
                 .long("transpile")
                 .short("t")
@@ -43,7 +47,12 @@ fn main() -> io::Result<()> {
                 .long("cell-size")
                 .short("c")
                 .takes_value(true)
-                .help("defines the cell size used"))
+                .help("defines the cell size in bits"))
+        .arg(Arg::with_name("cell modulus")
+                .long("cell-modulus")
+                .short("m")
+                .takes_value(true)
+                .help("defines the cell modulus"))
         .get_matches();
     
     let mut buffer = String::new();
@@ -59,12 +68,21 @@ fn main() -> io::Result<()> {
     if let Some(cell_size) = matches.value_of("cell size") {
         match options::CellSize::from_str(cell_size) {
             Ok(cs) => options.cell_size = cs,
-            Err(e) => {
+            Err(_e) => {
                 eprintln!("invalid cell size '{}'", cell_size);
                 exit(1);
             }
         }
     }
+    else if let Some(cell_modulus) = matches.value_of("cell modulus") {
+        match u64::from_str(cell_modulus) {
+            Ok(cs) => options.cell_size = options::CellSize::Modular(cs),
+            Err(_e) => {
+                eprintln!("invalid cell modulus '{}'", cell_modulus);
+                exit(1);
+            }
+        }
+    }
 
     let insts = parser::parse(&buffer);
     if let Ok(mut insts) = insts {
@@ -72,35 +90,41 @@ fn main() -> io::Result<()> {
         lin_loop_optimizer.visit_instructions(&mut insts);
         let _ = std::mem::replace(&mut insts, lin_loop_optimizer.instructions);
         
-        //for ref inst in &insts {
-            //println!("{}\n", inst.to_string());
-        //}
-        //println!("{}", trans::java::transpile(&insts));
-        //let c = trans::c::transpile_dfg(&dfg);
-        //println!("{}", c);
-        //println!("{}", trans::java::transpile(&insts));
-        
-        match matches.value_of("transpile") {
-            Some(lang) => {
-                //let arena = Arena::new();
-                //let dfg = optimize::create_dfg(&mut insts, &arena);
-                let code = if lang == "c" {
-                    //trans::c::transpile_dfg(&dfg)
-                    trans::c::transpile(&options, &insts)
-                } else if lang == "java" {
-                    trans::java::transpile(&options, &insts)
-                } else if lang == "python" {
-                    trans::python::transpile(&options, &insts)
-                } else if lang == "zombie_ir" {
-                    trans::zombie_ir::transpile(&insts)
-                } else {
-                    eprintln!("invalid transpiler lang '{}'", lang);
-                    "".to_owned()
-                };
-                println!("{}", code);
-            },
-            None => {
-                let _code = compile::compile(&insts);
+
+        if matches.is_present("interpret") {
+            interpret::run(&insts, &options);
+        }
+        else {
+            //for ref inst in &insts {
+                //println!("{}\n", inst.to_string());
+            //}
+            //println!("{}", trans::java::transpile(&insts));
+            //let c = trans::c::transpile_dfg(&dfg);
+            //println!("{}", c);
+            //println!("{}", trans::java::transpile(&insts));
+            
+            match matches.value_of("transpile") {
+                Some(lang) => {
+                    //let arena = Arena::new();
+                    //let dfg = optimize::create_dfg(&mut insts, &arena);
+                    let code = if lang == "c" {
+                        //trans::c::transpile_dfg(&dfg)
+                        trans::c::transpile(&options, &insts)
+                    } else if lang == "java" {
+                        trans::java::transpile(&options, &insts)
+                    } else if lang == "python" {
+                        trans::python::transpile(&options, &insts)
+                    } else if lang == "zombie_ir" {
+                        trans::zombie_ir::transpile(&insts)
+                    } else {
+                        eprintln!("invalid transpiler lang '{}'", lang);
+                        "".to_owned()
+                    };
+                    println!("{}", code);
+                },
+                None => {
+                    let _code = compile::compile(&insts);
+                }
             }
         }
     }

+ 3 - 2
src/options.rs

@@ -1,15 +1,16 @@
 use std::str::FromStr;
 
+#[derive(PartialEq, Clone)]
 pub enum CellLayout {
     Trusting,
     Wrapping,
     Unbounded
 }
 
-
+#[derive(PartialEq, Clone)]
 pub enum CellSize {
     Bits(usize),
-    Modular(usize),
+    Modular(u64),
     Int
 }