mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Toy_VM and Toy_Stack are working and tested, read more
At this point, only a minimal number of operations are working, and after running any kind of source code, the 'result' is simply left on the VM's stack. Still, it's awesome to see it reach this point.
This commit is contained in:
@@ -86,7 +86,7 @@ int test_bytecode_from_source(Toy_Bucket* bucket) {
|
||||
}
|
||||
|
||||
//check contents of the routine (this is copy/pasted from test_routine.c, and tweaked with the offset)
|
||||
int offset = strlen(TOY_VERSION_BUILD) + 3;
|
||||
int offset = 3 + strlen(TOY_VERSION_BUILD) + 1;
|
||||
if (offset % 4 != 0) {
|
||||
offset += 4 - (offset % 4); //ceil
|
||||
}
|
||||
|
||||
179
tests/cases/test_stack.c
Normal file
179
tests/cases/test_stack.c
Normal file
@@ -0,0 +1,179 @@
|
||||
#include "toy_stack.h"
|
||||
#include "toy_console_colors.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int test_stack_with_init() {
|
||||
//init and free the stack
|
||||
{
|
||||
Toy_Stack stack;
|
||||
Toy_initStack(&stack);
|
||||
|
||||
//check if it worked
|
||||
if (
|
||||
stack.ptr != NULL ||
|
||||
stack.capacity != 0 ||
|
||||
stack.count != 0)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to init Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_freeStack(&stack);
|
||||
}
|
||||
|
||||
//push, peek and pop stack
|
||||
{
|
||||
Toy_Stack stack;
|
||||
Toy_initStack(&stack);
|
||||
|
||||
//check if it worked (push)
|
||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(42));
|
||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(69));
|
||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(420));
|
||||
if (
|
||||
stack.ptr == NULL ||
|
||||
stack.capacity != 64 ||
|
||||
stack.count != 3)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to push Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check if it worked (peek)
|
||||
Toy_Value top1 = Toy_peekStack(&stack);
|
||||
if (
|
||||
TOY_VALUE_IS_INTEGER(top1) != true ||
|
||||
TOY_VALUE_AS_INTEGER(top1) != 420)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to peek Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check if it worked (pop)
|
||||
Toy_Value top2 = Toy_popStack(&stack);
|
||||
if (
|
||||
stack.ptr == NULL ||
|
||||
stack.capacity != 64 ||
|
||||
stack.count != 2 ||
|
||||
TOY_VALUE_IS_INTEGER(top2) != true ||
|
||||
TOY_VALUE_AS_INTEGER(top2) != 420)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check if it worked (post-pop peek)
|
||||
Toy_Value top3 = Toy_peekStack(&stack);
|
||||
if (
|
||||
TOY_VALUE_IS_INTEGER(top3) != true ||
|
||||
TOY_VALUE_AS_INTEGER(top3) != 69)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop then peek Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_freeStack(&stack);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_stack_with_preallocate() {
|
||||
//preallocate and free the stack
|
||||
{
|
||||
Toy_Stack stack;
|
||||
Toy_preallocateStack(&stack);
|
||||
|
||||
//check if it worked
|
||||
if (
|
||||
stack.ptr == NULL ||
|
||||
stack.capacity != 64 ||
|
||||
stack.count != 0)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to preallocate Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_freeStack(&stack);
|
||||
}
|
||||
|
||||
//push, peek and pop stack
|
||||
{
|
||||
Toy_Stack stack;
|
||||
Toy_initStack(&stack);
|
||||
|
||||
//check if it worked (push)
|
||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(42));
|
||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(69));
|
||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(420));
|
||||
if (
|
||||
stack.ptr == NULL ||
|
||||
stack.capacity != 64 ||
|
||||
stack.count != 3)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to push Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check if it worked (peek)
|
||||
Toy_Value top1 = Toy_peekStack(&stack);
|
||||
if (
|
||||
TOY_VALUE_IS_INTEGER(top1) != true ||
|
||||
TOY_VALUE_AS_INTEGER(top1) != 420)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to peek Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check if it worked (pop)
|
||||
Toy_Value top2 = Toy_popStack(&stack);
|
||||
if (
|
||||
stack.ptr == NULL ||
|
||||
stack.capacity != 64 ||
|
||||
stack.count != 2 ||
|
||||
TOY_VALUE_IS_INTEGER(top2) != true ||
|
||||
TOY_VALUE_AS_INTEGER(top2) != 420)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check if it worked (post-pop peek)
|
||||
Toy_Value top3 = Toy_peekStack(&stack);
|
||||
if (
|
||||
TOY_VALUE_IS_INTEGER(top3) != true ||
|
||||
TOY_VALUE_AS_INTEGER(top3) != 69)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop then peek Toy_Stack\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_freeStack(&stack);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
//run each test set, returning the total errors given
|
||||
int total = 0, res = 0;
|
||||
|
||||
{
|
||||
res = test_stack_with_init();
|
||||
if (res == 0) {
|
||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||
}
|
||||
total += res;
|
||||
}
|
||||
|
||||
{
|
||||
res = test_stack_with_preallocate();
|
||||
if (res == 0) {
|
||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||
}
|
||||
total += res;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
@@ -33,6 +33,23 @@ int main() {
|
||||
}
|
||||
}
|
||||
|
||||
//test value equality
|
||||
{
|
||||
Toy_Value answer = TOY_VALUE_TO_INTEGER(42);
|
||||
Toy_Value question = TOY_VALUE_TO_INTEGER(42);
|
||||
Toy_Value nice = TOY_VALUE_TO_INTEGER(69);
|
||||
|
||||
if (!TOY_VALUE_IS_EQUAL(answer, question)) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: equality check failed, expected true\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TOY_VALUE_IS_EQUAL(answer, nice)) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: equality check failed, expected false\n" TOY_CC_RESET);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
149
tests/cases/test_vm.c
Normal file
149
tests/cases/test_vm.c
Normal file
@@ -0,0 +1,149 @@
|
||||
#include "toy_vm.h"
|
||||
#include "toy_console_colors.h"
|
||||
|
||||
#include "toy_lexer.h"
|
||||
#include "toy_parser.h"
|
||||
#include "toy_bytecode.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//utils
|
||||
Toy_Bytecode makeBytecodeFromSource(Toy_Bucket** bucket, const char* source) {
|
||||
Toy_Lexer lexer;
|
||||
Toy_bindLexer(&lexer, source);
|
||||
|
||||
Toy_Parser parser;
|
||||
Toy_bindParser(&parser, &lexer);
|
||||
|
||||
Toy_Ast* ast = Toy_scanParser(bucket, &parser);
|
||||
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||
|
||||
return bc;
|
||||
}
|
||||
|
||||
//tests
|
||||
int test_setup_and_teardown(Toy_Bucket* bucket) {
|
||||
//basic init & quit
|
||||
{
|
||||
//generate bytecode for testing
|
||||
const char* source = "(1 + 2) * (3 + 4);";
|
||||
|
||||
Toy_Lexer lexer;
|
||||
Toy_bindLexer(&lexer, source);
|
||||
|
||||
Toy_Parser parser;
|
||||
Toy_bindParser(&parser, &lexer);
|
||||
|
||||
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
||||
|
||||
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||
|
||||
//run the setup
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr, bc.capacity);
|
||||
|
||||
//check the header size
|
||||
int headerSize = 3 + strlen(TOY_VERSION_BUILD) + 1;
|
||||
if (headerSize % 4 != 0) {
|
||||
headerSize += 4 - (headerSize % 4); //ceil
|
||||
}
|
||||
|
||||
//check the routine was loaded correctly
|
||||
if (
|
||||
vm.routine - vm.bc != headerSize ||
|
||||
vm.routineSize != 72 ||
|
||||
vm.paramCount != 0 ||
|
||||
vm.jumpsCount != 0 ||
|
||||
vm.dataCount != 0 ||
|
||||
vm.subsCount != 0
|
||||
)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to setup and teadown Toy_VM, source: %s\n" TOY_CC_RESET, source);
|
||||
|
||||
//cleanup and return
|
||||
Toy_freeVM(&vm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//don't run it this time, simply teadown
|
||||
Toy_freeVM(&vm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//tests
|
||||
int test_simple_execution(Toy_Bucket* bucket) {
|
||||
//basic init & quit
|
||||
{
|
||||
//generate bytecode for testing
|
||||
const char* source = "(1 + 2) * (3 + 4);";
|
||||
|
||||
Toy_Lexer lexer;
|
||||
Toy_bindLexer(&lexer, source);
|
||||
|
||||
Toy_Parser parser;
|
||||
Toy_bindParser(&parser, &lexer);
|
||||
|
||||
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
||||
|
||||
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||
|
||||
//run the setup
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, bc.ptr, bc.capacity);
|
||||
|
||||
//run
|
||||
Toy_runVM(&vm);
|
||||
|
||||
//check the final state of the stack
|
||||
if (vm.stack.count != 1 ||
|
||||
TOY_VALUE_IS_INTEGER( Toy_peekStack(&vm.stack) ) != true ||
|
||||
TOY_VALUE_AS_INTEGER( Toy_peekStack(&vm.stack) ) != 21
|
||||
)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed run the Toy_VM, source: %s\n" TOY_CC_RESET, source);
|
||||
|
||||
//cleanup and return
|
||||
Toy_freeVM(&vm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//teadown
|
||||
Toy_freeVM(&vm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
//run each test set, returning the total errors given
|
||||
int total = 0, res = 0;
|
||||
|
||||
{
|
||||
Toy_Bucket* bucket = NULL;
|
||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
||||
res = test_setup_and_teardown(bucket);
|
||||
TOY_BUCKET_FREE(bucket);
|
||||
if (res == 0) {
|
||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||
}
|
||||
total += res;
|
||||
}
|
||||
|
||||
{
|
||||
Toy_Bucket* bucket = NULL;
|
||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
||||
res = test_simple_execution(bucket);
|
||||
TOY_BUCKET_FREE(bucket);
|
||||
if (res == 0) {
|
||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||
}
|
||||
total += res;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
Reference in New Issue
Block a user