GetAttr: module/instance attr, or bind builtin method as BoundMethod. */
(recv_h: u32, name: &str)
| 70 | |
| 71 | /* GetAttr: module/instance attr, or bind builtin method as BoundMethod. */ |
| 72 | fn dispatch_get_attr(recv_h: u32, name: &str) -> Result<Val, VmErr> { |
| 73 | with_recv("edge_op get_attr: invalid receiver handle", recv_h, |vm, recv| { |
| 74 | // Module attribute. |
| 75 | if recv.is_heap() && let HeapObj::Module(_, attrs) = vm.heap.get(recv) |
| 76 | { |
| 77 | let bare = name; |
| 78 | if let Some((_, v)) = attrs.iter().find(|(n, _)| n == bare) { |
| 79 | return Ok(*v); |
| 80 | } |
| 81 | return Err(VmErr::Attribute(s!("module has no attribute '", str name, "'"))); |
| 82 | } |
| 83 | // Instance attribute. |
| 84 | if recv.is_heap() && let HeapObj::Instance(_cls, attrs) = vm.heap.get(recv) |
| 85 | { |
| 86 | let entries = attrs.borrow().entries.clone(); |
| 87 | for (k, v) in &entries { |
| 88 | if k.is_heap() |
| 89 | && let HeapObj::Str(s) = vm.heap.get(*k) |
| 90 | && s == name |
| 91 | { |
| 92 | return Ok(*v); |
| 93 | } |
| 94 | } |
| 95 | return Err(VmErr::Attribute(s!("instance has no attribute '", str name, "'"))); |
| 96 | } |
| 97 | // Builtin method -> BoundMethod. |
| 98 | let ty = vm.type_name(recv); |
| 99 | if let Some(mid) = lookup_method(ty, name) { |
| 100 | return vm.heap.alloc(HeapObj::BoundMethod(recv, mid)); |
| 101 | } |
| 102 | Err(VmErr::Attribute(s!("'", str ty, "' object has no attribute '", str name, "'"))) |
| 103 | }) |
| 104 | } |
| 105 | |
| 106 | /* SetAttr: writes to instance `__dict__`; rejects modules and builtins. */ |
| 107 | fn dispatch_set_attr(recv_h: u32, name: &str, args: &[Val]) -> Result<Val, VmErr> { |
no test coverage detected