wip symbol table, remove malloc_imm, fix docs

This commit is contained in:
zongor 2025-11-29 08:26:12 -08:00
parent 4f73339efb
commit 9d2053aef0
17 changed files with 471 additions and 443 deletions

View File

@ -55,33 +55,37 @@ You can view some examples in the =.ul.ir= files in =/test=
**Sample Program: =hello.ul.ir=** **Sample Program: =hello.ul.ir=**
#+BEGIN_SRC sh #+BEGIN_SRC sh
function main () global str terminal_namespace = "/dev/term/0"
str hello is $0 global str new_line = "\n"
global str message = "nuqneH 'u'?"
malloc_immediate "nuqneH 'u'?" -> hello function main ()
call pln hello str hello $0
load_immediate message -> hello
call pln hello -> void
exit 0 exit 0
function pln (str message is $0) function pln (str message $0)
str ts is $1 str ts $1
int msg_length is $2 int mode $5
str nl is $3 int msg_length $2
int nl_length is $4 str nl $3
int mode is $5 int nl_length $4
malloc_immediate "/dev/term/0" -> ts # get terminal device load_immediate terminal_namespace -> ts
load_immediate 0 -> mode load_immediate 0 -> mode
syscall OPEN ts mode -> ts syscall OPEN ts mode -> ts
strlen message -> msg_length strlen message -> msg_length
syscall WRITE ts message msg_length syscall WRITE ts message msg_length
malloc_immediate "\n" -> nl load_immediate new_line -> nl
strlen nl -> nl_length strlen nl -> nl_length
syscall WRITE ts nl nl_length syscall WRITE ts nl nl_length
return return
#+END_SRC #+END_SRC
#+BEGIN_SRC sh #+BEGIN_SRC sh
./build/linux/undar-linux-debug ./test/hello.asm.lisp ./build/linux/undar-linux-debug ./test/hello.ul.ir
#+END_SRC #+END_SRC
Running the compiler without arguments will put it in "REPL" mode. It will function similar to a LISP repl. Running the compiler without arguments will put it in "REPL" mode. It will function similar to a LISP repl.

View File

