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) {
|
static void get_(int canAssign) {
|
||||||
int isSlice = 0;
|
int isSlice = 0;
|
||||||
|
emitBytes(OP_DUP, 0);
|
||||||
if (match(TOKEN_COLON)) {
|
if (match(TOKEN_COLON)) {
|
||||||
emitByte(OP_NONE);
|
emitByte(OP_NONE);
|
||||||
isSlice = 1;
|
isSlice = 1;
|
||||||
@ -512,11 +513,12 @@ static void get_(int canAssign) {
|
|||||||
expression();
|
expression();
|
||||||
emitByte(OP_INVOKE_SETTER);
|
emitByte(OP_INVOKE_SETTER);
|
||||||
} else if (canAssign && matchAssignment()) {
|
} else if (canAssign && matchAssignment()) {
|
||||||
emitByte(OP_SWAP);
|
emitBytes(OP_DUP, 1); /* o o e o */
|
||||||
emitBytes(OP_DUP, 1);
|
emitBytes(OP_DUP, 0); /* o o e o o */
|
||||||
emitByte(OP_INVOKE_GETTER);
|
emitBytes(OP_DUP, 2); /* o o e o o e */
|
||||||
assignmentValue();
|
emitByte(OP_INVOKE_GETTER); /* o o e v */
|
||||||
emitByte(OP_INVOKE_SETTER);
|
assignmentValue(); /* o o e v a */
|
||||||
|
emitByte(OP_INVOKE_SETTER); /* r */
|
||||||
} else {
|
} else {
|
||||||
emitByte(OP_INVOKE_GETTER);
|
emitByte(OP_INVOKE_GETTER);
|
||||||
}
|
}
|
||||||
|
4
object.c
4
object.c
@ -121,6 +121,7 @@ KrkInstance * krk_newInstance(KrkClass * _class) {
|
|||||||
|
|
||||||
instance->_getter = NULL;
|
instance->_getter = NULL;
|
||||||
instance->_setter = NULL;
|
instance->_setter = NULL;
|
||||||
|
instance->_slicer = NULL;
|
||||||
|
|
||||||
KrkValue tmp;
|
KrkValue tmp;
|
||||||
if (krk_tableGet(&_class->methods, vm.specialMethodNames[METHOD_GET], &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)) {
|
if (krk_tableGet(&_class->methods, vm.specialMethodNames[METHOD_SET], &tmp)) {
|
||||||
instance->_setter = AS_OBJECT(tmp);
|
instance->_setter = AS_OBJECT(tmp);
|
||||||
}
|
}
|
||||||
|
if (krk_tableGet(&_class->methods, vm.specialMethodNames[METHOD_GETSLICE], &tmp)) {
|
||||||
|
instance->_slicer = AS_OBJECT(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
3
object.h
3
object.h
@ -89,8 +89,11 @@ typedef struct {
|
|||||||
KrkObj obj;
|
KrkObj obj;
|
||||||
KrkClass * _class;
|
KrkClass * _class;
|
||||||
KrkTable fields;
|
KrkTable fields;
|
||||||
|
|
||||||
|
/* Quick access for common stuff */
|
||||||
KrkObj * _getter;
|
KrkObj * _getter;
|
||||||
KrkObj * _setter;
|
KrkObj * _setter;
|
||||||
|
KrkObj * _slicer;
|
||||||
} KrkInstance;
|
} KrkInstance;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
34
vm.c
34
vm.c
@ -2845,9 +2845,13 @@ static KrkValue run() {
|
|||||||
}
|
}
|
||||||
case OP_INVOKE_GETTER: {
|
case OP_INVOKE_GETTER: {
|
||||||
if (IS_INSTANCE(krk_peek(1)) && AS_INSTANCE(krk_peek(1))->_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));
|
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 {
|
} else {
|
||||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(0)));
|
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: {
|
case OP_INVOKE_SETTER: {
|
||||||
if (IS_INSTANCE(krk_peek(2)) && AS_INSTANCE(krk_peek(2))->_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);
|
KrkValue result = krk_callSimple(OBJECT_VAL(AS_INSTANCE(krk_peek(3))->_setter), 3);
|
||||||
krk_push(result);
|
krk_push(result);
|
||||||
|
} else if (IS_STRING(krk_peek(2))) {
|
||||||
|
_strings_are_immutable(0,NULL);
|
||||||
|
goto _finishException;
|
||||||
} else {
|
} else {
|
||||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(0)));
|
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(0)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_INVOKE_GETSLICE: {
|
case OP_INVOKE_GETSLICE: {
|
||||||
krk_push(krk_peek(2)); /* object to top */
|
if (IS_INSTANCE(krk_peek(2)) && AS_INSTANCE(krk_peek(2))->_slicer) {
|
||||||
valueGetProperty(AS_STRING(vm.specialMethodNames[METHOD_GETSLICE]));
|
KrkValue result = krk_callSimple(OBJECT_VAL(AS_INSTANCE(krk_peek(3))->_slicer), 3);
|
||||||
krk_swap(3);
|
krk_push(result);
|
||||||
krk_pop();
|
} else if (IS_STRING(krk_peek(2))) {
|
||||||
switch (krk_callValue(krk_peek(2),2,1)) {
|
KrkValue out = _string_get_slice(3, (KrkValue[]){krk_peek(2), krk_peek(1), krk_peek(0)});
|
||||||
case 2: break;
|
krk_pop(); /* max */
|
||||||
case 1: krk_push(krk_runNext()); break;
|
krk_pop(); /* min */
|
||||||
default: krk_runtimeError(vm.exceptions.typeError, "Invalid method call."); goto _finishException;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user