Oops, fix strings; simplify bytecode around getters/setters; use this approach for slicing
This commit is contained in:
parent
49b7eb2941
commit
b93429d6a6
12
compiler.c
12
compiler.c
@ -484,6 +484,7 @@ static void assignmentValue(void) {
|
||||
|
||||
static void get_(int canAssign) {
|
||||
int isSlice = 0;
|
||||
emitBytes(OP_DUP, 0);
|
||||
if (match(TOKEN_COLON)) {
|
||||
emitByte(OP_NONE);
|
||||
isSlice = 1;
|
||||
@ -512,11 +513,12 @@ static void get_(int canAssign) {
|
||||
expression();
|
||||
emitByte(OP_INVOKE_SETTER);
|
||||
} else if (canAssign && matchAssignment()) {
|
||||
emitByte(OP_SWAP);
|
||||
emitBytes(OP_DUP, 1);
|
||||
emitByte(OP_INVOKE_GETTER);
|
||||
assignmentValue();
|
||||
emitByte(OP_INVOKE_SETTER);
|
||||
emitBytes(OP_DUP, 1); /* o o e o */
|
||||
emitBytes(OP_DUP, 0); /* o o e o o */
|
||||
emitBytes(OP_DUP, 2); /* o o e o o e */
|
||||
emitByte(OP_INVOKE_GETTER); /* o o e v */
|
||||
assignmentValue(); /* o o e v a */
|
||||
emitByte(OP_INVOKE_SETTER); /* r */
|
||||
} else {
|
||||
emitByte(OP_INVOKE_GETTER);
|
||||
}
|
||||
|
4
object.c
4
object.c
@ -121,6 +121,7 @@ KrkInstance * krk_newInstance(KrkClass * _class) {
|
||||
|
||||
instance->_getter = NULL;
|
||||
instance->_setter = NULL;
|
||||
instance->_slicer = NULL;
|
||||
|
||||
KrkValue tmp;
|
||||
if (krk_tableGet(&_class->methods, vm.specialMethodNames[METHOD_GET], &tmp)) {
|
||||
@ -129,6 +130,9 @@ KrkInstance * krk_newInstance(KrkClass * _class) {
|
||||
if (krk_tableGet(&_class->methods, vm.specialMethodNames[METHOD_SET], &tmp)) {
|
||||
instance->_setter = AS_OBJECT(tmp);
|
||||
}
|
||||
if (krk_tableGet(&_class->methods, vm.specialMethodNames[METHOD_GETSLICE], &tmp)) {
|
||||
instance->_slicer = AS_OBJECT(tmp);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
3
object.h
3
object.h
@ -89,8 +89,11 @@ typedef struct {
|
||||
KrkObj obj;
|
||||
KrkClass * _class;
|
||||
KrkTable fields;
|
||||
|
||||
/* Quick access for common stuff */
|
||||
KrkObj * _getter;
|
||||
KrkObj * _setter;
|
||||
KrkObj * _slicer;
|
||||
} KrkInstance;
|
||||
|
||||
typedef struct {
|
||||
|
34
vm.c
34
vm.c
@ -2845,9 +2845,13 @@ static KrkValue run() {
|
||||
}
|
||||
case OP_INVOKE_GETTER: {
|
||||
if (IS_INSTANCE(krk_peek(1)) && AS_INSTANCE(krk_peek(1))->_getter) {
|
||||
krk_push(krk_peek(0));
|
||||
vm.stackTop[-2] = krk_peek(2);
|
||||
krk_push(krk_callSimple(OBJECT_VAL(AS_INSTANCE(krk_peek(2))->_getter), 2));
|
||||
} else if (IS_STRING(krk_peek(1))) {
|
||||
KrkValue out = _string_get(2, (KrkValue[]){krk_peek(1), krk_peek(0)});
|
||||
krk_pop(); /* index */
|
||||
krk_pop(); /* base object */
|
||||
krk_pop(); /* duplicate for binds */
|
||||
krk_push(out); /* result */
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(0)));
|
||||
}
|
||||
@ -2855,25 +2859,29 @@ static KrkValue run() {
|
||||
}
|
||||
case OP_INVOKE_SETTER: {
|
||||
if (IS_INSTANCE(krk_peek(2)) && AS_INSTANCE(krk_peek(2))->_setter) {
|
||||
krk_push(krk_peek(0));
|
||||
vm.stackTop[-2] = krk_peek(2);
|
||||
vm.stackTop[-3] = krk_peek(3);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(AS_INSTANCE(krk_peek(3))->_setter), 3);
|
||||
krk_push(result);
|
||||
} else if (IS_STRING(krk_peek(2))) {
|
||||
_strings_are_immutable(0,NULL);
|
||||
goto _finishException;
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(0)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_INVOKE_GETSLICE: {
|
||||
krk_push(krk_peek(2)); /* object to top */
|
||||
valueGetProperty(AS_STRING(vm.specialMethodNames[METHOD_GETSLICE]));
|
||||
krk_swap(3);
|
||||
krk_pop();
|
||||
switch (krk_callValue(krk_peek(2),2,1)) {
|
||||
case 2: break;
|
||||
case 1: krk_push(krk_runNext()); break;
|
||||
default: krk_runtimeError(vm.exceptions.typeError, "Invalid method call."); goto _finishException;
|
||||
if (IS_INSTANCE(krk_peek(2)) && AS_INSTANCE(krk_peek(2))->_slicer) {
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(AS_INSTANCE(krk_peek(3))->_slicer), 3);
|
||||
krk_push(result);
|
||||
} else if (IS_STRING(krk_peek(2))) {
|
||||
KrkValue out = _string_get_slice(3, (KrkValue[]){krk_peek(2), krk_peek(1), krk_peek(0)});
|
||||
krk_pop(); /* max */
|
||||
krk_pop(); /* min */
|
||||
krk_pop(); /* base object */
|
||||
krk_pop(); /* duplicate for binds */
|
||||
krk_push(out); /* result */
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not sliceable", krk_typeName(krk_peek(0)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user