From 8f68a29d36e8002cf6072dea4b665bd9c5dac6ed Mon Sep 17 00:00:00 2001 From: rexim Date: Wed, 7 Jul 2021 21:15:11 +0700 Subject: [PATCH 1/7] Add func params to the parser --- bang/src/bang_compiler.c | 8 +----- bang/src/bang_parser.c | 62 +++++++++++++++++++++++++++++----------- bang/src/bang_parser.h | 11 ++++++- common/error.h | 17 +++++++++++ common/ll.h | 19 ++++++++++++ 5 files changed, 93 insertions(+), 24 deletions(-) create mode 100644 common/error.h create mode 100644 common/ll.h diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 67a0898..4b7a7d7 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -1,14 +1,8 @@ +#include "./error.h" #include "./bang_compiler.h" // 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; diff --git a/bang/src/bang_parser.c b/bang/src/bang_parser.c index ae13d4c..c7c9a2f 100644 --- a/bang/src/bang_parser.c +++ b/bang/src/bang_parser.c @@ -1,20 +1,10 @@ #include #include #include +#include "./error.h" +#include "./ll.h" #include "./bang_parser.h" -#define APPEND_LINKED_LIST(begin, end, node) \ - do { \ - if ((end) == NULL) { \ - assert((begin) == NULL); \ - (begin) = (end) = (node); \ - } else { \ - assert((begin) != NULL); \ - (end)->next = node; \ - (end) = node; \ - } \ - } while (0) - static Bang_Binary_Op_Def binary_op_defs[COUNT_BANG_BINARY_OP_KINDS] = { [BANG_BINARY_OP_KIND_AND] = { .kind = BANG_BINARY_OP_KIND_AND, @@ -146,7 +136,7 @@ Bang_Funcall_Arg *parse_bang_funcall_args(Arena *arena, Bang_Lexer *lexer) if (bang_lexer_peek(lexer, &token, 0) && token.kind != BANG_TOKEN_KIND_CLOSE_PAREN) { Bang_Funcall_Arg *node = arena_alloc(arena, sizeof(*node)); node->value = parse_bang_expr(arena, lexer); - APPEND_LINKED_LIST(begin, end, node); + LL_APPEND(begin, end, node); } // Rest args @@ -155,7 +145,7 @@ Bang_Funcall_Arg *parse_bang_funcall_args(Arena *arena, Bang_Lexer *lexer) Bang_Funcall_Arg *node = arena_alloc(arena, sizeof(*node)); node->value = parse_bang_expr(arena, lexer); - APPEND_LINKED_LIST(begin, end, node); + LL_APPEND(begin, end, node); } bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_CLOSE_PAREN); @@ -521,14 +511,54 @@ Bang_Block *parse_curly_bang_block(Arena *arena, Bang_Lexer *lexer) return begin; } +Bang_Proc_Param *parse_bang_proc_params(Arena *arena, Bang_Lexer *lexer) +{ + Bang_Proc_Param *begin = NULL; + Bang_Proc_Param *end = NULL; + + bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_OPEN_PAREN); + + Bang_Token token = {0}; + if (bang_lexer_peek(lexer, &token, 0) && token.kind == BANG_TOKEN_KIND_CLOSE_PAREN) { + bang_lexer_next(lexer, &token); + return begin; + } + + { + Bang_Proc_Param *param = arena_alloc(arena, sizeof(*param)); + param->name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; + bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_COLON); + param->type_name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; + LL_APPEND(begin, end, param); + } + + if (bang_lexer_peek(lexer, &token, 0) && token.kind == BANG_TOKEN_KIND_CLOSE_PAREN) { + bang_lexer_next(lexer, &token); + return begin; + } + + while (bang_lexer_peek(lexer, &token, 0) && token.kind == BANG_TOKEN_KIND_COMMA) { + bang_lexer_next(lexer, &token); + + Bang_Proc_Param *param = arena_alloc(arena, sizeof(*param)); + param->name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; + bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_COLON); + param->type_name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; + LL_APPEND(begin, end, param); + } + + bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_CLOSE_PAREN); + + return begin; +} + Bang_Proc_Def parse_bang_proc_def(Arena *arena, Bang_Lexer *lexer) { Bang_Proc_Def result = {0}; result.loc = bang_lexer_expect_keyword(lexer, SV("proc")).loc; result.name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; - bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_OPEN_PAREN); - bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_CLOSE_PAREN); + parse_bang_proc_params(arena, lexer); result.body = parse_curly_bang_block(arena, lexer); return result; diff --git a/bang/src/bang_parser.h b/bang/src/bang_parser.h index f9b155e..53114f3 100644 --- a/bang/src/bang_parser.h +++ b/bang/src/bang_parser.h @@ -14,6 +14,7 @@ typedef struct Bang_If Bang_If; typedef union Bang_Stmt_As Bang_Stmt_As; typedef struct Bang_Block Bang_Block; typedef struct Bang_Proc_Def Bang_Proc_Def; +typedef struct Bang_Proc_Param Bang_Proc_Param; typedef struct Bang_Var_Def Bang_Var_Def; typedef union Bang_Top_As Bang_Top_As; typedef struct Bang_Top Bang_Top; @@ -35,7 +36,7 @@ typedef enum { BANG_BINARY_OP_KIND_OR, BANG_BINARY_OP_KIND_EQ, COUNT_BANG_BINARY_OP_KINDS, -} Bang_Binary_Op_Kind; +} Bang_Binary_Op_Kind; typedef enum { BINARY_OP_PREC0 = 0, @@ -166,9 +167,16 @@ struct Bang_Block { Bang_Block *next; }; +struct Bang_Proc_Param { + String_View name; + String_View type_name; + Bang_Proc_Param *next; +}; + struct Bang_Proc_Def { Bang_Loc loc; String_View name; + Bang_Proc_Param *params; Bang_Block *body; }; @@ -204,6 +212,7 @@ Bang_Expr parse_bang_expr(Arena *arena, Bang_Lexer *lexer); Bang_Block *parse_curly_bang_block(Arena *arena, Bang_Lexer *lexer); Bang_If parse_bang_if(Arena *arena, Bang_Lexer *lexer); Bang_Stmt parse_bang_stmt(Arena *arena, Bang_Lexer *lexer); +Bang_Proc_Param *parse_bang_proc_params(Arena *arena, Bang_Lexer *lexer); Bang_Proc_Def parse_bang_proc_def(Arena *arena, Bang_Lexer *lexer); Bang_Top parse_bang_top(Arena *arena, Bang_Lexer *lexer); Bang_Var_Def parse_bang_var_def(Arena *arena, Bang_Lexer *lexer); diff --git a/common/error.h b/common/error.h new file mode 100644 index 0000000..40db34a --- /dev/null +++ b/common/error.h @@ -0,0 +1,17 @@ +#ifndef ERROR_H_ +#define ERROR_H_ + +#define UNIMPLEMENTED \ + do { \ + fprintf(stderr, "%s:%d: %s is not implemented yet\n", \ + __FILE__, __LINE__, __func__); \ + abort(); \ + } while(0) + +#define UNREACHABLE \ + do { \ + fprintf(stderr, "%s:%d: unreachable\n", __FILE__, __LINE__); \ + abort(); \ + } while(0) + +#endif // ERROR_H_ diff --git a/common/ll.h b/common/ll.h new file mode 100644 index 0000000..2f557e9 --- /dev/null +++ b/common/ll.h @@ -0,0 +1,19 @@ +#ifndef LL_H_ +#define LL_H_ + +#define LL_APPEND(begin, end, node) \ + do { \ + if ((end) == NULL) { \ + assert((begin) == NULL); \ + (begin) = (end) = (node); \ + } else { \ + assert((begin) != NULL); \ + (end)->next = node; \ + (end) = node; \ + } \ + } while (0) + +#define LL_FOREACH(type, iter, begin) \ + for(type *iter = (begin); iter != NULL; iter = iter->next) + +#endif // LL_H_ From 6749d60cb14f3202ff256d3457e68881795c49a5 Mon Sep 17 00:00:00 2001 From: rexim Date: Wed, 7 Jul 2021 21:29:52 +0700 Subject: [PATCH 2/7] Get rid of Proc_Def from Compiled_Proc --- bang/src/bang_compiler.c | 7 ++++--- bang/src/bang_compiler.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 4b7a7d7..215764c 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -558,7 +558,7 @@ void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block) Compiled_Proc *bang_get_compiled_proc_by_name(Bang *bang, String_View name) { for (size_t i = 0; i < bang->procs_count; ++i) { - if (sv_eq(bang->procs[i].def.name, name)) { + if (sv_eq(bang->procs[i].name, name)) { return &bang->procs[i]; } } @@ -572,13 +572,14 @@ void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def) bang_diag_msg(proc_def.loc, BANG_DIAG_ERROR, "procedure `"SV_Fmt"` is already defined", SV_Arg(proc_def.name)); - bang_diag_msg(existing_proc->def.loc, BANG_DIAG_NOTE, + bang_diag_msg(existing_proc->loc, BANG_DIAG_NOTE, "the first definition is located here"); exit(1); } Compiled_Proc proc = {0}; - proc.def = proc_def; + proc.name = proc_def.name; + proc.loc = proc_def.loc; proc.addr = basm->program_size; assert(bang->procs_count < BANG_PROCS_CAPACITY); bang->procs[bang->procs_count++] = proc; diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 3eb9840..1f7d47d 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -47,7 +47,8 @@ typedef struct { } Compiled_Var; typedef struct { - Bang_Proc_Def def; + String_View name; + Bang_Loc loc; Inst_Addr addr; } Compiled_Proc; From f5d9c46b3388119a1e0cca48c151ae28f03e0f93 Mon Sep 17 00:00:00 2001 From: rexim Date: Wed, 7 Jul 2021 21:32:36 +0700 Subject: [PATCH 3/7] Get rid of Bang_Var_Def in Compiled_Var --- bang/src/bang_compiler.c | 11 ++++++----- bang/src/bang_compiler.h | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 215764c..c46ac2a 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -432,7 +432,7 @@ Compiled_Var *bang_scope_get_compiled_var_by_name(Bang_Scope *scope, String_View assert(scope); for (size_t i = 0; i < scope->vars_count; ++i) { - if (sv_eq(scope->vars[i].def.name, name)) { + if (sv_eq(scope->vars[i].name, name)) { return &scope->vars[i]; } } @@ -654,7 +654,7 @@ void bang_generate_heap_base(Bang *bang, Basm *basm, String_View heap_base_var_n if (heap_base_var != NULL) { assert(heap_base_var->storage == BANG_VAR_STATIC_STORAGE); if (heap_base_var->type != BANG_TYPE_PTR) { - bang_diag_msg(heap_base_var->def.loc, BANG_DIAG_ERROR, + bang_diag_msg(heap_base_var->loc, BANG_DIAG_ERROR, "the special `"SV_Fmt"` variable is expected to be of type `%s` but it was defined as type `%s`", SV_Arg(heap_base_var_name), bang_type_def(BANG_TYPE_PTR).name, @@ -704,7 +704,7 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban bang_diag_msg(var_def.loc, BANG_DIAG_ERROR, "variable `"SV_Fmt"` is already defined", SV_Arg(var_def.name)); - bang_diag_msg(existing_var->def.loc, BANG_DIAG_ERROR, + bang_diag_msg(existing_var->loc, BANG_DIAG_ERROR, "the first definition is located here"); exit(1); } @@ -719,7 +719,7 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban bang_diag_msg(var_def.loc, bang->warnings_as_errors ? BANG_DIAG_ERROR : BANG_DIAG_WARNING, "variable `"SV_Fmt"` is shadowing another variable with the same name", SV_Arg(var_def.name)); - bang_diag_msg(shadowed_var->def.loc, BANG_DIAG_NOTE, + bang_diag_msg(shadowed_var->loc, BANG_DIAG_NOTE, "the shadowed variable is located here"); if (bang->warnings_as_errors) { @@ -729,7 +729,8 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban } Compiled_Var new_var = {0}; - new_var.def = var_def; + new_var.name = var_def.name; + new_var.loc = var_def.loc; new_var.type = type; new_var.storage = storage; diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 1f7d47d..ddc3bf6 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -36,7 +36,8 @@ typedef struct { Bang_Type_Def bang_type_def(Bang_Type type); typedef struct { - Bang_Var_Def def; + String_View name; + Bang_Loc loc; Bang_Type type; Bang_Var_Storage storage; // when storage == BANG_VAR_STATIC_STORAGE: From 28d22f013ea4427dbf2277768919881eaea7bc74 Mon Sep 17 00:00:00 2001 From: rexim Date: Wed, 7 Jul 2021 22:06:00 +0700 Subject: [PATCH 4/7] Implement compile_bang_funcall_into_basm() --- bang/src/bang_compiler.c | 72 ++++++++++++++++++++++++++++++++++------ bang/src/bang_compiler.h | 2 ++ bang/src/bang_parser.c | 10 ++++-- bang/src/bang_parser.h | 1 + 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index c46ac2a..ac6fd5a 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -1,4 +1,5 @@ #include "./error.h" +#include "./ll.h" #include "./bang_compiler.h" // TODO(#426): bang does not support type casting @@ -221,6 +222,65 @@ static void type_check_expr(Compiled_Expr expr, Bang_Type expected_type) } } +void compile_bang_funcall_into_basm(Bang *bang, Basm *basm, Bang_Funcall funcall) +{ + Compiled_Proc *proc = bang_get_compiled_proc_by_name(bang, funcall.name); + if (proc == NULL) { + bang_diag_msg(funcall.loc, BANG_DIAG_ERROR, + "unknown function `"SV_Fmt"`", + SV_Arg(funcall.name)); + exit(1); + } + + // Check arity + { + size_t params_arity = 0; + LL_FOREACH(Bang_Proc_Param, param, proc->params) { + params_arity += 1; + } + + size_t args_arity = 0; + LL_FOREACH(Bang_Funcall_Arg, arg, funcall.args) { + args_arity += 1; + } + + if (params_arity != args_arity) { + bang_diag_msg(funcall.loc, BANG_DIAG_ERROR, + "Function `"SV_Fmt"` expects %zu amount of arguments but got %zu\n", + SV_Arg(funcall.name), + params_arity, + args_arity); + exit(1); + } + } + + // Compile Funcall args + { + Bang_Proc_Param *param = proc->params; + Bang_Funcall_Arg *arg = funcall.args; + + while (arg && param) { + Compiled_Expr expr = compile_bang_expr_into_basm(bang, basm, arg->value); + Bang_Type param_type = 0; + if (!bang_type_by_name(param->type_name, ¶m_type)) { + bang_diag_msg(param->loc, BANG_DIAG_ERROR, + "`"SV_Fmt"` is not a valid type", + SV_Arg(param->type_name)); + exit(1); + } + + type_check_expr(expr, param_type); + + arg = arg->next; + param = param->next; + } + } + + compile_push_new_frame(bang, basm); + basm_push_inst(basm, INST_CALL, word_u64(proc->addr)); + compile_pop_frame(bang, basm); +} + Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr) { Compiled_Expr result = {0}; @@ -346,16 +406,7 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr basm_push_inst(basm, INST_HALT, word_u64(0)); result.type = BANG_TYPE_VOID; } else { - Compiled_Proc *proc = bang_get_compiled_proc_by_name(bang, funcall.name); - if (proc == NULL) { - bang_diag_msg(funcall.loc, BANG_DIAG_ERROR, - "unknown function `"SV_Fmt"`", - SV_Arg(funcall.name)); - exit(1); - } - compile_push_new_frame(bang, basm); - basm_push_inst(basm, INST_CALL, word_u64(proc->addr)); - compile_pop_frame(bang, basm); + compile_bang_funcall_into_basm(bang, basm, funcall); result.type = BANG_TYPE_VOID; } } @@ -580,6 +631,7 @@ void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def) Compiled_Proc proc = {0}; proc.name = proc_def.name; proc.loc = proc_def.loc; + proc.params = proc_def.params; proc.addr = basm->program_size; assert(bang->procs_count < BANG_PROCS_CAPACITY); bang->procs[bang->procs_count++] = proc; diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index ddc3bf6..35b6aca 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -50,6 +50,7 @@ typedef struct { typedef struct { String_View name; Bang_Loc loc; + Bang_Proc_Param *params; Inst_Addr addr; } Compiled_Proc; @@ -97,6 +98,7 @@ Compiled_Proc *bang_get_compiled_proc_by_name(Bang *bang, String_View name); void compile_typed_read(Basm *basm, Bang_Type type); void compile_typed_write(Basm *basm, Bang_Type type); +void compile_bang_funcall_into_basm(Bang *bang, Basm *basm, Bang_Funcall funcall); Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr); void compile_stmt_into_basm(Bang *bang, Basm *basm, Bang_Stmt stmt); void compile_block_into_basm(Bang *bang, Basm *basm, Bang_Block *block); diff --git a/bang/src/bang_parser.c b/bang/src/bang_parser.c index c7c9a2f..ca4ac14 100644 --- a/bang/src/bang_parser.c +++ b/bang/src/bang_parser.c @@ -526,7 +526,9 @@ Bang_Proc_Param *parse_bang_proc_params(Arena *arena, Bang_Lexer *lexer) { Bang_Proc_Param *param = arena_alloc(arena, sizeof(*param)); - param->name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; + token = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME); + param->loc = token.loc; + param->name = token.text; bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_COLON); param->type_name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; LL_APPEND(begin, end, param); @@ -541,7 +543,9 @@ Bang_Proc_Param *parse_bang_proc_params(Arena *arena, Bang_Lexer *lexer) bang_lexer_next(lexer, &token); Bang_Proc_Param *param = arena_alloc(arena, sizeof(*param)); - param->name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; + token = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME); + param->loc = token.loc; + param->name = token.text; bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_COLON); param->type_name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; LL_APPEND(begin, end, param); @@ -558,7 +562,7 @@ Bang_Proc_Def parse_bang_proc_def(Arena *arena, Bang_Lexer *lexer) result.loc = bang_lexer_expect_keyword(lexer, SV("proc")).loc; result.name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; - parse_bang_proc_params(arena, lexer); + result.params = parse_bang_proc_params(arena, lexer); result.body = parse_curly_bang_block(arena, lexer); return result; diff --git a/bang/src/bang_parser.h b/bang/src/bang_parser.h index 53114f3..d92d531 100644 --- a/bang/src/bang_parser.h +++ b/bang/src/bang_parser.h @@ -168,6 +168,7 @@ struct Bang_Block { }; struct Bang_Proc_Param { + Bang_Loc loc; String_View name; String_View type_name; Bang_Proc_Param *next; From 9b8205f4281369ac2eb18761d65aea423585b946 Mon Sep 17 00:00:00 2001 From: rexim Date: Wed, 7 Jul 2021 23:06:24 +0700 Subject: [PATCH 5/7] Replace Linked Lists with Dynamic Arrays --- bang/src/bang_compiler.c | 68 ++++++++++++++-------------------------- bang/src/bang_compiler.h | 2 +- bang/src/bang_parser.c | 57 ++++++++++++++++----------------- bang/src/bang_parser.h | 23 +++++++++++--- common/arena.c | 11 +++++++ common/arena.h | 1 + common/dynarray.h | 24 ++++++++++++++ common/ll.h | 19 ----------- 8 files changed, 107 insertions(+), 98 deletions(-) create mode 100644 common/dynarray.h delete mode 100644 common/ll.h diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index ac6fd5a..1663448 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -1,5 +1,4 @@ #include "./error.h" -#include "./ll.h" #include "./bang_compiler.h" // TODO(#426): bang does not support type casting @@ -234,15 +233,8 @@ void compile_bang_funcall_into_basm(Bang *bang, Basm *basm, Bang_Funcall funcall // Check arity { - size_t params_arity = 0; - LL_FOREACH(Bang_Proc_Param, param, proc->params) { - params_arity += 1; - } - - size_t args_arity = 0; - LL_FOREACH(Bang_Funcall_Arg, arg, funcall.args) { - args_arity += 1; - } + size_t params_arity = proc->params.size; + size_t args_arity = funcall.args.size; if (params_arity != args_arity) { bang_diag_msg(funcall.loc, BANG_DIAG_ERROR, @@ -256,23 +248,22 @@ void compile_bang_funcall_into_basm(Bang *bang, Basm *basm, Bang_Funcall funcall // Compile Funcall args { - Bang_Proc_Param *param = proc->params; - Bang_Funcall_Arg *arg = funcall.args; + size_t n = proc->params.size; - while (arg && param) { - Compiled_Expr expr = compile_bang_expr_into_basm(bang, basm, arg->value); + for (size_t i = 0; i < n; ++i) { + Bang_Proc_Param param = proc->params.items[i]; + Bang_Funcall_Arg arg = funcall.args.items[i]; + + Compiled_Expr expr = compile_bang_expr_into_basm(bang, basm, arg.value); Bang_Type param_type = 0; - if (!bang_type_by_name(param->type_name, ¶m_type)) { - bang_diag_msg(param->loc, BANG_DIAG_ERROR, + if (!bang_type_by_name(param.type_name, ¶m_type)) { + bang_diag_msg(param.loc, BANG_DIAG_ERROR, "`"SV_Fmt"` is not a valid type", - SV_Arg(param->type_name)); + SV_Arg(param.type_name)); exit(1); } type_check_expr(expr, param_type); - - arg = arg->next; - param = param->next; } } @@ -302,12 +293,12 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr if (sv_eq(funcall.name, SV("write"))) { bang_funcall_expect_arity(funcall, 1); - compile_bang_expr_into_basm(bang, basm, funcall.args->value); + compile_bang_expr_into_basm(bang, basm, funcall.args.items[0].value); basm_push_inst(basm, INST_NATIVE, word_u64(bang->write_id)); result.type = BANG_TYPE_VOID; } else if (sv_eq(funcall.name, SV("ptr"))) { bang_funcall_expect_arity(funcall, 1); - Bang_Expr arg = funcall.args->value; + Bang_Expr arg = funcall.args.items[0].value; if (arg.kind != BANG_EXPR_KIND_VAR_READ) { bang_diag_msg(funcall.loc, BANG_DIAG_ERROR, "expected variable name as the argument of `ptr` function"); @@ -319,9 +310,8 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr result.type = BANG_TYPE_PTR; } else if (sv_eq(funcall.name, SV("write_ptr"))) { bang_funcall_expect_arity(funcall, 2); - Bang_Funcall_Arg *args = funcall.args; - Bang_Expr arg0 = args->value; - Bang_Expr arg1 = args->next->value; + Bang_Expr arg0 = funcall.args.items[0].value; + Bang_Expr arg1 = funcall.args.items[1].value; Compiled_Expr buffer = compile_bang_expr_into_basm(bang, basm, arg0); type_check_expr(buffer, BANG_TYPE_PTR); @@ -334,9 +324,8 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr result.type = BANG_TYPE_VOID; } else if (sv_eq(funcall.name, SV("cast"))) { bang_funcall_expect_arity(funcall, 2); - Bang_Funcall_Arg *args = funcall.args; - Bang_Expr arg0 = args->value; - Bang_Expr arg1 = args->next->value; + Bang_Expr arg0 = funcall.args.items[0].value; + Bang_Expr arg1 = funcall.args.items[1].value; Bang_Type type = reinterpret_expr_as_type(arg0); @@ -359,10 +348,9 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr // TODO(#432): there is no special syntax for dereferencing the pointer } else if (sv_eq(funcall.name, SV("store_ptr"))) { bang_funcall_expect_arity(funcall, 3); - Bang_Funcall_Arg *args = funcall.args; - Bang_Expr arg0 = args->value; - Bang_Expr arg1 = args->next->value; - Bang_Expr arg2 = args->next->next->value; + Bang_Expr arg0 = funcall.args.items[0].value; + Bang_Expr arg1 = funcall.args.items[1].value; + Bang_Expr arg2 = funcall.args.items[2].value; Bang_Type type = reinterpret_expr_as_type(arg0); if (type == BANG_TYPE_VOID) { @@ -383,9 +371,8 @@ Compiled_Expr compile_bang_expr_into_basm(Bang *bang, Basm *basm, Bang_Expr expr result.type = BANG_TYPE_VOID; } else if (sv_eq(funcall.name, SV("load_ptr"))) { bang_funcall_expect_arity(funcall, 2); - Bang_Funcall_Arg *args = funcall.args; - Bang_Expr arg0 = args->value; - Bang_Expr arg1 = args->next->value; + Bang_Expr arg0 = funcall.args.items[0].value; + Bang_Expr arg1 = funcall.args.items[1].value; Bang_Type type = reinterpret_expr_as_type(arg0); if (type == BANG_TYPE_VOID) { @@ -643,16 +630,7 @@ void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def) void bang_funcall_expect_arity(Bang_Funcall funcall, size_t expected_arity) { - size_t actual_arity = 0; - - { - Bang_Funcall_Arg *args = funcall.args; - while (args != NULL) { - actual_arity += 1; - args = args->next; - } - } - + const size_t actual_arity = funcall.args.size; if (expected_arity != actual_arity) { bang_diag_msg(funcall.loc, BANG_DIAG_ERROR, "function `"SV_Fmt"` expects %zu amount of arguments but provided %zu", diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 35b6aca..6769f55 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -50,7 +50,7 @@ typedef struct { typedef struct { String_View name; Bang_Loc loc; - Bang_Proc_Param *params; + Dynarray_Of_Bang_Proc_Param params; Inst_Addr addr; } Compiled_Proc; diff --git a/bang/src/bang_parser.c b/bang/src/bang_parser.c index ca4ac14..77246d9 100644 --- a/bang/src/bang_parser.c +++ b/bang/src/bang_parser.c @@ -2,7 +2,7 @@ #include #include #include "./error.h" -#include "./ll.h" +#include "./dynarray.h" #include "./bang_parser.h" static Bang_Binary_Op_Def binary_op_defs[COUNT_BANG_BINARY_OP_KINDS] = { @@ -123,10 +123,9 @@ String_View parse_bang_lit_str(Arena *arena, Bang_Lexer *lexer) }; } -Bang_Funcall_Arg *parse_bang_funcall_args(Arena *arena, Bang_Lexer *lexer) +Dynarray_Of_Bang_Funcall_Arg parse_bang_funcall_args(Arena *arena, Bang_Lexer *lexer) { - Bang_Funcall_Arg *begin = NULL; - Bang_Funcall_Arg *end = NULL; + Dynarray_Of_Bang_Funcall_Arg args = {0}; bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_OPEN_PAREN); @@ -134,23 +133,25 @@ Bang_Funcall_Arg *parse_bang_funcall_args(Arena *arena, Bang_Lexer *lexer) // First arg if (bang_lexer_peek(lexer, &token, 0) && token.kind != BANG_TOKEN_KIND_CLOSE_PAREN) { - Bang_Funcall_Arg *node = arena_alloc(arena, sizeof(*node)); - node->value = parse_bang_expr(arena, lexer); - LL_APPEND(begin, end, node); + Bang_Funcall_Arg arg = { + .value = parse_bang_expr(arena, lexer), + }; + DYNARRAY_PUSH(arena, args, Bang_Funcall_Arg, arg); } // Rest args while (bang_lexer_peek(lexer, &token, 0) && token.kind != BANG_TOKEN_KIND_CLOSE_PAREN) { bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_COMMA); - Bang_Funcall_Arg *node = arena_alloc(arena, sizeof(*node)); - node->value = parse_bang_expr(arena, lexer); - LL_APPEND(begin, end, node); + Bang_Funcall_Arg arg = { + .value = parse_bang_expr(arena, lexer), + }; + DYNARRAY_PUSH(arena, args, Bang_Funcall_Arg, arg); } bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_CLOSE_PAREN); - return begin; + return args; } Bang_Funcall parse_bang_funcall(Arena *arena, Bang_Lexer *lexer) @@ -511,49 +512,49 @@ Bang_Block *parse_curly_bang_block(Arena *arena, Bang_Lexer *lexer) return begin; } -Bang_Proc_Param *parse_bang_proc_params(Arena *arena, Bang_Lexer *lexer) +Dynarray_Of_Bang_Proc_Param parse_bang_proc_params(Arena *arena, Bang_Lexer *lexer) { - Bang_Proc_Param *begin = NULL; - Bang_Proc_Param *end = NULL; + Dynarray_Of_Bang_Proc_Param params = {0}; bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_OPEN_PAREN); - + Bang_Token token = {0}; if (bang_lexer_peek(lexer, &token, 0) && token.kind == BANG_TOKEN_KIND_CLOSE_PAREN) { bang_lexer_next(lexer, &token); - return begin; + return params; } { - Bang_Proc_Param *param = arena_alloc(arena, sizeof(*param)); + Bang_Proc_Param param = {0}; token = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME); - param->loc = token.loc; - param->name = token.text; + param.loc = token.loc; + param.name = token.text; bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_COLON); - param->type_name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; - LL_APPEND(begin, end, param); + param.type_name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; + + DYNARRAY_PUSH(arena, params, Bang_Proc_Param, param); } if (bang_lexer_peek(lexer, &token, 0) && token.kind == BANG_TOKEN_KIND_CLOSE_PAREN) { bang_lexer_next(lexer, &token); - return begin; + return params; } while (bang_lexer_peek(lexer, &token, 0) && token.kind == BANG_TOKEN_KIND_COMMA) { bang_lexer_next(lexer, &token); - Bang_Proc_Param *param = arena_alloc(arena, sizeof(*param)); + Bang_Proc_Param param = {0}; token = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME); - param->loc = token.loc; - param->name = token.text; + param.loc = token.loc; + param.name = token.text; bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_COLON); - param->type_name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; - LL_APPEND(begin, end, param); + param.type_name = bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_NAME).text; + DYNARRAY_PUSH(arena, params, Bang_Proc_Param, param); } bang_lexer_expect_token(lexer, BANG_TOKEN_KIND_CLOSE_PAREN); - return begin; + return params; } Bang_Proc_Def parse_bang_proc_def(Arena *arena, Bang_Lexer *lexer) diff --git a/bang/src/bang_parser.h b/bang/src/bang_parser.h index d92d531..26a0bab 100644 --- a/bang/src/bang_parser.h +++ b/bang/src/bang_parser.h @@ -24,6 +24,8 @@ typedef struct Bang_Var_Read Bang_Var_Read; typedef struct Bang_While Bang_While; typedef struct Bang_Binary_Op Bang_Binary_Op; typedef struct Bang_Binary_Op_Def Bang_Binary_Op_Def; +typedef struct Dynarray_Of_Bang_Proc_Param Dynarray_Of_Bang_Proc_Param; +typedef struct Dynarray_Of_Bang_Funcall_Arg Dynarray_Of_Bang_Funcall_Arg; typedef enum { BANG_BINARY_OP_KIND_PLUS = 0, @@ -54,10 +56,16 @@ struct Bang_Binary_Op_Def { // TODO(#440): there are no unary operators in Bang +struct Dynarray_Of_Bang_Funcall_Arg { + size_t size; + size_t capacity; + Bang_Funcall_Arg *items; +}; + struct Bang_Funcall { Bang_Loc loc; String_View name; - Bang_Funcall_Arg *args; + Dynarray_Of_Bang_Funcall_Arg args; }; typedef enum { @@ -171,13 +179,18 @@ struct Bang_Proc_Param { Bang_Loc loc; String_View name; String_View type_name; - Bang_Proc_Param *next; +}; + +struct Dynarray_Of_Bang_Proc_Param { + size_t size; + size_t capacity; + Bang_Proc_Param *items; }; struct Bang_Proc_Def { Bang_Loc loc; String_View name; - Bang_Proc_Param *params; + Dynarray_Of_Bang_Proc_Param params; Bang_Block *body; }; @@ -207,13 +220,13 @@ void bang_module_push_top(Bang_Module *module, Bang_Top *top); Bang_Binary_Op_Def bang_binary_op_def(Bang_Binary_Op_Kind kind); String_View parse_bang_lit_str(Arena *arena, Bang_Lexer *lexer); -Bang_Funcall_Arg *parse_bang_funcall_args(Arena *arena, Bang_Lexer *lexer); +Dynarray_Of_Bang_Funcall_Arg parse_bang_funcall_args(Arena *arena, Bang_Lexer *lexer); Bang_Funcall parse_bang_funcall(Arena *arena, Bang_Lexer *lexer); Bang_Expr parse_bang_expr(Arena *arena, Bang_Lexer *lexer); Bang_Block *parse_curly_bang_block(Arena *arena, Bang_Lexer *lexer); Bang_If parse_bang_if(Arena *arena, Bang_Lexer *lexer); Bang_Stmt parse_bang_stmt(Arena *arena, Bang_Lexer *lexer); -Bang_Proc_Param *parse_bang_proc_params(Arena *arena, Bang_Lexer *lexer); +Dynarray_Of_Bang_Proc_Param parse_bang_proc_params(Arena *arena, Bang_Lexer *lexer); Bang_Proc_Def parse_bang_proc_def(Arena *arena, Bang_Lexer *lexer); Bang_Top parse_bang_top(Arena *arena, Bang_Lexer *lexer); Bang_Var_Def parse_bang_var_def(Arena *arena, Bang_Lexer *lexer); diff --git a/common/arena.c b/common/arena.c index a47dae3..1a0d695 100644 --- a/common/arena.c +++ b/common/arena.c @@ -77,6 +77,17 @@ void *arena_alloc(Arena *arena, size_t size) return arena_alloc_aligned(arena, size, sizeof(void*)); } +void *arena_realloc(Arena *arena, void *old_ptr, size_t old_size, size_t new_size) +{ + if (old_size < new_size) { + void *new_ptr = arena_alloc(arena, new_size); + memcpy(new_ptr, old_ptr, old_size); + return new_ptr; + } else { + return old_ptr; + } +} + void arena_clean(Arena *arena) { for (Region *iter = arena->first; diff --git a/common/arena.h b/common/arena.h index 8ff1a5d..599e8c0 100644 --- a/common/arena.h +++ b/common/arena.h @@ -28,6 +28,7 @@ typedef struct { void *arena_alloc_aligned(Arena *arena, size_t size, size_t alignment); void *arena_alloc(Arena *arena, size_t size); +void *arena_realloc(Arena *arena, void *old_ptr, size_t old_size, size_t new_size); void arena_clean(Arena *arena); void arena_free(Arena *arena); void arena_summary(Arena *arena); diff --git a/common/dynarray.h b/common/dynarray.h new file mode 100644 index 0000000..ce04e61 --- /dev/null +++ b/common/dynarray.h @@ -0,0 +1,24 @@ +#ifndef DYNARRAY_H_ +#define DYNARRAY_H_ + +#define DYNARRAY_PUSH(arena, dynarray, item_type, item) \ + do { \ + if (dynarray.size >= dynarray.capacity) { \ + size_t new_capacity = dynarray.capacity; \ + if (new_capacity == 0) { \ + new_capacity = 128; \ + } else { \ + new_capacity *= 2; \ + } \ + dynarray.items = arena_realloc(arena, \ + dynarray.items, \ + dynarray.capacity * \ + sizeof(item_type), \ + new_capacity * sizeof(item_type)); \ + dynarray.capacity = new_capacity; \ + } \ + \ + dynarray.items[dynarray.size++] = item; \ + } while (0) + +#endif // DYNARRAY_H_ diff --git a/common/ll.h b/common/ll.h deleted file mode 100644 index 2f557e9..0000000 --- a/common/ll.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LL_H_ -#define LL_H_ - -#define LL_APPEND(begin, end, node) \ - do { \ - if ((end) == NULL) { \ - assert((begin) == NULL); \ - (begin) = (end) = (node); \ - } else { \ - assert((begin) != NULL); \ - (end)->next = node; \ - (end) = node; \ - } \ - } while (0) - -#define LL_FOREACH(type, iter, begin) \ - for(type *iter = (begin); iter != NULL; iter = iter->next) - -#endif // LL_H_ From efe3522e2633308494fa27c022a6e9b043fbd66b Mon Sep 17 00:00:00 2001 From: rexim Date: Wed, 7 Jul 2021 23:08:09 +0700 Subject: [PATCH 6/7] Move scope managing outside of compile_block_into_basm() --- bang/src/bang_compiler.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 1663448..9fe66f7 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -448,10 +448,18 @@ void compile_bang_if_into_basm(Bang *bang, Basm *basm, Bang_If eef) basm_push_inst(basm, INST_NOT, word_u64(0)); Inst_Addr then_jmp_addr = basm_push_inst(basm, INST_JMP_IF, word_u64(0)); + + bang_push_new_scope(bang); compile_block_into_basm(bang, basm, eef.then); + bang_pop_scope(bang); + Inst_Addr else_jmp_addr = basm_push_inst(basm, INST_JMP, word_u64(0)); Inst_Addr else_addr = basm->program_size; + + bang_push_new_scope(bang); compile_block_into_basm(bang, basm, eef.elze); + bang_pop_scope(bang); + Inst_Addr end_addr = basm->program_size; basm->program[then_jmp_addr].operand = word_u64(else_addr); @@ -541,7 +549,9 @@ void compile_bang_while_into_basm(Bang *bang, Basm *basm, Bang_While hwile) basm_push_inst(basm, INST_NOT, word_u64(0)); Inst_Addr fallthrough_addr = basm_push_inst(basm, INST_JMP_IF, word_u64(0)); + bang_push_new_scope(bang); compile_block_into_basm(bang, basm, hwile.body); + bang_pop_scope(bang); basm_push_inst(basm, INST_JMP, word_u64(cond_expr.addr)); const Inst_Addr body_end_addr = basm->program_size; @@ -585,12 +595,10 @@ 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) @@ -623,7 +631,9 @@ void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def) assert(bang->procs_count < BANG_PROCS_CAPACITY); bang->procs[bang->procs_count++] = proc; + bang_push_new_scope(bang); compile_block_into_basm(bang, basm, proc_def.body); + bang_pop_scope(bang); basm_push_inst(basm, INST_RET, word_u64(0)); } From 770febe4f27df7c3e1911ee5340cbc5e0ac6d0f9 Mon Sep 17 00:00:00 2001 From: rexim Date: Thu, 8 Jul 2021 00:00:12 +0700 Subject: [PATCH 7/7] Make compile_proc_def_into_basm accept params properly --- bang/examples/rule110.bang | 103 +++++++++++++++++-------------------- bang/src/bang_compiler.c | 90 +++++++++++++++++++++++--------- bang/src/bang_compiler.h | 1 + 3 files changed, 114 insertions(+), 80 deletions(-) diff --git a/bang/examples/rule110.bang b/bang/examples/rule110.bang index 82a7366..69baa97 100644 --- a/bang/examples/rule110.bang +++ b/bang/examples/rule110.bang @@ -1,49 +1,13 @@ -var heap_base: ptr; - -var table_base: ptr; -var table_size: i64; -var table_index: u8; - -var states_base: ptr; -var state_size: i64; -var state_current: i64; -var state_next: i64; - -var display_base: ptr; - -proc init() { - # Init lookup table - table_base = heap_base; - table_size = 8; - store_ptr(u8, table_base + cast(ptr, 0), cast(u8, 0)); - store_ptr(u8, table_base + cast(ptr, 1), cast(u8, 1)); - store_ptr(u8, table_base + cast(ptr, 2), cast(u8, 1)); - store_ptr(u8, table_base + cast(ptr, 3), cast(u8, 1)); - store_ptr(u8, table_base + cast(ptr, 4), cast(u8, 0)); - store_ptr(u8, table_base + cast(ptr, 5), cast(u8, 1)); - store_ptr(u8, table_base + cast(ptr, 6), cast(u8, 1)); - store_ptr(u8, table_base + cast(ptr, 7), cast(u8, 0)); - - # Init 2 state buffers - state_size = 30; - state_current = 0; - states_base = table_base + cast(ptr, table_size); - store_ptr(u8, states_base + cast(ptr, state_size - 2), cast(u8, 1)); - - # Display buffer - display_base = states_base + cast(ptr, state_size * 2); -} - -proc print_state_current() { +proc print_state(state: ptr, state_size: i64, display: ptr) { var cell_ptr: ptr; var cell: u8; var i: i64 = 0; while i < state_size { - cell_ptr = states_base + cast(ptr, state_current * state_size + i); + cell_ptr = state + cast(ptr, i); cell = load_ptr(u8, cell_ptr); - cell_ptr = display_base + cast(ptr, i); + cell_ptr = display + cast(ptr, i); if cell < cast(u8, 1) { store_ptr(u8, cell_ptr, cast(u8, 32)); } else { @@ -53,37 +17,34 @@ proc print_state_current() { i = i + 1; } - cell_ptr = display_base + cast(ptr, state_size); + cell_ptr = display + cast(ptr, state_size); store_ptr(u8, cell_ptr, cast(u8, 10)); - write_ptr(display_base, state_size + 1); + write_ptr(display, state_size + 1); } -proc next_state() { - var cell_ptr: ptr; - var cell: u8; - - state_next = 1 - state_current; - +proc next_state(state_current: ptr, state_next: ptr, state_size: i64, table: ptr) { var i: i64 = 1; while i < state_size - 1 { - table_index = cast(u8, 0); + var cell_ptr: ptr; + var cell: u8; + var table_index: u8 = cast(u8, 0); - cell_ptr = states_base + cast(ptr, state_current * state_size + i - 1); + cell_ptr = state_current + cast(ptr, i - 1); cell = load_ptr(u8, cell_ptr); table_index = table_index * cast(u8, 2) + cell; - cell_ptr = states_base + cast(ptr, state_current * state_size + i); + cell_ptr = state_current + cast(ptr, i); cell = load_ptr(u8, cell_ptr); table_index = table_index * cast(u8, 2) + cell; - cell_ptr = states_base + cast(ptr, state_current * state_size + i + 1); + cell_ptr = state_current + cast(ptr, i + 1); cell = load_ptr(u8, cell_ptr); table_index = table_index * cast(u8, 2) + cell; - cell_ptr = table_base + cast(ptr, table_index); + cell_ptr = table + cast(ptr, table_index); cell = load_ptr(u8, cell_ptr); - cell_ptr = states_base + cast(ptr, state_next * state_size + i); + cell_ptr = state_next + cast(ptr, i); store_ptr(u8, cell_ptr, cell); i = i + 1; @@ -91,12 +52,42 @@ proc next_state() { state_current = state_next; } +var heap_base: ptr; + proc main() { - init(); + # Init lookup table + var table_base: ptr = heap_base; + var table_size: i64 = 8; + store_ptr(u8, table_base + cast(ptr, 0), cast(u8, 0)); + store_ptr(u8, table_base + cast(ptr, 1), cast(u8, 1)); + store_ptr(u8, table_base + cast(ptr, 2), cast(u8, 1)); + store_ptr(u8, table_base + cast(ptr, 3), cast(u8, 1)); + store_ptr(u8, table_base + cast(ptr, 4), cast(u8, 0)); + store_ptr(u8, table_base + cast(ptr, 5), cast(u8, 1)); + store_ptr(u8, table_base + cast(ptr, 6), cast(u8, 1)); + store_ptr(u8, table_base + cast(ptr, 7), cast(u8, 0)); + + # Init 2 state buffers + var state_size: i64 = 30; + var state_current: i64 = 0; + var states_base: ptr = table_base + cast(ptr, table_size); + store_ptr(u8, states_base + cast(ptr, state_size - 2), cast(u8, 1)); + + # Display buffer + var display_base: ptr = states_base + cast(ptr, state_size * 2); + + var i: i64 = 0; while i < state_size - 2 { - print_state_current(); - next_state(); + print_state(states_base + cast(ptr, state_size * state_current), + state_size, + display_base); + var state_next: i64 = 1 - state_current; + next_state(states_base + cast(ptr, state_size * state_current), + states_base + cast(ptr, state_size * state_next), + state_size, + table_base); + state_current = state_next; i = i + 1; } } diff --git a/bang/src/bang_compiler.c b/bang/src/bang_compiler.c index 9fe66f7..004b275 100644 --- a/bang/src/bang_compiler.c +++ b/bang/src/bang_compiler.c @@ -632,6 +632,24 @@ void compile_proc_def_into_basm(Bang *bang, Basm *basm, Bang_Proc_Def proc_def) bang->procs[bang->procs_count++] = proc; bang_push_new_scope(bang); + + for (size_t i = proc.params.size; i > 0; --i) { + Bang_Proc_Param param = proc.params.items[i - 1]; + Bang_Type type = 0; + if (!bang_type_by_name(param.type_name, &type)) { + bang_diag_msg(param.loc, BANG_DIAG_ERROR, + "type `"SV_Fmt"` does not exist", + SV_Arg(param.type_name)); + exit(1); + } + Compiled_Var var = compile_var_into_basm(bang, basm, param.loc, param.name, type, BANG_VAR_STACK_STORAGE); + + basm_push_inst(basm, INST_SWAP, word_u64(1)); + compile_get_var_addr(bang, basm, &var); + basm_push_inst(basm, INST_SWAP, word_u64(1)); + compile_typed_write(basm, var.type); + } + compile_block_into_basm(bang, basm, proc_def.body); bang_pop_scope(bang); @@ -720,18 +738,10 @@ void bang_prepare_var_stack(Bang *bang, Basm *basm, size_t stack_size) bang->stack_frame_var_addr = basm_push_buffer_to_memory(basm, (uint8_t*) &stack_start_addr, ptr_def.size).as_u64; } -void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Bang_Var_Storage storage) +Compiled_Var compile_var_into_basm(Bang *bang, Basm *basm, Bang_Loc loc, String_View name, Bang_Type type, Bang_Var_Storage storage) { - Bang_Type type = 0; - if (!bang_type_by_name(var_def.type_name, &type)) { - bang_diag_msg(var_def.loc, BANG_DIAG_ERROR, - "type `"SV_Fmt"` does not exist", - SV_Arg(var_def.type_name)); - exit(1); - } - if (type == BANG_TYPE_VOID) { - bang_diag_msg(var_def.loc, BANG_DIAG_ERROR, + bang_diag_msg(loc, BANG_DIAG_ERROR, "defining variables with type %s is not allowed", bang_type_def(type).name); exit(1); @@ -739,11 +749,11 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban // Existing Var Error { - Compiled_Var *existing_var = bang_scope_get_compiled_var_by_name(bang->scope, var_def.name); + Compiled_Var *existing_var = bang_scope_get_compiled_var_by_name(bang->scope, name); if (existing_var) { - bang_diag_msg(var_def.loc, BANG_DIAG_ERROR, + bang_diag_msg(loc, BANG_DIAG_ERROR, "variable `"SV_Fmt"` is already defined", - SV_Arg(var_def.name)); + SV_Arg(name)); bang_diag_msg(existing_var->loc, BANG_DIAG_ERROR, "the first definition is located here"); exit(1); @@ -754,11 +764,11 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban // Shadowed Var Warning { - Compiled_Var *shadowed_var = bang_get_compiled_var_by_name(bang, var_def.name); + Compiled_Var *shadowed_var = bang_get_compiled_var_by_name(bang, name); if (shadowed_var) { - bang_diag_msg(var_def.loc, bang->warnings_as_errors ? BANG_DIAG_ERROR : BANG_DIAG_WARNING, + bang_diag_msg(loc, bang->warnings_as_errors ? BANG_DIAG_ERROR : BANG_DIAG_WARNING, "variable `"SV_Fmt"` is shadowing another variable with the same name", - SV_Arg(var_def.name)); + SV_Arg(name)); bang_diag_msg(shadowed_var->loc, BANG_DIAG_NOTE, "the shadowed variable is located here"); @@ -769,8 +779,8 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban } Compiled_Var new_var = {0}; - new_var.name = var_def.name; - new_var.loc = var_def.loc; + new_var.name = name; + new_var.loc = loc; new_var.type = type; new_var.storage = storage; @@ -779,7 +789,40 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban switch (storage) { case BANG_VAR_STATIC_STORAGE: { new_var.addr = basm_push_byte_array_to_memory(basm, type_def.size, 0).as_u64; + } + break; + + case BANG_VAR_STACK_STORAGE: { + assert(type_def.size > 0); + bang->frame_size += type_def.size; + new_var.addr = bang->frame_size; + } + break; + default: + assert(false && "unreachable"); + exit(1); + } + + bang_scope_push_var(bang->scope, new_var); + + return new_var; +} + +void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Bang_Var_Storage storage) +{ + Bang_Type type = 0; + if (!bang_type_by_name(var_def.type_name, &type)) { + bang_diag_msg(var_def.loc, BANG_DIAG_ERROR, + "type `"SV_Fmt"` does not exist", + SV_Arg(var_def.type_name)); + exit(1); + } + + Compiled_Var new_var = compile_var_into_basm(bang, basm, var_def.loc, var_def.name, type, storage); + + switch (storage) { + case BANG_VAR_STATIC_STORAGE: { // TODO(#476): global variables cannot be initialized at the moment if (var_def.has_init) { bang_diag_msg(var_def.loc, BANG_DIAG_ERROR, @@ -790,10 +833,6 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban break; case BANG_VAR_STACK_STORAGE: { - assert(type_def.size > 0); - bang->frame_size += type_def.size; - new_var.addr = bang->frame_size; - if (var_def.has_init) { compile_get_var_addr(bang, basm, &new_var); @@ -815,8 +854,6 @@ void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Ban assert(false && "unreachable"); exit(1); } - - bang_scope_push_var(bang->scope, new_var); } void compile_push_new_frame(Bang *bang, Basm *basm) @@ -876,3 +913,8 @@ void bang_pop_scope(Bang *bang) bang->scope = bang->scope->parent; } + +// TODO: bang should fail compilation if main function accepts any arguments +// Right now the compiler generates the code that tries to accept the arguments +// and corrupts the stack because of that +// TODO: bang does not support procedures that return results diff --git a/bang/src/bang_compiler.h b/bang/src/bang_compiler.h index 6769f55..5e3417f 100644 --- a/bang/src/bang_compiler.h +++ b/bang/src/bang_compiler.h @@ -107,6 +107,7 @@ 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); +Compiled_Var compile_var_into_basm(Bang *bang, Basm *basm, Bang_Loc loc, String_View name, Bang_Type type, Bang_Var_Storage storage); void compile_var_def_into_basm(Bang *bang, Basm *basm, Bang_Var_Def var_def, Bang_Var_Storage storage); 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);