From d85fc54cbdd04c1f0e097959789328f54be0d2ca Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 17:37:59 +0700 Subject: [PATCH 01/12] Add support to local variable definitions for parser --- bang/examples/rule110.bang | 6 +----- bang/src/bang_compiler.c | 11 +++++++++++ bang/src/bang_parser.c | 7 ++++++- bang/src/bang_parser.h | 16 +++++++++------- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/bang/examples/rule110.bang b/bang/examples/rule110.bang index 2ed85e4..a0471cb 100644 --- a/bang/examples/rule110.bang +++ b/bang/examples/rule110.bang @@ -11,11 +11,6 @@ var state_next: i64; var display_base: ptr; -var i: i64; -var j: i64; -var cell_ptr: ptr; -var cell: u8; - proc init() { # Init lookup table table_base = heap_base; @@ -40,6 +35,7 @@ proc init() { } proc print_state_current() { + var i: u64; i = 0; while i < state_size { cell_ptr = states_base + cast(ptr, state_current * state_size + i); diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index fda42ac..3e8bcb0 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -454,6 +454,13 @@ void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile) basm->program[fallthrough_addr].operand = word_u64(body_end_addr); } +#define UNIMPLEMENTED \ + do { \ + fprintf(stderr, "%s:%d: %s is not implemented yet\n", \ + __FILE__, __LINE__, __func__); \ + abort(); \ + } while(0) + void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt) { switch (stmt.kind) { @@ -477,6 +484,10 @@ void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt) compile_bang_while_into_basm(bang, basm, stmt.as.hwile); break; + case BANG_STMT_KIND_VAR_DEF: + UNIMPLEMENTED; + break; + case COUNT_BANG_STMT_KINDS: default: assert(false && "compile_stmt_into_basm: unreachable"); diff --git a/bang/src/bang_parser.c b/bang/src/bang_parser.c index 7ea9aae..cf3020c 100644 --- a/bang/src/bang_parser.c +++ b/bang/src/bang_parser.c @@ -420,7 +420,7 @@ Bang_Stmt parse_bang_stmt(Arena *arena, Bang_Lexer *lexer) exit(1); } - static_assert(COUNT_BANG_STMT_KINDS == 4, "The amount of statements have changed. Please update the parse_bang_stmt function to take that into account"); + static_assert(COUNT_BANG_STMT_KINDS == 5, "The amount of statements have changed. Please update the parse_bang_stmt function to take that into account"); switch (token.kind) { case BANG_TOKEN_KIND_NAME: { @@ -434,6 +434,11 @@ Bang_Stmt parse_bang_stmt(Arena *arena, Bang_Lexer *lexer) stmt.kind = BANG_STMT_KIND_WHILE; stmt.as.hwile = parse_bang_while(arena, lexer); return stmt; + } else if (sv_eq(token.text, SV("var"))) { + Bang_Stmt stmt = {0}; + stmt.kind = BANG_STMT_KIND_VAR_DEF; + stmt.as.var_def = parse_bang_var_def(lexer); + return stmt; } else { Bang_Token next_token = {0}; if (bang_lexer_peek(lexer, &next_token, 1) && next_token.kind == BANG_TOKEN_KIND_EQ) { diff --git a/bang/src/bang_parser.h b/bang/src/bang_parser.h index 246426d..cd1df74 100644 --- a/bang/src/bang_parser.h +++ b/bang/src/bang_parser.h @@ -110,6 +110,7 @@ typedef enum { BANG_STMT_KIND_EXPR = 0, BANG_STMT_KIND_IF, BANG_STMT_KIND_VAR_ASSIGN, + BANG_STMT_KIND_VAR_DEF, BANG_STMT_KIND_WHILE, COUNT_BANG_STMT_KINDS, } Bang_Stmt_Kind; @@ -133,14 +134,21 @@ struct Bang_Var_Assign { Bang_Expr value; }; +struct Bang_Var_Def { + Bang_Loc loc; + String_View name; + String_View type_name; +}; + union Bang_Stmt_As { Bang_Expr expr; Bang_If eef; Bang_Var_Assign var_assign; Bang_While hwile; + Bang_Var_Def var_def; }; static_assert( - COUNT_BANG_STMT_KINDS == 4, + COUNT_BANG_STMT_KINDS == 5, "The amount of statement kinds has changed. " "Please update the union of those statements accordingly. " "Thanks!"); @@ -161,12 +169,6 @@ struct Bang_Proc_Def { Bang_Block *body; }; -struct Bang_Var_Def { - Bang_Loc loc; - String_View name; - String_View type_name; -}; - typedef enum { BANG_TOP_KIND_PROC = 0, BANG_TOP_KIND_VAR, From 8169d0e5200c3b0540a35b65e0287a720b31d601 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 18:37:24 +0700 Subject: [PATCH 02/12] Introduce the notion of the variable storage --- bang/src/bang.c | 1 + bang/src/bang_compiler.c | 163 +++++++++++++++++++++++++-------------- bang/src/bang_compiler.h | 23 +++++- 3 files changed, 125 insertions(+), 62 deletions(-) diff --git a/bang/src/bang.c b/bang/src/bang.c index 73a0e6c..b904d3a 100644 --- a/bang/src/bang.c +++ b/bang/src/bang.c @@ -105,6 +105,7 @@ int main(int argc, char **argv) Bang bang = {0}; bang.write_id = basm_push_external_native(&basm, SV("write")); + bang_prepare_var_stack(&bang, &basm); compile_bang_module_into_basm(&bang, &basm, module); bang_generate_entry_point(&bang, &basm, SV("main")); bang_generate_heap_base(&bang, &basm, SV("heap_base")); diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 3e8bcb0..4727e11 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -2,6 +2,13 @@ // TODO(#426): bang does not support type casting +#define UNIMPLEMENTED \ + do { \ + fprintf(stderr, "%s:%d: %s is not implemented yet\n", \ + __FILE__, __LINE__, __func__); \ + abort(); \ + } while(0) + typedef struct { bool exists; Inst_Type inst; @@ -138,8 +145,18 @@ Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_r exit(1); } - basm_push_inst(basm, INST_PUSH, word_u64(var->addr)); - compile_typed_read(basm, var->type); + switch (var->storage) { + case BANG_VAR_STATIC_STORAGE: { + basm_push_inst(basm, INST_PUSH, word_u64(var->addr_)); + compile_typed_read(basm, var->type); + } + break; + + case BANG_VAR_STACK_STORAGE: { + UNIMPLEMENTED; + } + break; + } return var->type; } @@ -237,8 +254,18 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr } Compiled_Var *var = bang_get_global_var_by_name(bang, arg.as.var_read.name); - basm_push_inst(basm, INST_PUSH, word_u64(var->addr)); - result.type = BANG_TYPE_PTR; + switch (var->storage) { + case BANG_VAR_STATIC_STORAGE: { + basm_push_inst(basm, INST_PUSH, word_u64(var->addr_)); + result.type = BANG_TYPE_PTR; + } + break; + + case BANG_VAR_STACK_STORAGE: { + UNIMPLEMENTED; + } + break; + } } else if (sv_eq(funcall.name, SV("write_ptr"))) { bang_funcall_expect_arity(funcall, 2); Bang_Funcall_Arg *args = funcall.args; @@ -420,18 +447,27 @@ void compile_bang_var_assign_into_basm(Bang *bang, Basm *basm, Bang_Var_Assign v exit(1); } - basm_push_inst(basm, INST_PUSH, word_u64(var->addr)); - Compiled_Expr expr = compile_bang_expr_into_basm(bang, basm, var_assign.value); + switch (var->storage) { + case BANG_VAR_STATIC_STORAGE: { + basm_push_inst(basm, INST_PUSH, word_u64(var->addr_)); + Compiled_Expr expr = compile_bang_expr_into_basm(bang, basm, var_assign.value); + if (expr.type != var->type) { + fprintf(stderr, Bang_Loc_Fmt": ERROR: cannot assign expression of type `%s` to a variable of type `%s`\n", + Bang_Loc_Arg(var_assign.loc), + bang_type_def(expr.type).name, + bang_type_def(var->type).name); + exit(1); + } - if (expr.type != var->type) { - fprintf(stderr, Bang_Loc_Fmt": ERROR: cannot assign expression of type `%s` to a variable of type `%s`\n", - Bang_Loc_Arg(var_assign.loc), - bang_type_def(expr.type).name, - bang_type_def(var->type).name); - exit(1); + compile_typed_write(basm, expr.type); + } + break; + case BANG_VAR_STACK_STORAGE: { + UNIMPLEMENTED; + } + break; } - compile_typed_write(basm, expr.type); } void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile) @@ -454,12 +490,6 @@ void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile) basm->program[fallthrough_addr].operand = word_u64(body_end_addr); } -#define UNIMPLEMENTED \ - do { \ - fprintf(stderr, "%s:%d: %s is not implemented yet\n", \ - __FILE__, __LINE__, __func__); \ - abort(); \ - } while(0) void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt) { @@ -485,7 +515,7 @@ void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt) break; case BANG_STMT_KIND_VAR_DEF: - UNIMPLEMENTED; + compile_stack_var_def_into_basm(bang, basm, stmt.as.var_def); break; case COUNT_BANG_STMT_KINDS: @@ -557,42 +587,6 @@ void bang_funcall_expect_arity(Bang_Funcall funcall, size_t expected_arity) } } -void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def) -{ - Bang_Type type = 0; - if (!bang_type_by_name(var_def.type_name, &type)) { - fprintf(stderr, Bang_Loc_Fmt": ERROR: type `"SV_Fmt"` does not exist\n", - Bang_Loc_Arg(var_def.loc), - SV_Arg(var_def.type_name)); - exit(1); - } - - if (type == BANG_TYPE_VOID) { - fprintf(stderr, Bang_Loc_Fmt": ERROR: defining variables with type %s is not allowed\n", - Bang_Loc_Arg(var_def.loc), - bang_type_def(type).name); - exit(1); - } - - Compiled_Var *existing_var = bang_get_global_var_by_name(bang, var_def.name); - if (existing_var) { - fprintf(stderr, Bang_Loc_Fmt": ERROR: variable `"SV_Fmt"` is already defined\n", - Bang_Loc_Arg(var_def.loc), - SV_Arg(var_def.name)); - fprintf(stderr, Bang_Loc_Fmt": NOTE: the first definition is located here\n", - Bang_Loc_Arg(existing_var->def.loc)); - exit(1); - } - - Compiled_Var new_var = {0}; - new_var.def = var_def; - new_var.addr = basm_push_byte_array_to_memory(basm, bang_type_def(type).size, 0).as_u64; - new_var.type = type; - - assert(bang->global_vars_count < BANG_GLOBAL_VARS_CAPACITY); - bang->global_vars[bang->global_vars_count++] = new_var; -} - void compile_bang_module_into_basm(Bang *bang, Basm *basm, Bang_Module module) { for (Bang_Top *top = module.tops_begin; top != NULL; top = top->next) { @@ -602,7 +596,7 @@ void compile_bang_module_into_basm(Bang *bang, Basm *basm, Bang_Module module) } break; case BANG_TOP_KIND_VAR: { - compile_var_def_into_basm(bang, basm, top->as.var); + compile_static_var_def_into_basm(bang, basm, top->as.var); } break; case COUNT_BANG_TOP_KINDS: @@ -631,6 +625,7 @@ void bang_generate_entry_point(Bang *bang, Basm *basm, String_View entry_proc_na void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_name) { Compiled_Var *heap_base_var = bang_get_global_var_by_name(bang, heap_base_var_name); + assert(heap_base_var->storage == BANG_VAR_STATIC_STORAGE); if (heap_base_var != NULL) { if (heap_base_var->type != BANG_TYPE_PTR) { @@ -643,8 +638,60 @@ void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_n } const Memory_Addr heap_base_addr = basm->memory_size; - memcpy(&basm->memory[heap_base_var->addr], + memcpy(&basm->memory[heap_base_var->addr_], &heap_base_addr, sizeof(heap_base_addr)); } } + +void bang_prepare_var_stack(Bang *bang, Basm *basm) +{ + basm_push_byte_array_to_memory(basm, BANG_STACK_CAPACITY, 0); + bang->stack_base_var_addr = + basm_push_byte_array_to_memory(basm, bang_type_def(BANG_TYPE_I64).size, 0).as_u64; +} + +void compile_static_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def) +{ + Bang_Type type = 0; + if (!bang_type_by_name(var_def.type_name, &type)) { + fprintf(stderr, Bang_Loc_Fmt": ERROR: type `"SV_Fmt"` does not exist\n", + Bang_Loc_Arg(var_def.loc), + SV_Arg(var_def.type_name)); + exit(1); + } + + if (type == BANG_TYPE_VOID) { + fprintf(stderr, Bang_Loc_Fmt": ERROR: defining variables with type %s is not allowed\n", + Bang_Loc_Arg(var_def.loc), + bang_type_def(type).name); + exit(1); + } + + Compiled_Var *existing_var = bang_get_global_var_by_name(bang, var_def.name); + if (existing_var) { + fprintf(stderr, Bang_Loc_Fmt": ERROR: variable `"SV_Fmt"` is already defined\n", + Bang_Loc_Arg(var_def.loc), + SV_Arg(var_def.name)); + fprintf(stderr, Bang_Loc_Fmt": NOTE: the first definition is located here\n", + Bang_Loc_Arg(existing_var->def.loc)); + exit(1); + } + + Compiled_Var new_var = {0}; + new_var.def = var_def; + new_var.storage = BANG_VAR_STATIC_STORAGE; + new_var.addr_ = basm_push_byte_array_to_memory(basm, bang_type_def(type).size, 0).as_u64; + new_var.type = type; + + assert(bang->global_vars_count < BANG_GLOBAL_VARS_CAPACITY); + bang->global_vars[bang->global_vars_count++] = new_var; +} + +void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def) +{ + (void) bang; + (void) basm; + (void) var_def; + UNIMPLEMENTED; +} diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 2091e29..87bbf3a 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -9,6 +9,11 @@ #define BANG_GLOBAL_VARS_CAPACITY 1024 #define BANG_PROCS_CAPACITY 1024 +typedef enum { + BANG_VAR_STATIC_STORAGE = 0, + BANG_VAR_STACK_STORAGE, +} Bang_Var_Storage; + // TODO(#433): there is no generic ptr type typedef enum { BANG_TYPE_VOID = 0, @@ -33,7 +38,12 @@ Bang_Type_Def bang_type_def(Bang_Type type); typedef struct { Bang_Var_Def def; Bang_Type type; - Memory_Addr addr; + Bang_Var_Storage storage; + // when storage == BANG_VAR_STATIC_STORAGE: + // addr is absolute address of the variable in memory + // when storage == BANG_VAR_STACK_STORAGE: + // addr is an offset from the top of the stack + Memory_Addr addr_; } Compiled_Var; typedef struct { @@ -41,9 +51,13 @@ typedef struct { Inst_Addr addr; } Compiled_Proc; +#define BANG_STACK_CAPACITY 4096 + typedef struct { Native_ID write_id; + Memory_Addr stack_base_var_addr; + Compiled_Var global_vars[BANG_GLOBAL_VARS_CAPACITY]; size_t global_vars_count; @@ -53,8 +67,6 @@ typedef struct { Bang_Loc entry_loc; } Bang; -void compile_begin_begin(Bang *bang); - Compiled_Var *bang_get_global_var_by_name(Bang *bang, String_View name); typedef struct { @@ -75,7 +87,8 @@ void compile_bang_if_into_basm(Bang *bang, Basm *basm, Bang_If eef); void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile); void compile_bang_var_assign_into_basm(Bang *bang, Basm *basm, Bang_Var_Assign var_assign); void compile_bang_module_into_basm(Bang *bang, Basm *basm, Bang_Module module); -void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def); +void compile_static_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def); +void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def); Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_read); Bang_Type compile_binary_op_into_basm(Bang *bang, Basm *basm, Bang_Binary_Op binary_op); @@ -84,4 +97,6 @@ void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_n void bang_funcall_expect_arity(Bang_Funcall funcall, size_t expected_arity); +void bang_prepare_var_stack(Bang *bang, Basm *basm); + #endif // BANG_COMPILER_H_ From 8e761053529df4133816634960d1135b4e991937 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 18:40:01 +0700 Subject: [PATCH 03/12] Rename addr_ -> addr --- bang/src/bang_compiler.c | 10 +++++----- bang/src/bang_compiler.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 4727e11..068d909 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -147,7 +147,7 @@ Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_r switch (var->storage) { case BANG_VAR_STATIC_STORAGE: { - basm_push_inst(basm, INST_PUSH, word_u64(var->addr_)); + basm_push_inst(basm, INST_PUSH, word_u64(var->addr)); compile_typed_read(basm, var->type); } break; @@ -256,7 +256,7 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr Compiled_Var *var = bang_get_global_var_by_name(bang, arg.as.var_read.name); switch (var->storage) { case BANG_VAR_STATIC_STORAGE: { - basm_push_inst(basm, INST_PUSH, word_u64(var->addr_)); + basm_push_inst(basm, INST_PUSH, word_u64(var->addr)); result.type = BANG_TYPE_PTR; } break; @@ -449,7 +449,7 @@ void compile_bang_var_assign_into_basm(Bang *bang, Basm *basm, Bang_Var_Assign v switch (var->storage) { case BANG_VAR_STATIC_STORAGE: { - basm_push_inst(basm, INST_PUSH, word_u64(var->addr_)); + basm_push_inst(basm, INST_PUSH, word_u64(var->addr)); Compiled_Expr expr = compile_bang_expr_into_basm(bang, basm, var_assign.value); if (expr.type != var->type) { fprintf(stderr, Bang_Loc_Fmt": ERROR: cannot assign expression of type `%s` to a variable of type `%s`\n", @@ -638,7 +638,7 @@ void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_n } const Memory_Addr heap_base_addr = basm->memory_size; - memcpy(&basm->memory[heap_base_var->addr_], + memcpy(&basm->memory[heap_base_var->addr], &heap_base_addr, sizeof(heap_base_addr)); } @@ -681,7 +681,7 @@ void compile_static_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_d Compiled_Var new_var = {0}; new_var.def = var_def; new_var.storage = BANG_VAR_STATIC_STORAGE; - new_var.addr_ = basm_push_byte_array_to_memory(basm, bang_type_def(type).size, 0).as_u64; + new_var.addr = basm_push_byte_array_to_memory(basm, bang_type_def(type).size, 0).as_u64; new_var.type = type; assert(bang->global_vars_count < BANG_GLOBAL_VARS_CAPACITY); diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 87bbf3a..651b239 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -43,7 +43,7 @@ typedef struct { // addr is absolute address of the variable in memory // when storage == BANG_VAR_STACK_STORAGE: // addr is an offset from the top of the stack - Memory_Addr addr_; + Memory_Addr addr; } Compiled_Var; typedef struct { From f23b803312fefd2ca8743747242f6548dc59c4cd Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:52:50 +0700 Subject: [PATCH 04/12] Introduce the notion of the scopes to Bang --- bang/src/bang.c | 19 ++++--- bang/src/bang_compiler.c | 114 +++++++++++++++++++++++++++++++-------- bang/src/bang_compiler.h | 34 +++++++++--- 3 files changed, 132 insertions(+), 35 deletions(-) diff --git a/bang/src/bang.c b/bang/src/bang.c index b904d3a..d9f46de 100644 --- a/bang/src/bang.c +++ b/bang/src/bang.c @@ -103,16 +103,23 @@ int main(int argc, char **argv) Bang_Lexer lexer = bang_lexer_from_sv(content, input_file_path); Bang_Module module = parse_bang_module(&basm.arena, &lexer); - Bang bang = {0}; + static Bang bang = {0}; bang.write_id = basm_push_external_native(&basm, SV("write")); bang_prepare_var_stack(&bang, &basm); - compile_bang_module_into_basm(&bang, &basm, module); - bang_generate_entry_point(&bang, &basm, SV("main")); - bang_generate_heap_base(&bang, &basm, SV("heap_base")); - assert(basm.has_entry); - basm_save_to_file_as_target(&basm, output_file_path, output_target); + + bang_push_new_scope(&bang); + { + compile_bang_module_into_basm(&bang, &basm, module); + + bang_generate_entry_point(&bang, &basm, SV("main")); + bang_generate_heap_base(&bang, &basm, SV("heap_base")); + assert(basm.has_entry); + basm_save_to_file_as_target(&basm, output_file_path, output_target); + } + bang_pop_scope(&bang); arena_free(&basm.arena); + arena_free(&bang.arena); return 0; } diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 068d909..8127941 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -137,7 +137,7 @@ void compile_typed_write(Basm *basm, Bang_Type type) Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_read) { - Compiled_Var *var = bang_get_global_var_by_name(bang, var_read.name); + Compiled_Var *var = bang_get_compiled_var_by_name(bang, var_read.name); if (var == NULL) { fprintf(stderr, Bang_Loc_Fmt": ERROR: could not read non-existing variable `"SV_Fmt"`\n", Bang_Loc_Arg(var_read.loc), @@ -153,7 +153,7 @@ Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_r break; case BANG_VAR_STACK_STORAGE: { - UNIMPLEMENTED; + assert(false && "TODO: reading stack variables is not implemented"); } break; } @@ -253,7 +253,7 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr exit(1); } - Compiled_Var *var = bang_get_global_var_by_name(bang, arg.as.var_read.name); + Compiled_Var *var = bang_get_compiled_var_by_name(bang, arg.as.var_read.name); switch (var->storage) { case BANG_VAR_STATIC_STORAGE: { basm_push_inst(basm, INST_PUSH, word_u64(var->addr)); @@ -262,7 +262,7 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr break; case BANG_VAR_STACK_STORAGE: { - UNIMPLEMENTED; + assert(false && "TODO: Taking a pointer to stack variable is not implemented"); } break; } @@ -396,7 +396,7 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr case COUNT_BANG_EXPR_KINDS: default: - assert(false && "compile_bang_expr_into_basm: unreachable"); + assert(false && "TODO: compile_bang_expr_into_basm: unreachable"); exit(1); } @@ -427,11 +427,34 @@ void compile_bang_if_into_basm(Bang *bang, Basm *basm, Bang_If eef) basm->program[else_jmp_addr].operand = word_u64(end_addr); } -Compiled_Var *bang_get_global_var_by_name(Bang *bang, String_View name) +void bang_scope_push_var(Bang_Scope *scope, Compiled_Var var) { - for (size_t i = 0; i < bang->global_vars_count; ++i) { - if (sv_eq(bang->global_vars[i].def.name, name)) { - return &bang->global_vars[i]; + assert(scope); + assert(scope->vars_count < BANG_SCOPE_VARS_CAPACITY); + scope->vars[scope->vars_count++] = var; +} + +Compiled_Var *bang_scope_get_compiled_var_by_name(Bang_Scope *scope, String_View name) +{ + assert(scope); + + for (size_t i = 0; i < scope->vars_count; ++i) { + if (sv_eq(scope->vars[i].def.name, name)) { + return &scope->vars[i]; + } + } + + return NULL; +} + +Compiled_Var *bang_get_compiled_var_by_name(Bang *bang, String_View name) +{ + for (Bang_Scope *scope = bang->scope; + scope != NULL; + scope = scope->parent) { + Compiled_Var *var = bang_scope_get_compiled_var_by_name(scope, name); + if (var != NULL) { + return var; } } return NULL; @@ -439,7 +462,7 @@ Compiled_Var *bang_get_global_var_by_name(Bang *bang, String_View name) void compile_bang_var_assign_into_basm(Bang *bang, Basm *basm, Bang_Var_Assign var_assign) { - Compiled_Var *var = bang_get_global_var_by_name(bang, var_assign.name); + Compiled_Var *var = bang_get_compiled_var_by_name(bang, var_assign.name); if (var == NULL) { fprintf(stderr, Bang_Loc_Fmt": ERROR: cannot assign non-existing variable `"SV_Fmt"`\n", Bang_Loc_Arg(var_assign.loc), @@ -462,8 +485,9 @@ void compile_bang_var_assign_into_basm(Bang *bang, Basm *basm, Bang_Var_Assign v compile_typed_write(basm, expr.type); } break; + case BANG_VAR_STACK_STORAGE: { - UNIMPLEMENTED; + assert(false && "TODO: assigning to stack variable is not implemented"); } break; } @@ -527,10 +551,12 @@ void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt) void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block) { + bang_push_new_scope(bang); while (block) { compile_stmt_into_basm(bang, basm, block->stmt); block = block->next; } + bang_pop_scope(bang); } Compiled_Proc *bang_get_compiled_proc_by_name(Bang *bang, String_View name) @@ -562,6 +588,7 @@ void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def) bang->procs[bang->procs_count++] = proc; compile_block_into_basm(bang, basm, proc_def.body); + basm_push_inst(basm, INST_RET, word_u64(0)); } @@ -624,10 +651,11 @@ void bang_generate_entry_point(Bang *bang, Basm *basm, String_View entry_proc_na void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_name) { - Compiled_Var *heap_base_var = bang_get_global_var_by_name(bang, heap_base_var_name); - assert(heap_base_var->storage == BANG_VAR_STATIC_STORAGE); + assert(bang->scope != NULL); + Compiled_Var *heap_base_var = bang_get_compiled_var_by_name(bang, heap_base_var_name); if (heap_base_var != NULL) { + assert(heap_base_var->storage == BANG_VAR_STATIC_STORAGE); if (heap_base_var->type != BANG_TYPE_PTR) { fprintf(stderr, Bang_Loc_Fmt": ERROR: the special `"SV_Fmt"` variable is expected to be of type `%s` but it was defined as type `%s`\n", Bang_Loc_Arg(heap_base_var->def.loc), @@ -647,8 +675,14 @@ void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_n void bang_prepare_var_stack(Bang *bang, Basm *basm) { basm_push_byte_array_to_memory(basm, BANG_STACK_CAPACITY, 0); - bang->stack_base_var_addr = - basm_push_byte_array_to_memory(basm, bang_type_def(BANG_TYPE_I64).size, 0).as_u64; + const Memory_Addr stack_start_addr = BANG_STACK_CAPACITY; + + bang->stack_top_var_addr = + basm_push_buffer_to_memory( + basm, (uint8_t*) &stack_start_addr, sizeof(stack_start_addr)).as_u64; + bang->stack_frame_var_addr = + basm_push_buffer_to_memory( + basm, (uint8_t*) &stack_start_addr, sizeof(stack_start_addr)).as_u64; } void compile_static_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def) @@ -668,7 +702,7 @@ void compile_static_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_d exit(1); } - Compiled_Var *existing_var = bang_get_global_var_by_name(bang, var_def.name); + Compiled_Var *existing_var = bang_scope_get_compiled_var_by_name(bang->scope, var_def.name); if (existing_var) { fprintf(stderr, Bang_Loc_Fmt": ERROR: variable `"SV_Fmt"` is already defined\n", Bang_Loc_Arg(var_def.loc), @@ -684,14 +718,50 @@ void compile_static_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_d new_var.addr = basm_push_byte_array_to_memory(basm, bang_type_def(type).size, 0).as_u64; new_var.type = type; - assert(bang->global_vars_count < BANG_GLOBAL_VARS_CAPACITY); - bang->global_vars[bang->global_vars_count++] = new_var; + bang_scope_push_var(bang->scope, new_var); } void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def) { - (void) bang; - (void) basm; - (void) var_def; - UNIMPLEMENTED; + Bang_Type type = 0; + if (!bang_type_by_name(var_def.type_name, &type)) { + fprintf(stderr, Bang_Loc_Fmt": ERROR: type `"SV_Fmt"` does not exist\n", + Bang_Loc_Arg(var_def.loc), + SV_Arg(var_def.type_name)); + exit(1); + } + + if (type == BANG_TYPE_VOID) { + fprintf(stderr, Bang_Loc_Fmt": ERROR: defining variables with type %s is not allowed\n", + Bang_Loc_Arg(var_def.loc), + bang_type_def(type).name); + exit(1); + } + + // TODO: bang compile does not warn about shadowing of the variable + + Compiled_Var *existing_var = bang_scope_get_compiled_var_by_name(bang->scope, var_def.name); + if (existing_var) { + fprintf(stderr, Bang_Loc_Fmt": ERROR: variable `"SV_Fmt"` is already defined\n", + Bang_Loc_Arg(var_def.loc), + SV_Arg(var_def.name)); + fprintf(stderr, Bang_Loc_Fmt": NOTE: the first definition is located here\n", + Bang_Loc_Arg(existing_var->def.loc)); + exit(1); + } + + assert(false && "TODO: compiling the stack variable is not implemented"); +} + +void bang_push_new_scope(Bang *bang) +{ + Bang_Scope *scope = arena_alloc(&bang->arena, sizeof(Bang_Scope)); + scope->parent = bang->scope; + bang->scope = scope; +} + +void bang_pop_scope(Bang *bang) +{ + assert(bang->scope != NULL); + bang->scope = bang->scope->parent; } diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 651b239..d50fbe3 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -6,7 +6,7 @@ #include "./bang_lexer.h" #include "./bang_parser.h" -#define BANG_GLOBAL_VARS_CAPACITY 1024 +#define BANG_SCOPE_VARS_CAPACITY 1024 #define BANG_PROCS_CAPACITY 1024 typedef enum { @@ -42,7 +42,7 @@ typedef struct { // when storage == BANG_VAR_STATIC_STORAGE: // addr is absolute address of the variable in memory // when storage == BANG_VAR_STACK_STORAGE: - // addr is an offset from the top of the stack + // addr is an offset from the stack frame Memory_Addr addr; } Compiled_Var; @@ -51,15 +51,32 @@ typedef struct { Inst_Addr addr; } Compiled_Proc; -#define BANG_STACK_CAPACITY 4096 +typedef struct Bang_Scope Bang_Scope; + +struct Bang_Scope { + Bang_Scope *parent; + Compiled_Var vars[BANG_SCOPE_VARS_CAPACITY]; + size_t vars_count; +}; + +Compiled_Var *bang_scope_get_compiled_var_by_name(Bang_Scope *scope, String_View + name); +void bang_scope_push_var(Bang_Scope *scope, Compiled_Var var); + +#define BANG_STACK_CAPACITY 32 + +#define STACK_TOP_VAR_TYPE BANG_TYPE_I64 +#define STACK_FRAME_VAR_TYPE BANG_TYPE_I64 typedef struct { + Arena arena; + Native_ID write_id; - Memory_Addr stack_base_var_addr; + Memory_Addr stack_top_var_addr; + Memory_Addr stack_frame_var_addr; - Compiled_Var global_vars[BANG_GLOBAL_VARS_CAPACITY]; - size_t global_vars_count; + Bang_Scope *scope; Compiled_Proc procs[BANG_PROCS_CAPACITY]; size_t procs_count; @@ -67,7 +84,7 @@ typedef struct { Bang_Loc entry_loc; } Bang; -Compiled_Var *bang_get_global_var_by_name(Bang *bang, String_View name); +Compiled_Var *bang_get_compiled_var_by_name(Bang *bang, String_View name); typedef struct { Bang_Expr ast; @@ -92,6 +109,9 @@ void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_de Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_read); Bang_Type compile_binary_op_into_basm(Bang *bang, Basm *basm, Bang_Binary_Op binary_op); +void bang_push_new_scope(Bang *bang); +void bang_pop_scope(Bang *bang); + void bang_generate_entry_point(Bang *bang, Basm *basm, String_View entry_proc_name); void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_name); From fcb333bec7783536d0f7c956511d724416dc5e87 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:54:23 +0700 Subject: [PATCH 05/12] Add TODO(#454) --- bang/src/bang_compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 8127941..2bf7075 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -153,7 +153,7 @@ Bang_Type compile_var_read_into_basm(Bang *bang, Basm *basm, Bang_Var_Read var_r break; case BANG_VAR_STACK_STORAGE: { - assert(false && "TODO: reading stack variables is not implemented"); + assert(false && "TODO(#454): reading stack variables is not implemented"); } break; } From fd6e657abcdeeba0150f3de03487ed680fd90486 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:54:24 +0700 Subject: [PATCH 06/12] Add TODO(#455) --- bang/src/bang_compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 2bf7075..a0b8e16 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -262,7 +262,7 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr break; case BANG_VAR_STACK_STORAGE: { - assert(false && "TODO: Taking a pointer to stack variable is not implemented"); + assert(false && "TODO(#455): Taking a pointer to stack variable is not implemented"); } break; } From d88fabddc5a42b7b9e9b1b010d73e9c02b889e21 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:54:25 +0700 Subject: [PATCH 07/12] Add TODO(#456) --- bang/src/bang_compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index a0b8e16..86eb87d 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -487,7 +487,7 @@ void compile_bang_var_assign_into_basm(Bang *bang, Basm *basm, Bang_Var_Assign v break; case BANG_VAR_STACK_STORAGE: { - assert(false && "TODO: assigning to stack variable is not implemented"); + assert(false && "TODO(#456): assigning to stack variable is not implemented"); } break; } From c27a142f98e0ea00d5a9ec1b072b6c0b317ce752 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:54:25 +0700 Subject: [PATCH 08/12] Add TODO(#457) --- bang/src/bang_compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 86eb87d..1901c84 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -738,7 +738,7 @@ void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_de exit(1); } - // TODO: bang compile does not warn about shadowing of the variable + // TODO(#457): bang compile does not warn about shadowing of the variable Compiled_Var *existing_var = bang_scope_get_compiled_var_by_name(bang->scope, var_def.name); if (existing_var) { From 0da0758539f8d26a89926914142a23bcc4df06de Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:54:26 +0700 Subject: [PATCH 09/12] Add TODO(#458) --- bang/src/bang_compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 1901c84..173b0eb 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -750,7 +750,7 @@ void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_de exit(1); } - assert(false && "TODO: compiling the stack variable is not implemented"); + assert(false && "TODO(#458): compiling the stack variable is not implemented"); } void bang_push_new_scope(Bang *bang) From 07f6b6bf2a67d02bfdc8cf69c87b92005e0e7a25 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:54:41 +0700 Subject: [PATCH 10/12] Remove redundant TODO --- bang/src/bang_compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 173b0eb..66990e2 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -396,7 +396,7 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr case COUNT_BANG_EXPR_KINDS: default: - assert(false && "TODO: compile_bang_expr_into_basm: unreachable"); + assert(false && "compile_bang_expr_into_basm: unreachable"); exit(1); } From 81572459e3dd11e07ddf5ecb0a99150444a6fa4c Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:55:19 +0700 Subject: [PATCH 11/12] Fix the formatting remarks --- bang/src/bang_compiler.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index d50fbe3..239eb4f 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -59,8 +59,7 @@ struct Bang_Scope { size_t vars_count; }; -Compiled_Var *bang_scope_get_compiled_var_by_name(Bang_Scope *scope, String_View - name); +Compiled_Var *bang_scope_get_compiled_var_by_name(Bang_Scope *scope, String_View name); void bang_scope_push_var(Bang_Scope *scope, Compiled_Var var); #define BANG_STACK_CAPACITY 32 From 35c7802f97f23d7e3b60b130d5c936ecaa7a8cbd Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 17 Jun 2021 19:59:17 +0700 Subject: [PATCH 12/12] Fix the unused variable warning for MSVC --- bang/src/bang_compiler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 66990e2..d3d5160 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -750,6 +750,7 @@ void compile_stack_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_de exit(1); } + (void) basm; assert(false && "TODO(#458): compiling the stack variable is not implemented"); }