1
0
Fork 0

Incrementally build the compiler from the assembler

This commit is contained in:
zongor 2026-02-17 20:41:23 -08:00
parent 374a5d5c5d
commit 56550a3690
9 changed files with 2292 additions and 475 deletions

File diff suppressed because it is too large Load Diff

View File

@ -119,10 +119,10 @@ static TokenType checkKeyword(int start, int length, const char *rest,
} }
static TokenType identifierType() { static TokenType identifierType() {
switch (lexer.start[0]) { switch (parser.start[0]) {
case 'a': case 'a':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'n': case 'n':
return checkKeyword(2, 1, "d", TOKEN_OPERATOR_AND); return checkKeyword(2, 1, "d", TOKEN_OPERATOR_AND);
case 's': case 's':
@ -131,8 +131,8 @@ static TokenType identifierType() {
} }
break; break;
case 'c': case 'c':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'l': case 'l':
return checkKeyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE); return checkKeyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE);
case 'o': case 'o':
@ -143,8 +143,8 @@ static TokenType identifierType() {
case 'e': case 'e':
return checkKeyword(1, 3, "lse", TOKEN_KEYWORD_ELSE); return checkKeyword(1, 3, "lse", TOKEN_KEYWORD_ELSE);
case 'f': case 'f':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'a': case 'a':
return checkKeyword(2, 3, "lse", TOKEN_KEYWORD_FALSE); return checkKeyword(2, 3, "lse", TOKEN_KEYWORD_FALSE);
case 'o': case 'o':
@ -156,8 +156,8 @@ static TokenType identifierType() {
} }
break; break;
case 'i': case 'i':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'f': case 'f':
return checkKeyword(2, 0, "", TOKEN_KEYWORD_IF); return checkKeyword(2, 0, "", TOKEN_KEYWORD_IF);
case 's': case 's':
@ -169,8 +169,8 @@ static TokenType identifierType() {
case '3': case '3':
return checkKeyword(2, 1, "2", TOKEN_TYPE_INT); return checkKeyword(2, 1, "2", TOKEN_TYPE_INT);
case 'n': case 'n':
if (lexer.current - lexer.start > 2) { if (parser.current - parser.start > 2) {
switch (lexer.start[2]) { switch (parser.start[2]) {
case 'i': case 'i':
return checkKeyword(3, 2, "t", TOKEN_KEYWORD_INIT); return checkKeyword(3, 2, "t", TOKEN_KEYWORD_INIT);
case 't': case 't':
@ -182,8 +182,8 @@ static TokenType identifierType() {
} }
break; break;
case 'n': case 'n':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'a': case 'a':
return checkKeyword(2, 1, "t", TOKEN_TYPE_NAT); return checkKeyword(2, 1, "t", TOKEN_TYPE_NAT);
case 'i': case 'i':
@ -192,8 +192,8 @@ static TokenType identifierType() {
} }
break; break;
case 'o': case 'o':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'p': case 'p':
return checkKeyword(2, 2, "en", TOKEN_KEYWORD_OPEN); return checkKeyword(2, 2, "en", TOKEN_KEYWORD_OPEN);
case 'r': case 'r':
@ -202,19 +202,21 @@ static TokenType identifierType() {
} }
break; break;
case 'p': case 'p':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 't':
return checkKeyword(2, 1, "r", TOKEN_TYPE_PTR);
case 'l': case 'l':
return checkKeyword(2, 2, "ex", TOKEN_KEYWORD_PLEX); return checkKeyword(2, 2, "ex", TOKEN_KEYWORD_PLEX);
} }
} }
break; break;
case 'r': case 'r':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'e': case 'e':
if (lexer.current - lexer.start > 2) { if (parser.current - parser.start > 2) {
switch (lexer.start[2]) { switch (parser.start[2]) {
case 'a': case 'a':
return checkKeyword(3, 1, "d", TOKEN_KEYWORD_READ); return checkKeyword(3, 1, "d", TOKEN_KEYWORD_READ);
case 't': case 't':
@ -226,11 +228,11 @@ static TokenType identifierType() {
} }
break; break;
case 's': case 's':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 't': case 't':
if (lexer.current - lexer.start > 2) { if (parser.current - parser.start > 2) {
switch (lexer.start[2]) { switch (parser.start[2]) {
case 'r': case 'r':
return checkKeyword(2, 0, "", TOKEN_TYPE_STR); return checkKeyword(2, 0, "", TOKEN_TYPE_STR);
case 'a': case 'a':
@ -241,8 +243,8 @@ static TokenType identifierType() {
} }
break; break;
case 't': case 't':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'h': case 'h':
return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS); return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS);
case 'r': case 'r':
@ -251,8 +253,8 @@ static TokenType identifierType() {
} }
break; break;
case 'u': case 'u':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 's': case 's':
return checkKeyword(2, 1, "e", TOKEN_KEYWORD_USE); return checkKeyword(2, 1, "e", TOKEN_KEYWORD_USE);
case '8': case '8':
@ -265,8 +267,8 @@ static TokenType identifierType() {
} }
break; break;
case 'w': case 'w':
if (lexer.current - lexer.start > 1) { if (parser.current - parser.start > 1) {
switch (lexer.start[1]) { switch (parser.start[1]) {
case 'h': case 'h':
return checkKeyword(2, 3, "ile", TOKEN_KEYWORD_WHILE); return checkKeyword(2, 3, "ile", TOKEN_KEYWORD_WHILE);
case 'r': case 'r':
@ -401,6 +403,8 @@ const char *token_type_to_string(TokenType type) {
return "TYPE_REAL"; return "TYPE_REAL";
case TOKEN_TYPE_STR: case TOKEN_TYPE_STR:
return "TYPE_STR"; return "TYPE_STR";
case TOKEN_TYPE_PTR:
return "TYPE_PTR";
case TOKEN_KEYWORD_PLEX: case TOKEN_KEYWORD_PLEX:
return "KEYWORD_PLEX"; return "KEYWORD_PLEX";
case TOKEN_KEYWORD_FN: case TOKEN_KEYWORD_FN:
@ -433,8 +437,8 @@ const char *token_type_to_string(TokenType type) {
return "TOKEN_KEYWORD_READ"; return "TOKEN_KEYWORD_READ";
case TOKEN_KEYWORD_WRITE: case TOKEN_KEYWORD_WRITE:
return "TOKEN_KEYWORD_WRITE"; return "TOKEN_KEYWORD_WRITE";
case TOKEN_KEYWORD_REFRESH: case TOKEN_KEYWORD_STAT:
return "TOKEN_KEYWORD_REFRESH"; return "TOKEN_KEYWORD_STAT";
case TOKEN_KEYWORD_CLOSE: case TOKEN_KEYWORD_CLOSE:
return "TOKEN_KEYWORD_CLOSE"; return "TOKEN_KEYWORD_CLOSE";
case TOKEN_KEYWORD_NIL: case TOKEN_KEYWORD_NIL:

View File

@ -18,6 +18,7 @@ typedef enum {
TOKEN_TYPE_STR, TOKEN_TYPE_STR,
TOKEN_TYPE_BOOL, TOKEN_TYPE_BOOL,
TOKEN_TYPE_VOID, TOKEN_TYPE_VOID,
TOKEN_TYPE_PTR,
TOKEN_KEYWORD_PLEX, TOKEN_KEYWORD_PLEX,
TOKEN_KEYWORD_FN, TOKEN_KEYWORD_FN,
TOKEN_KEYWORD_CONST, TOKEN_KEYWORD_CONST,
@ -34,7 +35,7 @@ typedef enum {
TOKEN_KEYWORD_OPEN, TOKEN_KEYWORD_OPEN,
TOKEN_KEYWORD_READ, TOKEN_KEYWORD_READ,
TOKEN_KEYWORD_WRITE, TOKEN_KEYWORD_WRITE,
TOKEN_KEYWORD_REFRESH, TOKEN_KEYWORD_STAT,
TOKEN_KEYWORD_CLOSE, TOKEN_KEYWORD_CLOSE,
TOKEN_KEYWORD_LOOP, TOKEN_KEYWORD_LOOP,
TOKEN_KEYWORD_DO, TOKEN_KEYWORD_DO,

View File

@ -1,47 +1,38 @@
/** str terminal_namespace = "/dev/term/0";
* Constants str new_line = "\n";
*/ int x = 1;
str term_namespace = "/dev/term/0";
str nl = "\n";
int x = 0;
int y = 1; int y = 1;
plex Terminal { function main () {
nat handle; load_absolute_32 x -> $0;
load_absolute_32 y -> $1;
call add ($0 $1) -> $2;
int_to_string $2 -> $3;
call pln ($3);
exit 0;
} }
/** function add (int a, int b) {
* Main function int result;
*/ add_int a b -> result;
function main() { return result;
int tmp0 = x;
int tmp1 = y;
int tmp2 = add(tmp0, tmp1);
str tmp3 = tmp2 as str;
pln(tmp3);
} }
/** function pln (str message) {
* Add two numbers together ptr term;
*/ int msg_length;
function add(int a, int b) int { str nl;
int tmp0 = a + b; int nl_length;
return tmp0; int mode;
} str term_ns;
/** load_immediate 0 -> mode;
* Print with a newline load_address terminal_namespace -> term_ns;
*/ syscall OPEN term_ns mode term;
function pln(str message) { string_length message -> msg_length;
str term_ns = term_namespace; syscall WRITE term message msg_length;
int mode = 0; load_address new_line -> nl;
string_length nl -> nl_length;
Terminal term = open(term_ns, mode); syscall WRITE term nl nl_length;
return;
int msg_len = message.length;
write(term, message, msg_len);
str nl_local = nl;
int nl_len = nl.length;
write(term, nl_local, nl_len);
} }

View File

@ -1,60 +1,51 @@
/** str terminal_namespace = "/dev/term/0";
* Constants str new_line = "\n";
*/
str term_namespace = "/dev/term/0";
str nl = "\n";
plex Terminal { function main () {
nat handle; int str_n;
load_immediate 35 -> $0;
call fib ($0) -> $0;
int_to_string $0 -> str_n;
call pln (str_n);
exit 0;
} }
/** function fib (int n) {
* Main function load_immediate 2 -> $1;
*/
function main() {
int fib = 35;
int ans = fib(35);
str ans_s = ans as str;
pln(ans_s);
}
/** jump_lt_int base_case n $1;
* Recursively calculate fibonacci
*/
function fib(int n) int {
int base_check = 2;
jump_lt_int base_case n base_check; load_immediate 2 -> $3;
jump end1; sub_int n $3 -> $4;
do base_case; call fib ($4) -> $5;
load_immediate 1 -> $3;
sub_int n $3 -> $4;
call fib ($4) -> $6;
add_int $6 $5 -> $7;
return $7;
else base_case;
return n; return n;
else base_case_end;
int tmp_c2 = 2;
int tmp_c2_n = n - tmp_c2;
int ans_c2 = fib(tmp_c2_n);
int tmp_c1 = 1;
int tmp_c1_n = tmp_c1 - n;
int ans_c1 = fib(tmp_c1_n);
int ans = tmp_c1_n + tmp_c2_n;
return ans;
} }
/** function pln (str message) {
* Print with a newline ptr term;
*/ int msg_length;
function pln(str message) { str nl;
str term_ns = term_namespace; int nl_length;
int mode = 0; int mode;
str term_ns;
Terminal term = open(term_ns, mode); load_immediate 0 -> mode;
load_address terminal_namespace -> term_ns;
int msg_len = message.length; syscall OPEN term_ns mode term;
write(term, message, msg_len); string_length message -> msg_length;
syscall WRITE term message msg_length;
str nl_local = nl; load_address new_line -> nl;
int nl_len = nl.length; string_length nl -> nl_length;
write(term, nl_local, nl_len); syscall WRITE term nl nl_length;
return;
} }

View File

@ -1,32 +1,30 @@
str term_namespace = "/dev/term/0"; str terminal_namespace = "/dev/term/0";
str new_line = "\n";
str hello = "nuqneH 'u'?"; str hello = "nuqneH 'u'?";
str nl = "\n";
plex Terminal { function main () {
nat handle; str msg;
load_address hello -> msg;
call pln (msg);
exit 0;
} }
/** function pln (str message) {
* Main function ptr term;
*/ int msg_length;
function main() { str nl;
str msg = hello; int nl_length;
pln(msg); int mode;
} str term_ns;
/** load_immediate 0 -> mode;
* Print with a newline load_address terminal_namespace -> term_ns;
*/ syscall OPEN term_ns mode term;
function pln(str message) { string_length message -> msg_length;
str term_ns = term_namespace; syscall WRITE term message msg_length;
int mode = 0; load_address new_line -> nl;
string_length nl -> nl_length;
Terminal term = open(term_ns, mode); syscall WRITE term nl nl_length;
return;
int msg_len = message.length;
write(term, message, msg_len);
str nl_local = nl;
int nl_len = nl.length;
write(term, nl_local, nl_len);
} }

View File

@ -1,65 +1,63 @@
str term_namespace = "/dev/term/0"; str terminal_namespace = "/dev/term/0";
str prompt = "Enter a string:"; str prompt = "Enter a string:";
str nl = "\n"; str new_line = "\n";
function main () {
real a;
int i;
int mode $11;
str term $10;
plex Terminal { // do (i = 5000; i >= 0, i = i - 1)
nat handle; load_immediate 5.0 -> a;
} load_immediate 5000 -> i;
load_immediate 0 -> $2;
/** load_immediate -1 -> $3;
* Main function load_immediate 5.0 -> $5;
*/
function main() {
str term_ns = term_namespace;
int mode = 0;
Terminal term = open(term_ns, mode);
real a = 5.0;
// do (int i = 5000; i >= 0, i = i - 1)
int i = 5000;
int tmp0 = 0;
int tmp1 = 1;
int tmp2 = 5.0;
loop loop_body { loop loop_body {
a = a + tmp2; add_real a $5 -> a;
i = i - tmp1; add_int i $3 -> i;
jump_ge_int loop_body i tmp0; jump_ge_int loop_body i $2;
} }
nat b = a as nat; load_address terminal_namespace -> term;
str local_prompt = prompt; load_immediate 0 -> mode;
pln(local_prompt); syscall OPEN term mode term; // Terminal term = open("/dev/term/0", 0);
nat size = 32; nat b $1;
str user_string = malloc(size); real_to_nat a -> b;
read(term, user_string, size); load_address prompt -> $7;
string_length $7 -> $8;
syscall WRITE term $7 $8; // print prompt
str a_str = a as str; str user_string $9;
pln(a_str); load_immediate 32 -> $8;
malloc $8 -> user_string;
syscall READ term user_string $8; // read in max 32 byte string
str b_str = b as str; call pln (user_string);
pln(b_str); nat_to_string b -> $4;
call pln ($4);
pln(user_string); real_to_string a -> $3;
call pln ($3);
exit 0;
} }
/** function pln (str message) {
* Print with a newline ptr term;
*/ int msg_length;
function pln(str message) { str nl;
str term_ns = term_namespace; int nl_length;
int mode = 0; int mode;
str term_ns;
Terminal term = open(term_ns, mode); load_immediate 0 -> mode;
load_address terminal_namespace -> term_ns;
int msg_len = message.length; syscall OPEN term_ns mode term;
write(term, message, msg_len); string_length message -> msg_length;
syscall WRITE term message msg_length;
str nl_local = nl; load_address new_line -> nl;
int nl_len = nl.length; string_length nl -> nl_length;
write(term, nl_local, nl_len); syscall WRITE term nl nl_length;
return;
} }

View File

@ -1,26 +1,43 @@
/** str terminal_namespace = "/dev/term/0";
* Constants str prompt = "Enter a string:";
*/ str new_line = "\n";
const str nl = "\n";
plex Terminal { function main () {
nat handle; int mode;
str term;
load_address terminal_namespace -> term;
load_immediate 0 -> mode;
syscall OPEN term mode term; // Terminal term = open("/dev/term/0", 0);
load_address prompt -> $7;
string_length $7 -> $8;
syscall WRITE term $7 $8; // print prompt
str user_string;
load_immediate 32 -> $8;
malloc $8 -> user_string;
syscall READ term user_string $8; // read in max 32 byte string
call pln (user_string);
exit 0;
} }
/** function pln (str message) {
* Main function ptr term;
*/ int msg_length;
function main() { str nl;
Terminal term = open("/dev/term/0", 0); int nl_length;
pln(term, "Enter a string: "); int mode;
pln(term, term.read(32)); str term_ns;
return 0;
}
/** load_immediate 0 -> mode;
* Print with a newline load_address terminal_namespace -> term_ns;
*/ syscall OPEN term_ns mode term;
function pln(Terminal term, str message) { string_length message -> msg_length;
write(term, message, message.length); syscall WRITE term message msg_length;
write(term, nl, nl.length); load_address new_line -> nl;
string_length nl -> nl_length;
syscall WRITE term nl nl_length;
return;
} }

View File

@ -34,188 +34,195 @@ byte DARK_ORANGE = 208;
byte GOLD = 244; byte GOLD = 244;
byte SELECTED_COLOR = 255; byte SELECTED_COLOR = 255;
plex Screen {
nat handle;
nat width;
nat height;
byte[] buffer;
}
plex Mouse {
nat handle;
nat x;
nat y;
bool left;
bool right;
bool middle;
bool btn4;
}
function main () { function main () {
str screen_name = screen_namespace; // Open screen
int mode = 0; ptr screen $0;
Screen screen = open(screen_name, mode); str screen_name $18;
int mode $11;
nat screen_buffer $21;
nat width = screen.width; // use load immediate because it a pointer to a string, not a value
nat size = screen.size; load_address screen_namespace -> screen_name;
nat screen_offset = 16; load_immediate 0 -> mode;
nat screen_buffer = screen_buffer + screen_offset; syscall OPEN screen_name mode screen; // Screen screen = open("/dev/screen/0", 0);
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 // open mouse
str mouse_name = mouse_namespace; ptr mouse $15;
Mouse mouse = open(mouse_name, mode); 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 = BLACK; byte color $1;
nat x_pos = 1; nat x_pos $12;
nat y_pos = 1; nat y_pos $13;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width);
color = WHITE; load_absolute_8 BLACK -> color;
x_pos = 21; load_immediate 1 -> x_pos;
y_pos = 1; load_immediate 1 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
color = CHARCOAL; load_absolute_8 WHITE -> color;
x_pos = 1; load_immediate 21 -> x_pos;
y_pos = 21; load_immediate 1 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
color = DARK_GRAY; load_absolute_8 CHARCOAL -> color;
x_pos = 21; load_immediate 1 -> x_pos;
y_pos = 21; load_immediate 21 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
color = RED; load_absolute_8 DARK_GRAY -> color;
x_pos = 1; load_immediate 21 -> x_pos;
y_pos = 41; load_immediate 21 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
color = ORANGE; load_absolute_8 RED -> color;
x_pos = 21; load_immediate 1 -> x_pos;
y_pos = 41; load_immediate 41 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
color = YELLOW; load_absolute_8 ORANGE -> color;
x_pos = 1; load_immediate 21 -> x_pos;
y_pos = 61; load_immediate 41 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
color = GREEN; load_absolute_8 YELLOW -> color;
x_pos = 21; load_immediate 1 -> x_pos;
y_pos = 61; load_immediate 61 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
color = BLUE; load_absolute_8 GREEN -> color;
x_pos = 1; load_immediate 21 -> x_pos;
y_pos = 81; load_immediate 61 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
color = PURPLE; load_absolute_8 BLUE -> color;
x_pos = 21; load_immediate 1 -> x_pos;
y_pos = 81; load_immediate 81 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 PURPLE -> color;
load_immediate 21 -> x_pos;
load_immediate 81 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
// screen.draw // screen.draw
write(screen, screen_buffer, size); syscall WRITE screen screen_buffer size;
nat zero = 0; nat m_zero $11;
loop draw { loop draw_loop {
// load mouse click data // load mouse click data
refresh(mouse); syscall REFRESH mouse;
byte left_down = mouse.down; byte left_down $9;
load_offset_8 mouse 16 -> left_down; // load btn1 pressed
jump_eq_nat draw left_down zero; // if (!btn1.left) continue; jump_eq_nat draw_loop left_down m_zero; // if (!btn1.left) continue;
nat mouse_x = mouse.x; nat mouse_x $7;
nat mouse_y = mouse.y; 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 = 20; nat box_size $14;
load_immediate 20 -> box_size;
// first row // first row
color = BLACK; load_absolute_8 BLACK -> color;
x_pos = 1; load_immediate 1 -> x_pos;
y_pos = 1; load_immediate 1 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
color = WHITE; load_absolute_8 WHITE -> color;
x_pos = 21; load_immediate 21 -> x_pos;
y_pos = 1; load_immediate 1 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
color = CHARCOAL; load_absolute_8 CHARCOAL -> color;
x_pos = 1; load_immediate 1 -> x_pos;
y_pos = 21; load_immediate 21 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
DARK_GRAY -> color; load_absolute_8 DARK_GRAY -> color;
x_pos = 21; load_immediate 21 -> x_pos;
y_pos = 21; load_immediate 21 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
color = RED; load_absolute_8 RED -> color;
x_pos = 1; load_immediate 1 -> x_pos;
y_pos = 41; load_immediate 41 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
color = ORANGE; load_absolute_8 ORANGE -> color;
x_pos = 21; load_immediate 21 -> x_pos;
y_pos = 41; load_immediate 41 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
color = YELLOW; load_absolute_8 YELLOW -> color;
x_pos = 1; load_immediate 1 -> x_pos;
y_pos = 61; load_immediate 61 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
color = GREEN; load_absolute_8 GREEN -> color;
x_pos = 21; load_immediate 21 -> x_pos;
y_pos = 61; load_immediate 61 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
color = BLUE; load_absolute_8 BLUE -> color;
x_pos = 1; load_immediate 1 -> x_pos;
y_pos = 81; load_immediate 81 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
color = PURPLE; load_absolute_8 PURPLE -> color;
x_pos = 21; load_immediate 21 -> x_pos;
y_pos = 81; load_immediate 81 -> y_pos;
draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
set_color(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);
write(screen, screen_buffer, size); syscall WRITE screen screen_buffer size;
byte selected_color = SELECTED_COLOR; byte selected_color $25;
load_absolute_8 SELECTED_COLOR -> selected_color;
nat brush_size = 5; nat brush_size $19;
load_immediate 5 -> brush_size;
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);
jump draw; jump draw_loop;
} }
// Flush and exit // Flush and exit
exit 0; exit 0;
} }
function set_color (int click_x, int click_y, int box_x, int box_y, byte check_color, int size) { function set_color_if_clicked (int click_x $0, int click_y $1,
int box_x $2, int box_y $3, byte check_color $4, int bsize $5) {
// Compute right // Compute right
int right_edge = box_x + size; int right_edge $6;
add_int box_x bsize -> right_edge;
// Compute bottom = box_y + size // Compute bottom = box_y + bsize
int bottom_edge = box_y + size; int bottom_edge $7;
add_int box_y bsize -> 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;
@ -223,55 +230,72 @@ function set_color (int click_x, int click_y, int box_x, int box_y, byte check_c
jump_lt_int fail click_y box_y; jump_lt_int fail click_y box_y;
jump_gt_int fail click_y bottom_edge; jump_gt_int fail click_y bottom_edge;
SELECTED_COLOR = check_color; store_absolute_8 check_color -> SELECTED_COLOR;
else fail else fail
return; return;
} }
function draw_outlined_swatch(nat base, byte swatch_color, int x, int y, int width) { function draw_outlined_swatch(nat base,
byte swatch_color, int x, int y, int width) {
nat background_color = GRAY; // Constants
byte selected_color = SELECTED_COLOR; nat background_color;
load_absolute_8 GRAY -> background_color;
byte selected_color;
load_absolute_8 SELECTED_COLOR -> selected_color;
jump_eq_int set_selected swatch_color selected_color; jump_eq_int set_selected swatch_color selected_color;
jump end_set_selected; jump end_set_selected;
do set_selected do set_selected
background_color = DARK_GRAY; load_absolute_8 DARK_GRAY -> background_color;
else end_set_selected else end_set_selected
nat outline_size = 20; nat outline_size;
nat fill_size = 17; load_immediate 20 -> outline_size;
draw_box(base, width, background_color, x, y, outline_size, outline_size); nat fill_size;
load_immediate 17 -> fill_size;
nat offset = 2; nat offset;
int xO = x + offset; // x + 2 load_immediate 2 -> offset;
int yO = y + offset; // y + 2
draw_box(base, width, swatch_color, xO, yO, fill_size, fill_size); call draw_box (base width background_color x y outline_size outline_size);
int x_off;
int y_off;
add_int x offset -> x_off; // x + 2
add_int y offset -> y_off; // y + 2
call draw_box (base width swatch_color x_off y_off fill_size fill_size);
return; return;
} }
function draw_box (nat base, nat screen_width, byte box_color, function draw_box (nat db_base, nat screen_width,
nat x, nat y, nat width, nat height) { byte box_color, nat x_start, nat y_start,
nat db_width, nat height) {
nat fat_ptr_size = 4;
// Compute start address: base + y*640 + x // Compute start address: base + y*640 + x
nat offset = y * screen_width; nat offset;
offset = offset + x; mul_int y_start screen_width -> offset;
offset = offset + base; add_int offset x_start -> offset;
offset = offset + fat_ptr_size; // need to add offset for fat pointer size add_nat offset db_base -> offset;
nat fat_ptr_size;
load_immediate 4 -> fat_ptr_size;
add_nat offset fat_ptr_size -> offset; // need to add offset for fat pointer size
int i = 1; int i;
int zero = 0; load_immediate 1 -> i;
int zero;
load_immediate 0 -> zero;
loop draw_box_outer { loop draw_box_outer {
memset(offset, width, box_color); // draw row memset_8 box_color db_width -> offset; // draw row
offset = offset + screen_width; // next row += 640 add_int offset screen_width -> offset; // next row += 640
height = height - i; // 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;