mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Fixed a 'malformed assignment' issue, read more
I've also added some support for compiler errors in general, but these will get expanded on later. I've also quickly added a valgrind option to the tests and found a few leaks. I'll deal with these later. Summary of changes: * Clarified the lifetime of the bytecode in memory * Erroneous routines exit without compiling * Empty VMs don't run * Added a check for malformed assignments * Renamed "routine" to "module" within the VM * VM no longer tries to free the bytecode - must be done manually * Started experimenting with valgrind, not yet ready
This commit is contained in:
12
makefile
12
makefile
@@ -50,6 +50,18 @@ test-cases-gdb:
|
||||
test-integrations-gdb:
|
||||
$(MAKE) -C $(TOY_INTEGRATIONSDIR) gdb -k
|
||||
|
||||
#same as above, but with valgrind
|
||||
.PHONY: tests-valgrind
|
||||
tests-valgrind: clean test-cases-valgrind test-integrations-valgrind
|
||||
|
||||
.PHONY: test-cases-valgrind
|
||||
test-cases-valgrind:
|
||||
$(MAKE) -C $(TOY_CASESDIR) valgrind -k
|
||||
|
||||
.PHONY: test-integrations-valgrind
|
||||
test-integrations-valgrind:
|
||||
$(MAKE) -C $(TOY_INTEGRATIONSDIR) valgrind -k
|
||||
|
||||
#TODO: mustfail tests
|
||||
|
||||
#util targets
|
||||
|
||||
@@ -311,18 +311,19 @@ int repl(const char* filepath) {
|
||||
}
|
||||
|
||||
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
|
||||
//free the bytecode, and leave the VM ready for the next loop
|
||||
Toy_resetVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
|
||||
printf("%s> ", prompt); //shows the terminal prompt
|
||||
}
|
||||
|
||||
//cleanp all memory
|
||||
//cleanup all memory
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBucket(&bucket);
|
||||
|
||||
@@ -531,7 +532,7 @@ int main(int argc, const char* argv[]) {
|
||||
//run the setup
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -544,6 +545,7 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
//cleanup
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
Toy_freeBucket(&bucket);
|
||||
free(source);
|
||||
}
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
|
||||
1 + 2;
|
||||
//TODO: mustfails
|
||||
var a = 0;
|
||||
var b = a = a + 1, 6;
|
||||
|
||||
|
||||
@@ -57,11 +57,17 @@ static void writeBytecodeBody(Toy_Bytecode* bc, Toy_Ast* ast) {
|
||||
//eventually, the bytecode may support multiple modules packed into one file
|
||||
void* module = Toy_compileRoutine(ast);
|
||||
|
||||
//don't try writing an empty module
|
||||
if (module == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t len = (size_t)(((int*)module)[0]);
|
||||
|
||||
expand(bc, len);
|
||||
memcpy(bc->ptr + bc->count, module, len);
|
||||
bc->count += len;
|
||||
bc->moduleCount++;
|
||||
}
|
||||
|
||||
//exposed functions
|
||||
@@ -73,9 +79,11 @@ Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast) {
|
||||
bc.capacity = 0;
|
||||
bc.count = 0;
|
||||
|
||||
bc.moduleCount = 0;
|
||||
|
||||
//build
|
||||
writeBytecodeHeader(&bc);
|
||||
writeBytecodeBody(&bc, ast);
|
||||
writeBytecodeBody(&bc, ast); //TODO: implement module packing
|
||||
|
||||
return bc;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ typedef struct Toy_Bytecode {
|
||||
unsigned char* ptr;
|
||||
unsigned int capacity;
|
||||
unsigned int count;
|
||||
|
||||
unsigned int moduleCount;
|
||||
} Toy_Bytecode;
|
||||
|
||||
TOY_API Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast);
|
||||
|
||||
@@ -329,6 +329,22 @@ static unsigned int writeInstructionVarDeclare(Toy_Routine** rt, Toy_AstVarDecla
|
||||
static unsigned int writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
||||
unsigned int result = 0;
|
||||
|
||||
//don't treat these as valid values
|
||||
switch (ast.expr->type) {
|
||||
case TOY_AST_BLOCK:
|
||||
case TOY_AST_COMPOUND:
|
||||
case TOY_AST_ASSERT:
|
||||
case TOY_AST_PRINT:
|
||||
case TOY_AST_VAR_DECLARE:
|
||||
//emit a compiler error, set the panic flag and skip out
|
||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Invalid AST type found: Malformed assignment\n" TOY_CC_RESET);
|
||||
(*rt)->panic = true;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//name, duplicate, right, opcode
|
||||
if (ast.flag == TOY_AST_FLAG_ASSIGN) {
|
||||
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
||||
@@ -473,6 +489,11 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//if an error occured, just exit
|
||||
if (rt == NULL || (*rt) == NULL || (*rt)->panic) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int result = 0;
|
||||
|
||||
//determine how to write each instruction based on the Ast
|
||||
@@ -542,19 +563,17 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
||||
|
||||
//meta instructions are disallowed
|
||||
case TOY_AST_PASS:
|
||||
//NOTE: this should be disallowed, but for now it's required for testing
|
||||
// fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST type found: Unknown pass\n" TOY_CC_RESET);
|
||||
// exit(-1);
|
||||
//NOTE: this *should* be disallowed, but for now it's required for testing
|
||||
break;
|
||||
|
||||
case TOY_AST_ERROR:
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST type found: Unknown error\n" TOY_CC_RESET);
|
||||
exit(-1);
|
||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Invalid AST type found: Unknown 'error'\n" TOY_CC_RESET);
|
||||
(*rt)->panic = true;
|
||||
break;
|
||||
|
||||
case TOY_AST_END:
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST type found: Unknown end\n" TOY_CC_RESET);
|
||||
exit(-1);
|
||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Invalid AST type found: Unknown 'end'\n" TOY_CC_RESET);
|
||||
(*rt)->panic = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -562,8 +581,6 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
||||
}
|
||||
|
||||
static void* writeRoutine(Toy_Routine* rt, Toy_Ast* ast) {
|
||||
//build the routine's parts
|
||||
//TODO: param
|
||||
//code
|
||||
writeRoutineCode(&rt, ast);
|
||||
EMIT_BYTE(&rt, code, TOY_OPCODE_RETURN); //temp terminator
|
||||
@@ -571,6 +588,11 @@ static void* writeRoutine(Toy_Routine* rt, Toy_Ast* ast) {
|
||||
EMIT_BYTE(&rt, code, 0);
|
||||
EMIT_BYTE(&rt, code, 0);
|
||||
|
||||
//if an error occurred, just exit
|
||||
if (rt->panic) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//write the header and combine the parts
|
||||
void* buffer = NULL;
|
||||
unsigned int capacity = 0, count = 0;
|
||||
@@ -667,10 +689,11 @@ void* Toy_compileRoutine(Toy_Ast* ast) {
|
||||
rt.subsCapacity = 0;
|
||||
rt.subsCount = 0;
|
||||
|
||||
rt.panic = false;
|
||||
|
||||
//build
|
||||
void * buffer = writeRoutine(&rt, ast);
|
||||
|
||||
|
||||
//cleanup the temp object
|
||||
free(rt.param);
|
||||
free(rt.code);
|
||||
|
||||
@@ -24,6 +24,8 @@ typedef struct Toy_Routine {
|
||||
unsigned char* subs; //subroutines, recursively
|
||||
unsigned int subsCapacity;
|
||||
unsigned int subsCount;
|
||||
|
||||
bool panic; //any issues found at this point are compilation errors
|
||||
} Toy_Routine;
|
||||
|
||||
TOY_API void* Toy_compileRoutine(Toy_Ast* ast);
|
||||
|
||||
@@ -12,16 +12,16 @@
|
||||
|
||||
//utilities
|
||||
#define READ_BYTE(vm) \
|
||||
vm->routine[vm->routineCounter++]
|
||||
vm->module[vm->programCounter++]
|
||||
|
||||
#define READ_UNSIGNED_INT(vm) \
|
||||
*((unsigned int*)(vm->routine + readPostfixUtil(&(vm->routineCounter), 4)))
|
||||
*((unsigned int*)(vm->module + readPostfixUtil(&(vm->programCounter), 4)))
|
||||
|
||||
#define READ_INT(vm) \
|
||||
*((int*)(vm->routine + readPostfixUtil(&(vm->routineCounter), 4)))
|
||||
*((int*)(vm->module + readPostfixUtil(&(vm->programCounter), 4)))
|
||||
|
||||
#define READ_FLOAT(vm) \
|
||||
*((float*)(vm->routine + readPostfixUtil(&(vm->routineCounter), 4)))
|
||||
*((float*)(vm->module + readPostfixUtil(&(vm->programCounter), 4)))
|
||||
|
||||
static inline int readPostfixUtil(unsigned int* ptr, int amount) {
|
||||
int ret = *ptr;
|
||||
@@ -31,7 +31,7 @@ static inline int readPostfixUtil(unsigned int* ptr, int amount) {
|
||||
|
||||
static inline void fixAlignment(Toy_VM* vm) {
|
||||
//NOTE: It's a tilde, not a negative sign
|
||||
vm->routineCounter = (vm->routineCounter + 3) & ~0b11;
|
||||
vm->programCounter = (vm->programCounter + 3) & ~0b11;
|
||||
}
|
||||
|
||||
//instruction handlers
|
||||
@@ -68,10 +68,10 @@ static void processRead(Toy_VM* vm) {
|
||||
int len = (int)READ_BYTE(vm);
|
||||
|
||||
//grab the jump as an integer
|
||||
unsigned int jump = vm->routine[ vm->jumpsAddr + READ_INT(vm) ];
|
||||
unsigned int jump = vm->module[ vm->jumpsAddr + READ_INT(vm) ];
|
||||
|
||||
//jumps are relative to the data address
|
||||
char* cstring = (char*)(vm->routine + vm->dataAddr + jump);
|
||||
char* cstring = (char*)(vm->module + vm->dataAddr + jump);
|
||||
|
||||
//build a string from the data section
|
||||
if (stringType == TOY_STRING_LEAF) {
|
||||
@@ -142,10 +142,10 @@ static void processDeclare(Toy_VM* vm) {
|
||||
bool constant = READ_BYTE(vm); //constness
|
||||
|
||||
//grab the jump
|
||||
unsigned int jump = *(unsigned int*)(vm->routine + vm->jumpsAddr + READ_INT(vm));
|
||||
unsigned int jump = *(unsigned int*)(vm->module + vm->jumpsAddr + READ_INT(vm));
|
||||
|
||||
//grab the data
|
||||
char* cstring = (char*)(vm->routine + vm->dataAddr + jump);
|
||||
char* cstring = (char*)(vm->module + vm->dataAddr + jump);
|
||||
|
||||
//build the name string
|
||||
Toy_String* name = Toy_createNameStringLength(&vm->stringBucket, cstring, len, type, constant);
|
||||
@@ -166,7 +166,7 @@ static void processAssign(Toy_VM* vm) {
|
||||
Toy_Value name = Toy_popStack(&vm->stack);
|
||||
|
||||
//check name string type
|
||||
if (!TOY_VALUE_IS_STRING(name) && TOY_VALUE_AS_STRING(name)->type != TOY_STRING_NAME) {
|
||||
if (!TOY_VALUE_IS_STRING(name) || TOY_VALUE_AS_STRING(name)->type != TOY_STRING_NAME) {
|
||||
Toy_error("Invalid assignment target");
|
||||
return;
|
||||
}
|
||||
@@ -596,18 +596,18 @@ void Toy_initVM(Toy_VM* vm) {
|
||||
Toy_resetVM(vm);
|
||||
}
|
||||
|
||||
void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode) {
|
||||
if (bytecode[0] != TOY_VERSION_MAJOR || bytecode[1] > TOY_VERSION_MINOR) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Wrong bytecode version found: expected %d.%d.%d found %d.%d.%d, exiting\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, bytecode[0], bytecode[1], bytecode[2]);
|
||||
void Toy_bindVM(Toy_VM* vm, struct Toy_Bytecode* bc) {
|
||||
if (bc->ptr[0] != TOY_VERSION_MAJOR || bc->ptr[1] > TOY_VERSION_MINOR) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Wrong bytecode version found: expected %d.%d.%d found %d.%d.%d, exiting\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, bc->ptr[0], bc->ptr[1], bc->ptr[2]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (bytecode[2] != TOY_VERSION_PATCH) {
|
||||
fprintf(stderr, TOY_CC_WARN "WARNING: Wrong bytecode version found: expected %d.%d.%d found %d.%d.%d, continuing\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, bytecode[0], bytecode[1], bytecode[2]);
|
||||
if (bc->ptr[2] != TOY_VERSION_PATCH) {
|
||||
fprintf(stderr, TOY_CC_WARN "WARNING: Wrong bytecode version found: expected %d.%d.%d found %d.%d.%d, continuing\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, bc->ptr[0], bc->ptr[1], bc->ptr[2]);
|
||||
}
|
||||
|
||||
if (strcmp((char*)(bytecode + 3), TOY_VERSION_BUILD) != 0) {
|
||||
fprintf(stderr, TOY_CC_WARN "WARNING: Wrong bytecode build info found: expected '%s' found '%s', continuing\n" TOY_CC_RESET, TOY_VERSION_BUILD, (char*)(bytecode + 3));
|
||||
if (strcmp((char*)(bc->ptr + 3), TOY_VERSION_BUILD) != 0) {
|
||||
fprintf(stderr, TOY_CC_WARN "WARNING: Wrong bytecode build info found: expected '%s' found '%s', continuing\n" TOY_CC_RESET, TOY_VERSION_BUILD, (char*)(bc->ptr + 3));
|
||||
}
|
||||
|
||||
//offset by the header size
|
||||
@@ -616,18 +616,17 @@ void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode) {
|
||||
offset += 4 - (offset % 4); //ceil
|
||||
}
|
||||
|
||||
//delegate
|
||||
Toy_bindVMToRoutine(vm, bytecode + offset);
|
||||
|
||||
//cache these
|
||||
vm->bc = bytecode;
|
||||
if (bc->moduleCount != 0) { //tmp check, just in case the bytecode is empty; will rework this when module packing works
|
||||
//delegate to a more specialized function
|
||||
Toy_bindVMToModule(vm, bc->ptr + offset);
|
||||
}
|
||||
}
|
||||
|
||||
void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine) {
|
||||
vm->routine = routine;
|
||||
void Toy_bindVMToModule(Toy_VM* vm, unsigned char* module) {
|
||||
vm->module = module;
|
||||
|
||||
//read the header metadata
|
||||
vm->routineSize = READ_UNSIGNED_INT(vm);
|
||||
vm->moduleSize = READ_UNSIGNED_INT(vm);
|
||||
vm->paramSize = READ_UNSIGNED_INT(vm);
|
||||
vm->jumpsSize = READ_UNSIGNED_INT(vm);
|
||||
vm->dataSize = READ_UNSIGNED_INT(vm);
|
||||
@@ -663,10 +662,15 @@ void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine) {
|
||||
}
|
||||
|
||||
void Toy_runVM(Toy_VM* vm) {
|
||||
//NO-OP on empty VMs
|
||||
if (vm->module == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: read params into scope
|
||||
|
||||
//prep the routine counter for execution
|
||||
vm->routineCounter = vm->codeAddr;
|
||||
//prep the program counter for execution
|
||||
vm->programCounter = vm->codeAddr;
|
||||
|
||||
//begin
|
||||
process(vm);
|
||||
@@ -679,17 +683,12 @@ void Toy_freeVM(Toy_VM* vm) {
|
||||
Toy_freeBucket(&vm->stringBucket);
|
||||
Toy_freeBucket(&vm->scopeBucket);
|
||||
|
||||
//free the bytecode
|
||||
free(vm->bc);
|
||||
|
||||
Toy_resetVM(vm);
|
||||
}
|
||||
|
||||
void Toy_resetVM(Toy_VM* vm) {
|
||||
vm->bc = NULL;
|
||||
|
||||
vm->routine = NULL;
|
||||
vm->routineSize = 0;
|
||||
vm->module = NULL;
|
||||
vm->moduleSize = 0;
|
||||
|
||||
vm->paramSize = 0;
|
||||
vm->jumpsSize = 0;
|
||||
@@ -702,7 +701,7 @@ void Toy_resetVM(Toy_VM* vm) {
|
||||
vm->dataAddr = 0;
|
||||
vm->subsAddr = 0;
|
||||
|
||||
vm->routineCounter = 0;
|
||||
vm->programCounter = 0;
|
||||
|
||||
//NOTE: stack, scope and memory are not altered during resets
|
||||
}
|
||||
|
||||
@@ -2,17 +2,15 @@
|
||||
|
||||
#include "toy_common.h"
|
||||
|
||||
#include "toy_bytecode.h"
|
||||
#include "toy_bucket.h"
|
||||
#include "toy_stack.h"
|
||||
#include "toy_scope.h"
|
||||
|
||||
typedef struct Toy_VM {
|
||||
//hold the raw bytecode
|
||||
unsigned char* bc;
|
||||
|
||||
//raw instructions to be executed
|
||||
unsigned char* routine;
|
||||
unsigned int routineSize;
|
||||
unsigned char* module;
|
||||
unsigned int moduleSize;
|
||||
|
||||
unsigned int paramSize;
|
||||
unsigned int jumpsSize;
|
||||
@@ -25,7 +23,7 @@ typedef struct Toy_VM {
|
||||
unsigned int dataAddr;
|
||||
unsigned int subsAddr;
|
||||
|
||||
unsigned int routineCounter;
|
||||
unsigned int programCounter;
|
||||
|
||||
//stack - immediate-level values only
|
||||
Toy_Stack* stack;
|
||||
@@ -41,8 +39,8 @@ typedef struct Toy_VM {
|
||||
} Toy_VM;
|
||||
|
||||
TOY_API void Toy_initVM(Toy_VM* vm);
|
||||
TOY_API void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode); //process the version data
|
||||
TOY_API void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine); //process the routine only
|
||||
TOY_API void Toy_bindVM(Toy_VM* vm, struct Toy_Bytecode* bc); //process the version data
|
||||
TOY_API void Toy_bindVMToModule(Toy_VM* vm, unsigned char* module); //process the module only
|
||||
|
||||
TOY_API void Toy_runVM(Toy_VM* vm);
|
||||
TOY_API void Toy_freeVM(Toy_VM* vm);
|
||||
|
||||
@@ -72,3 +72,13 @@ build-run-gdb: $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.exe)
|
||||
.PRECIOUS: $(TEST_OUTDIR)/%.run-gdb
|
||||
$(TEST_OUTDIR)/%.run-gdb: $(TEST_OUTDIR)/%.exe
|
||||
gdb $< -ix gdb_init -ex=run --batch --return-child-result --args "$<"
|
||||
|
||||
#valgrind targets
|
||||
valgrind: build-source build-cases build-link build-run-valgrind
|
||||
|
||||
.PHONY: build-run-valgrind
|
||||
build-run-valgrind: $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.exe))) $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.run-valgrind)))
|
||||
|
||||
.PRECIOUS: $(TEST_OUTDIR)/%.run-valgrind
|
||||
$(TEST_OUTDIR)/%.run-valgrind: $(TEST_OUTDIR)/%.exe
|
||||
valgrind $< --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose
|
||||
|
||||
@@ -44,7 +44,7 @@ int test_setup_and_teardown(Toy_Bucket** bucketHandle) {
|
||||
//run the setup
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//check the header size
|
||||
int headerSize = 3 + strlen(TOY_VERSION_BUILD) + 1;
|
||||
@@ -52,10 +52,10 @@ int test_setup_and_teardown(Toy_Bucket** bucketHandle) {
|
||||
headerSize += 4 - (headerSize % 4); //ceil
|
||||
}
|
||||
|
||||
//check the routine was loaded correctly
|
||||
//check the module was loaded correctly
|
||||
if (
|
||||
vm.routine - vm.bc != headerSize ||
|
||||
vm.routineSize != 72 ||
|
||||
vm.module - bc.ptr != headerSize ||
|
||||
vm.moduleSize != 72 ||
|
||||
vm.paramSize != 0 ||
|
||||
vm.jumpsSize != 0 ||
|
||||
vm.dataSize != 0 ||
|
||||
@@ -66,11 +66,13 @@ int test_setup_and_teardown(Toy_Bucket** bucketHandle) {
|
||||
|
||||
//cleanup and return
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//don't run it this time, simply teadown
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -95,7 +97,7 @@ int test_simple_execution(Toy_Bucket** bucketHandle) {
|
||||
//run the setup
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -111,11 +113,13 @@ int test_simple_execution(Toy_Bucket** bucketHandle) {
|
||||
|
||||
//cleanup and return
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//teadown
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -140,7 +144,7 @@ int test_opcode_not_equal(Toy_Bucket** bucketHandle) {
|
||||
//run the setup
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -156,11 +160,13 @@ int test_opcode_not_equal(Toy_Bucket** bucketHandle) {
|
||||
|
||||
//cleanup and return
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//teadown
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -193,7 +199,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -207,6 +213,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
Toy_resetAssertFailureCallback();
|
||||
free(callbackUtilReceived);
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -215,6 +222,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
free(callbackUtilReceived);
|
||||
callbackUtilReceived = NULL;
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
//test assert false
|
||||
@@ -234,7 +242,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -249,6 +257,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
Toy_resetAssertFailureCallback();
|
||||
free(callbackUtilReceived);
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -257,6 +266,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
free(callbackUtilReceived);
|
||||
callbackUtilReceived = NULL;
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
//test assert false with message
|
||||
@@ -276,7 +286,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -291,6 +301,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
Toy_resetAssertFailureCallback();
|
||||
free(callbackUtilReceived);
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -299,6 +310,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) {
|
||||
free(callbackUtilReceived);
|
||||
callbackUtilReceived = NULL;
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -322,7 +334,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -337,6 +349,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
Toy_resetPrintCallback();
|
||||
free(callbackUtilReceived);
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -345,6 +358,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
free(callbackUtilReceived);
|
||||
callbackUtilReceived = NULL;
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
//test print with a string
|
||||
@@ -364,7 +378,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -379,6 +393,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
Toy_resetPrintCallback();
|
||||
free(callbackUtilReceived);
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -387,6 +402,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
free(callbackUtilReceived);
|
||||
callbackUtilReceived = NULL;
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
//test print with a string concat
|
||||
@@ -406,7 +422,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -421,6 +437,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
Toy_resetPrintCallback();
|
||||
free(callbackUtilReceived);
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -429,6 +446,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) {
|
||||
free(callbackUtilReceived);
|
||||
callbackUtilReceived = NULL;
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -453,7 +471,7 @@ int test_scope(Toy_Bucket** bucketHandle) {
|
||||
//run the setup
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -475,11 +493,13 @@ int test_scope(Toy_Bucket** bucketHandle) {
|
||||
|
||||
//cleanup and return
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//teadown
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
//test declaration with absent value
|
||||
@@ -500,7 +520,7 @@ int test_scope(Toy_Bucket** bucketHandle) {
|
||||
//run the setup
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr);
|
||||
Toy_bindVM(&vm, &bc);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
@@ -520,11 +540,13 @@ int test_scope(Toy_Bucket** bucketHandle) {
|
||||
|
||||
//cleanup and return
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//teadown
|
||||
Toy_freeVM(&vm);
|
||||
Toy_freeBytecode(bc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -540,7 +562,7 @@ int test_vm_reuse(Toy_Bucket** bucketHandle) {
|
||||
|
||||
//run 1
|
||||
Toy_Bytecode bc1 = makeBytecodeFromSource(bucketHandle, "print \"Hello world!\";");
|
||||
Toy_bindVM(&vm, bc1.ptr);
|
||||
Toy_bindVM(&vm, &bc1);
|
||||
Toy_runVM(&vm);
|
||||
Toy_resetVM(&vm);
|
||||
|
||||
@@ -559,7 +581,7 @@ int test_vm_reuse(Toy_Bucket** bucketHandle) {
|
||||
|
||||
//run 2
|
||||
Toy_Bytecode bc2 = makeBytecodeFromSource(bucketHandle, "print \"Hello world!\";");
|
||||
Toy_bindVM(&vm, bc2.ptr);
|
||||
Toy_bindVM(&vm, &bc2);
|
||||
Toy_runVM(&vm);
|
||||
Toy_resetVM(&vm);
|
||||
|
||||
@@ -578,7 +600,7 @@ int test_vm_reuse(Toy_Bucket** bucketHandle) {
|
||||
|
||||
//run 3
|
||||
Toy_Bytecode bc3 = makeBytecodeFromSource(bucketHandle, "print \"Hello world!\";");
|
||||
Toy_bindVM(&vm, bc3.ptr);
|
||||
Toy_bindVM(&vm, &bc3);
|
||||
Toy_runVM(&vm);
|
||||
Toy_resetVM(&vm);
|
||||
|
||||
|
||||
@@ -43,6 +43,14 @@ run-gdb: $(TEST_SCRIPTFILES:.toy=.toy-gdb)
|
||||
%.toy-gdb: %.toy
|
||||
gdb $(TEST_OUTDIR)/$(TEST_REPLNAME) -ix gdb_init -ex=run --batch --return-child-result --args "$(TEST_OUTDIR)/$(TEST_REPLNAME)" "-f" "../$<" "--verbose"
|
||||
|
||||
#same as above, but with valgrind
|
||||
valgrind: source repl run-valgrind
|
||||
|
||||
run-valgrind: $(TEST_SCRIPTFILES:.toy=.toy-valgrind)
|
||||
|
||||
%.toy-valgrind: %.toy
|
||||
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose $(TEST_OUTDIR)/$(TEST_REPLNAME) -f ../$< --verbose
|
||||
|
||||
#compile the source and repl first
|
||||
source: $(TEST_OBJDIR) $(TEST_OUTDIR)
|
||||
$(MAKE) SRC_OUTDIR=../$(TOY_INTEGRATIONSDIR)/$(TEST_OUTDIR) -C $(TEST_SOURCEDIR)
|
||||
|
||||
Reference in New Issue
Block a user