mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Added 'Toy_String' to 'Toy_Value' structure, read more
To help with storing strings within tables, I've replaced the unused '_padding' member of 'Toy_String' with 'cachedHash', which is set to zero on string allocation. The hash of a string isn't generated and stored until it's actually needed, as the rope pattern means not every string needs a hash - hopefully this will save unnecessarily wasted time. When a hash of a string is needed, the hashing function first checks to see if that string already has one, and if so, returns it. Again, less time wasted. When generating a new string hash, the hashing function takes the string's type into account, as node-based strings first need their contents assembled into a simple char buffer. Other changes include: * Changed 'TOY_VALUE_TO_*' to 'TOY_VALUE_FROM_*' * Changed 'TOY_VALUE_IS_EQUAL' to 'TOY_VALUES_ARE_EQUAL' * Added a missing '#pragma once' to 'toy_print.h'
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
//general utilities
|
||||
#include "toy_common.h"
|
||||
#include "toy_console_colors.h"
|
||||
#include "toy_print.h"
|
||||
|
||||
//basic structures
|
||||
#include "toy_value.h"
|
||||
@@ -21,3 +22,4 @@
|
||||
#include "toy_parser.h"
|
||||
#include "toy_bytecode.h"
|
||||
#include "toy_vm.h"
|
||||
|
||||
|
||||
@@ -130,4 +130,5 @@ void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||
|
||||
void Toy_private_emitAstPass(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||
void Toy_private_emitAstError(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||
void Toy_private_emitAstEnd(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||
void Toy_private_emitAstEnd(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||
|
||||
|
||||
@@ -11,3 +11,4 @@ typedef struct Toy_Bytecode {
|
||||
|
||||
TOY_API Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast);
|
||||
TOY_API void Toy_freeBytecode(Toy_Bytecode bc);
|
||||
|
||||
|
||||
@@ -75,3 +75,4 @@ NOTE: you need both font AND background for these to work
|
||||
#define TOY_CC_RESET
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,3 +13,4 @@ extern const Toy_KeywordTypeTuple Toy_private_keywords[];
|
||||
//access
|
||||
const char* Toy_private_findKeywordByType(const Toy_TokenType type);
|
||||
Toy_TokenType Toy_private_findTypeByKeyword(const char* keyword);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "toy_token_types.h"
|
||||
#include "toy_common.h"
|
||||
#include "toy_token_types.h"
|
||||
|
||||
//lexers are bound to a string of code
|
||||
typedef struct {
|
||||
@@ -25,3 +25,4 @@ TOY_API void Toy_private_printToken(Toy_Token* token); //debugging
|
||||
|
||||
//util
|
||||
#define TOY_BLANK_TOKEN() ((Toy_Token){TOY_TOKEN_NULL, 0, 0, NULL})
|
||||
|
||||
|
||||
@@ -42,3 +42,4 @@ typedef enum Toy_OpcodeType {
|
||||
TOY_OPCODE_ERROR,
|
||||
TOY_OPCODE_EOF = 255,
|
||||
} Toy_OpcodeType;
|
||||
|
||||
|
||||
@@ -217,15 +217,15 @@ static ParsingTuple parsingRulesetTable[] = {
|
||||
static Toy_AstFlag atomic(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||
switch(parser->previous.type) {
|
||||
case TOY_TOKEN_NULL:
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_TO_NULL());
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_FROM_NULL());
|
||||
return TOY_AST_FLAG_NONE;
|
||||
|
||||
case TOY_TOKEN_LITERAL_TRUE:
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_TO_BOOLEAN(true));
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_FROM_BOOLEAN(true));
|
||||
return TOY_AST_FLAG_NONE;
|
||||
|
||||
case TOY_TOKEN_LITERAL_FALSE:
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_TO_BOOLEAN(false));
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_FROM_BOOLEAN(false));
|
||||
return TOY_AST_FLAG_NONE;
|
||||
|
||||
case TOY_TOKEN_LITERAL_INTEGER: {
|
||||
@@ -241,7 +241,7 @@ static Toy_AstFlag atomic(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast
|
||||
|
||||
int value = 0;
|
||||
sscanf(buffer, "%d", &value);
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_TO_INTEGER(value));
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_FROM_INTEGER(value));
|
||||
return TOY_AST_FLAG_NONE;
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ static Toy_AstFlag atomic(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast
|
||||
|
||||
float value = 0;
|
||||
sscanf(buffer, "%f", &value);
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_TO_FLOAT(value));
|
||||
Toy_private_emitAstValue(bucketHandle, rootHandle, TOY_VALUE_FROM_FLOAT(value));
|
||||
return TOY_AST_FLAG_NONE;
|
||||
}
|
||||
|
||||
@@ -280,10 +280,10 @@ static Toy_AstFlag unary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast*
|
||||
|
||||
//negative numbers
|
||||
if ((*rootHandle)->type == TOY_AST_VALUE && TOY_VALUE_IS_INTEGER((*rootHandle)->value.value) && connectedDigit) {
|
||||
(*rootHandle)->value.value = TOY_VALUE_TO_INTEGER( -TOY_VALUE_AS_INTEGER((*rootHandle)->value.value) );
|
||||
(*rootHandle)->value.value = TOY_VALUE_FROM_INTEGER( -TOY_VALUE_AS_INTEGER((*rootHandle)->value.value) );
|
||||
}
|
||||
else if ((*rootHandle)->type == TOY_AST_VALUE && TOY_VALUE_IS_FLOAT((*rootHandle)->value.value) && connectedDigit) {
|
||||
(*rootHandle)->value.value = TOY_VALUE_TO_FLOAT( -TOY_VALUE_AS_FLOAT((*rootHandle)->value.value) );
|
||||
(*rootHandle)->value.value = TOY_VALUE_FROM_FLOAT( -TOY_VALUE_AS_FLOAT((*rootHandle)->value.value) );
|
||||
}
|
||||
else {
|
||||
//actually emit the negation node
|
||||
@@ -296,7 +296,7 @@ static Toy_AstFlag unary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast*
|
||||
|
||||
//inverted booleans
|
||||
if ((*rootHandle)->type == TOY_AST_VALUE && TOY_VALUE_IS_BOOLEAN((*rootHandle)->value.value)) {
|
||||
(*rootHandle)->value.value = TOY_VALUE_TO_BOOLEAN( !TOY_VALUE_AS_BOOLEAN((*rootHandle)->value.value) );
|
||||
(*rootHandle)->value.value = TOY_VALUE_FROM_BOOLEAN( !TOY_VALUE_AS_BOOLEAN((*rootHandle)->value.value) );
|
||||
}
|
||||
else {
|
||||
//actually emit the negation node
|
||||
|
||||
@@ -19,3 +19,4 @@ typedef struct Toy_Parser {
|
||||
TOY_API void Toy_bindParser(Toy_Parser* parser, Toy_Lexer* lexer);
|
||||
TOY_API Toy_Ast* Toy_scanParser(Toy_Bucket** bucketHandle, Toy_Parser* parser);
|
||||
TOY_API void Toy_resetParser(Toy_Parser* parser);
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "toy_common.h"
|
||||
|
||||
//handle callbacks for printing to the terminal, or elsewhere
|
||||
|
||||
@@ -27,3 +27,4 @@ typedef struct Toy_Routine {
|
||||
} Toy_Routine;
|
||||
|
||||
TOY_API void* Toy_compileRoutine(Toy_Ast* ast);
|
||||
|
||||
|
||||
@@ -15,3 +15,4 @@ TOY_API void Toy_freeStack(Toy_Stack* stack);
|
||||
TOY_API void Toy_pushStack(Toy_Stack** stackHandle, Toy_Value value);
|
||||
TOY_API Toy_Value Toy_peekStack(Toy_Stack** stackHandle);
|
||||
TOY_API Toy_Value Toy_popStack(Toy_Stack** stackHandle);
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ Toy_String* Toy_createStringLength(Toy_Bucket** bucketHandle, const char* cstrin
|
||||
ret->type = TOY_STRING_LEAF;
|
||||
ret->length = length;
|
||||
ret->refCount = 1;
|
||||
ret->cachedHash = 0; //don't calc until needed
|
||||
memcpy(ret->as.leaf.data, cstring, length);
|
||||
ret->as.leaf.data[length] = '\0';
|
||||
|
||||
@@ -61,6 +62,7 @@ TOY_API Toy_String* Toy_createNameString(Toy_Bucket** bucketHandle, const char*
|
||||
ret->type = TOY_STRING_NAME;
|
||||
ret->length = length;
|
||||
ret->refCount = 1;
|
||||
ret->cachedHash = 0; //don't calc until needed
|
||||
memcpy(ret->as.name.data, cname, length);
|
||||
ret->as.name.data[length] = '\0';
|
||||
|
||||
@@ -87,6 +89,7 @@ Toy_String* Toy_deepCopyString(Toy_Bucket** bucketHandle, Toy_String* str) {
|
||||
ret->type = TOY_STRING_LEAF;
|
||||
ret->length = str->length;
|
||||
ret->refCount = 1;
|
||||
ret->cachedHash = str->cachedHash;
|
||||
deepCopyUtil(ret->as.leaf.data, str); //copy each leaf into the buffer
|
||||
ret->as.leaf.data[ret->length] = '\0';
|
||||
}
|
||||
@@ -94,6 +97,7 @@ Toy_String* Toy_deepCopyString(Toy_Bucket** bucketHandle, Toy_String* str) {
|
||||
ret->type = TOY_STRING_NAME;
|
||||
ret->length = str->length;
|
||||
ret->refCount = 1;
|
||||
ret->cachedHash = str->cachedHash;
|
||||
memcpy(ret->as.name.data, str->as.name.data, str->length);
|
||||
ret->as.name.data[ret->length] = '\0';
|
||||
}
|
||||
@@ -117,6 +121,7 @@ Toy_String* Toy_concatStrings(Toy_Bucket** bucketHandle, Toy_String* left, Toy_S
|
||||
ret->type = TOY_STRING_NODE;
|
||||
ret->length = left->length + right->length;
|
||||
ret->refCount = 1;
|
||||
ret->cachedHash = 0; //don't calc until needed
|
||||
ret->as.node.left = left;
|
||||
ret->as.node.right = right;
|
||||
|
||||
@@ -250,4 +255,4 @@ int Toy_compareStrings(Toy_String* left, Toy_String* right) {
|
||||
const char* rightHead = NULL;
|
||||
|
||||
return deepCompareUtil(left, right, &leftHead, &rightHead);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "toy_common.h"
|
||||
|
||||
#include "toy_bucket.h"
|
||||
@@ -13,8 +15,7 @@ typedef struct Toy_String { //32 | 64 BITNESS
|
||||
|
||||
unsigned int length; //4 | 4
|
||||
unsigned int refCount; //4 | 4
|
||||
|
||||
int _padding; //4 | 4
|
||||
unsigned int cachedHash; //4 | 4
|
||||
|
||||
union {
|
||||
struct {
|
||||
@@ -52,3 +53,4 @@ TOY_API int Toy_getStringRefCount(Toy_String* str);
|
||||
TOY_API char* Toy_getStringRawBuffer(Toy_String* str); //allocates the buffer on the heap, needs to be freed
|
||||
|
||||
TOY_API int Toy_compareStrings(Toy_String* left, Toy_String* right); //return value mimics strcmp()
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ static void probeAndInsert(Toy_Table** tableHandle, Toy_Value key, Toy_Value val
|
||||
//probe
|
||||
while (true) {
|
||||
//if we're overriding an existing value
|
||||
if (TOY_VALUE_IS_EQUAL((*tableHandle)->data[probe].key, key)) {
|
||||
if (TOY_VALUES_ARE_EQUAL((*tableHandle)->data[probe].key, key)) {
|
||||
(*tableHandle)->data[probe] = entry;
|
||||
|
||||
//TODO: benchmark the psl optimisation
|
||||
@@ -120,13 +120,13 @@ Toy_Value Toy_lookupTable(Toy_Table** tableHandle, Toy_Value key) {
|
||||
|
||||
while (true) {
|
||||
//found the entry
|
||||
if (TOY_VALUE_IS_EQUAL((*tableHandle)->data[probe].key, key)) {
|
||||
if (TOY_VALUES_ARE_EQUAL((*tableHandle)->data[probe].key, key)) {
|
||||
return (*tableHandle)->data[probe].value;
|
||||
}
|
||||
|
||||
//if its an empty slot
|
||||
if (TOY_VALUE_IS_NULL((*tableHandle)->data[probe].key)) {
|
||||
return TOY_VALUE_TO_NULL();
|
||||
return TOY_VALUE_FROM_NULL();
|
||||
}
|
||||
|
||||
//adjust and continue
|
||||
@@ -145,7 +145,7 @@ void Toy_removeTable(Toy_Table** tableHandle, Toy_Value key) {
|
||||
|
||||
while (true) {
|
||||
//found the entry
|
||||
if (TOY_VALUE_IS_EQUAL((*tableHandle)->data[probe].key, key)) {
|
||||
if (TOY_VALUES_ARE_EQUAL((*tableHandle)->data[probe].key, key)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -174,6 +174,6 @@ void Toy_removeTable(Toy_Table** tableHandle, Toy_Value key) {
|
||||
}
|
||||
|
||||
//finally, wipe the removed entry
|
||||
(*tableHandle)->data[wipe] = (Toy_TableEntry){ .key = TOY_VALUE_TO_NULL(), .value = TOY_VALUE_TO_NULL(), .psl = 0 };
|
||||
(*tableHandle)->data[wipe] = (Toy_TableEntry){ .key = TOY_VALUE_FROM_NULL(), .value = TOY_VALUE_FROM_NULL(), .psl = 0 };
|
||||
(*tableHandle)->count--;
|
||||
}
|
||||
|
||||
@@ -25,3 +25,4 @@ TOY_API void Toy_freeTable(Toy_Table* table);
|
||||
TOY_API void Toy_insertTable(Toy_Table** tableHandle, Toy_Value key, Toy_Value value);
|
||||
TOY_API Toy_Value Toy_lookupTable(Toy_Table** tableHandle, Toy_Value key);
|
||||
TOY_API void Toy_removeTable(Toy_Table** tableHandle, Toy_Value key);
|
||||
|
||||
|
||||
@@ -106,3 +106,4 @@ typedef enum Toy_TokenType {
|
||||
TOY_TOKEN_ERROR,
|
||||
TOY_TOKEN_EOF,
|
||||
} Toy_TokenType;
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "toy_value.h"
|
||||
#include "toy_console_colors.h"
|
||||
|
||||
#include "toy_print.h"
|
||||
#include "toy_string.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
bool Toy_private_isTruthy(Toy_Value value) {
|
||||
//null is an error
|
||||
@@ -21,7 +24,7 @@ bool Toy_private_isTruthy(Toy_Value value) {
|
||||
|
||||
bool Toy_private_isEqual(Toy_Value left, Toy_Value right) {
|
||||
//temp check
|
||||
if (right.type > TOY_VALUE_FLOAT) {
|
||||
if (right.type > TOY_VALUE_STRING) {
|
||||
Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value equality comparison\n" TOY_CC_RESET); //TODO: varargs
|
||||
}
|
||||
|
||||
@@ -51,6 +54,11 @@ bool Toy_private_isEqual(Toy_Value left, Toy_Value right) {
|
||||
return false;
|
||||
|
||||
case TOY_VALUE_STRING:
|
||||
if (TOY_VALUE_IS_STRING(right)) {
|
||||
return Toy_compareStrings(TOY_VALUE_AS_STRING(left), TOY_VALUE_AS_STRING(right)) == 0;
|
||||
}
|
||||
return false;
|
||||
|
||||
case TOY_VALUE_ARRAY:
|
||||
case TOY_VALUE_DICTIONARY:
|
||||
case TOY_VALUE_FUNCTION:
|
||||
@@ -96,7 +104,28 @@ unsigned int Toy_hashValue(Toy_Value value) {
|
||||
case TOY_VALUE_FLOAT:
|
||||
return hashUInt( *((int*)(&TOY_VALUE_AS_FLOAT(value))) );
|
||||
|
||||
case TOY_VALUE_STRING:
|
||||
case TOY_VALUE_STRING: {
|
||||
Toy_String* str = TOY_VALUE_AS_STRING(value);
|
||||
|
||||
if (str->cachedHash != 0) {
|
||||
return str->cachedHash;
|
||||
}
|
||||
else if (str->type == TOY_STRING_NODE) {
|
||||
//TODO: I wonder it it would be possible to discretely swap the composite node string with a new leaf string here? Would that speed up other parts of the code by not having to walk the tree?
|
||||
char* buffer = Toy_getStringRawBuffer(str);
|
||||
str->cachedHash = hashCString(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
else if (str->type == TOY_STRING_LEAF) {
|
||||
str->cachedHash = hashCString(str->as.leaf.data);
|
||||
}
|
||||
else if (str->type == TOY_STRING_NAME) {
|
||||
str->cachedHash = hashCString(str->as.name.data);
|
||||
}
|
||||
|
||||
return str->cachedHash;
|
||||
}
|
||||
|
||||
case TOY_VALUE_ARRAY:
|
||||
case TOY_VALUE_DICTIONARY:
|
||||
case TOY_VALUE_FUNCTION:
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#include "toy_common.h"
|
||||
|
||||
//forward declarations
|
||||
struct Toy_String;
|
||||
|
||||
typedef enum Toy_ValueType {
|
||||
TOY_VALUE_NULL,
|
||||
TOY_VALUE_BOOLEAN,
|
||||
@@ -20,15 +23,15 @@ typedef struct Toy_Value { //32 | 64 BITNESS
|
||||
bool boolean; //1 | 1
|
||||
int integer; //4 | 4
|
||||
float number; //4 | 4
|
||||
//TODO: strings
|
||||
struct Toy_String* string; //4 | 8
|
||||
//TODO: arrays
|
||||
//TODO: dictonaries
|
||||
//TODO: functions
|
||||
//TODO: opaque
|
||||
} as; //4 | 4
|
||||
} as; //4 | 8
|
||||
|
||||
Toy_ValueType type; //4 | 4
|
||||
} Toy_Value; //8 | 8
|
||||
} Toy_Value; //8 | 12
|
||||
|
||||
#define TOY_VALUE_IS_NULL(value) ((value).type == TOY_VALUE_NULL)
|
||||
#define TOY_VALUE_IS_BOOLEAN(value) ((value).type == TOY_VALUE_BOOLEAN)
|
||||
@@ -43,18 +46,21 @@ typedef struct Toy_Value { //32 | 64 BITNESS
|
||||
#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)
|
||||
//TODO: more
|
||||
|
||||
#define TOY_VALUE_TO_NULL() ((Toy_Value){{ .integer = 0 }, TOY_VALUE_NULL})
|
||||
#define TOY_VALUE_TO_BOOLEAN(value) ((Toy_Value){{ .boolean = value }, TOY_VALUE_BOOLEAN})
|
||||
#define TOY_VALUE_TO_INTEGER(value) ((Toy_Value){{ .integer = value }, TOY_VALUE_INTEGER})
|
||||
#define TOY_VALUE_TO_FLOAT(value) ((Toy_Value){{ .number = value }, TOY_VALUE_FLOAT})
|
||||
#define TOY_VALUE_FROM_NULL() ((Toy_Value){{ .integer = 0 }, TOY_VALUE_NULL})
|
||||
#define TOY_VALUE_FROM_BOOLEAN(value) ((Toy_Value){{ .boolean = value }, TOY_VALUE_BOOLEAN})
|
||||
#define TOY_VALUE_FROM_INTEGER(value) ((Toy_Value){{ .integer = value }, TOY_VALUE_INTEGER})
|
||||
#define TOY_VALUE_FROM_FLOAT(value) ((Toy_Value){{ .number = value }, TOY_VALUE_FLOAT})
|
||||
#define TOY_VALUE_FROM_STRING(value) ((Toy_Value){{ .string = value }, TOY_VALUE_STRING})
|
||||
//TODO: more
|
||||
|
||||
#define TOY_VALUE_IS_TRUTHY(value) Toy_private_isTruthy(value)
|
||||
TOY_API bool Toy_private_isTruthy(Toy_Value value);
|
||||
|
||||
#define TOY_VALUE_IS_EQUAL(left, right) Toy_private_isEqual(left, right)
|
||||
#define TOY_VALUES_ARE_EQUAL(left, right) Toy_private_isEqual(left, right)
|
||||
TOY_API bool Toy_private_isEqual(Toy_Value left, Toy_Value right);
|
||||
|
||||
unsigned int Toy_hashValue(Toy_Value value);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ static inline void fix_alignment(Toy_VM* vm) {
|
||||
static void processRead(Toy_VM* vm) {
|
||||
Toy_ValueType type = READ_BYTE(vm);
|
||||
|
||||
Toy_Value value = TOY_VALUE_TO_NULL();
|
||||
Toy_Value value = TOY_VALUE_FROM_NULL();
|
||||
|
||||
switch(type) {
|
||||
case TOY_VALUE_NULL: {
|
||||
@@ -47,19 +47,19 @@ static void processRead(Toy_VM* vm) {
|
||||
}
|
||||
|
||||
case TOY_VALUE_BOOLEAN: {
|
||||
value = TOY_VALUE_TO_BOOLEAN((bool)READ_BYTE(vm));
|
||||
value = TOY_VALUE_FROM_BOOLEAN((bool)READ_BYTE(vm));
|
||||
break;
|
||||
}
|
||||
|
||||
case TOY_VALUE_INTEGER: {
|
||||
fix_alignment(vm);
|
||||
value = TOY_VALUE_TO_INTEGER(READ_INT(vm));
|
||||
value = TOY_VALUE_FROM_INTEGER(READ_INT(vm));
|
||||
break;
|
||||
}
|
||||
|
||||
case TOY_VALUE_FLOAT: {
|
||||
fix_alignment(vm);
|
||||
value = TOY_VALUE_TO_FLOAT(READ_FLOAT(vm));
|
||||
value = TOY_VALUE_FROM_FLOAT(READ_FLOAT(vm));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -126,30 +126,30 @@ static void processArithmetic(Toy_VM* vm, Toy_OpcodeType opcode) {
|
||||
|
||||
//coerce ints into floats if needed
|
||||
if (TOY_VALUE_IS_INTEGER(left) && TOY_VALUE_IS_FLOAT(right)) {
|
||||
left = TOY_VALUE_TO_FLOAT( (float)TOY_VALUE_AS_INTEGER(left) );
|
||||
left = TOY_VALUE_FROM_FLOAT( (float)TOY_VALUE_AS_INTEGER(left) );
|
||||
}
|
||||
else
|
||||
if (TOY_VALUE_IS_FLOAT(left) && TOY_VALUE_IS_INTEGER(right)) {
|
||||
right = TOY_VALUE_TO_FLOAT( (float)TOY_VALUE_AS_INTEGER(right) );
|
||||
right = TOY_VALUE_FROM_FLOAT( (float)TOY_VALUE_AS_INTEGER(right) );
|
||||
}
|
||||
|
||||
//apply operation
|
||||
Toy_Value result = TOY_VALUE_TO_NULL();
|
||||
Toy_Value result = TOY_VALUE_FROM_NULL();
|
||||
|
||||
if (opcode == TOY_OPCODE_ADD) {
|
||||
result = TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_TO_FLOAT( TOY_VALUE_AS_FLOAT(left) + TOY_VALUE_AS_FLOAT(right)) : TOY_VALUE_TO_INTEGER( TOY_VALUE_AS_INTEGER(left) + TOY_VALUE_AS_INTEGER(right) );
|
||||
result = TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_FROM_FLOAT( TOY_VALUE_AS_FLOAT(left) + TOY_VALUE_AS_FLOAT(right)) : TOY_VALUE_FROM_INTEGER( TOY_VALUE_AS_INTEGER(left) + TOY_VALUE_AS_INTEGER(right) );
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_SUBTRACT) {
|
||||
result = TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_TO_FLOAT( TOY_VALUE_AS_FLOAT(left) - TOY_VALUE_AS_FLOAT(right)) : TOY_VALUE_TO_INTEGER( TOY_VALUE_AS_INTEGER(left) - TOY_VALUE_AS_INTEGER(right) );
|
||||
result = TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_FROM_FLOAT( TOY_VALUE_AS_FLOAT(left) - TOY_VALUE_AS_FLOAT(right)) : TOY_VALUE_FROM_INTEGER( TOY_VALUE_AS_INTEGER(left) - TOY_VALUE_AS_INTEGER(right) );
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_MULTIPLY) {
|
||||
result = TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_TO_FLOAT( TOY_VALUE_AS_FLOAT(left) * TOY_VALUE_AS_FLOAT(right)) : TOY_VALUE_TO_INTEGER( TOY_VALUE_AS_INTEGER(left) * TOY_VALUE_AS_INTEGER(right) );
|
||||
result = TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_FROM_FLOAT( TOY_VALUE_AS_FLOAT(left) * TOY_VALUE_AS_FLOAT(right)) : TOY_VALUE_FROM_INTEGER( TOY_VALUE_AS_INTEGER(left) * TOY_VALUE_AS_INTEGER(right) );
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_DIVIDE) {
|
||||
result = TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_TO_FLOAT( TOY_VALUE_AS_FLOAT(left) / TOY_VALUE_AS_FLOAT(right)) : TOY_VALUE_TO_INTEGER( TOY_VALUE_AS_INTEGER(left) / TOY_VALUE_AS_INTEGER(right) );
|
||||
result = TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_FROM_FLOAT( TOY_VALUE_AS_FLOAT(left) / TOY_VALUE_AS_FLOAT(right)) : TOY_VALUE_FROM_INTEGER( TOY_VALUE_AS_INTEGER(left) / TOY_VALUE_AS_INTEGER(right) );
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_MODULO) {
|
||||
result = TOY_VALUE_TO_INTEGER( TOY_VALUE_AS_INTEGER(left) % TOY_VALUE_AS_INTEGER(right) );
|
||||
result = TOY_VALUE_FROM_INTEGER( TOY_VALUE_AS_INTEGER(left) % TOY_VALUE_AS_INTEGER(right) );
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid opcode %d passed to processArithmetic, exiting\n" TOY_CC_RESET, opcode);
|
||||
@@ -166,14 +166,14 @@ static void processComparison(Toy_VM* vm, Toy_OpcodeType opcode) {
|
||||
|
||||
//most things can be equal, so handle it separately
|
||||
if (opcode == TOY_OPCODE_COMPARE_EQUAL) {
|
||||
bool equal = TOY_VALUE_IS_EQUAL(left, right);
|
||||
bool equal = TOY_VALUES_ARE_EQUAL(left, right);
|
||||
|
||||
//equality has an optional "negate" opcode within it's word
|
||||
if (READ_BYTE(vm) != TOY_OPCODE_NEGATE) {
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN(equal) );
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(equal) );
|
||||
}
|
||||
else {
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN(!equal) );
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(!equal) );
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -181,25 +181,25 @@ static void processComparison(Toy_VM* vm, Toy_OpcodeType opcode) {
|
||||
|
||||
//coerce ints into floats if needed
|
||||
if (TOY_VALUE_IS_INTEGER(left) && TOY_VALUE_IS_FLOAT(right)) {
|
||||
left = TOY_VALUE_TO_FLOAT( (float)TOY_VALUE_AS_INTEGER(left) );
|
||||
left = TOY_VALUE_FROM_FLOAT( (float)TOY_VALUE_AS_INTEGER(left) );
|
||||
}
|
||||
else
|
||||
if (TOY_VALUE_IS_FLOAT(left) && TOY_VALUE_IS_INTEGER(right)) {
|
||||
right = TOY_VALUE_TO_FLOAT( (float)TOY_VALUE_AS_INTEGER(right) );
|
||||
right = TOY_VALUE_FROM_FLOAT( (float)TOY_VALUE_AS_INTEGER(right) );
|
||||
}
|
||||
|
||||
//other opcodes
|
||||
if (opcode == TOY_OPCODE_COMPARE_LESS) {
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) < TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) < TOY_VALUE_AS_INTEGER(right)) );
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) < TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) < TOY_VALUE_AS_INTEGER(right)) );
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_COMPARE_LESS_EQUAL) {
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) <= TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) <= TOY_VALUE_AS_INTEGER(right)) );
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) <= TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) <= TOY_VALUE_AS_INTEGER(right)) );
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_COMPARE_GREATER) {
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) > TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) > TOY_VALUE_AS_INTEGER(right)) );
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) > TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) > TOY_VALUE_AS_INTEGER(right)) );
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_COMPARE_GREATER_EQUAL) {
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) >= TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) >= TOY_VALUE_AS_INTEGER(right)) );
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) >= TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) >= TOY_VALUE_AS_INTEGER(right)) );
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid opcode %d passed to processComparison, exiting\n" TOY_CC_RESET, opcode);
|
||||
@@ -212,23 +212,23 @@ static void processLogical(Toy_VM* vm, Toy_OpcodeType opcode) {
|
||||
Toy_Value right = Toy_popStack(&vm->stack);
|
||||
Toy_Value left = Toy_popStack(&vm->stack);
|
||||
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN( TOY_VALUE_IS_TRUTHY(left) && TOY_VALUE_IS_TRUTHY(right) ));
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( TOY_VALUE_IS_TRUTHY(left) && TOY_VALUE_IS_TRUTHY(right) ));
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_OR) {
|
||||
Toy_Value right = Toy_popStack(&vm->stack);
|
||||
Toy_Value left = Toy_popStack(&vm->stack);
|
||||
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN( TOY_VALUE_IS_TRUTHY(left) || TOY_VALUE_IS_TRUTHY(right) ));
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( TOY_VALUE_IS_TRUTHY(left) || TOY_VALUE_IS_TRUTHY(right) ));
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_TRUTHY) {
|
||||
Toy_Value top = Toy_popStack(&vm->stack);
|
||||
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN( TOY_VALUE_IS_TRUTHY(top) ));
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( TOY_VALUE_IS_TRUTHY(top) ));
|
||||
}
|
||||
else if (opcode == TOY_OPCODE_NEGATE) {
|
||||
Toy_Value top = Toy_popStack(&vm->stack);
|
||||
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_TO_BOOLEAN( !TOY_VALUE_IS_TRUTHY(top) ));
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( !TOY_VALUE_IS_TRUTHY(top) ));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid opcode %d passed to processLogical, exiting\n" TOY_CC_RESET, opcode);
|
||||
|
||||
Reference in New Issue
Block a user