From c59f6b7d0b582131bed4450bbb9aa1a71d5a01af Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 26 Feb 2017 00:44:26 +0000 Subject: ++ -- statements; add strconv.odin (and replace some of the fmt procs); Fix ~ on 64 bit constants; Fix integer casts from smaller to larger size --- src/parser.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/parser.c') diff --git a/src/parser.c b/src/parser.c index f14f37599..8349a8d6b 100644 --- a/src/parser.c +++ b/src/parser.c @@ -186,6 +186,10 @@ AST_NODE_KIND(_StmtBegin, "", i32) \ Token op; \ AstNodeArray lhs, rhs; \ }) \ + AST_NODE_KIND(IncDecStmt, "increment decrement statement", struct { \ + Token op; \ + AstNode *expr; \ + }) \ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \ AST_NODE_KIND(BlockStmt, "block statement", struct { \ AstNodeArray stmts; \ @@ -467,6 +471,7 @@ Token ast_node_token(AstNode *node) { case AstNode_ExprStmt: return ast_node_token(node->ExprStmt.expr); case AstNode_TagStmt: return node->TagStmt.token; case AstNode_AssignStmt: return node->AssignStmt.op; + case AstNode_IncDecStmt: return ast_node_token(node->IncDecStmt.expr); case AstNode_BlockStmt: return node->BlockStmt.open; case AstNode_IfStmt: return node->IfStmt.token; case AstNode_WhenStmt: return node->WhenStmt.token; @@ -802,6 +807,16 @@ AstNode *ast_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rh return result; } + +AstNode *ast_inc_dec_stmt(AstFile *f, Token op, AstNode *expr) { + AstNode *result = make_ast_node(f, AstNode_IncDecStmt); + result->IncDecStmt.op = op; + result->IncDecStmt.expr = expr; + return result; +} + + + AstNode *ast_block_stmt(AstFile *f, AstNodeArray stmts, Token open, Token close) { AstNode *result = make_ast_node(f, AstNode_BlockStmt); result->BlockStmt.stmts = stmts; @@ -2272,6 +2287,13 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) { return ast_bad_stmt(f, token, f->curr_token); } + switch (token.kind) { + case Token_Inc: + case Token_Dec: + next_token(f); + return ast_inc_dec_stmt(f, token, lhs.e[0]); + } + return ast_expr_stmt(f, lhs.e[0]); } -- cgit v1.2.3 From 3c9143957c1726848e7f286ca6c96d410c84b585 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 26 Feb 2017 14:19:03 +0000 Subject: Ellipsis is now just `..`; Remove half-closed range operator and treat all of them as half-closed; slice expression uses `..`; --- code/demo.odin | 8 ++-- core/_preload.odin | 6 +-- core/decimal.odin | 131 +++++++++++++++++++++++++-------------------------- core/fmt.odin | 110 +++++++++++++++++++++--------------------- core/hash.odin | 4 +- core/math.odin | 8 ++-- core/mem.odin | 4 +- core/os_windows.odin | 6 +-- core/strconv.odin | 73 ++++++++++++++-------------- core/utf8.odin | 2 +- src/check_stmt.c | 3 +- src/ir.c | 3 +- src/parser.c | 9 +--- src/tokenizer.c | 40 ++++++++++++---- 14 files changed, 210 insertions(+), 197 deletions(-) (limited to 'src/parser.c') diff --git a/code/demo.odin b/code/demo.odin index a8511b29e..ea5e59a0d 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -9,14 +9,14 @@ main :: proc() { buf: [64]byte; - // len := strconv.generic_ftoa(buf[:], 123.5431, 'f', 4, 64); + // len := strconv.generic_ftoa(buf[..], 123.5431, 'f', 4, 64); x := 624.123; - s := strconv.format_float(buf[:], x, 'f', 6, 64); + s := strconv.format_float(buf[..], x, 'f', 6, 64); fmt.println(s); fmt.printf("%3d\n", 102); - i := 123; - fmt.println(123); + a := [..]int{0, 1, 2, 3, 4, 5, 6}; + fmt.println(a[0..4]); when false { diff --git a/core/_preload.odin b/core/_preload.odin index 56f9bfa45..fab23057f 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -316,7 +316,7 @@ __bounds_check_error :: proc(file: string, line, column: int, index, count: int) if 0 <= index && index < count { return; } - fmt.fprintf(os.stderr, "%s(%d:%d) Index %d is out of bounds range 0..<%d\n", + fmt.fprintf(os.stderr, "%s(%d:%d) Index %d is out of bounds range 0..%d\n", file, line, column, index, count); __debug_trap(); } @@ -325,7 +325,7 @@ __slice_expr_error :: proc(file: string, line, column: int, low, high: int) { if 0 <= low && low <= high { return; } - fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: [%d:%d]\n", + fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: [%d..%d]\n", file, line, column, low, high); __debug_trap(); } @@ -333,7 +333,7 @@ __substring_expr_error :: proc(file: string, line, column: int, low, high: int) if 0 <= low && low <= high { return; } - fmt.fprintf(os.stderr, "%s(%d:%d) Invalid substring indices: [%d:%d]\n", + fmt.fprintf(os.stderr, "%s(%d:%d) Invalid substring indices: [%d..%d]\n", file, line, column, low, high); __debug_trap(); } diff --git a/core/decimal.odin b/core/decimal.odin index 90582d20c..07031104b 100644 --- a/core/decimal.odin +++ b/core/decimal.odin @@ -3,11 +3,10 @@ // NOTE: This is only for floating point printing and nothing else Decimal :: struct { - d: [384]byte, // big-endian digits - ndu: int, - dp: int, - neg: bool, - trunc: bool, + digits: [384]byte, // big-endian digits + count: int, + decimal_point: int, + neg, trunc: bool, } decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string { @@ -19,42 +18,42 @@ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string { } - n := 10 + a.ndu + abs(a.dp); + n := 10 + a.count + abs(a.decimal_point); // TODO(bill): make this work with a buffer that's not big enough assert(buf.count >= n); - buf = buf[:n]; + buf = buf[..n]; - if a.ndu == 0 { + if a.count == 0 { buf[0] = '0'; - return cast(string)buf[0:1]; + return cast(string)buf[0..1]; } w := 0; - if a.dp <= 0 { + if a.decimal_point <= 0 { buf[w] = '0'; w++; buf[w] = '.'; w++; - w += digit_zero(buf[w: w-a.dp]); - w += copy(buf[w:], a.d[0:a.ndu]); - } else if a.dp < a.ndu { - w += copy(buf[w:], a.d[0:a.dp]); + w += digit_zero(buf[w .. w-a.decimal_point]); + w += copy(buf[w..], a.digits[0..a.count]); + } else if a.decimal_point < a.count { + w += copy(buf[w..], a.digits[0..a.decimal_point]); buf[w] = '.'; w++; - w += copy(buf[w:], a.d[a.dp:a.ndu]); + w += copy(buf[w..], a.digits[a.decimal_point .. a.count]); } else { - w += copy(buf[w:], a.d[0:a.ndu]); - w += digit_zero(buf[w : w+a.dp-a.ndu]); + w += copy(buf[w..], a.digits[0..a.count]); + w += digit_zero(buf[w .. w+a.decimal_point-a.count]); } - return cast(string)buf[0:w]; + return cast(string)buf[0..w]; } // trim trailing zeros trim :: proc(a: ^Decimal) { - for a.ndu > 0 && a.d[a.ndu-1] == '0' { - a.ndu--; + for a.count > 0 && a.digits[a.count-1] == '0' { + a.count--; } - if a.ndu == 0 { - a.dp = 0; + if a.count == 0 { + a.decimal_point = 0; } } @@ -70,12 +69,12 @@ assign :: proc(a: ^Decimal, i: u64) { i = j; } - a.ndu = 0; + a.count = 0; for n--; n >= 0; n-- { - a.d[a.ndu] = buf[n]; - a.ndu++; + a.digits[a.count] = buf[n]; + a.count++; } - a.dp = a.ndu; + a.decimal_point = a.count; trim(a); } @@ -88,10 +87,10 @@ shift_right :: proc(a: ^Decimal, k: uint) { n: uint; for ; n>>k == 0; r++ { - if r >= a.ndu { + if r >= a.count { if n == 0 { // Just in case - a.ndu = 0; + a.count = 0; return; } for n>>k == 0 { @@ -100,18 +99,18 @@ shift_right :: proc(a: ^Decimal, k: uint) { } break; } - c := cast(uint)a.d[r]; + c := cast(uint)a.digits[r]; n = n*10 + c - '0'; } - a.dp -= r-1; + a.decimal_point -= r-1; mask: uint = (1<>k; n &= mask; - a.d[w] = cast(byte)('0' + dig); + a.digits[w] = cast(byte)('0' + dig); w++; n = n*10 + c - '0'; } @@ -119,8 +118,8 @@ shift_right :: proc(a: ^Decimal, k: uint) { for n > 0 { dig := n>>k; n &= mask; - if w < a.d.count { - a.d[w] = cast(byte)('0' + dig); + if w < a.digits.count { + a.digits[w] = cast(byte)('0' + dig); w++; } else if dig > 0 { a.trunc = true; @@ -129,24 +128,24 @@ shift_right :: proc(a: ^Decimal, k: uint) { } - a.ndu = w; + a.count = w; trim(a); } shift_left :: proc(a: ^Decimal, k: uint) { delta := cast(int)(k/4); - r := a.ndu; // read index - w := a.ndu+delta; // write index + r := a.count; // read index + w := a.count+delta; // write index n: uint; for r--; r >= 0; r-- { - n += (cast(uint)a.d[r] - '0') << k; + n += (cast(uint)a.digits[r] - '0') << k; quo := n/10; rem := n - 10*quo; w--; - if w < a.d.count { - a.d[w] = cast(byte)('0' + rem); + if w < a.digits.count { + a.digits[w] = cast(byte)('0' + rem); } else if rem != 0 { a.trunc = true; } @@ -157,23 +156,23 @@ shift_left :: proc(a: ^Decimal, k: uint) { quo := n/10; rem := n - 10*quo; w--; - if w < a.d.count { - a.d[w] = cast(byte)('0' + rem); + if w < a.digits.count { + a.digits[w] = cast(byte)('0' + rem); } else if rem != 0 { a.trunc = true; } n = quo; } - a.ndu += delta; - a.ndu = min(a.ndu, a.d.count); - a.dp += delta; + a.count += delta; + a.count = min(a.count, a.digits.count); + a.decimal_point += delta; trim(a); } shift :: proc(a: ^Decimal, k: int) { match { - case a.ndu == 0: + case a.count == 0: // no need to update case k > 0: for k > max_shift { @@ -193,19 +192,19 @@ shift :: proc(a: ^Decimal, k: int) { } can_round_up :: proc(a: ^Decimal, nd: int) -> bool { - if nd < 0 || nd >= a.ndu { return false ; } - if a.d[nd] == '5' && nd+1 == a.ndu { + if nd < 0 || nd >= a.count { return false ; } + if a.digits[nd] == '5' && nd+1 == a.count { if a.trunc { return true; } - return nd > 0 && (a.d[nd-1]-'0')%2 != 0; + return nd > 0 && (a.digits[nd-1]-'0')%2 != 0; } - return a.d[nd] >= '5'; + return a.digits[nd] >= '5'; } round :: proc(a: ^Decimal, nd: int) { - if nd < 0 || nd >= a.ndu { return; } + if nd < 0 || nd >= a.count { return; } if can_round_up(a, nd) { round_up(a, nd); } else { @@ -214,44 +213,44 @@ round :: proc(a: ^Decimal, nd: int) { } round_up :: proc(a: ^Decimal, nd: int) { - if nd < 0 || nd >= a.ndu { return; } + if nd < 0 || nd >= a.count { return; } for i := nd-1; i >= 0; i-- { - if c := a.d[i]; c < '9' { - a.d[i]++; - a.ndu = i+1; + if c := a.digits[i]; c < '9' { + a.digits[i]++; + a.count = i+1; return; } } // Number is just 9s - a.d[0] = '1'; - a.ndu = 1; - a.dp++; + a.digits[0] = '1'; + a.count = 1; + a.decimal_point++; } round_down :: proc(a: ^Decimal, nd: int) { - if nd < 0 || nd >= a.ndu { return; } - a.ndu = nd; + if nd < 0 || nd >= a.count { return; } + a.count = nd; trim(a); } // Extract integer part, rounded appropriately. There are no guarantees about overflow. rounded_integer :: proc(a: ^Decimal) -> u64 { - if a.dp > 20 { + if a.decimal_point > 20 { return 0xffff_ffff_ffff_ffff; } i: int; n: u64 = 0; - m := min(a.dp, a.ndu); + m := min(a.decimal_point, a.count); for i = 0; i < m; i++ { - n = n*10 + cast(u64)(a.d[i]-'0'); + n = n*10 + cast(u64)(a.digits[i]-'0'); } - for ; i < a.dp; i++ { + for ; i < a.decimal_point; i++ { n *= 10; } - if can_round_up(a, a.dp) { + if can_round_up(a, a.decimal_point) { n++; } return n; diff --git a/core/fmt.odin b/core/fmt.odin index af0c26874..eb9233996 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -16,7 +16,7 @@ buffer_write :: proc(buf: ^Buffer, b: []byte) { if buf.length < buf.data.count { n := min(buf.data.count-buf.length, b.count); if n > 0 { - copy(buf.data[buf.length:], b[:n]); + copy(buf.data[buf.length..], b[..n]); buf.length += n; } } @@ -37,7 +37,7 @@ buffer_write_rune :: proc(buf: ^Buffer, r: rune) { } b, n := utf8.encode_rune(r); - buffer_write(buf, b[:n]); + buffer_write(buf, b[..n]); } Fmt_Info :: struct { @@ -61,46 +61,46 @@ Fmt_Info :: struct { -fprint :: proc(fd: os.Handle, args: ...any) -> int { +fprint :: proc(fd: os.Handle, args: ..any) -> int { data: [_BUFFER_SIZE]byte; - buf := Buffer{data[:], 0}; - bprint(^buf, ...args); - os.write(fd, buf.data[:buf.length]); + buf := Buffer{data[..], 0}; + 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: [_BUFFER_SIZE]byte; - buf := Buffer{data[:], 0}; - bprintln(^buf, ...args); - os.write(fd, buf.data[:buf.length]); + 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 { +fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { data: [_BUFFER_SIZE]byte; - buf := Buffer{data[:], 0}; - bprintf(^buf, fmt, ...args); - os.write(fd, buf.data[:buf.length]); + buf := Buffer{data[..], 0}; + 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); } fprint_type :: proc(fd: os.Handle, info: ^Type_Info) { data: [_BUFFER_SIZE]byte; - buf := Buffer{data[:], 0}; + buf := Buffer{data[..], 0}; buffer_write_type(^buf, info); - os.write(fd, buf.data[:buf.length]); + os.write(fd, buf.data[..buf.length]); } buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { @@ -176,7 +176,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, "[...]"); + buffer_write_string(buf, "[..]"); buffer_write_type(buf, info.elem); case Slice: buffer_write_string(buf, "["); @@ -241,7 +241,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { variant := union_cast(^Struct)variant_type; vc := variant.names.count-cf.names.count; - for j in 0.. 0 { buffer_write_string(buf, ", "); } @@ -280,7 +280,7 @@ 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; @@ -296,7 +296,7 @@ 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; @@ -310,23 +310,23 @@ bprintln :: proc(buf: ^Buffer, args: ...any) -> int { return buf.length; } -sprint :: proc(buf: []byte, args: ...any) -> string { +sprint :: proc(buf: []byte, args: ..any) -> string { b: Buffer; b.data = buf; - count := bprint(^b, ...args); - return cast(string)b.data[:b.length]; + count := bprint(^b, ..args); + return cast(string)b.data[..b.length]; } -sprintln :: proc(buf: []byte, args: ...any) -> string { +sprintln :: proc(buf: []byte, args: ..any) -> string { b: Buffer; b.data = buf; - count := bprintln(^b, ...args); - return cast(string)b.data[:b.length]; + count := bprintln(^b, ..args); + return cast(string)b.data[..b.length]; } -sprintf :: proc(buf: []byte, fmt: string, args: ...any) -> string { +sprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string { b: Buffer; b.data = buf; - count := bprintf(^b, fmt, ...args); - return cast(string)b.data[:b.length]; + count := bprintf(^b, fmt, ..args); + return cast(string)b.data[..b.length]; } @@ -341,7 +341,7 @@ parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: bool ok := true; i := 0; - for o in offset.. str.count { buffer_write_byte(fi.buf, str[0]); fmt_write_padding(fi, fi.width - str.count); - buffer_write_string(fi.buf, str[1:]); + buffer_write_string(fi.buf, str[1..]); } else { _pad(fi, str); } } else { - _pad(fi, str[1:]); + _pad(fi, str[1..]); } default: @@ -747,7 +747,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { buffer_write_byte(fi.buf, '['); defer buffer_write_byte(fi.buf, ']'); - for i in 0.. 0 { buffer_write_string(fi.buf, ", "); } @@ -764,7 +764,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { buffer_write_byte(fi.buf, '['); defer buffer_write_byte(fi.buf, ']'); array := cast(^Raw_Dynamic_Array)v.data; - for i in 0.. 0 { buffer_write_string(fi.buf, ", "); } @@ -786,7 +786,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { entry_type := union_cast(^Struct)ed.elem; entry_size := ed.elem_size; - for i in 0.. 0 { buffer_write_string(fi.buf, ", "); } @@ -815,7 +815,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 in 0.. 0 { buffer_write_string(fi.buf, ", "); } @@ -827,7 +827,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { buffer_write_byte(fi.buf, '<'); defer buffer_write_byte(fi.buf, '>'); - for i in 0.. 0 { buffer_write_string(fi.buf, ", "); } @@ -920,7 +920,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; @@ -933,7 +933,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ...any) -> int { i++; } if i > prev_i { - buffer_write_string(b, fmt[prev_i:i]); + buffer_write_string(b, fmt[prev_i..i]); } if i >= end { break; @@ -1026,7 +1026,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ...any) -> int { break; } - verb, w := utf8.decode_rune(fmt[i:]); + verb, w := utf8.decode_rune(fmt[i..]); i += w; if verb == '%' { @@ -1043,7 +1043,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 in 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 fb3720176..6d61594d2 100644 --- a/core/hash.odin +++ b/core/hash.odin @@ -66,7 +66,7 @@ murmur32 :: proc(data: []byte) -> u32 { h1 = h1*5 + 0xe6546b64; } - tail := data[nblocks*4:]; + tail := data[nblocks*4 ..]; k1: u32; match tail.count&3 { @@ -174,7 +174,7 @@ murmur64 :: proc(data: []byte) -> u64 { len -= 4; } - data8 := slice_to_bytes(data32[i:])[:3]; + data8 := slice_to_bytes(data32[i..])[..3]; match len { case 3: h2 ~= cast(u32)data8[2] << 16; diff --git a/core/math.odin b/core/math.odin index 6214bf824..f0b53950f 100644 --- a/core/math.odin +++ b/core/math.odin @@ -151,8 +151,8 @@ mat4_identity :: proc() -> Mat4 { } mat4_transpose :: proc(m: Mat4) -> Mat4 { - for j in 0..<4 { - for i in 0..<4 { + for j in 0..4 { + for i in 0..4 { m[i][j], m[j][i] = m[j][i], m[i][j]; } } @@ -161,8 +161,8 @@ mat4_transpose :: proc(m: Mat4) -> Mat4 { mul :: proc(a, b: Mat4) -> Mat4 { c: Mat4; - for j in 0..<4 { - for i in 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 5e89b38a9..b5e119921 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -32,7 +32,7 @@ copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "_ compare :: proc(a, b: []byte) -> int #link_name "__mem_compare" { n := min(a.count, b.count); - for i in 0.. (Handle, Errno) { } buf: [300]byte; - copy(buf[:], cast([]byte)path); + copy(buf[..], cast([]byte)path); handle := cast(Handle)CreateFileA(^buf[0], access, share_mode, sa, create_mode, FILE_ATTRIBUTE_NORMAL, nil); if handle != INVALID_HANDLE { @@ -184,7 +184,7 @@ last_write_time_by_name :: proc(name: string) -> File_Time { assert(buf.count > name.count); - copy(buf[:], cast([]byte)name); + copy(buf[..], cast([]byte)name); if win32.GetFileAttributesExA(^buf[0], win32.GetFileExInfoStandard, ^data) != 0 { last_write_time = data.last_write_time; @@ -201,7 +201,7 @@ last_write_time_by_name :: proc(name: string) -> File_Time { read_entire_file :: proc(name: string) -> ([]byte, bool) { buf: [300]byte; - copy(buf[:], cast([]byte)name); + copy(buf[..], cast([]byte)name); fd, err := open(name, O_RDONLY, 0); if err != ERROR_NONE { diff --git a/core/strconv.odin b/core/strconv.odin index 9f51808ad..57090cba9 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -1,6 +1,5 @@ #import . "decimal.odin"; #import "math.odin"; -#import format "fmt.odin"; Int_Flag :: enum { PREFIX = 1<<0, @@ -22,7 +21,7 @@ parse_bool :: proc(s: string) -> (result: bool, ok: bool) { format_bool :: proc(buf: []byte, b: bool) -> string { s := b ? "true" : "false"; len := copy(buf, cast([]byte)s); - return cast(string)buf[:len]; + return cast(string)buf[..len]; } format_uint :: proc(buf: []byte, u: u64, base: int) -> string { @@ -44,10 +43,10 @@ format_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> str Decimal_Slice :: struct { - d: []byte, - ndu: int, - dp: int, - neg: bool, + digits: []byte, + count: int, + decimal_point: int, + neg: bool, } Float_Info :: struct { @@ -89,7 +88,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [ s = "+Inf"; } len := copy(buf, cast([]byte)s); - return buf[:len]; + return buf[..len]; case 0: // denormalized exp++; @@ -108,19 +107,19 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [ shortest := prec < 0; if shortest { round_shortest(d, mant, exp, flt); - digs = Decimal_Slice{d = d.d[:], ndu = d.ndu, dp = d.dp}; + digs = Decimal_Slice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point}; match fmt { case 'e', 'E': - prec = digs.ndu-1; + prec = digs.count-1; case 'f', 'F': - prec = max(digs.ndu-digs.dp, 0); + prec = max(digs.count-digs.decimal_point, 0); case 'g', 'G': - prec = digs.ndu; + prec = digs.count; } } else { match fmt { case 'e', 'E': round(d, prec+1); - case 'f', 'F': round(d, d.dp+prec); + case 'f', 'F': round(d, d.decimal_point+prec); case 'g', 'G': if prec == 0 { prec = 1; @@ -128,7 +127,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [ round(d, prec); } - digs = Decimal_Slice{d = d.d[:], ndu = d.ndu, dp = d.dp}; + digs = Decimal_Slice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point}; } return format_digits(buf, shortest, neg, digs, prec, fmt); } @@ -138,7 +137,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slice, prec: int, fmt: byte) -> []byte { match fmt { case 'f', 'F': - add_bytes :: proc(dst: ^[]byte, w: ^int, bytes: ...byte) { + add_bytes :: proc(dst: ^[]byte, w: ^int, bytes: ..byte) { for b in bytes { if dst.count <= w^ { break; @@ -148,7 +147,7 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic } } - dst := buf[:]; + dst := buf[..]; w := 0; if neg { add_bytes(^dst, ^w, '-'); @@ -157,10 +156,10 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic } // integer, padded with zeros when needed - if digs.dp > 0 { - m := min(digs.ndu, digs.dp); - add_bytes(^dst, ^w, ...digs.d[:m]); - for ; m < digs.dp; m++ { + if digs.decimal_point > 0 { + m := min(digs.count, digs.decimal_point); + add_bytes(^dst, ^w, ..digs.digits[..m]); + for ; m < digs.decimal_point; m++ { add_bytes(^dst, ^w, '0'); } } else { @@ -170,16 +169,16 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic // fractional part if prec > 0 { add_bytes(^dst, ^w, '.'); - for i in 0..= 100*(exp-mantbits) */ minexp := flt.bias+1; - if exp > minexp && 332*(d.dp-d.ndu) >= 100*(exp - cast(int)flt.mantbits) { + if exp > minexp && 332*(d.decimal_point-d.count) >= 100*(exp - cast(int)flt.mantbits) { // Number is already its shortest return; } @@ -232,19 +231,19 @@ round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) { inclusive := mant%2 == 0; - for i in 0.. (rune, int) { } start = max(start, 0); - r, size = decode_rune(s[start:end]); + r, size = decode_rune(s[start..end]); if start+size != end { return RUNE_ERROR, 1; } diff --git a/src/check_stmt.c b/src/check_stmt.c index 9c0b0c187..6fd7cb925 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -715,8 +715,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { TokenKind op = Token_Lt; switch (ie->op.kind) { - case Token_HalfOpenRange: op = Token_Lt; break; - case Token_Ellipsis: op = Token_LtEq; break; + case Token_Ellipsis: op = Token_Lt; break; default: error(ie->op, "Invalid range operator"); break; } bool ok = compare_exact_values(Token_Lt, a, b); diff --git a/src/ir.c b/src/ir.c index 831a1cf8b..282d30efc 100644 --- a/src/ir.c +++ b/src/ir.c @@ -4742,8 +4742,7 @@ void ir_build_range_interval(irProcedure *proc, AstNodeIntervalExpr *node, Type TokenKind op = Token_Lt; switch (node->op.kind) { - case Token_HalfOpenRange: op = Token_Lt; break; - case Token_Ellipsis: op = Token_LtEq; break; + case Token_Ellipsis: op = Token_Lt; break; default: GB_PANIC("Invalid interval operator"); break; } irValue *cond = ir_emit_comp(proc, op, ir_emit_load(proc, value), upper); diff --git a/src/parser.c b/src/parser.c index 8349a8d6b..23053a816 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1950,16 +1950,12 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { f->expr_level++; open = expect_token(f, Token_OpenBracket); - // if (f->curr_token.kind != Token_Ellipsis && - // f->curr_token.kind != Token_HalfOpenRange) { - if (f->curr_token.kind != Token_Colon) { + if (f->curr_token.kind != Token_Ellipsis) { indices[0] = parse_expr(f, false); } bool is_index = true; - // if (f->curr_token.kind == Token_Ellipsis || - // f->curr_token.kind == Token_HalfOpenRange) { - if (f->curr_token.kind == Token_Colon) { + if (f->curr_token.kind == Token_Ellipsis) { is_index = false; interval = f->curr_token; next_token(f); @@ -2261,7 +2257,6 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) { allow_token(f, Token_in); AstNode *expr = parse_expr(f, false); switch (f->curr_token.kind) { - case Token_HalfOpenRange: case Token_Ellipsis: { Token op = f->curr_token; next_token(f); diff --git a/src/tokenizer.c b/src/tokenizer.c index dde3391a1..cfc1423f0 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -73,8 +73,8 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \ TOKEN_KIND(Token_Semicolon, ";"), \ TOKEN_KIND(Token_Period, "."), \ TOKEN_KIND(Token_Comma, ","), \ - TOKEN_KIND(Token_Ellipsis, "..."), \ - TOKEN_KIND(Token_HalfOpenRange, "..<"), \ + TOKEN_KIND(Token_Ellipsis, ".."), \ + /* TOKEN_KIND(Token_HalfOpenRange, "..<"), */ \ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \ \ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ @@ -225,6 +225,23 @@ void syntax_error_va(Token token, char *fmt, va_list va) { gb_mutex_unlock(&global_error_collector.mutex); } +void syntax_warning_va(Token token, char *fmt, va_list va) { + gb_mutex_lock(&global_error_collector.mutex); + global_error_collector.warning_count++; + // NOTE(bill): Duplicate error, skip it + if (!token_pos_eq(global_error_collector.prev, token.pos)) { + global_error_collector.prev = token.pos; + gb_printf_err("%.*s(%td:%td) Syntax Warning: %s\n", + LIT(token.pos.file), token.pos.line, token.pos.column, + gb_bprintf_va(fmt, va)); + } else if (token.pos.line == 0) { + gb_printf_err("Warning: %s\n", gb_bprintf_va(fmt, va)); + } + + gb_mutex_unlock(&global_error_collector.mutex); +} + + void warning(Token token, char *fmt, ...) { va_list va; @@ -247,6 +264,13 @@ void syntax_error(Token token, char *fmt, ...) { va_end(va); } +void syntax_warning(Token token, char *fmt, ...) { + va_list va; + va_start(va, fmt); + syntax_warning_va(token, fmt, va); + va_end(va); +} + void compiler_error(char *fmt, ...) { va_list va; @@ -834,13 +858,11 @@ Token tokenizer_get_token(Tokenizer *t) { token.kind = Token_Period; // Default 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_HalfOpenRange; - } else if (t->curr_rune == '.') { - advance_to_next_rune(t); - token.kind = Token_Ellipsis; - } + token.kind = Token_Ellipsis; + // if (t->curr_rune == '<') { + // advance_to_next_rune(t); + // token.kind = Token_HalfOpenRange; + // } } break; -- cgit v1.2.3 From f29e303ce7b11fbe88a4b63374c08130c6c189dd Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 26 Feb 2017 15:14:08 +0000 Subject: Slices now have a capacity. --- code/demo.odin | 18 ++--- core/_preload.odin | 35 ++++++++-- src/check_expr.c | 35 ++++++---- src/check_stmt.c | 1 + src/ir.c | 190 +++++++++++++++++++++++++++-------------------------- src/ir_print.c | 9 ++- src/parser.c | 44 +++++++++---- src/types.c | 35 ++++++---- 8 files changed, 224 insertions(+), 143 deletions(-) (limited to 'src/parser.c') diff --git a/code/demo.odin b/code/demo.odin index ea5e59a0d..8162fc0d3 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -8,15 +8,17 @@ #import "strconv.odin"; main :: proc() { - buf: [64]byte; - // len := strconv.generic_ftoa(buf[..], 123.5431, 'f', 4, 64); - x := 624.123; - s := strconv.format_float(buf[..], x, 'f', 6, 64); + // buf: [64]byte; + // // len := strconv.generic_ftoa(buf[..], 123.5431, 'f', 4, 64); + // x := 624.123; + // s := strconv.format_float(buf[..], x, 'f', 6, 64); + // fmt.println(s); + // fmt.printf("%3d\n", 102); + + a: [10]int; + s := a[..0]; + append(s, 1, 2, 6, 3, 6, 5, 5, 5, 5, 1, 2); fmt.println(s); - fmt.printf("%3d\n", 102); - - a := [..]int{0, 1, 2, 3, 4, 5, 6}; - fmt.println(a[0..4]); when false { diff --git a/core/_preload.odin b/core/_preload.odin index fab23057f..83ce45ce7 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -321,12 +321,12 @@ __bounds_check_error :: proc(file: string, line, column: int, index, count: int) __debug_trap(); } -__slice_expr_error :: proc(file: string, line, column: int, low, high: int) { - if 0 <= low && low <= high { +__slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) { + if 0 <= low && low <= high && high <= max { return; } - fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: [%d..%d]\n", - file, line, column, low, high); + fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: [%d..%d..%d]\n", + file, line, column, low, high, max); __debug_trap(); } __substring_expr_error :: proc(file: string, line, column: int, low, high: int) { @@ -361,8 +361,9 @@ Raw_String :: struct #ordered { }; Raw_Slice :: struct #ordered { - data: rawptr, - count: int, + data: rawptr, + count: int, + capacity: int, }; Raw_Dynamic_Array :: struct #ordered { @@ -451,6 +452,28 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in return array.count; } +__slice_append :: proc(slice_: rawptr, elem_size, elem_align: int, + items: rawptr, item_count: int) -> int { + slice := cast(^Raw_Slice)slice_; + + if item_count <= 0 || items == nil { + return slice.count; + } + + + ok := true; + if item_count > (slice.capacity-slice.count) { + item_count = (slice.capacity-slice.count); + } + if item_count > 0 { + data := cast(^byte)slice.data; + assert(data != nil); + mem.copy(data + (elem_size*slice.count), items, elem_size * item_count); + slice.count += item_count; + } + return slice.count; +} + // Map stuff diff --git a/src/check_expr.c b/src/check_expr.c index aa5222d9d..264a5d072 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -3057,19 +3057,26 @@ 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) + // append :: proc([]Type, item: ..Type) Type *type = operand->type; type = base_type(type); - if (!is_type_dynamic_array(type)) { + if (!is_type_dynamic_array(type) && !is_type_slice(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a dynamic array, got `%s`", str); + error_node(operand->expr, "Expected a slice or dynamic array, got `%s`", str); gb_string_free(str); return false; } - // TODO(bill): Semi-memory leaks - Type *elem = type->DynamicArray.elem; - Type *slice_elem = make_type_slice(c->allocator, elem); + Type *elem = NULL; + Type *slice_elem = NULL; + if (is_type_dynamic_array(type)) { + // TODO(bill): Semi-memory leaks + elem = type->DynamicArray.elem; + } else { + elem = type->Slice.elem; + } + slice_elem = make_type_slice(c->allocator, elem); Type *proc_type_params = make_type_tuple(c->allocator); proc_type_params->Tuple.variables = gb_alloc_array(c->allocator, Entity *, 2); @@ -3404,7 +3411,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } break; case BuiltinProc_swizzle: { - // swizzle :: proc(v: {N}T, T...) -> {M}T + // swizzle :: proc(v: {N}T, T..) -> {M}T Type *vector_type = base_type(operand->type); if (!is_type_vector(vector_type)) { gbString type_str = type_to_string(operand->type); @@ -5433,13 +5440,17 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = write_expr_to_string(str, se->expr); str = gb_string_appendc(str, "["); str = write_expr_to_string(str, se->low); - str = gb_string_appendc(str, ":"); + str = gb_string_appendc(str, ".."); str = write_expr_to_string(str, se->high); + if (se->index3) { + str = gb_string_appendc(str, ".."); + str = write_expr_to_string(str, se->max); + } str = gb_string_appendc(str, "]"); 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); @@ -5458,7 +5469,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) { if (at->count != NULL && at->count->kind == AstNode_UnaryExpr && at->count->UnaryExpr.op.kind == Token_Ellipsis) { - str = gb_string_appendc(str, "..."); + str = gb_string_appendc(str, ".."); } else { str = write_expr_to_string(str, at->count); } @@ -5467,7 +5478,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) { case_end; case_ast_node(at, DynamicArrayType, node); - str = gb_string_appendc(str, "[...]"); + str = gb_string_appendc(str, "[..]"); str = write_expr_to_string(str, at->elem); case_end; @@ -5500,7 +5511,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = gb_string_appendc(str, ": "); } if (f->flags&FieldFlag_ellipsis) { - str = gb_string_appendc(str, "..."); + str = gb_string_appendc(str, ".."); } str = write_expr_to_string(str, f->type); case_end; diff --git a/src/check_stmt.c b/src/check_stmt.c index 6fd7cb925..768410803 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -1258,6 +1258,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case Entity_Variable: { Type *t = base_type(type_deref(e->type)); if (is_type_struct(t) || is_type_raw_union(t)) { + // TODO(bill): Make it work for unions too Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node)); GB_ASSERT(found != NULL); for_array(i, (*found)->elements.entries) { diff --git a/src/ir.c b/src/ir.c index 282d30efc..a455c0164 100644 --- a/src/ir.c +++ b/src/ir.c @@ -218,6 +218,7 @@ struct irProcedure { TokenPos pos; \ irValue *low; \ irValue *high; \ + irValue *max; \ bool is_substring; \ }) \ IR_INSTR_KIND(DebugDeclare, struct { \ @@ -956,11 +957,12 @@ irValue *ir_make_instr_bounds_check(irProcedure *p, TokenPos pos, irValue *index v->Instr.BoundsCheck.len = len; return v; } -irValue *ir_make_instr_slice_bounds_check(irProcedure *p, TokenPos pos, irValue *low, irValue *high, bool is_substring) { +irValue *ir_make_instr_slice_bounds_check(irProcedure *p, TokenPos pos, irValue *low, irValue *high, irValue *max, bool is_substring) { irValue *v = ir_alloc_instr(p, irInstr_SliceBoundsCheck); v->Instr.SliceBoundsCheck.pos = pos; v->Instr.SliceBoundsCheck.low = low; v->Instr.SliceBoundsCheck.high = high; + v->Instr.SliceBoundsCheck.max = max; v->Instr.SliceBoundsCheck.is_substring = is_substring; return v; } @@ -1845,6 +1847,7 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { switch (index) { case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->Slice.elem)); break; case 1: result_type = make_type_pointer(a, t_int); break; + case 2: result_type = make_type_pointer(a, t_int); break; } } else if (is_type_string(t)) { switch (index) { @@ -2070,6 +2073,11 @@ irValue *ir_slice_count(irProcedure *proc, irValue *slice) { GB_ASSERT(t->kind == Type_Slice); return ir_emit_struct_ev(proc, slice, 1); } +irValue *ir_slice_capacity(irProcedure *proc, irValue *slice) { + Type *t = base_type(ir_type(slice)); + GB_ASSERT(t->kind == Type_Slice); + return ir_emit_struct_ev(proc, slice, 2); +} irValue *ir_dynamic_array_elem(irProcedure *proc, irValue *da) { Type *t = ir_type(da); @@ -2106,8 +2114,19 @@ irValue *ir_string_len(irProcedure *proc, irValue *string) { } +void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *count, irValue *capacity) { + Type *t = ir_type(slice_ptr); + GB_ASSERT(is_type_pointer(t)); + t = type_deref(t); + GB_ASSERT(is_type_slice(t)); + ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 0), data); + ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 1), count); + ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 2), capacity); +} + + -irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *low, irValue *high) { +irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *low, irValue *high, irValue *max) { // TODO(bill): array bounds checking for slice creation // TODO(bill): check that low < high <= max gbAllocator a = proc->module->allocator; @@ -2123,8 +2142,16 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, case Type_Pointer: high = v_one; break; } } + if (max == NULL) { + switch (bt->kind) { + case Type_Array: high = ir_array_len(proc, base); break; + case Type_Slice: high = ir_slice_capacity(proc, base); break; + case Type_Pointer: high = v_one; break; + } + } irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); + irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); irValue *elem = NULL; switch (bt->kind) { @@ -2136,14 +2163,7 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, elem = ir_emit_ptr_offset(proc, elem, low); irValue *slice = ir_add_local_generated(proc, slice_type); - - irValue *gep = NULL; - gep = ir_emit_struct_ep(proc, slice, 0); - ir_emit_store(proc, gep, elem); - - gep = ir_emit_struct_ep(proc, slice, 1); - ir_emit_store(proc, gep, len); - + ir_fill_slice(proc, slice, elem, len, cap); return slice; } @@ -2386,7 +2406,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { ir_emit_store(proc, elem_ptr, elem); irValue *len = ir_string_len(proc, value); - irValue *slice = ir_add_local_slice(proc, dst, elem_ptr, v_zero, len); + irValue *cap = len; + irValue *slice = ir_add_local_slice(proc, dst, elem_ptr, v_zero, len, cap); return ir_emit_load(proc, slice); } @@ -2757,7 +2778,7 @@ void ir_emit_bounds_check(irProcedure *proc, Token token, irValue *index, irValu ir_emit(proc, ir_make_instr_bounds_check(proc, token.pos, index, len)); } -void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, bool is_substring) { +void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *max, bool is_substring) { if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { return; } @@ -2765,10 +2786,11 @@ void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, ir low = ir_emit_conv(proc, low, t_int); high = ir_emit_conv(proc, high, t_int); - ir_emit(proc, ir_make_instr_slice_bounds_check(proc, token.pos, low, high, is_substring)); + ir_emit(proc, ir_make_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring)); } + //////////////////////////////////////////////////////////////// // // @Build @@ -3161,7 +3183,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv irValue *count = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int); - ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, false); + ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, count, false); irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, count, t_int); @@ -3173,10 +3195,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv irValue *ptr = ir_emit_conv(proc, call, ptr_type); irValue *slice = ir_add_local_generated(proc, slice_type); - irValue *gep0 = ir_emit_struct_ep(proc, slice, 0); - irValue *gep1 = ir_emit_struct_ep(proc, slice, 1); - ir_emit_store(proc, gep0, ptr); - ir_emit_store(proc, gep1, count); + ir_fill_slice(proc, slice, ptr, count, count); return ir_emit_load(proc, slice); } break; @@ -3315,8 +3334,16 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv Type *type = ir_type(array_ptr); GB_ASSERT(is_type_pointer(type)); type = base_type(type_deref(type)); - GB_ASSERT(is_type_dynamic_array(type)); - Type *elem_type = type->DynamicArray.elem; + Type *elem_type = NULL; + bool is_slice = false; + if (is_type_dynamic_array(type)) { + elem_type = type->DynamicArray.elem; + } else if (is_type_slice(type)) { + is_slice = true; + elem_type = type->Slice.elem; + } else { + GB_PANIC("Invalid type to append"); + } irValue *elem_size = ir_make_const_int(a, type_size_of(a, elem_type)); irValue *elem_align = ir_make_const_int(a, type_align_of(a, elem_type)); @@ -3373,10 +3400,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv } irValue *base_elem = ir_emit_array_epi(proc, base_array, 0); - irValue *slice_elem = ir_emit_struct_ep(proc, slice, 0); - ir_emit_store(proc, slice_elem, base_elem); irValue *len = ir_make_const_int(a, slice_len); - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len); + ir_fill_slice(proc, slice, base_elem, len, len); } arg_count = 2; @@ -3393,6 +3418,10 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv daa_args[2] = elem_align; daa_args[3] = ir_emit_conv(proc, items, t_rawptr); daa_args[4] = ir_emit_conv(proc, item_count, t_int); + + if (is_slice) { + return ir_emit_global_call(proc, "__slice_append", daa_args, 5); + } return ir_emit_global_call(proc, "__dynamic_array_append", daa_args, 5); } break; @@ -3538,8 +3567,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv Type *slice_type = make_type_slice(proc->module->allocator, type_deref(ir_type(ptr))); irValue *slice = ir_add_local_generated(proc, slice_type); - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), ptr); - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), count); + ir_fill_slice(proc, slice, ptr, count, count); return ir_emit_load(proc, slice); } break; @@ -3556,9 +3584,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv irValue *ptr = ir_emit_conv(proc, ir_slice_elem(proc, s), t_u8_ptr); irValue *count = ir_slice_count(proc, s); count = ir_emit_arith(proc, Token_Mul, count, ir_make_const_int(proc->module->allocator, elem_size), t_int); - - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), ptr); - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), count); + ir_fill_slice(proc, slice, ptr, count, count); return ir_emit_load(proc, slice); } break; @@ -3681,11 +3707,9 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv ir_emit_store(proc, addr, args[i]); } - irValue *base_elem = ir_emit_array_epi(proc, base_array, 0); - irValue *slice_elem = ir_emit_struct_ep(proc, slice, 0); - ir_emit_store(proc, slice_elem, base_elem); + irValue *base_elem = ir_emit_array_epi(proc, base_array, 0); irValue *len = ir_make_const_int(allocator, slice_len); - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len); + ir_fill_slice(proc, slice, base_elem, len, len); } arg_count = type->param_count; @@ -4076,9 +4100,11 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { gbAllocator a = proc->module->allocator; irValue *low = v_zero; irValue *high = NULL; + irValue *max = NULL; if (se->low != NULL) low = ir_build_expr(proc, se->low); if (se->high != NULL) high = ir_build_expr(proc, se->high); + if (se->max != NULL) max = ir_build_expr(proc, se->max); irValue *addr = ir_build_addr(proc, se->expr).addr; irValue *base = ir_emit_load(proc, addr); Type *type = base_type(ir_type(base)); @@ -4096,16 +4122,15 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { Type *slice_type = type; if (high == NULL) high = ir_slice_count(proc, base); + if (max == NULL) max = ir_slice_capacity(proc, base); - ir_emit_slice_bounds_check(proc, se->open, low, high, false); + ir_emit_slice_bounds_check(proc, se->open, low, high, max, false); irValue *elem = ir_emit_ptr_offset(proc, ir_slice_elem(proc, base), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); + irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); irValue *slice = ir_add_local_generated(proc, slice_type); - - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem); - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len); - + ir_fill_slice(proc, slice, elem, len, cap); return ir_make_addr(slice); } @@ -4113,16 +4138,15 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { Type *dynamic_array = type; if (high == NULL) high = ir_dynamic_array_count(proc, base); + if (max == NULL) max = ir_dynamic_array_capacity(proc, base); - ir_emit_slice_bounds_check(proc, se->open, low, high, false); + ir_emit_slice_bounds_check(proc, se->open, low, high, max, false); irValue *elem = ir_emit_ptr_offset(proc, ir_dynamic_array_elem(proc, base), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); + irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); irValue *slice = ir_add_local_generated(proc, dynamic_array); - - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem); - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len); - + ir_fill_slice(proc, slice, elem, len, cap); return ir_make_addr(slice); } @@ -4131,38 +4155,31 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { Type *slice_type = make_type_slice(a, type->Array.elem); if (high == NULL) high = ir_array_len(proc, base); + if (max == NULL) max = ir_array_len(proc, base); - ir_emit_slice_bounds_check(proc, se->open, low, high, false); + ir_emit_slice_bounds_check(proc, se->open, low, high, max, false); irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); + irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); irValue *slice = ir_add_local_generated(proc, slice_type); - - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem); - ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len); - + ir_fill_slice(proc, slice, elem, len, cap); return ir_make_addr(slice); } case Type_Basic: { GB_ASSERT(type == t_string); - if (high == NULL) { - high = ir_string_len(proc, base); - } - - ir_emit_slice_bounds_check(proc, se->open, low, high, true); + if (high == NULL) high = ir_string_len(proc, base); + if (max == NULL) max = ir_string_len(proc, base); - irValue *elem, *len; - len = ir_emit_arith(proc, Token_Sub, high, low, t_int); + ir_emit_slice_bounds_check(proc, se->open, low, high, max, true); - elem = ir_string_elem(proc, base); - elem = ir_emit_ptr_offset(proc, elem, low); + irValue *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low); + irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); irValue *str = ir_add_local_generated(proc, t_string); - irValue *gep0 = ir_emit_struct_ep(proc, str, 0); - irValue *gep1 = ir_emit_struct_ep(proc, str, 1); - ir_emit_store(proc, gep0, elem); - ir_emit_store(proc, gep1, len); + ir_emit_store(proc, ir_emit_struct_ep(proc, str, 0), elem); + ir_emit_store(proc, ir_emit_struct_ep(proc, str, 1), len); return ir_make_addr(str); } break; @@ -4369,13 +4386,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { ir_emit_store(proc, offset, ev); } - irValue *gep0 = ir_emit_struct_ep(proc, v, 0); - irValue *gep1 = ir_emit_struct_ep(proc, v, 1); - irValue *gep2 = ir_emit_struct_ep(proc, v, 1); - - ir_emit_store(proc, gep0, data); - ir_emit_store(proc, gep1, ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count)); - ir_emit_store(proc, gep2, ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count)); + irValue *count = ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count); + ir_fill_slice(proc, v, data, count, count); } } break; @@ -6030,16 +6042,6 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) { array_add(&m->foreign_library_paths, library_path); } -void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *count) { - Type *t = ir_type(slice_ptr); - GB_ASSERT(is_type_pointer(t)); - t = type_deref(t); - GB_ASSERT(is_type_slice(t)); - irValue *elem = ir_emit_struct_ep(proc, slice_ptr, 0); - irValue *len = ir_emit_struct_ep(proc, slice_ptr, 1); - ir_emit_store(proc, elem, data); - ir_emit_store(proc, len, count); -} void ir_gen_tree(irGen *s) { irModule *m = &s->module; @@ -6376,9 +6378,10 @@ void ir_gen_tree(irGen *s) { irValue *global_type_table = ir_find_global_variable(proc, str_lit("__type_table")); Type *type = base_type(type_deref(ir_type(ir_global_type_info_data))); GB_ASSERT(is_type_array(type)); + irValue *len = ir_make_const_int(proc->module->allocator, type->Array.count); ir_fill_slice(proc, global_type_table, ir_emit_array_epi(proc, ir_global_type_info_data, 0), - ir_make_const_int(proc->module->allocator, type->Array.count)); + len, len); } @@ -6562,8 +6565,9 @@ void ir_gen_tree(irGen *s) { } } - ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Tuple.variable_count)); - ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Tuple.variable_count)); + irValue *count = ir_make_const_int(a, t->Tuple.variable_count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count); } break; case Type_Record: { switch (t->Record.kind) { @@ -6609,9 +6613,10 @@ void ir_gen_tree(irGen *s) { ir_emit_store(proc, offset, ir_make_const_int(a, foffset)); } - ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Record.field_count)); - ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Record.field_count)); - ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, ir_make_const_int(a, t->Record.field_count)); + irValue *count = ir_make_const_int(a, t->Record.field_count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count); } break; case TypeRecord_Union: { ir_emit_comment(proc, str_lit("Type_Info_Union")); @@ -6652,9 +6657,10 @@ void ir_gen_tree(irGen *s) { } - ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 0), memory_types, ir_make_const_int(a, field_count)); - ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 1), memory_names, ir_make_const_int(a, field_count)); - ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 2), memory_offsets, ir_make_const_int(a, field_count)); + irValue *count = ir_make_const_int(a, field_count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 0), memory_types, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 1), memory_names, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 2), memory_offsets, count, count); } { @@ -6681,9 +6687,8 @@ void ir_gen_tree(irGen *s) { } irValue *count = ir_make_const_int(a, variant_count); - - ir_fill_slice(proc, variant_names, memory_names, count); - ir_fill_slice(proc, variant_types, memory_types, count); + ir_fill_slice(proc, variant_names, memory_names, count, count); + ir_fill_slice(proc, variant_types, memory_types, count, count); } } break; @@ -6716,9 +6721,10 @@ void ir_gen_tree(irGen *s) { } } - ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Record.field_count)); - ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Record.field_count)); - ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, ir_make_const_int(a, t->Record.field_count)); + irValue *count = ir_make_const_int(a, t->Record.field_count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count); } break; case TypeRecord_Enum: ir_emit_comment(proc, str_lit("Type_Info_Enum")); diff --git a/src/ir_print.c b/src/ir_print.c index 3018e2463..9bc7e5f41 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -191,7 +191,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { case Type_Slice: ir_fprintf(f, "{"); ir_print_type(f, m, t->Slice.elem); - ir_fprintf(f, "*, i%lld}", word_bits); + ir_fprintf(f, "*, i%lld, i%lld}", word_bits, word_bits); return; case Type_DynamicArray: ir_fprintf(f, "{"); @@ -1249,6 +1249,13 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { ir_fprintf(f, " "); ir_print_value(f, m, bc->high, t_int); + if (!bc->is_substring) { + ir_fprintf(f, ", "); + ir_print_type(f, m, t_int); + ir_fprintf(f, " "); + ir_print_value(f, m, bc->max, t_int); + } + ir_fprintf(f, ")\n"); } break; diff --git a/src/parser.c b/src/parser.c index 23053a816..160b72ef3 100644 --- a/src/parser.c +++ b/src/parser.c @@ -151,8 +151,9 @@ AST_NODE_KIND(_ExprBegin, "", i32) \ AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \ AST_NODE_KIND(SliceExpr, "slice expression", struct { \ AstNode *expr; \ - Token open, close, interval; \ - AstNode *low, *high; \ + Token open, close; \ + bool index3; \ + AstNode *low, *high, *max; \ }) \ AST_NODE_KIND(CallExpr, "call expression", struct { \ AstNode * proc; \ @@ -667,14 +668,15 @@ AstNode *ast_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, T } -AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, Token interval, AstNode *low, AstNode *high) { +AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, bool index3, AstNode *low, AstNode *high, AstNode *max) { AstNode *result = make_ast_node(f, AstNode_SliceExpr); result->SliceExpr.expr = expr; result->SliceExpr.open = open; result->SliceExpr.close = close; - result->SliceExpr.interval = interval; + result->SliceExpr.index3 = index3; result->SliceExpr.low = low; result->SliceExpr.high = high; + result->SliceExpr.max = max; return result; } @@ -1945,7 +1947,9 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { // TODO(bill): Handle this } Token open = {0}, close = {0}, interval = {0}; - AstNode *indices[2] = {0}; + AstNode *indices[3] = {0}; + isize ellipsis_count = 0; + Token ellipses[2] = {0}; f->expr_level++; open = expect_token(f, Token_OpenBracket); @@ -1955,23 +1959,37 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { } bool is_index = true; - if (f->curr_token.kind == Token_Ellipsis) { - is_index = false; - interval = f->curr_token; + while (f->curr_token.kind == Token_Ellipsis && ellipsis_count < gb_count_of(ellipses)) { + ellipses[ellipsis_count++] = f->curr_token; next_token(f); - if (f->curr_token.kind != Token_CloseBracket && + if (f->curr_token.kind != Token_Ellipsis && + f->curr_token.kind != Token_CloseBracket && f->curr_token.kind != Token_EOF) { - indices[1] = parse_expr(f, false); + indices[ellipsis_count] = parse_expr(f, false); } } + f->expr_level--; close = expect_token(f, Token_CloseBracket); - if (is_index) { - operand = ast_index_expr(f, operand, indices[0], open, close); + if (ellipsis_count > 0) { + bool index3 = false; + if (ellipsis_count == 2) { + index3 = true; + // 2nd and 3rd index must be present + if (indices[1] == NULL) { + error(ellipses[0], "2nd index required in 3-index slice expression"); + indices[1] = ast_bad_expr(f, ellipses[0], ellipses[1]); + } + if (indices[2] == NULL) { + error(ellipses[1], "3rd index required in 3-index slice expression"); + indices[2] = ast_bad_expr(f, ellipses[1], close); + } + } + operand = ast_slice_expr(f, operand, open, close, index3, indices[0], indices[1], indices[2]); } else { - operand = ast_slice_expr(f, operand, open, close, interval, indices[0], indices[1]); + operand = ast_index_expr(f, operand, indices[0], open, close); } } break; diff --git a/src/types.c b/src/types.c index a734e3c01..0142fa227 100644 --- a/src/types.c +++ b/src/types.c @@ -1090,6 +1090,7 @@ gb_global Entity *entity__any_data = NULL; gb_global Entity *entity__string_data = NULL; gb_global Entity *entity__string_count = NULL; gb_global Entity *entity__slice_count = NULL; +gb_global Entity *entity__slice_capacity = NULL; gb_global Entity *entity__dynamic_array_count = NULL; gb_global Entity *entity__dynamic_array_capacity = NULL; @@ -1251,6 +1252,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n } else if (type->kind == Type_Slice) { String data_str = str_lit("data"); String count_str = str_lit("count"); + String capacity_str = str_lit("capacity"); if (str_eq(field_name, data_str)) { selection_add_index(&sel, 0); @@ -1265,7 +1267,16 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = entity__slice_count; return sel; + } else if (str_eq(field_name, capacity_str)) { + selection_add_index(&sel, 2); + if (entity__slice_capacity == NULL) { + entity__slice_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 2); + } + + sel.entity = entity__slice_capacity; + return sel; } + } else if (type->kind == Type_DynamicArray) { String data_str = str_lit("data"); String count_str = str_lit("count"); @@ -1779,7 +1790,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Slice: // ptr + count - return 2 * build_context.word_size; + return 3 * build_context.word_size; case Type_Map: { if (t->Map.count == 0) { // Dynamic @@ -1875,23 +1886,24 @@ i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) { } else if (t->kind == Type_Basic) { if (t->Basic.kind == Basic_string) { switch (index) { - case 0: return 0; // data + case 0: return 0; // data case 1: return build_context.word_size; // count } } else if (t->Basic.kind == Basic_any) { switch (index) { - case 0: return 0; // type_info + case 0: return 0; // type_info case 1: return build_context.word_size; // data } } } else if (t->kind == Type_Slice) { switch (index) { - case 0: return 0; // data + case 0: return 0; // data case 1: return 1*build_context.word_size; // count + case 2: return 2*build_context.word_size; // capacity } } else if (t->kind == Type_DynamicArray) { switch (index) { - case 0: return 0; // data + case 0: return 0; // data case 1: return 1*build_context.word_size; // count case 2: return 2*build_context.word_size; // capacity case 3: return 3*build_context.word_size; // allocator @@ -1928,6 +1940,13 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s } } break; + case Type_Slice: + switch (index) { + case 0: t = t_rawptr; break; + case 1: t = t_int; break; + case 2: t = t_int; break; + } + break; case Type_DynamicArray: switch (index) { case 0: t = t_rawptr; break; @@ -1936,12 +1955,6 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s case 3: t = t_allocator; break; } break; - case Type_Slice: - switch (index) { - case 0: t = t_rawptr; break; - case 1: t = t_int; break; - } - break; } } } -- cgit v1.2.3