Skip to content

Commit 4b52f72

Browse files
committed
load_attr to use class based attribute getting.
1 parent 0597cff commit 4b52f72

5 files changed

Lines changed: 84 additions & 18 deletions

File tree

tests/snippets/class.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
class Foo:
2-
print("Defining class")
3-
def __init__(self):
4-
print("initing: ", self)
5-
self.x = 5
2+
def __init__(self, x):
3+
self.x = x
4+
5+
def square(self):
6+
return self.x * self.x
67

78
y = 7
89

9-
print("Done defining: ", Foo)
10-
print("Init: ", Foo.__init__)
11-
print("y = ", Foo.y)
12-
foo = Foo()
13-
print("Done initting: ", foo)
14-
print("Foo's x: ", foo.x)
10+
foo = Foo(5)
11+
12+
assert foo.y == Foo.y
13+
assert foo.x == 5
14+
assert foo.square() == 25

vm/src/objclass.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::pyobject::AttributeProtocol;
2-
use super::pyobject::{PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol};
2+
use super::pyobject::{PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
33
use super::vm::VirtualMachine;
44

55
pub fn get_attribute(
@@ -17,13 +17,16 @@ pub fn get_attribute(
1717
vm.invoke(
1818
attr_class.get_attr(&String::from("__get__")),
1919
PyFuncArgs {
20-
args: vec![attr, cls],
20+
args: vec![attr, obj, cls],
2121
},
2222
)
2323
} else {
2424
Ok(attr)
2525
}
2626
} else {
27-
Err(vm.new_exception(String::from("TypeError goes here!")))
27+
Err(vm.new_exception(format!(
28+
"AttributeError: {:?} object has no attribute {}",
29+
cls, name
30+
)))
2831
}
2932
}

vm/src/objfunction.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::pyobject::{PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, TypeProtocol};
1+
use super::pyobject::{PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult};
22
use super::vm::VirtualMachine;
33
use std::collections::HashMap;
44

@@ -23,6 +23,18 @@ pub fn create_type(type_type: PyObjectRef) -> PyObjectRef {
2323
typ
2424
}
2525

26+
pub fn create_bound_method_type(type_type: PyObjectRef) -> PyObjectRef {
27+
let dict = HashMap::new();
28+
let typ = PyObject::new(
29+
PyObjectKind::Class {
30+
name: "method".to_string(),
31+
dict: PyObject::new(PyObjectKind::Dict { elements: dict }, type_type.clone()),
32+
},
33+
type_type.clone(),
34+
);
35+
typ
36+
}
37+
2638
fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
27-
unimplemented!("not yet!");
39+
Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone()))
2840
}

vm/src/pyobject.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub struct PyContext {
4747
pub tuple_type: PyObjectRef,
4848
pub dict_type: PyObjectRef,
4949
pub function_type: PyObjectRef,
50+
pub bound_method_type: PyObjectRef,
5051
}
5152

