From a9bc374fc038a630842cd8487ce2c68fa73fdd92 Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Sun, 2 Sep 2018 20:44:46 +0200 Subject: [PATCH] Implement dir on object --- vm/src/builtins.rs | 45 ++++++++++++++++++++++++++++++++++--------- vm/src/obj/objtype.rs | 4 ++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 9e5eb1681..750aed4f8 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use std::io::{self, Write}; use super::compile; +use super::obj::objdict; use super::obj::objstr; use super::obj::objtype; use super::objbool; @@ -32,14 +33,40 @@ fn dir_locals(vm: &mut VirtualMachine) -> PyObjectRef { get_locals(vm) } -fn dir_object(vm: &mut VirtualMachine, _obj: PyObjectRef) -> PyObjectRef { - let d = vm.new_dict(); - // TODO: loop over dict of instance, next of class? - // TODO: Implement dir for objects - // for i in obj.iter_items() { - // d.set_item(k, v); - // } - d +fn dir_object(vm: &mut VirtualMachine, obj: &PyObjectRef) -> PyObjectRef { + // Gather all members here: + let mut members: Vec = vec![]; + + // Get class attributes: + let mut base_classes = objtype::base_classes(obj); + base_classes.reverse(); + for bc in base_classes { + if let PyObjectKind::Class { + name: _, + dict, + mro: _, + } = &bc.borrow().kind + { + let elements = objdict::get_elements(dict); + for (name, _value) in elements { + members.push(name.to_string()); + } + } + } + + // Get instance attributes: + if let PyObjectKind::Instance { dict } = &obj.borrow().kind { + let elements = objdict::get_elements(dict); + for (name, _value) in elements { + members.push(name.to_string()); + } + } + + // Sort members: + members.sort(); + + let members_pystr = members.into_iter().map(|m| vm.ctx.new_str(m)).collect(); + vm.ctx.new_list(members_pystr) } // builtin_abs @@ -115,7 +142,7 @@ fn builtin_dir(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(dir_locals(vm)) } else { let obj = args.args.into_iter().next().unwrap(); - Ok(dir_object(vm, obj)) + Ok(dir_object(vm, &obj)) } } diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 864ae7f3d..dd5d64b31 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -54,6 +54,10 @@ fn _mro(cls: PyObjectRef) -> Option> { } } +pub fn base_classes(obj: &PyObjectRef) -> Vec { + _mro(obj.typ()).unwrap() +} + pub fn isinstance(obj: &PyObjectRef, cls: PyObjectRef) -> bool { let mro = _mro(obj.typ()).unwrap(); mro.into_iter().any(|c| c.is(&cls))