mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Finished if-then-else tests, finally.
This commit is contained in:
@@ -842,9 +842,6 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) {
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: implement test if-then
|
|
||||||
//TODO: implement test if-then-else
|
|
||||||
|
|
||||||
//if-then
|
//if-then
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
@@ -936,6 +933,121 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) {
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if-then-else
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
const char* source = "if (true) print \"hello world\"; else print \"goodbye world\";";
|
||||||
|
Toy_Lexer lexer;
|
||||||
|
Toy_Parser parser;
|
||||||
|
|
||||||
|
Toy_bindLexer(&lexer, source);
|
||||||
|
Toy_bindParser(&parser, &lexer);
|
||||||
|
Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser);
|
||||||
|
|
||||||
|
//run
|
||||||
|
void* buffer = Toy_compileRoutine(ast);
|
||||||
|
int len = ((int*)buffer)[0];
|
||||||
|
|
||||||
|
//check header
|
||||||
|
int* ptr = (int*)buffer;
|
||||||
|
|
||||||
|
if ((ptr++)[0] != 116 || //total size
|
||||||
|
(ptr++)[0] != 0 || //param count
|
||||||
|
(ptr++)[0] != 8 || //jump count
|
||||||
|
(ptr++)[0] != 28 || //data count
|
||||||
|
(ptr++)[0] != 0 || //subs count
|
||||||
|
|
||||||
|
(ptr++)[0] != 32 || //code addr
|
||||||
|
(ptr++)[0] != 80 || //jump addr
|
||||||
|
(ptr++)[0] != 88 || //data addr
|
||||||
|
|
||||||
|
//header size: 32
|
||||||
|
|
||||||
|
false)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
|
//cleanup and return
|
||||||
|
free(buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check code
|
||||||
|
if (//cond
|
||||||
|
*((unsigned char*)(buffer + 32)) != TOY_OPCODE_READ ||
|
||||||
|
*((unsigned char*)(buffer + 33)) != TOY_VALUE_BOOLEAN ||
|
||||||
|
*((bool*)(buffer + 34)) != true || //bools are packed
|
||||||
|
*((unsigned char*)(buffer + 35)) != 0 ||
|
||||||
|
|
||||||
|
*((unsigned char*)(buffer + 36)) != TOY_OPCODE_JUMP ||
|
||||||
|
*((unsigned char*)(buffer + 37)) != TOY_OP_PARAM_JUMP_RELATIVE ||
|
||||||
|
*((unsigned char*)(buffer + 38)) != TOY_OP_PARAM_JUMP_IF_FALSE ||
|
||||||
|
*((unsigned char*)(buffer + 39)) != 0 ||
|
||||||
|
|
||||||
|
*((int*)(buffer + 40)) != 20 || //param: jump distance (relative)
|
||||||
|
|
||||||
|
//then branch
|
||||||
|
*((unsigned char*)(buffer + 44)) != TOY_OPCODE_READ ||
|
||||||
|
*((unsigned char*)(buffer + 45)) != TOY_VALUE_STRING ||
|
||||||
|
*((unsigned char*)(buffer + 46)) != TOY_STRING_LEAF ||
|
||||||
|
*((unsigned char*)(buffer + 47)) != 0 ||
|
||||||
|
|
||||||
|
*((int*)(buffer + 48)) != 0 || //first indirection
|
||||||
|
|
||||||
|
*((unsigned char*)(buffer + 52)) != TOY_OPCODE_PRINT ||
|
||||||
|
*((unsigned char*)(buffer + 53)) != 0 ||
|
||||||
|
*((unsigned char*)(buffer + 54)) != 0 ||
|
||||||
|
*((unsigned char*)(buffer + 55)) != 0 ||
|
||||||
|
|
||||||
|
//jump to the end
|
||||||
|
*((unsigned char*)(buffer + 56)) != TOY_OPCODE_JUMP ||
|
||||||
|
*((unsigned char*)(buffer + 57)) != TOY_OP_PARAM_JUMP_RELATIVE ||
|
||||||
|
*((unsigned char*)(buffer + 58)) != TOY_OP_PARAM_JUMP_ALWAYS ||
|
||||||
|
*((unsigned char*)(buffer + 59)) != 0 ||
|
||||||
|
|
||||||
|
*((int*)(buffer + 60)) != 12 || //param: jump distance (relative)
|
||||||
|
|
||||||
|
//else branch
|
||||||
|
*((unsigned char*)(buffer + 64)) != TOY_OPCODE_READ ||
|
||||||
|
*((unsigned char*)(buffer + 65)) != TOY_VALUE_STRING ||
|
||||||
|
*((unsigned char*)(buffer + 66)) != TOY_STRING_LEAF ||
|
||||||
|
*((unsigned char*)(buffer + 67)) != 0 ||
|
||||||
|
|
||||||
|
*((int*)(buffer + 68)) != 4 || //second indirection
|
||||||
|
|
||||||
|
*((unsigned char*)(buffer + 72)) != TOY_OPCODE_PRINT ||
|
||||||
|
*((unsigned char*)(buffer + 73)) != 0 ||
|
||||||
|
*((unsigned char*)(buffer + 74)) != 0 ||
|
||||||
|
*((unsigned char*)(buffer + 75)) != 0 ||
|
||||||
|
|
||||||
|
//EOF
|
||||||
|
*((unsigned char*)(buffer + 76)) != TOY_OPCODE_RETURN ||
|
||||||
|
*((unsigned char*)(buffer + 77)) != 0 ||
|
||||||
|
*((unsigned char*)(buffer + 78)) != 0 ||
|
||||||
|
*((unsigned char*)(buffer + 79)) != 0 ||
|
||||||
|
|
||||||
|
//jump region
|
||||||
|
*((int*)(buffer + 80)) != 0 ||
|
||||||
|
*((int*)(buffer + 84)) != 12 ||
|
||||||
|
|
||||||
|
//data region (strings begin at 4-byte words)
|
||||||
|
strcmp((char*)(buffer + 88), "hello world") != 0 ||
|
||||||
|
|
||||||
|
strcmp((char*)(buffer + 100), "goodbye world") != 0 ||
|
||||||
|
|
||||||
|
false)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
|
//cleanup and return
|
||||||
|
free(buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
//print
|
//print
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
|
|||||||
@@ -452,6 +452,185 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) {
|
||||||
|
//test if-then (truthy)
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_setPrintCallback(callbackUtil);
|
||||||
|
const char* source = "if (true) print \"hello world\";";
|
||||||
|
|
||||||
|
Toy_Lexer lexer;
|
||||||
|
Toy_bindLexer(&lexer, source);
|
||||||
|
|
||||||
|
Toy_Parser parser;
|
||||||
|
Toy_bindParser(&parser, &lexer);
|
||||||
|
|
||||||
|
Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser);
|
||||||
|
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||||
|
|
||||||
|
Toy_VM vm;
|
||||||
|
Toy_initVM(&vm);
|
||||||
|
Toy_bindVM(&vm, &bc);
|
||||||
|
|
||||||
|
//run
|
||||||
|
Toy_runVM(&vm);
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (callbackUtilReceived == NULL ||
|
||||||
|
strcmp(callbackUtilReceived, "hello world") != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected value '%s' passed to print in if keyword, source: %s\n" TOY_CC_RESET, callbackUtilReceived != NULL ? callbackUtilReceived : "NULL", source);
|
||||||
|
|
||||||
|
//cleanup and return
|
||||||
|
Toy_resetPrintCallback();
|
||||||
|
free(callbackUtilReceived);
|
||||||
|
Toy_freeVM(&vm);
|
||||||
|
Toy_freeBytecode(bc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//teadown
|
||||||
|
Toy_resetPrintCallback();
|
||||||
|
free(callbackUtilReceived);
|
||||||
|
callbackUtilReceived = NULL;
|
||||||
|
Toy_freeVM(&vm);
|
||||||
|
Toy_freeBytecode(bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//test if-then (falsy)
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_setPrintCallback(callbackUtil);
|
||||||
|
const char* source = "if (false) print \"hello world\";";
|
||||||
|
|
||||||
|
Toy_Lexer lexer;
|
||||||
|
Toy_bindLexer(&lexer, source);
|
||||||
|
|
||||||
|
Toy_Parser parser;
|
||||||
|
Toy_bindParser(&parser, &lexer);
|
||||||
|
|
||||||
|
Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser);
|
||||||
|
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||||
|
|
||||||
|
Toy_VM vm;
|
||||||
|
Toy_initVM(&vm);
|
||||||
|
Toy_bindVM(&vm, &bc);
|
||||||
|
|
||||||
|
//run
|
||||||
|
Toy_runVM(&vm);
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (callbackUtilReceived != NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected value '%s' passed to print in if keyword, source: %s\n" TOY_CC_RESET, callbackUtilReceived != NULL ? callbackUtilReceived : "NULL", source);
|
||||||
|
|
||||||
|
//cleanup and return
|
||||||
|
Toy_resetPrintCallback();
|
||||||
|
free(callbackUtilReceived);
|
||||||
|
Toy_freeVM(&vm);
|
||||||
|
Toy_freeBytecode(bc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//teadown
|
||||||
|
Toy_resetPrintCallback();
|
||||||
|
free(callbackUtilReceived);
|
||||||
|
callbackUtilReceived = NULL;
|
||||||
|
Toy_freeVM(&vm);
|
||||||
|
Toy_freeBytecode(bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//test if-then-else (truthy)
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_setPrintCallback(callbackUtil);
|
||||||
|
const char* source = "if (true) print \"hello world\"; else print \"failed\";";
|
||||||
|
|
||||||
|
Toy_Lexer lexer;
|
||||||
|
Toy_bindLexer(&lexer, source);
|
||||||
|
|
||||||
|
Toy_Parser parser;
|
||||||
|
Toy_bindParser(&parser, &lexer);
|
||||||
|
|
||||||
|
Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser);
|
||||||
|
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||||
|
|
||||||
|
Toy_VM vm;
|
||||||
|
Toy_initVM(&vm);
|
||||||
|
Toy_bindVM(&vm, &bc);
|
||||||
|
|
||||||
|
//run
|
||||||
|
Toy_runVM(&vm);
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (callbackUtilReceived == NULL ||
|
||||||
|
strcmp(callbackUtilReceived, "hello world") != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected value '%s' passed to print in if keyword, source: %s\n" TOY_CC_RESET, callbackUtilReceived != NULL ? callbackUtilReceived : "NULL", source);
|
||||||
|
|
||||||
|
//cleanup and return
|
||||||
|
Toy_resetPrintCallback();
|
||||||
|
free(callbackUtilReceived);
|
||||||
|
Toy_freeVM(&vm);
|
||||||
|
Toy_freeBytecode(bc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//teadown
|
||||||
|
Toy_resetPrintCallback();
|
||||||
|
free(callbackUtilReceived);
|
||||||
|
callbackUtilReceived = NULL;
|
||||||
|
Toy_freeVM(&vm);
|
||||||
|
Toy_freeBytecode(bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//test if-then-else (falsy)
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_setPrintCallback(callbackUtil);
|
||||||
|
const char* source = "if (false) print \"hello world\"; else print \"failed\";";
|
||||||
|
|
||||||
|
Toy_Lexer lexer;
|
||||||
|
Toy_bindLexer(&lexer, source);
|
||||||
|
|
||||||
|
Toy_Parser parser;
|
||||||
|
Toy_bindParser(&parser, &lexer);
|
||||||
|
|
||||||
|
Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser);
|
||||||
|
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||||
|
|
||||||
|
Toy_VM vm;
|
||||||
|
Toy_initVM(&vm);
|
||||||
|
Toy_bindVM(&vm, &bc);
|
||||||
|
|
||||||
|
//run
|
||||||
|
Toy_runVM(&vm);
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (callbackUtilReceived == NULL ||
|
||||||
|
strcmp(callbackUtilReceived, "failed") != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected value '%s' passed to print in if keyword, source: %s\n" TOY_CC_RESET, callbackUtilReceived != NULL ? callbackUtilReceived : "NULL", source);
|
||||||
|
|
||||||
|
//cleanup and return
|
||||||
|
Toy_resetPrintCallback();
|
||||||
|
free(callbackUtilReceived);
|
||||||
|
Toy_freeVM(&vm);
|
||||||
|
Toy_freeBytecode(bc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//teadown
|
||||||
|
Toy_resetPrintCallback();
|
||||||
|
free(callbackUtilReceived);
|
||||||
|
callbackUtilReceived = NULL;
|
||||||
|
Toy_freeVM(&vm);
|
||||||
|
Toy_freeBytecode(bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int test_scope(Toy_Bucket** bucketHandle) {
|
int test_scope(Toy_Bucket** bucketHandle) {
|
||||||
//test declaration with initial value
|
//test declaration with initial value
|
||||||
{
|
{
|
||||||
@@ -681,7 +860,15 @@ int main() {
|
|||||||
total += res;
|
total += res;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: test_ifThenElse()
|
{
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
|
res = test_keyword_ifThenElse(&bucket);
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
if (res == 0) {
|
||||||
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
|
}
|
||||||
|
total += res;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
|
|||||||
Reference in New Issue
Block a user