Unverified implementation for __getattr__

This commit is contained in:
K. Lange 2021-01-14 23:16:13 +09:00
parent 6f51f7b841
commit 5568665ad6
5 changed files with 56 additions and 1 deletions

View File

@ -136,6 +136,8 @@ typedef struct KrkClass {
KrkObj * _exit;
KrkObj * _delitem;
KrkObj * _iter;
KrkObj * _getattr;
KrkObj * _dir;
} KrkClass;
typedef struct KrkInstance {

24
test/testGetattrDir.krk Normal file
View File

@ -0,0 +1,24 @@
class Foo():
def __getattr__(name):
if name in self._dict:
return self._dict[name]
else:
raise AttributeError(name)
def __init__():
self._dict = {'foo': 1, 'bar': 42}
let f = Foo()
print(f)
print(dir(f))
print(f.foo)
class Bar(object):
def __dir__(self):
let out = super().__dir__()
out.append("butts")
return out
let b = Bar()
print(dir(b))
try:
b.butts

View File

@ -0,0 +1,4 @@
<instance of Foo at 0x55e8a79995b0>
['__class__', '__str__', '__init__', '__dir__', '__repr__', '__getattr__', '_dict']
1
['__class__', '__str__', '__dir__', '__repr__', 'butts']

25
vm.c
View File

@ -303,6 +303,8 @@ void krk_finalizeClass(KrkClass * _class) {
{&_class->_exit, METHOD_EXIT},
{&_class->_delitem, METHOD_DELITEM},
{&_class->_iter, METHOD_ITER},
{&_class->_getattr, METHOD_GETATTR},
{&_class->_dir, METHOD_DIR},
{NULL, 0},
};
@ -2682,6 +2684,19 @@ static KrkValue _len(int argc, KrkValue argv[]) {
return krk_callSimple(OBJECT_VAL(type->_len), 1, 0);
}
static KrkValue _dir(int argc, KrkValue argv[]) {
if (argc != 1) {
krk_runtimeError(vm.exceptions.argumentError, "dir() takes exactly one argument");
return NONE_VAL();
}
KrkClass * type = AS_CLASS(krk_typeOf(1,&argv[0]));
if (!type->_dir) {
return krk_dirObject(argc,argv); /* Fallback */
}
krk_push(argv[0]);
return krk_callSimple(OBJECT_VAL(type->_dir), 1, 0);
}
static KrkValue _repr(int argc, KrkValue argv[]) {
if (argc != 1) {
krk_runtimeError(vm.exceptions.argumentError, "repr() takes exactly one argument");
@ -3105,6 +3120,8 @@ void krk_initVM(int flags) {
vm.specialMethodNames[METHOD_EXIT] = OBJECT_VAL(S("__exit__"));
vm.specialMethodNames[METHOD_DELITEM] = OBJECT_VAL(S("__delitem__")); /* delitem */
vm.specialMethodNames[METHOD_ITER] = OBJECT_VAL(S("__iter__"));
vm.specialMethodNames[METHOD_GETATTR] = OBJECT_VAL(S("__getattr__"));
vm.specialMethodNames[METHOD_DIR] = OBJECT_VAL(S("__dir__"));
/* Create built-in class `object` */
vm.objectClass = krk_newClass(S("object"));
@ -3276,7 +3293,7 @@ void krk_initVM(int flags) {
BUILTIN_FUNCTION("dictOf", krk_dict_of); /* Equivalent to dict() */
BUILTIN_FUNCTION("isinstance", krk_isinstance);
BUILTIN_FUNCTION("globals", krk_globals);
BUILTIN_FUNCTION("dir", krk_dirObject);
BUILTIN_FUNCTION("dir", _dir);
BUILTIN_FUNCTION("len", _len);
BUILTIN_FUNCTION("repr", _repr);
BUILTIN_FUNCTION("print", _print);
@ -3709,6 +3726,12 @@ static int valueGetProperty(KrkString * name) {
return 1;
}
if (objectClass->_getattr) {
krk_push(OBJECT_VAL(name));
krk_push(krk_callSimple(OBJECT_VAL(objectClass->_getattr), 2, 0));
return 1;
}
return 0;
}

2
vm.h
View File

@ -43,6 +43,8 @@ typedef enum {
METHOD_EXIT,
METHOD_DELITEM,
METHOD_ITER,
METHOD_GETATTR,
METHOD_DIR,
METHOD__MAX,
} KrkSpecialMethods;