5253
/*
@@ -70,6 +71,7 @@ impl PyContext {
7071
tuple_type: type_type.clone(),
7172
dict_type: type_type.clone(),
7273
function_type: objfunction::create_type(type_type.clone()),
74+
bound_method_type: objfunction::create_bound_method_type(type_type.clone()),
7375
type_type: type_type,
7476
}
7577
}
@@ -162,6 +164,16 @@ impl PyContext {
162164
)
163165
}
164166

167+
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
168+
PyObject::new(
169+
PyObjectKind::BoundMethod {
170+
function: function,
171+
object: object,
172+
},
173+
self.bound_method_type.clone(),
174+
)
175+
}
176+
165177
/* TODO: something like this?
166178
pub fn new_instance(&self, name: String) -> PyObjectRef {
167179
PyObject::new(PyObjectKind::Class { name: name }, self.type_type.clone())
@@ -370,6 +382,10 @@ pub enum PyObjectKind {
370382
code: PyObjectRef,
371383
scope: PyObjectRef,
372384
},
385+
BoundMethod {
386+
function: PyObjectRef,
387+
object: PyObjectRef,
388+
},
373389
Scope {
374390
scope: Scope,
375391
},
@@ -412,6 +428,10 @@ impl fmt::Debug for PyObjectKind {
412428
&PyObjectKind::NameError { name: _ } => write!(f, "NameError"),
413429
&PyObjectKind::Code { ref code } => write!(f, "code: {:?}", code),
414430
&PyObjectKind::Function { code: _, scope: _ } => write!(f, "function"),
431+
&PyObjectKind::BoundMethod {
432+
function: _,
433+
object: _,
434+
} => write!(f, "bound-method"),
415435
&PyObjectKind::Module { name: _, dict: _ } => write!(f, "module"),
416436
&PyObjectKind::Scope { scope: _ } => write!(f, "scope"),
417437
&PyObjectKind::None => write!(f, "None"),
@@ -482,6 +502,7 @@ impl PyObject {
482502
PyObjectKind::Instance { dict: _ } => format!("<instance>"),
483503
PyObjectKind::Code { code: _ } => format!("<code>"),
484504
PyObjectKind::Function { code: _, scope: _ } => format!("<func>"),
505+
PyObjectKind::BoundMethod { .. } => format!("<bound-method>"),
485506
PyObjectKind::RustFunction { function: _ } => format!("<rustfunc>"),
486507
PyObjectKind::Module { ref name, dict: _ } => format!("<module '{}'>", name),
487508
PyObjectKind::Scope { ref scope } => format!("<scope '{:?}'>", scope),

vm/src/vm.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use super::builtins;
1212
use super::bytecode;
1313
use super::frame::{copy_code, Block, Frame};
1414
use super::import::import;
15+
use super::objclass;
1516
use super::objlist;
1617
use super::objstr;
1718
use super::objtype;
@@ -68,6 +69,10 @@ impl VirtualMachine {
6869
self.ctx.new_bool(false)
6970
}
7071

72+
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
73+
self.ctx.new_bound_method(function, object)
74+
}
75+
7176
pub fn get_type(&self) -> PyObjectRef {
7277
self.ctx.type_type.clone()
7378
}
@@ -490,6 +495,16 @@ impl VirtualMachine {
490495
self.run_frame(frame)
491496
}
492497
PyObjectKind::Class { name: _, dict: _ } => self.new_instance(func_ref.clone(), args),
498+
PyObjectKind::BoundMethod {
499+
ref function,
500+
ref object,
501+
} => {
502+
let mut self_args = PyFuncArgs {
503+
args: args.args.clone(),
504+
};
505+
self_args.args.insert(0, object.clone());
506+
self.invoke(function.clone(), self_args)
507+
}
493508
ref kind => {
494509
unimplemented!("invoke unimplemented for: {:?}", kind);
495510
}
@@ -507,11 +522,26 @@ impl VirtualMachine {
507522
None
508523
}
509524

525+
fn get_attribute(&mut self, obj: PyObjectRef, attr_name: &String) -> PyResult {
526+
let typ = obj.typ();
527+
let typ_ref = typ.borrow();
528+
match typ_ref.kind {
529+
PyObjectKind::Class { .. } => {
530+
objclass::get_attribute(self, typ.clone(), obj.clone(), attr_name)
531+
}
532+
_ => panic!("It's not a class: {:?}", typ),
533+
}
534+
}
535+
510536
fn load_attr(&mut self, attr_name: &String) -> Option<PyResult> {
511537
let parent = self.pop_value();
512-
let obj = parent.get_attr(attr_name);
513-
self.push_value(obj);
514-
None
538+
match self.get_attribute(parent, attr_name) {
539+
Ok(obj) => {
540+
self.push_value(obj);
541+
None
542+
}
543+
Err(err) => Some(Err(err)),
544+
}
515545
}
516546

517547
fn store_attr(&mut self, attr_name: &String) -> Option<PyResult> {

0 commit comments

Comments
 (0)