diff --git a/repl/main.c b/repl/main.c index 940869a..e484e94 100644 --- a/repl/main.c +++ b/repl/main.c @@ -341,6 +341,8 @@ static void debugStackPrint(Toy_Stack* stack) { printf("%s\t", Toy_private_getValueTypeAsCString(v.type)); + v = Toy_unwrapValue(v); + switch(v.type) { case TOY_VALUE_NULL: printf("null"); @@ -382,6 +384,7 @@ static void debugStackPrint(Toy_Stack* stack) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: printf("???"); break; @@ -406,6 +409,9 @@ static void debugScopePrint(Toy_Scope* scope, int depth) { printf("%s\t%s\t", Toy_private_getValueTypeAsCString(v.type), TOY_VALUE_AS_STRING(k)->as.name.data); + k = Toy_unwrapValue(k); + v = Toy_unwrapValue(v); + switch(v.type) { case TOY_VALUE_NULL: printf("null"); @@ -447,6 +453,7 @@ static void debugScopePrint(Toy_Scope* scope, int depth) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: printf("???"); break; diff --git a/scripts/advent_1a.toy b/scripts/advent_1a.toy new file mode 100644 index 0000000..f70e7ed --- /dev/null +++ b/scripts/advent_1a.toy @@ -0,0 +1,27 @@ +//advent of code thingy +var arr = [ + 3, 4, + 4, 3, + 2, 5, + 1, 3, + 3, 9, + 3 , 3 +]; + +var total = 0; +var counter = 0; + +while (counter < arr.length) { + var difference = arr[counter] - arr[counter+1]; + + if (difference < 0) { + difference = -difference; + } + + total += difference; + + counter += 2; +} + +print difference; + diff --git a/source/toy_array.h b/source/toy_array.h index 02398ec..ec25b5f 100644 --- a/source/toy_array.h +++ b/source/toy_array.h @@ -40,3 +40,5 @@ TOY_API Toy_Array* Toy_resizeArray(Toy_Array* array, unsigned int capacity); #ifndef TOY_ARRAY_PUSHBACK #define TOY_ARRAY_PUSHBACK(array, value) (TOY_ARRAY_EXPAND(array),(array)->data[(array)->count++] = (value)) #endif + +//URGENT: check array length from scripts diff --git a/source/toy_ast.c b/source/toy_ast.c index 9c72c14..3b028bc 100644 --- a/source/toy_ast.c +++ b/source/toy_ast.c @@ -84,13 +84,23 @@ void Toy_private_emitAstGroup(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) { (*astHandle) = tmp; } -void Toy_private_emitAstCompound(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_AstFlag flag, Toy_Ast* right) { +void Toy_private_emitAstCompound(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_AstFlag flag) { Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast)); tmp->type = TOY_AST_COMPOUND; tmp->compound.flag = flag; - tmp->compound.left = *astHandle; //left-recursive - tmp->compound.right = right; + tmp->compound.child = *astHandle; + + (*astHandle) = tmp; +} + +void Toy_private_emitAstAggregate(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_AstFlag flag, Toy_Ast* right) { + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast)); + + tmp->type = TOY_AST_AGGREGATE; + tmp->aggregate.flag = flag; + tmp->aggregate.left = *astHandle; //left-recursive + tmp->aggregate.right = right; (*astHandle) = tmp; } diff --git a/source/toy_ast.h b/source/toy_ast.h index 3f45944..1b72287 100644 --- a/source/toy_ast.h +++ b/source/toy_ast.h @@ -16,6 +16,7 @@ typedef enum Toy_AstType { TOY_AST_COMPARE, TOY_AST_GROUP, TOY_AST_COMPOUND, + TOY_AST_AGGREGATE, TOY_AST_ASSERT, TOY_AST_IF_THEN_ELSE, @@ -58,8 +59,10 @@ typedef enum Toy_AstFlag { TOY_AST_FLAG_COMPARE_GREATER = 24, TOY_AST_FLAG_COMPARE_GREATER_EQUAL = 25, - TOY_AST_FLAG_COMPOUND_COLLECTION = 30, - TOY_AST_FLAG_COMPOUND_INDEX = 31, + TOY_AST_FLAG_COMPOUND_ARRAY = 30, + // TOY_AST_FLAG_COMPOUND_TABLE = 31, + TOY_AST_FLAG_COLLECTION = 32, + TOY_AST_FLAG_INDEX = 33, TOY_AST_FLAG_AND = 40, TOY_AST_FLAG_OR = 41, @@ -115,11 +118,17 @@ typedef struct Toy_AstGroup { } Toy_AstGroup; typedef struct Toy_AstCompound { + Toy_AstType type; + Toy_AstFlag flag; + Toy_Ast* child; +} Toy_AstCompound; + +typedef struct Toy_AstAggregate { Toy_AstType type; Toy_AstFlag flag; Toy_Ast* left; Toy_Ast* right; -} Toy_AstCompound; +} Toy_AstAggregate; typedef struct Toy_AstAssert { Toy_AstType type; @@ -191,7 +200,8 @@ union Toy_Ast { //32 | 64 BITNESS Toy_AstBinary binary; //16 | 24 Toy_AstCompare compare; //16 | 24 Toy_AstGroup group; //8 | 16 - Toy_AstCompound compound; //16 | 24 + Toy_AstCompound compound; //12 | 16 + Toy_AstAggregate aggregate; //16 | 24 Toy_AstAssert assert; //16 | 24 Toy_AstIfThenElse ifThenElse; //16 | 32 Toy_AstWhileThen whileThen; //16 | 24 @@ -214,7 +224,8 @@ void Toy_private_emitAstUnary(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, To void Toy_private_emitAstBinary(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right); void Toy_private_emitAstCompare(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right); void Toy_private_emitAstGroup(Toy_Bucket** bucketHandle, Toy_Ast** astHandle); -void Toy_private_emitAstCompound(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right); +void Toy_private_emitAstCompound(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag); +void Toy_private_emitAstAggregate(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right); void Toy_private_emitAstAssert(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* child, Toy_Ast* msg); void Toy_private_emitAstIfThenElse(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch, Toy_Ast* elseBranch); diff --git a/source/toy_parser.c b/source/toy_parser.c index 8cee9e2..024d915 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -117,6 +117,7 @@ static Toy_AstFlag unary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast* static Toy_AstFlag binary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag group(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); +static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); //precedence definitions static ParsingTuple parsingRulesetTable[] = { @@ -195,7 +196,7 @@ static ParsingTuple parsingRulesetTable[] = { //structural operators {PREC_NONE,group,NULL},// TOY_TOKEN_OPERATOR_PAREN_LEFT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_PAREN_RIGHT, - {PREC_GROUP,NULL,compound},// TOY_TOKEN_OPERATOR_BRACKET_LEFT, + {PREC_GROUP,compound,aggregate},// TOY_TOKEN_OPERATOR_BRACKET_LEFT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACKET_RIGHT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_LEFT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_RIGHT, @@ -208,7 +209,7 @@ static ParsingTuple parsingRulesetTable[] = { {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_COLON, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_SEMICOLON, // ; - {PREC_GROUP,NULL,compound},// TOY_TOKEN_OPERATOR_COMMA, // , + {PREC_GROUP,NULL,aggregate},// TOY_TOKEN_OPERATOR_COMMA, // , {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_DOT, // . {PREC_CALL,NULL,binary},// TOY_TOKEN_OPERATOR_CONCAT, // .. @@ -562,17 +563,16 @@ static Toy_AstFlag group(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast* } static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { - //infix must advance - advance(parser); + //read in an array or dictionary aggregate - if (parser->previous.type == TOY_TOKEN_OPERATOR_COMMA) { - parsePrecedence(bucketHandle, parser, rootHandle, PREC_GROUP); //NOT +1, as compounds are right-recursive - return TOY_AST_FLAG_COMPOUND_COLLECTION; - } - else if (parser->previous.type == TOY_TOKEN_OPERATOR_BRACKET_LEFT) { + if (parser->previous.type == TOY_TOKEN_OPERATOR_BRACKET_LEFT) { parsePrecedence(bucketHandle, parser, rootHandle, PREC_GROUP); - consume(parser, TOY_TOKEN_OPERATOR_BRACKET_RIGHT, "Expected ']' at the end of index expression"); - return TOY_AST_FLAG_COMPOUND_INDEX; + consume(parser, TOY_TOKEN_OPERATOR_BRACKET_RIGHT, "Expected ']' at the end of compound expression"); + Toy_private_emitAstCompound(bucketHandle, rootHandle, TOY_AST_FLAG_COMPOUND_ARRAY); + + return TOY_AST_FLAG_NONE; + + //TODO: read in a dictionary } else { printError(parser, parser->previous, "Unexpected token passed to compound precedence rule"); @@ -581,6 +581,31 @@ static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A } } +static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { + //infix must advance + advance(parser); + + if (parser->previous.type == TOY_TOKEN_OPERATOR_COMMA) { + parsePrecedence(bucketHandle, parser, rootHandle, PREC_GROUP); //NOT +1, as compounds are right-recursive + return TOY_AST_FLAG_COLLECTION; + } + else if (parser->previous.type == TOY_TOKEN_OPERATOR_BRACKET_LEFT) { + parsePrecedence(bucketHandle, parser, rootHandle, PREC_GROUP); + consume(parser, TOY_TOKEN_OPERATOR_BRACKET_RIGHT, "Expected ']' at the end of index expression"); + return TOY_AST_FLAG_INDEX; + } + else { + printError(parser, parser->previous, "Unexpected token passed to aggregate precedence rule"); + Toy_private_emitAstError(bucketHandle, rootHandle); + return TOY_AST_FLAG_NONE; + } +} + +//TODO: allow trailing commas +// static Toy_AstFlag noop(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { +// return return TOY_AST_FLAG_NONE; +// } + static ParsingTuple* getParsingRule(Toy_TokenType type) { return &parsingRulesetTable[type]; } @@ -638,7 +663,7 @@ static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A Toy_private_emitAstCompare(bucketHandle, rootHandle, flag, ptr); } else if (flag >= 30 && flag <= 39) { - Toy_private_emitAstCompound(bucketHandle, rootHandle, flag, ptr); + Toy_private_emitAstAggregate(bucketHandle, rootHandle, flag, ptr); } else { Toy_private_emitAstBinary(bucketHandle, rootHandle, flag, ptr); @@ -668,9 +693,9 @@ static void makeAssertStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_As Toy_private_emitAstPass(bucketHandle, rootHandle); } else { - //NOTE: if it's a compound, then it's got a second arg - if (ast->type == TOY_AST_COMPOUND) { - Toy_private_emitAstAssert(bucketHandle, rootHandle, ast->compound.left, ast->compound.right); + //NOTE: if it's an aggregate node, then it's got a second arg + if (ast->type == TOY_AST_AGGREGATE) { + Toy_private_emitAstAssert(bucketHandle, rootHandle, ast->aggregate.left, ast->aggregate.right); } else { Toy_private_emitAstAssert(bucketHandle, rootHandle, ast, NULL); diff --git a/source/toy_routine.c b/source/toy_routine.c index 2b72f3d..ebc756c 100644 --- a/source/toy_routine.c +++ b/source/toy_routine.c @@ -208,7 +208,7 @@ static unsigned int writeInstructionBinary(Toy_Routine** rt, Toy_AstBinary ast) } //4-byte alignment - EMIT_BYTE(rt, code,TOY_OPCODE_PASS); //checked in compound assignments + EMIT_BYTE(rt, code,TOY_OPCODE_PASS); //checked in combined assignments EMIT_BYTE(rt, code,0); EMIT_BYTE(rt, code,0); @@ -263,17 +263,41 @@ static unsigned int writeInstructionGroup(Toy_Routine** rt, Toy_AstGroup ast) { } static unsigned int writeInstructionCompound(Toy_Routine** rt, Toy_AstCompound ast) { + unsigned int result = writeRoutineCode(rt, ast.child); + + if (ast.flag == TOY_AST_FLAG_COMPOUND_ARRAY) { + //signal how many values to read in as an array value + EMIT_BYTE(rt, code, TOY_OPCODE_READ); + EMIT_BYTE(rt, code, TOY_VALUE_ARRAY); + + //4-byte alignment + EMIT_BYTE(rt, code,0); + EMIT_BYTE(rt, code,0); + + //how many elements + EMIT_INT(rt, code, result); + + return 1; //leaves only 1 value on the stack + } + else { + fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST compound flag found\n" TOY_CC_RESET); + exit(-1); + return 0; + } +} + +static unsigned int writeInstructionAggregate(Toy_Routine** rt, Toy_AstAggregate ast) { unsigned int result = 0; //left, then right result += writeRoutineCode(rt, ast.left); result += writeRoutineCode(rt, ast.right); - if (ast.flag == TOY_AST_FLAG_COMPOUND_COLLECTION) { + if (ast.flag == TOY_AST_FLAG_COLLECTION) { //collections are handled above return result; } - else if (ast.flag == TOY_AST_FLAG_COMPOUND_INDEX) { + else if (ast.flag == TOY_AST_FLAG_INDEX) { //value[index, length] EMIT_BYTE(rt, code, TOY_OPCODE_INDEX); EMIT_BYTE(rt, code, result); @@ -285,7 +309,7 @@ static unsigned int writeInstructionCompound(Toy_Routine** rt, Toy_AstCompound a return 1; //leaves only 1 value on the stack } else { - fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST compound flag found\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST aggregate flag found\n" TOY_CC_RESET); exit(-1); return 0; } @@ -429,10 +453,12 @@ static unsigned int writeInstructionVarDeclare(Toy_Routine** rt, Toy_AstVarDecla static unsigned int writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) { unsigned int result = 0; + //URGENT: check for LHS in index + //don't treat these as valid values switch (ast.expr->type) { case TOY_AST_BLOCK: - case TOY_AST_COMPOUND: + case TOY_AST_AGGREGATE: case TOY_AST_ASSERT: case TOY_AST_PRINT: case TOY_AST_VAR_DECLARE: @@ -594,7 +620,7 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) { return 0; } - //NOTE: 'result' is used to in 'writeInstructionCompound()' + //NOTE: 'result' is used to in 'writeInstructionAggregate()' unsigned int result = 0; //determine how to write each instruction based on the Ast @@ -642,6 +668,10 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) { result += writeInstructionCompound(rt, ast->compound); break; + case TOY_AST_AGGREGATE: + result += writeInstructionAggregate(rt, ast->aggregate); + break; + case TOY_AST_ASSERT: result += writeInstructionAssert(rt, ast->assert); break; diff --git a/source/toy_scope.c b/source/toy_scope.c index af61695..fda31de 100644 --- a/source/toy_scope.c +++ b/source/toy_scope.c @@ -7,6 +7,8 @@ #include "toy_print.h" +//URGENT: don't let references get saved into a scope + //utils static void incrementRefCount(Toy_Scope* scope) { for (Toy_Scope* iter = scope; iter; iter = iter->next) { @@ -126,6 +128,8 @@ void Toy_declareScope(Toy_Scope* scope, Toy_String* key, Toy_Value value) { Toy_insertTable(&scope->table, TOY_VALUE_FROM_STRING(Toy_copyString(key)), value); } + +//TODO: check for clearign old values void Toy_assignScope(Toy_Scope* scope, Toy_String* key, Toy_Value value) { if (key->type != TOY_STRING_NAME) { fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET); @@ -161,7 +165,7 @@ void Toy_assignScope(Toy_Scope* scope, Toy_String* key, Toy_Value value) { entryPtr->value = value; } -Toy_Value Toy_accessScope(Toy_Scope* scope, Toy_String* key) { +Toy_Value* Toy_accessScopeAsPointer(Toy_Scope* scope, Toy_String* key) { if (key->type != TOY_STRING_NAME) { fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET); exit(-1); @@ -173,10 +177,10 @@ Toy_Value Toy_accessScope(Toy_Scope* scope, Toy_String* key) { char buffer[key->length + 256]; sprintf(buffer, "Undefined variable: %s\n", key->as.name.data); Toy_error(buffer); - return TOY_VALUE_FROM_NULL(); + NULL; } - return entryPtr->value; + return &(entryPtr->value); } bool Toy_isDeclaredScope(Toy_Scope* scope, Toy_String* key) { diff --git a/source/toy_scope.h b/source/toy_scope.h index 618dd9e..93e2f4a 100644 --- a/source/toy_scope.h +++ b/source/toy_scope.h @@ -23,6 +23,6 @@ TOY_API Toy_Scope* Toy_deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope //manage the contents TOY_API void Toy_declareScope(Toy_Scope* scope, Toy_String* key, Toy_Value value); TOY_API void Toy_assignScope(Toy_Scope* scope, Toy_String* key, Toy_Value value); -TOY_API Toy_Value Toy_accessScope(Toy_Scope* scope, Toy_String* key); +TOY_API Toy_Value* Toy_accessScopeAsPointer(Toy_Scope* scope, Toy_String* key); TOY_API bool Toy_isDeclaredScope(Toy_Scope* scope, Toy_String* key); diff --git a/source/toy_value.c b/source/toy_value.c index 7d077b8..e54b653 100644 --- a/source/toy_value.c +++ b/source/toy_value.c @@ -18,30 +18,42 @@ static unsigned int hashUInt(unsigned int x) { } //exposed functions +Toy_Value Toy_unwrapValue(Toy_Value value) { + //turns out C doesn't have actual references + if (value.type == TOY_VALUE_REFERENCE) { + return Toy_unwrapValue(*(value.as.reference)); + } + else { + return value; + } +} + unsigned int Toy_hashValue(Toy_Value value) { + value = Toy_unwrapValue(value); + switch(value.type) { case TOY_VALUE_NULL: return 0; case TOY_VALUE_BOOLEAN: - return TOY_VALUE_AS_BOOLEAN(value) ? 1 : 0; + return value.as.boolean ? 1 : 0; case TOY_VALUE_INTEGER: - return hashUInt(TOY_VALUE_AS_INTEGER(value)); + return hashUInt((unsigned int)value.as.integer); case TOY_VALUE_FLOAT: - return hashUInt( *((int*)(&TOY_VALUE_AS_FLOAT(value))) ); + return hashUInt( *((unsigned int*)(&value.as.number)) ); case TOY_VALUE_STRING: - return Toy_hashString(TOY_VALUE_AS_STRING(value)); + return Toy_hashString(value.as.string); case TOY_VALUE_ARRAY: { //since array internals can change, recalc the hash each time it's needed - Toy_Array* array = TOY_VALUE_AS_ARRAY(value); + Toy_Array* ptr = value.as.array; unsigned int hash = 0; - for (unsigned int i = 0; i < array->count; i++) { - hash ^= Toy_hashValue(array->data[i]); + for (unsigned int i = 0; i < ptr->count; i++) { + hash ^= Toy_hashValue(ptr->data[i]); } return hash; @@ -52,6 +64,7 @@ unsigned int Toy_hashValue(Toy_Value value) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: fprintf(stderr, TOY_CC_ERROR "ERROR: Can't hash an unknown value type, exiting\n" TOY_CC_RESET); exit(-1); @@ -61,6 +74,8 @@ unsigned int Toy_hashValue(Toy_Value value) { } Toy_Value Toy_copyValue(Toy_Value value) { + value = Toy_unwrapValue(value); + switch(value.type) { case TOY_VALUE_NULL: case TOY_VALUE_BOOLEAN: @@ -69,20 +84,20 @@ Toy_Value Toy_copyValue(Toy_Value value) { return value; case TOY_VALUE_STRING: { - Toy_String* string = TOY_VALUE_AS_STRING(value); - return TOY_VALUE_FROM_STRING(Toy_copyString(string)); + return TOY_VALUE_FROM_STRING(Toy_copyString(value.as.string)); } case TOY_VALUE_ARRAY: { - Toy_Array* array = TOY_VALUE_AS_ARRAY(value); - Toy_Array* result = Toy_resizeArray(NULL, array->capacity); + //arrays probably won't get copied much + Toy_Array* ptr = value.as.array; + Toy_Array* result = Toy_resizeArray(NULL, ptr->capacity); - for (unsigned int i = 0; i < array->count; i++) { - result->data[i] = Toy_copyValue(array->data[i]); + for (unsigned int i = 0; i < ptr->count; i++) { + result->data[i] = Toy_copyValue(ptr->data[i]); } - result->capacity = array->capacity; - result->count = array->count; + result->capacity = ptr->capacity; + result->count = ptr->count; return TOY_VALUE_FROM_ARRAY(result); } @@ -92,6 +107,7 @@ Toy_Value Toy_copyValue(Toy_Value value) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: fprintf(stderr, TOY_CC_ERROR "ERROR: Can't copy an unknown value type, exiting\n" TOY_CC_RESET); exit(-1); @@ -102,6 +118,8 @@ Toy_Value Toy_copyValue(Toy_Value value) { } void Toy_freeValue(Toy_Value value) { + //NOTE: do not unwrap this value, as references shouldn't be freed + switch(value.type) { case TOY_VALUE_NULL: case TOY_VALUE_BOOLEAN: @@ -110,19 +128,18 @@ void Toy_freeValue(Toy_Value value) { break; case TOY_VALUE_STRING: { - Toy_String* string = TOY_VALUE_AS_STRING(value); - Toy_freeString(string); + Toy_freeString(value.as.string); break; } case TOY_VALUE_ARRAY: { - Toy_Array* array = TOY_VALUE_AS_ARRAY(value); + Toy_Array* ptr = value.as.array; - for (unsigned int i = 0; i < array->count; i++) { - Toy_freeValue(array->data[i]); + for (unsigned int i = 0; i < ptr->count; i++) { + Toy_freeValue(ptr->data[i]); } - TOY_ARRAY_FREE(array); + TOY_ARRAY_FREE(ptr); break; } @@ -131,6 +148,7 @@ void Toy_freeValue(Toy_Value value) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: fprintf(stderr, TOY_CC_ERROR "ERROR: Can't free an unknown value type, exiting\n" TOY_CC_RESET); exit(-1); @@ -138,15 +156,17 @@ void Toy_freeValue(Toy_Value value) { } bool Toy_checkValueIsTruthy(Toy_Value value) { + value = Toy_unwrapValue(value); + //null is an error - if (TOY_VALUE_IS_NULL(value)) { + if (value.type == TOY_VALUE_NULL) { Toy_error("'null' is neither true nor false"); return false; } //only 'false' is falsy - if (TOY_VALUE_IS_BOOLEAN(value)) { - return TOY_VALUE_AS_BOOLEAN(value); + if (value.type == TOY_VALUE_BOOLEAN) { + return value.as.boolean; } //anything else is truthy @@ -154,57 +174,65 @@ bool Toy_checkValueIsTruthy(Toy_Value value) { } bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right) { + left = Toy_unwrapValue(left); + right = Toy_unwrapValue(right); + switch(left.type) { case TOY_VALUE_NULL: - return TOY_VALUE_IS_NULL(right); + return right.type == TOY_VALUE_NULL; case TOY_VALUE_BOOLEAN: - return TOY_VALUE_IS_BOOLEAN(right) && TOY_VALUE_AS_BOOLEAN(left) == TOY_VALUE_AS_BOOLEAN(right); + return right.type == TOY_VALUE_NULL && left.as.boolean == right.as.boolean; case TOY_VALUE_INTEGER: - if (TOY_VALUE_IS_INTEGER(right)) { - return TOY_VALUE_AS_INTEGER(left) == TOY_VALUE_AS_INTEGER(right); + if (right.type == TOY_VALUE_INTEGER) { + return left.as.integer == right.as.integer; } - else if (TOY_VALUE_IS_FLOAT(right)) { - return TOY_VALUE_AS_INTEGER(left) == TOY_VALUE_AS_FLOAT(right); + else if (right.type == TOY_VALUE_FLOAT) { + return left.as.integer == right.as.number; } else { break; } case TOY_VALUE_FLOAT: - if (TOY_VALUE_IS_INTEGER(right)) { - return TOY_VALUE_AS_FLOAT(left) == TOY_VALUE_AS_INTEGER(right); + if (right.type == TOY_VALUE_INTEGER) { + return left.as.number == right.as.integer; } - else if (TOY_VALUE_IS_FLOAT(right)) { - return TOY_VALUE_AS_FLOAT(left) == TOY_VALUE_AS_FLOAT(right); + else if (right.type == TOY_VALUE_FLOAT) { + return left.as.number == right.as.number; } else { break; } case TOY_VALUE_STRING: - if (TOY_VALUE_IS_STRING(right)) { - return Toy_compareStrings(TOY_VALUE_AS_STRING(left), TOY_VALUE_AS_STRING(right)) == 0; + if (right.type == TOY_VALUE_STRING) { + return Toy_compareStrings(left.as.string, right.as.string) == 0; } else { break; } case TOY_VALUE_ARRAY: { - Toy_Array* leftArray = TOY_VALUE_AS_ARRAY(left); - Toy_Array* rightArray = TOY_VALUE_AS_ARRAY(right); + if (right.type == TOY_VALUE_ARRAY) { + Toy_Array* leftArray = left.as.array; + Toy_Array* rightArray = right.as.array; - //different lengths is an easy way to check - if (leftArray->count != rightArray->count) { - return false; - } - - for (unsigned int i = 0; i < leftArray->count; i++) { - //any mismatch is an easy difference - if (Toy_checkValuesAreEqual(leftArray->data[i], rightArray->data[i])) { + //different lengths is an easy way to check + if (leftArray->count != rightArray->count) { return false; } + + for (unsigned int i = 0; i < leftArray->count; i++) { + //any mismatch is an easy difference + if (Toy_checkValuesAreEqual(leftArray->data[i], rightArray->data[i])) { + return false; + } + } + } + else { + break; } //finally @@ -216,6 +244,7 @@ bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown types in value equality, exiting\n" TOY_CC_RESET); exit(-1); @@ -225,21 +254,23 @@ bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right) { } bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right) { - //NOTE: "equal" and "comparable" are different - equal means they're identical, comparable is only possible for certain types + left = Toy_unwrapValue(left); + right = Toy_unwrapValue(right); + //NOTE: "equal" and "comparable" are different - equal means they're identical, comparable is only possible for certain types switch(left.type) { case TOY_VALUE_NULL: return false; case TOY_VALUE_BOOLEAN: - return TOY_VALUE_IS_BOOLEAN(right); + return right.type == TOY_VALUE_BOOLEAN; case TOY_VALUE_INTEGER: case TOY_VALUE_FLOAT: - return TOY_VALUE_IS_INTEGER(right) || TOY_VALUE_IS_FLOAT(right); + return right.type == TOY_VALUE_INTEGER || right.type == TOY_VALUE_FLOAT; case TOY_VALUE_STRING: - return TOY_VALUE_IS_STRING(right); + return right.type == TOY_VALUE_STRING; case TOY_VALUE_ARRAY: //nothing is comparable with an array @@ -250,6 +281,7 @@ bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: fprintf(stderr, TOY_CC_ERROR "Unknown types in value comparison check, exiting\n" TOY_CC_RESET); exit(-1); @@ -259,6 +291,9 @@ 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); + //comparison means there's a difference in value, with some kind of quantity - so null, bool, etc. aren't comparable switch(left.type) { case TOY_VALUE_NULL: @@ -266,30 +301,30 @@ int Toy_compareValues(Toy_Value left, Toy_Value right) { break; case TOY_VALUE_INTEGER: - if (TOY_VALUE_IS_INTEGER(right)) { - return TOY_VALUE_AS_INTEGER(left) - TOY_VALUE_AS_INTEGER(right); + if (right.type == TOY_VALUE_INTEGER) { + return left.as.integer - right.as.integer; } - else if (TOY_VALUE_IS_FLOAT(right)) { - return TOY_VALUE_AS_INTEGER(left) - TOY_VALUE_AS_FLOAT(right); + else if (right.type == TOY_VALUE_FLOAT) { + return left.as.integer - right.as.number; } else { break; } case TOY_VALUE_FLOAT: - if (TOY_VALUE_IS_INTEGER(right)) { - return TOY_VALUE_AS_FLOAT(left) - TOY_VALUE_AS_INTEGER(right); + if (right.type == TOY_VALUE_INTEGER) { + return left.as.number - right.as.integer; } - else if (TOY_VALUE_IS_FLOAT(right)) { - return TOY_VALUE_AS_FLOAT(left) - TOY_VALUE_AS_FLOAT(right); + else if (right.type == TOY_VALUE_FLOAT) { + return left.as.number - right.as.number; } else { break; } case TOY_VALUE_STRING: - if (TOY_VALUE_IS_STRING(right)) { - return Toy_compareStrings(TOY_VALUE_AS_STRING(left), TOY_VALUE_AS_STRING(right)); + if (right.type == TOY_VALUE_STRING) { + return Toy_compareStrings(left.as.string, right.as.string); } case TOY_VALUE_ARRAY: @@ -300,15 +335,20 @@ int Toy_compareValues(Toy_Value left, Toy_Value right) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: - fprintf(stderr, TOY_CC_ERROR "Unknown types in value comparison, exiting\n" TOY_CC_RESET); - exit(-1); + break; } - return -1; + fprintf(stderr, TOY_CC_ERROR "Unknown types in value comparison, exiting\n" TOY_CC_RESET); + exit(-1); + + return ~0; } Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) { + value = Toy_unwrapValue(value); + //TODO: could have "constant" strings that can be referenced, instead of null, true, false, etc. switch(value.type) { @@ -316,18 +356,18 @@ Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) { return Toy_createString(bucketHandle, "null"); case TOY_VALUE_BOOLEAN: - return Toy_createString(bucketHandle, TOY_VALUE_AS_BOOLEAN(value) ? "true" : "false"); + return Toy_createString(bucketHandle, value.as.boolean ? "true" : "false"); case TOY_VALUE_INTEGER: { char buffer[16]; - sprintf(buffer, "%d", TOY_VALUE_AS_INTEGER(value)); + sprintf(buffer, "%d", value.as.integer); return Toy_createString(bucketHandle, buffer); } case TOY_VALUE_FLOAT: { //using printf char buffer[16]; - sprintf(buffer, "%f", TOY_VALUE_AS_FLOAT(value)); + sprintf(buffer, "%f", value.as.number); //BUGFIX: printf format specificer '%f' will set the precision to 6 decimal places, which means there's trailing zeroes unsigned int length = strlen(buffer); @@ -343,28 +383,33 @@ Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) { } case TOY_VALUE_STRING: - return Toy_copyString(TOY_VALUE_AS_STRING(value)); + return Toy_copyString(value.as.string); case TOY_VALUE_ARRAY: { - //TODO: concat + free is definitely a performance nightmare - Toy_Array* array = TOY_VALUE_AS_ARRAY(value); + //TODO: concat + free is definitely a performance nightmare, could make an append function? + Toy_Array* ptr = value.as.array; Toy_String* string = Toy_createStringLength(bucketHandle, "[", 1); Toy_String* comma = Toy_createStringLength(bucketHandle, ",", 1); //reusable - for (unsigned int i = 0; i < array->count; i++) { + for (unsigned int i = 0; i < ptr->count; i++) { //append each element - Toy_String* tmp = Toy_concatStrings(bucketHandle, string, Toy_stringifyValue(bucketHandle, array->data[i])); //increment ref + Toy_String* tmp = Toy_concatStrings(bucketHandle, string, Toy_stringifyValue(bucketHandle, ptr->data[i])); //increment ref Toy_freeString(string); //decrement ref string = tmp; //if we need a comma - if (i + 1 < array->count) { + if (i + 1 < ptr->count) { Toy_String* tmp = Toy_concatStrings(bucketHandle, string, comma); //increment ref Toy_freeString(string); //decrement ref string = tmp; } } + //closing bracket + Toy_String* tmp = Toy_concatStrings(bucketHandle, string, Toy_createStringLength(bucketHandle, "]", 1)); + Toy_freeString(string); + string = tmp; + //clean up Toy_freeString(comma); //TODO: reusable global, or string type "permanent" @@ -376,6 +421,7 @@ Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) { case TOY_VALUE_OPAQUE: case TOY_VALUE_TYPE: case TOY_VALUE_ANY: + case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: fprintf(stderr, TOY_CC_ERROR "Unknown types in value stringify, exiting\n" TOY_CC_RESET); exit(-1); @@ -397,6 +443,7 @@ const char* Toy_private_getValueTypeAsCString(Toy_ValueType type) { case TOY_VALUE_OPAQUE: return "opaque"; case TOY_VALUE_TYPE: return "type"; case TOY_VALUE_ANY: return "any"; + case TOY_VALUE_REFERENCE: return "reference"; case TOY_VALUE_UNKNOWN: return "unknown"; } diff --git a/source/toy_value.h b/source/toy_value.h index 914bf44..7e43624 100644 --- a/source/toy_value.h +++ b/source/toy_value.h @@ -20,39 +20,45 @@ typedef enum Toy_ValueType { TOY_VALUE_OPAQUE, TOY_VALUE_TYPE, TOY_VALUE_ANY, + + TOY_VALUE_REFERENCE, //not a value itself, but pointing to one TOY_VALUE_UNKNOWN, //The correct type is unknown, but will be determined later } Toy_ValueType; //8 bytes in size -typedef struct Toy_Value { //32 | 64 BITNESS +typedef struct Toy_Value { //32 | 64 BITNESS union { - bool boolean; //1 | 1 - int integer; //4 | 4 - float number; //4 | 4 - struct Toy_String* string; //4 | 8 - struct Toy_Array* array; //4 | 8 + struct Toy_Value* reference; //4 | 8 + bool boolean; //1 | 1 + int integer; //4 | 4 + float number; //4 | 4 + struct Toy_String* string; //4 | 8 + struct Toy_Array* array; //4 | 8 //TODO: more types go here //TODO: consider 'stack' as a possible addition - } as; //4 | 8 - Toy_ValueType type; //4 | 4 -} Toy_Value; //8 | 16 + } as; //4 | 8 -#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) -#define TOY_VALUE_IS_TABLE(value) ((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) + Toy_ValueType type; //4 | 4 +} Toy_Value; //8 | 16 -#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) ((value).as.array) +#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_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) //TODO: more #define TOY_VALUE_FROM_NULL() ((Toy_Value){{ .integer = 0 }, TOY_VALUE_NULL}) @@ -63,7 +69,10 @@ typedef struct Toy_Value { //32 | 64 BITNESS #define TOY_VALUE_FROM_ARRAY(value) ((Toy_Value){{ .array = value }, TOY_VALUE_ARRAY}) //TODO: more +#define TOY_REFERENCE_FROM_POINTER(ptr) ((Toy_Value){{ .reference = ptr }, TOY_VALUE_REFERENCE}) + //utilities +TOY_API Toy_Value Toy_unwrapValue(Toy_Value value); TOY_API unsigned int Toy_hashValue(Toy_Value value); TOY_API Toy_Value Toy_copyValue(Toy_Value value); diff --git a/source/toy_vm.c b/source/toy_vm.c index bd4d3c6..fac11db 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -5,6 +5,7 @@ #include "toy_opcodes.h" #include "toy_value.h" #include "toy_string.h" +#include "toy_array.h" #include #include @@ -90,8 +91,34 @@ static void processRead(Toy_VM* vm) { } case TOY_VALUE_ARRAY: { - // - // break; + fixAlignment(vm); + + //the number of values to read from the stack + unsigned int count = (unsigned int)READ_INT(vm); + unsigned int capacity = count > TOY_ARRAY_INITIAL_CAPACITY ? count : TOY_ARRAY_INITIAL_CAPACITY; + + //neat trick to find the next power of two, inclusive (restriction of the array system) TODO: move this into a function + capacity--; + capacity |= capacity >> 1; + capacity |= capacity >> 2; + capacity |= capacity >> 4; + capacity |= capacity >> 8; + capacity |= capacity >> 16; + capacity++; + + //create the array and read in the values + Toy_Array* array = Toy_resizeArray(NULL, capacity); + array->capacity = capacity; + array->count = count; + + for (int i = count - 1; i >= 0; i--) { //read in backwards from the stack + array->data[i] = Toy_popStack(&vm->stack); + } + + //finished + value = TOY_VALUE_FROM_ARRAY(array); + + break; } case TOY_VALUE_TABLE: { @@ -174,6 +201,8 @@ static void processAssign(Toy_VM* vm) { //assign it Toy_assignScope(vm->scope, TOY_VALUE_AS_STRING(name), value); + //URGENT: complex assignments + //cleanup Toy_freeValue(name); } @@ -187,9 +216,20 @@ static void processAccess(Toy_VM* vm) { return; } - //find and push the value - Toy_Value value = Toy_accessScope(vm->scope, TOY_VALUE_AS_STRING(name)); - Toy_pushStack(&vm->stack, Toy_copyValue(value)); + //find the value + Toy_Value* valuePtr = Toy_accessScopeAsPointer(vm->scope, TOY_VALUE_AS_STRING(name)); + + //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)) { + //TODO: more types to be implemented + Toy_Value ref = TOY_REFERENCE_FROM_POINTER(valuePtr); + + Toy_pushStack(&vm->stack, ref); + } + + else { + Toy_pushStack(&vm->stack, Toy_copyValue(*valuePtr)); + } //cleanup Toy_freeValue(name); @@ -198,7 +238,6 @@ static void processAccess(Toy_VM* vm) { static void processDuplicate(Toy_VM* vm) { Toy_Value value = Toy_copyValue(Toy_peekStack(&vm->stack)); Toy_pushStack(&vm->stack, value); - Toy_freeValue(value); //check for compound assignments Toy_OpcodeType squeezed = READ_BYTE(vm); @@ -216,8 +255,15 @@ static void processArithmetic(Toy_VM* vm, Toy_OpcodeType opcode) { char buffer[256]; snprintf(buffer, 256, "Invalid types '%s' and '%s' passed in arithmetic", Toy_private_getValueTypeAsCString(left.type), Toy_private_getValueTypeAsCString(right.type)); Toy_error(buffer); - Toy_freeValue(left); - Toy_freeValue(right); + + if (TOY_VALUE_IS_REFERENCE(left) != true) { + Toy_freeValue(left); + } + + if (TOY_VALUE_IS_REFERENCE(right) != true) { + Toy_freeValue(right); + } + return; } @@ -297,17 +343,30 @@ static void processComparison(Toy_VM* vm, Toy_OpcodeType opcode) { Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(!equal) ); } - Toy_freeValue(left); - Toy_freeValue(right); + if (TOY_VALUE_IS_REFERENCE(left) != true) { + Toy_freeValue(left); + } + + if (TOY_VALUE_IS_REFERENCE(right) != true) { + Toy_freeValue(right); + } + return; } - if (Toy_checkValuesAreComparable(left, right) == false) { + if (Toy_checkValuesAreComparable(left, right) != true) { char buffer[256]; snprintf(buffer, 256, "Can't compare value types '%s' and '%s'", Toy_private_getValueTypeAsCString(left.type), Toy_private_getValueTypeAsCString(right.type)); Toy_error(buffer); - Toy_freeValue(left); - Toy_freeValue(right); + + if (TOY_VALUE_IS_REFERENCE(left) != true) { + Toy_freeValue(left); + } + + if (TOY_VALUE_IS_REFERENCE(right) != true) { + Toy_freeValue(right); + } + return; } @@ -333,8 +392,13 @@ static void processComparison(Toy_VM* vm, Toy_OpcodeType opcode) { Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(false)); } - Toy_freeValue(left); - Toy_freeValue(right); + if (TOY_VALUE_IS_REFERENCE(left) != true) { + Toy_freeValue(left); + } + + if (TOY_VALUE_IS_REFERENCE(right) != true) { + Toy_freeValue(right); + } } static void processLogical(Toy_VM* vm, Toy_OpcodeType opcode) { @@ -382,20 +446,29 @@ static void processJump(Toy_VM* vm) { case TOY_OP_PARAM_JUMP_IF_TRUE: { Toy_Value value = Toy_popStack(&vm->stack); if (Toy_checkValueIsTruthy(value) == true) { - Toy_freeValue(value); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } break; } - Toy_freeValue(value); + + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } return; } case TOY_OP_PARAM_JUMP_IF_FALSE: { Toy_Value value = Toy_popStack(&vm->stack); if (Toy_checkValueIsTruthy(value) != true) { - Toy_freeValue(value); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } break; } - Toy_freeValue(value); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } return; } } @@ -433,7 +506,7 @@ static void processAssert(Toy_VM* vm) { } //do the check - if (TOY_VALUE_IS_NULL(value) || Toy_checkValueIsTruthy(value) == false) { + if (TOY_VALUE_IS_NULL(value) || Toy_checkValueIsTruthy(value) != true) { //on a failure, print the message Toy_String* string = Toy_stringifyValue(&vm->stringBucket, message); char* buffer = Toy_getStringRawBuffer(string); @@ -446,8 +519,13 @@ static void processAssert(Toy_VM* vm) { } //cleanup - Toy_freeValue(value); - Toy_freeValue(message); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } + + if (TOY_VALUE_IS_REFERENCE(message) != true) { + Toy_freeValue(message); + } } static void processPrint(Toy_VM* vm) { @@ -460,7 +538,10 @@ static void processPrint(Toy_VM* vm) { free(buffer); Toy_freeString(string); - Toy_freeValue(value); + + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } } static void processConcat(Toy_VM* vm) { @@ -469,6 +550,13 @@ static void processConcat(Toy_VM* vm) { if (!TOY_VALUE_IS_STRING(left) || !TOY_VALUE_IS_STRING(right)) { Toy_error("Failed to concatenate a value that is not a string"); + + if (TOY_VALUE_IS_REFERENCE(left) != true) { + Toy_freeValue(left); + } + if (TOY_VALUE_IS_REFERENCE(right) != true) { + Toy_freeValue(right); + } return; } @@ -495,7 +583,7 @@ static void processIndex(Toy_VM* vm) { } else { Toy_error("Incorrect number of elements found in index"); - //TODO: clear stack + //URGENT: clear stack, then leave null return; } @@ -504,26 +592,53 @@ static void processIndex(Toy_VM* vm) { //type checks if (!TOY_VALUE_IS_INTEGER(index)) { Toy_error("Failed to index a string"); - Toy_freeValue(value); - Toy_freeValue(index); - Toy_freeValue(length); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } + if (TOY_VALUE_IS_REFERENCE(index) != true) { + Toy_freeValue(index); + } + if (TOY_VALUE_IS_REFERENCE(length) != true) { + Toy_freeValue(length); + } return; } if (!(TOY_VALUE_IS_NULL(length) || TOY_VALUE_IS_INTEGER(length))) { Toy_error("Failed to index-length a string"); - Toy_freeValue(value); - Toy_freeValue(index); - Toy_freeValue(length); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } + if (TOY_VALUE_IS_REFERENCE(index) != true) { + Toy_freeValue(index); + } + if (TOY_VALUE_IS_REFERENCE(length) != true) { + Toy_freeValue(length); + } return; } //extract values int i = TOY_VALUE_AS_INTEGER(index); int l = TOY_VALUE_IS_INTEGER(length) ? TOY_VALUE_AS_INTEGER(length) : 1; + Toy_String* str = TOY_VALUE_AS_STRING(value); + + //check indexing is within bounds + if ( (i < 0 || i >= str->length) || (i+l <= 0 || i+l > str->length)) { + Toy_error("String index is out of bounds"); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } + if (TOY_VALUE_IS_REFERENCE(index) != true) { + Toy_freeValue(index); + } + if (TOY_VALUE_IS_REFERENCE(length) != true) { + Toy_freeValue(length); + } + return; + } //extract string - Toy_String* str = TOY_VALUE_AS_STRING(value); Toy_String* result = NULL; //extract cstring, based on type @@ -545,14 +660,83 @@ static void processIndex(Toy_VM* vm) { Toy_pushStack(&vm->stack, TOY_VALUE_FROM_STRING(result)); } + else if (TOY_VALUE_IS_ARRAY(value)) { + //type checks + if (!TOY_VALUE_IS_INTEGER(index)) { + Toy_error("Failed to index a string"); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } + if (TOY_VALUE_IS_REFERENCE(index) != true) { + Toy_freeValue(index); + } + if (TOY_VALUE_IS_REFERENCE(length) != true) { + Toy_freeValue(length); + } + return; + } + + if (!(TOY_VALUE_IS_NULL(length) || TOY_VALUE_IS_INTEGER(length))) { + Toy_error("Failed to index-length a string"); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } + if (TOY_VALUE_IS_REFERENCE(index) != true) { + Toy_freeValue(index); + } + if (TOY_VALUE_IS_REFERENCE(length) != true) { + Toy_freeValue(length); + } + return; + } + + //extract values + int i = TOY_VALUE_AS_INTEGER(index); + int l = TOY_VALUE_IS_INTEGER(length) ? TOY_VALUE_AS_INTEGER(length) : 1; + Toy_Array* array = TOY_VALUE_AS_ARRAY(value); + + //check indexing is within bounds + if ( (i < 0 || i >= array->count) || (i+l <= 0 || i+l > array->count)) { + Toy_error("Array index is out of bounds"); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } + if (TOY_VALUE_IS_REFERENCE(index) != true) { + Toy_freeValue(index); + } + if (TOY_VALUE_IS_REFERENCE(length) != true) { + Toy_freeValue(length); + } + 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(array->data[i]) || TOY_VALUE_IS_ARRAY(array->data[i])) { + //TODO: more types to be implemented + 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])); + } + } + else { fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown value type '%s' found in processIndex, exiting\n" TOY_CC_RESET, Toy_private_getValueTypeAsCString(value.type)); exit(-1); } - Toy_freeValue(value); - Toy_freeValue(index); - Toy_freeValue(length); + if (TOY_VALUE_IS_REFERENCE(value) != true) { + Toy_freeValue(value); + } + if (TOY_VALUE_IS_REFERENCE(index) != true) { + Toy_freeValue(index); + } + if (TOY_VALUE_IS_REFERENCE(length) != true) { + Toy_freeValue(length); + } } static void process(Toy_VM* vm) { diff --git a/tests/cases/test_ast.c b/tests/cases/test_ast.c index cb75698..bcc115f 100644 --- a/tests/cases/test_ast.c +++ b/tests/cases/test_ast.c @@ -23,7 +23,8 @@ int test_sizeof_ast_64bit() { TEST_SIZEOF(Toy_AstBinary, 24); TEST_SIZEOF(Toy_AstCompare, 24); TEST_SIZEOF(Toy_AstGroup, 16); - TEST_SIZEOF(Toy_AstCompound, 24); + TEST_SIZEOF(Toy_AstCompound, 16); + TEST_SIZEOF(Toy_AstAggregate, 24); TEST_SIZEOF(Toy_AstAssert, 24); TEST_SIZEOF(Toy_AstIfThenElse, 32); TEST_SIZEOF(Toy_AstWhileThen, 24); @@ -61,7 +62,8 @@ int test_sizeof_ast_32bit() { TEST_SIZEOF(Toy_AstBinary, 16); TEST_SIZEOF(Toy_AstCompare, 16); TEST_SIZEOF(Toy_AstGroup, 8); - TEST_SIZEOF(Toy_AstCompound, 16); + TEST_SIZEOF(Toy_AstCompound, 12); + TEST_SIZEOF(Toy_AstAggregate, 16); TEST_SIZEOF(Toy_AstAssert, 12); TEST_SIZEOF(Toy_AstIfThenElse, 16); TEST_SIZEOF(Toy_AstWhileThen, 12); @@ -194,33 +196,33 @@ int test_type_emission(Toy_Bucket** bucketHandle) { } } - //emit compound + //emit aggregate { //build the AST Toy_Ast* ast = NULL; Toy_Ast* right = NULL; Toy_private_emitAstValue(bucketHandle, &ast, TOY_VALUE_FROM_INTEGER(42)); Toy_private_emitAstValue(bucketHandle, &right, TOY_VALUE_FROM_INTEGER(69)); - Toy_private_emitAstCompound(bucketHandle, &ast, TOY_AST_FLAG_COMPOUND_COLLECTION, right); + Toy_private_emitAstAggregate(bucketHandle, &ast, TOY_AST_FLAG_COLLECTION, right); //check if it worked if ( ast == NULL || - ast->type != TOY_AST_COMPOUND || + ast->type != TOY_AST_AGGREGATE || - ast->compound.left == NULL || - ast->compound.left->type != TOY_AST_VALUE || - TOY_VALUE_IS_INTEGER(ast->compound.left->value.value) != true || - TOY_VALUE_AS_INTEGER(ast->compound.left->value.value) != 42 || + ast->aggregate.left == NULL || + ast->aggregate.left->type != TOY_AST_VALUE || + TOY_VALUE_IS_INTEGER(ast->aggregate.left->value.value) != true || + TOY_VALUE_AS_INTEGER(ast->aggregate.left->value.value) != 42 || - ast->compound.right == NULL || - ast->compound.right->type != TOY_AST_VALUE || - TOY_VALUE_IS_INTEGER(ast->compound.right->value.value) != true || - TOY_VALUE_AS_INTEGER(ast->compound.right->value.value) != 69 || + ast->aggregate.right == NULL || + ast->aggregate.right->type != TOY_AST_VALUE || + TOY_VALUE_IS_INTEGER(ast->aggregate.right->value.value) != true || + TOY_VALUE_AS_INTEGER(ast->aggregate.right->value.value) != 69 || false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to emit a compound as 'Toy_Ast', state unknown\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to emit an aggregate as 'Toy_Ast', state unknown\n" TOY_CC_RESET); return -1; } } diff --git a/tests/cases/test_parser.c b/tests/cases/test_parser.c index 9f95dcc..c7f4267 100644 --- a/tests/cases/test_parser.c +++ b/tests/cases/test_parser.c @@ -455,7 +455,7 @@ int test_binary(Toy_Bucket** bucketHandle) { return 0; } -int test_compound(Toy_Bucket** bucketHandle) { +int test_aggregate(Toy_Bucket** bucketHandle) { //test collections (do it first, because it's used below) { char* source = "1, 2, 3;"; @@ -467,27 +467,27 @@ int test_compound(Toy_Bucket** bucketHandle) { ast->type != TOY_AST_BLOCK || ast->block.child == NULL || - ast->block.child->type != TOY_AST_COMPOUND || - ast->block.child->compound.flag != TOY_AST_FLAG_COMPOUND_COLLECTION || + ast->block.child->type != TOY_AST_AGGREGATE || + ast->block.child->aggregate.flag != TOY_AST_FLAG_COLLECTION || - ast->block.child->compound.left == NULL || - ast->block.child->compound.left->type != TOY_AST_VALUE || - TOY_VALUE_IS_INTEGER(ast->block.child->compound.left->value.value) != true || - TOY_VALUE_AS_INTEGER(ast->block.child->compound.left->value.value) != 1 || + ast->block.child->aggregate.left == NULL || + ast->block.child->aggregate.left->type != TOY_AST_VALUE || + TOY_VALUE_IS_INTEGER(ast->block.child->aggregate.left->value.value) != true || + TOY_VALUE_AS_INTEGER(ast->block.child->aggregate.left->value.value) != 1 || - ast->block.child->compound.right == NULL || - ast->block.child->compound.right->type != TOY_AST_COMPOUND || - ast->block.child->compound.right->compound.flag != TOY_AST_FLAG_COMPOUND_COLLECTION || + ast->block.child->aggregate.right == NULL || + ast->block.child->aggregate.right->type != TOY_AST_AGGREGATE || + ast->block.child->aggregate.right->aggregate.flag != TOY_AST_FLAG_COLLECTION || - ast->block.child->compound.right->compound.left == NULL || - ast->block.child->compound.right->compound.left->type != TOY_AST_VALUE || - TOY_VALUE_IS_INTEGER(ast->block.child->compound.right->compound.left->value.value) != true || - TOY_VALUE_AS_INTEGER(ast->block.child->compound.right->compound.left->value.value) != 2 || + ast->block.child->aggregate.right->aggregate.left == NULL || + ast->block.child->aggregate.right->aggregate.left->type != TOY_AST_VALUE || + TOY_VALUE_IS_INTEGER(ast->block.child->aggregate.right->aggregate.left->value.value) != true || + TOY_VALUE_AS_INTEGER(ast->block.child->aggregate.right->aggregate.left->value.value) != 2 || - ast->block.child->compound.right->compound.right == NULL || - ast->block.child->compound.right->compound.right->type != TOY_AST_VALUE || - TOY_VALUE_IS_INTEGER(ast->block.child->compound.right->compound.right->value.value) != true || - TOY_VALUE_AS_INTEGER(ast->block.child->compound.right->compound.right->value.value) != 3 || + ast->block.child->aggregate.right->aggregate.right == NULL || + ast->block.child->aggregate.right->aggregate.right->type != TOY_AST_VALUE || + TOY_VALUE_IS_INTEGER(ast->block.child->aggregate.right->aggregate.right->value.value) != true || + TOY_VALUE_AS_INTEGER(ast->block.child->aggregate.right->aggregate.right->value.value) != 3 || false) { @@ -507,17 +507,17 @@ int test_compound(Toy_Bucket** bucketHandle) { ast->type != TOY_AST_BLOCK || ast->block.child == NULL || - ast->block.child->type != TOY_AST_COMPOUND || - ast->block.child->compound.flag != TOY_AST_FLAG_COMPOUND_INDEX || + ast->block.child->type != TOY_AST_AGGREGATE || + ast->block.child->aggregate.flag != TOY_AST_FLAG_INDEX || - ast->block.child->compound.left == NULL || - ast->block.child->compound.left->type != TOY_AST_VAR_ACCESS || - ast->block.child->compound.left->varAccess.name->type != TOY_STRING_NAME || - strcmp(ast->block.child->compound.left->varAccess.name->as.name.data, "name") != 0 || + ast->block.child->aggregate.left == NULL || + ast->block.child->aggregate.left->type != TOY_AST_VAR_ACCESS || + ast->block.child->aggregate.left->varAccess.name->type != TOY_STRING_NAME || + strcmp(ast->block.child->aggregate.left->varAccess.name->as.name.data, "name") != 0 || - ast->block.child->compound.right->type != TOY_AST_VALUE || - TOY_VALUE_IS_INTEGER(ast->block.child->compound.right->value.value) != true || - TOY_VALUE_AS_INTEGER(ast->block.child->compound.right->value.value) != 0 || + ast->block.child->aggregate.right->type != TOY_AST_VALUE || + TOY_VALUE_IS_INTEGER(ast->block.child->aggregate.right->value.value) != true || + TOY_VALUE_AS_INTEGER(ast->block.child->aggregate.right->value.value) != 0 || false) { @@ -537,23 +537,23 @@ int test_compound(Toy_Bucket** bucketHandle) { ast->type != TOY_AST_BLOCK || ast->block.child == NULL || - ast->block.child->type != TOY_AST_COMPOUND || - ast->block.child->compound.flag != TOY_AST_FLAG_COMPOUND_INDEX || + ast->block.child->type != TOY_AST_AGGREGATE || + ast->block.child->aggregate.flag != TOY_AST_FLAG_INDEX || - ast->block.child->compound.left == NULL || - ast->block.child->compound.left->type != TOY_AST_VAR_ACCESS || - ast->block.child->compound.left->varAccess.name->type != TOY_STRING_NAME || - strcmp(ast->block.child->compound.left->varAccess.name->as.name.data, "name") != 0 || + ast->block.child->aggregate.left == NULL || + ast->block.child->aggregate.left->type != TOY_AST_VAR_ACCESS || + ast->block.child->aggregate.left->varAccess.name->type != TOY_STRING_NAME || + strcmp(ast->block.child->aggregate.left->varAccess.name->as.name.data, "name") != 0 || - ast->block.child->compound.right->type != TOY_AST_COMPOUND || - ast->block.child->compound.right->compound.flag != TOY_AST_FLAG_COMPOUND_COLLECTION || - ast->block.child->compound.right->compound.left->type != TOY_AST_VALUE || + ast->block.child->aggregate.right->type != TOY_AST_AGGREGATE || + ast->block.child->aggregate.right->aggregate.flag != TOY_AST_FLAG_COLLECTION || + ast->block.child->aggregate.right->aggregate.left->type != TOY_AST_VALUE || - TOY_VALUE_IS_INTEGER(ast->block.child->compound.right->compound.left->value.value) != true || - TOY_VALUE_AS_INTEGER(ast->block.child->compound.right->compound.left->value.value) != 0 || + TOY_VALUE_IS_INTEGER(ast->block.child->aggregate.right->aggregate.left->value.value) != true || + TOY_VALUE_AS_INTEGER(ast->block.child->aggregate.right->aggregate.left->value.value) != 0 || - TOY_VALUE_IS_INTEGER(ast->block.child->compound.right->compound.right->value.value) != true || - TOY_VALUE_AS_INTEGER(ast->block.child->compound.right->compound.right->value.value) != 1 || + TOY_VALUE_IS_INTEGER(ast->block.child->aggregate.right->aggregate.right->value.value) != true || + TOY_VALUE_AS_INTEGER(ast->block.child->aggregate.right->aggregate.right->value.value) != 1 || false) { @@ -927,7 +927,7 @@ int main() { { Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - res = test_compound(&bucket); + res = test_aggregate(&bucket); Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); diff --git a/tests/cases/test_scope.c b/tests/cases/test_scope.c index e612c81..bcaf9d3 100644 --- a/tests/cases/test_scope.c +++ b/tests/cases/test_scope.c @@ -329,7 +329,7 @@ int test_scope_elements() { return -1; } - Toy_Value result = Toy_accessScope(scope, hello2); + Toy_Value* result = Toy_accessScopeAsPointer(scope, hello2); //check integer if (scope == NULL || @@ -338,8 +338,8 @@ int test_scope_elements() { scope->table->capacity != 8 || scope->refCount != 1 || - TOY_VALUE_IS_INTEGER(result) != true || - TOY_VALUE_AS_INTEGER(result) != 42 || + TOY_VALUE_IS_INTEGER(*result) != true || + TOY_VALUE_AS_INTEGER(*result) != 42 || false) { @@ -354,7 +354,7 @@ int test_scope_elements() { //assign values Toy_assignScope(scope, hello1, TOY_VALUE_FROM_FLOAT(3.1415f)); - Toy_Value resultTwo = Toy_accessScope(scope, hello2); + Toy_Value* resultTwo = Toy_accessScopeAsPointer(scope, hello2); //check float if (scope == NULL || @@ -363,8 +363,8 @@ int test_scope_elements() { scope->table->capacity != 8 || scope->refCount != 1 || - TOY_VALUE_IS_FLOAT(resultTwo) != true || - TOY_VALUE_AS_FLOAT(resultTwo) != 3.1415f || + TOY_VALUE_IS_FLOAT(*resultTwo) != true || + TOY_VALUE_AS_FLOAT(*resultTwo) != 3.1415f || false) { @@ -399,10 +399,10 @@ int test_scope_elements() { { //check it's accessible - Toy_Value result1 = Toy_accessScope(scope, hello); + Toy_Value* result1 = Toy_accessScopeAsPointer(scope, hello); - if (TOY_VALUE_IS_INTEGER(result1) != true || - TOY_VALUE_AS_INTEGER(result1) != 42) + if (TOY_VALUE_IS_INTEGER(*result1) != true || + TOY_VALUE_AS_INTEGER(*result1) != 42) { fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to access from an ancestor Toy_Scope\n" TOY_CC_RESET); Toy_freeString(hello); @@ -416,10 +416,10 @@ int test_scope_elements() { { //check it's shadowed correctly - Toy_Value result2 = Toy_accessScope(scope, hello); + Toy_Value* result2 = Toy_accessScopeAsPointer(scope, hello); - if (TOY_VALUE_IS_FLOAT(result2) != true || - TOY_VALUE_AS_FLOAT(result2) != 3.1415f) + if (TOY_VALUE_IS_FLOAT(*result2) != true || + TOY_VALUE_AS_FLOAT(*result2) != 3.1415f) { fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to shadow an entry in Toy_Scope\n" TOY_CC_RESET); Toy_freeString(hello); @@ -433,10 +433,10 @@ int test_scope_elements() { { //check it's recovered correctly - Toy_Value result3 = Toy_accessScope(scope, hello); + Toy_Value* result3 = Toy_accessScopeAsPointer(scope, hello); - if (TOY_VALUE_IS_INTEGER(result3) != true || - TOY_VALUE_AS_INTEGER(result3) != 42) + if (TOY_VALUE_IS_INTEGER(*result3) != true || + TOY_VALUE_AS_INTEGER(*result3) != 42) { fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to recover an entry in Toy_Scope\n" TOY_CC_RESET); Toy_freeString(hello); @@ -450,10 +450,10 @@ int test_scope_elements() { { //check it's assigned correctly - Toy_Value result4 = Toy_accessScope(scope, hello); + Toy_Value* result4 = Toy_accessScopeAsPointer(scope, hello); - if (TOY_VALUE_IS_INTEGER(result4) != true || - TOY_VALUE_AS_INTEGER(result4) != 8891) + if (TOY_VALUE_IS_INTEGER(*result4) != true || + TOY_VALUE_AS_INTEGER(*result4) != 8891) { fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to assign to an ancestor in Toy_Scope\n" TOY_CC_RESET); Toy_freeString(hello); @@ -467,10 +467,10 @@ int test_scope_elements() { { //check it's in the correct state - Toy_Value result5 = Toy_accessScope(scope, hello); + Toy_Value* result5 = Toy_accessScopeAsPointer(scope, hello); - if (TOY_VALUE_IS_INTEGER(result5) != true || - TOY_VALUE_AS_INTEGER(result5) != 8891) + if (TOY_VALUE_IS_INTEGER(*result5) != true || + TOY_VALUE_AS_INTEGER(*result5) != 8891) { fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to access an altered entry of an ancestor in Toy_Scope\n" TOY_CC_RESET); Toy_freeString(hello); diff --git a/tests/cases/test_vm.c b/tests/cases/test_vm.c index 173629d..daaa1c5 100644 --- a/tests/cases/test_vm.c +++ b/tests/cases/test_vm.c @@ -663,8 +663,8 @@ int test_scope(Toy_Bucket** bucketHandle) { vm.scope == NULL || Toy_isDeclaredScope(vm.scope, key) == false || - TOY_VALUE_IS_INTEGER(Toy_accessScope(vm.scope, key)) != true || - TOY_VALUE_AS_INTEGER(Toy_accessScope(vm.scope, key)) != 42 + TOY_VALUE_IS_INTEGER(*Toy_accessScopeAsPointer(vm.scope, key)) != true || + TOY_VALUE_AS_INTEGER(*Toy_accessScopeAsPointer(vm.scope, key)) != 42 ) { @@ -712,7 +712,7 @@ int test_scope(Toy_Bucket** bucketHandle) { vm.scope == NULL || Toy_isDeclaredScope(vm.scope, key) == false || - TOY_VALUE_IS_NULL(Toy_accessScope(vm.scope, key)) != true + TOY_VALUE_IS_NULL(*Toy_accessScopeAsPointer(vm.scope, key)) != true ) { fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected result in 'Toy_VM' when testing scope, source: %s\n" TOY_CC_RESET, source);