#include "test.h" #include "vm.h" #include /* Array of test mappings */ struct TestMapping internal_tests[] = { {"simple.ul", test_simple_compile}, {"loop.ul", test_loop_compile}, {"add.ul", test_add_function_compile}, {"fib.ul", test_recursive_function_compile}, {"window.ul", test_window_click_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_simple_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, 0, 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, 10000); 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, 5, 0, 0); /* a */ vm->code[vm->cp++].u = real_alloc(vm, 5.0f); 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_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); uint32_t str_addr = str_alloc(vm, "Enter a string:", 16); vm->code[vm->cp++].u = nat_alloc(vm, str_addr); 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 */ vm->code[vm->cp++].u = int_alloc(vm, 1); 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 = int_alloc(vm, 1); 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; } bool test_window_click_compile(VM *vm) { uint32_t screen_path_addr = str_alloc(vm, "/dev/screen/0", 14); /*uint32_t mouse_path_addr = str_alloc(vm, "/dev/mouse/0", 12);*/ /* Open screen device: R0=path, R1=mode */ vm->code[vm->cp++].u = OP(OP_LOAD, 0, 0, 0); /* R0 = screen path */ vm->code[vm->cp++].u = nat_alloc(vm, screen_path_addr); vm->code[vm->cp++].u = OP(OP_LOAD, 1, 0, 0); /* R1 = mode (0) */ vm->code[vm->cp++].u = int_alloc(vm, 0); vm->code[vm->cp++].u = OP(OP_SYSCALL, SYSCALL_DEVICE_OPEN, 0, 2); /* syscall_id, first_reg=0, arg_count=2 */ /* Check if open succeeded (result in vm->acc) */ vm->code[vm->cp++].u = OP(OP_GET_ACC, 2, 0, 0); /* Move result to R2 */ /* Create simple test pixel data */ uint32_t test_pixel_addr = vm->mp; vm->memory[vm->mp].c[0] = (char)((255 / 32) << 5) | ((0 / 32) << 2) | (0 / 64); vm->memory[vm->mp].c[1] = (char)((255 / 32) << 5) | ((0 / 32) << 2) | (0 / 64); vm->memory[vm->mp].c[2] = (char)((255 / 32) << 5) | ((0 / 32) << 2) | (0 / 64); vm->memory[vm->mp++].c[3] = (char)((255 / 32) << 5) | ((0 / 32) << 2) | (0 / 64); vm->frames[vm->fp].allocated.end++; /* Main loop to check for mouse input */ uint32_t loop_start = vm->cp; /* Write to screen: R0=path, R1=buffer, R2=size */ vm->code[vm->cp++].u = OP(OP_LOAD, 0, 0, 0); vm->code[vm->cp++].u = nat_alloc(vm, screen_path_addr); vm->code[vm->cp++].u = OP(OP_LOAD, 1, 0, 0); vm->code[vm->cp++].u = nat_alloc(vm, test_pixel_addr); vm->code[vm->cp++].u = OP(OP_LOAD, 2, 0, 0); vm->code[vm->cp++].u = int_alloc(vm, 1); vm->code[vm->cp++].u = OP(OP_SYSCALL, SYSCALL_DEVICE_WRITE, 0, 3); /* syscall_id, first_reg=0, arg_count=3 */ vm->code[vm->cp++].u = OP(OP_LOAD, 3, 0, 0); vm->code[vm->cp++].u = nat_alloc(vm, loop_start); vm->code[vm->cp++].u = OP(OP_JMP, 3, 0, 0); /* Infinite loop for testing */ vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); return true; }