From 65dedbb1caaa785a444d32a7a15adaf6c396b07f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 16 Feb 2022 11:54:15 +0000 Subject: Add `#subtype` struct field prefix, required to have a COM interface hierarchy --- src/parser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 0914c77ca..b55d745f1 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3504,12 +3504,13 @@ enum FieldPrefixKind : i32 { FieldPrefix_Unknown = -1, FieldPrefix_Invalid = 0, - FieldPrefix_using, + FieldPrefix_using, // implies #subtype FieldPrefix_const, FieldPrefix_no_alias, FieldPrefix_c_vararg, FieldPrefix_auto_cast, FieldPrefix_any_int, + FieldPrefix_subtype, // does not imply `using` semantics }; struct ParseFieldPrefixMapping { @@ -3526,6 +3527,7 @@ gb_global ParseFieldPrefixMapping parse_field_prefix_mappings[] = { {str_lit("c_vararg"), Token_Hash, FieldPrefix_c_vararg, FieldFlag_c_vararg}, {str_lit("const"), Token_Hash, FieldPrefix_const, FieldFlag_const}, {str_lit("any_int"), Token_Hash, FieldPrefix_any_int, FieldFlag_any_int}, + {str_lit("subtype"), Token_Hash, FieldPrefix_subtype, FieldFlag_subtype}, }; -- cgit v1.2.3 From 71df46456a4db2592e8cebbdd4c46dc8b58b5a24 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 18 Feb 2022 21:30:25 +0000 Subject: Minimize memory usage by having an arena per thread rather than an arena per file --- src/array.cpp | 4 +++- src/checker.cpp | 4 ++-- src/common.cpp | 2 +- src/main.cpp | 2 +- src/parser.cpp | 12 ++++++------ src/parser.hpp | 6 ++---- 6 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/array.cpp b/src/array.cpp index ac3727978..d08bd647f 100644 --- a/src/array.cpp +++ b/src/array.cpp @@ -89,7 +89,9 @@ template void slice_init(Slice *s, gbAllocator const &allocator, isize count) { GB_ASSERT(count >= 0); s->data = gb_alloc_array(allocator, T, count); - GB_ASSERT(s->data != nullptr); + if (count > 0) { + GB_ASSERT(s->data != nullptr); + } s->count = count; } diff --git a/src/checker.cpp b/src/checker.cpp index f8aa8d45b..f440b7c9a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -225,8 +225,8 @@ bool decl_info_has_init(DeclInfo *d) { Scope *create_scope(CheckerInfo *info, Scope *parent, isize init_elements_capacity=DEFAULT_SCOPE_CAPACITY) { Scope *s = gb_alloc_item(permanent_allocator(), Scope); s->parent = parent; - string_map_init(&s->elements, permanent_allocator(), init_elements_capacity); - ptr_set_init(&s->imported, permanent_allocator(), 0); + string_map_init(&s->elements, heap_allocator(), init_elements_capacity); + ptr_set_init(&s->imported, heap_allocator(), 0); mutex_init(&s->mutex); if (parent != nullptr && parent != builtin_pkg->scope) { diff --git a/src/common.cpp b/src/common.cpp index ab2a46118..d3ee95b76 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -1021,7 +1021,7 @@ LoadedFileError load_file_32(char const *fullpath, LoadedFile *memory_mapped_fil #endif } - gbFileContents fc = gb_file_read_contents(heap_allocator(), true, fullpath); + gbFileContents fc = gb_file_read_contents(permanent_allocator(), true, fullpath); if (fc.size > I32_MAX) { err = LoadedFile_FileTooLarge; diff --git a/src/main.cpp b/src/main.cpp index 014fbf822..291b56996 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2577,7 +2577,7 @@ int main(int arg_count, char const **arg_ptr) { // NOTE(bill): add 'shared' directory if it is not already set if (!find_library_collection_path(str_lit("shared"), nullptr)) { add_library_collection(str_lit("shared"), - get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("shared"))); + get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("shared"))); } diff --git a/src/parser.cpp b/src/parser.cpp index 7309d9769..8a7ab2d20 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -57,6 +57,9 @@ isize ast_node_size(AstKind kind) { return align_formula_isize(gb_size_of(AstCommonStuff) + ast_variant_sizes[kind], gb_align_of(void *)); } + +gb_global std::atomic global_total_node_memory_allocated; + // NOTE(bill): And this below is why is I/we need a new language! Discriminated unions are a pain in C/C++ Ast *alloc_ast_node(AstFile *f, AstKind kind) { gbAllocator a = ast_allocator(f); @@ -66,6 +69,9 @@ Ast *alloc_ast_node(AstFile *f, AstKind kind) { Ast *node = cast(Ast *)gb_alloc(a, size); node->kind = kind; node->file_id = f ? f->id : 0; + + global_total_node_memory_allocated += size; + return node; } @@ -4851,12 +4857,6 @@ ParseFileError init_ast_file(AstFile *f, String fullpath, TokenPos *err_pos) { f->prev_token = f->tokens[f->prev_token_index]; f->curr_token = f->tokens[f->curr_token_index]; - isize const page_size = 4*1024; - isize block_size = 2*f->tokens.count*gb_size_of(Ast); - block_size = ((block_size + page_size-1)/page_size) * page_size; - block_size = gb_clamp(block_size, page_size, DEFAULT_MINIMUM_BLOCK_SIZE); - f->arena.minimum_block_size = block_size; - array_init(&f->comments, heap_allocator(), 0, 0); array_init(&f->imports, heap_allocator(), 0, 0); diff --git a/src/parser.hpp b/src/parser.hpp index 83c755553..f6791a291 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -97,8 +97,6 @@ struct AstFile { AstPackage * pkg; Scope * scope; - Arena arena; - Ast * pkg_decl; String fullpath; Tokenizer tokenizer; @@ -801,10 +799,10 @@ gb_inline bool is_ast_when_stmt(Ast *node) { return node->kind == Ast_WhenStmt; } -gb_global gb_thread_local Arena global_ast_arena = {}; +gb_global gb_thread_local Arena global_thread_local_ast_arena = {}; gbAllocator ast_allocator(AstFile *f) { - Arena *arena = f ? &f->arena : &global_ast_arena; + Arena *arena = &global_thread_local_ast_arena; return arena_allocator(arena); } -- cgit v1.2.3 From cad753e3986183fa180abae480a85432b4b36af1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 22 Feb 2022 22:53:13 +0000 Subject: Simplify `parse_binary_expr` --- src/parser.cpp | 157 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 109 insertions(+), 48 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 8a7ab2d20..c214df782 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3013,66 +3013,127 @@ i32 token_precedence(AstFile *f, TokenKind t) { return 0; } +// Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) { +// Ast *expr = parse_unary_expr(f, lhs); +// for (i32 prec = token_precedence(f, f->curr_token.kind); prec >= prec_in; prec--) { +// for (;;) { +// Token op = f->curr_token; +// i32 op_prec = token_precedence(f, op.kind); +// if (op_prec != prec) { +// // NOTE(bill): This will also catch operators that are not valid "binary" operators +// break; +// } +// Token prev = f->prev_token; +// switch (op.kind) { +// case Token_if: +// case Token_when: +// if (prev.pos.line < op.pos.line) { +// // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition +// goto loop_end; +// } +// break; +// } +// expect_operator(f); // NOTE(bill): error checks too + +// if (op.kind == Token_Question) { +// Ast *cond = expr; +// // Token_Question +// Ast *x = parse_expr(f, lhs); +// Token token_c = expect_token(f, Token_Colon); +// Ast *y = parse_expr(f, lhs); +// expr = ast_ternary_if_expr(f, x, cond, y); +// } else if (op.kind == Token_if || op.kind == Token_when) { +// Ast *x = expr; +// Ast *cond = parse_expr(f, lhs); +// Token tok_else = expect_token(f, Token_else); +// Ast *y = parse_expr(f, lhs); + +// switch (op.kind) { +// case Token_if: +// expr = ast_ternary_if_expr(f, x, cond, y); +// break; +// case Token_when: +// expr = ast_ternary_when_expr(f, x, cond, y); +// break; +// } +// } else { +// Ast *right = parse_binary_expr(f, false, prec+1); +// if (right == nullptr) { +// syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string)); +// } +// if (op.kind == Token_or_else) { +// // NOTE(bill): easier to handle its logic different with its own AST kind +// expr = ast_or_else_expr(f, expr, op, right); +// } else { +// expr = ast_binary_expr(f, op, expr, right); +// } +// } + +// lhs = false; +// } +// loop_end:; +// } +// return expr; +// } + Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) { Ast *expr = parse_unary_expr(f, lhs); - for (i32 prec = token_precedence(f, f->curr_token.kind); prec >= prec_in; prec--) { - for (;;) { - Token op = f->curr_token; - i32 op_prec = token_precedence(f, op.kind); - if (op_prec != prec) { - // NOTE(bill): This will also catch operators that are not valid "binary" operators - break; + for (;;) { + Token op = f->curr_token; + i32 op_prec = token_precedence(f, op.kind); + if (op_prec < prec_in) { + // NOTE(bill): This will also catch operators that are not valid "binary" operators + break; + } + Token prev = f->prev_token; + switch (op.kind) { + case Token_if: + case Token_when: + if (prev.pos.line < op.pos.line) { + // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition + goto loop_end; } - Token prev = f->prev_token; + break; + } + expect_operator(f); // NOTE(bill): error checks too + + if (op.kind == Token_Question) { + Ast *cond = expr; + // Token_Question + Ast *x = parse_expr(f, lhs); + Token token_c = expect_token(f, Token_Colon); + Ast *y = parse_expr(f, lhs); + expr = ast_ternary_if_expr(f, x, cond, y); + } else if (op.kind == Token_if || op.kind == Token_when) { + Ast *x = expr; + Ast *cond = parse_expr(f, lhs); + Token tok_else = expect_token(f, Token_else); + Ast *y = parse_expr(f, lhs); + switch (op.kind) { case Token_if: + expr = ast_ternary_if_expr(f, x, cond, y); + break; case Token_when: - if (prev.pos.line < op.pos.line) { - // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition - goto loop_end; - } + expr = ast_ternary_when_expr(f, x, cond, y); break; } - expect_operator(f); // NOTE(bill): error checks too - - if (op.kind == Token_Question) { - Ast *cond = expr; - // Token_Question - Ast *x = parse_expr(f, lhs); - Token token_c = expect_token(f, Token_Colon); - Ast *y = parse_expr(f, lhs); - expr = ast_ternary_if_expr(f, x, cond, y); - } else if (op.kind == Token_if || op.kind == Token_when) { - Ast *x = expr; - Ast *cond = parse_expr(f, lhs); - Token tok_else = expect_token(f, Token_else); - Ast *y = parse_expr(f, lhs); - - switch (op.kind) { - case Token_if: - expr = ast_ternary_if_expr(f, x, cond, y); - break; - case Token_when: - expr = ast_ternary_when_expr(f, x, cond, y); - break; - } + } else { + Ast *right = parse_binary_expr(f, false, op_prec+1); + if (right == nullptr) { + syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string)); + } + if (op.kind == Token_or_else) { + // NOTE(bill): easier to handle its logic different with its own AST kind + expr = ast_or_else_expr(f, expr, op, right); } else { - Ast *right = parse_binary_expr(f, false, prec+1); - if (right == nullptr) { - syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string)); - } - if (op.kind == Token_or_else) { - // NOTE(bill): easier to handle its logic different with its own AST kind - expr = ast_or_else_expr(f, expr, op, right); - } else { - expr = ast_binary_expr(f, op, expr, right); - } + expr = ast_binary_expr(f, op, expr, right); } - - lhs = false; } - loop_end:; + + lhs = false; } + loop_end:; return expr; } -- cgit v1.2.3 From 62d232d798fff25597b6e3591c6a178c32fa440e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 22 Feb 2022 22:59:00 +0000 Subject: Correct `ExactValue_Pointer` --- src/exact_value.cpp | 17 ++++++++++++--- src/parser.cpp | 63 ----------------------------------------------------- 2 files changed, 14 insertions(+), 66 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/exact_value.cpp b/src/exact_value.cpp index fd90278e5..3dae96853 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -630,6 +630,9 @@ void match_exact_values(ExactValue *x, ExactValue *y) { case ExactValue_Bool: case ExactValue_String: case ExactValue_Quaternion: + case ExactValue_Pointer: + case ExactValue_Procedure: + case ExactValue_Typeid: return; case ExactValue_Integer: @@ -671,9 +674,6 @@ void match_exact_values(ExactValue *x, ExactValue *y) { return; } break; - - case ExactValue_Procedure: - return; } compiler_error("match_exact_values: How'd you get here? Invalid ExactValueKind %d", x->kind); @@ -932,6 +932,17 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) { break; } + case ExactValue_Pointer: { + switch (op) { + case Token_CmpEq: return x.value_pointer == y.value_pointer; + case Token_NotEq: return x.value_pointer != y.value_pointer; + case Token_Lt: return x.value_pointer < y.value_pointer; + case Token_LtEq: return x.value_pointer <= y.value_pointer; + case Token_Gt: return x.value_pointer > y.value_pointer; + case Token_GtEq: return x.value_pointer >= y.value_pointer; + } + } + case ExactValue_Typeid: switch (op) { case Token_CmpEq: return are_types_identical(x.value_typeid, y.value_typeid); diff --git a/src/parser.cpp b/src/parser.cpp index c214df782..9659e8c18 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3013,69 +3013,6 @@ i32 token_precedence(AstFile *f, TokenKind t) { return 0; } -// Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) { -// Ast *expr = parse_unary_expr(f, lhs); -// for (i32 prec = token_precedence(f, f->curr_token.kind); prec >= prec_in; prec--) { -// for (;;) { -// Token op = f->curr_token; -// i32 op_prec = token_precedence(f, op.kind); -// if (op_prec != prec) { -// // NOTE(bill): This will also catch operators that are not valid "binary" operators -// break; -// } -// Token prev = f->prev_token; -// switch (op.kind) { -// case Token_if: -// case Token_when: -// if (prev.pos.line < op.pos.line) { -// // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition -// goto loop_end; -// } -// break; -// } -// expect_operator(f); // NOTE(bill): error checks too - -// if (op.kind == Token_Question) { -// Ast *cond = expr; -// // Token_Question -// Ast *x = parse_expr(f, lhs); -// Token token_c = expect_token(f, Token_Colon); -// Ast *y = parse_expr(f, lhs); -// expr = ast_ternary_if_expr(f, x, cond, y); -// } else if (op.kind == Token_if || op.kind == Token_when) { -// Ast *x = expr; -// Ast *cond = parse_expr(f, lhs); -// Token tok_else = expect_token(f, Token_else); -// Ast *y = parse_expr(f, lhs); - -// switch (op.kind) { -// case Token_if: -// expr = ast_ternary_if_expr(f, x, cond, y); -// break; -// case Token_when: -// expr = ast_ternary_when_expr(f, x, cond, y); -// break; -// } -// } else { -// Ast *right = parse_binary_expr(f, false, prec+1); -// if (right == nullptr) { -// syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string)); -// } -// if (op.kind == Token_or_else) { -// // NOTE(bill): easier to handle its logic different with its own AST kind -// expr = ast_or_else_expr(f, expr, op, right); -// } else { -// expr = ast_binary_expr(f, op, expr, right); -// } -// } - -// lhs = false; -// } -// loop_end:; -// } -// return expr; -// } - Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) { Ast *expr = parse_unary_expr(f, lhs); for (;;) { -- cgit v1.2.3 From d4ccb69ccc56fb57cad48493a9e5e78ca3529a84 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 21:49:19 +0000 Subject: Check if directory exists with the same target executable name when building a directory --- src/parser.cpp | 16 ++++++++++++++++ src/parser.hpp | 1 + 2 files changed, 17 insertions(+) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 9659e8c18..f70afe346 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -5719,6 +5719,22 @@ ParseFileError parse_packages(Parser *p, String init_filename) { error_line("Expected either a directory or a .odin file, got '%.*s'\n", LIT(init_filename)); return ParseFile_WrongExtension; } + } else if (init_fullpath.len != 0) { + String path = init_fullpath; + if (path[path.len-1] == '/') { + path.len -= 1; + } + if ((build_context.command_kind & Command__does_build) && + build_context.build_mode == BuildMode_Executable) { + String short_path = filename_from_path(path); + char *cpath = alloc_cstring(heap_allocator(), short_path); + defer (gb_free(heap_allocator(), cpath)); + + if (gb_file_exists(cpath)) { + error_line("Please specify the executable name with -out: as a directory exists with the same name in the current working directory"); + return ParseFile_DirectoryAlreadyExists; + } + } } diff --git a/src/parser.hpp b/src/parser.hpp index f6791a291..c33d1520b 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -46,6 +46,7 @@ enum ParseFileError { ParseFile_InvalidToken, ParseFile_GeneralError, ParseFile_FileTooLarge, + ParseFile_DirectoryAlreadyExists, ParseFile_Count, }; -- cgit v1.2.3 From fad851d80c4d2ded5eba6b766ca00d90893c73aa Mon Sep 17 00:00:00 2001 From: Sébastien Marie Date: Thu, 3 Mar 2022 15:57:51 +0000 Subject: check for semi-colon before EOF too --- src/parser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index f70afe346..94a585f35 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1538,7 +1538,7 @@ void fix_advance_to_next_stmt(AstFile *f) { Token expect_closing(AstFile *f, TokenKind kind, String context) { if (f->curr_token.kind != kind && f->curr_token.kind == Token_Semicolon && - f->curr_token.string == "\n") { + (f->curr_token.string == "\n" || f->curr_token.kind == Token_EOF)) { Token tok = f->prev_token; tok.pos.column += cast(i32)tok.string.len; syntax_error(tok, "Missing ',' before newline in %.*s", LIT(context)); @@ -1560,6 +1560,7 @@ void assign_removal_flag_to_semicolon(AstFile *f) { switch (curr_token->kind) { case Token_CloseBrace: case Token_CloseParen: + case Token_EOF: ok = true; break; } -- cgit v1.2.3