mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Simple importing scheme working
This commit is contained in:
1 parent
8198c4afb7
commit
5187c2e974
8 files changed
+78
-17
No files matched your search
@@ -0,0 +1,10 @@
|
||||
|
||||
# TODO: implement standard library here
|
||||
|
||||
|
||||
def rgb_to_yiq(r, g, b):
|
||||
y = 0.30*r + 0.59*g + 0.11*b
|
||||
i = 0.74*(r-y) - 0.27*(b-y)
|
||||
q = 0.48*(r-y) + 0.41*(b-y)
|
||||
return (y, i, q)
|
||||
|
||||
@@ -90,6 +90,10 @@ pub enum Expression {
|
||||
op: Comparison,
|
||||
b: Box<Expression>,
|
||||
},
|
||||
Attribute {
|
||||
value: Box<Expression>,
|
||||
name: String,
|
||||
},
|
||||
Call {
|
||||
function: Box<Expression>,
|
||||
args: Vec<Expression>,
|
||||
|
||||
@@ -187,6 +187,7 @@ AtomExpr: ast::Expression = {
|
||||
<e:Atom> => e,
|
||||
<f:AtomExpr> "(" <a:FunctionArguments> ")" => ast::Expression::Call { function: Box::new(f), args: a },
|
||||
<e:AtomExpr> "[" <s:Subscript> "]" => ast::Expression::Binop { a: Box::new(e), op: ast::Operator::Subscript, b: Box::new(s) },
|
||||
<e:AtomExpr> "." <n:Identifier> => ast::Expression::Attribute { value: Box::new(e), name: n },
|
||||
};
|
||||
|
||||
Subscript: ast::Expression = {
|
||||
@@ -256,6 +257,7 @@ extern {
|
||||
"+" => lexer::Tok::Plus,
|
||||
"-" => lexer::Tok::Minus,
|
||||
":" => lexer::Tok::Colon,
|
||||
"." => lexer::Tok::Dot,
|
||||
"," => lexer::Tok::Comma,
|
||||
"*" => lexer::Tok::Star,
|
||||
"&" => lexer::Tok::Amper,
|
||||
|
||||
+6
-1
@@ -65,10 +65,15 @@ pub fn len(args: Vec<Rc<NativeType>>) -> NativeType {
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn fill_scope() {
|
||||
pub fn fill_scope() -> PyObjectRef {
|
||||
// scope[String::from("print")] = print;
|
||||
let obj = PyObject::new(PyObjectKind::Module);
|
||||
obj.borrow_mut().dict.insert(String::from("print"), PyObject::new(PyObjectKind::RustFunction { function: print }));
|
||||
obj
|
||||
}
|
||||
|
||||
fn any() {}
|
||||
|
||||
fn all() {}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ pub enum Instruction {
|
||||
LoadConst { value: Constant },
|
||||
UnaryOperation { op: UnaryOperator },
|
||||
BinaryOperation { op: BinaryOperator },
|
||||
LoadAttr { name: String },
|
||||
CompareOperation { op: ComparisonOperator },
|
||||
Pop,
|
||||
Rotate { amount: usize },
|
||||
|
||||
@@ -252,6 +252,10 @@ impl Compiler {
|
||||
let i = Instruction::UnaryOperation { op: i };
|
||||
self.emit(i);
|
||||
}
|
||||
ast::Expression::Attribute { value, name } => {
|
||||
self.compile_expression(*value);
|
||||
self.emit(Instruction::LoadAttr { name: name });
|
||||
}
|
||||
ast::Expression::Compare { a, op, b } => {
|
||||
self.compile_expression(*a);
|
||||
self.compile_expression(*b);
|
||||
|
||||
@@ -15,6 +15,10 @@ Basically reference counting, but then done by rust.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* Good reference: https://github.com/ProgVal/pythonvm-rust/blob/master/src/objects/mod.rs
|
||||
*/
|
||||
|
||||
/*
|
||||
The PyRef type implements
|
||||
https://doc.rust-lang.org/std/cell/index.html#introducing-mutability-inside-of-something-immutable
|
||||
@@ -72,6 +76,7 @@ pub enum PyObjectKind {
|
||||
Function {
|
||||
code: bytecode::CodeObject,
|
||||
},
|
||||
Module,
|
||||
None,
|
||||
Type,
|
||||
RustFunction {
|
||||
@@ -163,6 +168,10 @@ impl PyObject {
|
||||
pub fn into_ref(self) -> PyObjectRef {
|
||||
Rc::new(RefCell::new(self))
|
||||
}
|
||||
|
||||
pub fn new_int(i: i32) -> PyObjectRef {
|
||||
PyObject::new(PyObjectKind::Integer { value: i })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<&'a PyObject> for &'a PyObject {
|
||||
|
||||
+42
-16
@@ -1,6 +1,8 @@
|
||||
|
||||
/*
|
||||
* Implement virtual machine to run instructions.
|
||||
* See also:
|
||||
* https://github.com/ProgVal/pythonvm-rust/blob/master/src/processor/mod.rs
|
||||
*/
|
||||
|
||||
extern crate rustpython_parser;
|
||||
@@ -37,7 +39,6 @@ struct Frame {
|
||||
blocks: Vec<Block>, // Block frames, for controling loops and exceptions
|
||||
globals: HashMap<String, PyObjectRef>, // Variables
|
||||
locals: HashMap<String, PyObjectRef>, // Variables
|
||||
labels: HashMap<usize, usize>, // Maps label id to line number, just for speedup
|
||||
lasti: usize, // index of last instruction ran
|
||||
// cmp_op: Vec<&'a Fn(NativeType, NativeType) -> bool>, // TODO: change compare to a function list
|
||||
}
|
||||
@@ -49,7 +50,6 @@ pub struct VirtualMachine {
|
||||
impl Frame {
|
||||
pub fn new(code: Rc<bytecode::CodeObject>, callargs: HashMap<String, PyObjectRef>, globals: Option<HashMap<String, PyObjectRef>>) -> Frame {
|
||||
//populate the globals and locals
|
||||
let labels = HashMap::new();
|
||||
//TODO: This is wrong, check https://github.com/nedbat/byterun/blob/31e6c4a8212c35b5157919abff43a7daa0f377c6/byterun/pyvm2.py#L95
|
||||
let globals = match globals {
|
||||
Some(g) => g,
|
||||
@@ -69,7 +69,6 @@ impl Frame {
|
||||
// save the callargs as locals
|
||||
globals: locals.clone(),
|
||||
locals: locals,
|
||||
labels: labels,
|
||||
lasti: 0,
|
||||
}
|
||||
}
|
||||
@@ -109,8 +108,8 @@ impl VirtualMachine {
|
||||
self.frames.last_mut().unwrap()
|
||||
}
|
||||
|
||||
fn pop_frame(&mut self) {
|
||||
self.frames.pop().unwrap();
|
||||
fn pop_frame(&mut self) -> Frame {
|
||||
self.frames.pop().unwrap()
|
||||
}
|
||||
|
||||
fn push_value(&mut self, obj: PyObjectRef) {
|
||||
@@ -125,14 +124,17 @@ impl VirtualMachine {
|
||||
self.current_frame().pop_multiple(count)
|
||||
}
|
||||
|
||||
fn store_name(&mut self, name: String, obj: PyObjectRef) {
|
||||
self.current_frame().locals.insert(name, obj);
|
||||
}
|
||||
|
||||
fn run(&mut self, code: Rc<bytecode::CodeObject>) -> Result<PyObjectRef, PyObjectRef> {
|
||||
let frame = Frame::new(code, HashMap::new(), None);
|
||||
self.run_frame(frame)
|
||||
self.run_frame(frame).0
|
||||
}
|
||||
|
||||
// The Option<i32> 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, mut frame: Frame) -> Result<PyObjectRef, PyObjectRef> {
|
||||
fn run_frame(&mut self, mut frame: Frame) -> (Result<PyObjectRef, PyObjectRef>, Frame) {
|
||||
self.frames.push(frame);
|
||||
|
||||
// Execute until return or exception:
|
||||
@@ -155,9 +157,12 @@ impl VirtualMachine {
|
||||
//}
|
||||
};
|
||||
|
||||
self.pop_frame();
|
||||
value
|
||||
let frame2 = self.pop_frame();
|
||||
(value, frame2)
|
||||
}
|
||||
/*
|
||||
fn run_code(&mut self, code: i32) -> Result<PyCodeObject, PyCodeObject> {
|
||||
}*/
|
||||
|
||||
fn subscript(&mut self, a: &PyObject, b: &PyObject) -> PyObjectRef {
|
||||
// debug!("tos: {:?}, tos1: {:?}", tos, tos1);
|
||||
@@ -274,7 +279,7 @@ impl VirtualMachine {
|
||||
}
|
||||
PyObjectKind::Function { ref code } => {
|
||||
let frame = Frame::new(Rc::new(code.clone()), HashMap::new(), None);
|
||||
self.run_frame(frame)
|
||||
self.run_frame(frame).0
|
||||
}
|
||||
_ => {
|
||||
println!("Not impl {:?}", f);
|
||||
@@ -293,9 +298,19 @@ impl VirtualMachine {
|
||||
debug!("Got ast: {:?}", program);
|
||||
let bytecode = compile(program);
|
||||
debug!("Code object: {:?}", bytecode);
|
||||
let obj = PyObject::new(PyObjectKind::Code { code: bytecode });
|
||||
// TODO: execute in global object namespace
|
||||
// vm.evaluate(bytecode);
|
||||
// let obj = PyObject::new(PyObjectKind::Code { code: bytecode });
|
||||
let obj = PyObject::new(PyObjectKind::Module);
|
||||
|
||||
// As a sort of hack, create a frame and run code in it
|
||||
let frame = Frame::new(Rc::new(bytecode), HashMap::new(), None);
|
||||
let frame2 = self.run_frame(frame).1;
|
||||
|
||||
// TODO: we might find a better solution than this:
|
||||
for (name, member_obj) in frame2.locals.iter() {
|
||||
obj.borrow_mut().dict.insert(name.to_string(), member_obj.clone());
|
||||
}
|
||||
|
||||
// Push module on stack:
|
||||
self.push_value(obj);
|
||||
None
|
||||
},
|
||||
@@ -305,6 +320,13 @@ impl VirtualMachine {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_attr(&mut self, name: String) {
|
||||
let parent = self.pop_value();
|
||||
// Lookup name in obj
|
||||
let obj = parent.borrow().dict[&name].clone();
|
||||
self.push_value(obj);
|
||||
}
|
||||
|
||||
// Execute a single instruction:
|
||||
fn execute_instruction(&mut self) -> Option<Result<PyObjectRef, PyObjectRef>> {
|
||||
// let frame = self.frames.last_mut().unwrap();
|
||||
@@ -325,7 +347,7 @@ impl VirtualMachine {
|
||||
match &instruction {
|
||||
&bytecode::Instruction::LoadConst { ref value } => {
|
||||
let obj = match value {
|
||||
&bytecode::Constant::Integer { ref value } => { PyObject::new(PyObjectKind::Integer { value: *value }) },
|
||||
&bytecode::Constant::Integer { ref value } => PyObject::new_int(*value),
|
||||
// &bytecode::Constant::Float
|
||||
&bytecode::Constant::String { ref value } => { PyObject::new(PyObjectKind::String { value: value.clone() }) },
|
||||
&bytecode::Constant::Code { ref code } => { PyObject::new(PyObjectKind::Code { code: code.clone() }) },
|
||||
@@ -352,7 +374,7 @@ impl VirtualMachine {
|
||||
&bytecode::Instruction::StoreName { ref name } => {
|
||||
// take top of stack and assign in scope:
|
||||
let obj = self.pop_value();
|
||||
self.current_frame().locals.insert(name.clone(), obj);
|
||||
self.store_name(name.clone(), obj);
|
||||
None
|
||||
},
|
||||
&bytecode::Instruction::Pop => {
|
||||
@@ -409,6 +431,10 @@ impl VirtualMachine {
|
||||
self.execute_binop(op);
|
||||
None
|
||||
},
|
||||
&bytecode::Instruction::LoadAttr { ref name } => {
|
||||
self.load_attr(name.to_string());
|
||||
None
|
||||
},
|
||||
&bytecode::Instruction::UnaryOperation { ref op } => {
|
||||
self.execute_unop(op);
|
||||
None
|
||||
|
||||
Reference in new issue
Block a user