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