From 9d2053aef077bee39fbcc71985222e952588344b Mon Sep 17 00:00:00 2001 From: zongor Date: Sat, 29 Nov 2025 08:26:12 -0800 Subject: [PATCH] wip symbol table, remove malloc_imm, fix docs --- README.org | 30 +-- src/tools/assembler/assembler.c | 317 +++++++++++++++++--------------- src/tools/assembler/lexer.c | 194 +++++++++---------- src/tools/assembler/lexer.h | 9 +- src/tools/compiler/compiler.c | 12 +- src/tools/compiler/lexer.c | 4 +- src/tools/compiler/lexer.h | 4 +- src/vm/opcodes.h | 1 - test/add.ul.ir | 2 +- test/fib.ul.ir | 14 +- test/hello.ul.ir | 9 +- test/loop.ul.ir | 51 ++--- test/malloc.ul.ir | 25 +-- test/paint-bw.ul.ir | 195 ++++++++++---------- test/paint.ul.ir | 20 +- test/simple.ul.ir | 2 +- test/window.ul.ir | 25 +-- 17 files changed, 471 insertions(+), 443 deletions(-) diff --git a/README.org b/README.org index 5386796..37686f5 100644 --- a/README.org +++ b/README.org @@ -55,33 +55,37 @@ You can view some examples in the =.ul.ir= files in =/test= **Sample Program: =hello.ul.ir=** #+BEGIN_SRC sh -function main () - str hello is $0 +global str terminal_namespace = "/dev/term/0" +global str new_line = "\n" +global str message = "nuqneH 'u'?" - malloc_immediate "nuqneH 'u'?" -> hello - call pln hello +function main () + str hello $0 + + load_immediate message -> hello + call pln hello -> void exit 0 -function pln (str message is $0) - str ts is $1 - int msg_length is $2 - str nl is $3 - int nl_length is $4 - int mode is $5 +function pln (str message $0) + str ts $1 + int mode $5 + int msg_length $2 + str nl $3 + int nl_length $4 - malloc_immediate "/dev/term/0" -> ts # get terminal device + load_immediate terminal_namespace -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - malloc_immediate "\n" -> nl + load_immediate new_line -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return #+END_SRC #+BEGIN_SRC sh -./build/linux/undar-linux-debug ./test/hello.asm.lisp +./build/linux/undar-linux-debug ./test/hello.ul.ir #+END_SRC Running the compiler without arguments will put it in "REPL" mode. It will function similar to a LISP repl. diff --git a/src/tools/assembler/assembler.c b/src/tools/assembler/assembler.c index 3110e60..6b769d9 100644 --- a/src/tools/assembler/assembler.c +++ b/src/tools/assembler/assembler.c @@ -15,8 +15,6 @@ void emit_u32(VM *vm, u32 value) { vm->cp += 4; } -void emit_opcode(VM *vm, Opcode op) { emit_byte(vm, op); } - SymbolTable *symbol_table_init() { SymbolTable *table = malloc(sizeof(SymbolTable)); table->symbols = malloc(16 * sizeof(Symbol)); @@ -56,8 +54,8 @@ u32 get_ref(VM *vm, SymbolTable *st, const char *name, ScopeType scope) { return sym->ref; } -Token nextTokenIs(TokenType type) { - Token token = nextToken(); +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); @@ -71,7 +69,7 @@ Token nextTokenIs(TokenType type) { bool define_global(VM *vm, SymbolTable *st) { Symbol s; - Token token_type = nextToken(); + Token token_type = next_token(); switch (token_type.type) { case TOKEN_TYPE_BOOL: s.type = BOOL; @@ -114,8 +112,8 @@ bool define_global(VM *vm, SymbolTable *st) { return false; } - Token eq = nextTokenIs(TOKEN_EQ); - Token name = nextTokenIs(TOKEN_IDENTIFIER); + Token eq = next_token_is(TOKEN_EQ); + Token name = next_token_is(TOKEN_IDENTIFIER); if (name.length > MAX_SYMBOL_NAME_LENGTH) { return false; @@ -127,21 +125,21 @@ bool define_global(VM *vm, SymbolTable *st) { s.ref = addr; s.scope = GLOBAL; - Token value = nextToken(); + Token value = next_token(); switch (value.type) { case TOKEN_KEYWORD_TRUE: { u32 addr = vm->mp; write_u8(vm, memory, addr, 1); - vm->mp += 1; - vm->frames[vm->fp].end += 1; + vm->mp += s.size; + vm->frames[vm->fp].end += s.size; } case TOKEN_KEYWORD_FALSE: { u32 addr = vm->mp; write_u8(vm, memory, addr, 0); - vm->mp += 1; - vm->frames[vm->fp].end += 1; + vm->mp += s.size; + vm->frames[vm->fp].end += s.size; } case TOKEN_LITERAL_INT: { i32 out = atoi(value.start); @@ -266,7 +264,7 @@ void define_var(VM *vm, SymbolTable *st, Token regType) { break; } case TOKEN_TYPE_REAL: { - s.type = REAL; + s.type = F32; s.size = 4; break; } @@ -286,7 +284,7 @@ void define_var(VM *vm, SymbolTable *st, Token regType) { exit(1); } - Token name = nextTokenIs(TOKEN_IDENTIFIER); + Token name = next_token_is(TOKEN_IDENTIFIER); if (name.length > MAX_SYMBOL_NAME_LENGTH) { printf("VARIABLE NAME TOO LONG at line %d: %.*s\n", regType.line, regType.length, regType.start); @@ -295,9 +293,9 @@ void define_var(VM *vm, SymbolTable *st, Token regType) { memcpy(s.name, name.start, name.length); - nextTokenIs(TOKEN_BIG_MONEY); + next_token_is(TOKEN_BIG_MONEY); - Token reg_num = nextTokenIs(TOKEN_LITERAL_INT); + Token reg_num = next_token_is(TOKEN_LITERAL_INT); s.ref = atoi(reg_num.start); symbol_table_add(st, s); } @@ -305,33 +303,33 @@ void define_var(VM *vm, SymbolTable *st, Token regType) { /** * function . */ -void define_function(vm *vm, SymbolTable *st) { +void define_function(VM *vm, SymbolTable *st) { Symbol s; s.scope = LOCAL; s.type = FUNCTION; - Token name = nextTokenIs(TOKEN_IDENTIFIER); + Token name = next_token_is(TOKEN_IDENTIFIER); if (name.length > MAX_SYMBOL_NAME_LENGTH) { - printf("FUNCITON NAME TOO LONG at line %d: %.*s\n", regType.line, - regType.length, regType.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); - nextTokenIs(TOKEN_LPAREN); + next_token_is(TOKEN_LPAREN); - Token next = nextToken(); + Token next = next_token(); while (next.type != TOKEN_RPAREN) { - Token regType = nextToken(); + Token regType = next_token(); define_var(vm, st, regType); - Token comma = nextToken(); - if (comma.type == TOKEN_COMMA) { + Token next = next_token(); + if (next.type == TOKEN_COMMA) { continue; - } else if (comma.type == TOKEN_RPAREN) { + } else if (next.type == TOKEN_RPAREN) { break; } else { - printf("ERROR at line %d: %.*s\n", comma.line, comma.length, comma.start); + printf("ERROR at line %d: %.*s\n", next.line, next.length, next.start); exit(1); } } @@ -347,10 +345,10 @@ void define_branch(VM *vm, SymbolTable *st) { s.scope = LOCAL; s.type = VOID; - token name = nextTokenIs(TOKEN_IDENTIFIER); + Token name = next_token_is(TOKEN_IDENTIFIER); if (name.length > MAX_SYMBOL_NAME_LENGTH) { - printf("BRANCH NAME TOO LONG at line %d: %.*s\n", regType.line, - regType.length, regType.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); @@ -364,136 +362,150 @@ void define_branch(VM *vm, SymbolTable *st) { */ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { Token token; - initLexer(source); + init_lexer(source); do { - token = nextToken(); + token = next_token(); if (token.type == TOKEN_ERROR) { printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); exit(1); } - if (token.type != TOKEN_EOF) { - printf("Line %d [%s]: %.*s\n", token.line, tokenTypeToString(token.type), - token.length, token.start); - if (token.type == TOKEN_KEYWORD_GLOBAL) { - define_global(vm, st); - continue; - } + if (token.type == TOKEN_KEYWORD_GLOBAL) { + define_global(vm, st); + continue; + } - if (token.type == TOKEN_KEYWORD_FN) { - define_function(vm, st); - continue; - } + if (token.type == TOKEN_KEYWORD_FN) { + define_function(vm, st); + continue; + } - if (token.type == TOKEN_KEYWORD_PLEX || token.type == TOKEN_TYPE_I8 || - token.type == TOKEN_TYPE_I16 || token.type == TOKEN_TYPE_INT || - token.type == TOKEN_TYPE_U8 || token.type == TOKEN_TYPE_U16 || - token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL || - token.type == TOKEN_TYPE_STR || token.type == TOKEN_TYPE_BOOL) { - define_var(vm, st, token); - continue; - } + if (token.type == TOKEN_KEYWORD_PLEX || token.type == TOKEN_TYPE_I8 || + token.type == TOKEN_TYPE_I16 || token.type == TOKEN_TYPE_INT || + token.type == TOKEN_TYPE_U8 || token.type == TOKEN_TYPE_U16 || + token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL || + token.type == TOKEN_TYPE_STR || token.type == TOKEN_TYPE_BOOL) { + define_var(vm, st, token); + continue; + } - if (token.type == TOKEN_KEYWORD_LOOP || token.type == TOKEN_KEYWORD_IF || - token.type == TOKEN_KEYWORD_ELSE || token.type == TOKEN_KEYWORD_DO || - token.type == TOKEN_KEYWORD_FOR) { - define_branch(vm, st); - continue; - } + if (token.type == TOKEN_KEYWORD_LOOP || token.type == TOKEN_KEYWORD_IF || + token.type == TOKEN_KEYWORD_ELSE || token.type == TOKEN_KEYWORD_DO || + token.type == TOKEN_KEYWORD_FOR) { + define_branch(vm, st); + continue; + } - if (token.type == TOKEN_IDENTIFIER) { - // 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, "syscall")) { - } 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")) { - } else if (streq(token.start, "malloc")) { - } else if (streq(token.start, "malloc_immediate")) { - } else if (streq(token.start, "memset_8")) { - } else if (streq(token.start, "memset_16")) { - } else if (streq(token.start, "memset_32")) { - } else if (streq(token.start, "register_move")) { - } else if (streq(token.start, "add_int")) { - } else if (streq(token.start, "sub_int")) { - } else if (streq(token.start, "mul_int")) { - } else if (streq(token.start, "div_int")) { - } else if (streq(token.start, "abs_int")) { - } else if (streq(token.start, "neg_int")) { - } else if (streq(token.start, "add_nat")) { - } else if (streq(token.start, "sub_nat")) { - } else if (streq(token.start, "mul_nat")) { - } else if (streq(token.start, "div_nat")) { - } else if (streq(token.start, "abs_nat")) { - } else if (streq(token.start, "neg_nat")) { - } else if (streq(token.start, "add_real")) { - } else if (streq(token.start, "sub_real")) { - } else if (streq(token.start, "mul_real")) { - } else if (streq(token.start, "div_real")) { - } else if (streq(token.start, "abs_real")) { - } else if (streq(token.start, "neg_real")) { - } else if (streq(token.start, "int_to_real")) { - } else if (streq(token.start, "nat_to_real")) { - } else if (streq(token.start, "real_to_int")) { - } else if (streq(token.start, "real_to_nat")) { - } else if (streq(token.start, "bit_shift_left")) { - } else if (streq(token.start, "bit_shift_right")) { - } else if (streq(token.start, "bit_shift_r_ext")) { - } else if (streq(token.start, "bit_and")) { - } else if (streq(token.start, "bit_or")) { - } else if (streq(token.start, "bit_xor")) { - } else if (streq(token.start, "jump")) { - } else if (streq(token.start, "jump_if_flag")) { - } else if (streq(token.start, "jump_eq_int")) { - } else if (streq(token.start, "jump_neq_int")) { - } else if (streq(token.start, "jump_gt_int")) { - } else if (streq(token.start, "jump_lt_int")) { - } else if (streq(token.start, "jump_le_int")) { - } else if (streq(token.start, "jump_ge_int")) { - } else if (streq(token.start, "jump_eq_nat")) { - } else if (streq(token.start, "jump_neq_nat")) { - } else if (streq(token.start, "jump_gt_nat")) { - } else if (streq(token.start, "jump_lt_nat")) { - } else if (streq(token.start, "jump_le_nat")) { - } else if (streq(token.start, "jump_ge_nat")) { - } else if (streq(token.start, "jump_eq_real")) { - } else if (streq(token.start, "jump_neq_real")) { - } else if (streq(token.start, "jump_ge_real")) { - } else if (streq(token.start, "jump_gt_real")) { - } else if (streq(token.start, "jump_lt_real")) { - } else if (streq(token.start, "jump_le_real")) { - } else if (streq(token.start, "string_length")) { - } 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 + if (token.type == TOKEN_IDENTIFIER) { + // check to see if it is an opcode first + if (streq(token.start, "exit")) { + vm->pc++; + + next_token_is(TOKEN_LITERAL_NAT); + vm->pc+=4; + } else if (streq(token.start, "call")) { + vm->pc++; + + next_token_is(TOKEN_IDENTIFIER); + vm->pc+=4; + + vm->pc++; /* number of args (implied) */ + + Token next = next_token(); + while (next.type != TOKEN_ARROW_LEFT) { + vm->pc++; + Token next = next_token(); } + /* return type */ + next = next_token(); + vm->pc++; + } else if (streq(token.start, "syscall")) { + } 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")) { + } else if (streq(token.start, "malloc")) { + } else if (streq(token.start, "memset_8")) { + } else if (streq(token.start, "memset_16")) { + } else if (streq(token.start, "memset_32")) { + } else if (streq(token.start, "register_move")) { + } else if (streq(token.start, "add_int")) { + } else if (streq(token.start, "sub_int")) { + } else if (streq(token.start, "mul_int")) { + } else if (streq(token.start, "div_int")) { + } else if (streq(token.start, "abs_int")) { + } else if (streq(token.start, "neg_int")) { + } else if (streq(token.start, "add_nat")) { + } else if (streq(token.start, "sub_nat")) { + } else if (streq(token.start, "mul_nat")) { + } else if (streq(token.start, "div_nat")) { + } else if (streq(token.start, "abs_nat")) { + } else if (streq(token.start, "neg_nat")) { + } else if (streq(token.start, "add_real")) { + } else if (streq(token.start, "sub_real")) { + } else if (streq(token.start, "mul_real")) { + } else if (streq(token.start, "div_real")) { + } else if (streq(token.start, "abs_real")) { + } else if (streq(token.start, "neg_real")) { + } else if (streq(token.start, "int_to_real")) { + } else if (streq(token.start, "nat_to_real")) { + } else if (streq(token.start, "real_to_int")) { + } else if (streq(token.start, "real_to_nat")) { + } else if (streq(token.start, "bit_shift_left")) { + } else if (streq(token.start, "bit_shift_right")) { + } else if (streq(token.start, "bit_shift_r_ext")) { + } else if (streq(token.start, "bit_and")) { + } else if (streq(token.start, "bit_or")) { + } else if (streq(token.start, "bit_xor")) { + } else if (streq(token.start, "jump")) { + } else if (streq(token.start, "jump_if_flag")) { + } else if (streq(token.start, "jump_eq_int")) { + } else if (streq(token.start, "jump_neq_int")) { + } else if (streq(token.start, "jump_gt_int")) { + } else if (streq(token.start, "jump_lt_int")) { + } else if (streq(token.start, "jump_le_int")) { + } else if (streq(token.start, "jump_ge_int")) { + } else if (streq(token.start, "jump_eq_nat")) { + } else if (streq(token.start, "jump_neq_nat")) { + } else if (streq(token.start, "jump_gt_nat")) { + } else if (streq(token.start, "jump_lt_nat")) { + } else if (streq(token.start, "jump_le_nat")) { + } else if (streq(token.start, "jump_ge_nat")) { + } else if (streq(token.start, "jump_eq_real")) { + } else if (streq(token.start, "jump_neq_real")) { + } else if (streq(token.start, "jump_ge_real")) { + } else if (streq(token.start, "jump_gt_real")) { + } else if (streq(token.start, "jump_lt_real")) { + } else if (streq(token.start, "jump_le_real")) { + } else if (streq(token.start, "string_length")) { + } 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 } } } while (token.type != TOKEN_EOF); @@ -504,15 +516,15 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { */ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { Token token; - initLexer(source); + init_lexer(source); do { - token = nextToken(); + token = next_token(); if (token.type == TOKEN_ERROR) { printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); break; } if (token.type != TOKEN_EOF) { - printf("Line %d [%s]: %.*s\n", token.line, tokenTypeToString(token.type), + printf("Line %d [%s]: %.*s\n", token.line, token_type_to_string(token.type), token.length, token.start); if (token.type == TOKEN_KEYWORD_GLOBAL) { @@ -561,7 +573,6 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { } else if (streq(token.start, "store_offset_16")) { } else if (streq(token.start, "store_offset_32")) { } else if (streq(token.start, "malloc")) { - } else if (streq(token.start, "malloc_immediate")) { } else if (streq(token.start, "memset_8")) { } else if (streq(token.start, "memset_16")) { } else if (streq(token.start, "memset_32")) { diff --git a/src/tools/assembler/lexer.c b/src/tools/assembler/lexer.c index 655aa94..371bed0 100644 --- a/src/tools/assembler/lexer.c +++ b/src/tools/assembler/lexer.c @@ -6,24 +6,24 @@ typedef struct { const char *start; const char *current; - int line; + i32 line; } Lexer; Lexer lexer; -void initLexer(const char *source) { +void init_lexer(const char *source) { lexer.start = source; lexer.current = source; lexer.line = 1; } -static bool isAlpha(char c) { +static bool is_alpha(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } -static bool isDigit(char c) { return c >= '0' && c <= '9'; } +static bool is_digit(char c) { return c >= '0' && c <= '9'; } -static bool isAtEnd() { return *lexer.current == '\0'; } +static bool is_at_end() { return *lexer.current == '\0'; } static char advance() { lexer.current++; @@ -32,14 +32,14 @@ static char advance() { static char peek() { return *lexer.current; } -static char peekNext() { - if (isAtEnd()) +static char peek_next() { + if (is_at_end()) return '\0'; return lexer.current[1]; } static bool match(char expected) { - if (isAtEnd()) + if (is_at_end()) return false; if (*lexer.current != expected) return false; @@ -47,25 +47,25 @@ static bool match(char expected) { return true; } -static Token makeToken(TokenType type) { +static Token make_token(TokenType type) { Token token; token.type = type; token.start = lexer.start; - token.length = (int)(lexer.current - lexer.start); + token.length = (i32)(lexer.current - lexer.start); token.line = lexer.line; return token; } -static Token errorToken(const char *message) { +static Token error_token(const char *message) { Token token; token.type = TOKEN_ERROR; token.start = message; - token.length = (int)strlen(message); + token.length = (i32)strlen(message); token.line = lexer.line; return token; } -static void skipWhitespace() { +static void skip_whitespace() { for (;;) { char c = peek(); switch (c) { @@ -79,19 +79,19 @@ static void skipWhitespace() { advance(); break; case '/': - if (peekNext() == '/') { + if (peek_next() == '/') { // Single-line comment: skip until newline or end of file advance(); - while (peek() != '\n' && !isAtEnd()) + while (peek() != '\n' && !is_at_end()) advance(); - } else if (peekNext() == '*') { + } else if (peek_next() == '*') { // Multi-line comment: skip until '*/' or end of file advance(); advance(); - while (!isAtEnd()) { + while (!is_at_end()) { if (peek() == '\n') lexer.line++; - if (peek() == '*' && peekNext() == '/') { + if (peek() == '*' && peek_next() == '/') { advance(); advance(); break; // Exit loop, comment ended @@ -108,7 +108,7 @@ static void skipWhitespace() { } } -static TokenType checkKeyword(int start, int length, const char *rest, +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) { @@ -124,9 +124,9 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 'n': - return checkKeyword(2, 1, "d", TOKEN_OPERATOR_AND); + return check_keyword(2, 1, "d", TOKEN_OPERATOR_AND); case 's': - return checkKeyword(2, 0, "", TOKEN_KEYWORD_AS); + return check_keyword(2, 0, "", TOKEN_KEYWORD_AS); } } break; @@ -134,47 +134,47 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 'l': - return checkKeyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE); + return check_keyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE); case 'o': - return checkKeyword(2, 3, "nst", TOKEN_KEYWORD_CONST); + return check_keyword(2, 3, "nst", TOKEN_KEYWORD_CONST); } } break; case 'e': - return checkKeyword(1, 3, "lse", TOKEN_KEYWORD_ELSE); + return check_keyword(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); + return check_keyword(2, 3, "lse", TOKEN_KEYWORD_FALSE); case 'o': - return checkKeyword(2, 1, "r", TOKEN_KEYWORD_FOR); + return check_keyword(2, 1, "r", TOKEN_KEYWORD_FOR); case '3': - return checkKeyword(1, 1, "2", TOKEN_TYPE_REAL); + return check_keyword(1, 1, "2", TOKEN_TYPE_REAL); } - return checkKeyword(1, 7, "unction", TOKEN_KEYWORD_FN); + 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 checkKeyword(2, 0, "", TOKEN_KEYWORD_IF); + return check_keyword(2, 0, "", TOKEN_KEYWORD_IF); case 's': - return checkKeyword(2, 0, "", TOKEN_KEYWORD_IS); + return check_keyword(2, 0, "", TOKEN_KEYWORD_IS); case '8': - return checkKeyword(2, 0, "", TOKEN_TYPE_I8); + return check_keyword(2, 0, "", TOKEN_TYPE_I8); case '1': - return checkKeyword(2, 1, "6", TOKEN_TYPE_I16); + return check_keyword(2, 1, "6", TOKEN_TYPE_I16); case '3': - return checkKeyword(2, 1, "2", TOKEN_TYPE_INT); + return check_keyword(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); + return check_keyword(3, 2, "t", TOKEN_KEYWORD_INIT); case 't': - return checkKeyword(3, 0, "", TOKEN_TYPE_INT); + return check_keyword(3, 0, "", TOKEN_TYPE_INT); } } break; @@ -185,9 +185,9 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 'a': - return checkKeyword(2, 1, "t", TOKEN_TYPE_NAT); + return check_keyword(2, 1, "t", TOKEN_TYPE_NAT); case 'i': - return checkKeyword(2, 1, "l", TOKEN_KEYWORD_NIL); + return check_keyword(2, 1, "l", TOKEN_KEYWORD_NIL); } } break; @@ -195,9 +195,9 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 'p': - return checkKeyword(2, 2, "en", TOKEN_KEYWORD_OPEN); + return check_keyword(2, 2, "en", TOKEN_KEYWORD_OPEN); case 'r': - return checkKeyword(2, 0, "", TOKEN_OPERATOR_OR); + return check_keyword(2, 0, "", TOKEN_OPERATOR_OR); } } break; @@ -205,7 +205,7 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 'l': - return checkKeyword(2, 2, "ex", TOKEN_KEYWORD_PLEX); + return check_keyword(2, 2, "ex", TOKEN_KEYWORD_PLEX); } } break; @@ -216,11 +216,11 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 2) { switch (lexer.start[2]) { case 'a': - return checkKeyword(3, 1, "d", TOKEN_KEYWORD_READ); + return check_keyword(3, 1, "d", TOKEN_KEYWORD_READ); case 'f': - return checkKeyword(3, 4, "resh", TOKEN_KEYWORD_REFRESH); + return check_keyword(3, 4, "resh", TOKEN_KEYWORD_REFRESH); case 't': - return checkKeyword(3, 3, "urn", TOKEN_KEYWORD_RETURN); + return check_keyword(3, 3, "urn", TOKEN_KEYWORD_RETURN); } } break; @@ -231,7 +231,7 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 't': - return checkKeyword(2, 1, "r", TOKEN_TYPE_STR); + return check_keyword(2, 1, "r", TOKEN_TYPE_STR); } } break; @@ -239,9 +239,9 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 'h': - return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS); + return check_keyword(2, 2, "is", TOKEN_KEYWORD_THIS); case 'r': - return checkKeyword(2, 2, "ue", TOKEN_KEYWORD_TRUE); + return check_keyword(2, 2, "ue", TOKEN_KEYWORD_TRUE); } } break; @@ -249,13 +249,13 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 's': - return checkKeyword(2, 1, "e", TOKEN_KEYWORD_USE); + return check_keyword(2, 1, "e", TOKEN_KEYWORD_USE); case '8': - return checkKeyword(2, 0, "", TOKEN_TYPE_U8); + return check_keyword(2, 0, "", TOKEN_TYPE_U8); case '1': - return checkKeyword(2, 1, "6", TOKEN_TYPE_U16); + return check_keyword(2, 1, "6", TOKEN_TYPE_U16); case '3': - return checkKeyword(2, 1, "2", TOKEN_TYPE_NAT); + return check_keyword(2, 1, "2", TOKEN_TYPE_NAT); } } break; @@ -263,129 +263,133 @@ static TokenType identifierType() { if (lexer.current - lexer.start > 1) { switch (lexer.start[1]) { case 'h': - return checkKeyword(2, 3, "ile", TOKEN_KEYWORD_WHILE); + return check_keyword(2, 3, "ile", TOKEN_KEYWORD_WHILE); case 'r': - return checkKeyword(2, 3, "ite", TOKEN_KEYWORD_WRITE); + return check_keyword(2, 3, "ite", TOKEN_KEYWORD_WRITE); } } break; case 'g': - return checkKeyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL); + return check_keyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL); case 'l': - return checkKeyword(1, 4, "oop", TOKEN_KEYWORD_LOOP); + return check_keyword(1, 4, "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 (isAlpha(peek()) || isDigit(peek())) + while (is_alpha(peek()) || is_digit(peek())) advance(); - return makeToken(identifierType()); + return make_token(identifierType()); } static Token number() { - while (isDigit(peek())) + while (is_digit(peek())) advance(); /* Look for a fractional part. */ - if (peek() == '.' && isDigit(peekNext())) { + if (peek() == '.' && is_digit(peek_next())) { /* Consume the ".". */ advance(); - while (isDigit(peek())) + while (is_digit(peek())) advance(); - return makeToken(TOKEN_LITERAL_REAL); + return make_token(TOKEN_LITERAL_REAL); } - return makeToken(TOKEN_LITERAL_INT); + return make_token(TOKEN_LITERAL_INT); } static Token string() { - while (peek() != '"' && !isAtEnd()) { + while (peek() != '"' && !is_at_end()) { if (peek() == '\n') lexer.line++; advance(); } - if (isAtEnd()) - return errorToken("Unterminated string."); + if (is_at_end()) + return error_token("Unterminated string."); /* The closing quote. */ advance(); - return makeToken(TOKEN_LITERAL_STR); + return make_token(TOKEN_LITERAL_STR); } -Token nextToken() { - skipWhitespace(); +Token next_token() { + skip_whitespace(); lexer.start = lexer.current; - if (isAtEnd()) - return makeToken(TOKEN_EOF); + if (is_at_end()) + return make_token(TOKEN_EOF); char c = advance(); - if (isAlpha(c)) + if (is_alpha(c)) return identifier(); - if (isDigit(c)) + if (is_digit(c)) return number(); switch (c) { case '(': - return makeToken(TOKEN_LPAREN); + return make_token(TOKEN_LPAREN); case ')': - return makeToken(TOKEN_RPAREN); + return make_token(TOKEN_RPAREN); case '{': - return makeToken(TOKEN_LBRACE); + return make_token(TOKEN_LBRACE); case '}': - return makeToken(TOKEN_RBRACE); + return make_token(TOKEN_RBRACE); case '[': - return makeToken(TOKEN_LBRACKET); + return make_token(TOKEN_LBRACKET); case ']': - return makeToken(TOKEN_RBRACKET); + return make_token(TOKEN_RBRACKET); case ';': - return makeToken(TOKEN_SEMICOLON); + return make_token(TOKEN_SEMICOLON); case ',': - return makeToken(TOKEN_COMMA); + return make_token(TOKEN_COMMA); case '.': - return makeToken(TOKEN_DOT); + return make_token(TOKEN_DOT); case '-': - return makeToken(match('>') ? TOKEN_ARROW_LEFT : TOKEN_MINUS); + return make_token(match('>') ? TOKEN_ARROW_LEFT : TOKEN_MINUS); case '+': - return makeToken(TOKEN_PLUS); + return make_token(TOKEN_PLUS); case '/': - return makeToken(TOKEN_SLASH); + return make_token(TOKEN_SLASH); case '&': - return makeToken(match('&') ? TOKEN_AND_AND : TOKEN_AND); + return make_token(match('&') ? TOKEN_AND_AND : TOKEN_AND); case '#': - return makeToken(TOKEN_MESH); + return make_token(TOKEN_MESH); case '$': - return makeToken(TOKEN_BIG_MONEY); + return make_token(TOKEN_BIG_MONEY); case '*': - return makeToken(TOKEN_STAR); + return make_token(TOKEN_STAR); case '!': - return makeToken(match('=') ? TOKEN_BANG_EQ : TOKEN_BANG); + return make_token(match('=') ? TOKEN_BANG_EQ : TOKEN_BANG); case '=': - return makeToken(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ); + return make_token(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ); case '<': - return makeToken(match('=') ? TOKEN_LTE : TOKEN_LT); + return make_token(match('=') ? TOKEN_LTE : TOKEN_LT); case '>': - return makeToken(match('=') ? TOKEN_GTE : TOKEN_GT); + return make_token(match('=') ? TOKEN_GTE : TOKEN_GT); case '"': return string(); } - return errorToken("Unexpected character."); + return error_token("Unexpected character."); } -const char *tokenTypeToString(TokenType type) { +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"; + return "LITERAL_i32"; case TOKEN_LITERAL_NAT: return "LITERAL_NAT"; case TOKEN_LITERAL_REAL: @@ -393,7 +397,7 @@ const char *tokenTypeToString(TokenType type) { case TOKEN_LITERAL_STR: return "LITERAL_STR"; case TOKEN_TYPE_INT: - return "TYPE_INT"; + return "TYPE_i32"; case TOKEN_TYPE_NAT: return "TYPE_NAT"; case TOKEN_TYPE_REAL: diff --git a/src/tools/assembler/lexer.h b/src/tools/assembler/lexer.h index 5ad14ef..3d8ad1a 100644 --- a/src/tools/assembler/lexer.h +++ b/src/tools/assembler/lexer.h @@ -16,6 +16,8 @@ typedef enum { TOKEN_TYPE_NAT, TOKEN_TYPE_REAL, TOKEN_TYPE_STR, + TOKEN_TYPE_BOOL, + TOKEN_TYPE_VOID, TOKEN_KEYWORD_PLEX, TOKEN_KEYWORD_FN, TOKEN_KEYWORD_CONST, @@ -36,6 +38,7 @@ typedef enum { TOKEN_KEYWORD_REFRESH, TOKEN_KEYWORD_CLOSE, TOKEN_KEYWORD_LOOP, + TOKEN_KEYWORD_DO, TOKEN_KEYWORD_NIL, TOKEN_KEYWORD_TRUE, TOKEN_KEYWORD_FALSE, @@ -79,8 +82,8 @@ typedef struct { int line; } Token; -void initLexer(const char *source); -Token nextToken(); -const char* tokenTypeToString(TokenType type); +void init_lexer(const char *source); +Token next_token(); +const char* token_type_to_string(TokenType type); #endif diff --git a/src/tools/compiler/compiler.c b/src/tools/compiler/compiler.c index 1b29e68..889c277 100644 --- a/src/tools/compiler/compiler.c +++ b/src/tools/compiler/compiler.c @@ -184,14 +184,14 @@ Symbol *global(VM *vm) { s.ref.global = vm->mp; - Token token_type = nextToken(); - Token array_or_eq = nextToken(); + Token token_type = next_token(); + Token array_or_eq = next_token(); if (array_or_eq.type == TOKEN_LBRACKET) { - Token rb = nextToken(); + Token rb = next_token(); if (rb.type != TOKEN_RBRACKET) return nil; - Token eq = nextToken(); + Token eq = next_token(); if (eq.type != TOKEN_EQ) return nil; @@ -268,7 +268,7 @@ Symbol *global(VM *vm) { s.type = t; - Token value = nextToken(); + Token value = next_token(); return nil; } @@ -345,7 +345,7 @@ void advance() { parser.previous = parser.current; for (;;) { - parser.current = nextToken(); + parser.current = next_token(); if (parser.current.type != TOKEN_ERROR) break; diff --git a/src/tools/compiler/lexer.c b/src/tools/compiler/lexer.c index 397d7cc..490e952 100644 --- a/src/tools/compiler/lexer.c +++ b/src/tools/compiler/lexer.c @@ -315,7 +315,7 @@ static Token string() { return makeToken(TOKEN_LITERAL_STR); } -Token nextToken() { +Token next_token() { skipWhitespace(); lexer.start = lexer.current; @@ -376,7 +376,7 @@ Token nextToken() { return errorToken("Unexpected character."); } -const char *tokenTypeToString(TokenType type) { +const char *token_type_to_string(TokenType type) { switch (type) { case TOKEN_EOF: return "EOF"; diff --git a/src/tools/compiler/lexer.h b/src/tools/compiler/lexer.h index eaa137c..3e0ab11 100644 --- a/src/tools/compiler/lexer.h +++ b/src/tools/compiler/lexer.h @@ -79,7 +79,7 @@ typedef struct { } Token; void initLexer(const char *source); -Token nextToken(); -const char* tokenTypeToString(TokenType type); +Token next_token(); +const char* token_type_to_string(TokenType type); #endif diff --git a/src/vm/opcodes.h b/src/vm/opcodes.h index 6a53937..91d2b57 100644 --- a/src/vm/opcodes.h +++ b/src/vm/opcodes.h @@ -28,7 +28,6 @@ typedef enum { OP_STORE_OFF_16, /* store_offset_16 : memory[locals[dest] + offset] = locals[src1] && 0xFFFF */ OP_STORE_OFF_32, /* store_offset_32 : memory[locals[dest] + offset] = locals[src1] */ OP_MALLOC, /* malloc : dest = fat ptr to memory of ((src1 as size) + 4) */ - OP_MALLOC_IMM, /* malloc_immediate : dest = fat ptr to memory of raw */ OP_MEMSET_8, /* memset_8 : dest <-> dest+count = src1 as u8 */ OP_MEMSET_16, /* memset_16 : dest <-> dest+count = src1 as u8 */ OP_MEMSET_32, /* memset_32 : dest <-> dest+count = src1 as u32 */ diff --git a/test/add.ul.ir b/test/add.ul.ir index f7e6a8a..3364204 100644 --- a/test/add.ul.ir +++ b/test/add.ul.ir @@ -11,7 +11,7 @@ function main () load_absolute_32 y -> $1 call add $0 $1 -> ans int_to_string ans -> ans_string - call pln ans_string + call pln ans_string -> void exit 0 function add (int a $0, int b $1) diff --git a/test/fib.ul.ir b/test/fib.ul.ir index 7f73714..d823c9a 100644 --- a/test/fib.ul.ir +++ b/test/fib.ul.ir @@ -6,23 +6,23 @@ function main () int str_n $1 load_immediate 35 -> n - call &fib n -> n + call fib n -> n int_to_string n -> str_n - call &pln str_n + call pln str_n -> void exit 0 function fib (int n $0) load_immediate 2 -> $1 - jump_lt_int &base_case n $1 + jump_lt_int base_case n $1 load_immediate 2 -> $3 sub_int n $3 -> $4 - call &fib $4 -> $5 + call fib $4 -> $5 load_immediate 1 -> $3 sub_int n $3 -> $4 - call &fib $4 -> $6 + call fib $4 -> $6 add_int $6 $5 -> $7 return $7 @@ -37,12 +37,12 @@ function pln (str message $0) str nl $3 int nl_length $4 - load_immediate &terminal_namespace -> ts + load_immediate terminal_namespace -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - load_immediate &new_line -> nl + load_immediate new_line -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return diff --git a/test/hello.ul.ir b/test/hello.ul.ir index 3c48000..204fab3 100644 --- a/test/hello.ul.ir +++ b/test/hello.ul.ir @@ -5,8 +5,8 @@ global str message = "nuqneH 'u'?" function main () str hello $0 - load_immediate &message -> hello - call pln hello + load_immediate message -> hello + call pln hello -> void exit 0 function pln (str message $0) @@ -16,13 +16,12 @@ function pln (str message $0) str nl $3 int nl_length $4 - - load_immediate &terminal_namespace -> ts + load_immediate terminal_namespace -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - load_immediate &new_line -> nl + load_immediate new_line -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return diff --git a/test/loop.ul.ir b/test/loop.ul.ir index a72d97c..26b2406 100644 --- a/test/loop.ul.ir +++ b/test/loop.ul.ir @@ -1,9 +1,12 @@ - +global str terminal_namespace = "/dev/term/0" +global str prompt = "Enter a string:" +global str new_line = "\n" + function main () - real a is $0 - int i is $1 - int mode is $11 - str term is $10 + real a $0 + int i $1 + int mode $11 + str term $10 load_immediate 5.0 -> a load_immediate 5000 -> i @@ -15,41 +18,41 @@ function main () add_int i $3 -> i jump_ge_int loop_body i $2 - malloc_immediate "/dev/term/0" -> term + load_immediate terminal_namespace -> term load_immediate 0 -> mode - syscall OPEN term mode -> term # Terminal term = open("/dev/term/0", 0); + syscall OPEN term mode -> term // Terminal term = open("/dev/term/0", 0); - nat b is $1 + nat b $1 real_to_nat a -> b - malloc_immediate "Enter a string:" -> $7 + load_immediate prompt -> $7 string_length $7 -> $8 - syscall WRITE term $7 $8 # print prompt + syscall WRITE term $7 $8 // print prompt - str user_string is $9 + str user_string $9 load_immediate 32 -> $8 malloc $8 -> user_string - syscall READ term user_string $8 # read in max 32 byte string + syscall READ term user_string $8 // read in max 32 byte string - call pln user_string + call pln user_string -> void nat_to_string b -> $4 - call pln $4 + call pln $4 -> void real_to_string a -> $3 - call pln $3 + call pln $3 -> void exit 0 -function pln (str message is $0) - str ts is $1 - int mode is $5 - int msg_length is $2 - str nl is $3 - int nl_length is $4 +function pln (str message $0) + str ts $1 + int mode $5 + int msg_length $2 + str nl $3 + int nl_length $4 - malloc_immediate "/dev/term/0" -> ts + load_immediate terminal_namespace -> ts load_immediate 0 -> mode - syscall OPEN ts mode -> ts # get terminal device + syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - malloc_immediate "\n" -> nl + load_immediate new_line -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return \ No newline at end of file diff --git a/test/malloc.ul.ir b/test/malloc.ul.ir index cc69b12..248ca99 100644 --- a/test/malloc.ul.ir +++ b/test/malloc.ul.ir @@ -1,22 +1,25 @@ - +global str terminal_namespace = "/dev/term/0" +global str prompt = "Enter a string:" +global str new_line = "\n" + function main () int mode $11; str term $10; - malloc_immediate "/dev/term/0" -> term + load_immediate terminal_namespace -> term load_immediate 0 -> mode - syscall OPEN term mode -> term # Terminal term = open("/dev/term/0", 0); + syscall OPEN term mode -> term // Terminal term = open("/dev/term/0", 0); - malloc_immediate "Enter a string:" -> $7 + load_immediate prompt -> $7 string_length $7 -> $8 - syscall WRITE term $7 $8 # print prompt + syscall WRITE term $7 $8 // print prompt str user_string $9 load_immediate 32 -> $8 malloc $8 -> user_string - syscall READ term user_string $8 # read in max 32 byte string + syscall READ term user_string $8 // read in max 32 byte string - call pln user_string; + call pln user_string -> void exit 0 function pln (str message $0) @@ -24,14 +27,14 @@ function pln (str message $0) int mode $5 int msg_length $2 str nl $3 - int nl_length $4 + int nl_length $4 - malloc_immediate "/dev/term/0" -> ts + load_immediate terminal_namespace -> ts load_immediate 0 -> mode - syscall OPEN ts mode -> ts # get terminal device + syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - malloc_immediate "\n" -> nl + load_immediate new_line -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return diff --git a/test/paint-bw.ul.ir b/test/paint-bw.ul.ir index ab40219..4c1fb02 100644 --- a/test/paint-bw.ul.ir +++ b/test/paint-bw.ul.ir @@ -8,177 +8,178 @@ global const byte LIGHT_GRAY = 182 global byte SELECTED_COLOR = 255 function main () - # Open screen - plex screen is $0 - str screen_name is $18 - int mode is $11 - nat screen_buffer is $21 + // Open screen + plex screen $0 + str screen_name $18 + int mode $11 + nat screen_buffer $21 - # use load immediate because it is a pointer to a string, not a value - load_address &screen_namespace -> screen_name + // use load immediate because it a pointer to a string, not a value + load_address screen_namespace -> screen_name load_immediate 0 -> mode - syscall OPEN screen_name mode -> screen # Screen screen = open("/dev/screen/0", 0); + syscall OPEN screen_name mode -> screen // Screen screen = open("/dev/screen/0", 0); - nat width is $20 - nat size is $22 - load_offset_32 screen 8 -> width # load width - load_offset_32 screen 12 -> size # load size - load_immediate 16 -> $1 # offset for screen buffer + nat width $20 + nat size $22 + load_offset_32 screen 8 -> width // load width + load_offset_32 screen 12 -> size // load size + load_immediate 16 -> $1 // offset for screen buffer add_nat screen $1 -> screen_buffer - # open mouse - plex mouse is $15 - str mouse_name is $16 - load_address &mouse_namespace -> mouse_name - syscall OPEN mouse_name mode -> mouse # Mouse mouse = open("/dev/mouse/0", 0); + // open mouse + plex mouse $15 + str mouse_name $16 + load_address mouse_namespace -> mouse_name + syscall OPEN mouse_name mode -> mouse // Mouse mouse = open("/dev/mouse/0", 0); - byte color is $1 - nat x_pos is $12 - nat y_pos is $13 + byte color $1 + nat x_pos $12 + nat y_pos $13 - load_absolute_32 &BLACK -> color + load_absolute_32 BLACK -> color load_immediate 1 -> x_pos load_immediate 1 -> y_pos - call &draw_outlined_swatch screen_buffer color x_pos y_pos width + call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void - load_absolute_32 &WHITE -> color + load_absolute_32 WHITE -> color load_immediate 21 -> x_pos load_immediate 1 -> y_pos - call &draw_outlined_swatch screen_buffer color x_pos y_pos width + call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void - # screen.draw# + // screen.draw syscall WRITE screen screen_buffer size - nat zero is $11 + nat zero $11 - draw_loop: - # load mouse click data + loop draw_loop + // load mouse click data syscall REFRESH mouse - byte left_down is $9 - load_offset_8 mouse 16 -> left_down # load btn1 pressed + byte left_down $9 + load_offset_8 mouse 16 -> left_down // load btn1 pressed - jump_eq_nat &draw_loop left_down zero + jump_eq_nat draw_loop left_down zero - nat mouse_x is $7 - nat mouse_y is $8 - load_offset_32 mouse 8 -> mouse_x # load x - load_offset_32 mouse 12 -> mouse_y # load y + nat mouse_x $7 + nat mouse_y $8 + load_offset_32 mouse 8 -> mouse_x // load x + load_offset_32 mouse 12 -> mouse_y // load y - nat box_size is $14 + nat box_size $14 load_immediate 20 -> box_size - # first row - load_absolute_32 &BLACK -> color + // first row + load_absolute_32 BLACK -> color load_immediate 1 -> x_pos load_immediate 1 -> y_pos - call &draw_outlined_swatch screen_buffer color x_pos y_pos width - call &set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size + call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void + call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void - load_absolute_32 &WHITE -> color + load_absolute_32 WHITE -> color load_immediate 21 -> x_pos load_immediate 1 -> y_pos - call &draw_outlined_swatch screen_buffer color x_pos y_pos width - call &set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size + call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void + call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void syscall WRITE screen screen_buffer size - byte selected_color is $25 - load_absolute_32 &SELECTED_COLOR -> selected_color + byte selected_color $25 + load_absolute_32 SELECTED_COLOR -> selected_color - nat brush_size is $19 + nat brush_size $19 load_immediate 5 -> brush_size - call &draw_box screen_buffer width selected_color mouse_x mouse_y brush_size brush_size + call draw_box screen_buffer width selected_color mouse_x mouse_y brush_size brush_size -> void - jump &draw_loop + jump draw_loop - # Flush and exit + // Flush and exit exit 0 -function set_color_if_clicked (int click_x is $0, int click_y is $1, - int box_x is $2, int box_y is $3, byte color is $4, int box_size is $5) +function set_color_if_clicked (int click_x $0, int click_y $1, + int box_x $2, int box_y $3, byte color $4, int box_size $5) - # Compute right - int right_edge is $6 + // Compute right + int right_edge $6 add_int box_x box_size -> right_edge - # Compute bottom = box_y + box_size - int bottom_edge is $7 + // Compute bottom = box_y + box_size + int bottom_edge $7 add_int box_y box_size -> bottom_edge - # Bounds check: x in [box_x, right] and y in [box_y, bottom] - jump_lt_int &fail click_x box_x - jump_ge_int &fail click_x right_edge - jump_lt_int &fail click_y box_y - jump_ge_int &fail click_y bottom_edge + // Bounds check: x in [box_x, right] and y in [box_y, bottom] + jump_lt_int fail click_x box_x + jump_ge_int fail click_x right_edge + 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 SELECTED_COLOR color - fail: + else fail return -function draw_outlined_swatch(nat base is $0, - byte color is $1, int x is $2, int y is $3, int width is $4) +function draw_outlined_swatch(nat base $0, + byte color $1, int x $2, int y $3, int width $4) - # Constants - nat background_color is $5 - load_absolute_32 &GRAY -> background_color + // Constants + nat background_color $5 + load_absolute_32 GRAY -> background_color - byte selected_color is $10 - load_absolute_32 &SELECTED_COLOR -> selected_color + byte selected_color $10 + load_absolute_32 SELECTED_COLOR -> selected_color - jump_eq_int &set_selected selected_color color - jump &end_set_selected + jump_eq_int set_selected selected_color color + jump end_set_selected set_selected: - load_absolute_32 &DARK_GRAY -> background_color + load_absolute_32 DARK_GRAY -> background_color end_set_selected: - nat outline_size is $6 + nat outline_size $6 load_immediate 20 -> outline_size - nat fill_size is $7 + nat fill_size $7 load_immediate 17 -> fill_size - nat offset is $8 + nat offset $8 load_immediate 2 -> offset - call &draw_box base width background_color x y outline_size outline_size + call draw_box base width background_color x y outline_size outline_size -> void - add_int x offset -> $9 # x + 2 - add_int y offset -> $10 # y + 2 + add_int x offset -> $9 // x + 2 + add_int y offset -> $10 // y + 2 - call &draw_box base width color $9 $10 fill_size fill_size + call draw_box base width color $9 $10 fill_size fill_size -> void return -function draw_box (nat base is $0, nat screen_width is $1, - byte color is $2, nat x_start is $3, nat y_start is $4, nat width is $5, nat height is $6) +function draw_box (nat base $0, nat screen_width $1, + byte color $2, nat x_start $3, nat y_start $4, + nat width $5, nat height $6) - # Compute start address: base + y*640 + x - nat offset is $15 + // Compute start address: base + y*640 + x + nat offset $15 mul_int y_start screen_width -> offset add_int offset x_start -> offset add_nat offset base -> offset - nat fat_ptr_size is $25 + nat fat_ptr_size $25 load_immediate 4 -> fat_ptr_size - add_nat offset fat_ptr_size -> offset # need to add offset for fat pointer size + add_nat offset fat_ptr_size -> offset // need to add offset for fat pointer size - int i is $30 + int i $30 load_immediate 1 -> i - int zero is $26 + int zero $26 load_immediate 0 -> zero - int row_end is $27 - nat pixel_ptr is $29 + int row_end $27 + nat pixel_ptr $29 - draw_box_outer: - add_int offset width -> row_end # current + width - register_move offset -> pixel_ptr # set pixel point - memset_8 pixel_ptr color width # draw row - add_int offset screen_width -> offset # next row += 640 - sub_int height i -> height # decrement row count - jump_gt_int &draw_box_outer height zero + loop draw_box_outer + add_int offset width -> row_end // current + width + register_move offset -> pixel_ptr // set pixel point + memset_8 pixel_ptr color width // draw row + add_int offset screen_width -> offset // next row += 640 + sub_int height i -> height // decrement row count + jump_gt_int draw_box_outer height zero return diff --git a/test/paint.ul.ir b/test/paint.ul.ir index 3dac05e..0adc914 100644 --- a/test/paint.ul.ir +++ b/test/paint.ul.ir @@ -39,12 +39,12 @@ function main () load_absolute_32 BLACK -> color load_immediate 1 -> x_pos load_immediate 1 -> y_pos - call draw_outlined_swatch screen_buffer color x_pos y_pos width + call draw_outlined_swatch [screen_buffer color x_pos y_pos width] -> void load_absolute_32 WHITE -> color load_immediate 21 -> x_pos load_immediate 1 -> y_pos - call draw_outlined_swatch screen_buffer color x_pos y_pos width + call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void // screen.draw// syscall WRITE screen screen_buffer size @@ -72,15 +72,15 @@ function main () load_absolute_32 BLACK -> color load_immediate 1 -> x_pos load_immediate 1 -> y_pos - call draw_outlined_swatch screen_buffer color x_pos y_pos width - call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size + call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void + call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void load_absolute_32 WHITE -> color load_immediate 21 -> x_pos load_immediate 1 -> y_pos - call draw_outlined_swatch screen_buffer color x_pos y_pos width - call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size + call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void + call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void syscall WRITE screen screen_buffer size @@ -90,7 +90,7 @@ function main () nat brush_size $19 load_immediate 5 -> brush_size - call draw_box screen_buffer width selected_color mouse_x mouse_y brush_size brush_size + call draw_box screen_buffer width selected_color mouse_x mouse_y brush_size brush_size -> void jump draw_loop @@ -144,12 +144,12 @@ function draw_outlined_swatch(nat base $0, nat offset $8 load_immediate 2 -> offset - call draw_box base width background_color x y outline_size outline_size + call draw_box base width background_color x y outline_size outline_size -> void add_int x offset -> $9 // x + 2 add_int y offset -> $10 // y + 2 - call draw_box base width color $9 $10 fill_size fill_size + call draw_box base width color $9 $10 fill_size fill_size -> void return @@ -180,5 +180,5 @@ function draw_box (nat base $0, nat screen_width $1, memset_8 pixel_ptr color width // draw row add_int offset screen_width -> offset // next row += 640 sub_int height i -> height // decrement row count - jump_gt_int draw_box_outer height zero + jump_gt_int draw_box_outer height zero return diff --git a/test/simple.ul.ir b/test/simple.ul.ir index e4a1407..572d680 100644 --- a/test/simple.ul.ir +++ b/test/simple.ul.ir @@ -11,7 +11,7 @@ function main () add_real x y -> result str result_str $3 real_to_string result -> result_str - call &pln result_str + call &pln result_str -> void exit 0 function pln (str message $0) diff --git a/test/window.ul.ir b/test/window.ul.ir index c942eeb..c860dfc 100644 --- a/test/window.ul.ir +++ b/test/window.ul.ir @@ -24,21 +24,21 @@ function main () syscall OPEN screen mode -> screen nat_to_string screen -> tmp_str - call pln tmp_str + call pln tmp_str -> void load_offset_32 screen 8 -> width nat_to_string width -> tmp_str - call pln tmp_str + call pln tmp_str -> void load_offset_32 screen 12 -> buffer_size nat_to_string buffer_size -> tmp_str - call pln tmp_str + call pln tmp_str -> void load_immediate 16 -> offset_temp add_nat screen offset_temp -> screen_buffer nat_to_string screen_buffer -> tmp_str - call pln tmp_str + call pln tmp_str -> void // open mouse load_immediate mouse_namespace -> mouse @@ -72,17 +72,18 @@ function main () exit 0 function pln (str message $0) - str term $1 - int msg_length $2 - str nl $3 - int nl_length $4 + str ts $1 int mode $5 + int msg_length $2 + str nl $3 + int nl_length $4 + load_immediate terminal_namespace -> ts load_immediate 0 -> mode - syscall OPEN terminal_namespace mode -> term + syscall OPEN ts mode -> ts strlen message -> msg_length - syscall WRITE term message msg_length - load_address new_line -> nl + syscall WRITE ts message msg_length + load_immediate new_line -> nl strlen nl -> nl_length - syscall WRITE term nl nl_length + syscall WRITE ts nl nl_length return