diff --git a/src/chunk.h b/src/chunk.h index 1391848..57dd822 100644 --- a/src/chunk.h +++ b/src/chunk.h @@ -65,7 +65,8 @@ typedef enum { OP_FILTER_EXCEPT, OP_CREATE_CLASSMETHOD, OP_INVOKE_ITER, - /* current highest: 41 */ + OP_INVOKE_CONTAINS, + /* current highest: 42 */ OP_CALL = 64, OP_CLASS, diff --git a/src/compiler.c b/src/compiler.c index 519a9c5..37d9d78 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -624,11 +624,7 @@ _dotDone: static void in_(int canAssign) { parsePrecedence(PREC_COMPARISON); - KrkToken contains = syntheticToken("__contains__"); - ssize_t ind = identifierConstant(&contains); - EMIT_CONSTANT_OP(OP_GET_PROPERTY, ind); - emitByte(OP_SWAP); - emitBytes(OP_CALL,1); + emitByte(OP_INVOKE_CONTAINS); } static void not_(int canAssign) { diff --git a/src/object.h b/src/object.h index e7b7aa8..9b651ee 100644 --- a/src/object.h +++ b/src/object.h @@ -180,6 +180,7 @@ typedef struct KrkClass { KrkObj * _dir; KrkObj * _setslice; KrkObj * _delslice; + KrkObj * _contains; } KrkClass; /** diff --git a/src/opcodes.h b/src/opcodes.h index 68c3667..095a946 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -31,6 +31,7 @@ SIMPLE(OP_INVOKE_GETSLICE) SIMPLE(OP_INVOKE_SETSLICE) SIMPLE(OP_INVOKE_DELSLICE) SIMPLE(OP_INVOKE_ITER) +SIMPLE(OP_INVOKE_CONTAINS) SIMPLE(OP_SWAP) SIMPLE(OP_FINALIZE) SIMPLE(OP_IS) diff --git a/src/vm.c b/src/vm.c index 5e0a00a..26835b2 100644 --- a/src/vm.c +++ b/src/vm.c @@ -458,6 +458,7 @@ void krk_finalizeClass(KrkClass * _class) { {&_class->_iter, METHOD_ITER}, {&_class->_getattr, METHOD_GETATTR}, {&_class->_dir, METHOD_DIR}, + {&_class->_contains, METHOD_CONTAINS}, {NULL, 0}, }; @@ -1185,6 +1186,7 @@ void krk_initVM(int flags) { _(METHOD_ITER, "__iter__"), _(METHOD_GETATTR, "__getattr__"), _(METHOD_DIR, "__dir__"), + _(METHOD_CONTAINS, "__contains__"), #undef _ }; for (size_t i = 0; i < METHOD__MAX; ++i) { @@ -2009,6 +2011,16 @@ static KrkValue run() { } break; } + case OP_INVOKE_CONTAINS: { + KrkClass * type = krk_getType(krk_peek(0)); + if (likely(type->_contains)) { + krk_swap(1); + krk_push(krk_callSimple(OBJECT_VAL(type->_contains), 2, 0)); + } else { + krk_runtimeError(vm.exceptions->attributeError, "'%s' object can not be tested for membership", krk_typeName(krk_peek(0))); + } + break; + } case OP_FINALIZE: { KrkClass * _class = AS_CLASS(krk_peek(0)); /* Store special methods for quick access */ diff --git a/src/vm.h b/src/vm.h index a00344d..d009540 100644 --- a/src/vm.h +++ b/src/vm.h @@ -90,6 +90,7 @@ typedef enum { METHOD_DIR, METHOD_SETSLICE, METHOD_DELSLICE, + METHOD_CONTAINS, METHOD__MAX, } KrkSpecialMethods;