implement automatic register handling with scope.
This commit is contained in:
parent
56550a3690
commit
292aca1251
|
|
@ -132,46 +132,11 @@ u32 get_reg(Token token, ScopeTable *st) {
|
||||||
return get_ref(st, token.start, token.length);
|
return get_ref(st, token.start, token.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.type == TOKEN_BIG_MONEY) {
|
fprintf(stderr, "Error: Not a symbol at line %d: %.*s\n",
|
||||||
token = next_token();
|
|
||||||
return atoi(token.start);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Error: Not a register or symbol at line %d: %.*s\n",
|
|
||||||
token.line, token.length, token.start);
|
token.line, token.length, token.start);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Token next_id_or_reg() {
|
|
||||||
Token token = next_token();
|
|
||||||
if (token.type == TOKEN_IDENTIFIER) {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.type == TOKEN_BIG_MONEY) {
|
|
||||||
token = next_token();
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Not an ID or register at line %d: %.*s\n", token.line, token.length,
|
|
||||||
token.start);
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token next_id_or_ptr() {
|
|
||||||
Token token = next_token();
|
|
||||||
|
|
||||||
if (token.type != TOKEN_IDENTIFIER && token.type != TOKEN_LITERAL_NAT &&
|
|
||||||
token.type != TOKEN_LITERAL_INT && token.type != TOKEN_LITERAL_REAL) {
|
|
||||||
printf("Not an ID or register at line %d: %.*s\n", token.line, token.length,
|
|
||||||
token.start);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token next_token_is(TokenType type) {
|
Token next_token_is(TokenType type) {
|
||||||
Token token = next_token();
|
Token token = next_token();
|
||||||
if (token.type != type) {
|
if (token.type != type) {
|
||||||
|
|
@ -191,10 +156,9 @@ bool parse_const(VM *vm, ScopeTable *st) {
|
||||||
/**
|
/**
|
||||||
* Global .
|
* Global .
|
||||||
*/
|
*/
|
||||||
bool define_global(VM *vm, ScopeTable *st) {
|
bool define_global(VM *vm, ScopeTable *st, Token token_type) {
|
||||||
Symbol s;
|
Symbol s;
|
||||||
|
|
||||||
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;
|
||||||
|
|
@ -432,11 +396,8 @@ void define_var(ScopeTable *st, Token regType) {
|
||||||
s.name_length = name.length;
|
s.name_length = name.length;
|
||||||
|
|
||||||
Token next = next_token();
|
Token next = next_token();
|
||||||
if (next.type == TOKEN_BIG_MONEY) {
|
if (next.type == TOKEN_SEMICOLON) {
|
||||||
Token reg_num = next_token_is(TOKEN_LITERAL_INT);
|
s.ref = st->current_reg++;
|
||||||
s.ref = atoi(reg_num.start);
|
|
||||||
} else if (next.type == TOKEN_SEMICOLON) {
|
|
||||||
s.ref = st->scopes[st->scope_ref].count;
|
|
||||||
} else {
|
} else {
|
||||||
printf("Unexpected token ERROR at line %d: %.*s\n", regType.line, regType.length,
|
printf("Unexpected token ERROR at line %d: %.*s\n", regType.line, regType.length,
|
||||||
regType.start);
|
regType.start);
|
||||||
|
|
@ -461,6 +422,10 @@ void define_function(VM *vm, ScopeTable *st) {
|
||||||
Symbol s;
|
Symbol s;
|
||||||
s.scope = LOCAL;
|
s.scope = LOCAL;
|
||||||
s.type = FUNCTION;
|
s.type = FUNCTION;
|
||||||
|
|
||||||
|
/* push the last used reg on the stack */
|
||||||
|
st->last_used_registers[st->reg_count++] = st->current_reg;
|
||||||
|
st->current_reg = 0;
|
||||||
|
|
||||||
Token name = next_token_is(TOKEN_IDENTIFIER);
|
Token name = next_token_is(TOKEN_IDENTIFIER);
|
||||||
if (name.length > MAX_SYMBOL_NAME_LENGTH) {
|
if (name.length > MAX_SYMBOL_NAME_LENGTH) {
|
||||||
|
|
@ -499,6 +464,9 @@ void define_function(VM *vm, ScopeTable *st) {
|
||||||
st->scope_ref = temp; // need to add to the parents scope
|
st->scope_ref = temp; // need to add to the parents scope
|
||||||
symbol_table_add(st, s);
|
symbol_table_add(st, s);
|
||||||
st->scope_ref = (i32)st->count;
|
st->scope_ref = (i32)st->count;
|
||||||
|
|
||||||
|
/* pop the current reg off the stack */
|
||||||
|
st->current_reg = st->last_used_registers[--st->reg_count];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -680,7 +648,7 @@ void build_symbol_table(VM *vm, char *source, ScopeTable *st) {
|
||||||
define_var(st, token);
|
define_var(st, token);
|
||||||
next_token_is(TOKEN_SEMICOLON);
|
next_token_is(TOKEN_SEMICOLON);
|
||||||
} else {
|
} else {
|
||||||
define_global(vm, st);
|
define_global(vm, st, token);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -2373,6 +2341,7 @@ bool compile(VM *vm, ScopeTable *st, char *source) {
|
||||||
build_symbol_table(vm, source, st);
|
build_symbol_table(vm, source, st);
|
||||||
vm->cp = 0; /* actually start emitting code */
|
vm->cp = 0; /* actually start emitting code */
|
||||||
st->count = 0;
|
st->count = 0;
|
||||||
|
st->reg_count = 0;
|
||||||
emit_bytecode(vm, source, st);
|
emit_bytecode(vm, source, st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,9 @@ struct scope_tab_s {
|
||||||
u32 capacity;
|
u32 capacity;
|
||||||
i32 scope_ref;
|
i32 scope_ref;
|
||||||
u32 depth;
|
u32 depth;
|
||||||
|
u8 last_used_registers[1024];
|
||||||
|
u32 reg_count;
|
||||||
|
u8 current_reg;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool compile(VM *vm, ScopeTable *st, char *source);
|
bool compile(VM *vm, ScopeTable *st, char *source);
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,20 @@ int x = 1;
|
||||||
int y = 1;
|
int y = 1;
|
||||||
|
|
||||||
function main () {
|
function main () {
|
||||||
load_absolute_32 x -> $0;
|
int local_x;
|
||||||
load_absolute_32 y -> $1;
|
int local_y;
|
||||||
call add ($0 $1) -> $2;
|
int result;
|
||||||
int_to_string $2 -> $3;
|
int result_str;
|
||||||
call pln ($3);
|
|
||||||
|
load_absolute_32 x -> local_x;
|
||||||
|
load_absolute_32 y -> local_y;
|
||||||
|
call add (local_x local_y) -> result;
|
||||||
|
int_to_string result -> result_str;
|
||||||
|
call pln (result_str);
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add (int a, int b) {
|
function add (int a, int b) int {
|
||||||
int result;
|
int result;
|
||||||
add_int a b -> result;
|
add_int a b -> result;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,38 @@ str terminal_namespace = "/dev/term/0";
|
||||||
str new_line = "\n";
|
str new_line = "\n";
|
||||||
|
|
||||||
function main () {
|
function main () {
|
||||||
|
int result;
|
||||||
int str_n;
|
int str_n;
|
||||||
|
|
||||||
load_immediate 35 -> $0;
|
load_immediate 35 -> result;
|
||||||
call fib ($0) -> $0;
|
call fib (result) -> result;
|
||||||
int_to_string $0 -> str_n;
|
int_to_string result -> str_n;
|
||||||
call pln (str_n);
|
call pln (str_n);
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fib (int n) {
|
function fib (int n) {
|
||||||
load_immediate 2 -> $1;
|
int result;
|
||||||
|
load_immediate 2 -> result;
|
||||||
|
|
||||||
jump_lt_int base_case n $1;
|
jump_lt_int base_case n result;
|
||||||
|
|
||||||
load_immediate 2 -> $3;
|
int two;
|
||||||
sub_int n $3 -> $4;
|
int tmp_n;
|
||||||
call fib ($4) -> $5;
|
int result_a;
|
||||||
|
int result_b;
|
||||||
|
|
||||||
load_immediate 1 -> $3;
|
load_immediate 2 -> two;
|
||||||
sub_int n $3 -> $4;
|
sub_int n two -> tmp_n;
|
||||||
call fib ($4) -> $6;
|
call fib (tmp_n) -> result_a;
|
||||||
|
|
||||||
add_int $6 $5 -> $7;
|
int one;
|
||||||
return $7;
|
load_immediate 1 -> one;
|
||||||
|
sub_int n one -> tmp_n;
|
||||||
|
call fib (tmp_n) -> result_b;
|
||||||
|
|
||||||
|
add_int result_b result_a -> result;
|
||||||
|
return result;
|
||||||
|
|
||||||
else base_case;
|
else base_case;
|
||||||
return n;
|
return n;
|
||||||
|
|
|
||||||
|
|
@ -5,41 +5,50 @@ str new_line = "\n";
|
||||||
function main () {
|
function main () {
|
||||||
real a;
|
real a;
|
||||||
int i;
|
int i;
|
||||||
int mode $11;
|
int mode;
|
||||||
str term $10;
|
str term;
|
||||||
|
int zero;
|
||||||
|
int decrement;
|
||||||
|
real five;
|
||||||
|
|
||||||
// do (i = 5000; i >= 0, i = i - 1)
|
// do (i = 5000; i >= 0, i = i - 1)
|
||||||
load_immediate 5.0 -> a;
|
load_immediate 5.0 -> a;
|
||||||
load_immediate 5000 -> i;
|
load_immediate 5000 -> i;
|
||||||
load_immediate 0 -> $2;
|
load_immediate 0 -> zero;
|
||||||
load_immediate -1 -> $3;
|
load_immediate -1 -> decrement;
|
||||||
load_immediate 5.0 -> $5;
|
load_immediate 5.0 -> five;
|
||||||
loop loop_body {
|
loop loop_body {
|
||||||
add_real a $5 -> a;
|
add_real a five -> a;
|
||||||
add_int i $3 -> i;
|
add_int i decrement -> i;
|
||||||
jump_ge_int loop_body i $2;
|
jump_ge_int loop_body i zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
load_address terminal_namespace -> term;
|
load_address 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 $1;
|
nat b;
|
||||||
|
str prompt_str;
|
||||||
|
nat prompt_len;
|
||||||
real_to_nat a -> b;
|
real_to_nat a -> b;
|
||||||
load_address prompt -> $7;
|
load_address prompt -> prompt_str;
|
||||||
string_length $7 -> $8;
|
string_length prompt_str -> prompt_len;
|
||||||
syscall WRITE term $7 $8; // print prompt
|
syscall WRITE term prompt_str prompt_len; // print prompt
|
||||||
|
|
||||||
str user_string $9;
|
str user_string;
|
||||||
load_immediate 32 -> $8;
|
nat user_max_string_size;
|
||||||
malloc $8 -> user_string;
|
load_immediate 32 -> user_max_string_size;
|
||||||
syscall READ term user_string $8; // read in max 32 byte string
|
malloc user_max_string_size -> user_string;
|
||||||
|
syscall READ term user_string user_max_string_size; // read in max 32 byte string
|
||||||
|
|
||||||
|
str b_string;
|
||||||
|
str a_string;
|
||||||
|
|
||||||
call pln (user_string);
|
call pln (user_string);
|
||||||
nat_to_string b -> $4;
|
nat_to_string b -> b_string;
|
||||||
call pln ($4);
|
call pln (b_string);
|
||||||
real_to_string a -> $3;
|
real_to_string a -> a_string;
|
||||||
call pln ($3);
|
call pln (a_string);
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,17 @@ function main () {
|
||||||
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);
|
||||||
|
|
||||||
load_address prompt -> $7;
|
str prompt_string;
|
||||||
string_length $7 -> $8;
|
nat prompt_len;
|
||||||
syscall WRITE term $7 $8; // print prompt
|
load_address prompt -> prompt_string;
|
||||||
|
string_length prompt_string -> prompt_len;
|
||||||
|
syscall WRITE term prompt_string prompt_len; // print prompt
|
||||||
|
|
||||||
str user_string;
|
str user_string;
|
||||||
load_immediate 32 -> $8;
|
nat user_max_string_size;
|
||||||
malloc $8 -> user_string;
|
load_immediate 32 -> user_max_string_size;
|
||||||
syscall READ term user_string $8; // read in max 32 byte string
|
malloc user_max_string_size -> user_string;
|
||||||
|
syscall READ term user_string user_max_string_size; // read in max 32 byte string
|
||||||
|
|
||||||
call pln (user_string);
|
call pln (user_string);
|
||||||
exit 0;
|
exit 0;
|
||||||
|
|
|
||||||
|
|
@ -36,32 +36,34 @@ byte SELECTED_COLOR = 255;
|
||||||
|
|
||||||
function main () {
|
function main () {
|
||||||
// Open screen
|
// Open screen
|
||||||
ptr screen $0;
|
ptr screen;
|
||||||
str screen_name $18;
|
str screen_name;
|
||||||
int mode $11;
|
int mode;
|
||||||
nat screen_buffer $21;
|
nat screen_buffer;
|
||||||
|
|
||||||
// use load immediate because it 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 $20;
|
nat width;
|
||||||
nat size $22;
|
nat size;
|
||||||
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
|
|
||||||
add_nat screen $1 -> screen_buffer;
|
nat offset;
|
||||||
|
load_immediate 16 -> offset; // offset for screen buffer
|
||||||
|
add_nat screen offset -> screen_buffer;
|
||||||
|
|
||||||
// open mouse
|
// open mouse
|
||||||
ptr mouse $15;
|
ptr mouse;
|
||||||
str mouse_name $16;
|
str mouse_name;
|
||||||
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 $1;
|
byte color;
|
||||||
nat x_pos $12;
|
nat x_pos;
|
||||||
nat y_pos $13;
|
nat y_pos;
|
||||||
|
|
||||||
load_absolute_8 BLACK -> color;
|
load_absolute_8 BLACK -> color;
|
||||||
load_immediate 1 -> x_pos;
|
load_immediate 1 -> x_pos;
|
||||||
|
|
@ -116,23 +118,24 @@ function main () {
|
||||||
// screen.draw
|
// screen.draw
|
||||||
syscall WRITE screen screen_buffer size;
|
syscall WRITE screen screen_buffer size;
|
||||||
|
|
||||||
nat m_zero $11;
|
nat zero;
|
||||||
|
load_immediate 0 -> zero;
|
||||||
|
|
||||||
loop draw_loop {
|
loop draw_loop {
|
||||||
// load mouse click data
|
// load mouse click data
|
||||||
syscall REFRESH mouse;
|
syscall REFRESH mouse;
|
||||||
|
|
||||||
byte left_down $9;
|
byte left_down;
|
||||||
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 m_zero; // if (!btn1.left) continue;
|
jump_eq_nat draw_loop left_down zero; // if (!btn1.left) continue;
|
||||||
|
|
||||||
nat mouse_x $7;
|
nat mouse_x;
|
||||||
nat mouse_y $8;
|
nat mouse_y;
|
||||||
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 $14;
|
nat box_size;
|
||||||
load_immediate 20 -> box_size;
|
load_immediate 20 -> box_size;
|
||||||
|
|
||||||
// first row
|
// first row
|
||||||
|
|
@ -198,10 +201,10 @@ function main () {
|
||||||
|
|
||||||
syscall WRITE screen screen_buffer size;
|
syscall WRITE screen screen_buffer size;
|
||||||
|
|
||||||
byte selected_color $25;
|
byte selected_color;
|
||||||
load_absolute_8 SELECTED_COLOR -> selected_color;
|
load_absolute_8 SELECTED_COLOR -> selected_color;
|
||||||
|
|
||||||
nat brush_size $19;
|
nat brush_size;
|
||||||
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);
|
||||||
|
|
@ -213,16 +216,15 @@ function main () {
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_color_if_clicked (int click_x $0, int click_y $1,
|
function set_color_if_clicked (int click_x, int click_y, int box_x, int box_y, byte check_color, int size) {
|
||||||
int box_x $2, int box_y $3, byte check_color $4, int bsize $5) {
|
|
||||||
|
|
||||||
// Compute right
|
// Compute right
|
||||||
int right_edge $6;
|
int right_edge;
|
||||||
add_int box_x bsize -> right_edge;
|
add_int box_x size -> right_edge;
|
||||||
|
|
||||||
// Compute bottom = box_y + bsize
|
// Compute bottom = box_y + size
|
||||||
int bottom_edge $7;
|
int bottom_edge;
|
||||||
add_int box_y bsize -> bottom_edge;
|
add_int box_y 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;
|
||||||
|
|
@ -236,8 +238,7 @@ function set_color_if_clicked (int click_x $0, int click_y $1,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function draw_outlined_swatch(nat base,
|
function draw_outlined_swatch(nat base, byte color, int x, int y, int width) {
|
||||||
byte swatch_color, int x, int y, int width) {
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
nat background_color;
|
nat background_color;
|
||||||
|
|
@ -246,7 +247,7 @@ function draw_outlined_swatch(nat base,
|
||||||
byte selected_color;
|
byte selected_color;
|
||||||
load_absolute_8 SELECTED_COLOR -> selected_color;
|
load_absolute_8 SELECTED_COLOR -> selected_color;
|
||||||
|
|
||||||
jump_eq_int set_selected swatch_color selected_color;
|
jump_eq_int set_selected color selected_color;
|
||||||
jump end_set_selected;
|
jump end_set_selected;
|
||||||
do set_selected
|
do set_selected
|
||||||
load_absolute_8 DARK_GRAY -> background_color;
|
load_absolute_8 DARK_GRAY -> background_color;
|
||||||
|
|
@ -265,10 +266,10 @@ function draw_outlined_swatch(nat base,
|
||||||
|
|
||||||
int x_off;
|
int x_off;
|
||||||
int y_off;
|
int y_off;
|
||||||
add_int x offset -> x_off; // x + 2
|
add_int x offset -> x_off; // x + 2
|
||||||
add_int y offset -> y_off; // y + 2
|
add_int y offset -> y_off; // y + 2
|
||||||
|
|
||||||
call draw_box (base width swatch_color x_off y_off fill_size fill_size);
|
call draw_box (base width color x_off y_off fill_size fill_size);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -278,12 +279,13 @@ function draw_box (nat db_base, nat screen_width,
|
||||||
nat db_width, nat height) {
|
nat db_width, nat height) {
|
||||||
|
|
||||||
// Compute start address: base + y*640 + x
|
// Compute start address: base + y*640 + x
|
||||||
nat offset;
|
|
||||||
mul_int y_start screen_width -> offset;
|
|
||||||
add_int offset x_start -> offset;
|
|
||||||
add_nat offset db_base -> offset;
|
|
||||||
nat fat_ptr_size;
|
nat fat_ptr_size;
|
||||||
load_immediate 4 -> fat_ptr_size;
|
load_immediate 4 -> fat_ptr_size;
|
||||||
|
|
||||||
|
nat offset;
|
||||||
|
mul_nat y_start screen_width -> offset;
|
||||||
|
add_nat offset x_start -> offset;
|
||||||
|
add_nat offset db_base -> offset;
|
||||||
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;
|
int i;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue