Actually give new property objects a class so we can do things with them directly
This commit is contained in:
parent
d5d3d721e7
commit
663de74695
@ -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__);
|
||||
|
@ -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.
|
||||
|
7
src/vm.c
7
src/vm.c
@ -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;
|
||||
|
1
src/vm.h
1
src/vm.h
@ -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. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user