diff --git a/code/demo.odin b/code/demo.odin index bc193ef1f..2577f8d3c 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -10,17 +10,28 @@ #import ht "http_test.odin"; main :: proc() { + { + Fruit :: enum { + APPLE, + BANANA, + COCONUT, + } + + fmt.println(Fruit.names); + } + +when false { { m: map[f32]int; - reserve(^m, 16); + reserve(m, 16); defer free(m); m[1.0] = 1278; m[2.0] = 7643; m[3.0] = 564; - c := m[3.0]; _, ok := m[3.0]; - // assert(ok && c == 564); + c := m[3.0]; + assert(ok && c == 564); fmt.print("map["); i := 0; @@ -28,7 +39,7 @@ main :: proc() { if i > 0 { fmt.print(", "); } - fmt.printf("%f=%v", key, val); + fmt.printf("%v=%v", key, val); i += 1; } fmt.println("]"); @@ -48,48 +59,36 @@ main :: proc() { fmt.println(m); } - - - // fm: map[128, int]f32; - -/* { - sig: u32; - x := __cpuid(0, ^sig); - fmt.println(sig, x); - } + fmt.println("Hellope!"); + x: [dynamic]f64; + reserve(x, 16); + defer free(x); + append(x, 2_000_000.500_000, 3, 5, 7); + for p, i in x { + if i > 0 { fmt.print(", "); } + fmt.print(p); + } + fmt.println(); - i: int; + { + Vec3 :: [vector 3]f32; - fmt.println("Hellope!"); + 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); - x: [dynamic]f64; - defer free(x); - append(^x, 2_000_000.500_000, 3, 5, 7); - - for p, i in x { - if i > 0 { fmt.print(", "); } - fmt.print(p); - } - fmt.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); - - for i in x { - fmt.println(i); + for i in x { + fmt.println(i); + } } } -*/ +} } diff --git a/core/_preload.odin b/core/_preload.odin index 1eb8a2d06..d9b93a2c6 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -52,15 +52,12 @@ Type_Info :: union { Float: struct #ordered { size: int, // in bytes }, - Any: struct #ordered {}, String: struct #ordered {}, Boolean: struct #ordered {}, + Any: struct #ordered {}, Pointer: struct #ordered { elem: ^Type_Info, // nil -> rawptr }, - Maybe: struct #ordered { - elem: ^Type_Info, - }, Procedure: struct #ordered { params: ^Type_Info, // Type_Info.Tuple results: ^Type_Info, // Type_Info.Tuple @@ -146,6 +143,8 @@ __cpuid :: proc(level: u32, sig: ^u32) -> i32 #foreign __llvm_core "__get_cpuid" + + // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it) Allocator_Mode :: enum u8 { ALLOC, @@ -199,23 +198,17 @@ free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline { if ptr == nil { return; } + if a.procedure == nil { + return; + } a.procedure(a.data, Allocator_Mode.FREE, 0, 0, ptr, 0, 0); } -__free_raw_dynamic_array :: proc(a: ^Raw_Dynamic_Array) { - if a.allocator.procedure == nil { - return; - } - if a.data == nil { - return; - } - free_ptr_with_allocator(a.allocator, a.data); -} - free_ptr :: proc(ptr: rawptr) #inline { __check_context(); free_ptr_with_allocator(context.allocator, ptr); } + free_all :: proc() #inline { __check_context(); a := context.allocator; @@ -306,11 +299,11 @@ __string_eq :: proc(a, b: string) -> bool { if a.data == b.data { return true; } - return mem.compare(cast(rawptr)a.data, cast(rawptr)b.data, a.count) == 0; + return __string_cmp(a, b) == 0; } __string_cmp :: proc(a, b: string) -> int { - return mem.compare(cast(rawptr)a.data, cast(rawptr)b.data, min(a.count, b.count)); + return mem.compare(cast([]byte)a, cast([]byte)b); } __string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); } @@ -504,7 +497,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) { nm: Raw_Dynamic_Map; new_header.m = ^nm; - reserve(^nm.hashes, new_count); + reserve(nm.hashes, new_count); nm.hashes.count = nm.hashes.capacity; __dynamic_array_reserve(^nm.entries, entry_size, entry_align, m.entries.count); for _, i in nm.hashes { @@ -660,3 +653,13 @@ __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) { m.hashes[last.hash_index] = fr.entry_index; } } + + +__print_ti_ptr :: proc(ti: ^Type_Info) { + fmt.println(ti); + match type e in ti { + case Type_Info.Enum: + fmt.println(e.names); + } +} + diff --git a/core/fmt.odin b/core/fmt.odin index 91519167b..48f70b46a 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -134,9 +134,6 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { buffer_write_string(buf, "^"); buffer_write_type(buf, info.elem); } - case Maybe: - buffer_write_string(buf, "?"); - buffer_write_type(buf, info.elem); case Procedure: buffer_write_string(buf, "proc"); if info.params == nil { @@ -420,8 +417,9 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) { } fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) { - negative := signed && cast(i64)u < 0; - u = abs(u); + s := cast(i64)u; + negative := signed && s < 0; + u = cast(u64)abs(s); buf: [256]byte; if fi.width_set || fi.prec_set { width := fi.width + fi.prec + 3; @@ -628,6 +626,7 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) { fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) { match verb { case 'p', 'v': + // Okay default: fmt_bad_verb(fi, verb); return; @@ -747,16 +746,6 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_pointer(fi, (cast(^rawptr)v.data)^, verb); } - case Maybe: - // TODO(bill): Correct verbs for Maybe types? - size := mem.size_of_type_info(info.elem); - data := slice_ptr(cast(^byte)v.data, size+1); - if data[size] != 0 { - fmt_arg(fi, any{info.elem, v.data}, verb); - } else { - buffer_write_string(fi.buf, "nil"); - } - case Array: if verb != 'v' { fmt_bad_verb(fi, verb); @@ -799,9 +788,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { buffer_write_string(fi.buf, "map["); defer buffer_write_byte(fi.buf, ']'); entries := ^(cast(^Raw_Dynamic_Map)v.data).entries; - gs, _ := union_cast(^Struct)info.generated_struct; - ed, _ := union_cast(^Dynamic_Array)gs.fields[1].type_info; - entry_type, _ := union_cast(^Struct)ed.elem; + gs, gs_ok := union_cast(^Struct)type_info_base(info.generated_struct); assert(gs_ok); + ed, ed_ok := union_cast(^Dynamic_Array)type_info_base(gs.fields[1].type_info); assert(ed_ok); + + entry_type, et_ok := union_cast(^Struct)ed.elem; assert(et_ok); entry_size := ed.elem_size; for i in 0.. 0 { diff --git a/core/math.odin b/core/math.odin index b8f8df360..6214bf824 100644 --- a/core/math.odin +++ b/core/math.odin @@ -46,10 +46,6 @@ bit_reverse :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bitreverse.i16"; bit_reverse :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32"; bit_reverse :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64"; -byte_swap :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16"; -byte_swap :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32"; -byte_swap :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64"; - fmuladd :: proc(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32"; fmuladd :: proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64"; diff --git a/core/mem.odin b/core/mem.odin index bf789c608..3bff8fc74 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -1,6 +1,11 @@ #import "fmt.odin"; #import "os.odin"; +swap :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16"; +swap :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32"; +swap :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64"; + + set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" { llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64"; llvm_memset_64bit(data, cast(byte)value, len, 1, false); @@ -12,22 +17,21 @@ zero :: proc(data: rawptr, len: int) -> rawptr #link_name "__mem_zero" { } copy :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy" { - // NOTE(bill): This _must_ implemented like C's memmove + // NOTE(bill): This _must_ be implemented like C's memmove llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memmove.p0i8.p0i8.i64"; llvm_memmove_64bit(dst, src, len, 1, false); return dst; } copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy_non_overlapping" { - // NOTE(bill): This _must_ implemented like C's memcpy + // NOTE(bill): This _must_ be implemented like C's memcpy llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memcpy.p0i8.p0i8.i64"; llvm_memcpy_64bit(dst, src, len, 1, false); return dst; } -compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" { - a := slice_ptr(cast(^byte)dst, n); - b := slice_ptr(cast(^byte)src, n); +compare :: proc(a, b: []byte) -> int #link_name "__mem_compare" { + n := min(a.count, b.count); for i in 0.. int #link_name "__mem_compare" { kilobytes :: proc(x: int) -> int #inline { return (x) * 1024; } megabytes :: proc(x: int) -> int #inline { return kilobytes(x) * 1024; } -gigabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; } -terabytes :: proc(x: int) -> int #inline { return terabytes(x) * 1024; } +gigabytes :: proc(x: int) -> int #inline { return megabytes(x) * 1024; } +terabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; } is_power_of_two :: proc(x: int) -> bool { if x <= 0 { @@ -213,7 +217,6 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int { WORD_SIZE :: size_of(int); MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants? using Type_Info; - match type info in type_info { case Named: return align_of_type_info(info.base); @@ -225,14 +228,16 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int { return WORD_SIZE; case Boolean: return 1; + case Any: + return WORD_SIZE; case Pointer: return WORD_SIZE; - case Maybe: - return max(align_of_type_info(info.elem), 1); case Procedure: return WORD_SIZE; case Array: return align_of_type_info(info.elem); + case Dynamic_Array: + return WORD_SIZE; case Slice: return WORD_SIZE; case Vector: @@ -240,12 +245,18 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int { count := cast(int)max(prev_pow2(cast(i64)info.count), 1); total := size * count; return clamp(total, 1, MAX_ALIGN); + case Tuple: + return info.align; case Struct: return info.align; case Union: return info.align; case Raw_Union: return info.align; + case Enum: + return align_of_type_info(info.base); + case Map: + return align_of_type_info(info.generated_struct); } return 0; @@ -266,16 +277,14 @@ size_of_type_info :: proc(type_info: ^Type_Info) -> int { return info.size; case Float: return info.size; - case Any: - return 2*WORD_SIZE; case String: return 2*WORD_SIZE; case Boolean: return 1; + case Any: + return 2*WORD_SIZE; case Pointer: return WORD_SIZE; - case Maybe: - return size_of_type_info(info.elem) + 1; case Procedure: return WORD_SIZE; case Array: @@ -287,39 +296,29 @@ size_of_type_info :: proc(type_info: ^Type_Info) -> int { align := align_of_type_info(info.elem); alignment := align_formula(size, align); return alignment*(count-1) + size; + case Dynamic_Array: + return size_of(rawptr) + 2*size_of(int) + size_of(Allocator); case Slice: - return 3*WORD_SIZE; + return 2*WORD_SIZE; case Vector: - is_bool :: proc(type_info: ^Type_Info) -> bool { - match type info in type_info { - case Named: - return is_bool(info.base); - case Boolean: - return true; - } - return false; - } - count := info.count; if count == 0 { return 0; } - bit_size := 8*size_of_type_info(info.elem); - if is_bool(info.elem) { - // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1` - // Silly LLVM spec - bit_size = 1; - } - total_size_in_bits := bit_size * count; - total_size := (total_size_in_bits+7)/8; - return total_size; - + size := size_of_type_info(info.elem); + align := align_of_type_info(info.elem); + alignment := align_formula(size, align); + return alignment*(count-1) + size; case Struct: return info.size; case Union: return info.size; case Raw_Union: return info.size; + case Enum: + return size_of_type_info(info.base); + case Map: + return size_of_type_info(info.generated_struct); } return 0; diff --git a/core/sys/windows.odin b/core/sys/windows.odin index 01bad758c..baa6218d4 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -1,3 +1,4 @@ +_ := compile_assert(ODIN_OS == "windows"); #foreign_system_library "kernel32.lib"; #foreign_system_library "user32.lib"; #foreign_system_library "gdi32.lib"; diff --git a/core/types.odin b/core/types.odin index 5464346d1..e22b96c8b 100644 --- a/core/types.odin +++ b/core/types.odin @@ -56,14 +56,6 @@ is_pointer :: proc(info: ^Type_Info) -> bool { } return false; } -is_maybe :: proc(info: ^Type_Info) -> bool { - if info == nil { return false; } - - match type i in type_info_base(info) { - case Type_Info.Maybe: return true; - } - return false; -} is_procedure :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } @@ -88,6 +80,14 @@ is_dynamic_array :: proc(info: ^Type_Info) -> bool { } return false; } +is_dynamic_map :: proc(info: ^Type_Info) -> bool { + if info == nil { return false; } + + match type i in type_info_base(info) { + case Type_Info.Map: return i.count == 0; + } + return false; +} is_slice :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } diff --git a/src/check_expr.c b/src/check_expr.c index 04f246532..3a4f57ea8 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -167,14 +167,6 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) { return 1; } - if (is_type_maybe(dst)) { - Type *elem = base_type(dst)->Maybe.elem; - if (are_types_identical(elem, s)) { - return 1; - } - return -1; - } - if (check_is_assignable_to_using_subtype(operand->type, type)) { return 4; } @@ -743,7 +735,13 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod } else if (str_eq(name, str_lit("max_value"))) { error_node(field, "`max_value` is a reserved identifier for enumerations"); continue; - } + } else if (str_eq(name, str_lit("names"))) { + error_node(field, "`names` is a reserved identifier for enumerations"); + continue; + }/* else if (str_eq(name, str_lit("base_type"))) { + error_node(field, "`base_type` is a reserved identifier for enumerations"); + continue; + } */ if (compare_exact_values(Token_Gt, min_value, iota)) { min_value = iota; @@ -779,6 +777,11 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod enum_type->Record.enum_max_value = make_entity_constant(c->allocator, c->context.scope, make_token_ident(str_lit("max_value")), constant_type, max_value); + enum_type->Record.enum_names = make_entity_field(c->allocator, c->context.scope, + make_token_ident(str_lit("names")), t_string_slice, false, 0); + enum_type->Record.enum_names->Variable.is_immutable = true; + enum_type->Record.enum_names->flags |= EntityFlag_EnumField; + gb_temp_arena_memory_end(tmp); } @@ -909,7 +912,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) { } -void check_ident (Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint) { +void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint) { GB_ASSERT(n->kind == AstNode_Ident); o->mode = Addressing_Invalid; o->expr = n; @@ -1285,12 +1288,6 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { goto end; case_end; - case_ast_node(mt, MaybeType, e); - Type *elem = check_type(c, mt->type); - type = make_type_maybe(c->allocator, elem); - goto end; - case_end; - case_ast_node(at, ArrayType, e); if (at->count != NULL) { Type *elem = check_type_extra(c, at->elem, NULL); @@ -1689,29 +1686,6 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { o->type = make_type_pointer(c->allocator, o->type); return; } - - case Token_Maybe: { // Make maybe - Type *t = default_type(o->type); - - if (o->mode == Addressing_Type) { - o->type = make_type_pointer(c->allocator, t); - return; - } - - if (!is_operand_value(*o) || is_type_untyped(t)) { - if (ast_node_expect(node, AstNode_UnaryExpr)) { - ast_node(ue, UnaryExpr, node); - gbString str = expr_to_string(ue->expr); - error(op, "Cannot convert `%s` to a maybe", str); - gb_string_free(str); - } - o->mode = Addressing_Invalid; - return; - } - o->mode = Addressing_Value; - o->type = make_type_maybe(c->allocator, t); - return; - } } if (!check_unary_op(c, o, op)) { @@ -2436,13 +2410,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level } break; - case Type_Maybe: - if (is_type_untyped_nil(operand->type)) { - // Okay - } else if (level == 0) { - goto error; - } - default: if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) { goto error; @@ -2545,7 +2512,14 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h check_op_expr = false; entity = scope_lookup_entity(e->ImportName.scope, sel_name); - if (entity == NULL) { + bool is_declared = entity != NULL; + if (entity->kind == Entity_Builtin) { + is_declared = false; + } + if (entity->scope->is_global && !e->ImportName.scope->is_global) { + is_declared = false; + } + if (!is_declared) { error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(sel_name), LIT(name)); goto error; } @@ -2638,6 +2612,11 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (entity == NULL && selector->kind == AstNode_Ident) { sel = lookup_field(c->allocator, operand->type, selector->Ident.string, operand->mode == Addressing_Type); entity = sel.entity; + + // NOTE(bill): Add enum type info needed for fields like `names` + if (entity != NULL && (entity->flags&EntityFlag_EnumField)) { + add_type_info_type(c, operand->type); + } } if (entity == NULL && selector->kind == AstNode_BasicLit) { if (is_type_struct(operand->type) || is_type_tuple(operand->type)) { @@ -2699,6 +2678,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } + add_entity_use(c, selector, entity); switch (entity->kind) { @@ -2755,10 +2735,11 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (err) { - ast_node(proc, Ident, ce->proc); - error(ce->close, "`%s` arguments for `%.*s`, expected %td, got %td", - err, LIT(proc->string), + gbString expr = expr_to_string(ce->proc); + error(ce->close, "`%s` arguments for `%s`, expected %td, got %td", + err, expr, bp->arg_count, ce->args.count); + gb_string_free(expr); return false; } } @@ -2852,19 +2833,12 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id case BuiltinProc_reserve: { - // reserve :: proc(^[dynamic]Type, count: int) { - // reserve :: proc(^map[Key]Type, count: int) { + // reserve :: proc([dynamic]Type, count: int) { + // reserve :: proc(map[Key]Type, count: int) { Type *type = operand->type; - if (!is_type_pointer(type)) { - gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer, got `%s`", str); - gb_string_free(str); - return false; - } - type = type_deref(type); if (!is_type_dynamic_array(type) && !is_type_dynamic_map(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer to a dynamic array or dynamic map, got `%s`", str); + error_node(operand->expr, "Expected a dynamic array or dynamic map, got `%s`", str); gb_string_free(str); return false; } @@ -2887,16 +2861,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id case BuiltinProc_clear: { Type *type = operand->type; - if (!is_type_pointer(type)) { - gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer, got `%s`", str); - gb_string_free(str); - return false; - } - type = type_deref(type); if (!is_type_dynamic_array(type) && !is_type_map(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer to a map or dynamic array, got `%s`", str); + error_node(operand->expr, "Expected a map or dynamic array, got `%s`", str); gb_string_free(str); return false; } @@ -2906,18 +2873,12 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } break; case BuiltinProc_append: { - // append :: proc(^[dynamic]Type, item: ...Type) { + // append :: proc([dynamic]Type, item: ...Type) { Type *type = operand->type; - if (!is_type_pointer(type)) { - gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str); - gb_string_free(str); - return false; - } - type = base_type(type_deref(type)); + type = base_type(type); if (!is_type_dynamic_array(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str); + error_node(operand->expr, "Expected a dynamic array, got `%s`", str); gb_string_free(str); return false; } @@ -3140,7 +3101,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } break; case BuiltinProc_compile_assert: - // compile_assert :: proc(cond: bool) + // compile_assert :: proc(cond: bool) -> bool if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) { gbString str = expr_to_string(ce->args.e[0]); @@ -3153,10 +3114,13 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id error_node(call, "Compile time assertion: `%s`", str); gb_string_free(str); } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; break; case BuiltinProc_assert: - // assert :: proc(cond: bool) + // assert :: proc(cond: bool) -> bool if (!is_type_boolean(operand->type)) { gbString str = expr_to_string(ce->args.e[0]); @@ -3165,7 +3129,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id return false; } - operand->mode = Addressing_NoValue; + operand->mode = Addressing_Value; + operand->type = t_untyped_bool; break; case BuiltinProc_panic: @@ -5187,37 +5152,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } case_end; - case_ast_node(de, DemaybeExpr, node); - check_expr_or_type(c, o, de->expr); - if (o->mode == Addressing_Invalid) { - goto error; - } else { - Type *t = base_type(o->type); - if (t->kind == Type_Maybe) { - Entity **variables = gb_alloc_array(c->allocator, Entity *, 2); - Type *elem = t->Maybe.elem; - Token tok = make_token_ident(str_lit("")); - variables[0] = make_entity_param(c->allocator, NULL, tok, elem, false, true); - variables[1] = make_entity_param(c->allocator, NULL, tok, t_bool, false, true); - - Type *tuple = make_type_tuple(c->allocator); - tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = 2; - - o->type = tuple; - o->mode = Addressing_Variable; - } else { - gbString str = expr_to_string(o->expr); - error_node(o->expr, "Cannot demaybe `%s`", str); - gb_string_free(str); - goto error; - } - } - case_end; - case AstNode_ProcType: case AstNode_PointerType: - case AstNode_MaybeType: case AstNode_ArrayType: case AstNode_VectorType: case AstNode_StructType: @@ -5401,16 +5337,19 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = write_expr_to_string(str, ue->expr); case_end; + case_ast_node(ce, CastExpr, node); + str = string_append_token(str, ce->token); + str = gb_string_appendc(str, "("); + str = write_expr_to_string(str, ce->type); + str = gb_string_appendc(str, ")"); + str = write_expr_to_string(str, ce->expr); + case_end; + case_ast_node(de, DerefExpr, node); str = write_expr_to_string(str, de->expr); str = gb_string_appendc(str, "^"); case_end; - case_ast_node(de, DemaybeExpr, node); - str = write_expr_to_string(str, de->expr); - str = gb_string_appendc(str, "?"); - case_end; - case_ast_node(be, BinaryExpr, node); str = write_expr_to_string(str, be->left); str = gb_string_appendc(str, " "); @@ -5462,11 +5401,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = write_expr_to_string(str, pt->type); case_end; - case_ast_node(mt, MaybeType, node); - str = gb_string_appendc(str, "?"); - str = write_expr_to_string(str, mt->type); - case_end; - case_ast_node(at, ArrayType, node); str = gb_string_appendc(str, "["); str = write_expr_to_string(str, at->count); diff --git a/src/checker.c b/src/checker.c index 78643e03c..32743d257 100644 --- a/src/checker.c +++ b/src/checker.c @@ -630,11 +630,12 @@ void init_universal_scope(BuildContext *bc) { } - t_u8_ptr = make_type_pointer(a, t_u8); - t_int_ptr = make_type_pointer(a, t_int); - t_i64_ptr = make_type_pointer(a, t_i64); - t_f64_ptr = make_type_pointer(a, t_f64); - t_byte_slice = make_type_slice(a, t_byte); + t_u8_ptr = make_type_pointer(a, t_u8); + t_int_ptr = make_type_pointer(a, t_int); + t_i64_ptr = make_type_pointer(a, t_i64); + t_f64_ptr = make_type_pointer(a, t_f64); + t_byte_slice = make_type_slice(a, t_byte); + t_string_slice = make_type_slice(a, t_string); } @@ -911,11 +912,6 @@ void add_type_info_type(Checker *c, Type *t) { } } break; - case Type_Maybe: - add_type_info_type(c, bt->Maybe.elem); - add_type_info_type(c, t_bool); - break; - case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break; @@ -1099,48 +1095,46 @@ void init_preload(Checker *c) { - if (record->field_count != 20) { + if (record->field_count != 19) { compiler_error("Invalid `Type_Info` layout"); } t_type_info_named = record->fields[ 1]->type; t_type_info_integer = record->fields[ 2]->type; t_type_info_float = record->fields[ 3]->type; - t_type_info_any = record->fields[ 4]->type; - t_type_info_string = record->fields[ 5]->type; - t_type_info_boolean = record->fields[ 6]->type; + t_type_info_string = record->fields[ 4]->type; + t_type_info_boolean = record->fields[ 5]->type; + t_type_info_any = record->fields[ 6]->type; t_type_info_pointer = record->fields[ 7]->type; - t_type_info_maybe = record->fields[ 8]->type; - t_type_info_procedure = record->fields[ 9]->type; - t_type_info_array = record->fields[10]->type; - t_type_info_dynamic_array = record->fields[11]->type; - t_type_info_slice = record->fields[12]->type; - t_type_info_vector = record->fields[13]->type; - t_type_info_tuple = record->fields[14]->type; - t_type_info_struct = record->fields[15]->type; - t_type_info_union = record->fields[16]->type; - t_type_info_raw_union = record->fields[17]->type; - t_type_info_enum = record->fields[18]->type; - t_type_info_map = record->fields[19]->type; + t_type_info_procedure = record->fields[ 8]->type; + t_type_info_array = record->fields[ 9]->type; + t_type_info_dynamic_array = record->fields[10]->type; + t_type_info_slice = record->fields[11]->type; + t_type_info_vector = record->fields[12]->type; + t_type_info_tuple = record->fields[13]->type; + t_type_info_struct = record->fields[14]->type; + t_type_info_union = record->fields[15]->type; + t_type_info_raw_union = record->fields[16]->type; + t_type_info_enum = record->fields[17]->type; + t_type_info_map = record->fields[18]->type; - t_type_info_named_ptr = make_type_pointer(heap_allocator(), t_type_info_named); - t_type_info_integer_ptr = make_type_pointer(heap_allocator(), t_type_info_integer); - t_type_info_float_ptr = make_type_pointer(heap_allocator(), t_type_info_float); - t_type_info_any_ptr = make_type_pointer(heap_allocator(), t_type_info_any); - t_type_info_string_ptr = make_type_pointer(heap_allocator(), t_type_info_string); - t_type_info_boolean_ptr = make_type_pointer(heap_allocator(), t_type_info_boolean); - t_type_info_pointer_ptr = make_type_pointer(heap_allocator(), t_type_info_pointer); - t_type_info_maybe_ptr = make_type_pointer(heap_allocator(), t_type_info_maybe); - t_type_info_procedure_ptr = make_type_pointer(heap_allocator(), t_type_info_procedure); - t_type_info_array_ptr = make_type_pointer(heap_allocator(), t_type_info_array); - t_type_info_dynamic_array_ptr = make_type_pointer(heap_allocator(), t_type_info_dynamic_array); - t_type_info_slice_ptr = make_type_pointer(heap_allocator(), t_type_info_slice); - t_type_info_vector_ptr = make_type_pointer(heap_allocator(), t_type_info_vector); - t_type_info_tuple_ptr = make_type_pointer(heap_allocator(), t_type_info_tuple); - t_type_info_struct_ptr = make_type_pointer(heap_allocator(), t_type_info_struct); - t_type_info_union_ptr = make_type_pointer(heap_allocator(), t_type_info_union); - t_type_info_raw_union_ptr = make_type_pointer(heap_allocator(), t_type_info_raw_union); - t_type_info_enum_ptr = make_type_pointer(heap_allocator(), t_type_info_enum); - t_type_info_map_ptr = make_type_pointer(heap_allocator(), t_type_info_map); + t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named); + t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer); + t_type_info_float_ptr = make_type_pointer(c->allocator, t_type_info_float); + t_type_info_string_ptr = make_type_pointer(c->allocator, t_type_info_string); + t_type_info_boolean_ptr = make_type_pointer(c->allocator, t_type_info_boolean); + t_type_info_any_ptr = make_type_pointer(c->allocator, t_type_info_any); + t_type_info_pointer_ptr = make_type_pointer(c->allocator, t_type_info_pointer); + t_type_info_procedure_ptr = make_type_pointer(c->allocator, t_type_info_procedure); + t_type_info_array_ptr = make_type_pointer(c->allocator, t_type_info_array); + t_type_info_dynamic_array_ptr = make_type_pointer(c->allocator, t_type_info_dynamic_array); + t_type_info_slice_ptr = make_type_pointer(c->allocator, t_type_info_slice); + t_type_info_vector_ptr = make_type_pointer(c->allocator, t_type_info_vector); + t_type_info_tuple_ptr = make_type_pointer(c->allocator, t_type_info_tuple); + t_type_info_struct_ptr = make_type_pointer(c->allocator, t_type_info_struct); + t_type_info_union_ptr = make_type_pointer(c->allocator, t_type_info_union); + t_type_info_raw_union_ptr = make_type_pointer(c->allocator, t_type_info_raw_union); + t_type_info_enum_ptr = make_type_pointer(c->allocator, t_type_info_enum); + t_type_info_map_ptr = make_type_pointer(c->allocator, t_type_info_map); } if (t_allocator == NULL) { @@ -1714,6 +1708,19 @@ void check_import_entities(Checker *c, MapScope *file_scopes) { file_str = import_file; } + if (fl->cond != NULL) { + Operand operand = {Addressing_Invalid}; + check_expr(c, &operand, fl->cond); + if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) { + error_node(fl->cond, "Non-constant boolean `when` condition"); + continue; + } + if (operand.value.kind == ExactValue_Bool && + !operand.value.value_bool) { + continue; + } + } + String library_name = path_to_entity_name(fl->library_name.string, file_str); if (str_eq(library_name, str_lit("_"))) { error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string)); diff --git a/src/entity.c b/src/entity.c index 221ec91b6..37c79b488 100644 --- a/src/entity.c +++ b/src/entity.c @@ -37,6 +37,7 @@ typedef enum EntityFlag { EntityFlag_VectorElem = 1<<5, EntityFlag_Ellipsis = 1<<6, EntityFlag_NoAlias = 1<<7, + EntityFlag_EnumField = 1<<8, } EntityFlag; typedef enum OverloadKind { diff --git a/src/ir.c b/src/ir.c index 117173ab3..7ddcb6344 100644 --- a/src/ir.c +++ b/src/ir.c @@ -1788,11 +1788,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { case 0: result_type = make_type_pointer(a, t_type_info_ptr); break; case 1: result_type = make_type_pointer(a, t_rawptr); break; } - } else if (is_type_maybe(t)) { - switch (index) { - case 0: result_type = make_type_pointer(a, t->Maybe.elem); break; - case 1: result_type = make_type_pointer(a, t_bool); break; - } } else if (is_type_dynamic_array(t)) { switch (index) { case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->DynamicArray.elem)); break; @@ -1848,11 +1843,6 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { case 0: result_type = t_type_info_ptr; break; case 1: result_type = t_rawptr; break; } - } else if (is_type_maybe(t)) { - switch (index) { - case 0: result_type = t->Maybe.elem; break; - case 1: result_type = t_bool; break; - } } else if (is_type_dynamic_array(t)) { switch (index) { case 0: result_type = make_type_pointer(a, t->DynamicArray.elem); break; @@ -2165,15 +2155,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { return value; } - if (is_type_maybe(dst)) { - irValue *maybe = ir_add_local_generated(proc, dst); - irValue *val = ir_emit_struct_ep(proc, maybe, 0); - irValue *set = ir_emit_struct_ep(proc, maybe, 1); - ir_emit_store(proc, val, value); - ir_emit_store(proc, set, v_true); - return ir_emit_load(proc, maybe); - } - // integer -> integer if (is_type_integer(src) && is_type_integer(dst)) { GB_ASSERT(src->kind == Type_Basic && @@ -2396,7 +2377,6 @@ bool ir_is_type_aggregate(Type *t) { case Type_Array: case Type_Slice: - case Type_Maybe: case Type_Record: case Type_Tuple: return true; @@ -3130,22 +3110,33 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv args[1] = ptr; return ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2); } else if (is_type_dynamic_map(type)) { - // irValue *val = ir_build_expr(proc, node); - // irValue *map_ptr = ir_address_from_load_or_generate_local(proc, val); + irValue *map = ir_build_expr(proc, node); + irValue *map_ptr = ir_address_from_load_or_generate_local(proc, map); - // { - // irValue *array = ir_emit_conv(proc, ir_emit_struct_ep(proc, map_ptr, 0), t_raw_dynamic_array_ptr); - // irValue **args = gb_alloc_array(a, irValue *, 1); - // args[0] = array; - // ir_emit_global_call(proc, "__free_raw_dynamic_array", args, 1); - // } - // { - // irValue *array = ir_emit_conv(proc, ir_emit_struct_ep(proc, map_ptr, 1), t_raw_dynamic_array_ptr); - // irValue **args = gb_alloc_array(a, irValue *, 1); - // args[0] = array; - // ir_emit_global_call(proc, "__free_raw_dynamic_array", args, 1); - // } + { + irValue *array = ir_emit_struct_ep(proc, map_ptr, 0); + irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3)); + irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0)); + da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr); + + irValue **args = gb_alloc_array(a, irValue *, 1); + args[0] = da_allocator; + args[1] = da_ptr; + ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2); + } + { + irValue *array = ir_emit_struct_ep(proc, map_ptr, 1); + + irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3)); + irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0)); + da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr); + + irValue **args = gb_alloc_array(a, irValue *, 1); + args[0] = da_allocator; + args[1] = da_ptr; + ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2); + } return NULL; } @@ -3176,7 +3167,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv ir_emit_comment(proc, str_lit("reserve")); gbAllocator a = proc->module->allocator; - irValue *ptr = ir_build_expr(proc, ce->args.e[0]); + irValue *ptr = ir_build_addr(proc, ce->args.e[0]).addr; Type *type = ir_type(ptr); GB_ASSERT(is_type_pointer(type)); type = base_type(type_deref(type)); @@ -3208,8 +3199,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv } break; case BuiltinProc_clear: { - ir_emit_comment(proc, str_lit("reserve")); - irValue *ptr = ir_build_expr(proc, ce->args.e[0]); + ir_emit_comment(proc, str_lit("clear")); + irValue *ptr = ir_build_addr(proc, ce->args.e[0]).addr; Type *t = base_type(type_deref(ir_type(ptr))); if (is_type_dynamic_array(t)) { irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1); @@ -3229,7 +3220,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv ir_emit_comment(proc, str_lit("append")); gbAllocator a = proc->module->allocator; - irValue *array_ptr = ir_build_expr(proc, ce->args.e[0]); + irValue *array_ptr = ir_build_addr(proc, ce->args.e[0]).addr; Type *type = ir_type(array_ptr); GB_ASSERT(is_type_pointer(type)); type = base_type(type_deref(type)); @@ -3348,7 +3339,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv ir_emit_jump(proc, done); ir_start_block(proc, done); - return NULL; + return cond; } break; case BuiltinProc_panic: { @@ -3596,10 +3587,6 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv return ir_emit_call(proc, value, args, arg_count); case_end; - case_ast_node(de, DemaybeExpr, expr); - return ir_addr_load(proc, ir_build_addr(proc, expr)); - case_end; - case_ast_node(se, SliceExpr, expr); return ir_addr_load(proc, ir_build_addr(proc, expr)); case_end; @@ -3722,7 +3709,34 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { AstNode *sel = unparen_expr(se->selector); if (sel->kind == AstNode_Ident) { String selector = sel->Ident.string; - Type *type = base_type(type_of_expr(proc->module->info, se->expr)); + Type *type = type_of_expr(proc->module->info, se->expr); + + if (is_type_enum(type)) { + Selection sel = lookup_field(proc->module->allocator, type, selector, true); + Entity *e = sel.entity; + GB_ASSERT(e->kind == Entity_Variable); + i32 index = e->Variable.field_index; + switch (index) { + case 0: { + irValue *ti_ptr = ir_type_info(proc, type); + { + irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 1); + args[0] = ti_ptr; + ti_ptr = ir_emit_global_call(proc, "type_info_base", args, 1); + } + + + irValue *enum_info = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr); + irValue *names_ptr = ir_emit_struct_ep(proc, enum_info, 1); + return ir_make_addr(names_ptr); + } break; + default: + GB_PANIC("Unhandled enum index %d %.*s", index, LIT(selector)); + break; + } + } + + type = base_type(type); if (type == t_invalid) { // NOTE(bill): Imports @@ -4056,18 +4070,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { return ir_make_addr(addr); case_end; - case_ast_node(de, DemaybeExpr, expr); - ir_emit_comment(proc, str_lit("DemaybeExpr")); - irValue *maybe = ir_build_expr(proc, de->expr); - Type *t = default_type(type_of_expr(proc->module->info, expr)); - GB_ASSERT(is_type_tuple(t)); - - irValue *result = ir_add_local_generated(proc, t); - ir_emit_store(proc, result, maybe); - - return ir_make_addr(result); - case_end; - case_ast_node(ce, CallExpr, expr); // NOTE(bill): This is make sure you never need to have an `array_ev` irValue *e = ir_build_expr(proc, expr); @@ -5276,6 +5278,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { String tag_var_name = ms->var->Ident.string; + AstNodeArray default_stmts = {0}; irBlock *default_block = NULL; @@ -5291,19 +5294,32 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { default_block = ir_new_block(proc, clause, "type-match.dflt.body"); continue; } + GB_ASSERT(cc->list.count == 1); irBlock *body = ir_new_block(proc, clause, "type-match.case.body"); - Scope *scope = *map_scope_get(&proc->module->info->scopes, hash_pointer(clause)); - Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name); - GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name)); + Entity *tag_var_entity = NULL; + Type *tag_var_type = NULL; + if (str_eq(tag_var_name, str_lit("_"))) { + Type *t = type_of_expr(proc->module->info, cc->list.e[0]); + if (is_union_ptr) { + t = make_type_pointer(proc->module->allocator, t); + } + tag_var_type = t; + } else { + Scope *scope = *map_scope_get(&proc->module->info->scopes, hash_pointer(clause)); + tag_var_entity = current_scope_lookup_entity(scope, tag_var_name); + GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name)); + tag_var_type = tag_var_entity->type; + } + GB_ASSERT(tag_var_type != NULL); irBlock *next_cond = NULL; irValue *cond = NULL; if (is_union_ptr) { - Type *bt = type_deref(tag_var_entity->type); + Type *bt = type_deref(tag_var_type); irValue *index = NULL; Type *ut = base_type(type_deref(ir_type(parent))); GB_ASSERT(ut->Record.kind == TypeRecord_Union); @@ -5316,16 +5332,25 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { } GB_ASSERT(index != NULL); - irValue *tag_var = ir_add_local(proc, tag_var_entity); - irValue *data_ptr = ir_emit_conv(proc, union_data, tag_var_entity->type); + irValue *tag_var = NULL; + if (tag_var_entity != NULL) { + tag_var = ir_add_local(proc, tag_var_entity); + } else { + tag_var = ir_add_local_generated(proc, tag_var_type); + } + + + irValue *data_ptr = ir_emit_conv(proc, union_data, tag_var_type); ir_emit_store(proc, tag_var, data_ptr); cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index); } else if (is_any) { - Type *type = tag_var_entity->type; + Type *type = tag_var_type; irValue *any_data = ir_emit_struct_ev(proc, parent, 1); irValue *data = ir_emit_conv(proc, any_data, make_type_pointer(proc->module->allocator, type)); - ir_module_add_value(proc->module, tag_var_entity, data); + if (tag_var_entity != NULL) { + ir_module_add_value(proc->module, tag_var_entity, data); + } irValue *any_ti = ir_emit_struct_ev(proc, parent, 0); irValue *case_ti = ir_type_info(proc, type); @@ -6228,11 +6253,6 @@ void ir_gen_tree(irGen *s) { irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Pointer.elem); ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep); } break; - case Type_Maybe: { - tag = ir_emit_conv(proc, ti_ptr, t_type_info_maybe_ptr); - irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Maybe.elem); - ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep); - } break; case Type_Array: { tag = ir_emit_conv(proc, ti_ptr, t_type_info_array_ptr); irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Array.elem); diff --git a/src/ir_print.c b/src/ir_print.c index 670db48cd..da411fdc6 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -172,13 +172,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { ir_print_type(f, m, t->Pointer.elem); ir_fprintf(f, "*"); return; - case Type_Maybe: - ir_fprintf(f, "{"); - ir_print_type(f, m, t->Maybe.elem); - ir_fprintf(f, ", "); - ir_print_type(f, m, t_bool); - ir_fprintf(f, "}"); - return; case Type_Array: ir_fprintf(f, "[%lld x ", t->Array.count); ir_print_type(f, m, t->Array.elem); @@ -306,25 +299,11 @@ void ir_print_compound_element(irFileBuffer *f, irModule *m, ExactValue v, Type ir_print_type(f, m, elem_type); ir_fprintf(f, " "); - if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) { - Type *t = base_type(elem_type)->Maybe.elem; - ir_fprintf(f, "{"); - ir_print_type(f, m, t); - ir_fprintf(f, " "); - } - if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) { ir_fprintf(f, "zeroinitializer"); } else { ir_print_exact_value(f, m, v, elem_type); } - - if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) { - ir_fprintf(f, ", "); - ir_print_type(f, m, t_bool); - ir_fprintf(f, " "); - ir_fprintf(f, "true}"); - } } void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) { diff --git a/src/parser.c b/src/parser.c index 079e39c2f..7531412ef 100644 --- a/src/parser.c +++ b/src/parser.c @@ -147,7 +147,6 @@ AST_NODE_KIND(_ExprBegin, "", i32) \ AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \ AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \ AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \ - AST_NODE_KIND(DemaybeExpr, "demaybe expression", struct { Token op; AstNode *expr; }) \ AST_NODE_KIND(SliceExpr, "slice expression", struct { \ AstNode *expr; \ Token open, close, interval; \ @@ -333,10 +332,6 @@ AST_NODE_KIND(_TypeBegin, "", i32) \ Token token; \ AstNode *type; \ }) \ - AST_NODE_KIND(MaybeType, "maybe type", struct { \ - Token token; \ - AstNode *type; \ - }) \ AST_NODE_KIND(ArrayType, "array type", struct { \ Token token; \ AstNode *count; \ @@ -469,7 +464,6 @@ Token ast_node_token(AstNode *node) { case AstNode_CastExpr: return node->CastExpr.token; case AstNode_FieldValue: return node->FieldValue.eq; case AstNode_DerefExpr: return node->DerefExpr.op; - case AstNode_DemaybeExpr: return node->DemaybeExpr.op; case AstNode_BlockExpr: return node->BlockExpr.open; case AstNode_GiveExpr: return node->GiveExpr.token; case AstNode_IfExpr: return node->IfExpr.token; @@ -513,7 +507,6 @@ Token ast_node_token(AstNode *node) { case AstNode_HelperType: return node->HelperType.token; case AstNode_ProcType: return node->ProcType.token; case AstNode_PointerType: return node->PointerType.token; - case AstNode_MaybeType: return node->MaybeType.token; case AstNode_ArrayType: return node->ArrayType.token; case AstNode_DynamicArrayType: return node->DynamicArrayType.token; case AstNode_VectorType: return node->VectorType.token; @@ -693,13 +686,6 @@ AstNode *ast_deref_expr(AstFile *f, AstNode *expr, Token op) { return result; } -AstNode *ast_demaybe_expr(AstFile *f, AstNode *expr, Token op) { - AstNode *result = make_ast_node(f, AstNode_DemaybeExpr); - result->DemaybeExpr.expr = expr; - result->DemaybeExpr.op = op; - return result; -} - AstNode *ast_interval_expr(AstFile *f, Token op, AstNode *left, AstNode *right) { AstNode *result = make_ast_node(f, AstNode_IntervalExpr); @@ -1031,13 +1017,6 @@ AstNode *ast_pointer_type(AstFile *f, Token token, AstNode *type) { return result; } -AstNode *ast_maybe_type(AstFile *f, Token token, AstNode *type) { - AstNode *result = make_ast_node(f, AstNode_MaybeType); - result->MaybeType.token = token; - result->MaybeType.type = type; - return result; -} - AstNode *ast_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) { AstNode *result = make_ast_node(f, AstNode_ArrayType); result->ArrayType.token = token; @@ -1999,10 +1978,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { operand = ast_deref_expr(f, operand, expect_token(f, Token_Pointer)); break; - case Token_Maybe: // Demaybe - operand = ast_demaybe_expr(f, operand, expect_token(f, Token_Maybe)); - break; - case Token_OpenBrace: if (!lhs && is_literal_type(operand) && f->expr_level >= 0) { operand = parse_literal_value(f, operand); @@ -2565,12 +2540,6 @@ AstNode *parse_type_or_ident(AstFile *f) { return ast_pointer_type(f, token, elem); } - case Token_Maybe: { - Token token = expect_token(f, Token_Maybe); - AstNode *elem = parse_type(f); - return ast_maybe_type(f, token, elem); - } - case Token_OpenBracket: { Token token = expect_token(f, Token_OpenBracket); AstNode *count_expr = NULL; diff --git a/src/tokenizer.c b/src/tokenizer.c index 9dacdba64..308224157 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -17,7 +17,7 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \ TOKEN_KIND(Token_Hash, "#"), \ TOKEN_KIND(Token_At, "@"), \ TOKEN_KIND(Token_Pointer, "^"), \ - TOKEN_KIND(Token_Maybe, "?"), \ + /* TOKEN_KIND(Token_Maybe, "?"), */ \ TOKEN_KIND(Token_Add, "+"), \ TOKEN_KIND(Token_Sub, "-"), \ TOKEN_KIND(Token_Mul, "*"), \ @@ -55,6 +55,8 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \ TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \ TOKEN_KIND(Token_ArrowRight, "->"), \ TOKEN_KIND(Token_ArrowLeft, "<-"), \ + TOKEN_KIND(Token_Increment, "++"), \ + TOKEN_KIND(Token_Decrement, "--"), \ \ TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \ TOKEN_KIND(Token_CmpEq, "=="), \ @@ -80,7 +82,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \ \ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ - /* TODO(bill): So of these keywords are not used but "reserved", why not remove them? */ \ + /* TODO(bill): Of these keywords are not used but "reserved", why not remove them? */ \ TOKEN_KIND(Token_when, "when"), \ TOKEN_KIND(Token_if, "if"), \ TOKEN_KIND(Token_else, "else"), \ @@ -870,9 +872,9 @@ Token tokenizer_get_token(Tokenizer *t) { case '^': token.kind = Token_Pointer; break; - case '?': - token.kind = Token_Maybe; - break; + // case '?': + // token.kind = Token_Maybe; + // break; case ';': token.kind = Token_Semicolon; break; @@ -907,10 +909,10 @@ Token tokenizer_get_token(Tokenizer *t) { case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break; case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break; case '+': - token.kind = token_kind_variant2(t, Token_Add, Token_AddEq); + token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Increment); break; case '-': - token.kind = token_kind_variant3(t, Token_Sub, Token_SubEq, '>', Token_ArrowRight); + token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Decrement, '>', Token_ArrowRight); break; case '/': { if (t->curr_rune == '/') { diff --git a/src/types.c b/src/types.c index dbded4a73..71888a372 100644 --- a/src/types.c +++ b/src/types.c @@ -11,6 +11,20 @@ typedef enum BasicKind { Basic_u32, Basic_i64, Basic_u64, + +/* Basic_i16le, + Basic_i16be, + Basic_u16le, + Basic_u16be, + Basic_i32le, + Basic_i32be, + Basic_u32le, + Basic_u32be, + Basic_i64le, + Basic_i64be, + Basic_u64le, + Basic_u64be, */ + // Basic_i128, // Basic_u128, // Basic_f16, @@ -93,6 +107,7 @@ typedef struct TypeRecord { Entity * enum_count; Entity * enum_min_value; Entity * enum_max_value; + Entity * enum_names; } TypeRecord; #define TYPE_KINDS \ @@ -102,7 +117,6 @@ typedef struct TypeRecord { TYPE_KIND(DynamicArray, struct { Type *elem; }) \ TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \ TYPE_KIND(Slice, struct { Type *elem; }) \ - TYPE_KIND(Maybe, struct { Type *elem; }) \ TYPE_KIND(Record, TypeRecord) \ TYPE_KIND(Named, struct { \ String name; \ @@ -177,16 +191,16 @@ typedef struct BaseTypeSizes { } BaseTypeSizes; -typedef Array(isize) Array_isize; +typedef Array(i32) Array_i32; typedef struct Selection { - Entity * entity; - Array_isize index; - bool indirect; // Set if there was a pointer deref anywhere down the line + Entity * entity; + Array_i32 index; + bool indirect; // Set if there was a pointer deref anywhere down the line } Selection; Selection empty_selection = {0}; -Selection make_selection(Entity *entity, Array_isize index, bool indirect) { +Selection make_selection(Entity *entity, Array_i32 index, bool indirect) { Selection s = {entity, index, indirect}; return s; } @@ -273,6 +287,7 @@ gb_global Type *t_int_ptr = NULL; gb_global Type *t_i64_ptr = NULL; gb_global Type *t_f64_ptr = NULL; gb_global Type *t_byte_slice = NULL; +gb_global Type *t_string_slice = NULL; gb_global Type *t_type_info = NULL; @@ -289,7 +304,6 @@ gb_global Type *t_type_info_any = NULL; gb_global Type *t_type_info_string = NULL; gb_global Type *t_type_info_boolean = NULL; gb_global Type *t_type_info_pointer = NULL; -gb_global Type *t_type_info_maybe = NULL; gb_global Type *t_type_info_procedure = NULL; gb_global Type *t_type_info_array = NULL; gb_global Type *t_type_info_dynamic_array = NULL; @@ -310,7 +324,6 @@ gb_global Type *t_type_info_any_ptr = NULL; gb_global Type *t_type_info_string_ptr = NULL; gb_global Type *t_type_info_boolean_ptr = NULL; gb_global Type *t_type_info_pointer_ptr = NULL; -gb_global Type *t_type_info_maybe_ptr = NULL; gb_global Type *t_type_info_procedure_ptr = NULL; gb_global Type *t_type_info_array_ptr = NULL; gb_global Type *t_type_info_dynamic_array_ptr = NULL; @@ -393,12 +406,6 @@ Type *make_type_pointer(gbAllocator a, Type *elem) { return t; } -Type *make_type_maybe(gbAllocator a, Type *elem) { - Type *t = alloc_type(a, Type_Maybe); - t->Maybe.elem = elem; - return t; -} - Type *make_type_array(gbAllocator a, Type *elem, i64 count) { Type *t = alloc_type(a, Type_Array); t->Array.elem = elem; @@ -630,10 +637,6 @@ bool is_type_pointer(Type *t) { } return t->kind == Type_Pointer; } -bool is_type_maybe(Type *t) { - t = base_type(t); - return t->kind == Type_Maybe; -} bool is_type_tuple(Type *t) { t = base_type(t); return t->kind == Type_Tuple; @@ -780,7 +783,6 @@ bool type_has_nil(Type *t) { case Type_DynamicArray: case Type_Proc: case Type_Pointer: - case Type_Maybe: return true; } return false; @@ -890,12 +892,6 @@ bool are_types_identical(Type *x, Type *y) { } break; - case Type_Maybe: - if (y->kind == Type_Maybe) { - return are_types_identical(x->Maybe.elem, y->Maybe.elem); - } - break; - case Type_Named: if (y->kind == Type_Named) { return x->Named.base == y->Named.base; @@ -981,9 +977,6 @@ bool is_type_cte_safe(Type *type) { case Type_Slice: return false; - case Type_Maybe: - return is_type_cte_safe(type->Maybe.elem); - case Type_Record: { if (type->Record.kind != TypeRecord_Struct) { return false; @@ -1026,12 +1019,14 @@ typedef enum ProcTypeOverloadKind { ProcOverload_ResultCount, ProcOverload_ResultTypes, + ProcOverload_NotProcedure, + } ProcTypeOverloadKind; ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) { - GB_ASSERT(is_type_proc(x)); - GB_ASSERT(is_type_proc(y)); + if (!is_type_proc(x)) return ProcOverload_NotProcedure; + if (!is_type_proc(y)) return ProcOverload_NotProcedure; TypeProc *px = &base_type(x)->Proc; TypeProc *py = &base_type(y)->Proc; @@ -1113,7 +1108,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) { Entity *f = type->Record.fields[i]; if (f->kind == Entity_Variable) { if (f->Variable.field_src_index == index) { - Array_isize sel_array = {0}; + Array_i32 sel_array = {0}; array_init_count(&sel_array, a, 1); sel_array.e[0] = i; return make_selection(f, sel_array, false); @@ -1125,7 +1120,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) { for (isize i = 0; i < max_count; i++) { Entity *f = type->Tuple.variables[i]; if (i == index) { - Array_isize sel_array = {0}; + Array_i32 sel_array = {0}; array_init_count(&sel_array, a, 1); sel_array.e[0] = i; return make_selection(f, sel_array, false); @@ -1352,6 +1347,10 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = type->Record.enum_max_value; return sel; } + if (str_eq(field_name, str_lit("names"))) { + sel.entity = type->Record.enum_names; + return sel; + } } for (isize i = 0; i < type->Record.field_count; i++) { @@ -1558,17 +1557,6 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type return max; } break; - case Type_Maybe: { - Type *elem = t->Maybe.elem; - type_path_push(path, elem); - if (path->failure) { - return FAILURE_ALIGNMENT; - } - i64 align = gb_max(type_align_of_internal(s, allocator, t->Maybe.elem, path), type_align_of_internal(s, allocator, t_bool, path)); - type_path_pop(path); - return align; - } - case Type_Map: { if (t->Map.count == 0) { // Dynamic return type_align_of_internal(s, allocator, t->Map.generated_struct_type, path); @@ -1773,18 +1761,6 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP case Type_Slice: // ptr + count return 2 * s.word_size; - case Type_Maybe: { // value + bool - i64 align, size; - Type *elem = t->Maybe.elem; - align = type_align_of_internal(s, allocator, elem, path); - if (path->failure) { - return FAILURE_SIZE; - } - size = align_formula(type_size_of_internal(s, allocator, elem, path), align); - size += type_size_of_internal(s, allocator, t_bool, path); - return align_formula(size, align); - } - case Type_Map: { if (t->Map.count == 0) { // Dynamic return type_size_of_internal(s, allocator, t->Map.generated_struct_type, path); @@ -1969,11 +1945,6 @@ gbString write_type_to_string(gbString str, Type *type) { str = write_type_to_string(str, type->Pointer.elem); break; - case Type_Maybe: - str = gb_string_appendc(str, "?"); - str = write_type_to_string(str, type->Maybe.elem); - break; - case Type_Array: str = gb_string_appendc(str, gb_bprintf("[%lld]", type->Array.count)); str = write_type_to_string(str, type->Array.elem);