Support upvalue cells as exposed objects

This commit is contained in:
K. Lange 2023-02-12 07:39:12 +09:00
parent ffa5d7e611
commit 46b63fc871
5 changed files with 76 additions and 1 deletions

View File

@ -1336,6 +1336,53 @@ KRK_Function(__build_class__) {
return krk_pop(); return krk_pop();
} }
#undef CURRENT_CTYPE
#define CURRENT_CTYPE KrkUpvalue *
#define IS_Cell(o) (krk_isObjType((o), KRK_OBJ_UPVALUE))
#define AS_Cell(o) ((KrkUpvalue*)AS_OBJECT(o))
KRK_StaticMethod(Cell,__new__) {
KrkClass * _class = NULL;
KrkValue contents = NONE_VAL();
if (!krk_parseArgs("O!|V", (const char*[]){"cls","contents"}, KRK_BASE_CLASS(type), &_class, &contents)) {
return NONE_VAL();
}
if (_class != KRK_BASE_CLASS(Cell)) {
return krk_runtimeError(vm.exceptions->typeError, "can not assemble new Cell from %R", OBJECT_VAL(_class));
}
KrkUpvalue * out = krk_newUpvalue(-1);
out->closed = contents;
return OBJECT_VAL(out);
}
#define UPVALUE_LOCATION(upvalue) (upvalue->location == -1 ? &upvalue->closed : &upvalue->owner->stack[upvalue->location])
KRK_Method(Cell,__repr__) {
struct StringBuilder sb = {0};
KrkValue contents = *UPVALUE_LOCATION(self);
if (!krk_pushStringBuilderFormat(&sb,"<cell at %p: %T object", (void*)self, contents)) goto _error;
if (IS_OBJECT(contents)) {
if (!krk_pushStringBuilderFormat(&sb, " at %p>", (void*)AS_OBJECT(contents))) goto _error;
} else {
krk_pushStringBuilder(&sb,'>');
}
return krk_finishStringBuilder(&sb);
_error:
krk_discardStringBuilder(&sb);
return NONE_VAL();
}
KRK_Method(Cell,cell_contents) {
if (argc > 1) {
*UPVALUE_LOCATION(self) = argv[1];
}
return *UPVALUE_LOCATION(self);
}
_noexport _noexport
void _createAndBind_builtins(void) { void _createAndBind_builtins(void) {
vm.baseClasses->objectClass = krk_newClass(S("object"), NULL); vm.baseClasses->objectClass = krk_newClass(S("object"), NULL);
@ -1483,6 +1530,14 @@ void _createAndBind_builtins(void) {
BIND_METHOD(enumerate,__call__); BIND_METHOD(enumerate,__call__);
krk_finalizeClass(enumerate); krk_finalizeClass(enumerate);
KrkClass * Cell = ADD_BASE_CLASS(KRK_BASE_CLASS(Cell), "Cell", object);
Cell->allocSize = 0;
Cell->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
BIND_STATICMETHOD(Cell,__new__);
BIND_METHOD(Cell,__repr__);
BIND_PROP(Cell,cell_contents);
krk_finalizeClass(Cell);
BUILTIN_FUNCTION("isinstance", FUNC_NAME(krk,isinstance), BUILTIN_FUNCTION("isinstance", FUNC_NAME(krk,isinstance),
"@brief Check if an object is an instance of a type.\n" "@brief Check if an object is an instance of a type.\n"
"@arguments inst, cls\n\n" "@arguments inst, cls\n\n"

View File

@ -202,6 +202,8 @@ static void _closure_more(OPARGS, size_t constant) {
break; break;
} }
} }
} else if (isLocal & 4) {
fprintf(f, "classcell");
} else { fprintf(f, "upvalue<%d>", index); } } else { fprintf(f, "upvalue<%d>", index); }
if (j + 1 != function->upvalueCount) fprintf(f, ", "); if (j + 1 != function->upvalueCount) fprintf(f, ", ");
} }

View File

@ -146,6 +146,7 @@ struct BaseClasses {
KrkClass * ThreadClass; /**< Threading.Thread */ KrkClass * ThreadClass; /**< Threading.Thread */
KrkClass * LockClass; /**< Threading.Lock */ KrkClass * LockClass; /**< Threading.Lock */
KrkClass * CompilerStateClass; /**< Compiler global state */ KrkClass * CompilerStateClass; /**< Compiler global state */
KrkClass * CellClass; /**< Upvalue cell */
}; };
/** /**

View File

@ -187,6 +187,22 @@ KRK_Method(function,__code__) {
return OBJECT_VAL(AS_CLOSURE(self)->function); return OBJECT_VAL(AS_CLOSURE(self)->function);
} }
KRK_Method(function,__closure__) {
ATTRIBUTE_NOT_ASSIGNABLE();
if (!IS_CLOSURE(self)) {
return OBJECT_VAL(krk_newTuple(0));
}
size_t cnt = AS_CLOSURE(self)->upvalueCount;
KrkTuple * out = krk_newTuple(cnt);
krk_push(OBJECT_VAL(out));
for (size_t i = 0; i < cnt; ++i) {
out->values.values[out->values.count++] = OBJECT_VAL(AS_CLOSURE(self)->upvalues[i]);
}
return krk_pop();
}
#undef CURRENT_CTYPE #undef CURRENT_CTYPE
#define CURRENT_CTYPE KrkCodeObject* #define CURRENT_CTYPE KrkCodeObject*
@ -414,6 +430,7 @@ void _createAndBind_functionClass(void) {
BIND_PROP(function,__annotations__); BIND_PROP(function,__annotations__);
BIND_PROP(function,__code__); BIND_PROP(function,__code__);
BIND_PROP(function,__globals__); BIND_PROP(function,__globals__);
BIND_PROP(function,__closure__);
krk_defineNative(&function->methods, "__repr__", FUNC_NAME(function,__str__)); krk_defineNative(&function->methods, "__repr__", FUNC_NAME(function,__str__));
krk_defineNative(&function->methods, "__class_getitem__", krk_GenericAlias)->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD; krk_defineNative(&function->methods, "__class_getitem__", krk_GenericAlias)->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD;
krk_finalizeClass(function); krk_finalizeClass(function);

View File

@ -280,7 +280,7 @@ inline KrkClass * krk_getType(KrkValue of) {
[KRK_OBJ_CLOSURE] = offsetof(struct BaseClasses, functionClass), [KRK_OBJ_CLOSURE] = offsetof(struct BaseClasses, functionClass),
[KRK_OBJ_BOUND_METHOD] = offsetof(struct BaseClasses, methodClass), [KRK_OBJ_BOUND_METHOD] = offsetof(struct BaseClasses, methodClass),
[KRK_OBJ_STRING] = offsetof(struct BaseClasses, strClass), [KRK_OBJ_STRING] = offsetof(struct BaseClasses, strClass),
[KRK_OBJ_UPVALUE] = offsetof(struct BaseClasses, objectClass), [KRK_OBJ_UPVALUE] = offsetof(struct BaseClasses, CellClass),
[KRK_OBJ_CLASS] = offsetof(struct BaseClasses, typeClass), [KRK_OBJ_CLASS] = offsetof(struct BaseClasses, typeClass),
[KRK_OBJ_TUPLE] = offsetof(struct BaseClasses, tupleClass), [KRK_OBJ_TUPLE] = offsetof(struct BaseClasses, tupleClass),
[KRK_OBJ_BYTES] = offsetof(struct BaseClasses, bytesClass), [KRK_OBJ_BYTES] = offsetof(struct BaseClasses, bytesClass),