@ -15,8 +15,6 @@ void emit_u32(VM *vm, u32 value) {
vm->cp += 4; vm->cp += 4;
} }
void emit_opcode(VM *vm, Opcode op) { emit_byte(vm, op); }
SymbolTable *symbol_table_init() { SymbolTable *symbol_table_init() {
SymbolTable *table = malloc(sizeof(SymbolTable)); SymbolTable *table = malloc(sizeof(SymbolTable));
table->symbols = malloc(16 * sizeof(Symbol)); 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; return sym->ref;
} }
Token nextTokenIs(TokenType type) { Token next_token_is(TokenType type) {
Token token = nextToken(); Token token = next_token();
if (token.type != type) { if (token.type != type) {
printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start);
exit(1); exit(1);
@ -71,7 +69,7 @@ Token nextTokenIs(TokenType type) {
bool define_global(VM *vm, SymbolTable *st) { bool define_global(VM *vm, SymbolTable *st) {
Symbol s; Symbol s;
Token token_type = nextToken(); Token token_type = next_token();
switch (token_type.type) { switch (token_type.type) {
case TOKEN_TYPE_BOOL: case TOKEN_TYPE_BOOL:
s.type = BOOL; s.type = BOOL;
@ -114,8 +112,8 @@ bool define_global(VM *vm, SymbolTable *st) {
return false; return false;
} }
Token eq = nextTokenIs(TOKEN_EQ); Token eq = next_token_is(TOKEN_EQ);
Token name = nextTokenIs(TOKEN_IDENTIFIER); Token name = next_token_is(TOKEN_IDENTIFIER);
if (name.length > MAX_SYMBOL_NAME_LENGTH) { if (name.length > MAX_SYMBOL_NAME_LENGTH) {
return false; return false;
@ -127,21 +125,21 @@ bool define_global(VM *vm, SymbolTable *st) {
s.ref = addr; s.ref = addr;
s.scope = GLOBAL; s.scope = GLOBAL;
Token value = nextToken(); Token value = next_token();
switch (value.type) { switch (value.type) {
case TOKEN_KEYWORD_TRUE: { case TOKEN_KEYWORD_TRUE: {
u32 addr = vm->mp; u32 addr = vm->mp;
write_u8(vm, memory, addr, 1); write_u8(vm, memory, addr, 1);
vm->mp += 1; vm->mp += s.size;
vm->frames[vm->fp].end += 1; vm->frames[vm->fp].end += s.size;
} }
case TOKEN_KEYWORD_FALSE: { case TOKEN_KEYWORD_FALSE: {
u32 addr = vm->mp; u32 addr = vm->mp;
write_u8(vm, memory, addr, 0); write_u8(vm, memory, addr, 0);
vm->mp += 1; vm->mp += s.size;
vm->frames[vm->fp].end += 1; vm->frames[vm->fp].end += s.size;
} }
case TOKEN_LITERAL_INT: { case TOKEN_LITERAL_INT: {
i32 out = atoi(value.start); i32 out = atoi(value.start);
@ -266,7 +264,7 @@ void define_var(VM *vm, SymbolTable *st, Token regType) {
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
s.type = REAL; s.type = F32;
s.size = 4; s.size = 4;
break; break;
} }
@ -286,7 +284,7 @@ void define_var(VM *vm, SymbolTable *st, Token regType) {
exit(1); exit(1);
} }
Token name = nextTokenIs(TOKEN_IDENTIFIER); Token name = next_token_is(TOKEN_IDENTIFIER);
if (name.length > MAX_SYMBOL_NAME_LENGTH) { if (name.length > MAX_SYMBOL_NAME_LENGTH) {
printf("VARIABLE NAME TOO LONG at line %d: %.*s\n", regType.line, printf("VARIABLE NAME TOO LONG at line %d: %.*s\n", regType.line,
regType.length, regType.start); regType.length, regType.start);
@ -295,9 +293,9 @@ void define_var(VM *vm, SymbolTable *st, Token regType) {
memcpy(s.name, name.start, name.length); 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); s.ref = atoi(reg_num.start);
symbol_table_add(st, s); symbol_table_add(st, s);
} }
@ -305,33 +303,33 @@ void define_var(VM *vm, SymbolTable *st, Token regType) {
/** /**
* function . * function .
*/ */
void define_function(vm *vm, SymbolTable *st) { void define_function(VM *vm, SymbolTable *st) {
Symbol s; Symbol s;
s.scope = LOCAL; s.scope = LOCAL;
s.type = FUNCTION; s.type = FUNCTION;
Token name = nextTokenIs(TOKEN_IDENTIFIER); Token name = next_token_is(TOKEN_IDENTIFIER);
if (name.length > MAX_SYMBOL_NAME_LENGTH) { if (name.length > MAX_SYMBOL_NAME_LENGTH) {
printf("FUNCITON NAME TOO LONG at line %d: %.*s\n", regType.line, printf("FUNCITON NAME TOO LONG at line %d: %.*s\n", name.line,
regType.length, regType.start); name.length, name.start);
exit(1); exit(1);
} }
memcpy(s.name, name.start, name.length); 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) { while (next.type != TOKEN_RPAREN) {
Token regType = nextToken(); Token regType = next_token();
define_var(vm, st, regType); define_var(vm, st, regType);
Token comma = nextToken(); Token next = next_token();
if (comma.type == TOKEN_COMMA) { if (next.type == TOKEN_COMMA) {
continue; continue;
} else if (comma.type == TOKEN_RPAREN) { } else if (next.type == TOKEN_RPAREN) {
break; break;
} else { } 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); exit(1);
} }
} }
@ -347,10 +345,10 @@ void define_branch(VM *vm, SymbolTable *st) {
s.scope = LOCAL; s.scope = LOCAL;
s.type = VOID; s.type = VOID;
token name = nextTokenIs(TOKEN_IDENTIFIER); Token name = next_token_is(TOKEN_IDENTIFIER);
if (name.length > MAX_SYMBOL_NAME_LENGTH) { if (name.length > MAX_SYMBOL_NAME_LENGTH) {
printf("BRANCH NAME TOO LONG at line %d: %.*s\n", regType.line, printf("BRANCH NAME TOO LONG at line %d: %.*s\n", name.line,
regType.length, regType.start); name.length, name.start);
exit(1); exit(1);
} }
memcpy(s.name, name.start, name.length); memcpy(s.name, name.start, name.length);
@ -364,16 +362,13 @@ void define_branch(VM *vm, SymbolTable *st) {
*/ */
void build_symbol_table(VM *vm, char *source, SymbolTable *st) { void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
Token token; Token token;
initLexer(source); init_lexer(source);
do { do {
token = nextToken(); token = next_token();
if (token.type == TOKEN_ERROR) { if (token.type == TOKEN_ERROR) {
printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start);
exit(1); 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) { if (token.type == TOKEN_KEYWORD_GLOBAL) {
define_global(vm, st); define_global(vm, st);
@ -404,7 +399,26 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
if (token.type == TOKEN_IDENTIFIER) { if (token.type == TOKEN_IDENTIFIER) {
// check to see if it is an opcode first // check to see if it is an opcode first
if (streq(token.start, "exit")) { if (streq(token.start, "exit")) {
vm->pc++;
next_token_is(TOKEN_LITERAL_NAT);
vm->pc+=4;
} else if (streq(token.start, "call")) { } 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, "syscall")) {
} else if (streq(token.start, "load_immediate")) { } else if (streq(token.start, "load_immediate")) {
} else if (streq(token.start, "load_indirect_8")) { } else if (streq(token.start, "load_indirect_8")) {
@ -426,7 +440,6 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
} else if (streq(token.start, "store_offset_16")) { } else if (streq(token.start, "store_offset_16")) {
} else if (streq(token.start, "store_offset_32")) { } else if (streq(token.start, "store_offset_32")) {
} else if (streq(token.start, "malloc")) { } 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_8")) {
} else if (streq(token.start, "memset_16")) { } else if (streq(token.start, "memset_16")) {
} else if (streq(token.start, "memset_32")) { } else if (streq(token.start, "memset_32")) {
@ -495,7 +508,6 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
// some other identifier // some other identifier
} }
} }
}
} while (token.type != TOKEN_EOF); } 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) { void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
Token token; Token token;
initLexer(source); init_lexer(source);
do { do {
token = nextToken(); token = next_token();
if (token.type == TOKEN_ERROR) { if (token.type == TOKEN_ERROR) {
printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start);
break; break;
} }
if (token.type != TOKEN_EOF) { 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); token.length, token.start);
if (token.type == TOKEN_KEYWORD_GLOBAL) { 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_16")) {
} else if (streq(token.start, "store_offset_32")) { } else if (streq(token.start, "store_offset_32")) {
} else if (streq(token.start, "malloc")) { } 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_8")) {
} else if (streq(token.start, "memset_16")) { } else if (streq(token.start, "memset_16")) {
} else if (streq(token.start, "memset_32")) { } else if (streq(token.start, "memset_32")) {

View File

@ -6,24 +6,24 @@
typedef struct { typedef struct {
const char *start; const char *start;
const char *current; const char *current;
int line; i32 line;
} Lexer; } Lexer;
Lexer lexer; Lexer lexer;
void initLexer(const char *source) { void init_lexer(const char *source) {
lexer.start = source; lexer.start = source;
lexer.current = source; lexer.current = source;
lexer.line = 1; lexer.line = 1;
} }
static bool isAlpha(char c) { static bool is_alpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || 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() { static char advance() {
lexer.current++; lexer.current++;
@ -32,14 +32,14 @@ static char advance() {
static char peek() { return *lexer.current; } static char peek() { return *lexer.current; }
static char peekNext() { static char peek_next() {
if (isAtEnd()) if (is_at_end())
return '\0'; return '\0';
return lexer.current[1]; return lexer.current[1];
} }
static bool match(char expected) { static bool match(char expected) {
if (isAtEnd()) if (is_at_end())
return false; return false;
if (*lexer.current != expected) if (*lexer.current != expected)
return false; return false;
@ -47,25 +47,25 @@ static bool match(char expected) {
return true; return true;
} }
static Token makeToken(TokenType type) { static Token make_token(TokenType type) {
Token token; Token token;
token.type = type; token.type = type;
token.start = lexer.start; token.start = lexer.start;
token.length = (int)(lexer.current - lexer.start); token.length = (i32)(lexer.current - lexer.start);
token.line = lexer.line; token.line = lexer.line;
return token; return token;
} }
static Token errorToken(const char *message) { static Token error_token(const char *message) {
Token token; Token token;
token.type = TOKEN_ERROR; token.type = TOKEN_ERROR;
token.start = message; token.start = message;
token.length = (int)strlen(message); token.length = (i32)strlen(message);
token.line = lexer.line; token.line = lexer.line;
return token; return token;
} }
static void skipWhitespace() { static void skip_whitespace() {
for (;;) { for (;;) {
char c = peek(); char c = peek();
switch (c) { switch (c) {
@ -79,19 +79,19 @@ static void skipWhitespace() {
advance(); advance();
break; break;
case '/': case '/':
if (peekNext() == '/') { if (peek_next() == '/') {
// Single-line comment: skip until newline or end of file // Single-line comment: skip until newline or end of file
advance(); advance();
while (peek() != '\n' && !isAtEnd()) while (peek() != '\n' && !is_at_end())
advance(); advance();
} else if (peekNext() == '*') { } else if (peek_next() == '*') {
// Multi-line comment: skip until '*/' or end of file // Multi-line comment: skip until '*/' or end of file
advance(); advance();
advance(); advance();
while (!isAtEnd()) { while (!is_at_end()) {
if (peek() == '\n') if (peek() == '\n')
lexer.line++; lexer.line++;
if (peek() == '*' && peekNext() == '/') { if (peek() == '*' && peek_next() == '/') {
advance(); advance();
advance(); advance();
break; // Exit loop, comment ended 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) { TokenType type) {
if (lexer.current - lexer.start == start + length && if (lexer.current - lexer.start == start + length &&
memcmp(lexer.start + start, rest, length) == 0) { memcmp(lexer.start + start, rest, length) == 0) {
@ -124,9 +124,9 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'n': case 'n':
return checkKeyword(2, 1, "d", TOKEN_OPERATOR_AND); return check_keyword(2, 1, "d", TOKEN_OPERATOR_AND);
case 's': case 's':
return checkKeyword(2, 0, "", TOKEN_KEYWORD_AS); return check_keyword(2, 0, "", TOKEN_KEYWORD_AS);
} }
} }
break; break;
@ -134,47 +134,47 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'l': case 'l':
return checkKeyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE); return check_keyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE);
case 'o': case 'o':
return checkKeyword(2, 3, "nst", TOKEN_KEYWORD_CONST); return check_keyword(2, 3, "nst", TOKEN_KEYWORD_CONST);
} }
} }
break; break;
case 'e': case 'e':
return checkKeyword(1, 3, "lse", TOKEN_KEYWORD_ELSE); return check_keyword(1, 3, "lse", TOKEN_KEYWORD_ELSE);
case 'f': case 'f':
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'a': case 'a':
return checkKeyword(2, 3, "lse", TOKEN_KEYWORD_FALSE); return check_keyword(2, 3, "lse", TOKEN_KEYWORD_FALSE);
case 'o': case 'o':
return checkKeyword(2, 1, "r", TOKEN_KEYWORD_FOR); return check_keyword(2, 1, "r", TOKEN_KEYWORD_FOR);
case '3': 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; break;
case 'i': case 'i':
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'f': case 'f':
return checkKeyword(2, 0, "", TOKEN_KEYWORD_IF); return check_keyword(2, 0, "", TOKEN_KEYWORD_IF);
case 's': case 's':
return checkKeyword(2, 0, "", TOKEN_KEYWORD_IS); return check_keyword(2, 0, "", TOKEN_KEYWORD_IS);
case '8': case '8':
return checkKeyword(2, 0, "", TOKEN_TYPE_I8); return check_keyword(2, 0, "", TOKEN_TYPE_I8);
case '1': case '1':
return checkKeyword(2, 1, "6", TOKEN_TYPE_I16); return check_keyword(2, 1, "6", TOKEN_TYPE_I16);
case '3': case '3':
return checkKeyword(2, 1, "2", TOKEN_TYPE_INT); return check_keyword(2, 1, "2", TOKEN_TYPE_INT);
case 'n': case 'n':
if (lexer.current - lexer.start > 2) { if (lexer.current - lexer.start > 2) {
switch (lexer.start[2]) { switch (lexer.start[2]) {
case 'i': case 'i':
return checkKeyword(3, 2, "t", TOKEN_KEYWORD_INIT); return check_keyword(3, 2, "t", TOKEN_KEYWORD_INIT);
case 't': case 't':
return checkKeyword(3, 0, "", TOKEN_TYPE_INT); return check_keyword(3, 0, "", TOKEN_TYPE_INT);
} }
} }
break; break;
@ -185,9 +185,9 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'a': case 'a':
return checkKeyword(2, 1, "t", TOKEN_TYPE_NAT); return check_keyword(2, 1, "t", TOKEN_TYPE_NAT);
case 'i': case 'i':
return checkKeyword(2, 1, "l", TOKEN_KEYWORD_NIL); return check_keyword(2, 1, "l", TOKEN_KEYWORD_NIL);
} }
} }
break; break;
@ -195,9 +195,9 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'p': case 'p':
return checkKeyword(2, 2, "en", TOKEN_KEYWORD_OPEN); return check_keyword(2, 2, "en", TOKEN_KEYWORD_OPEN);
case 'r': case 'r':
return checkKeyword(2, 0, "", TOKEN_OPERATOR_OR); return check_keyword(2, 0, "", TOKEN_OPERATOR_OR);
} }
} }
break; break;
@ -205,7 +205,7 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'l': case 'l':
return checkKeyword(2, 2, "ex", TOKEN_KEYWORD_PLEX); return check_keyword(2, 2, "ex", TOKEN_KEYWORD_PLEX);
} }
} }
break; break;
@ -216,11 +216,11 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 2) { if (lexer.current - lexer.start > 2) {
switch (lexer.start[2]) { switch (lexer.start[2]) {
case 'a': case 'a':
return checkKeyword(3, 1, "d", TOKEN_KEYWORD_READ); return check_keyword(3, 1, "d", TOKEN_KEYWORD_READ);
case 'f': case 'f':
return checkKeyword(3, 4, "resh", TOKEN_KEYWORD_REFRESH); return check_keyword(3, 4, "resh", TOKEN_KEYWORD_REFRESH);
case 't': case 't':
return checkKeyword(3, 3, "urn", TOKEN_KEYWORD_RETURN); return check_keyword(3, 3, "urn", TOKEN_KEYWORD_RETURN);
} }
} }
break; break;
@ -231,7 +231,7 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 't': case 't':
return checkKeyword(2, 1, "r", TOKEN_TYPE_STR); return check_keyword(2, 1, "r", TOKEN_TYPE_STR);
} }
} }
break; break;
@ -239,9 +239,9 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'h': case 'h':
return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS); return check_keyword(2, 2, "is", TOKEN_KEYWORD_THIS);
case 'r': case 'r':
return checkKeyword(2, 2, "ue", TOKEN_KEYWORD_TRUE); return check_keyword(2, 2, "ue", TOKEN_KEYWORD_TRUE);
} }
} }
break; break;
@ -249,13 +249,13 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 's': case 's':
return checkKeyword(2, 1, "e", TOKEN_KEYWORD_USE); return check_keyword(2, 1, "e", TOKEN_KEYWORD_USE);
case '8': case '8':
return checkKeyword(2, 0, "", TOKEN_TYPE_U8); return check_keyword(2, 0, "", TOKEN_TYPE_U8);
case '1': case '1':
return checkKeyword(2, 1, "6", TOKEN_TYPE_U16); return check_keyword(2, 1, "6", TOKEN_TYPE_U16);
case '3': case '3':
return checkKeyword(2, 1, "2", TOKEN_TYPE_NAT); return check_keyword(2, 1, "2", TOKEN_TYPE_NAT);
} }
} }
break; break;
@ -263,129 +263,133 @@ static TokenType identifierType() {
if (lexer.current - lexer.start > 1) { if (lexer.current - lexer.start > 1) {
switch (lexer.start[1]) { switch (lexer.start[1]) {
case 'h': case 'h':
return checkKeyword(2, 3, "ile", TOKEN_KEYWORD_WHILE); return check_keyword(2, 3, "ile", TOKEN_KEYWORD_WHILE);
case 'r': case 'r':
return checkKeyword(2, 3, "ite", TOKEN_KEYWORD_WRITE); return check_keyword(2, 3, "ite", TOKEN_KEYWORD_WRITE);
} }
} }
break; break;
case 'g': case 'g':
return checkKeyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL); return check_keyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL);
case 'l': 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; return TOKEN_IDENTIFIER;
} }
static Token identifier() { static Token identifier() {
while (isAlpha(peek()) || isDigit(peek())) while (is_alpha(peek()) || is_digit(peek()))
advance(); advance();
return makeToken(identifierType()); return make_token(identifierType());
} }
static Token number() { static Token number() {
while (isDigit(peek())) while (is_digit(peek()))
advance(); advance();
/* Look for a fractional part. */ /* Look for a fractional part. */
if (peek() == '.' && isDigit(peekNext())) { if (peek() == '.' && is_digit(peek_next())) {
/* Consume the ".". */ /* Consume the ".". */
advance(); advance();
while (isDigit(peek())) while (is_digit(peek()))
advance(); 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() { static Token string() {
while (peek() != '"' && !isAtEnd()) { while (peek() != '"' && !is_at_end()) {
if (peek() == '\n') if (peek() == '\n')
lexer.line++; lexer.line++;
advance(); advance();
} }
if (isAtEnd()) if (is_at_end())
return errorToken("Unterminated string."); return error_token("Unterminated string.");
/* The closing quote. */ /* The closing quote. */
advance(); advance();
return makeToken(TOKEN_LITERAL_STR); return make_token(TOKEN_LITERAL_STR);
} }
Token nextToken() { Token next_token() {
skipWhitespace(); skip_whitespace();
lexer.start = lexer.current; lexer.start = lexer.current;
if (isAtEnd()) if (is_at_end())
return makeToken(TOKEN_EOF); return make_token(TOKEN_EOF);
char c = advance(); char c = advance();
if (isAlpha(c)) if (is_alpha(c))
return identifier(); return identifier();
if (isDigit(c)) if (is_digit(c))
return number(); return number();
switch (c) { switch (c) {
case '(': case '(':
return makeToken(TOKEN_LPAREN); return make_token(TOKEN_LPAREN);
case ')': case ')':
return makeToken(TOKEN_RPAREN); return make_token(TOKEN_RPAREN);
case '{': case '{':
return makeToken(TOKEN_LBRACE); return make_token(TOKEN_LBRACE);
case '}': case '}':
return makeToken(TOKEN_RBRACE); return make_token(TOKEN_RBRACE);
case '[': case '[':
return makeToken(TOKEN_LBRACKET); return make_token(TOKEN_LBRACKET);
case ']': case ']':
return makeToken(TOKEN_RBRACKET); return make_token(TOKEN_RBRACKET);
case ';': case ';':
return makeToken(TOKEN_SEMICOLON); return make_token(TOKEN_SEMICOLON);
case ',': case ',':
return makeToken(TOKEN_COMMA); return make_token(TOKEN_COMMA);
case '.': case '.':
return makeToken(TOKEN_DOT); return make_token(TOKEN_DOT);
case '-': case '-':
return makeToken(match('>') ? TOKEN_ARROW_LEFT : TOKEN_MINUS); return make_token(match('>') ? TOKEN_ARROW_LEFT : TOKEN_MINUS);
case '+': case '+':
return makeToken(TOKEN_PLUS); return make_token(TOKEN_PLUS);
case '/': case '/':
return makeToken(TOKEN_SLASH); return make_token(TOKEN_SLASH);
case '&': case '&':
return makeToken(match('&') ? TOKEN_AND_AND : TOKEN_AND); return make_token(match('&') ? TOKEN_AND_AND : TOKEN_AND);
case '#': case '#':
return makeToken(TOKEN_MESH); return make_token(TOKEN_MESH);
case '$': case '$':
return makeToken(TOKEN_BIG_MONEY); return make_token(TOKEN_BIG_MONEY);
case '*': case '*':
return makeToken(TOKEN_STAR); return make_token(TOKEN_STAR);
case '!': case '!':
return makeToken(match('=') ? TOKEN_BANG_EQ : TOKEN_BANG); return make_token(match('=') ? TOKEN_BANG_EQ : TOKEN_BANG);
case '=': case '=':
return makeToken(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ); return make_token(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ);
case '<': case '<':
return makeToken(match('=') ? TOKEN_LTE : TOKEN_LT); return make_token(match('=') ? TOKEN_LTE : TOKEN_LT);
case '>': case '>':
return makeToken(match('=') ? TOKEN_GTE : TOKEN_GT); return make_token(match('=') ? TOKEN_GTE : TOKEN_GT);
case '"': case '"':
return string(); 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) { switch (type) {
case TOKEN_EOF: case TOKEN_EOF:
return "EOF"; return "EOF";
case TOKEN_IDENTIFIER: case TOKEN_IDENTIFIER:
return "IDENTIFIER"; return "IDENTIFIER";
case TOKEN_LITERAL_INT: case TOKEN_LITERAL_INT:
return "LITERAL_INT"; return "LITERAL_i32";
case TOKEN_LITERAL_NAT: case TOKEN_LITERAL_NAT:
return "LITERAL_NAT"; return "LITERAL_NAT";
case TOKEN_LITERAL_REAL: case TOKEN_LITERAL_REAL:
@ -393,7 +397,7 @@ const char *tokenTypeToString(TokenType type) {
case TOKEN_LITERAL_STR: case TOKEN_LITERAL_STR:
return "LITERAL_STR"; return "LITERAL_STR";
case TOKEN_TYPE_INT: case TOKEN_TYPE_INT:
return "TYPE_INT"; return "TYPE_i32";
case TOKEN_TYPE_NAT: case TOKEN_TYPE_NAT:
return "TYPE_NAT"; return "TYPE_NAT";
case TOKEN_TYPE_REAL: case TOKEN_TYPE_REAL:

View File

@ -16,6 +16,8 @@ typedef enum {
TOKEN_TYPE_NAT, TOKEN_TYPE_NAT,
TOKEN_TYPE_REAL, TOKEN_TYPE_REAL,
TOKEN_TYPE_STR, TOKEN_TYPE_STR,
TOKEN_TYPE_BOOL,
TOKEN_TYPE_VOID,
TOKEN_KEYWORD_PLEX, TOKEN_KEYWORD_PLEX,
TOKEN_KEYWORD_FN, TOKEN_KEYWORD_FN,
TOKEN_KEYWORD_CONST, TOKEN_KEYWORD_CONST,
@ -36,6 +38,7 @@ typedef enum {
TOKEN_KEYWORD_REFRESH, TOKEN_KEYWORD_REFRESH,
TOKEN_KEYWORD_CLOSE, TOKEN_KEYWORD_CLOSE,
TOKEN_KEYWORD_LOOP, TOKEN_KEYWORD_LOOP,
TOKEN_KEYWORD_DO,
TOKEN_KEYWORD_NIL, TOKEN_KEYWORD_NIL,
TOKEN_KEYWORD_TRUE, TOKEN_KEYWORD_TRUE,
TOKEN_KEYWORD_FALSE, TOKEN_KEYWORD_FALSE,
@ -79,8 +82,8 @@ typedef struct {
int line; int line;
} Token; } Token;
void initLexer(const char *source); void init_lexer(const char *source);
Token nextToken(); Token next_token();
const char* tokenTypeToString(TokenType type); const char* token_type_to_string(TokenType type);
#endif #endif

View File

@ -184,14 +184,14 @@ Symbol *global(VM *vm) {
s.ref.global = vm->mp; s.ref.global = vm->mp;
Token token_type = nextToken(); Token token_type = next_token();
Token array_or_eq = nextToken(); Token array_or_eq = next_token();
if (array_or_eq.type == TOKEN_LBRACKET) { if (array_or_eq.type == TOKEN_LBRACKET) {
Token rb = nextToken(); Token rb = next_token();
if (rb.type != TOKEN_RBRACKET) if (rb.type != TOKEN_RBRACKET)
return nil; return nil;
Token eq = nextToken(); Token eq = next_token();
if (eq.type != TOKEN_EQ) if (eq.type != TOKEN_EQ)
return nil; return nil;
@ -268,7 +268,7 @@ Symbol *global(VM *vm) {
s.type = t; s.type = t;
Token value = nextToken(); Token value = next_token();
return nil; return nil;
} }
@ -345,7 +345,7 @@ void advance() {
parser.previous = parser.current; parser.previous = parser.current;
for (;;) { for (;;) {
parser.current = nextToken(); parser.current = next_token();
if (parser.current.type != TOKEN_ERROR) if (parser.current.type != TOKEN_ERROR)
break; break;

View File

@ -315,7 +315,7 @@ static Token string() {
return makeToken(TOKEN_LITERAL_STR); return makeToken(TOKEN_LITERAL_STR);
} }
Token nextToken() { Token next_token() {
skipWhitespace(); skipWhitespace();
lexer.start = lexer.current; lexer.start = lexer.current;
@ -376,7 +376,7 @@ Token nextToken() {
return errorToken("Unexpected character."); return errorToken("Unexpected character.");
} }
const char *tokenTypeToString(TokenType type) { const char *token_type_to_string(TokenType type) {
switch (type) { switch (type) {
case TOKEN_EOF: case TOKEN_EOF:
return "EOF"; return "EOF";

View File

@ -79,7 +79,7 @@ typedef struct {
} Token; } Token;
void initLexer(const char *source); void initLexer(const char *source);
Token nextToken(); Token next_token();
const char* tokenTypeToString(TokenType type); const char* token_type_to_string(TokenType type);
#endif #endif

View File

@ -28,7 +28,6 @@ typedef enum {
OP_STORE_OFF_16, /* store_offset_16 : memory[locals[dest] + offset] = locals[src1] && 0xFFFF */ 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_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, /* malloc : dest = fat ptr to memory of ((src1 as size) + 4) */
OP_MALLOC_IMM, /* malloc_immediate : dest = fat ptr to memory of raw <str or array or plex>*/
OP_MEMSET_8, /* memset_8 : dest <-> dest+count = src1 as u8 */ OP_MEMSET_8, /* memset_8 : dest <-> dest+count = src1 as u8 */
OP_MEMSET_16, /* memset_16 : 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 */ OP_MEMSET_32, /* memset_32 : dest <-> dest+count = src1 as u32 */

View File

@ -11,7 +11,7 @@ function main ()
load_absolute_32 y -> $1 load_absolute_32 y -> $1
call add $0 $1 -> ans call add $0 $1 -> ans
int_to_string ans -> ans_string int_to_string ans -> ans_string
call pln ans_string call pln ans_string -> void
exit 0 exit 0
function add (int a $0, int b $1) function add (int a $0, int b $1)

View File

@ -6,23 +6,23 @@ function main ()
int str_n $1 int str_n $1
load_immediate 35 -> n load_immediate 35 -> n
call &fib n -> n call fib n -> n
int_to_string n -> str_n int_to_string n -> str_n
call &pln str_n call pln str_n -> void
exit 0 exit 0
function fib (int n $0) function fib (int n $0)
load_immediate 2 -> $1 load_immediate 2 -> $1
jump_lt_int &base_case n $1 jump_lt_int base_case n $1
load_immediate 2 -> $3 load_immediate 2 -> $3
sub_int n $3 -> $4 sub_int n $3 -> $4
call &fib $4 -> $5 call fib $4 -> $5
load_immediate 1 -> $3 load_immediate 1 -> $3
sub_int n $3 -> $4 sub_int n $3 -> $4
call &fib $4 -> $6 call fib $4 -> $6
add_int $6 $5 -> $7 add_int $6 $5 -> $7
return $7 return $7
@ -37,12 +37,12 @@ function pln (str message $0)
str nl $3 str nl $3
int nl_length $4 int nl_length $4
load_immediate &terminal_namespace -> ts load_immediate terminal_namespace -> ts
load_immediate 0 -> mode load_immediate 0 -> mode
syscall OPEN ts mode -> ts syscall OPEN ts mode -> ts
strlen message -> msg_length strlen message -> msg_length
syscall WRITE ts message msg_length syscall WRITE ts message msg_length
load_immediate &new_line -> nl load_immediate new_line -> nl
strlen nl -> nl_length strlen nl -> nl_length
syscall WRITE ts nl nl_length syscall WRITE ts nl nl_length
return return

View File

@ -5,8 +5,8 @@ global str message = "nuqneH 'u'?"
function main () function main ()
str hello $0 str hello $0
load_immediate &message -> hello load_immediate message -> hello
call pln hello call pln hello -> void
exit 0 exit 0
function pln (str message $0) function pln (str message $0)
@ -16,13 +16,12 @@ function pln (str message $0)
str nl $3 str nl $3
int nl_length $4 int nl_length $4
load_immediate terminal_namespace -> ts
load_immediate &terminal_namespace -> ts
load_immediate 0 -> mode load_immediate 0 -> mode
syscall OPEN ts mode -> ts syscall OPEN ts mode -> ts
strlen message -> msg_length strlen message -> msg_length
syscall WRITE ts message msg_length syscall WRITE ts message msg_length
load_immediate &new_line -> nl load_immediate new_line -> nl
strlen nl -> nl_length strlen nl -> nl_length
syscall WRITE ts nl nl_length syscall WRITE ts nl nl_length
return return

View File

@ -1,9 +1,12 @@
global str terminal_namespace = "/dev/term/0"
global str prompt = "Enter a string:"
global str new_line = "\n"
function main () function main ()
real a is $0 real a $0
int i is $1 int i $1
int mode is $11 int mode $11
str term is $10 str term $10
load_immediate 5.0 -> a load_immediate 5.0 -> a
load_immediate 5000 -> i load_immediate 5000 -> i
@ -15,41 +18,41 @@ function main ()
add_int i $3 -> i add_int i $3 -> i
jump_ge_int loop_body i $2 jump_ge_int loop_body i $2
malloc_immediate "/dev/term/0" -> term load_immediate terminal_namespace -> term
load_immediate 0 -> mode 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 real_to_nat a -> b
malloc_immediate "Enter a string:" -> $7 load_immediate prompt -> $7
string_length $7 -> $8 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 load_immediate 32 -> $8
malloc $8 -> user_string 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 nat_to_string b -> $4
call pln $4 call pln $4 -> void
real_to_string a -> $3 real_to_string a -> $3
call pln $3 call pln $3 -> void
exit 0 exit 0
function pln (str message is $0) function pln (str message $0)
str ts is $1 str ts $1
int mode is $5 int mode $5
int msg_length is $2 int msg_length $2
str nl is $3 str nl $3
int nl_length is $4 int nl_length $4
malloc_immediate "/dev/term/0" -> ts load_immediate terminal_namespace -> ts
load_immediate 0 -> mode load_immediate 0 -> mode
syscall OPEN ts mode -> ts # get terminal device syscall OPEN ts mode -> ts
strlen message -> msg_length strlen message -> msg_length
syscall WRITE ts message msg_length syscall WRITE ts message msg_length
malloc_immediate "\n" -> nl load_immediate new_line -> nl
strlen nl -> nl_length strlen nl -> nl_length
syscall WRITE ts nl nl_length syscall WRITE ts nl nl_length
return return

View File

@ -1,22 +1,25 @@
global str terminal_namespace = "/dev/term/0"
global str prompt = "Enter a string:"
global str new_line = "\n"
function main () function main ()
int mode $11; int mode $11;
str term $10; str term $10;
malloc_immediate "/dev/term/0" -> term load_immediate terminal_namespace -> term
load_immediate 0 -> mode 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 string_length $7 -> $8
syscall WRITE term $7 $8 # print prompt syscall WRITE term $7 $8 // print prompt
str user_string $9 str user_string $9
load_immediate 32 -> $8 load_immediate 32 -> $8
malloc $8 -> user_string 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 exit 0
function pln (str message $0) function pln (str message $0)
@ -26,12 +29,12 @@ function pln (str message $0)
str nl $3 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 load_immediate 0 -> mode
syscall OPEN ts mode -> ts # get terminal device syscall OPEN ts mode -> ts
strlen message -> msg_length strlen message -> msg_length
syscall WRITE ts message msg_length syscall WRITE ts message msg_length
malloc_immediate "\n" -> nl load_immediate new_line -> nl
strlen nl -> nl_length strlen nl -> nl_length
syscall WRITE ts nl nl_length syscall WRITE ts nl nl_length
return return

View File

@ -8,177 +8,178 @@ global const byte LIGHT_GRAY = 182
global byte SELECTED_COLOR = 255 global byte SELECTED_COLOR = 255
function main () function main ()
# Open screen // Open screen
plex screen is $0 plex screen $0
str screen_name is $18 str screen_name $18
int mode is $11 int mode $11
nat screen_buffer is $21 nat screen_buffer $21
# use load immediate because it is a pointer to a string, not a value // use load immediate because it a pointer to a string, not a value
load_address &screen_namespace -> screen_name load_address screen_namespace -> screen_name
load_immediate 0 -> mode 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 width $20
nat size is $22 nat size $22
load_offset_32 screen 8 -> width # load width load_offset_32 screen 8 -> width // load width
load_offset_32 screen 12 -> size # load size load_offset_32 screen 12 -> size // load size
load_immediate 16 -> $1 # offset for screen buffer load_immediate 16 -> $1 // offset for screen buffer
add_nat screen $1 -> screen_buffer add_nat screen $1 -> screen_buffer
# open mouse // open mouse
plex mouse is $15 plex mouse $15
str mouse_name is $16 str mouse_name $16
load_address &mouse_namespace -> mouse_name load_address mouse_namespace -> mouse_name
syscall OPEN mouse_name mode -> mouse # Mouse mouse = open("/dev/mouse/0", 0); syscall OPEN mouse_name mode -> mouse // Mouse mouse = open("/dev/mouse/0", 0);
byte color is $1 byte color $1
nat x_pos is $12 nat x_pos $12
nat y_pos is $13 nat y_pos $13
load_absolute_32 &BLACK -> color load_absolute_32 BLACK -> color
load_immediate 1 -> x_pos load_immediate 1 -> x_pos
load_immediate 1 -> y_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 21 -> x_pos
load_immediate 1 -> y_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 syscall WRITE screen screen_buffer size
nat zero is $11 nat zero $11
draw_loop: loop draw_loop
# load mouse click data // load mouse click data
syscall REFRESH mouse syscall REFRESH mouse
byte left_down is $9 byte left_down $9
load_offset_8 mouse 16 -> left_down # load btn1 pressed 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_x $7
nat mouse_y is $8 nat mouse_y $8
load_offset_32 mouse 8 -> mouse_x # load x load_offset_32 mouse 8 -> mouse_x // load x
load_offset_32 mouse 12 -> mouse_y # load y load_offset_32 mouse 12 -> mouse_y // load y
nat box_size is $14 nat box_size $14
load_immediate 20 -> box_size load_immediate 20 -> box_size
# first row // first row
load_absolute_32 &BLACK -> color load_absolute_32 BLACK -> color
load_immediate 1 -> x_pos load_immediate 1 -> x_pos
load_immediate 1 -> y_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
call &set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size 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 21 -> x_pos
load_immediate 1 -> y_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
call &set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void
syscall WRITE screen screen_buffer size syscall WRITE screen screen_buffer size
byte selected_color is $25 byte selected_color $25
load_absolute_32 &SELECTED_COLOR -> selected_color load_absolute_32 SELECTED_COLOR -> selected_color
nat brush_size is $19 nat brush_size $19
load_immediate 5 -> brush_size 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 exit 0
function set_color_if_clicked (int click_x is $0, int click_y is $1, function set_color_if_clicked (int click_x $0, int click_y $1,
int box_x is $2, int box_y is $3, byte color is $4, int box_size is $5) int box_x $2, int box_y $3, byte color $4, int box_size $5)
# Compute right // Compute right
int right_edge is $6 int right_edge $6
add_int box_x box_size -> right_edge add_int box_x box_size -> right_edge
# Compute bottom = box_y + box_size // Compute bottom = box_y + box_size
int bottom_edge is $7 int bottom_edge $7
add_int box_y box_size -> bottom_edge add_int box_y box_size -> bottom_edge
# Bounds check: x in [box_x, right] and y in [box_y, bottom] // Bounds check: x in [box_x, right] and y in [box_y, bottom]
jump_lt_int &fail click_x box_x jump_lt_int fail click_x box_x
jump_ge_int &fail click_x right_edge jump_ge_int fail click_x right_edge
jump_lt_int &fail click_y box_y jump_lt_int fail click_y box_y
jump_ge_int &fail click_y bottom_edge jump_ge_int fail click_y bottom_edge
store_absolute_8 &SELECTED_COLOR color store_absolute_8 SELECTED_COLOR color
fail: else fail
return return
function draw_outlined_swatch(nat base is $0, function draw_outlined_swatch(nat base $0,
byte color is $1, int x is $2, int y is $3, int width is $4) byte color $1, int x $2, int y $3, int width $4)
# Constants // Constants
nat background_color is $5 nat background_color $5
load_absolute_32 &GRAY -> background_color load_absolute_32 GRAY -> background_color
byte selected_color is $10 byte selected_color $10
load_absolute_32 &SELECTED_COLOR -> selected_color load_absolute_32 SELECTED_COLOR -> selected_color
jump_eq_int &set_selected selected_color color jump_eq_int set_selected selected_color color
jump &end_set_selected jump end_set_selected
set_selected: set_selected:
load_absolute_32 &DARK_GRAY -> background_color load_absolute_32 DARK_GRAY -> background_color
end_set_selected: end_set_selected:
nat outline_size is $6 nat outline_size $6
load_immediate 20 -> outline_size load_immediate 20 -> outline_size
nat fill_size is $7 nat fill_size $7
load_immediate 17 -> fill_size load_immediate 17 -> fill_size
nat offset is $8 nat offset $8
load_immediate 2 -> offset 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 x offset -> $9 // x + 2
add_int y offset -> $10 # y + 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 return
function draw_box (nat base is $0, nat screen_width is $1, function draw_box (nat base $0, nat screen_width $1,
byte color is $2, nat x_start is $3, nat y_start is $4, nat width is $5, nat height is $6) byte color $2, nat x_start $3, nat y_start $4,
nat width $5, nat height $6)
# Compute start address: base + y*640 + x // Compute start address: base + y*640 + x
nat offset is $15 nat offset $15
mul_int y_start screen_width -> offset mul_int y_start screen_width -> offset
add_int offset x_start -> offset add_int offset x_start -> offset
add_nat offset base -> offset add_nat offset base -> offset
nat fat_ptr_size is $25 nat fat_ptr_size $25
load_immediate 4 -> fat_ptr_size 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 load_immediate 1 -> i
int zero is $26 int zero $26
load_immediate 0 -> zero load_immediate 0 -> zero
int row_end is $27 int row_end $27
nat pixel_ptr is $29 nat pixel_ptr $29
draw_box_outer: loop draw_box_outer
add_int offset width -> row_end # current + width add_int offset width -> row_end // current + width
register_move offset -> pixel_ptr # set pixel point register_move offset -> pixel_ptr // set pixel point
memset_8 pixel_ptr color width # draw row memset_8 pixel_ptr color width // draw row
add_int offset screen_width -> offset # next row += 640 add_int offset screen_width -> offset // next row += 640
sub_int height i -> height # decrement row count 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 return

View File

@ -39,12 +39,12 @@ function main ()
load_absolute_32 BLACK -> color load_absolute_32 BLACK -> color
load_immediate 1 -> x_pos load_immediate 1 -> x_pos
load_immediate 1 -> y_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 21 -> x_pos
load_immediate 1 -> y_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 syscall WRITE screen screen_buffer size
@ -72,15 +72,15 @@ function main ()
load_absolute_32 BLACK -> color load_absolute_32 BLACK -> color
load_immediate 1 -> x_pos load_immediate 1 -> x_pos
load_immediate 1 -> y_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
call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size 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 21 -> x_pos
load_immediate 1 -> y_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
call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void
syscall WRITE screen screen_buffer size syscall WRITE screen screen_buffer size
@ -90,7 +90,7 @@ function main ()
nat brush_size $19 nat brush_size $19
load_immediate 5 -> brush_size 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
@ -144,12 +144,12 @@ function draw_outlined_swatch(nat base $0,
nat offset $8 nat offset $8
load_immediate 2 -> offset 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 x offset -> $9 // x + 2
add_int y offset -> $10 // y + 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 return

View File

@ -11,7 +11,7 @@ function main ()
add_real x y -> result add_real x y -> result
str result_str $3 str result_str $3
real_to_string result -> result_str real_to_string result -> result_str
call &pln result_str call &pln result_str -> void
exit 0 exit 0
function pln (str message $0) function pln (str message $0)

View File

@ -24,21 +24,21 @@ function main ()
syscall OPEN screen mode -> screen syscall OPEN screen mode -> screen
nat_to_string screen -> tmp_str nat_to_string screen -> tmp_str
call pln tmp_str call pln tmp_str -> void
load_offset_32 screen 8 -> width load_offset_32 screen 8 -> width
nat_to_string width -> tmp_str nat_to_string width -> tmp_str
call pln tmp_str call pln tmp_str -> void
load_offset_32 screen 12 -> buffer_size load_offset_32 screen 12 -> buffer_size
nat_to_string buffer_size -> tmp_str nat_to_string buffer_size -> tmp_str
call pln tmp_str call pln tmp_str -> void
load_immediate 16 -> offset_temp load_immediate 16 -> offset_temp
add_nat screen offset_temp -> screen_buffer add_nat screen offset_temp -> screen_buffer
nat_to_string screen_buffer -> tmp_str nat_to_string screen_buffer -> tmp_str
call pln tmp_str call pln tmp_str -> void
// open mouse // open mouse
load_immediate mouse_namespace -> mouse load_immediate mouse_namespace -> mouse
@ -72,17 +72,18 @@ function main ()
exit 0 exit 0
function pln (str message $0) function pln (str message $0)
str term $1 str ts $1
int mode $5
int msg_length $2 int msg_length $2
str nl $3 str nl $3
int nl_length $4 int nl_length $4
int mode $5
load_immediate terminal_namespace -> ts
load_immediate 0 -> mode load_immediate 0 -> mode
syscall OPEN terminal_namespace mode -> term syscall OPEN ts mode -> ts
strlen message -> msg_length strlen message -> msg_length
syscall WRITE term message msg_length syscall WRITE ts message msg_length
load_address new_line -> nl load_immediate new_line -> nl
strlen nl -> nl_length strlen nl -> nl_length
syscall WRITE term nl nl_length syscall WRITE ts nl nl_length
return return