diff --git a/code/demo.odin b/code/demo.odin index 7f941a764..c019faa99 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,5 +1,12 @@ #import "fmt.odin"; #import "utf8.odin"; +#import "atomic.odin"; +#import "hash.odin"; +#import "math.odin"; +#import "mem.odin"; +#import "opengl.odin"; +#import "os.odin"; +#import "sync.odin"; main :: proc() { syntax(); @@ -120,7 +127,6 @@ when_statements :: proc() { foreign_procedures(); } -#import "atomic.odin" when ODIN_OS == "windows"; #foreign_system_library win32_user "user32.lib" when ODIN_OS == "windows"; // NOTE: This is done on purpose for two reasons: // * Makes it clear where the platform specific stuff is @@ -132,6 +138,8 @@ foreign_procedures :: proc() { // NOTE: If that library doesn't get used, it doesn't get linked with // NOTE: There is not link checking yet to see if that procedure does come from that library + // See sys/windows.odin for more examples + special_expressions(); } @@ -148,8 +156,7 @@ special_expressions :: proc() { give x; } else { // TODO: Type cohesion is not yet finished - // E.g. this constant "number" should be able to be cast to a `f32` automatically - give cast(f32)123; + give 123; }; // semicolon is required as it's an expression @@ -176,24 +183,24 @@ loops :: proc() { for i := 0; i < 123; i += 1 { } */ - for i : 0..<123 { + for i in 0..<123 { } - for i : 0...122 { + for i in 0..122 { } - for val, idx : 12..<16 { + for val, idx in 12..<16 { fmt.println(val, idx); } - primes := [...]int{2, 3, 5, 7, 11, 13, 17, 19}; + primes := [..]int{2, 3, 5, 7, 11, 13, 17, 19}; - for p : primes { + for p in primes { fmt.println(p); } // Pointers to arrays, slices, or strings are allowed - for _ : ^primes { + for _ in ^primes { // ignore the value and just iterate across it } @@ -201,7 +208,7 @@ loops :: proc() { name := "你好,世界"; fmt.println(name); - for r : name { + for r in name { compile_assert(type_of_val(r) == rune); fmt.printf("%r\n", r); } @@ -210,14 +217,12 @@ loops :: proc() { while i := 0; i < name.count { r, size := utf8.decode_rune(name[i:]); i += size; - fmt.printf("%c\n", r); + fmt.printf("%r\n", r); } } - - // Emulate a C-style loop (not exactly the same though) while x := 0; x < 10 { defer x += 2; @@ -250,10 +255,8 @@ procedure_overloading :: proc() { foo(); foo(THINGF); - // foo(THINGI); + // foo(THINGI); // 14451 is just a number so it could go to either procedures foo(cast(int)THINGI); - fmt.println(THINGF); - fmt.println(THINGI); @@ -273,11 +276,12 @@ procedure_overloading :: proc() { fmt.println(foo(^a)); foo(^b); foo(c); - // foo(nil); - atomic.store(^a, 1); - + // foo(nil); // nil could go to numerous types thus the ambiguity f: proc(); - f = foo; + f = foo; // The correct `foo` to chosen f(); + + + // See math.odin and atomic.odin for more examples } diff --git a/core/_preload.odin b/core/_preload.odin index 96bf61f9b..0bcb45b52 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -100,7 +100,7 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { return nil; } base := info; - match type i : base { + match type i in base { case Type_Info.Named: base = i.base; } diff --git a/core/fmt.odin b/core/fmt.odin index 322350d7f..f7c11015e 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -58,38 +58,38 @@ Fmt_Info :: struct { -fprint :: proc(fd: os.Handle, args: ...any) -> int { +fprint :: proc(fd: os.Handle, args: ..any) -> int { data: [DEFAULT_BUFFER_SIZE]byte; buf := Buffer{data[:], 0}; - bprint(^buf, ...args); + bprint(^buf, ..args); os.write(fd, buf.data[:buf.length]); return buf.length; } -fprintln :: proc(fd: os.Handle, args: ...any) -> int { +fprintln :: proc(fd: os.Handle, args: ..any) -> int { data: [DEFAULT_BUFFER_SIZE]byte; buf := Buffer{data[:], 0}; - bprintln(^buf, ...args); + bprintln(^buf, ..args); os.write(fd, buf.data[:buf.length]); return buf.length; } -fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int { +fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { data: [DEFAULT_BUFFER_SIZE]byte; buf := Buffer{data[:], 0}; - bprintf(^buf, fmt, ...args); + bprintf(^buf, fmt, ..args); os.write(fd, buf.data[:buf.length]); return buf.length; } -print :: proc(args: ...any) -> int { - return fprint(os.stdout, ...args); +print :: proc(args: ..any) -> int { + return fprint(os.stdout, ..args); } -println :: proc(args: ...any) -> int { - return fprintln(os.stdout, ...args); +println :: proc(args: ..any) -> int { + return fprintln(os.stdout, ..args); } -printf :: proc(fmt: string, args: ...any) -> int { - return fprintf(os.stdout, fmt, ...args); +printf :: proc(fmt: string, args: ..any) -> int { + return fprintf(os.stdout, fmt, ..args); } @@ -107,7 +107,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { } using Type_Info; - match type info : ti { + match type info in ti { case Named: buffer_write_string(buf, info.name); case Integer: @@ -154,7 +154,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { case Tuple: count := info.fields.count; if count != 1 { buffer_write_string(buf, "("); } - for i : 0.. 0 { buffer_write_string(buf, ", "); } f := info.fields[i]; @@ -189,7 +189,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { if info.packed { buffer_write_string(buf, "#packed "); } if info.ordered { buffer_write_string(buf, "#ordered "); } buffer_write_string(buf, "{"); - for field, i : info.fields { + for field, i in info.fields { buffer_write_string(buf, field.name); buffer_write_string(buf, ": "); buffer_write_type(buf, field.type_info); @@ -199,7 +199,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { case Union: buffer_write_string(buf, "union {"); - for field, i : info.fields { + for field, i in info.fields { buffer_write_string(buf, field.name); buffer_write_string(buf, ": "); buffer_write_type(buf, field.type_info); @@ -209,7 +209,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { case Raw_Union: buffer_write_string(buf, "raw_union {"); - for field, i : info.fields { + for field, i in info.fields { buffer_write_string(buf, field.name); buffer_write_string(buf, ": "); buffer_write_type(buf, field.type_info); @@ -225,12 +225,12 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { } -bprint :: proc(buf: ^Buffer, args: ...any) -> int { +bprint :: proc(buf: ^Buffer, args: ..any) -> int { fi: Fmt_Info; fi.buf = buf; prev_string := false; - for arg, i : args { + for arg, i in args { is_string := arg.data != nil && is_type_string(arg.type_info); if i > 0 && !is_string && !prev_string { buffer_write_byte(buf, ' '); @@ -241,11 +241,11 @@ bprint :: proc(buf: ^Buffer, args: ...any) -> int { return buf.length; } -bprintln :: proc(buf: ^Buffer, args: ...any) -> int { +bprintln :: proc(buf: ^Buffer, args: ..any) -> int { fi: Fmt_Info; fi.buf = buf; - for arg, i : args { + for arg, i in args { if i > 0 { buffer_write_byte(buf, ' '); } @@ -262,7 +262,7 @@ is_type_string :: proc(info: ^Type_Info) -> bool { return false; } - match type i : type_info_base(info) { + match type i in type_info_base(info) { case String: return true; } @@ -274,7 +274,7 @@ is_type_integer :: proc(info: ^Type_Info) -> bool { return false; } - match type i : type_info_base(info) { + match type i in type_info_base(info) { case Integer: return true; } @@ -286,7 +286,7 @@ is_type_float :: proc(info: ^Type_Info) -> bool { return false; } - match type i : type_info_base(info) { + match type i in type_info_base(info) { case Float: return true; } @@ -305,7 +305,7 @@ parse_int :: proc(s: string, offset: int) -> (int, int, bool) { ok := true; i := 0; - for o : offset.. (int, int, bool) { if arg_index < args.count { arg := args[arg_index]; arg.type_info = type_info_base(arg.type_info); - match type i : arg { + match type i in arg { case int: num = i; case i8: num = cast(int)i; case i16: num = cast(int)i; @@ -413,7 +413,7 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) { count := min(width, fi.buf.data.count-fi.buf.length); start := fi.buf.length; - for i : start.. 0 { buffer_write_string(fi.buf, ", "); } @@ -757,7 +757,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { buffer_write_byte(fi.buf, '['); defer buffer_write_byte(fi.buf, ']'); - for i : 0.. 0 { buffer_write_string(fi.buf, ", "); } @@ -774,7 +774,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { buffer_write_byte(fi.buf, '['); defer buffer_write_byte(fi.buf, ']'); slice := cast(^[]byte)v.data; - for i : 0.. 0 { buffer_write_string(fi.buf, ", "); } @@ -784,7 +784,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { case Vector: is_bool :: proc(type_info: ^Type_Info) -> bool { - match type info : type_info { + match type info in type_info { case Named: return is_bool(info.base); case Boolean: @@ -800,7 +800,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { return; } - for i : 0.. 0 { buffer_write_string(fi.buf, ", "); } @@ -813,7 +813,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { buffer_write_byte(fi.buf, '{'); defer buffer_write_byte(fi.buf, '}'); - for f, i : info.fields { + for f, i in info.fields { if i > 0 { buffer_write_string(fi.buf, ", "); } @@ -848,7 +848,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { if verb == 'T' { ti := arg.type_info; - match type a : arg { + match type a in arg { case ^Type_Info: ti = a; } buffer_write_type(fi.buf, ti); @@ -858,7 +858,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { base_arg := arg; base_arg.type_info = type_info_base(base_arg.type_info); - match type a : base_arg { + match type a in base_arg { case bool: fmt_bool(fi, a, verb); case f32: fmt_float(fi, cast(f64)a, 32, verb); case f64: fmt_float(fi, a, 64, verb); @@ -880,7 +880,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { } -bprintf :: proc(b: ^Buffer, fmt: string, args: ...any) -> int { +bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int { fi := Fmt_Info{}; end := fmt.count; arg_index := 0; @@ -1004,7 +1004,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ...any) -> int { if !fi.reordered && arg_index < args.count { buffer_write_string(b, "%!(EXTRA "); - for arg, index : args[arg_index:] { + for arg, index in args[arg_index:] { if index > 0 { buffer_write_string(b, ", "); } diff --git a/core/hash.odin b/core/hash.odin index 01875442d..7348bef53 100644 --- a/core/hash.odin +++ b/core/hash.odin @@ -1,7 +1,7 @@ crc32 :: proc(data: rawptr, len: int) -> u32 { result := ~cast(u32)0; s := slice_ptr(cast(^u8)data, len); - for i : 0..>8 ~ __CRC32_TABLE[(result ~ b) & 0xff]; } @@ -10,7 +10,7 @@ crc32 :: proc(data: rawptr, len: int) -> u32 { crc64 :: proc(data: rawptr, len: int) -> u64 { result := ~cast(u64)0; s := slice_ptr(cast(^u8)data, len); - for i : 0..>8 ~ __CRC64_TABLE[(result ~ b) & 0xff]; } @@ -21,7 +21,7 @@ fnv32 :: proc(data: rawptr, len: int) -> u32 { s := slice_ptr(cast(^u8)data, len); h: u32 = 0x811c9dc5; - for i : 0.. u64 { s := slice_ptr(cast(^u8)data, len); h: u64 = 0xcbf29ce484222325; - for i : 0.. u32 { s := slice_ptr(cast(^u8)data, len); h: u32 = 0x811c9dc5; - for i : 0.. u64 { s := slice_ptr(cast(^u8)data, len); h :u64 = 0xcbf29ce484222325; - for i : 0.. u64 { data := slice_ptr(cast(^u64)data_, len/size_of(u64)); data2 := slice_ptr(cast(^u8)data_, len); - for i : 0 ..< data.count { + for i in 0 ..< data.count { k := data[i]; k *= m; diff --git a/core/math.odin b/core/math.odin index 6913b9652..b8f8df360 100644 --- a/core/math.odin +++ b/core/math.odin @@ -155,8 +155,8 @@ mat4_identity :: proc() -> Mat4 { } mat4_transpose :: proc(m: Mat4) -> Mat4 { - for j : 0..<4 { - for i : 0..<4 { + for j in 0..<4 { + for i in 0..<4 { m[i][j], m[j][i] = m[j][i], m[i][j]; } } @@ -165,8 +165,8 @@ mat4_transpose :: proc(m: Mat4) -> Mat4 { mul :: proc(a, b: Mat4) -> Mat4 { c: Mat4; - for j : 0..<4 { - for i : 0..<4 { + for j in 0..<4 { + for i in 0..<4 { c[j][i] = a[0][i]*b[j][0] + a[1][i]*b[j][1] + a[2][i]*b[j][2] + diff --git a/core/mem.odin b/core/mem.odin index d0e010a78..1ad80137d 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -28,7 +28,7 @@ copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "_ 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); - for i : 0.. int { MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants? using Type_Info; - match type info : type_info { + match type info in type_info { case Named: return align_of_type_info(info.base); case Integer: @@ -257,7 +257,7 @@ align_formula :: proc(size, align: int) -> int { size_of_type_info :: proc(type_info: ^Type_Info) -> int { WORD_SIZE :: size_of(int); using Type_Info; - match type info : type_info { + match type info in type_info { case Named: return size_of_type_info(info.base); case Integer: @@ -289,7 +289,7 @@ size_of_type_info :: proc(type_info: ^Type_Info) -> int { return 3*WORD_SIZE; case Vector: is_bool :: proc(type_info: ^Type_Info) -> bool { - match type info : type_info { + match type info in type_info { case Named: return is_bool(info.base); case Boolean: diff --git a/src/check_decl.c b/src/check_decl.c index 39c924ebd..9fb786286 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -64,6 +64,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra Array(Operand) operands; array_init_reserve(&operands, c->tmp_allocator, 2*lhs_count); + // TODO(bill): Allow for type hints from the entities for_array(i, inits) { AstNode *rhs = inits.e[i]; Operand o = {0}; diff --git a/src/check_expr.c b/src/check_expr.c index 273f237fb..f6037beee 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -4071,19 +4071,21 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error_node(ie->cond, "Non-boolean condition in if expression"); } - Operand x = {Addressing_Invalid}; Operand y = {Addressing_Invalid}; Type *if_type = NULL; Type *else_type = NULL; - check_expr(c, &x, ie->body); + if (type_hint) { + gb_printf_err("here\n"); + } + check_expr_with_type_hint(c, &x, ie->body, type_hint); if_type = x.type; if (ie->else_expr != NULL) { switch (ie->else_expr->kind) { case AstNode_IfExpr: case AstNode_BlockExpr: - check_expr(c, &y, ie->else_expr); + check_expr_with_type_hint(c, &y, ie->else_expr, if_type); else_type = y.type; break; default: diff --git a/src/parser.c b/src/parser.c index f8a732fb4..b3b1822c2 100644 --- a/src/parser.c +++ b/src/parser.c @@ -2944,7 +2944,7 @@ AstNode *parse_for_stmt(AstFile *f) { Token token = expect_token(f, Token_for); AstNodeArray names = parse_ident_list(f); parse_check_name_list_for_reserves(f, names); - Token colon = expect_token_after(f, Token_Colon, "for name list"); + Token colon = expect_token_after(f, Token_in, "for name list"); isize prev_level = f->expr_level; f->expr_level = -1; @@ -3029,7 +3029,7 @@ AstNode *parse_match_stmt(AstFile *f) { f->expr_level = -1; AstNode *var = parse_identifier(f); - expect_token(f, Token_Colon); + expect_token_after(f, Token_in, "match type name"); tag = parse_simple_stmt(f); f->expr_level = prev_level; diff --git a/src/tokenizer.c b/src/tokenizer.c index 79cdda258..c21c09942 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -75,7 +75,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \ TOKEN_KIND(Token_Semicolon, ";"), \ TOKEN_KIND(Token_Period, "."), \ TOKEN_KIND(Token_Comma, ","), \ - TOKEN_KIND(Token_Ellipsis, "..."), \ + TOKEN_KIND(Token_Ellipsis, ".."), \ TOKEN_KIND(Token_HalfOpenRange, "..<"), \ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \ \ @@ -94,6 +94,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_else, "else"), \ TOKEN_KIND(Token_while, "while"), \ TOKEN_KIND(Token_for, "for"), \ + TOKEN_KIND(Token_in, "in"), \ TOKEN_KIND(Token_when, "when"), \ TOKEN_KIND(Token_range, "range"), \ TOKEN_KIND(Token_defer, "defer"), \ @@ -845,14 +846,10 @@ Token tokenizer_get_token(Tokenizer *t) { case '.': token.kind = Token_Period; // Default - /* if (gb_is_between(t->curr_rune, '0', '9')) { // Might be a number - token = scan_number_to_token(t, true); - } else */ if (t->curr_rune == '.') { // Could be an ellipsis + if (t->curr_rune == '.') { // Could be an ellipsis advance_to_next_rune(t); - if (t->curr_rune == '.') { - advance_to_next_rune(t); - token.kind = Token_Ellipsis; - } else if (t->curr_rune == '<') { + token.kind = Token_Ellipsis; + if (t->curr_rune == '<') { advance_to_next_rune(t); token.kind = Token_HalfOpenRange; }