mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 11:14:38 +08:00
12 files changed
+149
-62
No files matched your search
Generated
+2
@@ -1,3 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.6.4"
|
||||
|
||||
+4
-4
@@ -68,7 +68,7 @@ fn main() {
|
||||
handle_exception(&mut vm, result);
|
||||
}
|
||||
|
||||
fn _run_string(vm: &mut VirtualMachine, source: &str, source_path: Option<String>) -> PyResult {
|
||||
fn _run_string(vm: &mut VirtualMachine, source: &str, source_path: String) -> PyResult {
|
||||
let code_obj = compile::compile(vm, source, &compile::Mode::Exec, source_path)?;
|
||||
// trace!("Code object: {:?}", code_obj.borrow());
|
||||
let builtins = vm.get_builtin_scope();
|
||||
@@ -91,7 +91,7 @@ fn run_command(vm: &mut VirtualMachine, mut source: String) -> PyResult {
|
||||
|
||||
// This works around https://github.com/RustPython/RustPython/issues/17
|
||||
source.push_str("\n");
|
||||
_run_string(vm, &source, None)
|
||||
_run_string(vm, &source, "<stdin>".to_string())
|
||||
}
|
||||
|
||||
fn run_module(vm: &mut VirtualMachine, module: &str) -> PyResult {
|
||||
@@ -105,7 +105,7 @@ fn run_script(vm: &mut VirtualMachine, script_file: &str) -> PyResult {
|
||||
// Parse an ast from it:
|
||||
let filepath = Path::new(script_file);
|
||||
match parser::read_file(filepath) {
|
||||
Ok(source) => _run_string(vm, &source, Some(filepath.to_str().unwrap().to_string())),
|
||||
Ok(source) => _run_string(vm, &source, filepath.to_str().unwrap().to_string()),
|
||||
Err(msg) => {
|
||||
error!("Parsing went horribly wrong: {}", msg);
|
||||
std::process::exit(1);
|
||||
@@ -114,7 +114,7 @@ fn run_script(vm: &mut VirtualMachine, script_file: &str) -> PyResult {
|
||||
}
|
||||
|
||||
fn shell_exec(vm: &mut VirtualMachine, source: &str, scope: PyObjectRef) -> bool {
|
||||
match compile::compile(vm, source, &compile::Mode::Single, None) {
|
||||
match compile::compile(vm, source, &compile::Mode::Single, "<stdin>".to_string()) {
|
||||
Ok(code) => {
|
||||
match vm.run_code_obj(code, scope) {
|
||||
Ok(_value) => {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
c1 = compile("1 + 1", "", 'eval')
|
||||
|
||||
code_class = type(c1)
|
||||
|
||||
def f(x, y, *args, power=1, **kwargs):
|
||||
assert code_class == type(c1)
|
||||
z = x * y
|
||||
return z ** power
|
||||
|
||||
c2 = f.__code__
|
||||
# print(c2)
|
||||
assert type(c2) == code_class
|
||||
print(dir(c2))
|
||||
assert c2.co_argcount == 2
|
||||
# assert c2.co_cellvars == ()
|
||||
# assert isinstance(c2.co_code, bytes)
|
||||
# assert c2.co_consts == (None,)
|
||||
assert "code.py" in c2.co_filename
|
||||
assert c2.co_firstlineno == 5, str(c2.co_firstlineno)
|
||||
# assert isinstance(c2.co_flags, int) # 'OPTIMIZED, NEWLOCALS, NOFREE'
|
||||
# assert c2.co_freevars == (), str(c2.co_freevars)
|
||||
assert c2.co_kwonlyargcount == 1, (c2.co_kwonlyargcount)
|
||||
# assert c2.co_lnotab == 0, c2.co_lnotab # b'\x00\x01' # Line number table
|
||||
assert c2.co_name == 'f', c2.co_name
|
||||
# assert c2.co_names == ('code_class', 'type', 'c1', 'AssertionError'), c2.co_names # , c2.co_names
|
||||
# assert c2.co_nlocals == 4, c2.co_nlocals #
|
||||
# assert c2.co_stacksize == 2, 'co_stacksize',
|
||||
# assert c2.co_varnames == ('x', 'y', 'power', 'z'), c2.co_varnames
|
||||
+3
-3
@@ -150,7 +150,7 @@ fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let filename = objstr::get_value(filename);
|
||||
|
||||
compile::compile(vm, &source, &mode, Some(filename))
|
||||
compile::compile(vm, &source, &mode, filename)
|
||||
}
|
||||
|
||||
fn builtin_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -200,7 +200,7 @@ fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let source = objstr::get_value(source);
|
||||
// TODO: fix this newline bug:
|
||||
let source = format!("{}\n", source);
|
||||
compile::compile(vm, &source, &mode, None)?
|
||||
compile::compile(vm, &source, &mode, "<string>".to_string())?
|
||||
} else {
|
||||
return Err(vm.new_type_error("code argument must be str or code object".to_string()));
|
||||
};
|
||||
@@ -246,7 +246,7 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let source = objstr::get_value(source);
|
||||
// TODO: fix this newline bug:
|
||||
let source = format!("{}\n", source);
|
||||
compile::compile(vm, &source, &mode, None)?
|
||||
compile::compile(vm, &source, &mode, "<string>".to_string())?
|
||||
} else if objtype::isinstance(source, &vm.ctx.code_type()) {
|
||||
source.clone()
|
||||
} else {
|
||||
|
||||
+5
-2
@@ -22,7 +22,8 @@ pub struct CodeObject {
|
||||
pub varargs: Option<Option<String>>, // *args or *
|
||||
pub kwonlyarg_names: Vec<String>,
|
||||
pub varkeywords: Option<Option<String>>, // **kwargs or **
|
||||
pub source_path: Option<String>,
|
||||
pub source_path: String,
|
||||
pub first_line_number: usize,
|
||||
pub obj_name: String, // Name of the object that created this code object
|
||||
pub is_generator: bool,
|
||||
}
|
||||
@@ -33,7 +34,8 @@ impl CodeObject {
|
||||
varargs: Option<Option<String>>,
|
||||
kwonlyarg_names: Vec<String>,
|
||||
varkeywords: Option<Option<String>>,
|
||||
source_path: Option<String>,
|
||||
source_path: String,
|
||||
first_line_number: usize,
|
||||
obj_name: String,
|
||||
) -> CodeObject {
|
||||
CodeObject {
|
||||
@@ -45,6 +47,7 @@ impl CodeObject {
|
||||
kwonlyarg_names,
|
||||
varkeywords,
|
||||
source_path,
|
||||
first_line_number,
|
||||
obj_name,
|
||||
is_generator: false,
|
||||
}
|
||||
|
||||
+19
-7
@@ -24,10 +24,10 @@ pub fn compile(
|
||||
vm: &mut VirtualMachine,
|
||||
source: &str,
|
||||
mode: &Mode,
|
||||
source_path: Option<String>,
|
||||
source_path: String,
|
||||
) -> PyResult {
|
||||
let mut compiler = Compiler::new();
|
||||
compiler.source_path = source_path.clone();
|
||||
compiler.source_path = Some(source_path.clone());
|
||||
compiler.push_new_code_object(source_path, "<module>".to_string());
|
||||
let syntax_error = vm.context().exceptions.syntax_error.clone();
|
||||
let result = match mode {
|
||||
@@ -78,13 +78,15 @@ impl Compiler {
|
||||
}
|
||||
}
|
||||
|
||||
fn push_new_code_object(&mut self, source_path: Option<String>, obj_name: String) {
|
||||
fn push_new_code_object(&mut self, source_path: String, obj_name: String) {
|
||||
let line_number = self.get_source_line_number();
|
||||
self.code_object_stack.push(CodeObject::new(
|
||||
Vec::new(),
|
||||
None,
|
||||
Vec::new(),
|
||||
None,
|
||||
source_path.clone(),
|
||||
line_number,
|
||||
obj_name,
|
||||
));
|
||||
}
|
||||
@@ -453,12 +455,14 @@ impl Compiler {
|
||||
} => {
|
||||
self.prepare_decorators(decorator_list)?;
|
||||
self.emit(Instruction::LoadBuildClass);
|
||||
let line_number = self.get_source_line_number();
|
||||
self.code_object_stack.push(CodeObject::new(
|
||||
vec![String::from("__locals__")],
|
||||
None,
|
||||
vec![],
|
||||
None,
|
||||
self.source_path.clone(),
|
||||
self.source_path.clone().unwrap(),
|
||||
line_number,
|
||||
name.clone(),
|
||||
));
|
||||
self.emit(Instruction::LoadName {
|
||||
@@ -653,12 +657,14 @@ impl Compiler {
|
||||
});
|
||||
}
|
||||
|
||||
let line_number = self.get_source_line_number();
|
||||
self.code_object_stack.push(CodeObject::new(
|
||||
args.args.clone(),
|
||||
args.vararg.clone(),
|
||||
args.kwonlyargs.clone(),
|
||||
args.kwarg.clone(),
|
||||
self.source_path.clone(),
|
||||
self.source_path.clone().unwrap(),
|
||||
line_number,
|
||||
name.to_string(),
|
||||
));
|
||||
|
||||
@@ -1162,13 +1168,15 @@ impl Compiler {
|
||||
}
|
||||
.to_string();
|
||||
|
||||
let line_number = self.get_source_line_number();
|
||||
// Create magnificent function <listcomp>:
|
||||
self.code_object_stack.push(CodeObject::new(
|
||||
vec![".0".to_string()],
|
||||
None,
|
||||
vec![],
|
||||
None,
|
||||
self.source_path.clone(),
|
||||
self.source_path.clone().unwrap(),
|
||||
line_number,
|
||||
name.clone(),
|
||||
));
|
||||
|
||||
@@ -1338,6 +1346,10 @@ impl Compiler {
|
||||
self.current_source_location = location.clone();
|
||||
}
|
||||
|
||||
fn get_source_line_number(&mut self) -> usize {
|
||||
self.current_source_location.get_row()
|
||||
}
|
||||
|
||||
fn mark_generator(&mut self) {
|
||||
self.current_code_object().is_generator = true;
|
||||
}
|
||||
@@ -1352,7 +1364,7 @@ mod tests {
|
||||
use rustpython_parser::parser;
|
||||
fn compile_exec(source: &str) -> CodeObject {
|
||||
let mut compiler = Compiler::new();
|
||||
compiler.push_new_code_object(Option::None, "<module>".to_string());
|
||||
compiler.push_new_code_object("source_path".to_string(), "<module>".to_string());
|
||||
let ast = parser::parse_program(&source.to_string()).unwrap();
|
||||
compiler.compile_program(&ast).unwrap();
|
||||
compiler.pop_code_object()
|
||||
|
||||
+8
-3
@@ -4,8 +4,13 @@ use super::compile;
|
||||
use super::pyobject::{PyObjectRef, PyResult};
|
||||
use super::vm::VirtualMachine;
|
||||
|
||||
pub fn eval(vm: &mut VirtualMachine, source: &str, scope: PyObjectRef) -> PyResult {
|
||||
match compile::compile(vm, source, &compile::Mode::Eval, None) {
|
||||
pub fn eval(
|
||||
vm: &mut VirtualMachine,
|
||||
source: &str,
|
||||
scope: PyObjectRef,
|
||||
source_path: &str,
|
||||
) -> PyResult {
|
||||
match compile::compile(vm, source, &compile::Mode::Eval, source_path.to_string()) {
|
||||
Ok(bytecode) => {
|
||||
debug!("Code object: {:?}", bytecode);
|
||||
vm.run_code_obj(bytecode, scope)
|
||||
@@ -24,7 +29,7 @@ mod tests {
|
||||
let source = String::from("print('Hello world')\n");
|
||||
let mut vm = VirtualMachine::new();
|
||||
let vars = vm.context().new_scope(None);
|
||||
let _result = eval(&mut vm, &source, vars);
|
||||
let _result = eval(&mut vm, &source, vars, "<unittest>");
|
||||
|
||||
// TODO: check result?
|
||||
//assert_eq!(
|
||||
|
||||
+10
-20
@@ -70,7 +70,7 @@ impl Frame {
|
||||
// locals.extend(callargs);
|
||||
|
||||
Frame {
|
||||
code: objcode::copy_code(&code),
|
||||
code: objcode::get_value(&code),
|
||||
stack: vec![],
|
||||
blocks: vec![],
|
||||
// save the callargs as locals
|
||||
@@ -88,11 +88,7 @@ impl Frame {
|
||||
}
|
||||
|
||||
pub fn run_frame(&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 filename = &self.code.source_path.to_string();
|
||||
|
||||
let prev_frame = mem::replace(&mut vm.current_frame, Some(vm.ctx.new_frame(self.clone())));
|
||||
|
||||
@@ -661,13 +657,10 @@ impl Frame {
|
||||
module: &str,
|
||||
symbol: &Option<String>,
|
||||
) -> FrameResult {
|
||||
let current_path = match &self.code.source_path {
|
||||
Some(source_path) => {
|
||||
let mut source_pathbuf = PathBuf::from(source_path);
|
||||
source_pathbuf.pop();
|
||||
source_pathbuf
|
||||
}
|
||||
None => PathBuf::from("."),
|
||||
let current_path = {
|
||||
let mut source_pathbuf = PathBuf::from(&self.code.source_path);
|
||||
source_pathbuf.pop();
|
||||
source_pathbuf
|
||||
};
|
||||
|
||||
let obj = import(vm, current_path, module, symbol)?;
|
||||
@@ -678,13 +671,10 @@ impl Frame {
|
||||
}
|
||||
|
||||
fn import_star(&mut self, vm: &mut VirtualMachine, module: &str) -> FrameResult {
|
||||
let current_path = match &self.code.source_path {
|
||||
Some(source_path) => {
|
||||
let mut source_pathbuf = PathBuf::from(source_path);
|
||||
source_pathbuf.pop();
|
||||
source_pathbuf
|
||||
}
|
||||
None => PathBuf::from("."),
|
||||
let current_path = {
|
||||
let mut source_pathbuf = PathBuf::from(&self.code.source_path);
|
||||
source_pathbuf.pop();
|
||||
source_pathbuf
|
||||
};
|
||||
|
||||
// Grab all the names from the module and put them in the context
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ fn import_uncached_module(
|
||||
vm,
|
||||
&source,
|
||||
&compile::Mode::Exec,
|
||||
Some(filepath.to_str().unwrap().to_string()),
|
||||
filepath.to_str().unwrap().to_string(),
|
||||
)?;
|
||||
// trace!("Code object: {:?}", code_obj);
|
||||
|
||||
|
||||
+66
-19
@@ -4,7 +4,7 @@
|
||||
|
||||
use super::super::bytecode;
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
@@ -13,15 +13,26 @@ pub fn init(context: &PyContext) {
|
||||
let code_type = &context.code_type;
|
||||
context.set_attr(code_type, "__new__", context.new_rustfunc(code_new));
|
||||
context.set_attr(code_type, "__repr__", context.new_rustfunc(code_repr));
|
||||
|
||||
for (name, f) in vec![
|
||||
(
|
||||
"co_argcount",
|
||||
code_co_argcount as fn(&mut VirtualMachine, PyFuncArgs) -> PyResult,
|
||||
),
|
||||
("co_filename", code_co_filename),
|
||||
("co_firstlineno", code_co_firstlineno),
|
||||
("co_kwonlyargcount", code_co_kwonlyargcount),
|
||||
("co_name", code_co_name),
|
||||
] {
|
||||
context.set_attr(code_type, name, context.new_member_descriptor(f))
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract rust bytecode object from a python code object.
|
||||
pub fn copy_code(code_obj: &PyObjectRef) -> bytecode::CodeObject {
|
||||
let code_obj = code_obj.borrow();
|
||||
if let PyObjectPayload::Code { ref code } = code_obj.payload {
|
||||
pub fn get_value(obj: &PyObjectRef) -> bytecode::CodeObject {
|
||||
if let PyObjectPayload::Code { code } = &obj.borrow().payload {
|
||||
code.clone()
|
||||
} else {
|
||||
panic!("Must be code obj");
|
||||
panic!("Inner error getting code {:?}", obj)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,18 +44,54 @@ fn code_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
fn code_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(o, Some(vm.ctx.code_type()))]);
|
||||
|
||||
// Fetch actual code:
|
||||
let code = copy_code(o);
|
||||
|
||||
let file = if let Some(source_path) = code.source_path {
|
||||
format!(", file {}", source_path)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
// TODO: fetch proper line info from code object
|
||||
let line = ", line 1".to_string();
|
||||
|
||||
let repr = format!("<code object at .. {}{}>", file, line);
|
||||
let code = get_value(o);
|
||||
let repr = format!(
|
||||
"<code object {} at 0x{:x} file {:?}, line {}>",
|
||||
code.obj_name,
|
||||
o.get_id(),
|
||||
code.source_path,
|
||||
code.first_line_number
|
||||
);
|
||||
Ok(vm.new_str(repr))
|
||||
}
|
||||
|
||||
fn member_code_obj(
|
||||
vm: &mut VirtualMachine,
|
||||
args: PyFuncArgs,
|
||||
) -> Result<bytecode::CodeObject, PyObjectRef> {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [
|
||||
(zelf, Some(vm.ctx.code_type())),
|
||||
(_cls, Some(vm.ctx.type_type()))
|
||||
]
|
||||
);
|
||||
Ok(get_value(zelf))
|
||||
}
|
||||
|
||||
fn code_co_argcount(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let code_obj = member_code_obj(vm, args)?;
|
||||
Ok(vm.ctx.new_int(code_obj.arg_names.len()))
|
||||
}
|
||||
|
||||
fn code_co_filename(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let code_obj = member_code_obj(vm, args)?;
|
||||
let source_path = code_obj.source_path;
|
||||
Ok(vm.new_str(source_path))
|
||||
}
|
||||
|
||||
fn code_co_firstlineno(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let code_obj = member_code_obj(vm, args)?;
|
||||
Ok(vm.ctx.new_int(code_obj.first_line_number))
|
||||
}
|
||||
|
||||
fn code_co_kwonlyargcount(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let code_obj = member_code_obj(vm, args)?;
|
||||
Ok(vm.ctx.new_int(code_obj.kwonlyarg_names.len()))
|
||||
}
|
||||
|
||||
fn code_co_name(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let code_obj = member_code_obj(vm, args)?;
|
||||
Ok(vm.new_str(code_obj.obj_name))
|
||||
}
|
||||
+2
-2
@@ -11,7 +11,7 @@ use std::collections::hash_map::HashMap;
|
||||
use super::builtins;
|
||||
use super::bytecode;
|
||||
use super::frame::Frame;
|
||||
use super::obj::objcode::copy_code;
|
||||
use super::obj::objcode;
|
||||
use super::obj::objgenerator;
|
||||
use super::obj::objiter;
|
||||
use super::obj::objsequence;
|
||||
@@ -282,7 +282,7 @@ impl VirtualMachine {
|
||||
defaults: &PyObjectRef,
|
||||
args: PyFuncArgs,
|
||||
) -> PyResult {
|
||||
let code_object = copy_code(code);
|
||||
let code_object = objcode::get_value(code);
|
||||
let scope = self.ctx.new_scope(Some(scope.clone()));
|
||||
self.fill_scope_from_args(&code_object, &scope, args, defaults)?;
|
||||
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ fn eval(vm: &mut VirtualMachine, source: &str, vars: PyObjectRef) -> PyResult {
|
||||
source.push('\n');
|
||||
}
|
||||
|
||||
let code_obj = compile::compile(vm, &source, &compile::Mode::Exec, None)?;
|
||||
let code_obj = compile::compile(vm, &source, &compile::Mode::Exec, "<string>".to_string())?;
|
||||
|
||||
vm.run_code_obj(code_obj, vars)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user