diff --git a/arch/linux/tui/main.c b/arch/linux/tui/main.c index 4ae1b74..fee067d 100644 --- a/arch/linux/tui/main.c +++ b/arch/linux/tui/main.c @@ -1,6 +1,5 @@ #include "../../../vm/vm.h" #include -#include #define CODE_SIZE 8192 #define MEMORY_SIZE 65536 @@ -9,7 +8,6 @@ u32 lcode[CODE_SIZE] = {0}; bool init_vm() { mem = lmem; - memset(mem, 0, MEMORY_SIZE*sizeof(u8)); code = lcode; lc = 0; mp = 0; @@ -87,7 +85,6 @@ void test_fibonacci() { code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 3); code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0); /* function fib (int n) int */ - //code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_DBG_PRINT, 1, 0); code[cp++] = ENCODE_B(OP_LOAD_IMM, 8, fib); code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, 2); code[cp++] = ENCODE_B(OP_LOAD_IMM, 2, base_case); @@ -113,9 +110,9 @@ void test_hello() { i32 main_local_count = 3; mp += (4 * main_local_count); code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, hello); - code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 12, 0); + code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 0, 0); code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, new_line); - code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 0); + code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 0, 0); code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0); } diff --git a/build b/build index b53db51..a1bb77e 100755 --- a/build +++ b/build @@ -69,7 +69,7 @@ case $MODE in BUILD_FLAGS="-g -Wall -Wextra -Werror -pedantic" ;; "release") - BUILD_FLAGS="-O2 -Wall -Wextra -Werror -pedantic" + BUILD_FLAGS="-Ofast -Wall -Wextra -Werror -pedantic" ;; esac diff --git a/test/add.ul b/test/add.ul new file mode 100644 index 0000000..7c61a9a --- /dev/null +++ b/test/add.ul @@ -0,0 +1,29 @@ +/** + * Plexes + */ +plex Terminal { + nat handle; +} + +/** + * Main function + */ +function main() { + pln(add(1, 1) as str); +} + +/** + * Add two numbers together + */ +function add(int a, int b) int { + return a + b; +} + +/** + * Print with a newline + */ +function pln(str message) { + Terminal term = open("/dev/term/0", 0); + term.write(message); + term.write("\n"); +} diff --git a/test/fib.ul b/test/fib.ul new file mode 100644 index 0000000..aafa25a --- /dev/null +++ b/test/fib.ul @@ -0,0 +1,30 @@ +/** + * Plexes + */ +plex Terminal { + nat handle; +} + +/** + * Main function + */ +function main() { + pln(fib(35) as str); +} + +/** + * Recursively calculate fibonacci + */ +function fib(int n) int { + if (n < 2) return n; + return fib(n - 2) + fib(n - 1); +} + +/** + * Print with a newline + */ +function pln(str message) { + Terminal term = open("/dev/term/0", 0); + term.write(message); + term.write("\n"); +} diff --git a/test/hello.ul b/test/hello.ul new file mode 100644 index 0000000..fba0a86 --- /dev/null +++ b/test/hello.ul @@ -0,0 +1,22 @@ +/** + * Plexes + */ +plex Terminal { + nat handle; +} + +/** + * Main function + */ +function main() { + pln("nuqneH 'u'?"); +} + +/** + * Print with a newline + */ +function pln(str message) { + Terminal term = open("/dev/term/0", 0); + term.write(message); + term.write("\n"); +} diff --git a/test/malloc.ul b/test/malloc.ul new file mode 100644 index 0000000..1561655 --- /dev/null +++ b/test/malloc.ul @@ -0,0 +1,26 @@ +/** + * Plexes + */ +plex Terminal { + nat handle; +} + + +/** + * Main function + */ +function main() { + Terminal term = open("/dev/term/0", 0); + pln("Enter a string: "); + pln(term.read(32) as str); + return 0; +} + +/** + * Print with a newline + */ +function pln(str message) { + Terminal term = open("/dev/term/0", 0); + term.write(message); + term.write("\n"); +} diff --git a/test/paint.ul b/test/paint.ul new file mode 100644 index 0000000..568395e --- /dev/null +++ b/test/paint.ul @@ -0,0 +1,108 @@ +/** + * Constants + */ +const byte BLACK = 0; +const byte WHITE = 255; +const byte DARK_GRAY = 73; +const byte GRAY = 146; +const byte LIGHT_GRAY = 182; + +byte selected_color = 255; + +trait Device { + nat handle; +} + +plex Screen implements Device { + nat handle; + nat width; + nat height; + byte[] buffer; + + draw() { + this.write(this.buffer); + } +} + +plex Mouse implements Device { + nat handle; + nat x; + nat y; + bool left; + bool right; + bool middle; + bool btn4; +} + +/** + * Main function + */ +function main() { + Screen screen = open("/dev/screen/0", 0); + Mouse mouse = open("/dev/mouse/0", 0); + + outline_swatch(screen, BLACK, 1, 1); + outline_swatch(screen, WHITE, 21, 1); + screen.draw(); + + loop { + if (!mouse.left) continue; + + int box_size = 20; + int x = 1; + int y = 1; + byte color = BLACK; + outlined_swatch(screen, color, x, y); + set_color(box_size, x, y, mouse.x, mouse.y, color); + + color = WHITE; + x = 21; + outlined_swatch(screen, color, x, y); + set_color(box_size, x, y, mouse.x, mouse.y, color); + screen.draw(); + + rectangle(screen, selected_color, x, y, 5, 5); + } + exit(0); +} + +/** + * Checks if the click is within the bound and update the selected color if so. + */ +function set_color(int box_size, int bx, int by, int mx, int my, byte color) { + int right = bx + box_size; + int bottom = by + box_size; + + if (mx < bx) return; + if (mx > right) return; + if (my < by) return; + if (my > bottom) return; + + selected_color = color; +} + +/** + * Draw a color box with a grey outline, if selected use a darker color + */ +function outline_swatch(Device screen, byte color, int x, int y) { + byte bg_color = GRAY; + if (selected_color == color) { + bg_color = DARK_GRAY; + } + + rectangle(screen, bg_color, x, y, 20, 20); + rectangle(screen, color, x + 2, y + 2, 17, 17); +} + +/** + * Draw a rectangle + */ +function rectangle(Device screen, byte color, int x, int y, int width, int height) { + int base = y * screen.width + x + screen.buffer.ptr + 4; + + do (int i = height; i > 0; i--) { + int row = base + width; + memset(screen.buffer, row, color, width); + base += screen.width; + } +} diff --git a/test/simple.ul b/test/simple.ul new file mode 100644 index 0000000..459abcd --- /dev/null +++ b/test/simple.ul @@ -0,0 +1,25 @@ +/** + * Constants + */ +const str nl = "\n"; + +plex Terminal { + nat handle; +} + +/** + * Main function + */ +function main() { + pln((1.0 + 1.0) as str); + exit(0); +} + +/** + * Print with a newline + */ +function pln(str message) { + Terminal term = open("/dev/term/0", 0); + write(term, message, message.length); + write(term, nl, nl.length); +} diff --git a/test/window.ul b/test/window.ul new file mode 100644 index 0000000..8b31ac5 --- /dev/null +++ b/test/window.ul @@ -0,0 +1,72 @@ +/** + * Constants + */ +const str screen_namespace = "/dev/screen/0" +const str mouse_namespace = "/dev/mouse/0" +const str terminal_namespace = "/dev/term/0" +const str new_line = "\n" +const byte WHITE = 255 + +/** + * Devices + */ +plex Terminal { + nat handle; +} + +plex Screen { + nat handle; + nat width; + nat height; + byte[] buffer; + + draw() { + write(this, this.buffer, this.buffer_size); + } +} + +plex Mouse { + nat handle; + nat x; + nat y; + bool left; + bool right; + bool middle; + bool btn4; + nat size; +} + +/** + * Main function + */ +function main() { + Screen screen = open(screen_namespace, 0); + pln(screen.handle as str); + pln(screen.width as str); + pln(screen.size as str); + unsafe { + pln(screen.screen_buffer.ptr as str); + } + + Mouse mouse = open(mouse_namespace, 0); + screen.draw(); + + loop { + if (mouse.left) { + unsafe { + screen.buffer[mouse.y * width + mouse.x + + screen.buffer.ptr + 4] = WHITE; + screen.draw(); + } + } + } +} + +/** + * Print with a newline + */ +function pln(str message) { + Terminal term = open(terminal_namespace, 0); + write(term, message, message.length); + write(term, nl, nl.length); +} diff --git a/tools/assembler/assembler.c b/tools/assembler/assembler.c deleted file mode 100644 index e51785e..0000000 --- a/tools/assembler/assembler.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "assembler.h" -/** - * Emit bytecode to the VM from the source string. - */ -void assemble(char *source, ScopeTable *st) { - -} diff --git a/tools/assembler/assembler.h b/tools/assembler/assembler.h deleted file mode 100644 index 6ce7cc4..0000000 --- a/tools/assembler/assembler.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef UNDAR_IR_ASSEMBLER_H -#define UNDAR_IR_ASSEMBLER_H - -#include "../../vm/libc.h" -#include "lexer.h" - -typedef enum { GLOBAL, LOCAL, VAR } ScopeType; -typedef enum { - VOID, - BOOL, - I8, - I16, - I32, - U8, - U16, - U32, - F8, - F16, - F32, - STR, - PLEX, - ARRAY, - FUNCTION -} SymbolType; - -typedef struct symbol_s Symbol; -typedef struct symbol_tab_s SymbolTable; -typedef struct scope_tab_s ScopeTable; - -#define MAX_SYMBOL_NAME_LENGTH 64 -struct symbol_s { - char name[MAX_SYMBOL_NAME_LENGTH]; - u8 name_length; - SymbolType type; - ScopeType scope; - u32 ref; // vm->mp if global, vm->pc local, register if var - u32 size; // size of symbol -}; - -struct symbol_tab_s { - Symbol symbols[256]; - u8 count; - i32 parent; -}; - -struct scope_tab_s { - SymbolTable *scopes; - u32 count; - u32 capacity; - i32 scope_ref; -}; - -void assemble(char *source, ScopeTable *st); - -#endif diff --git a/tools/assembler/lexer.c b/tools/assembler/lexer.c deleted file mode 100644 index cd62088..0000000 --- a/tools/assembler/lexer.c +++ /dev/null @@ -1,401 +0,0 @@ -#include - -#include "../../vm/libc.h" -#include "lexer.h" - -typedef struct { - const char *start; - const char *current; - i32 line; -} Lexer; - -Lexer lexer; - -void init_lexer(const char *source) { - lexer.start = source; - lexer.current = source; - lexer.line = 1; -} - -static bool is_alpha(char c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; -} - -static bool is_digit(char c) { return c >= '0' && c <= '9'; } - -static bool is_at_end() { return *lexer.current == '\0'; } - -static char advance() { - lexer.current++; - return lexer.current[-1]; -} - -static char peek() { return *lexer.current; } - -static char peek_next() { - if (is_at_end()) - return '\0'; - return lexer.current[1]; -} - -static bool match(char expected) { - if (is_at_end()) - return false; - if (*lexer.current != expected) - return false; - lexer.current++; - return true; -} - -static Token make_token(TokenType type) { - Token token; - token.type = type; - token.start = lexer.start; - token.length = (i32)(lexer.current - lexer.start); - token.line = lexer.line; - return token; -} - -static Token error_token(const char *message) { - Token token; - token.type = TOKEN_ERROR; - token.start = message; - token.length = (i32)strlen(message); - token.line = lexer.line; - return token; -} - -static void skip_whitespace() { - for (;;) { - char c = peek(); - switch (c) { - case ' ': - case '\r': - case '\t': - advance(); - break; - case '\n': - lexer.line++; - advance(); - break; - case '/': - if (peek_next() == '/') { - // Single-line comment: skip until newline or end of file - advance(); - while (peek() != '\n' && !is_at_end()) - advance(); - } else if (peek_next() == '*') { - // Multi-line comment: skip until '*/' or end of file - advance(); - advance(); - while (!is_at_end()) { - if (peek() == '\n') - lexer.line++; - if (peek() == '*' && peek_next() == '/') { - advance(); - advance(); - break; // Exit loop, comment ended - } - advance(); - } - } else { - return; // Not a comment, let tokenization handle it - } - break; - default: - return; - } - } -} - -static TokenType check_keyword(i32 start, i32 length, const char *rest, - TokenType type) { - if (lexer.current - lexer.start == start + length && - memcmp(lexer.start + start, rest, length) == 0) { - return type; - } - - return TOKEN_IDENTIFIER; -} - -static TokenType identifierType() { - switch (lexer.start[0]) { - case 'a': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'n': - return check_keyword(2, 1, "d", TOKEN_OPERATOR_AND); - case 's': - return check_keyword(2, 0, "", TOKEN_KEYWORD_AS); - } - } - break; - case 'c': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'l': - return check_keyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE); - case 'o': - return check_keyword(2, 3, "nst", TOKEN_KEYWORD_CONST); - } - } - break; - case 'e': - return check_keyword(1, 3, "lse", TOKEN_KEYWORD_ELSE); - case 'f': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'a': - return check_keyword(2, 3, "lse", TOKEN_KEYWORD_FALSE); - case 'o': - return check_keyword(2, 1, "r", TOKEN_KEYWORD_FOR); - case '3': - return check_keyword(1, 1, "2", TOKEN_TYPE_REAL); - } - return check_keyword(1, 7, "unction", TOKEN_KEYWORD_FN); - } - break; - case 'i': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'f': - return check_keyword(2, 0, "", TOKEN_KEYWORD_IF); - case 's': - return check_keyword(2, 0, "", TOKEN_KEYWORD_IS); - case '8': - return check_keyword(2, 0, "", TOKEN_TYPE_I8); - case '1': - return check_keyword(2, 1, "6", TOKEN_TYPE_I16); - case '3': - return check_keyword(2, 1, "2", TOKEN_TYPE_INT); - case 'n': - if (lexer.current - lexer.start > 2) { - switch (lexer.start[2]) { - case 'i': - return check_keyword(3, 2, "t", TOKEN_KEYWORD_INIT); - case 't': - return check_keyword(3, 0, "", TOKEN_TYPE_INT); - } - } - break; - } - } - break; - case 'n': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'a': - return check_keyword(2, 1, "t", TOKEN_TYPE_NAT); - case 'i': - return check_keyword(2, 1, "l", TOKEN_KEYWORD_NIL); - } - } - break; - case 'o': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'p': - return check_keyword(2, 2, "en", TOKEN_KEYWORD_OPEN); - case 'r': - return check_keyword(2, 0, "", TOKEN_OPERATOR_OR); - } - } - break; - case 'p': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'l': - return check_keyword(2, 2, "ex", TOKEN_KEYWORD_PLEX); - } - } - break; - case 'r': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'e': - if (lexer.current - lexer.start > 2) { - switch (lexer.start[2]) { - case 'f': - return check_keyword(3, 4, "resh", TOKEN_KEYWORD_REFRESH); - case 't': - return check_keyword(3, 3, "urn", TOKEN_KEYWORD_RETURN); - case 'a': - if (lexer.current - lexer.start > 3) { - switch(lexer.start[3]) { - case 'd': - return check_keyword(4, 0, "", TOKEN_KEYWORD_READ); - case 'l': - return check_keyword(4, 0, "", TOKEN_TYPE_REAL); - } - } - } - } - break; - } - } - break; - case 's': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 't': - return check_keyword(2, 1, "r", TOKEN_TYPE_STR); - } - } - break; - case 't': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'h': - return check_keyword(2, 2, "is", TOKEN_KEYWORD_THIS); - case 'r': - return check_keyword(2, 2, "ue", TOKEN_KEYWORD_TRUE); - } - } - break; - case 'u': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 's': - return check_keyword(2, 1, "e", TOKEN_KEYWORD_USE); - case '8': - return check_keyword(2, 0, "", TOKEN_TYPE_U8); - case '1': - return check_keyword(2, 1, "6", TOKEN_TYPE_U16); - case '3': - return check_keyword(2, 1, "2", TOKEN_TYPE_NAT); - } - } - break; - case 'w': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'h': - return check_keyword(2, 3, "ile", TOKEN_KEYWORD_WHILE); - case 'r': - return check_keyword(2, 3, "ite", TOKEN_KEYWORD_WRITE); - } - } - break; - case 'b': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { - case 'y': - return check_keyword(2, 2, "te", TOKEN_TYPE_U8); - case 'o': - return check_keyword(2, 2, "ol", TOKEN_TYPE_U8); - } - } - break; - case 'g': - return check_keyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL); - case 'l': - return check_keyword(1, 3, "oop", TOKEN_KEYWORD_LOOP); - case 'd': - return check_keyword(1, 1, "o", TOKEN_KEYWORD_DO); - case 'v': - return check_keyword(1, 3, "oid", TOKEN_TYPE_VOID); - } - - return TOKEN_IDENTIFIER; -} - -static Token identifier() { - while (is_alpha(peek()) || is_digit(peek())) - advance(); - return make_token(identifierType()); -} - -static Token number() { - while (is_digit(peek())) - advance(); - - /* Look for a fractional part. */ - if (peek() == '.' && is_digit(peek_next())) { - /* Consume the ".". */ - advance(); - - while (is_digit(peek())) - advance(); - - return make_token(TOKEN_LITERAL_REAL); - } - - return make_token(TOKEN_LITERAL_INT); -} - -static Token string() { - while (peek() != '"' && !is_at_end()) { - if (peek() == '\n') - lexer.line++; - advance(); - } - - if (is_at_end()) - return error_token("Unterminated string."); - - /* The closing quote. */ - advance(); - return make_token(TOKEN_LITERAL_STR); -} - -Token next_token() { - skip_whitespace(); - lexer.start = lexer.current; - - if (is_at_end()) - return make_token(TOKEN_EOF); - - char c = advance(); - if (is_alpha(c)) - return identifier(); - char next = peek(); - if ((c == '-' && is_digit(next)) || is_digit(c)) - return number(); - - switch (c) { - case '(': - return make_token(TOKEN_LPAREN); - case ')': - return make_token(TOKEN_RPAREN); - case '{': - return make_token(TOKEN_LBRACE); - case '}': - return make_token(TOKEN_RBRACE); - case '[': - return make_token(TOKEN_LBRACKET); - case ']': - return make_token(TOKEN_RBRACKET); - case ';': - return make_token(TOKEN_SEMICOLON); - case ',': - return make_token(TOKEN_COMMA); - case '.': - return make_token(TOKEN_DOT); - case '-': - return make_token(match('>') ? TOKEN_ARROW_RIGHT : TOKEN_MINUS); - case '+': - return make_token(TOKEN_PLUS); - case '/': - return make_token(TOKEN_SLASH); - case '&': - return make_token(match('&') ? TOKEN_AND_AND : TOKEN_AND); - case '#': - return make_token(TOKEN_MESH); - case '$': - return make_token(TOKEN_BIG_MONEY); - case '*': - return make_token(TOKEN_STAR); - case '!': - return make_token(match('=') ? TOKEN_BANG_EQ : TOKEN_BANG); - case '=': - return make_token(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ); - case '<': - return make_token(match('=') ? TOKEN_LTE : TOKEN_LT); - case '>': - return make_token(match('=') ? TOKEN_GTE : TOKEN_GT); - case '"': - return string(); - } - - return error_token("Unexpected character."); -} diff --git a/tools/compiler.c b/tools/compiler.c new file mode 100644 index 0000000..06f87a1 --- /dev/null +++ b/tools/compiler.c @@ -0,0 +1,152 @@ +#include "parser.h" +#include "compiler.h" + +#include +#include + +Symbol *symbol_table_lookup(ScopeTable *table, const char *name, u32 length, + i32 scope_ref) { + SymbolTable st = table->scopes[scope_ref]; + for (u32 i = 0; i < st.count; i++) { + if (st.symbols[i].name_length == length) { + if (sleq(st.symbols[i].name, name, length)) { + return &table->scopes[scope_ref].symbols[i]; + } + } + } + if (st.parent < 0) + return nil; + return symbol_table_lookup(table, name, length, st.parent); +} + +u8 symbol_table_add(ScopeTable *table, Symbol s) { + Symbol *sym = + symbol_table_lookup(table, s.name, s.name_length, table->scope_ref); + if (sym != nil) { + fprintf(stderr, + "Error: Symbol '%.*s' already defined, in this scope" + " please pick a different variable name or create a new scope.\n", + s.name_length, s.name); + exit(1); + } + + if (table->scopes[table->scope_ref].count + 1 > 255) { + fprintf(stderr, "Error: Only 255 symbols are allowed per scope" + " first off: impressive; secondly:" + " just create a new scope and keep going.\n"); + exit(1); + } + + if (!table_realloc(table)) { + fprintf(stderr, + "Error: Symbol table is out of memory! This is likely because you " + " built the assembler in static mode, increase the static size." + " if you built using malloc, that means your computer is out of" + " memory. Close a few tabs in your web browser and try again." + " Count was %d, while capacity was %d\n", + table->count, table->capacity); + exit(1); + } + + table->scopes[table->scope_ref].symbols[table->scopes[table->scope_ref].count] = s; + u8 index = table->scopes[table->scope_ref].count; + table->scopes[table->scope_ref].count++; + return index; +} + +u32 get_ref(ScopeTable *st, const char *name, u32 length) { + Symbol *sym = symbol_table_lookup(st, name, length, st->scope_ref); + if (!sym) { + fprintf(stderr, "Error: Assembler has no idea what Symbol '%.*s' means.\n", + length, name); + exit(1); + return 0; + } + return sym->ref; +} + +u32 get_ptr(Token token, ScopeTable *st) { + if (token.type == TOKEN_IDENTIFIER) { + return get_ref(st, token.start, token.length); + } + + if (token.type == TOKEN_LITERAL_INT) { + return atoi(token.start); + } + + if (token.type == TOKEN_LITERAL_NAT) { + char *endptr; + u32 out = (u32)strtoul(token.start, &endptr, 10); + if (endptr == token.start || *endptr != '\0') { + fprintf(stderr, "Invalid decimal literal at line %d: %.*s\n", token.line, + token.length, token.start); + exit(1); + } + return out; + } + + fprintf(stderr, "Error: Not a pointer or symbol at line %d: %.*s\n", + token.line, token.length, token.start); + exit(1); +} + +u32 get_reg(Token token, ScopeTable *st) { + if (token.type == TOKEN_IDENTIFIER) { + return get_ref(st, token.start, token.length); + } + + if (token.type == TOKEN_BIG_MONEY) { + token = next_token(); + return atoi(token.start); + } + + fprintf(stderr, "Error: Not a register or symbol at line %d: %.*s\n", + token.line, token.length, token.start); + exit(1); +} + +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 && + token.type != TOKEN_LITERAL_INT && token.type != TOKEN_LITERAL_REAL) { + 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) { + printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); + exit(1); + } + return token; +} + +/** + * Compile. + */ +bool compile(ScopeTable *st, char *source) { + return false; +} diff --git a/tools/compiler.h b/tools/compiler.h new file mode 100644 index 0000000..d55aebb --- /dev/null +++ b/tools/compiler.h @@ -0,0 +1,88 @@ +#ifndef UNDAR_COMPILER_H +#define UNDAR_COMPILER_H + +#include "../vm/libc.h" +#include "../vm/vm.h" + +typedef enum { GLOBAL, LOCAL, VAR } ScopeType; +typedef enum { + VOID, + BOOL, + I8, + I16, + I32, + U8, + U16, + U32, + F8, + F16, + F32, + STR, + PLEX, + ARRAY, + FUNCTION +} SymbolType; + +typedef struct symbol_s Symbol; +typedef struct symbol_tab_s SymbolTable; +typedef struct value_type_s ValueType; +typedef struct plex_fields_tab_s PlexFieldsTable; +typedef struct plex_def_s PlexDef; +typedef struct plex_tab_s PlexTable; +typedef struct scope_s Scope; +typedef struct scope_tab_s ScopeTable; + +struct value_type_s { + SymbolType type; + u32 name; + u32 size; + u32 table_ref; // if it is a heap object +}; + +struct plex_def_s { + u32 name; + u32 size; + u32 field_ref_start; + u32 field_count; +}; + +struct plex_fields_tab_s { + u32 *plex_refs; + ValueType *fields; + u32 count; + u32 capacity; +}; + +struct plex_tab_s { + PlexDef *symbols; + u32 count; + u32 capacity; +}; + +#define MAX_SYMBOL_NAME_LENGTH 64 +struct symbol_s { + char name[MAX_SYMBOL_NAME_LENGTH]; + u8 name_length; + SymbolType type; + ScopeType scope; + u32 ref; // vm->mp if global, vm->pc local, register if var + u32 size; // size of symbol +}; + +struct symbol_tab_s { + Symbol symbols[256]; + u8 count; + i32 parent; +}; + +struct scope_tab_s { + SymbolTable *scopes; + u32 count; + u32 capacity; + i32 scope_ref; +}; + +bool compile(ScopeTable *st, char *source); +extern bool table_realloc(ScopeTable *table);/* implement this in arch/ not here */ + +#endif diff --git a/tools/parser.c b/tools/parser.c new file mode 100644 index 0000000..01d8245 --- /dev/null +++ b/tools/parser.c @@ -0,0 +1,507 @@ +#include "parser.h" + +typedef struct { + const char *start; + const char *current; + int line; +} Lexer; + +Lexer lexer; + +void initLexer(const char *source) { + lexer.start = source; + lexer.current = source; + lexer.line = 1; +} + +static bool isAlpha(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; +} + +static bool isDigit(char c) { return c >= '0' && c <= '9'; } + +static bool isAtEnd() { return *lexer.current == '\0'; } + +static char advance() { + lexer.current++; + return lexer.current[-1]; +} + +static char peek() { return *lexer.current; } + +static char peekNext() { + if (isAtEnd()) + return '\0'; + return lexer.current[1]; +} + +static bool match(char expected) { + if (isAtEnd()) + return false; + if (*lexer.current != expected) + return false; + lexer.current++; + return true; +} + +static Token makeToken(TokenType type) { + Token token; + token.type = type; + token.start = lexer.start; + token.length = (int)(lexer.current - lexer.start); + token.line = lexer.line; + return token; +} + +static Token errorToken(const char *message) { + Token token; + token.type = TOKEN_ERROR; + token.start = message; + token.length = (int)slen(message); + token.line = lexer.line; + return token; +} + +static void skipWhitespace() { + for (;;) { + char c = peek(); + switch (c) { + case ' ': + case '\r': + case '\t': + advance(); + break; + case '\n': + lexer.line++; + advance(); + break; + case '/': + if (peekNext() == '/') { + // Single-line comment: skip until newline or end of file + advance(); + while (peek() != '\n' && !isAtEnd()) + advance(); + } else if (peekNext() == '*') { + // Multi-line comment: skip until '*/' or end of file + advance(); + advance(); + while (!isAtEnd()) { + if (peek() == '\n') + lexer.line++; + if (peek() == '*' && peekNext() == '/') { + advance(); + advance(); + break; // Exit loop, comment ended + } + advance(); + } + } else { + return; // Not a comment, let tokenization handle it + } + break; + default: + return; + } + } +} + +static TokenType checkKeyword(int start, int length, const char *rest, + TokenType type) { + if (lexer.current - lexer.start == start + length && + sleq(lexer.start + start, rest, length)) { + return type; + } + + return TOKEN_IDENTIFIER; +} + +static TokenType identifierType() { + switch (lexer.start[0]) { + case 'a': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'n': + return checkKeyword(2, 1, "d", TOKEN_OPERATOR_AND); + case 's': + return checkKeyword(2, 0, "", TOKEN_KEYWORD_AS); + } + } + break; + case 'c': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'l': + return checkKeyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE); + case 'o': + return checkKeyword(2, 3, "nst", TOKEN_KEYWORD_CONST); + } + } + break; + case 'e': + return checkKeyword(1, 3, "lse", TOKEN_KEYWORD_ELSE); + case 'f': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'a': + return checkKeyword(2, 3, "lse", TOKEN_KEYWORD_FALSE); + case 'o': + return checkKeyword(2, 1, "r", TOKEN_KEYWORD_FOR); + case '3': + return checkKeyword(2, 1, "2", TOKEN_TYPE_REAL); + } + return checkKeyword(1, 7, "unction", TOKEN_KEYWORD_FN); + } + break; + case 'i': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'f': + return checkKeyword(2, 0, "", TOKEN_KEYWORD_IF); + case 's': + return checkKeyword(2, 0, "", TOKEN_KEYWORD_IS); + case '8': + return checkKeyword(2, 0, "", TOKEN_TYPE_I8); + case '1': + return checkKeyword(2, 1, "6", TOKEN_TYPE_I16); + case '3': + return checkKeyword(2, 1, "2", TOKEN_TYPE_INT); + case 'n': + if (lexer.current - lexer.start > 2) { + switch (lexer.start[2]) { + case 'i': + return checkKeyword(3, 2, "t", TOKEN_KEYWORD_INIT); + case 't': + return checkKeyword(3, 0, "", TOKEN_TYPE_INT); + } + } + break; + } + } + break; + case 'n': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'a': + return checkKeyword(2, 1, "t", TOKEN_TYPE_NAT); + case 'i': + return checkKeyword(2, 1, "l", TOKEN_KEYWORD_NIL); + } + } + break; + case 'o': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'p': + return checkKeyword(2, 2, "en", TOKEN_KEYWORD_OPEN); + case 'r': + return checkKeyword(2, 0, "", TOKEN_OPERATOR_OR); + } + } + break; + case 'p': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'l': + return checkKeyword(2, 2, "ex", TOKEN_KEYWORD_PLEX); + } + } + break; + case 'r': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'e': + if (lexer.current - lexer.start > 2) { + switch (lexer.start[2]) { + case 'a': + return checkKeyword(3, 1, "d", TOKEN_KEYWORD_READ); + case 'f': + return checkKeyword(3, 4, "resh", TOKEN_KEYWORD_REFRESH); + case 't': + return checkKeyword(3, 3, "urn", TOKEN_KEYWORD_RETURN); + } + } + break; + } + } + break; + case 's': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 't': + return checkKeyword(2, 1, "r", TOKEN_TYPE_STR); + } + } + break; + case 't': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'h': + return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS); + case 'r': + return checkKeyword(2, 2, "ue", TOKEN_KEYWORD_TRUE); + } + } + break; + case 'u': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 's': + return checkKeyword(2, 1, "e", TOKEN_KEYWORD_USE); + case '8': + return checkKeyword(2, 0, "", TOKEN_TYPE_U8); + case '1': + return checkKeyword(2, 1, "6", TOKEN_TYPE_U16); + case '3': + return checkKeyword(2, 1, "2", TOKEN_TYPE_NAT); + } + } + break; + case 'w': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'h': + return checkKeyword(2, 3, "ile", TOKEN_KEYWORD_WHILE); + case 'r': + return checkKeyword(2, 3, "ite", TOKEN_KEYWORD_WRITE); + } + } + break; + case 'g': + return checkKeyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL); + } + + return TOKEN_IDENTIFIER; +} + +static Token identifier() { + while (isAlpha(peek()) || isDigit(peek())) + advance(); + return makeToken(identifierType()); +} + +static Token number() { + while (isDigit(peek())) + advance(); + + /* Look for a fractional part. */ + if (peek() == '.' && isDigit(peekNext())) { + /* Consume the ".". */ + advance(); + + while (isDigit(peek())) + advance(); + + return makeToken(TOKEN_LITERAL_REAL); + } + + return makeToken(TOKEN_LITERAL_INT); +} + +static Token string() { + while (peek() != '"' && !isAtEnd()) { + if (peek() == '\n') + lexer.line++; + advance(); + } + + if (isAtEnd()) + return errorToken("Unterminated string."); + + /* The closing quote. */ + advance(); + return makeToken(TOKEN_LITERAL_STR); +} + +Token next_token() { + skipWhitespace(); + lexer.start = lexer.current; + + if (isAtEnd()) + return makeToken(TOKEN_EOF); + + char c = advance(); + if (isAlpha(c)) + return identifier(); + if (isDigit(c)) + return number(); + + switch (c) { + case '(': + return makeToken(TOKEN_LPAREN); + case ')': + return makeToken(TOKEN_RPAREN); + case '{': + return makeToken(TOKEN_LBRACE); + case '}': + return makeToken(TOKEN_RBRACE); + case '[': + return makeToken(TOKEN_LBRACKET); + case ']': + return makeToken(TOKEN_RBRACKET); + case ';': + return makeToken(TOKEN_SEMICOLON); + case ',': + return makeToken(TOKEN_COMMA); + case '.': + return makeToken(TOKEN_DOT); + case '-': + return makeToken(match('>') ? TOKEN_ARROW_RIGHT : TOKEN_MINUS); + case '+': + return makeToken(TOKEN_PLUS); + case '/': + return makeToken(TOKEN_SLASH); + case '&': + return makeToken(match('&') ? TOKEN_AND_AND : TOKEN_AND); + case '#': + return makeToken(TOKEN_MESH); + case '$': + return makeToken(TOKEN_BIG_MONEY); + case '*': + return makeToken(TOKEN_STAR); + case '!': + return makeToken(match('=') ? TOKEN_BANG_EQ : TOKEN_BANG); + case '=': + return makeToken(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ); + case '<': + return makeToken(match('=') ? TOKEN_LTE : TOKEN_LT); + case '>': + return makeToken(match('=') ? TOKEN_GTE : TOKEN_GT); + case '"': + return string(); + } + + return errorToken("Unexpected character."); +} + +const char *token_type_to_string(TokenType type) { + switch (type) { + case TOKEN_EOF: + return "EOF"; + case TOKEN_IDENTIFIER: + return "IDENTIFIER"; + case TOKEN_LITERAL_INT: + return "LITERAL_INT"; + case TOKEN_LITERAL_NAT: + return "LITERAL_NAT"; + case TOKEN_LITERAL_REAL: + return "LITERAL_REAL"; + case TOKEN_LITERAL_STR: + return "LITERAL_STR"; + case TOKEN_TYPE_INT: + return "TYPE_INT"; + case TOKEN_TYPE_NAT: + return "TYPE_NAT"; + case TOKEN_TYPE_REAL: + return "TYPE_REAL"; + case TOKEN_TYPE_STR: + return "TYPE_STR"; + case TOKEN_KEYWORD_PLEX: + return "KEYWORD_PLEX"; + case TOKEN_KEYWORD_FN: + return "KEYWORD_FN"; + case TOKEN_KEYWORD_CONST: + return "KEYWORD_CONST"; + case TOKEN_KEYWORD_IF: + return "KEYWORD_IF"; + case TOKEN_KEYWORD_IS: + return "IS"; + case TOKEN_KEYWORD_AS: + return "AS"; + case TOKEN_KEYWORD_ELSE: + return "KEYWORD_ELSE"; + case TOKEN_KEYWORD_WHILE: + return "KEYWORD_WHILE"; + case TOKEN_KEYWORD_FOR: + return "KEYWORD_FOR"; + case TOKEN_KEYWORD_RETURN: + return "KEYWORD_RETURN"; + case TOKEN_KEYWORD_USE: + return "KEYWORD_USE"; + case TOKEN_KEYWORD_INIT: + return "KEYWORD_INIT"; + case TOKEN_KEYWORD_THIS: + return "KEYWORD_THIS"; + case TOKEN_KEYWORD_OPEN: + return "TOKEN_KEYWORD_OPEN"; + case TOKEN_KEYWORD_READ: + return "TOKEN_KEYWORD_READ"; + case TOKEN_KEYWORD_WRITE: + return "TOKEN_KEYWORD_WRITE"; + case TOKEN_KEYWORD_REFRESH: + return "TOKEN_KEYWORD_REFRESH"; + case TOKEN_KEYWORD_CLOSE: + return "TOKEN_KEYWORD_CLOSE"; + case TOKEN_KEYWORD_NIL: + return "KEYWORD_NIL"; + case TOKEN_KEYWORD_TRUE: + return "KEYWORD_TRUE"; + case TOKEN_KEYWORD_FALSE: + return "KEYWORD_FALSE"; + case TOKEN_KEYWORD_GLOBAL: + return "KEYWORD_GLOBAL"; + case TOKEN_OPERATOR_NOT: + return "OPERATOR_NOT"; + case TOKEN_OPERATOR_AND: + return "OPERATOR_AND"; + case TOKEN_OPERATOR_OR: + return "OPERATOR_OR"; + case TOKEN_BANG: + return "BANG"; + case TOKEN_BANG_EQ: + return "BANG_EQ"; + case TOKEN_EQ: + return "EQ"; + case TOKEN_EQ_EQ: + return "EQ_EQ"; + case TOKEN_GT: + return "GT"; + case TOKEN_LT: + return "LT"; + case TOKEN_GTE: + return "GTE"; + case TOKEN_LTE: + return "LTE"; + case TOKEN_DOT: + return "DOT"; + case TOKEN_COMMA: + return "COMMA"; + case TOKEN_COLON: + return "COLON"; + case TOKEN_SEMICOLON: + return "SEMICOLON"; + case TOKEN_PLUS: + return "PLUS"; + case TOKEN_MINUS: + return "MINUS"; + case TOKEN_STAR: + return "STAR"; + case TOKEN_SLASH: + return "SLASH"; + case TOKEN_LPAREN: + return "LPAREN"; + case TOKEN_RPAREN: + return "RPAREN"; + case TOKEN_LBRACE: + return "LBRACE"; + case TOKEN_RBRACE: + return "RBRACE"; + case TOKEN_LBRACKET: + return "LBRACKET"; + case TOKEN_RBRACKET: + return "RBRACKET"; + case TOKEN_ARROW_RIGHT: + return "ARROW_RIGHT"; + case TOKEN_MESH: + return "MESH"; + case TOKEN_BIG_MONEY: + return "BIG_MONEY"; + case TOKEN_AND: + return "AND"; + case TOKEN_AND_AND: + return "AND_AND"; + case TOKEN_ERROR: + return "ERROR"; + default: + return "UNKNOWN_TOKEN"; + } +} diff --git a/tools/assembler/lexer.h b/tools/parser.h similarity index 93% rename from tools/assembler/lexer.h rename to tools/parser.h index 7f352f8..06eef8b 100644 --- a/tools/assembler/lexer.h +++ b/tools/parser.h @@ -1,6 +1,8 @@ #ifndef UNDAR_LEXER_H #define UNDAR_LEXER_H +#include "../vm/libc.h" + typedef enum { TOKEN_EOF, TOKEN_IDENTIFIER, @@ -82,7 +84,8 @@ typedef struct { int line; } Token; -void init_lexer(const char *source); +void initLexer(const char *source); Token next_token(); +const char* token_type_to_string(TokenType type); #endif diff --git a/vm/vm.c b/vm/vm.c index 8dcfb26..28ab47d 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -91,7 +91,7 @@ bool step_vm() { mp += size; } else { /* otherwise just write the return value to its location */ - mcpy(&mem[parent_local_return_address], &return_value, sizeof(u32)); + globals[(parent_local_return_address / 4)] = return_value; } /* jump to parent frame */ @@ -150,21 +150,6 @@ bool step_vm() { locals[dest] = READ_U32(locals[src1]); return true; } - case OP_LOAD_ABS_8: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_LOAD_ABS_16: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_LOAD_ABS_32: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } case OP_LOAD_OFF_8: { DECODE_A(instruction) locals[dest] = READ_U8((locals[src1] + locals[src2])); @@ -180,21 +165,6 @@ bool step_vm() { locals[dest] = READ_U32((locals[src1] + locals[src2])); return true; } - case OP_STORE_ABS_8: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_STORE_ABS_16: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_STORE_ABS_32: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } case OP_STORE_IND_8: { DECODE_A(instruction) USED(src2); @@ -239,7 +209,9 @@ bool step_vm() { } case OP_MEM_CPY_8: { DECODE_A(instruction) - u32 i = 0; + + u8 *ptr_src; + u8 *ptr_dest; u32 mdest = locals[dest]; u32 msrc = locals[src1]; u32 count = locals[src2]; @@ -249,36 +221,39 @@ bool step_vm() { return true; } - for (i = 0; i < count; i++) { - mem[msrc + i] = mem[mdest + i]; - } + ptr_dest = &mem[mdest]; + ptr_src = &mem[msrc]; + mcpy(ptr_dest, ptr_src, count*sizeof(u8)); status = 0; return true; } case OP_MEM_CPY_16: { DECODE_A(instruction) - u32 i = 0; + + u8 *ptr_src; + u8 *ptr_dest; u32 mdest = locals[dest]; u32 msrc = locals[src1]; - u32 count = locals[src2] * 2; + u32 count = locals[src2]; if (mdest + count >= mp) { status = 1; return true; } - for (i = 0; i < count; i++) { - u16 value = READ_U16(mdest + i); - WRITE_U16(msrc + i, value); - } + ptr_dest = &mem[mdest]; + ptr_src = &mem[msrc]; + mcpy(ptr_dest, ptr_src, count*sizeof(u16)); status = 0; return true; } case OP_MEM_CPY_32: { DECODE_A(instruction) - u32 i = 0; + + u8 *ptr_src; + u8 *ptr_dest; u32 mdest = locals[dest]; u32 msrc = locals[src1]; u32 count = locals[src2]; @@ -288,98 +263,66 @@ bool step_vm() { return true; } - for (i = 0; i < count; i++) { - globals[msrc + i] = globals[mdest + i]; - } + ptr_dest = &mem[mdest]; + ptr_src = &mem[msrc]; + mcpy(ptr_dest, ptr_src, count*sizeof(u32)); status = 0; return true; } case OP_MEM_SET_8: { DECODE_A(instruction) - u32 i, start, end; - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - u32 r2 = fp + (src2 * 4); + u8 *ptr_dest; + u8 value = (u8)locals[src1]; + u32 count = locals[src2]; + u32 mdest = locals[dest]; - u8 value = (u8)READ_U32(r1); - u32 count = READ_U32(r2); - - if (r2 == 0) { + if (mdest + count >= mp) { status = 1; return true; } - start = READ_U32(rd); - end = start + count; - - if (start >= mp || r2 > mp || end > mp) { - status = 1; - return true; - } - - for (i = start; i < end; i++) { - mem[i] = value; - } + ptr_dest = &mem[mdest]; + mcpy(ptr_dest, &value, count*sizeof(u8)); status = 0; return true; } case OP_MEM_SET_16: { DECODE_A(instruction) - u32 i, start, end; - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - u32 r2 = fp + (src2 * 4); + u8 *ptr_dest; + u16 value = (u16)locals[src1]; + u32 count = locals[src2]; + u32 mdest = locals[dest]; - u16 value = (u16)READ_U32(r1); - u32 count = READ_U32(r2); - - if (r2 == 0) { + if (mdest + count >= mp) { status = 1; return true; } - start = READ_U32(rd); - end = start + count; - - if (start >= mp || r2 > mp || end > mp) { - status = 1; - return true; - } - - for (i = start; i < end; i += 2) { - WRITE_U16(i, value); - } + ptr_dest = &mem[mdest]; + mcpy(ptr_dest, &value, count*sizeof(u16)); status = 0; return true; } case OP_MEM_SET_32: { DECODE_A(instruction) - u32 i, start, end; + u8 *ptr_dest; u32 value = locals[src1]; u32 count = locals[src2]; + u32 mdest = locals[dest]; - if (count == 0) { + if (mdest + count >= mp) { status = 1; return true; } - start = READ_U32(locals[dest]); - end = start + count; - - if (start >= mp || count > mp || end > mp) { - status = 1; - return true; - } - - for (i = start; i < end; i += 4) { - WRITE_U32(i, value); - } + ptr_dest = &mem[mdest]; + mcpy(ptr_dest, &value, count*sizeof(u32)); status = 0; return true; @@ -514,10 +457,7 @@ bool step_vm() { MATH_OP_NO_CAST(^); } case OP_JMP_IMM: { - u32 imm = (((u32)code[(pc) + 3] << 24) | - ((u32)code[(pc) + 2] << 16) | - ((u32)code[(pc) + 1] << 8) | - ((u32)code[(pc)])); + DECODE_C(instruction) pc = imm; return true; } @@ -615,7 +555,7 @@ bool step_vm() { case OP_JLE_REAL: { COMPARE_AND_JUMP(i32, <=); } - case OP_INT_TO_STR: { + case OP_INT_TO_STR: { DECODE_A(instruction) u32 i = MAX_LEN_INT32; diff --git a/vm/vm.h b/vm/vm.h index 9300dc4..2874d0e 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -44,15 +44,9 @@ typedef enum { OP_LOAD_IND_8, /* load_indirect_8 : A : locals[dest] = memory[locals[src1]] as u8 */ OP_LOAD_IND_16, /* load_indirect_16 : A : locals[dest] = memory[locals[src1]] as u16 */ OP_LOAD_IND_32, /* load_indirect_32 : A : locals[dest] = memory[locals[src1]] as u32 */ - OP_LOAD_ABS_8, /* load_absolute_8 : E : locals[dest] = memory[src1:u32] as u8 */ - OP_LOAD_ABS_16, /* load_absolute_16 : E : locals[dest] = memory[src1:u32] as u16 */ - OP_LOAD_ABS_32, /* load_absolute_32 : E : locals[dest] = memory[src1:u32] as u32 */ OP_LOAD_OFF_8, /* load_offset_8 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u8 */ OP_LOAD_OFF_16, /* load_offset_16 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u16 */ OP_LOAD_OFF_32, /* load_offset_32 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u32 */ - OP_STORE_ABS_8, /* store_absolute_8 : E : memory[dest] = src1 && 0xFF */ - OP_STORE_ABS_16, /* store_absolute_16 : E : memory[dest] = src1 && 0xFFFF */ - OP_STORE_ABS_32, /* store_absolute_32 : E : memory[dest] = src1 */ OP_STORE_IND_8, /* store_indirect_8 : A : memory[locals[dest]] = locals[src1] && 0xFF */ OP_STORE_IND_16, /* store_indirect_16 : A : memory[locals[dest]] = locals[src1] && 0xFFFF*/ OP_STORE_IND_32, /* store_indirect_32 : A : memory[locals[dest]] = locals[src1] */