(&mut self, op: u16, chunk: &SSAChunk, slots: &mut [Val])
| 939 | |
| 940 | #[inline(never)] |
| 941 | fn exec_store_attr(&mut self, op: u16, chunk: &SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> { |
| 942 | let value = self.pop()?; |
| 943 | let obj = self.pop()?; |
| 944 | if !obj.is_heap() { return Err(cold_type("cannot set attribute")); } |
| 945 | let name = chunk.names.get(op as usize).ok_or(cold_runtime("StoreAttr: bad name index"))?.clone(); |
| 946 | if let HeapObj::Instance(cls_val, _) = self.heap.get(obj) { |
| 947 | let cls_val = *cls_val; |
| 948 | if let Some((member, _)) = self.lookup_class_member(cls_val, ssa_strip(&name)) |
| 949 | && member.is_heap() |
| 950 | && let HeapObj::Property(_, setter) = self.heap.get(member) { |
| 951 | let setter = *setter; |
| 952 | if setter.is_none() { |
| 953 | return Err(VmErr::Attribute(s!("can't set attribute '", str ssa_strip(&name), "'"))); |
| 954 | } |
| 955 | if self.depth >= self.max_calls { return Err(cold_depth()); } |
| 956 | self.push(setter); |
| 957 | self.push(obj); |
| 958 | self.push(value); |
| 959 | self.exec_call(2, chunk, slots)?; |
| 960 | self.pop()?; |
| 961 | return Ok(()); |
| 962 | } |
| 963 | } |
| 964 | // Class attribute: insert or replace in the mutable members store. |
| 965 | if let HeapObj::Class(_, _, members) = self.heap.get(obj) { |
| 966 | let bare = ssa_strip(&name).to_string(); |
| 967 | let mut m = members.borrow_mut(); |
| 968 | match m.iter_mut().find(|(n, _)| *n == bare) { |
| 969 | Some(slot) => slot.1 = value, |
| 970 | None => m.push((bare, value)), |
| 971 | } |
| 972 | return Ok(()); |
| 973 | } |
| 974 | let key = self.heap.alloc(HeapObj::Str(name))?; |
| 975 | match self.heap.get(obj) { |
| 976 | HeapObj::Instance(_, attrs) => { |
| 977 | attrs.borrow_mut().insert(key, value, &self.heap); |
| 978 | } |
| 979 | _ => return Err(cold_type("cannot set attribute on this type")), |
| 980 | } |
| 981 | Ok(()) |
| 982 | } |
| 983 | |
| 984 | #[inline(never)] |
| 985 | fn exec_build_module(&mut self, op: u16) -> Result<(), VmErr> { |
no test coverage detected