131 lines
5.8 KiB
C
131 lines
5.8 KiB
C
#include "test.h"
|
|
#include "vm.h"
|
|
#include <string.h>
|
|
|
|
/* Array of test mappings */
|
|
struct TestMapping internal_tests[] = {
|
|
{"simple.zrl", test_add_compile},
|
|
{"loop.zrl", test_loop_compile},
|
|
{"add.zrl", test_add_function_compile},
|
|
{"fib.zrl", test_recursive_function_compile},
|
|
/* Add more test mappings here */
|
|
{NULL, NULL} /* Sentinel to mark end of array */
|
|
};
|
|
|
|
bool compile_internal_test(const char* filename, VM* vm) {
|
|
int i;
|
|
for (i = 0; internal_tests[i].filename != NULL; i++) {
|
|
if (strcmp(internal_tests[i].filename, filename) == 0) {
|
|
return internal_tests[i].test_func(vm);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool test_add_compile(VM *vm) {
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 0, 0, 0);
|
|
vm->code[vm->cp++].u = nat_alloc(vm, 1);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 1, 1, 0);
|
|
vm->code[vm->cp++].u = nat_alloc(vm, 2);
|
|
vm->code[vm->cp++].u = OP(OP_ADD_UINT, 2, 1, 0); /* let sum = 1 + 2; */
|
|
vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 2, 0);
|
|
vm->code[vm->cp++].u = OP(OP_DBG_PRINT_STRING, 0, 3, 0); /* print(sum.toS()); */
|
|
vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* explicit halt */
|
|
return true;
|
|
}
|
|
|
|
bool test_loop_compile(VM *vm) {
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 0, 0, 0); /* let a = 5.0 */
|
|
vm->code[vm->cp++].u = real_alloc(vm, 5.0f);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 1, 0, 0); /* do (i = 50000, 0, -1) { */
|
|
vm->code[vm->cp++].u = int_alloc(vm, 50000);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 2, 0, 0); /* loop check value */
|
|
vm->code[vm->cp++].u = int_alloc(vm, 0);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 3, 0, 0); /* loop incriment value */
|
|
vm->code[vm->cp++].u = int_alloc(vm, -1);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 4, 0, 0); /* loop start */
|
|
uint32_t addr = vm->cp + 1;
|
|
vm->code[vm->cp++].u = int_alloc(vm, addr);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 5, 0, 0);
|
|
vm->code[vm->cp++].u = real_alloc(vm, 5.0f);
|
|
vm->code[vm->cp++].u = OP(OP_ADD_REAL, 0, 0, 5); /* a += 5.0; */
|
|
vm->code[vm->cp++].u = OP(OP_ADD_INT, 1, 1, 3); /* (implied by loop) i = i + (-1) */
|
|
vm->code[vm->cp++].u = OP(OP_JGE_INT, 4, 1, 2); /* } */
|
|
vm->code[vm->cp++].u = OP(OP_REAL_TO_UINT, 1, 0, 0); /* let b = a as nat; */
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 6, 0, 0);
|
|
vm->code[vm->cp++].u = str_alloc(vm, "Enter a string:", 0);
|
|
vm->code[vm->cp++].u = OP(OP_DBG_PRINT_STRING, 0, 6, 0); /* print("Enter a string: "); */
|
|
vm->code[vm->cp++].u = OP(OP_DBG_READ_STRING, 2, 0, 0); /* let user_string = gets(); */
|
|
vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 1, 0);
|
|
vm->code[vm->cp++].u = OP(OP_DBG_PRINT_STRING, 0, 3, 0); /* print(a.toS()); */
|
|
vm->code[vm->cp++].u = OP(OP_REAL_TO_STRING, 3, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_DBG_PRINT_STRING, 0, 3, 0); /* print(b.toS()); */
|
|
vm->code[vm->cp++].u = OP(OP_DBG_PRINT_STRING, 0, 2, 0); /* print(user_string); */
|
|
vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* program done */
|
|
return true;
|
|
}
|
|
|
|
bool test_add_function_compile(VM *vm) {
|
|
/* fn main() */
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 0, 0, 0); /* 1 */
|
|
uint32_t addr = int_alloc(vm, 1);
|
|
vm->code[vm->cp++].u = addr;
|
|
vm->code[vm->cp++].u = OP(OP_PUSH, 0, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 0, 0, 0); /* 1 */
|
|
vm->code[vm->cp++].u = addr;
|
|
vm->code[vm->cp++].u = OP(OP_PUSH, 0, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* ); */
|
|
vm->code[vm->cp++].u = 12;
|
|
vm->code[vm->cp++].u = OP(OP_POP, 0, 0, 0); /* get return value */
|
|
vm->code[vm->cp++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_DBG_PRINT_STRING, 0, 1, 0); /* print(sum.toS()); */
|
|
vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0);
|
|
/* fn add() */
|
|
vm->code[vm->cp++].u = OP(OP_POP, 0, 0, 0); /* a int */
|
|
vm->code[vm->cp++].u = OP(OP_POP, 1, 0, 0); /* b int */
|
|
vm->code[vm->cp++].u = OP(OP_ADD_INT, 2, 1, 0); /* a + b */
|
|
vm->code[vm->cp++].u = OP(OP_PUSH, 2, 0, 0); /* push on stack */
|
|
vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
|
|
return true;
|
|
}
|
|
|
|
bool test_recursive_function_compile(VM *vm) {
|
|
/* fn main() */
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 0, 0, 0); /* 35 */
|
|
vm->code[vm->cp++].u = int_alloc(vm, 35);
|
|
vm->code[vm->cp++].u = OP(OP_PUSH, 0, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* ); */
|
|
vm->code[vm->cp++].u = 9;
|
|
vm->code[vm->cp++].u = OP(OP_POP, 0, 0, 0); /* get return value */
|
|
vm->code[vm->cp++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_DBG_PRINT_STRING, 0, 1, 0); /* print(fib(35).toS()); */
|
|
vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0);
|
|
/* fn fib() */
|
|
vm->code[vm->cp++].u = OP(OP_POP, 0, 0, 0); /* n int */
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 1, 0, 0); /* 2 */
|
|
vm->code[vm->cp++].u = int_alloc(vm, 2);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 2, 0, 0); /* &fib */
|
|
vm->code[vm->cp++].u = int_alloc(vm, 32);
|
|
vm->code[vm->cp++].u = OP(OP_JLT_INT, 2, 0, 1);
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 3, 0, 0); /* 2 */
|
|
vm->code[vm->cp++].u = int_alloc(vm, 2);
|
|
vm->code[vm->cp++].u = OP(OP_SUB_INT, 4, 0, 3);
|
|
vm->code[vm->cp++].u = OP(OP_PUSH, 4, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 2) */
|
|
vm->code[vm->cp++].u = 9;
|
|
vm->code[vm->cp++].u = OP(OP_LOAD, 3, 0, 0); /* 1 */
|
|
vm->code[vm->cp++].u = int_alloc(vm, 1);
|
|
vm->code[vm->cp++].u = OP(OP_SUB_INT, 4, 0, 3);
|
|
vm->code[vm->cp++].u = OP(OP_PUSH, 4, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 1) */
|
|
vm->code[vm->cp++].u = 9;
|
|
vm->code[vm->cp++].u = OP(OP_POP, 4, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_POP, 5, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_ADD_INT, 6, 5, 4);
|
|
vm->code[vm->cp++].u = OP(OP_PUSH, 6, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_PUSH, 0, 0, 0);
|
|
vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
|
|
return true;
|
|
}
|