diff --git a/source/toy_value.c b/source/toy_value.c index 57acdbc..81f635e 100644 --- a/source/toy_value.c +++ b/source/toy_value.c @@ -18,6 +18,8 @@ static unsigned int hashUInt(unsigned int x) { return x; } +#define MAYBE_UNWRAP(value) if (TOY_VALUE_IS_REFERENCE(value)) { value = Toy_unwrapValue(value); } + //exposed functions Toy_Value Toy_unwrapValue(Toy_Value value) { //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) { - value = Toy_unwrapValue(value); + MAYBE_UNWRAP(value); switch(value.type) { case TOY_VALUE_NULL: @@ -88,7 +90,7 @@ unsigned int Toy_hashValue(Toy_Value value) { } Toy_Value Toy_copyValue(Toy_Value value) { - value = Toy_unwrapValue(value); + MAYBE_UNWRAP(value); switch(value.type) { case TOY_VALUE_NULL: @@ -186,7 +188,7 @@ void Toy_freeValue(Toy_Value value) { } bool Toy_checkValueIsTruthy(Toy_Value value) { - value = Toy_unwrapValue(value); + MAYBE_UNWRAP(value); //null is an error 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) { - left = Toy_unwrapValue(left); - right = Toy_unwrapValue(right); + MAYBE_UNWRAP(left); + MAYBE_UNWRAP(right); switch(left.type) { 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) { - left = Toy_unwrapValue(left); - right = Toy_unwrapValue(right); + MAYBE_UNWRAP(left); + MAYBE_UNWRAP(right); //NOTE: "equal" and "comparable" are different - equal means they're identical, comparable is only possible for certain types 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) { - left = Toy_unwrapValue(left); - right = Toy_unwrapValue(right); + MAYBE_UNWRAP(left); + MAYBE_UNWRAP(right); //comparison means there's a difference in value, with some kind of quantity - so null, bool, etc. aren't comparable 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) { - 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' diff --git a/source/toy_value.h b/source/toy_value.h index 8615f96..a4b0851 100644 --- a/source/toy_value.h +++ b/source/toy_value.h @@ -44,25 +44,25 @@ typedef struct Toy_Value { //32 | 64 BITNESS Toy_ValueType type; //4 | 4 } Toy_Value; //8 | 16 -#define TOY_VALUE_IS_NULL(value) (Toy_unwrapValue(value).type == TOY_VALUE_NULL) -#define TOY_VALUE_IS_BOOLEAN(value) (Toy_unwrapValue(value).type == TOY_VALUE_BOOLEAN) -#define TOY_VALUE_IS_INTEGER(value) (Toy_unwrapValue(value).type == TOY_VALUE_INTEGER) -#define TOY_VALUE_IS_FLOAT(value) (Toy_unwrapValue(value).type == TOY_VALUE_FLOAT) -#define TOY_VALUE_IS_STRING(value) (Toy_unwrapValue(value).type == TOY_VALUE_STRING) -#define TOY_VALUE_IS_ARRAY(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_FUNCTION(value) (Toy_unwrapValue(value).type == TOY_VALUE_FUNCTION) -#define TOY_VALUE_IS_OPAQUE(value) (Toy_unwrapValue(value).type == TOY_VALUE_OPAQUE) -#define TOY_VALUE_IS_TYPE(value) (Toy_unwrapValue(value).type == TOY_VALUE_TYPE) +#define TOY_VALUE_IS_NULL(value) ((value).type == TOY_VALUE_NULL) +#define TOY_VALUE_IS_BOOLEAN(value) ((value).type == TOY_VALUE_BOOLEAN) +#define TOY_VALUE_IS_INTEGER(value) ((value).type == TOY_VALUE_INTEGER) +#define TOY_VALUE_IS_FLOAT(value) ((value).type == TOY_VALUE_FLOAT) +#define TOY_VALUE_IS_STRING(value) ((value).type == TOY_VALUE_STRING) +#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) ((value).type == TOY_VALUE_TABLE || (TOY_VALUE_IS_REFERENCE(value) && Toy_unwrapValue(value).type == TOY_VALUE_TABLE)) +#define TOY_VALUE_IS_FUNCTION(value) ((value).type == TOY_VALUE_FUNCTION) +#define TOY_VALUE_IS_OPAQUE(value) ((value).type == TOY_VALUE_OPAQUE) +#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_AS_BOOLEAN(value) (Toy_unwrapValue(value).as.boolean) -#define TOY_VALUE_AS_INTEGER(value) (Toy_unwrapValue(value).as.integer) -#define TOY_VALUE_AS_FLOAT(value) (Toy_unwrapValue(value).as.number) -#define TOY_VALUE_AS_STRING(value) (Toy_unwrapValue(value).as.string) -#define TOY_VALUE_AS_ARRAY(value) (Toy_unwrapValue(value).as.array) -#define TOY_VALUE_AS_TABLE(value) (Toy_unwrapValue(value).as.table) -#define TOY_VALUE_AS_FUNCTION(value) (Toy_unwrapValue(value).as.function) +#define TOY_VALUE_AS_BOOLEAN(value) ((value).as.boolean) +#define TOY_VALUE_AS_INTEGER(value) ((value).as.integer) +#define TOY_VALUE_AS_FLOAT(value) ((value).as.number) +#define TOY_VALUE_AS_STRING(value) ((value).as.string) +#define TOY_VALUE_AS_ARRAY(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.array) +#define TOY_VALUE_AS_TABLE(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.table) +#define TOY_VALUE_AS_FUNCTION(value) ((value).as.function) //TODO: more #define TOY_VALUE_FROM_NULL() ((Toy_Value){{ .integer = 0 }, TOY_VALUE_NULL}) diff --git a/source/toy_vm.c b/source/toy_vm.c index a1a2828..1e5980a 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -271,7 +271,14 @@ static void processAssignCompound(Toy_VM* vm) { if (valuePtr == NULL) { return; } - target = TOY_REFERENCE_FROM_POINTER(valuePtr); + + //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); + } + else { + target = Toy_copyValue(*valuePtr); + } } //assign based on target's type @@ -297,7 +304,7 @@ static void processAssignCompound(Toy_VM* vm) { } //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 bool chainedAssignment = READ_BYTE(vm); @@ -313,7 +320,7 @@ static void processAssignCompound(Toy_VM* vm) { Toy_Table* table = TOY_VALUE_AS_TABLE(target); //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 bool chainedAssignment = READ_BYTE(vm); @@ -358,7 +365,6 @@ static void processAccess(Toy_VM* vm) { Toy_Value ref = TOY_REFERENCE_FROM_POINTER(valuePtr); Toy_pushStack(&vm->stack, ref); } - else { 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_pushStack(&vm->stack, ref); } - else { 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_pushStack(&vm->stack, ref); } - else { Toy_pushStack(&vm->stack, Toy_copyValue(entry->value)); }