diff --git a/Cargo.lock b/Cargo.lock
index aa2e7a5a0..2169e1c58 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -548,9 +548,6 @@ version = "0.1.0"
dependencies = [
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
diff --git a/py_code_object/Cargo.lock b/py_code_object/Cargo.lock
index c39b9fc3b..6ffa57615 100644
--- a/py_code_object/Cargo.lock
+++ b/py_code_object/Cargo.lock
@@ -87,6 +87,7 @@ version = "0.1.0"
dependencies = [
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustpython_vm 0.1.0",
"serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -114,6 +115,14 @@ name = "regex-syntax"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "rustpython_vm"
+version = "0.1.0"
+dependencies = [
+ "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "serde"
version = "0.8.23"
diff --git a/py_code_object/src/convert.rs b/py_code_object/src/convert.rs
index a4f4d1e59..6f4a1632c 100644
--- a/py_code_object/src/convert.rs
+++ b/py_code_object/src/convert.rs
@@ -3,249 +3,97 @@
// this into RustPython bytecode. This to decouple RustPython from CPython
// internal bytecode representations.
-use super::bytecode::{self, CodeObject, Instruction};
+use rustpython_vm::bytecode;
+use py_code_object::{PyCodeObject, NativeType};
-pub fn convert(cpython_bytecode: CPythonByteCode) -> ByteCode {
- let c = Converter::new();
- c.convert(c)
+pub fn convert(cpython_bytecode: PyCodeObject) -> bytecode::CodeObject {
+ let mut c = Converter::new();
+ c.convert(cpython_bytecode);
+ c.code2
}
// TODO: think of an appropriate name for this thing:
pub struct Converter {
- frames: Vec,
+ code: Option,
+ code2: bytecode::CodeObject,
}
impl Converter {
pub fn new() -> Converter {
Converter {
- frames: vec![],
+ code: None,
+ code2: bytecode::CodeObject::new(),
}
}
- fn curr_frame(&mut self) -> &mut Frame {
- self.frames.last_mut().unwrap()
- }
-
- fn pop_frame(&mut self) {
- self.frames.pop().unwrap();
- }
-
- fn unwind(&mut self, reason: String) {
- let curr_frame = self.curr_frame();
- let curr_block = curr_frame.blocks[curr_frame.blocks.len()-1].clone(); // use last?
- curr_frame.why = reason; // Why do we need this?
- debug!("block status: {:?}, {:?}", curr_block.block_type, curr_frame.why);
- match (curr_block.block_type.as_ref(), curr_frame.why.as_ref()) {
- ("loop", "break") => {
- curr_frame.lasti = curr_block.handler; //curr_frame.labels[curr_block.handler]; // Jump to the end
- // Return the why as None
- curr_frame.blocks.pop();
- },
- ("loop", "none") => (), //skipped
- _ => panic!("block stack operation not implemented")
+ pub fn convert(&mut self, code: PyCodeObject) {
+ self.code = Some(code);
+ for op_code in self.code.unwrap().co_code {
+ self.dispatch(op_code);
}
}
- // Can we get rid of the code paramter?
-
- fn make_frame(&self, code: PyCodeObject, callargs: HashMap>, globals: Option>>) -> Frame {
- //populate the globals and locals
- let mut labels = HashMap::new();
- let mut curr_offset = 0;
- for (idx, op) in code.co_code.iter().enumerate() {
- labels.insert(curr_offset, idx);
- curr_offset += op.0;
- }
- //TODO: This is wrong, check https://github.com/nedbat/byterun/blob/31e6c4a8212c35b5157919abff43a7daa0f377c6/byterun/pyvm2.py#L95
- let globals = match globals {
- Some(g) => g,
- None => HashMap::new(),
- };
- let mut locals = globals;
- locals.extend(callargs);
-
- //TODO: move this into the __builtin__ module when we have a module type
- locals.insert("print".to_string(), Rc::new(NativeType::NativeFunction(builtins::print)));
- locals.insert("len".to_string(), Rc::new(NativeType::NativeFunction(builtins::len)));
- Frame {
- code: code,
- stack: vec![],
- blocks: vec![],
- // save the callargs as locals
- globals: locals.clone(),
- locals: locals,
- labels: labels,
- lasti: 0,
- return_value: NativeType::NoneType,
- why: "none".to_string(),
- }
- }
-
- // The Option is the return value of the frame, remove when we have implemented frame
- // TODO: read the op codes directly from the internal code object
- fn run_frame(&mut self, frame: Frame) -> NativeType {
- self.frames.push(frame);
-
- //let mut why = None;
- // Change this to a loop for jump
- loop {
- //while curr_frame.lasti < curr_frame.code.co_code.len() {
- let op_code = {
- let curr_frame = self.curr_frame();
- if curr_frame.code.co_code.len() == 0 { panic!("Trying to run an empty frame. Check if the bytecode is empty"); }
- let op_code = curr_frame.code.co_code[curr_frame.lasti].clone();
- curr_frame.lasti += 1;
- op_code
- };
- let why = self.dispatch(op_code);
- /*if curr_frame.blocks.len() > 0 {
- self.manage_block_stack(&why);
- }
- */
- if let Some(_) = why {
- break;
- }
- }
- let return_value = {
- //let curr_frame = self.frames.last_mut().unwrap();
- self.curr_frame().return_value.clone()
- };
- self.pop_frame();
- return_value
- }
-
- pub fn run_code(&mut self, code: PyCodeObject) {
- let frame = self.make_frame(code, HashMap::new(), None);
- self.run_frame(frame);
- // check if there are any leftover frame, fail if any
- }
-
fn dispatch(&mut self, op_code: (usize, String, Option)) {
- {
- debug!("stack:{:?}", self.curr_frame().stack);
- debug!("env :{:?}", self.curr_frame().locals);
- debug!("Executing op code: {:?}", op_code);
- }
+ debug!("Converting op code: {:?}", op_code);
match (op_code.1.as_ref(), op_code.2) {
("LOAD_CONST", Some(consti)) => {
// println!("Loading const at index: {}", consti);
- let curr_frame = self.curr_frame();
- let value = curr_frame.code.co_consts[consti].clone();
- self.emit(LoadConst(None));
+ let value = match self.code.unwrap().co_consts[consti] {
+ // NativeType::Boolean { value } => { bytecode::Constant::Boolean { true } },
+ // NativeType::Int { value } => { bytecode::Constant::Integer { value: value } },
+ _ => { panic!("Not impl "); }
+ };
+ self.emit(bytecode::Instruction::LoadConst { value: value });
},
// TODO: universal stack element type
("LOAD_CONST", None) => {
- self.emit(LoadConst(None));
+ self.emit(bytecode::Instruction::LoadConst { value: bytecode::Constant::None });
},
("POP_TOP", None) => {
- self.emit(Pop(None));
- },
- ("LOAD_FAST", Some(var_num)) => {
- let curr_frame = self.curr_frame();
- let ref name = curr_frame.code.co_varnames[var_num];
- curr_frame.stack.push(curr_frame.locals.get::(name).unwrap().clone());
+ self.emit(bytecode::Instruction::Pop);
},
("STORE_NAME", Some(namei)) => {
// println!("Loading const at index: {}", consti);
- let curr_frame = self.curr_frame();
- curr_frame.locals.insert(curr_frame.code.co_names[namei].clone(), curr_frame.stack.pop().unwrap().clone());
+ let name = self.code.unwrap().co_names[namei].clone();
+ self.emit(bytecode::Instruction::StoreName { name });
},
("LOAD_NAME", Some(namei)) => {
// println!("Loading const at index: {}", consti);
- let curr_frame = self.curr_frame();
- &curr_frame.code.co_names[namei]
- let name = code.clone();
- self.emit(Instruction::LoadName { name });
+ let name = self.code.unwrap().co_names[namei].clone();
+ self.emit(bytecode::Instruction::LoadName { name });
},
("LOAD_GLOBAL", Some(namei)) => {
// We need to load the underlying value the name points to, but stuff like
// AssertionError is in the names right after compile, so we load the string
// instead for now
- let curr_frame = self.curr_frame();
- let name = &curr_frame.code.co_names[namei];
- curr_frame.stack.push(curr_frame.globals.get::(name).unwrap().clone());
+ // let curr_frame = self.curr_frame();
+ // let name = &curr_frame.code.co_names[namei];
},
("BUILD_LIST", Some(count)) => {
- self.emit(Instruction::BuildList { size: count });
+ self.emit(bytecode::Instruction::BuildList { size: count });
},
+/*
("BUILD_SLICE", Some(count)) => {
let curr_frame = self.curr_frame();
assert!(count == 2 || count == 3);
- let mut vec = vec!();
- for _ in 0..count {
- vec.push(curr_frame.stack.pop().unwrap());
- }
- vec.reverse();
- let mut out:Vec