diff --git a/src/arch/linux-tui/devices.c b/src/arch/linux-tui/devices.c deleted file mode 100644 index dcca021..0000000 --- a/src/arch/linux-tui/devices.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "devices.h" -#include -#include - -i32 console_open(void *data, u32 mode) { - USED(mode); - USED(data); - /* Nothing to open — stdin/stdout are always available */ - return 0; /* Success */ -} - -i32 console_read(void *data, u8 *buffer, u32 size) { - USED(data); - ssize_t result = read(STDIN_FILENO, buffer, size); - if (result < 0) return -1; /* Error */ - return (i32)result; /* Bytes read */ -} - -i32 console_write(void *data, const u8 *buffer, u32 size) { - USED(data); - ssize_t result = write(STDOUT_FILENO, buffer, size); - if (result < 0) return -1; /* Error */ - return (i32)result; /* Bytes written */ -} - -i32 console_close(void *data) { - USED(data); - /* Nothing to close — stdin/stdout are process-owned */ - return 0; -} - -i32 console_ioctl(void *data, u32 cmd, void *args) { - USED(data); - USED(cmd); - USED(args); - return -1; /* Unsupported */ -} - -i32 screen_open(void *data, u32 mode) { - USED(mode); - ScreenDeviceData *screen = (ScreenDeviceData *)data; - USED(screen); - - return 0; -} - -i32 screen_read(void *data, u8 *buffer, u32 size) { - USED(data); - USED(buffer); - USED(size); - return -1; -} - -i32 screen_write(void *data, const u8 *buffer, u32 size) { - ScreenDeviceData *screen = (ScreenDeviceData *)data; - - if (size > screen->framebuffer_size * sizeof(u8)) { - return -1; - } - - memcpy(&screen->vm->memory[screen->framebuffer_pos], buffer, size); - return 0; -} - -i32 screen_close(void *data) { - ScreenDeviceData *screen = (ScreenDeviceData *)data; - USED(screen); - - return 0; -} - -i32 keyboard_open(void *data, u32 mode) { - USED(data); - USED(mode); - return 0; -} - -i32 keyboard_read(void *data, u8 *buffer, u32 size) { - KeyboardDeviceData *kbd = (KeyboardDeviceData *)data; - - if (size < (u32)kbd->key_count) - return -1; - - memcpy(buffer, kbd->keys, kbd->key_count); - return 0; -} - -i32 keyboard_write(void *data, const u8 *buffer, u32 size) { - USED(data); - USED(buffer); - USED(size); - return -1; /* not writable */ -} - -i32 keyboard_close(void *data) { - USED(data); - return 0; -} diff --git a/src/arch/linux-tui/devices.h b/src/arch/linux-tui/devices.h deleted file mode 100644 index 7481a6c..0000000 --- a/src/arch/linux-tui/devices.h +++ /dev/null @@ -1,33 +0,0 @@ -#include "../../vm/device.h" -#include "../../vm/vm.h" - -/* Screen device data */ -typedef struct screen_device_data_s { - u32 width; - u32 height; - u32 framebuffer_pos; - u32 framebuffer_size; - VM* vm; -} ScreenDeviceData; - -/* Keyboard device data */ -typedef struct keyboard_device_data_s { - const u8 *keys; - i32 key_count; -} KeyboardDeviceData; - -i32 screen_open(void *data, u32 mode); -i32 screen_read(void *data, u8 *buffer, u32 size); -i32 screen_write(void *data, const u8 *buffer, u32 size); -i32 screen_close(void *data); - -i32 keyboard_open(void *data, u32 mode); -i32 keyboard_read(void *data, u8 *buffer, u32 size); -i32 keyboard_write(void *data, const u8 *buffer, u32 size); -i32 keyboard_close(void *data); - -i32 console_open(void *data, u32 mode); -i32 console_read(void *data, u8 *buffer, u32 size); -i32 console_write(void *data, const u8 *buffer, u32 size); -i32 console_close(void *data); -i32 console_ioctl(void *data, u32 cmd, void *args); diff --git a/src/arch/linux-tui/main.c b/src/arch/linux-tui/main.c deleted file mode 100644 index c8a47bb..0000000 --- a/src/arch/linux-tui/main.c +++ /dev/null @@ -1,264 +0,0 @@ -#include "../../tools/test.h" -#include "../../tools/parser.h" -#include "../../vm/vm.h" -#include "devices.h" - -#include -#include -#include -#include -#include -#include -#include - -#define MAX_SRC_SIZE 16384 - -static DeviceOps screen_ops = {.open = screen_open, - .read = screen_read, - .write = screen_write, - .close = screen_close, - .ioctl = nil}; - -static DeviceOps console_device_ops = { - .open = console_open, - .read = console_read, - .write = console_write, - .close = console_close, - .ioctl = console_ioctl, -}; - -static ScreenDeviceData screen_data = {0}; - -void compileFile(const char *path, VM *vm) { - USED(vm); - - FILE *f = fopen(path, "rb"); - if (!f) { - perror("fopen"); - exit(1); - } - - static char source[MAX_SRC_SIZE + 1]; - - fseek(f, 0, SEEK_END); - long len = ftell(f); - fseek(f, 0, SEEK_SET); - if (len >= MAX_SRC_SIZE) { - perror("source is larget than buffer"); - exit(1); - } - size_t read = fread(source, 1, len, f); - source[read] = '\0'; - fclose(f); -} - -void repl(VM *vm) { - USED(vm); - - char buffer[1024 * 10] = {0}; // Larger buffer for multi-line input - char line[1024]; - - for (;;) { - // Count current parentheses balance - int paren_balance = 0; - for (int i = 0; buffer[i]; i++) { - if (buffer[i] == '(') paren_balance++; - else if (buffer[i] == ')') paren_balance--; - } - - // Show appropriate prompt - if (paren_balance > 0) { - printf(".. "); // Continuation prompt when unbalanced - } else { - printf("> "); // Normal prompt when balanced - } - fflush(stdout); - - if (!fgets(line, sizeof(line), stdin)) { - printf("\n"); - break; - } - - // Append the new line to buffer - strncat(buffer, line, sizeof(buffer) - strlen(buffer) - 1); - - // Recalculate balance after adding new line - paren_balance = 0; - for (int i = 0; buffer[i]; i++) { - if (buffer[i] == '(') paren_balance++; - else if (buffer[i] == ')') paren_balance--; - } - - // Only parse when parentheses are balanced - if (paren_balance == 0) { - // Check if buffer has actual content (not just whitespace) - int has_content = 0; - for (int i = 0; buffer[i]; i++) { - if (!isspace(buffer[i])) { - has_content = 1; - break; - } - } - - if (has_content) { - ExprNode *ast = expr_parse(buffer, strlen(buffer)); - if (!ast) { - printf("Parse failed.\n"); - } else { - printf("AST:\n"); - expr_print(ast, 0); - expr_free(ast); - } - } - - // Reset buffer for next input - buffer[0] = '\0'; - } - // If unbalanced, continue reading more lines - } - exit(0); -} - -enum FlagType { - FLAG_NONE = 0, - FLAG_TEST_MODE = 1, - FLAG_DUMP_ROM = 2, - FLAG_GUI_MODE = 4, -}; - -#define MAX_INPUT_FILES 16 /* Adjust based on your system's constraints */ - -struct CompilerConfig { - u32 flags; - char *input_files[MAX_INPUT_FILES]; - i32 input_file_count; -}; - -i32 parse_arguments(i32 argc, char *argv[], struct CompilerConfig *config) { - i32 i; - - /* Initialize config */ - config->flags = 0; - config->input_file_count = 0; - - /* Zero out input files array for safety */ - for (i = 0; i < MAX_INPUT_FILES; i++) { - config->input_files[i] = NULL; - } - - for (i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - /* Long and short flag handling */ - if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gui") == 0) { - config->flags |= FLAG_GUI_MODE; - } else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) { - config->flags |= FLAG_TEST_MODE; - } else if (strcmp(argv[i], "-o") == 0 || - strcmp(argv[i], "--dump-rom") == 0) { - config->flags |= FLAG_DUMP_ROM; - } else { - fprintf(stderr, "Unknown flag: %s\n", argv[i]); - return -1; - } - } else if (strstr(argv[i], ".ul") != NULL) { - /* Collect input files */ - if (config->input_file_count >= MAX_INPUT_FILES) { - fprintf(stderr, "Too many input files. Maximum is %lld\n", - MAX_INPUT_FILES); - return -1; - } - config->input_files[config->input_file_count++] = argv[i]; - } - } - - return 0; -} - -/* - * This needs to be done dynamically eventually - */ -void register_sdl_devices(VM *vm) { - screen_data.vm = vm; - - struct winsize w; - ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); - - screen_data.width = w.ws_row * 2; - screen_data.height = w.ws_col; - screen_data.framebuffer_size = w.ws_row * w.ws_col * 2; - screen_data.framebuffer_pos = vm->mp; - vm->mp += screen_data.framebuffer_size; /* advance memory pointer */ - - vm_register_device(vm, "/dev/screen/0", "screen", &screen_data, &screen_ops); -} - -i32 main(i32 argc, char *argv[]) { - struct CompilerConfig config = {0}; - - if (parse_arguments(argc, argv, &config) != 0) { - fprintf(stderr, "Usage: %s [-d] [-g] [-o] [file2.ul] ...\n", - argv[0]); - return 64; - } - - VM vm = {0}; - if (config.input_file_count == 0) { - repl(&vm); - } else { - for (i32 j = 0; j < config.input_file_count; j++) { - compileFile(config.input_files[j], &vm); - } - - if (config.flags & FLAG_DUMP_ROM) { - FILE *file = fopen("memory_dump.bin", "wb"); - if (!file) { - perror("Failed to open file"); - return EXIT_FAILURE; - } - - size_t code_written = fwrite(vm.code, 1, CODE_SIZE, file); - if (code_written != CODE_SIZE) { - fprintf(stderr, "Incomplete code write: %zu bytes written out of %llu\n", - code_written, CODE_SIZE); - fclose(file); - return EXIT_FAILURE; - } - - size_t memory_written = fwrite(vm.memory, 1, MEMORY_SIZE, file); - if (memory_written != MEMORY_SIZE) { - fprintf(stderr, - "Incomplete memory write: %zu bytes written out of %llu\n", - memory_written, MEMORY_SIZE); - fclose(file); - return EXIT_FAILURE; - } - - fclose(file); - } - } - bool running = true; - vm_register_device(&vm, "/dev/term/0", "terminal", nil, &console_device_ops); - - if (config.flags & FLAG_GUI_MODE) { - u32 i; - register_sdl_devices(&vm); - while (running) { - step_vm(&vm); - - for (i = 0; i < vm.dc; i++) { - Device *dev = &vm.devices[i]; - if (strcmp(dev->type, "screen") == 0) { - //ScreenDeviceData *screen = (ScreenDeviceData *)dev->data; - //vm.memory[screen->framebuffer_pos], - break; - } - } - } - } else { - while (running) { - running = step_vm(&vm); - } - } - - return 0; -} diff --git a/src/arch/linux/main.c b/src/arch/linux/main.c index ff72554..cebdef0 100644 --- a/src/arch/linux/main.c +++ b/src/arch/linux/main.c @@ -193,6 +193,25 @@ bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) { } } +bool init_vm(VM *vm) { + vm->memory = (u8*)malloc(MEMORY_SIZE * sizeof(u8)); + vm->memory_size = MEMORY_SIZE; + + vm->code = (u8*)malloc(CODE_SIZE * sizeof(u8)); + vm->code_size = CODE_SIZE; + + vm->frames = (Frame*)malloc(FRAMES_SIZE * sizeof(Frame)); + vm->frames_size = FRAMES_SIZE; + + vm->stack = (u32*)malloc(STACK_SIZE * sizeof(u32)) + vm->stack_size = STACK_SIZE; + + vm->devices = (Device*)malloc(DEVICES_SIZE * sizeof(Device)); + vm->devices_size = DEVICES_SIZE; + + return true; +} + i32 main(i32 argc, char *argv[]) { bool dump_rom = false; char *input_file = nil; @@ -226,8 +245,8 @@ i32 main(i32 argc, char *argv[]) { } } - VM *vm; - if (!init_vm(vm)) { + VM vm = {0}; + if (!init_vm(&vm)) { printf("vm did not initialize for some reason."); return 1; } @@ -236,19 +255,19 @@ i32 main(i32 argc, char *argv[]) { if (input_file) { if (is_rom) { // Load ROM file directly - compilation_success = loadVM(input_file, vm); + compilation_success = loadVM(input_file, &vm); } else if (is_assembly) { // Compile Lisp file if (dump_rom && output_file) { - compilation_success = assembleAndSave(input_file, output_file, vm); + compilation_success = assembleAndSave(input_file, output_file, &vm); } else { - compilation_success = assembleAndSave(input_file, nil, vm); + compilation_success = assembleAndSave(input_file, nil, &vm); } } else { if (dump_rom && output_file) { - compilation_success = compileAndSave(input_file, output_file, vm); + compilation_success = compileAndSave(input_file, output_file, &vm); } else { - compilation_success = compileAndSave(input_file, nil, vm); + compilation_success = compileAndSave(input_file, nil, &vm); } } } else { @@ -262,7 +281,7 @@ i32 main(i32 argc, char *argv[]) { // If dump_rom flag was set without specifying output file, use default if (dump_rom && !is_rom && !output_file) { - if (!saveVM("memory_dump.bin", vm)) { + if (!saveVM("memory_dump.bin", &vm)) { printf("Failed to save VM to memory_dump.bin\n"); return EXIT_FAILURE; } @@ -270,7 +289,7 @@ i32 main(i32 argc, char *argv[]) { return EXIT_SUCCESS; } - vm_register_device(vm, "/dev/term/0", "terminal", &console_data, + vm_register_device(&vm, "/dev/term/0", "terminal", &console_data, &console_device_ops, 4); if (SDL_Init(SDL_INIT_VIDEO) < 0) { @@ -283,7 +302,7 @@ i32 main(i32 argc, char *argv[]) { screen_data.height = 480; screen_data.buffer_size = screen_data.width * screen_data.height; - vm_register_device(vm, "/dev/screen/0", "screen", &screen_data, &screen_ops, + vm_register_device(&vm, "/dev/screen/0", "screen", &screen_data, &screen_ops, 16 + screen_data.buffer_size); mouse_data.x = 0; @@ -293,10 +312,10 @@ i32 main(i32 argc, char *argv[]) { mouse_data.btn3 = 0; mouse_data.btn4 = 0; - vm_register_device(vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops, 16); + vm_register_device(&vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops, 16); keyboard_data.keys = SDL_GetKeyboardState(&keyboard_data.key_count); - vm_register_device(vm, "/dev/keyboard/0", "keyboard", &keyboard_data, + vm_register_device(&vm, "/dev/keyboard/0", "keyboard", &keyboard_data, &keyboard_ops, keyboard_data.key_count + 4); SDL_Event event; @@ -365,7 +384,7 @@ i32 main(i32 argc, char *argv[]) { i32 cycles_this_frame = 0; i32 max_cycles_per_frame = 100; // Adjust this value while (cycles_this_frame < max_cycles_per_frame) { - if (!step_vm(vm)) { + if (!step_vm(&vm)) { running = false; break; } @@ -400,5 +419,5 @@ i32 main(i32 argc, char *argv[]) { } } - return vm->flag; + return vm.flag; } diff --git a/src/tools/assembler/assembler.c b/src/tools/assembler/assembler.c index 8f3b62c..7c3bf11 100644 --- a/src/tools/assembler/assembler.c +++ b/src/tools/assembler/assembler.c @@ -54,6 +54,34 @@ u32 get_ref(VM *vm, SymbolTable *st, const char *name, ScopeType scope) { return sym->ref; } +Token next_id_or_reg() { + Token token = next_token(); + if (token.type == TOKEN_IDENTIFIER) { + return token; + } + + if (token.type == TOKEN_BIG_MONEY) { + token = next_token(); + return token; + } + + printf("Not an ID or register at line %d: %.*s\n", token.line, token.length, + token.start); + exit(1); + + return token; +} + +Token next_id_or_ptr() { + Token token = next_token(); + if (token.type != TOKEN_IDENTIFIER || token.type != TOKEN_LITERAL_NAT) { + printf("Not an ID or register at line %d: %.*s\n", token.line, token.length, + token.start); + exit(1); + } + return token; +} + Token next_token_is(TokenType type) { Token token = next_token(); if (token.type != type) { @@ -313,8 +341,8 @@ void define_function(VM *vm, SymbolTable *st) { Token name = next_token_is(TOKEN_IDENTIFIER); if (name.length > MAX_SYMBOL_NAME_LENGTH) { - printf("FUNCITON NAME TOO LONG at line %d: %.*s\n", name.line, - name.length, name.start); + printf("FUNCITON NAME TOO LONG at line %d: %.*s\n", name.line, name.length, + name.start); exit(1); } memcpy(s.name, name.start, name.length); @@ -350,12 +378,12 @@ void define_branch(VM *vm, SymbolTable *st) { Token name = next_token_is(TOKEN_IDENTIFIER); if (name.length > MAX_SYMBOL_NAME_LENGTH) { - printf("BRANCH NAME TOO LONG at line %d: %.*s\n", name.line, - name.length, name.start); + printf("BRANCH NAME TOO LONG at line %d: %.*s\n", name.line, name.length, + name.start); exit(1); } memcpy(s.name, name.start, name.length); - + s.ref = vm->pc; symbol_table_add(st, s); } @@ -405,19 +433,19 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { vm->pc++; next_token_is(TOKEN_LITERAL_NAT); - vm->pc+=4; + vm->pc += 4; next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "call")) { vm->pc++; next_token_is(TOKEN_IDENTIFIER); - vm->pc+=4; + vm->pc += 4; vm->pc++; /* number of args (implied) */ Token next = next_token(); - while (next.type != TOKEN_ARROW_LEFT) { + while (next.type != TOKEN_ARROW_RIGHT) { vm->pc++; Token next = next_token(); } @@ -425,97 +453,1037 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { next = next_token(); vm->pc++; /* we emit a value regardless, a void is register 255 */ if (next.type == TOKEN_SEMICOLON) { + /* exit early because no return type */ continue; } /* if it is not void, then it was the value */ next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "syscall")) { + vm->pc++; + + Token id_or_ptr = next_id_or_ptr(); + vm->pc += 4; + + Token next = next_token(); + while (next.type != TOKEN_SEMICOLON) { + if (next.type != TOKEN_ARROW_RIGHT) { + vm->pc++; + } + Token next = next_token(); + } + } else if (streq(token.start, "return")) { + vm->pc++; + + Token next = next_token(); + if (next.type == TOKEN_SEMICOLON) { + /* put 0xFF as return register */ + vm->pc++; + continue; + } + + next_token_is(TOKEN_SEMICOLON); + vm->pc++; + } else if (streq(token.start, "load_immediate")) { - } else if (streq(token.start, "load_indirect_8")) { - } else if (streq(token.start, "load_indirect_16")) { - } else if (streq(token.start, "load_indirect_32")) { - } else if (streq(token.start, "load_absolute_8")) { - } else if (streq(token.start, "load_absolute_16")) { - } else if (streq(token.start, "load_absolute_32")) { - } else if (streq(token.start, "load_offset_8")) { - } else if (streq(token.start, "load_offset_16")) { - } else if (streq(token.start, "load_offset_32")) { - } else if (streq(token.start, "store_absolute_8")) { - } else if (streq(token.start, "store_absolute_16")) { - } else if (streq(token.start, "store_absolute_32")) { - } else if (streq(token.start, "store_indirect_8")) { - } else if (streq(token.start, "store_indirect_16")) { - } else if (streq(token.start, "store_indirect_32")) { - } else if (streq(token.start, "store_offset_8")) { - } else if (streq(token.start, "store_offset_16")) { - } else if (streq(token.start, "store_offset_32")) { + vm->pc++; + + Token id_or_ptr = next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token output = next_id_or_reg(); + vm->pc++; + } else if (streq(token.start, "malloc")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + } else if (streq(token.start, "memset_8")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + next_id_or_reg(); + vm->pc++; + next_id_or_reg(); + vm->pc++; + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "memset_16")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + next_id_or_reg(); + vm->pc++; + next_id_or_reg(); + vm->pc++; + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "memset_32")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + next_id_or_reg(); + vm->pc++; + next_id_or_reg(); + vm->pc++; + next_token_is(TOKEN_SEMICOLON); + + } else if (streq(token.start, "load_offset_8")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "load_offset_16")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "load_offset_32")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "load_indirect_8")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "load_indirect_16")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "load_indirect_32")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "load_absolute_8")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "load_absolute_16")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "load_absolute_32")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_absolute_8")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_absolute_16")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_absolute_32")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_indirect_8")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_indirect_16")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_indirect_32")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_offset_8")) { + vm->pc++; + + next_id_or_reg(); /* src1 */ + vm->pc++; + + next_token_is(TOKEN_LITERAL_NAT); /* offset */ + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); /* dest */ + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_offset_16")) { + vm->pc++; + + next_id_or_reg(); /* src1 */ + vm->pc++; + + next_token_is(TOKEN_LITERAL_NAT); /* offset */ + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); /* dest */ + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "store_offset_32")) { + vm->pc++; + + next_id_or_reg(); /* src1 */ + vm->pc++; + + next_token_is(TOKEN_LITERAL_NAT); /* offset */ + vm->pc += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); /* dest */ + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "register_move")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "add_int")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "sub_int")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "mul_int")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "div_int")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "abs_int")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "neg_int")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "add_nat")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "sub_nat")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "mul_nat")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "div_nat")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "abs_nat")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "neg_nat")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "add_real")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "sub_real")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "mul_real")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "div_real")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "abs_real")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "neg_real")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "int_to_real")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "nat_to_real")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "real_to_int")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "real_to_nat")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "bit_shift_left")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "bit_shift_right")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "bit_shift_r_ext")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "bit_and")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "bit_or")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "bit_xor")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_if_flag")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_eq_int")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_neq_int")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_gt_int")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_lt_int")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_le_int")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_ge_int")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_eq_nat")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_neq_nat")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_gt_nat")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_lt_nat")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_le_nat")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_ge_nat")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_eq_real")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_neq_real")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_ge_real")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_gt_real")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_lt_real")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "jump_le_real")) { + vm->pc++; + + next_id_or_ptr(); + vm->pc += 4; + + next_id_or_reg(); + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "string_length")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "int_to_string")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "nat_to_string")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); + } else if (streq(token.start, "real_to_string")) { + vm->pc++; + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_ARROW_RIGHT); + + next_id_or_reg(); + vm->pc++; + + next_token_is(TOKEN_SEMICOLON); } else if (streq(token.start, "string_eq")) { } else if (streq(token.start, "string_concat")) { } else if (streq(token.start, "string_get_char")) { } else if (streq(token.start, "string_find_char")) { } else if (streq(token.start, "string_slice")) { - } else if (streq(token.start, "int_to_string")) { - } else if (streq(token.start, "nat_to_string")) { - } else if (streq(token.start, "real_to_string")) { } else if (streq(token.start, "string_to_int")) { } else if (streq(token.start, "string_to_nat")) { } else if (streq(token.start, "string_to_real")) { } else { // some other identifier + printf("Unknown id at line %d: %.*s\n", token.line, token.length, + token.start); + exit(1); } } } while (token.type != TOKEN_EOF); @@ -534,8 +1502,8 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { break; } if (token.type != TOKEN_EOF) { - printf("Line %d [%s]: %.*s\n", token.line, token_type_to_string(token.type), - token.length, token.start); + printf("Line %d [%s]: %.*s\n", token.line, + token_type_to_string(token.type), token.length, token.start); if (token.type == TOKEN_KEYWORD_GLOBAL) { // ignore, already processed @@ -562,6 +1530,7 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { // check to see if it is an opcode first if (streq(token.start, "exit")) { } else if (streq(token.start, "call")) { + } else if (streq(token.start, "return")) { } else if (streq(token.start, "syscall")) { } else if (streq(token.start, "load_immediate")) { } else if (streq(token.start, "load_indirect_8")) { @@ -661,6 +1630,7 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { void assemble(VM *vm, char *source) { SymbolTable *st = symbol_table_init(); build_symbol_table(vm, source, st); + vm->pc = 0; /* actuall start emitting code */ emit_bytecode(vm, source, st); free(st->symbols); free(st); diff --git a/src/tools/assembler/lexer.h b/src/tools/assembler/lexer.h index 3d8ad1a..debd5ce 100644 --- a/src/tools/assembler/lexer.h +++ b/src/tools/assembler/lexer.h @@ -71,7 +71,7 @@ typedef enum { TOKEN_RBRACE, TOKEN_LBRACKET, TOKEN_RBRACKET, - TOKEN_ARROW_LEFT, + TOKEN_ARROW_RIGHT, TOKEN_ERROR } TokenType; diff --git a/src/tools/compiler/lexer.c b/src/tools/compiler/lexer.c index 490e952..291a3a3 100644 --- a/src/tools/compiler/lexer.c +++ b/src/tools/compiler/lexer.c @@ -348,7 +348,7 @@ Token next_token() { case '.': return makeToken(TOKEN_DOT); case '-': - return makeToken(match('>') ? TOKEN_ARROW_LEFT : TOKEN_MINUS); + return makeToken(match('>') ? TOKEN_ARROW_RIGHT : TOKEN_MINUS); case '+': return makeToken(TOKEN_PLUS); case '/': @@ -492,8 +492,8 @@ const char *token_type_to_string(TokenType type) { return "LBRACKET"; case TOKEN_RBRACKET: return "RBRACKET"; - case TOKEN_ARROW_LEFT: - return "ARROW_LEFT"; + case TOKEN_ARROW_RIGHT: + return "ARROW_RIGHT"; case TOKEN_MESH: return "MESH"; case TOKEN_BIG_MONEY: diff --git a/src/tools/compiler/lexer.h b/src/tools/compiler/lexer.h index 3e0ab11..5f83f08 100644 --- a/src/tools/compiler/lexer.h +++ b/src/tools/compiler/lexer.h @@ -67,7 +67,7 @@ typedef enum { TOKEN_RBRACE, TOKEN_LBRACKET, TOKEN_RBRACKET, - TOKEN_ARROW_LEFT, + TOKEN_ARROW_RIGHT, TOKEN_ERROR } TokenType; diff --git a/test/paint.ul.ir b/test/paint.ul.ir index 97b8fdf..a7854d4 100644 --- a/test/paint.ul.ir +++ b/test/paint.ul.ir @@ -1,10 +1,10 @@ -global const str screen_namespace = "/dev/screen/0"; -global const str mouse_namespace = "/dev/mouse/0"; -global const byte BLACK = 0; -global const byte WHITE = 255; -global const byte DARK_GRAY = 73; -global const byte GRAY = 146; -global const byte LIGHT_GRAY = 182; +global str screen_namespace = "/dev/screen/0"; +global str mouse_namespace = "/dev/mouse/0"; +global byte BLACK = 0; +global byte WHITE = 255; +global byte DARK_GRAY = 73; +global byte GRAY = 146; +global byte LIGHT_GRAY = 182; global byte SELECTED_COLOR = 255; function main () @@ -114,7 +114,7 @@ function set_color_if_clicked (int click_x $0, int click_y $1, jump_lt_int fail click_y box_y; jump_ge_int fail click_y bottom_edge; - store_absolute_8 SELECTED_COLOR color; + store_absolute_8 color -> SELECTED_COLOR; else fail return;