Actually give new property objects a class so we can do things with them directly

This commit is contained in:
K. Lange 2021-02-20 15:43:22 +09:00
parent d5d3d721e7
commit 663de74695
4 changed files with 41 additions and 8 deletions

View File

@ -340,6 +340,34 @@ KRK_METHOD(LicenseReader,__call__,{
return krk_runtimeError(vm.exceptions->typeError, "unexpected error");
})
static KrkValue _property_repr(int argc, KrkValue argv[], int hasKw) {
if (argc != 1 || !IS_PROPERTY(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "?");
struct StringBuilder sb = {0};
pushStringBuilderStr(&sb, "Property(", 9);
KrkValue method = AS_PROPERTY(argv[0])->method;
if (IS_NATIVE(method)) {
pushStringBuilderStr(&sb, (char*)AS_NATIVE(method)->name, strlen(AS_NATIVE(method)->name));
} else if (IS_CLOSURE(method)) {
pushStringBuilderStr(&sb, AS_CLOSURE(method)->function->name->chars, AS_CLOSURE(method)->function->name->length);
}
pushStringBuilder(&sb,')');
return finishStringBuilder(&sb);
}
static KrkValue _property_doc(int argc, KrkValue argv[], int hasKw) {
if (argc != 1 || !IS_PROPERTY(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "?");
KrkValue method = AS_PROPERTY(argv[0])->method;
if (IS_NATIVE(method) && AS_NATIVE(method)->doc) {
return OBJECT_VAL(krk_copyString(AS_NATIVE(method)->doc, strlen(AS_NATIVE(method)->doc)));
} else if (IS_CLOSURE(method)) {
return OBJECT_VAL(AS_CLOSURE(method)->function->docstring);
}
return NONE_VAL();
}
_noexport
void _createAndBind_builtins(void) {
vm.baseClasses->objectClass = krk_newClass(S("object"), NULL);
@ -371,6 +399,11 @@ void _createAndBind_builtins(void) {
krk_attachNamedObject(&vm.builtins->fields, "__doc__",
(KrkObj*)S("Internal module containing built-in functions and classes."));
krk_makeClass(vm.builtins, &vm.baseClasses->propertyClass, "Property", vm.baseClasses->objectClass);
krk_defineNative(&vm.baseClasses->propertyClass->methods, ".__repr__", _property_repr);
krk_defineNative(&vm.baseClasses->propertyClass->methods, ":__doc__", _property_doc);
krk_finalizeClass(vm.baseClasses->propertyClass);
krk_makeClass(vm.builtins, &Helper, "Helper", vm.baseClasses->objectClass);
BIND_METHOD(Helper,__call__);
BIND_METHOD(Helper,__repr__);

View File

@ -90,10 +90,10 @@ static inline const char * _method_name(const char * func) {
/* This assumes you have a KrkInstance called `module` in the current scope. */
#define MAKE_CLASS(klass) do { krk_makeClass(module,&klass,#klass,vm.baseClasses->objectClass); klass ->allocSize = sizeof(struct klass); } while (0)
#define BIND_METHOD(klass,method) do { krk_defineNative(&klass->methods, "." #method, _ ## klass ## _ ## method); } while (0)
#define BIND_FIELD(klass,method) do { krk_defineNative(&klass->methods, ":" #method, _ ## klass ## _ ## method); } while (0)
#define BIND_PROP(klass,method) do { krk_defineNativeProperty(&klass->fields, #method, _ ## klass ## _ ## method); } while (0)
#define BIND_FUNC(module,func) do { krk_defineNative(&module->fields, #func, _krk_ ## func); } while (0)
#define BIND_METHOD(klass,method) krk_defineNative(&klass->methods, "." #method, _ ## klass ## _ ## method)
#define BIND_FIELD(klass,method) krk_defineNative(&klass->methods, ":" #method, _ ## klass ## _ ## method)
#define BIND_PROP(klass,method) krk_defineNativeProperty(&klass->fields, #method, _ ## klass ## _ ## method)
#define BIND_FUNC(module,func) krk_defineNative(&module->fields, #func, _krk_ ## func)
/**
* @brief Inline flexible string array.

View File

@ -523,6 +523,8 @@ inline KrkClass * krk_getType(KrkValue of) {
return vm.baseClasses->tupleClass;
case OBJ_BYTES:
return vm.baseClasses->bytesClass;
case OBJ_PROPERTY:
return vm.baseClasses->propertyClass;
case OBJ_INSTANCE:
return AS_INSTANCE(of)->_class;
default:
@ -1702,6 +1704,7 @@ static int valueGetProperty(KrkString * name) {
KrkInstance * instance = AS_INSTANCE(krk_peek(0));
if (krk_tableGet(&instance->fields, OBJECT_VAL(name), &value)) {
if (IS_PROPERTY(value)) {
/* Properties retreived from instances are magic. */
krk_push(krk_callSimple(AS_PROPERTY(value)->method, 1, 0));
return 1;
}
@ -1714,10 +1717,6 @@ static int valueGetProperty(KrkString * name) {
KrkClass * _class = AS_CLASS(krk_peek(0));
if (krk_tableGet(&_class->fields, OBJECT_VAL(name), &value) ||
krk_tableGet(&_class->methods, OBJECT_VAL(name), &value)) {
if (IS_PROPERTY(value)) {
krk_push(krk_callSimple(AS_PROPERTY(value)->method, 1, 0));
return 1;
}
krk_pop();
krk_push(value);
return 1;

View File

@ -156,6 +156,7 @@ struct BaseClasses {
KrkClass * dictitemsClass; /**< Iterator over the (key,value) pairs of a dict */
KrkClass * dictkeysClass; /**< Iterator over the keys of a dict */
KrkClass * bytesiteratorClass; /**< Iterator over the integer byte values of a bytes object. */
KrkClass * propertyClass; /**< Magic object that calls a function when accessed from an instance through the dot operator. */
};
/**