Reduced excessive calls to Toy_unwrapValue()

In practice, references only point to arrays or tables.

Fixed #176
This commit is contained in:
2025-02-17 04:42:22 +11:00
parent 15aea7c032
commit 76d89fe0ad
3 changed files with 39 additions and 33 deletions

View File

@@ -18,6 +18,8 @@ static unsigned int hashUInt(unsigned int x) {
return x; return x;
} }
#define MAYBE_UNWRAP(value) if (TOY_VALUE_IS_REFERENCE(value)) { value = Toy_unwrapValue(value); }
//exposed functions //exposed functions
Toy_Value Toy_unwrapValue(Toy_Value value) { Toy_Value Toy_unwrapValue(Toy_Value value) {
//turns out C doesn't have actual references //turns out C doesn't have actual references
@@ -30,7 +32,7 @@ Toy_Value Toy_unwrapValue(Toy_Value value) {
} }
unsigned int Toy_hashValue(Toy_Value value) { unsigned int Toy_hashValue(Toy_Value value) {
value = Toy_unwrapValue(value); MAYBE_UNWRAP(value);
switch(value.type) { switch(value.type) {
case TOY_VALUE_NULL: case TOY_VALUE_NULL:
@@ -88,7 +90,7 @@ unsigned int Toy_hashValue(Toy_Value value) {
} }
Toy_Value Toy_copyValue(Toy_Value value) { Toy_Value Toy_copyValue(Toy_Value value) {
value = Toy_unwrapValue(value); MAYBE_UNWRAP(value);
switch(value.type) { switch(value.type) {
case TOY_VALUE_NULL: case TOY_VALUE_NULL:
@@ -186,7 +188,7 @@ void Toy_freeValue(Toy_Value value) {
} }
bool Toy_checkValueIsTruthy(Toy_Value value) { bool Toy_checkValueIsTruthy(Toy_Value value) {
value = Toy_unwrapValue(value); MAYBE_UNWRAP(value);
//null is an error //null is an error
if (value.type == TOY_VALUE_NULL) { if (value.type == TOY_VALUE_NULL) {
@@ -212,8 +214,8 @@ bool Toy_checkValueIsTruthy(Toy_Value value) {
} }
bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right) { bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right) {
left = Toy_unwrapValue(left); MAYBE_UNWRAP(left);
right = Toy_unwrapValue(right); MAYBE_UNWRAP(right);
switch(left.type) { switch(left.type) {
case TOY_VALUE_NULL: case TOY_VALUE_NULL:
@@ -323,8 +325,8 @@ bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right) {
} }
bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right) { bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right) {
left = Toy_unwrapValue(left); MAYBE_UNWRAP(left);
right = Toy_unwrapValue(right); MAYBE_UNWRAP(right);
//NOTE: "equal" and "comparable" are different - equal means they're identical, comparable is only possible for certain types //NOTE: "equal" and "comparable" are different - equal means they're identical, comparable is only possible for certain types
switch(left.type) { switch(left.type) {
@@ -365,8 +367,8 @@ bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right) {
} }
int Toy_compareValues(Toy_Value left, Toy_Value right) { int Toy_compareValues(Toy_Value left, Toy_Value right) {
left = Toy_unwrapValue(left); MAYBE_UNWRAP(left);
right = Toy_unwrapValue(right); MAYBE_UNWRAP(right);
//comparison means there's a difference in value, with some kind of quantity - so null, bool, etc. aren't comparable //comparison means there's a difference in value, with some kind of quantity - so null, bool, etc. aren't comparable
switch(left.type) { switch(left.type) {
@@ -424,7 +426,7 @@ int Toy_compareValues(Toy_Value left, Toy_Value right) {
} }
Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) { Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
value = Toy_unwrapValue(value); MAYBE_UNWRAP(value);
//TODO: could have "constant" strings that can be referenced, instead of null, true, false, etc. - new string type of 'permanent' //TODO: could have "constant" strings that can be referenced, instead of null, true, false, etc. - new string type of 'permanent'

View File

@@ -44,25 +44,25 @@ typedef struct Toy_Value { //32 | 64 BITNESS
Toy_ValueType type; //4 | 4 Toy_ValueType type; //4 | 4
} Toy_Value; //8 | 16 } Toy_Value; //8 | 16
#define TOY_VALUE_IS_NULL(value) (Toy_unwrapValue(value).type == TOY_VALUE_NULL) #define TOY_VALUE_IS_NULL(value) ((value).type == TOY_VALUE_NULL)
#define TOY_VALUE_IS_BOOLEAN(value) (Toy_unwrapValue(value).type == TOY_VALUE_BOOLEAN) #define TOY_VALUE_IS_BOOLEAN(value) ((value).type == TOY_VALUE_BOOLEAN)
#define TOY_VALUE_IS_INTEGER(value) (Toy_unwrapValue(value).type == TOY_VALUE_INTEGER) #define TOY_VALUE_IS_INTEGER(value) ((value).type == TOY_VALUE_INTEGER)
#define TOY_VALUE_IS_FLOAT(value) (Toy_unwrapValue(value).type == TOY_VALUE_FLOAT) #define TOY_VALUE_IS_FLOAT(value) ((value).type == TOY_VALUE_FLOAT)
#define TOY_VALUE_IS_STRING(value) (Toy_unwrapValue(value).type == TOY_VALUE_STRING) #define TOY_VALUE_IS_STRING(value) ((value).type == TOY_VALUE_STRING)
#define TOY_VALUE_IS_ARRAY(value) (Toy_unwrapValue(value).type == TOY_VALUE_ARRAY) #define TOY_VALUE_IS_ARRAY(value) ((value).type == TOY_VALUE_ARRAY || (TOY_VALUE_IS_REFERENCE(value) && Toy_unwrapValue(value).type == TOY_VALUE_ARRAY))
#define TOY_VALUE_IS_TABLE(value) (Toy_unwrapValue(value).type == TOY_VALUE_TABLE) #define TOY_VALUE_IS_TABLE(value) ((value).type == TOY_VALUE_TABLE || (TOY_VALUE_IS_REFERENCE(value) && Toy_unwrapValue(value).type == TOY_VALUE_TABLE))
#define TOY_VALUE_IS_FUNCTION(value) (Toy_unwrapValue(value).type == TOY_VALUE_FUNCTION) #define TOY_VALUE_IS_FUNCTION(value) ((value).type == TOY_VALUE_FUNCTION)
#define TOY_VALUE_IS_OPAQUE(value) (Toy_unwrapValue(value).type == TOY_VALUE_OPAQUE) #define TOY_VALUE_IS_OPAQUE(value) ((value).type == TOY_VALUE_OPAQUE)
#define TOY_VALUE_IS_TYPE(value) (Toy_unwrapValue(value).type == TOY_VALUE_TYPE) #define TOY_VALUE_IS_TYPE(value) ((value).type == TOY_VALUE_TYPE)
#define TOY_VALUE_IS_REFERENCE(value) ((value).type == TOY_VALUE_REFERENCE) #define TOY_VALUE_IS_REFERENCE(value) ((value).type == TOY_VALUE_REFERENCE)
#define TOY_VALUE_AS_BOOLEAN(value) (Toy_unwrapValue(value).as.boolean) #define TOY_VALUE_AS_BOOLEAN(value) ((value).as.boolean)
#define TOY_VALUE_AS_INTEGER(value) (Toy_unwrapValue(value).as.integer) #define TOY_VALUE_AS_INTEGER(value) ((value).as.integer)
#define TOY_VALUE_AS_FLOAT(value) (Toy_unwrapValue(value).as.number) #define TOY_VALUE_AS_FLOAT(value) ((value).as.number)
#define TOY_VALUE_AS_STRING(value) (Toy_unwrapValue(value).as.string) #define TOY_VALUE_AS_STRING(value) ((value).as.string)
#define TOY_VALUE_AS_ARRAY(value) (Toy_unwrapValue(value).as.array) #define TOY_VALUE_AS_ARRAY(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.array)
#define TOY_VALUE_AS_TABLE(value) (Toy_unwrapValue(value).as.table) #define TOY_VALUE_AS_TABLE(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.table)
#define TOY_VALUE_AS_FUNCTION(value) (Toy_unwrapValue(value).as.function) #define TOY_VALUE_AS_FUNCTION(value) ((value).as.function)
//TODO: more //TODO: more
#define TOY_VALUE_FROM_NULL() ((Toy_Value){{ .integer = 0 }, TOY_VALUE_NULL}) #define TOY_VALUE_FROM_NULL() ((Toy_Value){{ .integer = 0 }, TOY_VALUE_NULL})

View File

@@ -271,8 +271,15 @@ static void processAssignCompound(Toy_VM* vm) {
if (valuePtr == NULL) { if (valuePtr == NULL) {
return; return;
} }
//in the event of a certain subset of types, create references instead (these should only exist on the stack)
if (TOY_VALUE_IS_REFERENCE(*valuePtr) || TOY_VALUE_IS_ARRAY(*valuePtr) || TOY_VALUE_IS_TABLE(*valuePtr)) {
target = TOY_REFERENCE_FROM_POINTER(valuePtr); target = TOY_REFERENCE_FROM_POINTER(valuePtr);
} }
else {
target = Toy_copyValue(*valuePtr);
}
}
//assign based on target's type //assign based on target's type
if (TOY_VALUE_IS_ARRAY(target)) { if (TOY_VALUE_IS_ARRAY(target)) {
@@ -297,7 +304,7 @@ static void processAssignCompound(Toy_VM* vm) {
} }
//set the value //set the value
array->data[index] = Toy_copyValue(Toy_unwrapValue(value)); array->data[index] = Toy_copyValue(TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value);
//in case of chaining, leave a copy on the stack //in case of chaining, leave a copy on the stack
bool chainedAssignment = READ_BYTE(vm); bool chainedAssignment = READ_BYTE(vm);
@@ -313,7 +320,7 @@ static void processAssignCompound(Toy_VM* vm) {
Toy_Table* table = TOY_VALUE_AS_TABLE(target); Toy_Table* table = TOY_VALUE_AS_TABLE(target);
//set the value //set the value
Toy_insertTable(&table, Toy_copyValue(Toy_unwrapValue(key)), Toy_copyValue(Toy_unwrapValue(value))); Toy_insertTable(&table, Toy_copyValue(TOY_VALUE_IS_REFERENCE(key) ? Toy_unwrapValue(key) : key), Toy_copyValue(TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value));
//in case of chaining, leave a copy on the stack //in case of chaining, leave a copy on the stack
bool chainedAssignment = READ_BYTE(vm); bool chainedAssignment = READ_BYTE(vm);
@@ -358,7 +365,6 @@ static void processAccess(Toy_VM* vm) {
Toy_Value ref = TOY_REFERENCE_FROM_POINTER(valuePtr); Toy_Value ref = TOY_REFERENCE_FROM_POINTER(valuePtr);
Toy_pushStack(&vm->stack, ref); Toy_pushStack(&vm->stack, ref);
} }
else { else {
Toy_pushStack(&vm->stack, Toy_copyValue(*valuePtr)); Toy_pushStack(&vm->stack, Toy_copyValue(*valuePtr));
} }
@@ -799,7 +805,6 @@ static void processIndex(Toy_VM* vm) {
Toy_Value ref = TOY_REFERENCE_FROM_POINTER(&(array->data[i])); Toy_Value ref = TOY_REFERENCE_FROM_POINTER(&(array->data[i]));
Toy_pushStack(&vm->stack, ref); Toy_pushStack(&vm->stack, ref);
} }
else { else {
Toy_pushStack(&vm->stack, Toy_copyValue(array->data[i])); Toy_pushStack(&vm->stack, Toy_copyValue(array->data[i]));
} }
@@ -833,7 +838,6 @@ static void processIndex(Toy_VM* vm) {
Toy_Value ref = TOY_REFERENCE_FROM_POINTER(&(entry->value)); Toy_Value ref = TOY_REFERENCE_FROM_POINTER(&(entry->value));
Toy_pushStack(&vm->stack, ref); Toy_pushStack(&vm->stack, ref);
} }
else { else {
Toy_pushStack(&vm->stack, Toy_copyValue(entry->value)); Toy_pushStack(&vm->stack, Toy_copyValue(entry->value));
} }