diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-02-11 17:33:23 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-02-11 17:33:23 +0000 |
| commit | 4306345ff10e9f8225b156633aa986fee3f97987 (patch) | |
| tree | a40e1363f48fe4d77111fcea0bf36b4f0ab3802f | |
| parent | 346aa5f71ca4e3d6a71187024f809eaf2fc6da1b (diff) | |
Dynamic array syntax [...]Type; make entities private with a prefix of `_`; fix extension checking
| -rw-r--r-- | code/demo.odin | 43 | ||||
| -rw-r--r-- | core/_preload.odin | 2 | ||||
| -rw-r--r-- | core/atomic.odin | 2 | ||||
| -rw-r--r-- | core/fmt.odin | 22 | ||||
| -rw-r--r-- | core/sys/windows.odin | 4 | ||||
| -rw-r--r-- | src/check_expr.c | 57 | ||||
| -rw-r--r-- | src/checker.c | 40 | ||||
| -rw-r--r-- | src/common.c | 1 | ||||
| -rw-r--r-- | src/entity.c | 9 | ||||
| -rw-r--r-- | src/main.c | 1 | ||||
| -rw-r--r-- | src/parser.c | 13 | ||||
| -rw-r--r-- | src/string.c | 33 | ||||
| -rw-r--r-- | src/tokenizer.c | 8 | ||||
| -rw-r--r-- | src/unicode.c | 25 |
14 files changed, 172 insertions, 88 deletions
diff --git a/code/demo.odin b/code/demo.odin index 0f4488f4d..401853f1d 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,4 +1,13 @@ -#import "fmt.odin"; +#import . "fmt.odin"; +#import "atomic.odin"; +#import "hash.odin"; +#import "math.odin"; +#import "mem.odin"; +#import "opengl.odin"; +#import "os.odin"; +#import "sync.odin"; +#import "types.odin"; +#import "utf8.odin"; main :: proc() { @@ -8,7 +17,7 @@ main :: proc() { BANANA, COCONUT, } - fmt.println(Fruit.names); + println(x, Fruit.names); } when false { @@ -24,16 +33,16 @@ when false { c := m[3.0]; assert(ok && c == 564); - fmt.print("map["); + print("map["); i := 0; for val, key in m { if i > 0 { - fmt.print(", "); + print(", "); } - fmt.printf("%v=%v", key, val); + printf("%v=%v", key, val); i += 1; } - fmt.println("]"); + println("]"); } { m := map[string]u32{ @@ -47,11 +56,11 @@ when false { _, ok := m["c"]; assert(ok && c == 7654); - fmt.println(m); + println(m); } { - fmt.println("Hellope!"); + println("Hellope!"); x: [dynamic]f64; reserve(x, 16); @@ -59,24 +68,24 @@ when false { append(x, 2_000_000.500_000, 3, 5, 7); for p, i in x { - if i > 0 { fmt.print(", "); } - fmt.print(p); + if i > 0 { print(", "); } + print(p); } - fmt.println(); + println(); { Vec3 :: [vector 3]f32; x := Vec3{1, 2, 3}; y := Vec3{4, 5, 6}; - fmt.println(x < y); - fmt.println(x + y); - fmt.println(x - y); - fmt.println(x * y); - fmt.println(x / y); + println(x < y); + println(x + y); + println(x - y); + println(x * y); + println(x / y); for i in x { - fmt.println(i); + println(i); } } } diff --git a/core/_preload.odin b/core/_preload.odin index 5938fc362..8924bf87c 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -373,7 +373,7 @@ Raw_Dynamic_Array :: struct #ordered { }; Raw_Dynamic_Map :: struct #ordered { - hashes: [dynamic]int, + hashes: [...]int, entries: Raw_Dynamic_Array, }; diff --git a/core/atomic.odin b/core/atomic.odin index 3be3c1d40..3db437a4b 100644 --- a/core/atomic.odin +++ b/core/atomic.odin @@ -5,7 +5,7 @@ _ := compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version -yield_thread :: proc() { win32._mm_pause(); } +yield_thread :: proc() { win32.mm_pause(); } mfence :: proc() { win32.ReadWriteBarrier(); } sfence :: proc() { win32.WriteBarrier(); } lfence :: proc() { win32.ReadBarrier(); } diff --git a/core/fmt.odin b/core/fmt.odin index caa17f77d..d990fcada 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -3,7 +3,8 @@ #import "utf8.odin"; #import "types.odin"; -DEFAULT_BUFFER_SIZE :: 1<<12; + +_BUFFER_SIZE :: 1<<12; Buffer :: struct { data: []byte, @@ -60,7 +61,7 @@ Fmt_Info :: struct { fprint :: proc(fd: os.Handle, args: ...any) -> int { - data: [DEFAULT_BUFFER_SIZE]byte; + data: [_BUFFER_SIZE]byte; buf := Buffer{data[:], 0}; bprint(^buf, ...args); os.write(fd, buf.data[:buf.length]); @@ -68,14 +69,14 @@ fprint :: proc(fd: os.Handle, args: ...any) -> int { } fprintln :: proc(fd: os.Handle, args: ...any) -> int { - data: [DEFAULT_BUFFER_SIZE]byte; + data: [_BUFFER_SIZE]byte; buf := Buffer{data[:], 0}; bprintln(^buf, ...args); os.write(fd, buf.data[:buf.length]); return buf.length; } fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int { - data: [DEFAULT_BUFFER_SIZE]byte; + data: [_BUFFER_SIZE]byte; buf := Buffer{data[:], 0}; bprintf(^buf, fmt, ...args); os.write(fd, buf.data[:buf.length]); @@ -95,7 +96,7 @@ printf :: proc(fmt: string, args: ...any) -> int { fprint_type :: proc(fd: os.Handle, info: ^Type_Info) { - data: [DEFAULT_BUFFER_SIZE]byte; + data: [_BUFFER_SIZE]byte; buf := Buffer{data[:], 0}; buffer_write_type(^buf, info); os.write(fd, buf.data[:buf.length]); @@ -174,8 +175,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { buffer_write_string(buf, "]"); buffer_write_type(buf, info.elem); case Dynamic_Array: - buffer_write_string(buf, "[dynamic"); - buffer_write_string(buf, "]"); + buffer_write_string(buf, "[...]"); buffer_write_type(buf, info.elem); case Slice: buffer_write_string(buf, "["); @@ -316,7 +316,7 @@ parse_int :: proc(s: string, offset: int) -> (int, int, bool) { return result, offset+i, i != 0; } -arg_number :: proc(fi: ^Fmt_Info, arg_index: int, format: string, offset: int, arg_count: int) -> (int, int, bool) { +_arg_number :: proc(fi: ^Fmt_Info, arg_index: int, format: string, offset: int, arg_count: int) -> (int, int, bool) { parse_arg_number :: proc(format: string) -> (int, int, bool) { if format.count < 3 { return 0, 1, false; @@ -961,7 +961,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ...any) -> int { } } - arg_index, i, was_prev_index = arg_number(^fi, arg_index, fmt, i, args.count); + arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, args.count); // Width if i < end && fmt[i] == '*' { @@ -991,7 +991,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ...any) -> int { fi.good_arg_index = false; } if i < end && fmt[i] == '*' { - arg_index, i, was_prev_index = arg_number(^fi, arg_index, fmt, i, args.count); + arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, args.count); i += 1; fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index); if fi.prec < 0 { @@ -1012,7 +1012,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ...any) -> int { } if !was_prev_index { - arg_index, i, was_prev_index = arg_number(^fi, arg_index, fmt, i, args.count); + arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, args.count); } if i >= end { diff --git a/core/sys/windows.odin b/core/sys/windows.odin index a8a88bf7b..4c32cbd3e 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -22,7 +22,7 @@ BOOL :: i32; WNDPROC :: #type proc(HWND, u32, WPARAM, LPARAM) -> LRESULT #cc_c; -INVALID_HANDLE_VALUE :: cast(HANDLE)(~cast(int)0); +INVALID_HANDLE_VALUE :: cast(HANDLE)~cast(int)0; FALSE: BOOL : 0; TRUE: BOOL : 1; @@ -288,7 +288,7 @@ InterlockedExchangeAdd64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign ke InterlockedAnd64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32; InterlockedOr64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32; -_mm_pause :: proc() #foreign kernel32; +mm_pause :: proc() #foreign kernel32 "_mm_pause"; ReadWriteBarrier :: proc() #foreign kernel32; WriteBarrier :: proc() #foreign kernel32; ReadBarrier :: proc() #foreign kernel32; diff --git a/src/check_expr.c b/src/check_expr.c index bec36496f..a6a07b140 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1081,6 +1081,11 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) { return 0; } Operand o = {0}; + if (e->kind == AstNode_UnaryExpr && + e->UnaryExpr.op.kind == Token_Question) { + return -1; + } + check_expr(c, &o, e); if (o.mode != Addressing_Constant) { if (o.mode != Addressing_Invalid) { @@ -1314,7 +1319,12 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { case_ast_node(at, ArrayType, e); if (at->count != NULL) { Type *elem = check_type_extra(c, at->elem, NULL); - type = make_type_array(c->allocator, elem, check_array_or_map_count(c, at->count, false)); + i64 count = check_array_or_map_count(c, at->count, false); + if (count < 0) { + error_node(at->count, "? can only be used in conjuction with compound literals"); + count = 0; + } + type = make_type_array(c->allocator, elem, count); } else { Type *elem = check_type(c, at->elem); type = make_type_slice(c->allocator, elem); @@ -2529,8 +2539,11 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h add_entity_use(c, op_expr, e); expr_entity = e; - if (e != NULL && e->kind == Entity_ImportName && - selector->kind == AstNode_Ident) { + if (e != NULL && e->kind == Entity_ImportName && selector->kind == AstNode_Ident) { + // IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile + // It pretty much needs to be in this order and this way + // If you can clean this up, please do but be really careful + String sel_name = selector->Ident.string; check_op_expr = false; @@ -2539,8 +2552,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (is_declared) { if (entity->kind == Entity_Builtin) { is_declared = false; - } - if (entity->scope->is_global && !e->ImportName.scope->is_global) { + } else if (entity->scope->is_global && !e->ImportName.scope->is_global) { is_declared = false; } } @@ -2564,6 +2576,17 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } } + + is_not_exported = !is_entity_name_exported(entity); + + if (is_not_exported) { + gbString sel_str = expr_to_string(selector); + error_node(op_expr, "`%s` is not exported by `%.*s`", sel_str, LIT(name)); + gb_string_free(sel_str); + // NOTE(bill): We will have to cause an error his even though it exists + goto error; + } + if (is_overloaded) { Scope *s = entity->scope; bool skip = false; @@ -2608,7 +2631,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } bool *found = map_bool_get(&e->ImportName.scope->implicit, hash_pointer(entity)); - if (!found) { is_not_exported = false; } else { @@ -4479,16 +4501,18 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(cl, CompoundLit, node); Type *type = type_hint; - bool ellipsis_array = false; + bool is_to_be_determined_array_count = false; bool is_constant = true; if (cl->type != NULL) { type = NULL; // [..]Type if (cl->type->kind == AstNode_ArrayType && cl->type->ArrayType.count != NULL) { - if (cl->type->ArrayType.count->kind == AstNode_Ellipsis) { + AstNode *count = cl->type->ArrayType.count; + if (count->kind == AstNode_UnaryExpr && + count->UnaryExpr.op.kind == Token_Question) { type = make_type_array(c->allocator, check_type(c, cl->type->ArrayType.elem), -1); - ellipsis_array = true; + is_to_be_determined_array_count = true; } } @@ -4663,7 +4687,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } } - if (t->kind == Type_Array && ellipsis_array) { + if (t->kind == Type_Array && is_to_be_determined_array_count) { t->Array.count = max; } } break; @@ -5185,11 +5209,13 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case AstNode_ProcType: case AstNode_PointerType: case AstNode_ArrayType: + case AstNode_DynamicArrayType: case AstNode_VectorType: case AstNode_StructType: case AstNode_UnionType: case AstNode_RawUnionType: case AstNode_EnumType: + case AstNode_MapType: o->mode = Addressing_Type; o->type = check_type(c, node); break; @@ -5417,7 +5443,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) { case_end; case_ast_node(e, Ellipsis, node); - str = gb_string_appendc(str, ".."); + str = gb_string_appendc(str, "..."); case_end; case_ast_node(fv, FieldValue, node); @@ -5433,13 +5459,18 @@ gbString write_expr_to_string(gbString str, AstNode *node) { case_ast_node(at, ArrayType, node); str = gb_string_appendc(str, "["); - str = write_expr_to_string(str, at->count); + if (at->count->kind == AstNode_UnaryExpr && + at->count->UnaryExpr.op.kind == Token_Hash) { + str = gb_string_appendc(str, "#"); + } else { + str = write_expr_to_string(str, at->count); + } str = gb_string_appendc(str, "]"); str = write_expr_to_string(str, at->elem); case_end; case_ast_node(at, DynamicArrayType, node); - str = gb_string_appendc(str, "[dynamic]"); + str = gb_string_appendc(str, "[...]"); str = write_expr_to_string(str, at->elem); case_end; diff --git a/src/checker.c b/src/checker.c index 0788db920..7f1d74f0d 100644 --- a/src/checker.c +++ b/src/checker.c @@ -1531,6 +1531,8 @@ void check_all_global_entities(Checker *c) { add_curr_ast_file(c, d->scope->file); if (!d->scope->has_been_imported) { + // NOTE(bill): All of these unchecked entities could mean a lot of unused allocations + // TODO(bill): Should this be worried about? continue; } @@ -1567,6 +1569,30 @@ void check_all_global_entities(Checker *c) { } +bool is_string_an_identifier(String s) { + isize offset = 0; + if (s.len < 1) { + return false; + } + while (offset < s.len) { + bool ok = false; + Rune r = -1; + isize size = gb_utf8_decode(s.text+offset, s.len-offset, &r); + if (offset == 0) { + ok = rune_is_letter(r); + } else { + ok = rune_is_letter(r) || rune_is_digit(r); + } + + if (!ok) { + return false; + } + offset += size; + } + + return offset == s.len; +} + String path_to_entity_name(String name, String fullpath) { if (name.len != 0) { return name; @@ -1677,9 +1703,17 @@ void check_import_entities(Checker *c, MapScope *file_scopes) { case Entity_LibraryName: break; default: { - bool ok = add_entity(c, parent_scope, NULL, e); - if (ok && id->is_import) { // `#import`ed entities don't get exported - map_bool_set(&parent_scope->implicit, hash_pointer(e), true); + + if (id->is_import) { + if (is_entity_name_exported(e)) { + // TODO(bill): Should these entities be imported but cause an error when used? + bool ok = add_entity(c, parent_scope, NULL, e); + if (ok) { + map_bool_set(&parent_scope->implicit, hash_pointer(e), true); + } + } + } else { + /* bool ok = */add_entity(c, parent_scope, NULL, e); } } break; } diff --git a/src/common.c b/src/common.c index e2a70f576..f09282b5a 100644 --- a/src/common.c +++ b/src/common.c @@ -6,6 +6,7 @@ gbAllocator heap_allocator(void) { return gb_heap_allocator(); } +#include "unicode.c" #include "string.c" #include "array.c" diff --git a/src/entity.c b/src/entity.c index 44809792f..b571f98e6 100644 --- a/src/entity.c +++ b/src/entity.c @@ -98,6 +98,15 @@ struct Entity { gb_global Entity *e_context = NULL; +bool is_entity_name_exported(Entity *e) { + GB_ASSERT(e != NULL); + String name = e->token.string; + if (name.len == 0) { + return false; + } + return name.text[0] != '_'; +} + Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) { Entity *entity = gb_alloc_item(a, Entity); diff --git a/src/main.c b/src/main.c index 3ff20ac61..41f4adda8 100644 --- a/src/main.c +++ b/src/main.c @@ -4,7 +4,6 @@ extern "C" { #include "common.c" #include "timings.c" -#include "unicode.c" #include "build.c" #include "tokenizer.c" #include "parser.c" diff --git a/src/parser.c b/src/parser.c index 06de58872..b4902982c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1832,6 +1832,7 @@ bool is_literal_type(AstNode *node) { case AstNode_ArrayType: case AstNode_VectorType: case AstNode_StructType: + case AstNode_DynamicArrayType: case AstNode_MapType: return true; } @@ -2575,8 +2576,8 @@ AstNode *parse_type_or_ident(AstFile *f) { AstNode *count_expr = NULL; bool is_vector = false; - if (f->curr_token.kind == Token_Ellipsis) { - count_expr = ast_ellipsis(f, expect_token(f, Token_Ellipsis), NULL); + if (f->curr_token.kind == Token_Question) { + count_expr = ast_unary_expr(f, expect_token(f, Token_Question), NULL); } else if (f->curr_token.kind == Token_vector) { next_token(f); if (f->curr_token.kind != Token_CloseBracket) { @@ -2587,7 +2588,7 @@ AstNode *parse_type_or_ident(AstFile *f) { syntax_error(f->curr_token, "Vector type missing count"); } is_vector = true; - } else if (f->curr_token.kind == Token_dynamic) { + } else if (f->curr_token.kind == Token_Ellipsis) { next_token(f); expect_token(f, Token_CloseBracket); return ast_dynamic_array_type(f, token, parse_type(f)); @@ -3527,6 +3528,7 @@ AstNodeArray parse_stmt_list(AstFile *f) { ParseFileError init_ast_file(AstFile *f, String fullpath) { + fullpath = string_trim_whitespace(fullpath); // Just in case if (!string_has_extension(fullpath, str_lit("odin"))) { return ParseFile_WrongExtension; } @@ -3606,6 +3608,9 @@ void destroy_parser(Parser *p) { bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) { gb_mutex_lock(&p->mutex); + path = string_trim_whitespace(path); + rel_path = string_trim_whitespace(rel_path); + for_array(i, p->imports) { String import = p->imports.e[i].path; if (str_eq(import, path)) { @@ -3786,7 +3791,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) { gb_printf_err("Invalid file extension: File must have the extension `.odin`"); break; case ParseFile_InvalidFile: - gb_printf_err("Invalid file"); + gb_printf_err("Invalid file or cannot be found"); break; case ParseFile_Permission: gb_printf_err("File permissions problem"); diff --git a/src/string.c b/src/string.c index 8558616bf..38874a7d5 100644 --- a/src/string.c +++ b/src/string.c @@ -145,16 +145,37 @@ gb_inline isize string_extension_position(String str) { return dot_pos; } +String string_trim_whitespace(String str) { + while (str.len > 0 && rune_is_whitespace(str.text[str.len-1])) { + str.len--; + } + + while (str.len > 0 && rune_is_whitespace(str.text[0])) { + str.text++; + str.len--; + } + + return str; +} + gb_inline bool string_has_extension(String str, String ext) { - if (str.len > ext.len+1) { - u8 *s = str.text+str.len - ext.len-1; - if (s[0] == '.') { - s++; - return gb_memcompare(s, ext.text, ext.len) == 0; + str = string_trim_whitespace(str); + if (str.len <= ext.len+1) { + return false; + } + isize len = str.len; + for (isize i = len-1; i >= 0; i--) { + if (str.text[i] == '.') { + break; } + len--; + } + if (len == 0) { return false; } - return false; + + u8 *s = str.text + len; + return gb_memcompare(s, ext.text, ext.len) == 0; } bool string_contains_char(String s, u8 c) { diff --git a/src/tokenizer.c b/src/tokenizer.c index 92256f021..766e8b912 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -107,12 +107,12 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_enum, "enum"), \ TOKEN_KIND(Token_vector, "vector"), \ TOKEN_KIND(Token_map, "map"), \ - TOKEN_KIND(Token_static, "static"), \ - TOKEN_KIND(Token_dynamic, "dynamic"), \ + /* TOKEN_KIND(Token_static, "static"), */ \ + /* TOKEN_KIND(Token_dynamic, "dynamic"), */ \ TOKEN_KIND(Token_using, "using"), \ TOKEN_KIND(Token_no_alias, "no_alias"), \ - /* TOKEN_KIND(Token_mutable, "mutable"), */ \ - /* TOKEN_KIND(Token_immutable, "immutable"), */\ + /* TOKEN_KIND(Token_mutable, "mutable"), */ \ + /* TOKEN_KIND(Token_immutable, "immutable"), */ \ TOKEN_KIND(Token_thread_local, "thread_local"), \ TOKEN_KIND(Token_cast, "cast"), \ TOKEN_KIND(Token_transmute, "transmute"), \ diff --git a/src/unicode.c b/src/unicode.c index e4bf28be8..d65f2f2ae 100644 --- a/src/unicode.c +++ b/src/unicode.c @@ -39,28 +39,3 @@ bool rune_is_whitespace(Rune r) { } return false; } - - -bool is_string_an_identifier(String s) { - isize offset = 0; - if (s.len < 1) { - return false; - } - while (offset < s.len) { - bool ok = false; - Rune r = -1; - isize size = gb_utf8_decode(s.text+offset, s.len-offset, &r); - if (offset == 0) { - ok = rune_is_letter(r); - } else { - ok = rune_is_letter(r) || rune_is_digit(r); - } - - if (!ok) { - return false; - } - offset += size; - } - - return offset == s.len; -} |