forked from Rust-related/RustPython
Compare commits
2 Commits
no_std
...
framestack
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5b6b61fba | ||
|
|
ee86229ff6 |
@@ -9,7 +9,8 @@ assert locals_dict['foo'] == foo
|
||||
def test_function():
|
||||
x = 17
|
||||
assert sys._getframe().f_locals is not locals_dict
|
||||
assert sys._getframe().f_locals['x'] == 17
|
||||
assert sys._getframe(0).f_locals['x'] == 17
|
||||
assert sys._getframe(1).f_locals['foo'] == 'bar'
|
||||
|
||||
test_function()
|
||||
|
||||
@@ -18,3 +19,8 @@ class TestClass():
|
||||
assert sys._getframe().f_locals['self'] == self
|
||||
|
||||
TestClass()
|
||||
|
||||
try:
|
||||
sys._getframe(100)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
@@ -3,7 +3,6 @@ extern crate rustpython_parser;
|
||||
use self::rustpython_parser::ast;
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::builtins;
|
||||
@@ -39,7 +38,6 @@ enum Block {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Frame {
|
||||
pub code: bytecode::CodeObject,
|
||||
// We need 1 stack per frame
|
||||
@@ -82,22 +80,13 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_frame_full(&mut self, vm: &mut VirtualMachine) -> PyResult {
|
||||
match self.run_frame(vm)? {
|
||||
ExecutionResult::Return(value) => Ok(value),
|
||||
_ => panic!("Got unexpected result from function"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_frame(&mut self, vm: &mut VirtualMachine) -> Result<ExecutionResult, PyObjectRef> {
|
||||
pub fn run(&mut self, vm: &mut VirtualMachine) -> Result<ExecutionResult, PyObjectRef> {
|
||||
let filename = if let Some(source_path) = &self.code.source_path {
|
||||
source_path.to_string()
|
||||
} else {
|
||||
"<unknown>".to_string()
|
||||
};
|
||||
|
||||
let prev_frame = mem::replace(&mut vm.current_frame, Some(vm.ctx.new_frame(self.clone())));
|
||||
|
||||
// This is the name of the object being run:
|
||||
let run_obj_name = &self.code.obj_name.to_string();
|
||||
|
||||
@@ -146,7 +135,6 @@ impl Frame {
|
||||
}
|
||||
};
|
||||
|
||||
vm.current_frame = prev_frame;
|
||||
value
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
*/
|
||||
|
||||
use super::super::frame::Frame;
|
||||
use super::super::pyobject::{
|
||||
AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
@@ -30,26 +29,25 @@ fn frame_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
fn frame_flocals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(frame, Some(vm.ctx.frame_type()))]);
|
||||
let frame = get_value(frame);
|
||||
let py_scope = frame.locals.clone();
|
||||
let py_scope = py_scope.borrow();
|
||||
if let PyObjectKind::Frame { ref frame } = frame.borrow().kind {
|
||||
let py_scope = frame.locals.clone();
|
||||
let py_scope = py_scope.borrow();
|
||||
|
||||
if let PyObjectKind::Scope { scope } = &py_scope.kind {
|
||||
Ok(scope.locals.clone())
|
||||
if let PyObjectKind::Scope { scope } = &py_scope.kind {
|
||||
Ok(scope.locals.clone())
|
||||
} else {
|
||||
panic!("The scope isn't a scope!");
|
||||
}
|
||||
} else {
|
||||
panic!("The scope isn't a scope!");
|
||||
panic!("Frame doesn't contain a frame: {:?}", frame);
|
||||
}
|
||||
}
|
||||
|
||||
fn frame_fcode(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(frame, Some(vm.ctx.frame_type()))]);
|
||||
Ok(vm.ctx.new_code_object(get_value(frame).code))
|
||||
}
|
||||
|
||||
pub fn get_value(obj: &PyObjectRef) -> Frame {
|
||||
if let PyObjectKind::Frame { frame } = &obj.borrow().kind {
|
||||
frame.clone()
|
||||
if let PyObjectKind::Frame { ref frame } = frame.borrow().kind {
|
||||
Ok(vm.ctx.new_code_object(frame.code.clone()))
|
||||
} else {
|
||||
panic!("Inner error getting int {:?}", obj);
|
||||
panic!("Frame doesn't contain a frame: {:?}", frame);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* The mythical generator.
|
||||
*/
|
||||
|
||||
use super::super::frame::{ExecutionResult, Frame};
|
||||
use super::super::frame::ExecutionResult;
|
||||
use super::super::pyobject::{
|
||||
AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
@@ -17,7 +17,7 @@ pub fn init(context: &PyContext) {
|
||||
generator_type.set_attr("send", context.new_rustfunc(generator_send));
|
||||
}
|
||||
|
||||
pub fn new_generator(vm: &mut VirtualMachine, frame: Frame) -> PyResult {
|
||||
pub fn new_generator(vm: &mut VirtualMachine, frame: PyObjectRef) -> PyResult {
|
||||
let g = PyObject::new(
|
||||
PyObjectKind::Generator { frame: frame },
|
||||
vm.ctx.generator_type.clone(),
|
||||
@@ -47,8 +47,13 @@ fn generator_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
fn send(vm: &mut VirtualMachine, gen: &PyObjectRef, value: &PyObjectRef) -> PyResult {
|
||||
if let PyObjectKind::Generator { ref mut frame } = gen.borrow_mut().kind {
|
||||
frame.push_value(value.clone());
|
||||
match frame.run_frame(vm)? {
|
||||
if let PyObjectKind::Frame { ref mut frame } = frame.borrow_mut().kind {
|
||||
frame.push_value(value.clone());
|
||||
} else {
|
||||
panic!("Generator frame isn't a frame.");
|
||||
}
|
||||
|
||||
match vm.run_frame(frame.clone())? {
|
||||
ExecutionResult::Yield(value) => Ok(value),
|
||||
ExecutionResult::Return(_value) => {
|
||||
// Stop iteration!
|
||||
|
||||
@@ -459,8 +459,13 @@ impl PyContext {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_frame(&self, frame: Frame) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::Frame { frame: frame }, self.frame_type())
|
||||
pub fn new_frame(&self, code: PyObjectRef, scope: PyObjectRef) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyObjectKind::Frame {
|
||||
frame: Frame::new(code, scope),
|
||||
},
|
||||
self.frame_type(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_property(&self, function: RustPyFunc) -> PyObjectRef {
|
||||
@@ -811,7 +816,7 @@ pub enum PyObjectKind {
|
||||
defaults: PyObjectRef,
|
||||
},
|
||||
Generator {
|
||||
frame: Frame,
|
||||
frame: PyObjectRef,
|
||||
},
|
||||
BoundMethod {
|
||||
function: PyObjectRef,
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use super::obj::objint;
|
||||
use super::obj::objtype;
|
||||
use super::pyobject::{DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::vm::VirtualMachine;
|
||||
use num_bigint::ToBigInt;
|
||||
use obj::objtype;
|
||||
use pyobject::{DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use num_traits::ToPrimitive;
|
||||
use std::env;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::{env, mem};
|
||||
use vm::VirtualMachine;
|
||||
|
||||
/*
|
||||
* The magic sys module.
|
||||
@@ -15,12 +18,31 @@ fn argv(ctx: &PyContext) -> PyObjectRef {
|
||||
ctx.new_list(argv)
|
||||
}
|
||||
|
||||
fn getframe(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
|
||||
if let Some(frame) = &vm.current_frame {
|
||||
Ok(frame.clone())
|
||||
} else {
|
||||
panic!("Current frame is undefined!")
|
||||
}
|
||||
fn getframe(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [],
|
||||
optional = [(offset, Some(vm.ctx.int_type()))]
|
||||
);
|
||||
let idx = match offset {
|
||||
Some(int) => {
|
||||
if let Some(offset) = objint::get_value(int).to_usize() {
|
||||
if offset > vm.frames.len() - 1 {
|
||||
return Err(vm.new_value_error("call stack is not deep enough".to_string()));
|
||||
}
|
||||
offset
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
|
||||
let idx = vm.frames.len() - idx - 1;
|
||||
|
||||
let frame = &vm.frames[idx];
|
||||
Ok(frame.clone())
|
||||
}
|
||||
|
||||
fn sys_getrefcount(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
33
vm/src/vm.rs
33
vm/src/vm.rs
@@ -10,7 +10,7 @@ use std::collections::hash_map::HashMap;
|
||||
|
||||
use super::builtins;
|
||||
use super::bytecode;
|
||||
use super::frame::Frame;
|
||||
use super::frame::ExecutionResult;
|
||||
use super::obj::objcode::copy_code;
|
||||
use super::obj::objgenerator;
|
||||
use super::obj::objiter;
|
||||
@@ -35,7 +35,7 @@ pub struct VirtualMachine {
|
||||
pub sys_module: PyObjectRef,
|
||||
pub stdlib_inits: HashMap<String, stdlib::StdlibInitFunc>,
|
||||
pub ctx: PyContext,
|
||||
pub current_frame: Option<PyObjectRef>,
|
||||
pub frames: Vec<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl VirtualMachine {
|
||||
@@ -52,13 +52,32 @@ impl VirtualMachine {
|
||||
sys_module: sysmod,
|
||||
stdlib_inits,
|
||||
ctx: ctx,
|
||||
current_frame: None,
|
||||
frames: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_code_obj(&mut self, code: PyObjectRef, scope: PyObjectRef) -> PyResult {
|
||||
let mut frame = Frame::new(code, scope);
|
||||
frame.run_frame_full(self)
|
||||
let frame = self.ctx.new_frame(code, scope);
|
||||
self.run_frame_full(frame)
|
||||
}
|
||||
|
||||
pub fn run_frame_full(&mut self, frame: PyObjectRef) -> PyResult {
|
||||
match self.run_frame(frame)? {
|
||||
ExecutionResult::Return(value) => Ok(value),
|
||||
_ => panic!("Got unexpected result from function"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_frame(&mut self, frame: PyObjectRef) -> Result<ExecutionResult, PyObjectRef> {
|
||||
let result;
|
||||
self.frames.push(frame.clone());
|
||||
if let PyObjectKind::Frame { ref mut frame } = frame.borrow_mut().kind {
|
||||
result = frame.run(self);
|
||||
} else {
|
||||
panic!("Frame doesn't contain a frame: {:?}", frame);
|
||||
}
|
||||
self.frames.pop();
|
||||
result
|
||||
}
|
||||
|
||||
/// Create a new python string object.
|
||||
@@ -260,13 +279,13 @@ impl VirtualMachine {
|
||||
self.fill_scope_from_args(&code_object, &scope, args, defaults)?;
|
||||
|
||||
// Construct frame:
|
||||
let mut frame = Frame::new(code.clone(), scope);
|
||||
let frame = self.ctx.new_frame(code.clone(), scope);
|
||||
|
||||
// If we have a generator, create a new generator
|
||||
if code_object.is_generator {
|
||||
objgenerator::new_generator(self, frame)
|
||||
} else {
|
||||
frame.run_frame_full(self)
|
||||
self.run_frame_full(frame)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user