Very initial rebuild of class creation

This commit is contained in:
K. Lange 2023-01-25 22:10:13 +09:00
parent f9df8b22ef
commit 617d30d804
12 changed files with 225 additions and 114 deletions

View File

@ -1241,6 +1241,98 @@ static void module_sweep(KrkInstance * inst) {
#endif
}
/**
* This should really be the default behavior of type.__new__?
*/
static void _callSetName(KrkClass * _class) {
KrkValue setnames = krk_list_of(0,NULL,0);
krk_push(setnames);
extern FUNC_SIG(list,append);
/* The semantics of this require that we first collect all of the relevant items... */
for (size_t i = 0; i < _class->methods.capacity; ++i) {
KrkTableEntry * entry = &_class->methods.entries[i];
if (!IS_KWARGS(entry->key)) {
KrkClass * type = krk_getType(entry->value);
if (type->_set_name) {
FUNC_NAME(list,append)(2,(KrkValue[]){setnames,entry->key},0);
FUNC_NAME(list,append)(2,(KrkValue[]){setnames,entry->value},0);
}
}
}
/* Then call __set_name__ on them */
for (size_t i = 0; i < AS_LIST(setnames)->count; i += 2) {
KrkValue name = AS_LIST(setnames)->values[i];
KrkValue value = AS_LIST(setnames)->values[i+1];
KrkClass * type = krk_getType(value);
if (type->_set_name) {
krk_push(value);
krk_push(OBJECT_VAL(_class));
krk_push(name);
krk_callDirect(type->_set_name, 3);
/* If any of these raises an exception, bail; CPython raises
* an outer exception, setting the cause, but I'm being lazy
* at the moment... */
if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
break;
}
}
}
/* List used to store name+value pairs */
krk_pop();
}
KRK_Function(__build_class__) {
KrkValue func = NONE_VAL();
KrkString * name = NULL;
KrkClass * base = vm.baseClasses->objectClass;
KrkValue metaclass = OBJECT_VAL(vm.baseClasses->typeClass);
if (!krk_parseArgs("VO!|O!$V~",
(const char*[]){"func","name","base","metaclass"},
&func,
vm.baseClasses->strClass, &name,
vm.baseClasses->typeClass, &base,
&metaclass)) {
return NONE_VAL();
}
/* Push function */
krk_push(func);
/* Dict */
krk_push(krk_dict_of(0,NULL,0));
/* Run the class function on it */
krk_push(krk_callStack(1));
/* Now make a class */
KrkClass * _class = krk_newClass(name, base);
krk_push(OBJECT_VAL(_class));
/* Now copy the values over */
krk_tableAddAll(AS_DICT(krk_peek(1)), &_class->methods);
krk_swap(1);
krk_pop(); /* Get rid of the namespace dict */
/* Now assign the upvalue for the original function if it's a closure. */
if (IS_CLOSURE(func)) {
if (AS_CLOSURE(func)->upvalueCount && AS_CLOSURE(func)->upvalues[0]->location == -1 && IS_NONE(AS_CLOSURE(func)->upvalues[0]->closed)) {
AS_CLOSURE(func)->upvalues[0]->closed = krk_peek(0);
}
}
krk_finalizeClass(_class);
_callSetName(_class);
/* We're done, return the resulting class object. */
return krk_pop();
}
_noexport
void _createAndBind_builtins(void) {
vm.baseClasses->objectClass = krk_newClass(S("object"), NULL);
@ -1513,5 +1605,8 @@ void _createAndBind_builtins(void) {
BUILTIN_FUNCTION("format", FUNC_NAME(krk,format),
"@brief Format a value for string printing.\n"
"@arguments value[,format_spec]");
BUILTIN_FUNCTION("__build_class__", FUNC_NAME(krk,__build_class__), "fuck");
}

View File

@ -100,6 +100,7 @@ typedef enum {
EXPR_ASSIGN_TARGET, /**< This expression is definitely an assignment target or chained to one. */
EXPR_DEL_TARGET, /**< This expression is in the target list of a 'del' statement. */
EXPR_METHOD_CALL, /**< This expression is the parameter list of a method call; only used by @ref dot and @ref call */
EXPR_CLASS_PARAMETERS,
} ExpressionType;
struct RewindState;
@ -148,6 +149,7 @@ typedef struct {
typedef struct {
size_t index; /**< Enclosing local index or upvalue index. */
char isLocal; /**< Flag indicating if @ref index is a local or upvalue index. */
KrkToken name;
} Upvalue;
/**
@ -391,6 +393,17 @@ static void initCompiler(struct GlobalState * state, Compiler * compiler, Functi
state->current->codeobject->potentialPositionals = 1;
}
if (type == TYPE_CLASS) {
Local * local = &state->current->locals[state->current->localCount++];
local->depth = 0;
local->isCaptured = 0;
local->name.start = "";
local->name.length = 0;
renameLocal(state, 0, local->name);
state->current->codeobject->requiredArgs = 1;
state->current->codeobject->potentialPositionals = 1;
}
if (isCoroutine(type)) state->current->codeobject->obj.flags |= KRK_OBJ_FLAGS_CODEOBJECT_IS_COROUTINE;
}
@ -1337,7 +1350,7 @@ static void doUpvalues(struct GlobalState * state, Compiler * compiler, KrkCodeO
assert(!!function->upvalueCount == !!compiler->upvalues);
for (size_t i = 0; i < function->upvalueCount; ++i) {
size_t index = compiler->upvalues[i].index;
emitByte((compiler->upvalues[i].isLocal ? 1 : 0) | ((index > 255) ? 2 : 0));
emitByte((compiler->upvalues[i].isLocal) | ((index > 255) ? 2 : 0));
if (index > 255) {
emitByte((index >> 16) & 0xFF);
emitByte((index >> 8) & 0xFF);
@ -1562,15 +1575,14 @@ static void classBody(struct GlobalState * state, size_t blockWidth) {
KrkToken name = state->parser.previous;
match(TOKEN_COLON);
/* Get __annotations__ from class */
emitBytes(OP_DUP, 0);
KrkToken annotations = syntheticToken("__annotations__");
size_t ind = identifierConstant(state, &annotations);
if (!state->currentClass->hasAnnotations) {
EMIT_OPERAND_OP(OP_MAKE_DICT, 0);
EMIT_OPERAND_OP(OP_SET_PROPERTY, ind);
EMIT_OPERAND_OP(OP_SET_NAME, ind);
state->currentClass->hasAnnotations = 1;
} else {
EMIT_OPERAND_OP(OP_GET_PROPERTY, ind);
EMIT_OPERAND_OP(OP_GET_NAME, ind);
}
emitConstant(OBJECT_VAL(krk_copyString(name.start, name.length)));
parsePrecedence(state, PREC_TERNARY);
@ -1586,7 +1598,8 @@ static void classBody(struct GlobalState * state, size_t blockWidth) {
parsePrecedence(state, PREC_COMMA);
rememberClassProperty(state, ind);
EMIT_OPERAND_OP(OP_CLASS_PROPERTY, ind);
EMIT_OPERAND_OP(OP_SET_NAME, ind);
emitByte(OP_POP);
if (!match(TOKEN_EOL) && !match(TOKEN_EOF)) {
errorAtCurrent("Expected end of line after class attribute declaration");
@ -1626,7 +1639,8 @@ static void classBody(struct GlobalState * state, size_t blockWidth) {
function(state, type, blockWidth);
rememberClassProperty(state, ind);
EMIT_OPERAND_OP(OP_CLASS_PROPERTY, ind);
EMIT_OPERAND_OP(OP_SET_NAME, ind);
emitByte(OP_POP);
}
}
@ -1636,28 +1650,29 @@ static void classBody(struct GlobalState * state, size_t blockWidth) {
EMIT_OPERAND_OP(how, val_ind); \
KrkToken name_tok = syntheticToken(propName); \
size_t name_ind = identifierConstant(state, &name_tok); \
EMIT_OPERAND_OP(OP_CLASS_PROPERTY, name_ind); \
EMIT_OPERAND_OP(OP_SET_NAME, name_ind); \
emitByte(OP_POP); \
} while (0)
static size_t addUpvalue(struct GlobalState * state, Compiler * compiler, ssize_t index, int isLocal, KrkToken name);
static KrkToken classDeclaration(struct GlobalState * state) {
size_t blockWidth = (state->parser.previous.type == TOKEN_INDENTATION) ? state->parser.previous.length : 0;
advance(); /* Collect the `class` */
consume(TOKEN_IDENTIFIER, "Expected class name after 'class'.");
KrkToken buildClass = syntheticToken("__build_class__");
size_t ind = identifierConstant(state, &buildClass);
EMIT_OPERAND_OP(OP_GET_GLOBAL, ind);
Compiler subcompiler;
initCompiler(state, &subcompiler, TYPE_CLASS);
subcompiler.codeobject->chunk.filename = subcompiler.enclosing->codeobject->chunk.filename;
beginScope(state);
/* We want to expose the mangled name within the class definition, which then
* becomes available as a nonlocal, but we want to hand the non-mangled name
* to the CLASS instruction so that __name__ is right. */
size_t nameInd = nonidentifierTokenConstant(state, &state->parser.previous);
identifierConstant(state, &state->parser.previous);
declareVariable(state);
EMIT_OPERAND_OP(OP_CLASS, nameInd);
markInitialized(state);
KrkToken classNameToken = state->parser.previous;
assert(addUpvalue(state, state->current, 0, 4, classNameToken) == 0);
ClassCompiler classCompiler;
classCompiler.name = state->parser.previous;
@ -1665,14 +1680,23 @@ static KrkToken classDeclaration(struct GlobalState * state) {
state->currentClass = &classCompiler;
classCompiler.hasAnnotations = 0;
RewindState parameters = {recordChunk(currentChunk()), krk_tellScanner(&state->scanner), state->parser};
/* Class parameters */
if (match(TOKEN_LEFT_PAREN)) {
startEatingWhitespace();
if (!check(TOKEN_RIGHT_PAREN)) {
expression(state);
emitByte(OP_INHERIT);
int parenDepth = 0;
while (!check(TOKEN_EOF)) {
if (check(TOKEN_RIGHT_PAREN) && parenDepth == 0) {
advance();
break;
} else if (match(TOKEN_LEFT_BRACE)) {
parenDepth++;
} else if (match(TOKEN_RIGHT_BRACE)) {
parenDepth--;
} else {
advance();
}
}
stopEatingWhitespace();
consume(TOKEN_RIGHT_PAREN, "Expected ')' after superclass.");
}
beginScope(state);
@ -1693,7 +1717,10 @@ static KrkToken classDeclaration(struct GlobalState * state) {
advance();
if (match(TOKEN_STRING) || match(TOKEN_BIG_STRING)) {
string(state, EXPR_NORMAL);
emitByte(OP_DOCSTRING);
KrkToken doc = syntheticToken("__doc__");
size_t ind = identifierConstant(state, &doc);
EMIT_OPERAND_OP(OP_SET_NAME, ind);
emitByte(OP_POP);
consume(TOKEN_EOL,"Garbage after docstring defintion");
if (!check(TOKEN_INDENTATION) || state->parser.current.length != currentIndentation) {
goto _pop_class;
@ -1710,14 +1737,30 @@ static KrkToken classDeclaration(struct GlobalState * state) {
}
} /* else empty class (and at end of file?) we'll allow it for now... */
_pop_class:
emitByte(OP_FINALIZE);
//emitByte(OP_FINALIZE);
state->currentClass = state->currentClass->enclosing;
KrkCodeObject * makeclass = endCompiler(state);
size_t indFunc = krk_addConstant(currentChunk(), OBJECT_VAL(makeclass));
EMIT_OPERAND_OP(OP_CLOSURE, indFunc);
doUpvalues(state, &subcompiler, makeclass);
freeCompiler(&subcompiler);
emitBytes(OP_CALL, 0);
RewindState afterFunction = {recordChunk(currentChunk()), krk_tellScanner(&state->scanner), state->parser};
size_t nameInd = nonidentifierTokenConstant(state, &classNameToken);
EMIT_OPERAND_OP(OP_CONSTANT, nameInd);
krk_rewindScanner(&state->scanner, parameters.oldScanner);
state->parser = parameters.oldParser;
if (match(TOKEN_LEFT_PAREN)) {
call(state, EXPR_CLASS_PARAMETERS, NULL);
} else {
emitBytes(OP_CALL, 2);
}
krk_rewindScanner(&state->scanner, afterFunction.oldScanner);
state->parser = afterFunction.oldParser;
return classCompiler.name;
}
@ -1853,7 +1896,8 @@ static KrkToken decorator(struct GlobalState * state, size_t level, FunctionType
} else {
size_t ind = identifierConstant(state, &funcName);
rememberClassProperty(state, ind);
EMIT_OPERAND_OP(OP_CLASS_PROPERTY, ind);
EMIT_OPERAND_OP(OP_SET_NAME, ind);
emitByte(OP_POP);
}
}
@ -2896,7 +2940,7 @@ _cleanupError:
#undef PUSH_CHAR
}
static size_t addUpvalue(struct GlobalState * state, Compiler * compiler, ssize_t index, int isLocal) {
static size_t addUpvalue(struct GlobalState * state, Compiler * compiler, ssize_t index, int isLocal, KrkToken name) {
size_t upvalueCount = compiler->codeobject->upvalueCount;
for (size_t i = 0; i < upvalueCount; ++i) {
Upvalue * upvalue = &compiler->upvalues[i];
@ -2911,19 +2955,28 @@ static size_t addUpvalue(struct GlobalState * state, Compiler * compiler, ssize_
}
compiler->upvalues[upvalueCount].isLocal = isLocal;
compiler->upvalues[upvalueCount].index = index;
compiler->upvalues[upvalueCount].name = name;
return compiler->codeobject->upvalueCount++;
}
static ssize_t resolveUpvalue(struct GlobalState * state, Compiler * compiler, KrkToken * name) {
size_t upvalueCount = compiler->codeobject->upvalueCount;
for (size_t i = 0; i < upvalueCount; ++i) {
if (identifiersEqual(name, &compiler->upvalues[i].name)) {
return i;
}
}
if (compiler->enclosing == NULL) return -1;
ssize_t local = resolveLocal(state, compiler->enclosing, name);
if (local != -1) {
compiler->enclosing->locals[local].isCaptured = 1;
return addUpvalue(state, compiler, local, 1);
return addUpvalue(state, compiler, local, 1, *name);
}
ssize_t upvalue = resolveUpvalue(state, compiler->enclosing, name);
if (upvalue != -1) {
return addUpvalue(state, compiler, upvalue, 0);
return addUpvalue(state, compiler, upvalue, 0, *name);
}
return -1;
}
@ -2959,8 +3012,7 @@ static void namedVariable(struct GlobalState * state, KrkToken name, int exprTyp
KrkString * constant = AS_STRING(currentChunk()->constants.values[properties->ind]);
if (constant->length == name.length && !memcmp(constant->chars, name.start, name.length)) {
ssize_t arg = properties->ind;
EMIT_OPERAND_OP(OP_GET_LOCAL, 0);
DO_VARIABLE(OP_SET_PROPERTY, OP_GET_PROPERTY, OP_NONE);
DO_VARIABLE(OP_SET_NAME, OP_GET_NAME, OP_NONE);
return;
}
properties = properties->next;
@ -3579,6 +3631,8 @@ static void call(struct GlobalState * state, int exprType, RewindState *rewind)
if (exprType == EXPR_METHOD_CALL) {
EMIT_OPERAND_OP(OP_CALL_METHOD, argCount);
} else if (exprType == EXPR_CLASS_PARAMETERS) {
EMIT_OPERAND_OP(OP_CALL, (argCount + 2));
} else {
EMIT_OPERAND_OP(OP_CALL, argCount);
}

View File

@ -188,11 +188,11 @@ typedef void (*KrkCleanupCallback)(struct KrkInstance *);
*/
typedef struct KrkClass {
KrkObj obj; /**< @protected @brief Base */
struct KrkClass * _class; /**< @brief Metaclass */
KrkTable methods; /**< @brief General attributes table */
KrkString * name; /**< @brief Name of the class */
KrkString * filename; /**< @brief Filename of the original source that defined the codeobject for the class */
KrkString * docstring; /**< @brief Storage for the class's docstring */
struct KrkClass * base; /**< @brief Pointer to base class implementation */
KrkTable methods; /**< @brief General attributes table */
size_t allocSize; /**< @brief Size to allocate when creating instances of this class */
KrkCleanupCallback _ongcscan; /**< @brief C function to call when the garbage collector visits an instance of this class in the scan phase */
KrkCleanupCallback _ongcsweep; /**< @brief C function to call when the garbage collector is discarding an instance of this class */

View File

@ -264,7 +264,7 @@ extern KrkValue FUNC_NAME(str,format)(int,const KrkValue*,int);
#define krk_string_format FUNC_NAME(str,format)
static inline void _setDoc_class(KrkClass * thing, const char * text, size_t size) {
thing->docstring = krk_copyString(text, size);
krk_attachNamedObject(&thing->methods, "__doc__", (KrkObj*)krk_copyString(text, size));
}
static inline void _setDoc_instance(KrkInstance * thing, const char * text, size_t size) {
krk_attachNamedObject(&thing->fields, "__doc__", (KrkObj*)krk_copyString(text, size));

View File

@ -371,7 +371,6 @@ static void blackenObject(KrkObj * object) {
KrkClass * _class = (KrkClass *)object;
krk_markObject((KrkObj*)_class->name);
krk_markObject((KrkObj*)_class->filename);
krk_markObject((KrkObj*)_class->docstring);
krk_markObject((KrkObj*)_class->base);
krk_markTable(&_class->methods);
break;

View File

@ -43,14 +43,6 @@ KRK_Method(type,__file__) {
return self->filename ? OBJECT_VAL(self->filename) : NONE_VAL();
}
KRK_Method(type,__doc__) {
if (argc > 1) {
if (!IS_STRING(argv[1])) return TYPE_ERROR(str,argv[1]);
self->docstring = AS_STRING(argv[1]);
}
return self->docstring ? OBJECT_VAL(self->docstring) : NONE_VAL();
}
KRK_Method(type,__str__) {
/* Determine if this class has a module */
KrkValue module = NONE_VAL();
@ -140,12 +132,11 @@ KRK_Method(type,__call__) {
_noexport
void _createAndBind_type(void) {
KrkClass * type = ADD_BASE_CLASS(vm.baseClasses->typeClass, "type", vm.baseClasses->objectClass);
type->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
//type->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
type->allocSize = sizeof(KrkClass);
BIND_PROP(type,__base__);
BIND_PROP(type,__file__);
BIND_PROP(type,__doc__);
BIND_PROP(type,__name__);
BIND_METHOD(type,__init__);

View File

@ -75,10 +75,10 @@ SIMPLE(OP_NOT)
OPERAND(OP_CALL, NOOP)
JUMP(OP_PUSH_WITH,+)
SIMPLE(OP_GREATER_EQUAL)
CONSTANT(OP_CLASS_PROPERTY, NOOP)
CONSTANT(OP_SET_NAME, NOOP)
SIMPLE(OP_INPLACE_ADD)
CONSTANT(OP_GET_METHOD, NOOP)
CONSTANT(OP_CLASS,NOOP)
OPERAND(OP_CLASS,NOOP)
SIMPLE(OP_LESS_EQUAL)
SIMPLE(OP_DOCSTRING)
SIMPLE(OP_MATMUL)
@ -113,3 +113,4 @@ JUMP(OP_CALL_ITER,+)
JUMP(OP_JUMP_IF_TRUE_OR_POP,+)
SIMPLE(OP_TRY_ELSE)
OPERAND(OP_MISSING_KW, NOOP)
CONSTANT(OP_GET_NAME, NOOP)

View File

@ -268,50 +268,6 @@ void krk_finalizeClass(KrkClass * _class) {
}
}
/**
* This should really be the default behavior of type.__new__?
*/
static void _callSetName(KrkClass * _class) {
KrkValue setnames = krk_list_of(0,NULL,0);
krk_push(setnames);
extern FUNC_SIG(list,append);
/* The semantics of this require that we first collect all of the relevant items... */
for (size_t i = 0; i < _class->methods.capacity; ++i) {
KrkTableEntry * entry = &_class->methods.entries[i];
if (!IS_KWARGS(entry->key)) {
KrkClass * type = krk_getType(entry->value);
if (type->_set_name) {
FUNC_NAME(list,append)(2,(KrkValue[]){setnames,entry->key},0);
FUNC_NAME(list,append)(2,(KrkValue[]){setnames,entry->value},0);
}
}
}
/* Then call __set_name__ on them */
for (size_t i = 0; i < AS_LIST(setnames)->count; i += 2) {
KrkValue name = AS_LIST(setnames)->values[i];
KrkValue value = AS_LIST(setnames)->values[i+1];
KrkClass * type = krk_getType(value);
if (type->_set_name) {
krk_push(value);
krk_push(OBJECT_VAL(_class));
krk_push(name);
krk_callDirect(type->_set_name, 3);
/* If any of these raises an exception, bail; CPython raises
* an outer exception, setting the cause, but I'm being lazy
* at the moment... */
if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
break;
}
}
}
/* List used to store name+value pairs */
krk_pop();
}
/**
* Maps values to their base classes.
* Internal version of type().
@ -342,6 +298,7 @@ inline KrkClass * krk_getType(KrkValue of) {
return vm.baseClasses->notImplClass;
case KRK_VAL_OBJECT:
if (IS_INSTANCE(of)) return AS_INSTANCE(of)->_class;
if (IS_CLASS(of) && AS_CLASS(of)->_class) return AS_CLASS(of)->_class;
return *(KrkClass **)((char*)vm.baseClasses + objClasses[AS_OBJECT(of)->type]);
default:
if (IS_FLOATING(of)) return vm.baseClasses->floatClass;
@ -2280,12 +2237,8 @@ _finishReturn: (void)0;
break;
}
case OP_FINALIZE: {
KrkClass * _class = AS_CLASS(krk_peek(0));
/* Store special methods for quick access */
krk_finalizeClass(_class);
/* Call __set_name__? */
_callSetName(_class);
break;
krk_runtimeError(vm.exceptions->typeError, "OP_FINALIZE called");
goto _finishException;
}
case OP_INHERIT: {
KrkValue superclass = krk_peek(0);
@ -2311,9 +2264,8 @@ _finishReturn: (void)0;
break;
}
case OP_DOCSTRING: {
KrkClass * me = AS_CLASS(krk_peek(1));
me->docstring = AS_STRING(krk_pop());
break;
krk_runtimeError(vm.exceptions->typeError, "OP_DOCSTRING called");
goto _finishException;
}
case OP_SWAP:
krk_swap(1);
@ -2657,6 +2609,10 @@ _finishReturn: (void)0;
}
if (isLocal & 1) {
closure->upvalues[i] = captureUpvalue(frame->slots + index);
} else if (isLocal & 4) {
closure->upvalues[i] = krk_newUpvalue(0);
closure->upvalues[i]->closed = NONE_VAL();
closure->upvalues[i]->location = -1;
} else {
closure->upvalues[i] = frame->closure->upvalues[index];
}
@ -2681,12 +2637,11 @@ _finishReturn: (void)0;
THREE_BYTE_OPERAND;
case OP_CLASS: {
ONE_BYTE_OPERAND;
KrkString * name = READ_STRING(OPERAND);
KrkClass * _class = krk_newClass(name, vm.baseClasses->objectClass);
krk_push(OBJECT_VAL(_class));
_class->filename = frame->closure->function->chunk.filename;
krk_attachNamedObject(&_class->methods, "__func__", (KrkObj*)frame->closure);
break;
/* OPERAND is number of arguments to pass to initializer */
/* stackTop[-OPERAND-1] is class function */
/* stackTop[-OPERAND-2] is class name */
krk_runtimeError(vm.exceptions->typeError, "what the fuck");
goto _finishException;
}
case OP_IMPORT_FROM_LONG:
THREE_BYTE_OPERAND;
@ -2746,10 +2701,16 @@ _finishReturn: (void)0;
}
break;
}
case OP_CLASS_PROPERTY_LONG:
case OP_SET_NAME_LONG:
THREE_BYTE_OPERAND;
case OP_CLASS_PROPERTY: {
case OP_SET_NAME: {
ONE_BYTE_OPERAND;
krk_push(krk_currentThread.stack[frame->slots]);
krk_swap(1);
krk_push(OBJECT_VAL(READ_STRING(OPERAND)));
krk_swap(1);
commonMethodInvoke(offsetof(KrkClass,_setter), 3, "'%T' object doesn't support item assignment");
#if 0
KrkValue method = krk_peek(0);
KrkClass * _class = AS_CLASS(krk_peek(1));
KrkValue name = OBJECT_VAL(READ_STRING(OPERAND));
@ -2761,6 +2722,16 @@ _finishReturn: (void)0;
AS_CLOSURE(method)->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD;
}
krk_pop();
#endif
break;
}
case OP_GET_NAME_LONG:
THREE_BYTE_OPERAND;
case OP_GET_NAME: {
ONE_BYTE_OPERAND;
krk_push(krk_currentThread.stack[frame->slots]);
krk_push(OBJECT_VAL(READ_STRING(OPERAND)));
commonMethodInvoke(offsetof(KrkClass,_getter), 2, "'%T' object doesn't support item assignment");
break;
}
case OP_GET_SUPER_LONG:

View File

@ -1,7 +1,7 @@
I am a function.
[42]
{'return': <class 'list'>, 'a': <class 'int'>, 'b': <class 'float'>}
{'return': None, 'anint': <class 'int'>, 'self': <class '__main__.Foo'>, 'adict': 'dict[str,object]'}
{'return': None, 'anint': <class 'int'>, 'self': None, 'adict': 'dict[str,object]'}
I am a method taking a dict.
None
{'astr': <class 'str'>, 'abool': <class 'bool'>}

View File

@ -1,4 +1,4 @@
['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'longList', 'ofAttributes', 'onThatObject', 'thatWeWantToSet']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'longList', 'ofAttributes', 'onThatObject', 'thatWeWantToSet']
1
2
3

View File

@ -7,10 +7,10 @@ False
[1, 3, 4, 5]
[1, 3, 4]
list index out of range: 3
['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'baz', 'qux']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'baz', 'qux']
42
['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'qux']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'qux']
hi
'object' object has no attribute 'baz'
['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__']
'object' object has no attribute 'bar'

View File

@ -1,3 +1,3 @@
['__class__', '__dir__', '__eq__', '__format__', '__func__', '__getattr__', '__hash__', '__init__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', '_dict']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__getattr__', '__hash__', '__init__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', '_dict']
1
['__class__', '__dir__', '__eq__', '__format__', '__func__', '__hash__', '__init__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', 'butts']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', 'butts']